Skip to content

Commit

Permalink
WIP scoring implementation
Browse files Browse the repository at this point in the history
Store scores in browser local storage
Allow clearing and downloading the current data
  • Loading branch information
nick-lironi-irvine committed Nov 17, 2024
1 parent 78b6abb commit 0a5aff7
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 0 deletions.
3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ export default tseslint.config(
eslintPluginPrettierRecommended,
{
ignores: ["**/*.js", "**/*.cjs"],
rules: {
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
},
},
);
Binary file added games/apple-catcher/public/assets/delete-data.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions games/apple-catcher/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ export const BLUE = 0x1e90ff;
export const ORANGE_STRING = "#ffa500";
export const ORANGE = parseInt(ORANGE_STRING.substring(1), 16);

export const GAME_SCORE_DATA_KEY = "ele-data";
export const PLAYER_ID_DATA_KEY = "playerId";
27 changes: 27 additions & 0 deletions games/apple-catcher/src/scenes/AppleCatcherScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import {
BLACK_STRING,
BLUE,
GAME_AREA_WIDTH,
GAME_SCORE_DATA_KEY,
GUTTER_WIDTH,
HALF_WIDTH,
HEIGHT,
ORANGE,
PLAYER_ID_DATA_KEY,
WIDTH,
} from "../constants.ts";
import Body = Phaser.Physics.Arcade.Body;
Expand Down Expand Up @@ -54,6 +56,12 @@ export abstract class AbstractCatcherScene extends Scene {
*/
protected abstract doReset(): void;

/**
* Allows scenes to report their scene-specific data; called once per level
* and should return one record per try
*/
protected abstract getSceneScoringData(): Record<string, unknown>[];

preload() {
this.load.image("tree", "assets/tree.png");
this.load.image("apple", "assets/apple.png");
Expand All @@ -65,6 +73,25 @@ export abstract class AbstractCatcherScene extends Scene {
init() {
this.registry.set(this.triesDataKey, 0);
this.registry.set(this.scoreDataKey, 0);
this.events.once("shutdown", () => {
/*
When the scene is shutdown, by navigating to another scene, we record
scores for the current scene
*/
const sceneScoringData = this.getSceneScoringData();
if (sceneScoringData?.length > 0) {
const currentData = JSON.parse(
localStorage.getItem(GAME_SCORE_DATA_KEY) ?? "{}",
);

const playerId = this.registry.get(PLAYER_ID_DATA_KEY);
currentData[playerId] = currentData[playerId] ?? {};
currentData[playerId][this.name] =
currentData[playerId][this.name] ?? [];
currentData[playerId][this.name].push(sceneScoringData);
localStorage.setItem(GAME_SCORE_DATA_KEY, JSON.stringify(currentData));
}
});
}

create() {
Expand Down
4 changes: 4 additions & 0 deletions games/apple-catcher/src/scenes/Level0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export class Level0 extends AbstractCatcherScene {
this.resetBasket();
}

protected getSceneScoringData() {
return [];
}

private setupBasket() {
this.basket = this.physics.add
.staticSprite(HALF_WIDTH, BASKET_BOTTOM, "basket")
Expand Down
36 changes: 36 additions & 0 deletions games/apple-catcher/src/scenes/Level1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ import Pointer = Phaser.Input.Pointer;
import SpriteWithDynamicBody = Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
import { renderVerticalPipe } from "../pipes.ts";

type ScoringData = {
// Where the basket was, relative to (0,0) top-left corner
basket: {
x: number;
y: number;
};
// 1 if the apple was caught, else 0
score: 0 | 1;
};

export class Level1 extends AbstractCatcherScene {
private basket: SpriteWithStaticBody;
private apple: SpriteWithDynamicBody;
private scoringData: ScoringData[];

constructor() {
super(
Expand All @@ -19,6 +30,11 @@ export class Level1 extends AbstractCatcherScene {
);
}

init() {
super.init();
this.scoringData = [];
}

create() {
super.create();
this.setupBasket();
Expand All @@ -35,10 +51,30 @@ export class Level1 extends AbstractCatcherScene {
}

protected doReset(): void {
this.recordScoreDataForCurrentTry();
this.resetBasket();
this.resetApple();
}

private recordScoreDataForCurrentTry() {
this.scoringData.push({
basket: {
x: this.basket.x,
y: this.basket.y,
},
score: this.apple.active ? 0 : 1,
});
}

protected getSceneScoringData() {
if (this.registry.get(this.triesDataKey) > this.scoringData.length) {
// capture the final score, if there was another try after the last reset,
// but not otherwise
this.recordScoreDataForCurrentTry();
}
return this.scoringData;
}

private setupBasket() {
this.basket = this.physics.add
.staticSprite(HALF_WIDTH, BASKET_BOTTOM, "basket")
Expand Down
4 changes: 4 additions & 0 deletions games/apple-catcher/src/scenes/Level2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class Level2 extends AbstractCatcherScene {
this.resetApple();
}

protected getSceneScoringData() {
return [];
}

private setupBasket() {
this.basket = this.physics.add
.staticSprite(HALF_WIDTH, BASKET_BOTTOM, "basket")
Expand Down
4 changes: 4 additions & 0 deletions games/apple-catcher/src/scenes/Level3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export class Level3 extends AbstractCatcherScene {
this.resetApple();
}

protected getSceneScoringData() {
return [];
}

private renderThreeForkedPipe() {
const pipeWidth = 80;
const pipeTop = 280;
Expand Down
4 changes: 4 additions & 0 deletions games/apple-catcher/src/scenes/Level4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export class Level4 extends AbstractCatcherScene {
this.resetApple();
}

protected getSceneScoringData() {
return [];
}

private setupBasket() {
this.basket = this.physics.add
.staticSprite(HALF_WIDTH, BASKET_BOTTOM, "basket")
Expand Down
28 changes: 28 additions & 0 deletions games/apple-catcher/src/scenes/MainMenu.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Scene } from "phaser";
import {
GAME_SCORE_DATA_KEY,
HALF_HEIGHT,
HALF_WIDTH,
HEIGHT,
PLAYER_ID_DATA_KEY,
QUARTER_WIDTH,
} from "../constants.ts";
Expand All @@ -14,6 +16,8 @@ export class MainMenu extends Scene {

preload() {
this.load.html("name_input", "assets/html_text_input.html");
this.load.image("download-data", "assets/download-data.png");
this.load.image("delete-data", "assets/delete-data.png");
}

create() {
Expand Down Expand Up @@ -54,5 +58,29 @@ export class MainMenu extends Scene {
this.scene.start("Level0");
}
});

this.add
.sprite(HALF_WIDTH - 100, HEIGHT - 50, "delete-data")
.setDisplaySize(50, 50)
.setInteractive()
.on("pointerdown", () => {
// remove the current data
localStorage.setItem(GAME_SCORE_DATA_KEY, "{}");
});

this.add
.sprite(HALF_WIDTH + 100, HEIGHT - 50, "download-data")
.setDisplaySize(50, 50)
.setInteractive()
.on("pointerdown", () => {
// Trigger download of the current data
const blob = new Blob(
[localStorage.getItem(GAME_SCORE_DATA_KEY) ?? ""],
{
type: "application/json",
},
);
window.location.href = URL.createObjectURL(blob);
});
}
}

0 comments on commit 0a5aff7

Please sign in to comment.