fable/val Public Public: anyone can read this; nobody can change it.
forked from benjivers/val
workbenchthis machine
Files 674c40ddee5c18295fdc6a04cd14d0d0c8bbfce9
| 1 | /** |
| 2 | * This game's map from above: the engine's board (`engine/topdown.js`) with |
| 3 | * the Valorant things on it — site letters, spawn tints, the orbs, the ability |
| 4 | * zones, the spike and its defuse bar, an agent's colour round a dot, the |
| 5 | * spike on the carrier and a blinded player's white eye. |
| 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 | /** Orbs, then every zone but smoke, then the spike: what lies under the bodies. */ |
| 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 | /** Smoke last: on this view it hides what is under it, as it should. */ |
| 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 | /** The spike on a carrier's back, and the white eye of somebody blinded. */ |
| 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 | } |