Title of State:
Adding a Title Card and Menu Window
Goal of Change:
a 3-state overlay on top of your existing fixed 1500×1500 stage:
- STATE 0: Title Card (1400×1400 panel centered) + Begin button bottom-center
- STATE 1: Menu Window (overlay panel) + Start Game button
- STATE 2: Game (overlays hidden) → your current canvas loop is what you see
PATCH 1 — HTML: add the overlay layer inside #stage
Code to Remove
45 - <div id="hud">READY</div>
Code to Add
45 - <div id="hud">READY</div>
<div id="overlayRoot">
<!-- TITLE CARD -->
<div id="titleCard" class="panel titleCard">
<div class="panelHeader">
<div class="panelTitle">TITLE CARD</div>
<div class="panelSub">1400 × 1400 • Click Begin</div>
</div>
<button id="btnBegin" class="btnPrimary btnBottomCenter" type="button">BEGIN</button>
</div>
<!-- MENU -->
<div id="menuPanel" class="panel menuPanel" style="display:none;">
<div class="panelHeader">
<div class="panelTitle">MENU</div>
<div class="panelSub">Start the game</div>
</div>
<div class="menuBody">
<button id="btnStartGame" class="btnPrimary" type="button">START GAME</button>
</div>
</div>
</div>
PATCH 2 — CSS: add overlay styles
Code to Remove
31 - #hud{
position:absolute;left:12px;top:12px;
padding:8px 10px;border-radius:10px;
background:rgba(0,0,0,.35);
border:1px solid rgba(255,255,255,.12);
font-size:12px;
user-select:none;
white-space:pre;
}
Code to Add
31 - #hud{
position:absolute;left:12px;top:12px;
padding:8px 10px;border-radius:10px;
background:rgba(0,0,0,.35);
border:1px solid rgba(255,255,255,.12);
font-size:12px;
user-select:none;
white-space:pre;
pointer-events:none;
}
/* =========================
OVERLAY SYSTEM (TITLE → MENU → GAME)
========================= */
#overlayRoot{
position:absolute; inset:0;
display:flex;
align-items:center;
justify-content:center;
}
.panel{
border-radius:18px;
border:1px solid rgba(255,255,255,.14);
background:rgba(15,20,34,.78);
box-shadow:0 24px 80px rgba(0,0,0,.55);
backdrop-filter: blur(8px);
}
.panelHeader{
padding:24px 26px 0 26px;
}
.panelTitle{
font-size:28px;
letter-spacing:.3px;
}
.panelSub{
margin-top:8px;
font-size:13px;
opacity:.85;
}
/* Title Card: 1400x1400 */
.titleCard{
width:1400px;
height:1400px;
position:relative;
}
/* Menu panel size */
.menuPanel{
width:900px;
height:600px;
position:relative;
display:flex;
flex-direction:column;
}
.menuBody{
flex:1;
display:flex;
align-items:center;
justify-content:center;
padding:26px;
}
.btnPrimary{
cursor:pointer;
border:1px solid rgba(255,255,255,.16);
background:rgba(255,255,255,.10);
color:#e9f0ff;
padding:12px 18px;
border-radius:12px;
font-size:14px;
letter-spacing:.2px;
}
.btnPrimary:hover{ background:rgba(255,255,255,.14); }
/* Begin button bottom-center inside title card */
.btnBottomCenter{
position:absolute;
left:50%;
bottom:26px;
transform:translateX(-50%);
min-width:200px;
}
PATCH 3 — JS: add state + button wiring Part 1
Code to Remove
158 - const hud = document.getElementById("hud");
Code to Add
158 - const hud = document.getElementById("hud");
/* Overlay elements */
const overlayRoot = document.getElementById("overlayRoot");
const titleCard = document.getElementById("titleCard");
const menuPanel = document.getElementById("menuPanel");
const btnBegin = document.getElementById("btnBegin");
const btnStartGame = document.getElementById("btnStartGame");
PATCH 3 — JS: add state + button wiring Part 2 – State Object
Code to Remove
168 - const S = {
paused:false,
mouseX:0, mouseY:0,
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
Code to Add
168 - const S = {
paused:false,
view:"TITLE", // "TITLE" | "MENU" | "GAME"
mouseX:0, mouseY:0,
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
PATCH 3 — JS: add state + button wiring Part 3 – Toggle Pause
Code to Remove
205 - function togglePause(){
S.paused = !S.paused;
}
Code to Add
205 - function togglePause(){
// Only allow pausing once the game is running
if(S.view !== "GAME") return;
S.paused = !S.paused;
}
Code to Add (right after the toggle pause)
210 - function setView(v){
S.view = v;
if(v === "TITLE"){
titleCard.style.display = "block";
menuPanel.style.display = "none";
overlayRoot.style.display = "flex";
S.paused = false;
} else if(v === "MENU"){
titleCard.style.display = "none";
menuPanel.style.display = "flex";
overlayRoot.style.display = "flex";
S.paused = false;
} else { // GAME
overlayRoot.style.display = "none";
S.paused = false;
}
}
/* Buttons */
btnBegin.addEventListener("click", ()=> setView("MENU"));
btnStartGame.addEventListener("click", ()=> setView("GAME"));
PATCH 3 — JS: add state + button wiring Part 4 – Pause
Code to Remove
272 - if(!S.paused) update(dt);
Code to Add
272 - if(S.view === "GAME" && !S.paused) update(dt);
PATCH 3 — JS: add state + button wiring Part 5 – Boot
Code to Remove
283 - setHUD("READY");
requestAnimationFrame(loop);
Code to Add
283 - setHUD("READY");
setView("TITLE");
requestAnimationFrame(loop);