| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
import { disc, drawTopdown as drawBoard } from "./engine/topdown.js"; |
| 9 |
import { AGENT_COLOUR } from "./scene.js"; |
| 10 |
|
| 11 |
const TILE_COLOUR = { |
| 12 |
"#": "#20242d", |
| 13 |
A: "#2c2a22", |
| 14 |
B: "#2c2a22", |
| 15 |
a: "#2a2024", |
| 16 |
d: "#1e2630", |
| 17 |
".": "#171a21", |
| 18 |
}; |
| 19 |
|
| 20 |
const tile = (cell) => TILE_COLOUR[cell] ?? "#171a21"; |
| 21 |
const label = (cell) => cell === "A" || cell === "B"; |
| 22 |
const trim = (p) => AGENT_COLOUR[p.agent] || "#888"; |
| 23 |
|
| 24 |
|
| 25 |
function under(ctx, snap, s) { |
| 26 |
for (const orb of snap.orbs) { |
| 27 |
ctx.fillStyle = "#c9a0ff"; |
| 28 |
ctx.beginPath(); |
| 29 |
ctx.arc(orb.x * s, orb.y * s, Math.max(2, 9 * s), 0, 7); |
| 30 |
ctx.fill(); |
| 31 |
} |
| 32 |
for (const zone of snap.zones) if (zone.k !== "smoke") drawZone(ctx, zone, s); |
| 33 |
|
| 34 |
if (snap.spike.x !== null) { |
| 35 |
const x = snap.spike.x * s; |
| 36 |
const y = snap.spike.y * s; |
| 37 |
const r = Math.max(2.5, 7 * s); |
| 38 |
ctx.fillStyle = snap.spike.planted ? (Math.floor(Date.now() / 250) % 2 ? "#ff5b4a" : "#8a2a22") : "#c8b45c"; |
| 39 |
ctx.fillRect(x - r, y - r, r * 2, r * 2); |
| 40 |
if (snap.spike.planted && snap.spike.defuse > 0) { |
| 41 |
ctx.fillStyle = "#4fd6a0"; |
| 42 |
ctx.fillRect(x - 20 * s, y + 12 * s, 40 * s * (snap.spike.defuse / 7), 3); |
| 43 |
} |
| 44 |
} |
| 45 |
} |
| 46 |
|
| 47 |
|
| 48 |
function over(ctx, snap, s) { |
| 49 |
for (const zone of snap.zones) if (zone.k === "smoke" && zone.f <= 0) drawZone(ctx, zone, s); |
| 50 |
} |
| 51 |
|
| 52 |
|
| 53 |
function badges(ctx, p, x, y, r) { |
| 54 |
if (p.spike) { |
| 55 |
ctx.fillStyle = "#f0d060"; |
| 56 |
ctx.fillRect(x - r * 0.4, y - r * 1.8, r * 0.8, r * 0.8); |
| 57 |
} |
| 58 |
if (p.blind) { |
| 59 |
ctx.fillStyle = "rgba(255,255,255,0.8)"; |
| 60 |
disc(ctx, x, y - r * 1.6, r * 0.35, true); |
| 61 |
} |
| 62 |
} |
| 63 |
|
| 64 |
export function drawTopdown(ctx, map, snap, look, box, opts = {}) { |
| 65 |
drawBoard(ctx, map, snap, look, box, { ...opts, tile, label, under, over, trim, badges }); |
| 66 |
} |
| 67 |
|
| 68 |
function drawZone(ctx, z, s) { |
| 69 |
const x = z.x * s; |
| 70 |
const y = z.y * s; |
| 71 |
const r = z.r * s; |
| 72 |
ctx.lineWidth = Math.max(1, s); |
| 73 |
if (z.k === "smoke") { |
| 74 |
ctx.fillStyle = "rgba(190,195,205,0.72)"; |
| 75 |
disc(ctx, x, y, r, true); |
| 76 |
} else if (z.k === "molly") { |
| 77 |
ctx.fillStyle = "rgba(230,110,50,0.45)"; |
| 78 |
ctx.strokeStyle = "#f08a4b"; |
| 79 |
disc(ctx, x, y, r, true, true); |
| 80 |
} else if (z.k === "wall") { |
| 81 |
ctx.fillStyle = "rgba(120,200,255,0.55)"; |
| 82 |
disc(ctx, x, y, r, true); |
| 83 |
} else if (z.k === "flash") { |
| 84 |
ctx.fillStyle = z.f > 0 ? "#ffe9a8" : "rgba(255,255,255,0.9)"; |
| 85 |
disc(ctx, x, y, z.f > 0 ? 5 * s : 30 * s, true); |
| 86 |
} else if (z.k === "dart") { |
| 87 |
ctx.strokeStyle = "rgba(90,220,170,0.7)"; |
| 88 |
disc(ctx, x, y, r, false, true); |
| 89 |
} else if (z.k === "trip") { |
| 90 |
ctx.strokeStyle = "rgba(230,200,90,0.8)"; |
| 91 |
disc(ctx, x, y, r, false, true); |
| 92 |
} else if (z.k === "heal") { |
| 93 |
ctx.fillStyle = "rgba(120,230,140,0.5)"; |
| 94 |
disc(ctx, x, y, 14 * s, true); |
| 95 |
} |
| 96 |
} |