clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

Align pause shutter with menu choreography

Dami committed 5865bc4
commit
5865bc4931625741e81ed6ea6351b1d2a03fb990
parent
58a90aa96da287064b7563c22549f9bc97911066
author
Dami <dami.etoile@gmail.com>
3 files changed, +32 -13
Msrc/render/menu-motion.js6+++++
Msrc/render/stage-pause.js35++++++++++++++++++++----------
Mtests/menu-motion.test.js4+++-
M src/render/menu-motion.js +6 -0
M src/render/stage-pause.js +23 -12
@@ -20,7 +20,7 @@ export function wrapCanvasText(ctx, value, maxWidth) {
2020 }2121 2222 export function pausePawX(width) {23- return Math.max(24, width / 2 - 176);23+ return Math.max(32, width / 2 - 176);2424 }2525 2626 export function renderPauseScene(ctx, view = {}) {
@@ -55,25 +55,29 @@ export function renderPauseScene(ctx, view = {}) {
5555 ctx.fillRect(0, 0, w, Math.max(96, h * 0.16));5656 ctx.fillRect(0, h - Math.max(72, h * 0.12), w, Math.max(72, h * 0.12));5757 }58- ctx.fillStyle = `rgba(0,0,0,${0.74 * motion.openProgress})`;58+ ctx.fillStyle = `rgba(0,0,0,${0.74 * motion.dimProgress})`;5959 ctx.fillRect(0, 0, w, h);60- const shutterHeight = h * 0.62 * motion.shutterProgress;60+ const itemTop = h * 0.24;61+ const menuTitleY = itemTop - 58;62+ const lastItemY = itemTop + Math.max(0, pauseItems.length - 1) * pauseMotionLayout.pitch;63+ const bandTop = menuTitleY - 25;64+ const bandBottom = lastItemY + pauseMotionLayout.height / 2 + 26;65+ const bandCenter = (bandTop + bandBottom) / 2;66+ const shutterHeight = (bandBottom - bandTop) * motion.shutterProgress;6167 ctx.fillStyle = "#0F0E0D";62- ctx.fillRect(0, (h - shutterHeight) / 2, w, shutterHeight);68+ ctx.fillRect(0, bandCenter - shutterHeight / 2, w, shutterHeight);6369 ctx.strokeStyle = "#F2EEE6";6470 ctx.lineWidth = 1;6571 ctx.beginPath();66- ctx.moveTo(0, (h - shutterHeight) / 2); ctx.lineTo(w, (h - shutterHeight) / 2);67- ctx.moveTo(0, (h + shutterHeight) / 2); ctx.lineTo(w, (h + shutterHeight) / 2);72+ ctx.moveTo(0, bandCenter - shutterHeight / 2); ctx.lineTo(w, bandCenter - shutterHeight / 2);73+ ctx.moveTo(0, bandCenter + shutterHeight / 2); ctx.lineTo(w, bandCenter + shutterHeight / 2);6874 ctx.stroke();6975 ctx.textAlign = "center"; ctx.textBaseline = "middle";7076 ctx.fillStyle = "#FF4B3E"; ctx.font = "700 13px Recursive, monospace";7177 const pauseTitle = "PAUSED".slice(0, Math.ceil(6 * motion.titleProgress));7278 ctx.globalAlpha = motion.titleProgress;73- ctx.fillText(pauseTitle, w / 2, Math.max(75, h * 0.12));79+ ctx.fillText(pauseTitle, w / 2, menuTitleY);7480 ctx.globalAlpha = 1;75- const itemTop = h * 0.24;76- const selectedY = itemTop + motion.selectedPosition * pauseMotionLayout.pitch;7781 pauseItems.forEach((item, i) => {7882 const itemMotion = motion.itemProgress[i] ?? 1;7983 const y = itemTop + i * pauseMotionLayout.pitch - (1 - itemMotion) * 22;
@@ -84,10 +88,18 @@ export function renderPauseScene(ctx, view = {}) {
8488 ctx.globalAlpha = 1;8589 });8690 if (pauseItems.length && motion.openProgress > 0) {91+ const selectedMotion = motion.itemProgress[selected] ?? 1;92+ const selectedY = itemTop + motion.selectedPosition * pauseMotionLayout.pitch - (1 - selectedMotion) * 22;93+ ctx.globalAlpha = selectedMotion;8794 ctx.fillStyle = "#FF4B3E";8895 ctx.fillRect(w / 2 - 160, selectedY - 27, 320, pauseMotionLayout.height);96+ ctx.globalAlpha = 1;8997 }90- const pawX = pausePawX(w);98+ const coarsePointer = view.coarsePointer ?? false;99+ const mobileMenu = w < 760 || coarsePointer;100+ const pawX = mobileMenu ? w / 2 - 160 + 16 : pausePawX(w);101+ const selectedMotion = motion.itemProgress[selected] ?? 1;102+ const selectedY = itemTop + motion.selectedPosition * pauseMotionLayout.pitch - (1 - selectedMotion) * 22;91103 pauseItems.forEach((item, i) => {92104 const itemMotion = motion.itemProgress[i] ?? 1;93105 const y = itemTop + i * pauseMotionLayout.pitch - (1 - itemMotion) * 22;
@@ -96,7 +108,7 @@ export function renderPauseScene(ctx, view = {}) {
96108 ctx.globalAlpha = itemMotion;97109 ctx.fillStyle = "#0F0E0D";98110 ctx.font = "800 20px 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif";99- ctx.textAlign = "right";111+ ctx.textAlign = mobileMenu ? "left" : "right";100112 ctx.fillText(i === Math.round(motion.selectedPosition) ? "🐾" : "", pawX,101113 y + 1 - (i === Math.round(motion.selectedPosition) ? motion.pawHop : 0));102114 ctx.fillStyle = labelInHighlight ? "#0F0E0D" : "#F2EEE6";
@@ -112,7 +124,6 @@ export function renderPauseScene(ctx, view = {}) {
112124 const hintStart = h - 86 - (hintLines.length - 1) * hintLineHeight;113125 hintLines.forEach((line, index) => ctx.fillText(line, 32, hintStart + index * hintLineHeight));114126 }115- const coarsePointer = view.coarsePointer ?? false;116127 if (w > 760 && !coarsePointer) {117128 drawKeycap(ctx, "↑↓", "choose", 32, h - 46);118129 drawKeycap(ctx, "ENTER", "select", w / 2 - 4, h - 46, "right");
M tests/menu-motion.test.js +3 -1