Title of State:

Resource Interaction

Goal of Change:

Goal: you can click a resource, it becomes selected + highlighted, and you get a readout (Type + world coords + distance + count index) in the HUD.

What we add:

PATCH 1 — State: add selected index

Code to Remove

381 - 
  resourceSettings: null,
  resources: [],       // [{Type, X, Y, Radius}...]

Code to Add

381 -
  resourceSettings: null,
  resources: [],               // [{Type, X, Y, Radius}...]
  selectedResourceIndex: -1,   // index into S.resources


PATCH 2 — Replace onClick() with selection logic (screen → world)

Code to Remove

459 - 
function onClick(x,y){
  // placeholder: prove it works
  // replace with selection / commands later
}

Code to Add

459 - 
function onClick(x,y){
  if(S.view !== "GAME") return;

  // screen -> world
  const wx = x + S.camX;
  const wy = y + S.camY;

  const idx = findResourceAtWorld(wx, wy);
  S.selectedResourceIndex = idx;

  // small HUD feedback (selection also reflected in draw + HUD lines)
  // idx === -1 means cleared selection
}


PATCH 3 — Add hit-test + selection helpers (insert right before drawResources())

Code to Remove

628 - 
function drawResources(){

Code to Add

628 -
function findResourceAtWorld(wx, wy){
  if(!S.resources || S.resources.length === 0) return -1;

  // pick nearest within radius
  let best = -1;
  let bestD2 = Infinity;

  for(let i=0;i<S.resources.length;i++){
    const n = S.resources[i];
    const dx = wx - n.X;
    const dy = wy - n.Y;
    const r = (n.Radius || 16) + 6; // click tolerance
    const d2 = dx*dx + dy*dy;
    if(d2 <= r*r && d2 < bestD2){
      bestD2 = d2;
      best = i;
    }
  }
  return best;
}

function drawSelectedResourceOverlay(){
  const i = S.selectedResourceIndex;
  if(i == null || i < 0) return;
  if(!S.resources || i >= S.resources.length) return;

  const n = S.resources[i];
  const sx = n.X - S.camX;
  const sy = n.Y - S.camY;

  // if selected is offscreen, do nothing
  if(sx < -80 || sy < -80 || sx > (VIEW+80) || sy > (VIEW+80)) return;

  // highlight ring
  ctx.save();
  ctx.globalAlpha = 0.95;
  ctx.strokeStyle = "rgba(255,255,255,.85)";
  ctx.lineWidth = 3;
  ctx.beginPath();
  ctx.arc(sx, sy, (n.Radius || 16) + 10, 0, Math.PI*2);
  ctx.stroke();

  // small crosshair
  ctx.globalAlpha = 0.6;
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(sx-18, sy); ctx.lineTo(sx+18, sy);
  ctx.moveTo(sx, sy-18); ctx.lineTo(sx, sy+18);
  ctx.stroke();

  // label
  ctx.globalAlpha = 0.9;
  ctx.fillStyle = "rgba(0,0,0,.75)";
  ctx.font = "12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
  ctx.fillText(`SEL ${n.Type}`, sx + 16, sy - 16);
  ctx.restore();
}

function drawResources(){


PATCH 4 — Draw: render selected overlay on top of resources

Code to Remove

773 - 
  // map first (so other debug overlays draw on top)
  drawMapNative();
  // resources on top of map
  drawResources();

Code to Add

773 - 
  // map first (so other debug overlays draw on top)
  drawMapNative();
  // resources on top of map
  drawResources();
  // selected resource overlay
  drawSelectedResourceOverlay();


PATCH 5 — HUD: include selected resource info

Code to Remove

812 - 
  setHUD(
  (S.paused ? "PAUSED" : "READY") +
  `\\nFPS: ${S.fps}` +
  `\\nM: ${Math.floor(S.mouseX)},${Math.floor(S.mouseY)}` +
  `\\nCAM: ${Math.floor(S.camX)},${Math.floor(S.camY)}` +
  `\\nRES: ${S.resources ? S.resources.length : 0}`
);

Code to Add

812 - 
  const si = S.selectedResourceIndex;
  let selLine = "\\nSEL: -";
  if(si != null && si >= 0 && S.resources && si < S.resources.length){
    const n = S.resources[si];
    selLine = `\\nSEL: #${si} ${n.Type} @ ${Math.floor(n.X)},${Math.floor(n.Y)}`;
  }

  setHUD(
  (S.paused ? "PAUSED" : "READY") +
  `\\nFPS: ${S.fps}` +
  `\\nM: ${Math.floor(S.mouseX)},${Math.floor(S.mouseY)}` +
  `\\nCAM: ${Math.floor(S.camX)},${Math.floor(S.camY)}` +
  `\\nRES: ${S.resources ? S.resources.length : 0}` +
  selLine
);


PATCH 6 — Clear selection when starting a new game

Code to Remove

566 - 
  reseed(seedInput.value);
  generateResources();
  setView("GAME");

Code to Add

566 - 
  reseed(seedInput.value);
  generateResources();
  S.selectedResourceIndex = -1;
  setView("GAME");


Result