Title of State:
Add 3 Maps to Game
Goal of Change:
implement map selection in the MENU, preload the 12 tile images, and in GAME we draw at native size (2560×2560 tiles, no scaling) and let the 1500×1500 canvas clip what doesn’t fit.
I made the images and loaded them to the site
PATCH 1 — Replace the MENU body with a 3-map selector + disabled Start
Code to Remove
141 - <div class="menuBody">
<button id="btnStartGame" class="btnPrimary" type="button">START GAME</button>
</div>
Code to Add
141 - <div class="menuBody">
<div class="menuGrid">
<button class="mapCard" id="mapGrass" type="button">
<div class="mapName">Grass</div>
<div class="mapMeta">5120×5120 (4 tiles)</div>
</button>
<button class="mapCard" id="mapSand" type="button">
<div class="mapName">Sand</div>
<div class="mapMeta">5120×5120 (4 tiles)</div>
</button>
<button class="mapCard" id="mapSnow" type="button">
<div class="mapName">Snow</div>
<div class="mapMeta">5120×5120 (4 tiles)</div>
</button>
</div>
<div class="menuActions">
<button id="btnStartGame" class="btnPrimary" type="button" disabled>START GAME</button>
</div>
</div>
PATCH 2 — Replace .menuBody{...} CSS with menu grid styles
Code to Remove
88 - .menuBody{
flex:1;
display:flex;
align-items:center;
justify-content:center;
padding:26px;
}
Code to Add
88 - .menuBody{
flex:1;
display:flex;
flex-direction:column;
gap:16px;
padding:22px 22px 20px 22px;
}
.menuGrid{
width:100%;
display:grid;
grid-template-columns: repeat(3, 1fr);
gap:14px;
}
.mapCard{
cursor:pointer;
text-align:left;
padding:16px;
border-radius:14px;
border:1px solid rgba(255,255,255,.14);
background:rgba(255,255,255,.06);
color:#e9f0ff;
min-height:130px;
}
.mapCard:hover{ background:rgba(255,255,255,.10); }
.mapCard.selected{
border-color:rgba(255,255,255,.34);
background:rgba(255,255,255,.12);
box-shadow:0 12px 34px rgba(0,0,0,.38);
}
.mapName{ font-size:18px; letter-spacing:.2px; }
.mapMeta{ margin-top:8px; font-size:12px; opacity:.85; }
.menuActions{
width:100%;
display:flex;
justify-content:center;
padding-top:4px;
}
#btnStartGame[disabled]{
opacity:.45;
cursor:not-allowed;
}
PATCH 3 — Add map buttons to the overlay element section
Code to Remove
223 - const btnBegin = document.getElementById("btnBegin");
const btnStartGame = document.getElementById("btnStartGame");
Code to Add
223 - const btnBegin = document.getElementById("btnBegin");
const btnStartGame = document.getElementById("btnStartGame");
/* Map buttons */
const mapGrassBtn = document.getElementById("mapGrass");
const mapSandBtn = document.getElementById("mapSand");
const mapSnowBtn = document.getElementById("mapSnow");
PATCH 4 — Add selected map + map assets to State
Code to Remove
232 - const S = {
paused:false,
view:"TITLE", // "TITLE" | "MENU" | "GAME"
mouseX:0, mouseY:0,
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
Code to Add
232 - const S = {
paused:false,
view:"TITLE", // "TITLE" | "MENU" | "GAME"
mapKey:null, // "GRASS" | "SAND" | "SNOW"
mouseX:0, mouseY:0,
fps:0, _acc:0, _frames:0,
last: performance.now(),
};
PATCH 5 — Replace the “Buttons” block with map logic + preload + guarded start
Code to Remove
295 - btnBegin.addEventListener("click", ()=> setView("MENU"));
btnStartGame.addEventListener("click", ()=> setView("GAME"));
Code to Add
295 - /* =========================
MAPS (NO SCALING)
========================= */
const MAPS = {
GRASS: [
"https://chrisdeasy.com/wp-content/uploads/20260212-Grass-1.png",
"https://chrisdeasy.com/wp-content/uploads/20260212-Grass-2.png",
"https://chrisdeasy.com/wp-content/uploads/20260212-Grass-3.png",
"https://chrisdeasy.com/wp-content/uploads/20260212-Grass-4.png",
],
SAND: [
"https://chrisdeasy.com/wp-content/uploads/20260213-Sand-1.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Sand-2.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Sand-3.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Sand-4.png",
],
SNOW: [
"https://chrisdeasy.com/wp-content/uploads/20260213-Snow-1.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Snow-2.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Snow-3.png",
"https://chrisdeasy.com/wp-content/uploads/20260213-Snow-4.png",
],
};
const MapImages = { GRASS:[null,null,null,null], SAND:[null,null,null,null], SNOW:[null,null,null,null] };
function loadImage(url){
return new Promise((resolve)=>{
const img = new Image();
img.onload = ()=> resolve(img);
img.onerror = ()=> resolve(null);
img.src = url;
});
}
async function preloadMaps(){
for(const key of Object.keys(MAPS)){
const imgs = await Promise.all(MAPS[key].map(loadImage));
MapImages[key] = imgs;
}
}
/* Map selection UI */
function setSelectedMap(key){
S.mapKey = key;
mapGrassBtn.classList.toggle("selected", key === "GRASS");
mapSandBtn.classList.toggle("selected", key === "SAND");
mapSnowBtn.classList.toggle("selected", key === "SNOW");
btnStartGame.disabled = false;
}
/* Buttons */
btnBegin.addEventListener("click", ()=> setView("MENU"));
mapGrassBtn.addEventListener("click", ()=> setSelectedMap("GRASS"));
mapSandBtn.addEventListener("click", ()=> setSelectedMap("SAND"));
mapSnowBtn.addEventListener("click", ()=> setSelectedMap("SNOW"));
btnStartGame.addEventListener("click", ()=>{
if(!S.mapKey) return;
setView("GAME");
});
PATCH 6 — Draw the selected map in GAME (no scaling, native tile placement)
Code to Remove
360 - /* Update / Draw */
function update(dt){
// your game logic goes here
}
function draw(){
// background
ctx.fillStyle = "#0f1422";
ctx.fillRect(0,0,W,H);
// anchor mark so you know it is drawing
const cx=W/2, cy=H/2;
ctx.strokeStyle="rgba(255,255,255,.22)";
ctx.lineWidth=1;
ctx.beginPath();
ctx.moveTo(cx-18,cy); ctx.lineTo(cx+18,cy);
ctx.moveTo(cx,cy-18); ctx.lineTo(cx,cy+18);
ctx.stroke();
// mouse dot (proves input works)
ctx.fillStyle="rgba(255,255,255,.65)";
ctx.beginPath();
ctx.arc(S.mouseX, S.mouseY, 3, 0, Math.PI*2);
ctx.fill();
}
Code to Add
360 - /* Update / Draw */
function update(dt){
// your game logic goes here
}
function drawMapNative(){
if(S.view !== "GAME") return;
if(!S.mapKey) return;
const tiles = MapImages[S.mapKey];
const t1 = tiles[0], t2 = tiles[1], t3 = tiles[2], t4 = tiles[3];
// NO SCALING.
// Each tile is 2560×2560. We draw them at native pixel coordinates.
// The 1500×1500 canvas will clip what doesn't fit.
if(t1) ctx.drawImage(t1, 0, 0);
if(t2) ctx.drawImage(t2, 2560, 0);
if(t3) ctx.drawImage(t3, 0, 2560);
if(t4) ctx.drawImage(t4, 2560, 2560);
}
function draw(){
// background
ctx.fillStyle = "#0f1422";
ctx.fillRect(0,0,W,H);
// map first (so other debug overlays draw on top)
drawMapNative();
// anchor mark so you know it is drawing
const cx=W/2, cy=H/2;
ctx.strokeStyle="rgba(255,255,255,.22)";
ctx.lineWidth=1;
ctx.beginPath();
ctx.moveTo(cx-18,cy); ctx.lineTo(cx+18,cy);
ctx.moveTo(cx,cy-18); ctx.lineTo(cx,cy+18);
ctx.stroke();
// mouse dot (proves input works)
ctx.fillStyle="rgba(255,255,255,.65)";
ctx.beginPath();
ctx.arc(S.mouseX, S.mouseY, 3, 0, Math.PI*2);
ctx.fill();
}
PATCH 7 — Preload maps at boot
Code to Remove
429 - setHUD("READY");
setView("TITLE");
requestAnimationFrame(loop);
Code to Add
429 - setHUD("READY");
setView("TITLE");
preloadMaps();
requestAnimationFrame(loop);