feat(settings/options/2048): allow faster movements and show restart modal when trying to move on an lost game
This commit is contained in:
@@ -28,33 +28,31 @@ const handleActivateA = () => {
|
||||
resetBoard();
|
||||
}
|
||||
},
|
||||
onCancel: () => {
|
||||
confirmationModal.close();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: one color scheme per app color
|
||||
const TILE_COLORS: Record<number, { bg: string; fg: string }> = {
|
||||
[0]: { bg: "#ccc0b4", fg: "#776e65" },
|
||||
[2]: { bg: "#eee4db", fg: "#776e65" },
|
||||
[4]: { bg: "#eee0cb", fg: "#776e65" },
|
||||
[8]: { bg: "#f3b27a", fg: "#f9f6f2" },
|
||||
[16]: { bg: "#f69664", fg: "#f9f6f2" },
|
||||
[32]: { bg: "#f67c5f", fg: "#f9f6f2" },
|
||||
[64]: { bg: "#f7603c", fg: "#f9f6f2" },
|
||||
[128]: { bg: "#ecd072", fg: "#f9f6f2" },
|
||||
[256]: { bg: "#eecc62", fg: "#f9f6f2" },
|
||||
[512]: { bg: "#eec950", fg: "#f9f6f2" },
|
||||
[1024]: { bg: "#edc53f", fg: "#f9f6f2" },
|
||||
[2048]: { bg: "#edc12e", fg: "#f9f6f2" },
|
||||
[4046]: { bg: "#3c3a33", fg: "#f9f6f2" },
|
||||
[0]: { bg: "#f7f7f7", fg: "#776e65" },
|
||||
[2]: { bg: "#ebebf3", fg: "#292929" },
|
||||
[4]: { bg: "#d3dbe3", fg: "#292929" },
|
||||
[8]: { bg: "#bacbd3", fg: "#292929" },
|
||||
[16]: { bg: "#a2bac3", fg: "#f9f6f2" },
|
||||
[32]: { bg: "#8aa2b2", fg: "#f9f6f2" },
|
||||
[64]: { bg: "#7192a2", fg: "#f9f6f2" },
|
||||
[128]: { bg: "#698aa2", fg: "#f9f6f2" },
|
||||
[256]: { bg: "#61829a", fg: "#f9f6f2" },
|
||||
[512]: { bg: "#5c7b92", fg: "#f9f6f2" },
|
||||
[1024]: { bg: "#57758a", fg: "#f9f6f2" }, // -2.5L, -0.8C
|
||||
[2048]: { bg: "#476277", fg: "#f9f6f2" },
|
||||
[4046]: { bg: "#173446", fg: "#f9f6f2" },
|
||||
};
|
||||
const LAST_TILE_COLOR =
|
||||
Object.values(TILE_COLORS)[Object.values(TILE_COLORS).length - 1]!;
|
||||
const TILE_SIZE = 28;
|
||||
const ANIM_DURATION = 0.1;
|
||||
|
||||
const BORDER_COLOR = "#bbada0";
|
||||
const BORDER_COLOR = "#d7d7d7";
|
||||
const BORDER_SIZE = 3;
|
||||
|
||||
const BOARD_X = 64;
|
||||
@@ -81,6 +79,21 @@ const cellY = (row: number) => BORDER_SIZE + row * (TILE_SIZE + BORDER_SIZE);
|
||||
let tiles: VisualTile[] = [];
|
||||
let animating = false;
|
||||
|
||||
const showRestartModal = () => {
|
||||
let confirmed = false;
|
||||
confirmationModal.open({
|
||||
text: "Game Over!\nRestart?",
|
||||
onConfirm: () => {
|
||||
confirmed = true;
|
||||
},
|
||||
onClosed: () => {
|
||||
if (confirmed) {
|
||||
resetBoard();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const buildTilesFromBoard = () => {
|
||||
tiles = [];
|
||||
for (let row = 0; row < BOARD_SIZE; row += 1) {
|
||||
@@ -104,6 +117,8 @@ onRender((ctx) => {
|
||||
ctx.textBaseline = "top";
|
||||
ctx.translate(BOARD_X, BOARD_Y);
|
||||
|
||||
assets.images.settings.bottomScreen.options._2048.frame.draw(ctx, -3, -3);
|
||||
|
||||
ctx.fillStyle = BORDER_COLOR;
|
||||
ctx.fillRect(
|
||||
0,
|
||||
@@ -251,7 +266,16 @@ if (board.every((r) => r.every((c) => c === 0))) {
|
||||
}
|
||||
|
||||
const slide = (rowDir: number, colDir: number) => {
|
||||
if (animating) return;
|
||||
if (isDead() && !confirmationModal.isOpen) {
|
||||
showRestartModal();
|
||||
return;
|
||||
}
|
||||
|
||||
if (animating) {
|
||||
gsap.globalTimeline.clear();
|
||||
animating = false;
|
||||
buildTilesFromBoard();
|
||||
}
|
||||
|
||||
const beforeTiles: { row: number; col: number; value: number }[] = [];
|
||||
for (let row = 0; row < BOARD_SIZE; row += 1) {
|
||||
@@ -358,6 +382,12 @@ const slide = (rowDir: number, colDir: number) => {
|
||||
const spawned = spawnTile();
|
||||
saveBoard();
|
||||
|
||||
if (isDead()) {
|
||||
buildTilesFromBoard();
|
||||
showRestartModal();
|
||||
return;
|
||||
}
|
||||
|
||||
tiles = animTiles;
|
||||
animating = true;
|
||||
|
||||
@@ -365,27 +395,11 @@ const slide = (rowDir: number, colDir: number) => {
|
||||
onComplete: () => {
|
||||
animating = false;
|
||||
buildTilesFromBoard();
|
||||
if (isDead()) {
|
||||
confirmationModal.open({
|
||||
text: "Game Over!\nRestart?",
|
||||
onConfirm: () => {
|
||||
resetBoard();
|
||||
confirmationModal.close();
|
||||
},
|
||||
onCancel: () => {
|
||||
confirmationModal.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
for (const { tile, toX, toY } of tweens) {
|
||||
tl.to(
|
||||
tile,
|
||||
{ x: toX, y: toY, duration: ANIM_DURATION, ease: "power1.out" },
|
||||
0,
|
||||
);
|
||||
tl.to(tile, { x: toX, y: toY, duration: ANIM_DURATION, ease: "none" }, 0);
|
||||
}
|
||||
|
||||
if (mergePairs.length > 0) {
|
||||
@@ -399,7 +413,7 @@ const slide = (rowDir: number, colDir: number) => {
|
||||
tl.fromTo(
|
||||
keep,
|
||||
{ scale: 1.1 },
|
||||
{ scale: 1, duration: ANIM_DURATION, ease: "power1.out" },
|
||||
{ scale: 1, duration: ANIM_DURATION, ease: "none" },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -424,6 +438,15 @@ const slide = (rowDir: number, colDir: number) => {
|
||||
|
||||
useKeyDown((key) => {
|
||||
switch (key) {
|
||||
// TODO: remove this, testing only
|
||||
case "n":
|
||||
savedBoard.value = [
|
||||
[0, 0, 2, 4],
|
||||
[8, 16, 32, 64],
|
||||
[128, 256, 512, 1024],
|
||||
[2048, 4096, 8192, 16384],
|
||||
];
|
||||
break;
|
||||
case "NDS_UP":
|
||||
slide(-1, 0);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user