feat(settings/options/2048): display score in top bar, and implement intro and outro animation
This commit is contained in:
@@ -12,8 +12,11 @@ const handleActivateB = () => {
|
||||
confirmationModal.open({
|
||||
text: $t("settings.options.2048.quitConfirmation"),
|
||||
onConfirm: () => {},
|
||||
onClosed: (choice) => {
|
||||
if (choice === "confirm") store.closeSubMenu();
|
||||
onClosed: async (choice) => {
|
||||
if (choice === "confirm") {
|
||||
await animateOutro();
|
||||
store.closeSubMenu();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -62,9 +65,17 @@ const BOARD_X = 64;
|
||||
const BOARD_Y = 32;
|
||||
const BOARD_SIZE = 4;
|
||||
|
||||
const SCORE_X = 195;
|
||||
const SCORE_Y = 36;
|
||||
const HIGH_SCORE_Y = 68;
|
||||
const SLIDE_OFFSET = 96;
|
||||
const SLIDE_DURATION = 0.25;
|
||||
const SCORE_OFFSET = -20;
|
||||
const SCORE_DURATION = 0.15;
|
||||
|
||||
const intro = reactive({
|
||||
frameOffsetY: SLIDE_OFFSET,
|
||||
frameOpacity: 0,
|
||||
scoreOffsetY: SCORE_OFFSET,
|
||||
tilesVisible: false,
|
||||
});
|
||||
|
||||
const emptyBoard = () =>
|
||||
Array.from({ length: BOARD_SIZE }, () =>
|
||||
@@ -125,12 +136,55 @@ const animateSpawnAll = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const animateIntro = async () => {
|
||||
buildTilesFromBoard();
|
||||
|
||||
await gsap
|
||||
.timeline()
|
||||
.to(intro, { frameOffsetY: 0, duration: SLIDE_DURATION, ease: "none" }, 0)
|
||||
.to(intro, { frameOpacity: 1, duration: SLIDE_DURATION, ease: "none" }, 0)
|
||||
.call(
|
||||
() => {
|
||||
intro.tilesVisible = true;
|
||||
animateSpawnAll();
|
||||
},
|
||||
[],
|
||||
SLIDE_DURATION,
|
||||
)
|
||||
.to(
|
||||
intro,
|
||||
{ scoreOffsetY: 0, duration: SCORE_DURATION, ease: "none" },
|
||||
SLIDE_DURATION,
|
||||
);
|
||||
};
|
||||
|
||||
const animateOutro = async () => {
|
||||
await gsap
|
||||
.timeline()
|
||||
.to(
|
||||
intro,
|
||||
{ frameOffsetY: SLIDE_OFFSET, duration: SLIDE_DURATION, ease: "none" },
|
||||
0,
|
||||
)
|
||||
.to(intro, { frameOpacity: 0, duration: SLIDE_DURATION, ease: "none" }, 0)
|
||||
.to(
|
||||
intro,
|
||||
{ scoreOffsetY: SCORE_OFFSET, duration: SCORE_DURATION, ease: "none" },
|
||||
0,
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
animateIntro();
|
||||
});
|
||||
|
||||
onRender((ctx) => {
|
||||
assets.images.home.topScreen.background.draw(ctx, 0, 0);
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(BOARD_X, BOARD_Y);
|
||||
ctx.globalAlpha = intro.frameOpacity;
|
||||
ctx.translate(BOARD_X, BOARD_Y + intro.frameOffsetY);
|
||||
|
||||
assets.images.settings.bottomScreen.options._2048.frame.draw(ctx, -3, -3);
|
||||
|
||||
@@ -149,6 +203,11 @@ onRender((ctx) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!intro.tilesVisible) {
|
||||
ctx.restore();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const tile of tiles) {
|
||||
const color = TILE_COLORS[tile.value] ?? LAST_TILE_COLOR;
|
||||
|
||||
@@ -174,27 +233,20 @@ onRender((ctx) => {
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
|
||||
ctx.font = "7px NDS7";
|
||||
ctx.fillStyle = "#010101";
|
||||
|
||||
// score
|
||||
ctx.fillText(`${$t("settings.options.2048.score")}:`, SCORE_X, SCORE_Y);
|
||||
ctx.fillText(score.toString(), SCORE_X, SCORE_Y + 16);
|
||||
|
||||
// high score
|
||||
ctx.fillText(
|
||||
`${$t("settings.options.2048.highScore")}:`,
|
||||
SCORE_X,
|
||||
HIGH_SCORE_Y,
|
||||
);
|
||||
ctx.fillText(
|
||||
savedState.value.highScore.toString(),
|
||||
SCORE_X,
|
||||
HIGH_SCORE_Y + 16,
|
||||
);
|
||||
});
|
||||
|
||||
onRender((ctx) => {
|
||||
ctx.translate(0, intro.scoreOffsetY);
|
||||
drawButton(ctx, `${$t("settings.options.2048.score")}: ${score}`, 10, 2, 118);
|
||||
drawButton(
|
||||
ctx,
|
||||
`${$t("settings.options.2048.highScore")}: ${savedState.value.highScore}`,
|
||||
138,
|
||||
2,
|
||||
108,
|
||||
);
|
||||
}, 110);
|
||||
|
||||
const getCell = (row: number, col: number) => board[row]![col]!;
|
||||
const setCell = (row: number, col: number, val: number) => {
|
||||
board[row]![col] = val;
|
||||
@@ -297,10 +349,9 @@ const isDead = () => {
|
||||
};
|
||||
|
||||
if (board.every((r) => r.every((c) => c === 0))) {
|
||||
resetBoard();
|
||||
} else {
|
||||
buildTilesFromBoard();
|
||||
animateSpawnAll();
|
||||
spawnTile();
|
||||
spawnTile();
|
||||
saveState();
|
||||
}
|
||||
|
||||
const slide = (rowDir: number, colDir: number) => {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 134 B |
Reference in New Issue
Block a user