/** * The board from above, drawn into a canvas that writes down the colour of * every dot. What is pinned here is colour: who is drawn in which. */ import { expect, test } from "bun:test"; import { drawTopdown } from "../../static/engine/topdown.js"; function fakeContext() { const dots: { x: number; y: number; fill: string }[] = []; const rings: string[] = []; let at: { x: number; y: number } | null = null; const noop = () => {}; const ctx = { dots, rings, fillStyle: "", strokeStyle: "", lineWidth: 1, font: "", textAlign: "left", globalAlpha: 1, save: noop, restore: noop, beginPath: () => { at = null; }, closePath: noop, clip: noop, rect: noop, translate: noop, rotate: noop, moveTo: noop, lineTo: noop, fillRect: noop, fillText: noop, arc: (x: number, y: number) => { at = { x, y }; }, fill: () => { if (at) dots.push({ ...at, fill: ctx.fillStyle }); }, stroke: () => { if (ctx.globalAlpha < 1) rings.push(ctx.strokeStyle); }, }; return ctx; } const map = { rows: ["....", "....", "....", "...."], tile: 100 }; const box = { x: 0, y: 0, w: 400, h: 400 }; const me = { id: "me", name: "Me", x: 50, y: 50, angle: 0, alive: true, hp: 100, mate: true }; const body = (over: Record) => ({ name: "B", y: 200, angle: 0, alive: true, hp: 100, mate: false, ...over }); const draw = (players: unknown[], marks?: unknown[]) => { const ctx = fakeContext(); drawTopdown(ctx as never, map, { me, players: [me, ...players], shots: [] }, (p: unknown) => p, box, { marks, labels: false }); return ctx; }; /** Body dots, left to right; the arrow that is you is not a dot. */ const dots = (ctx: ReturnType) => [...ctx.dots].sort((a, b) => a.x - b.x).map((d) => d.fill); test("without `side`, a mate, an enemy and a fallen mate wear exactly today's colours", () => { const ctx = draw([body({ id: "m", mate: true, x: 100 }), body({ id: "e", x: 200 }), body({ id: "d", mate: true, alive: false, x: 300 })]); expect(dots(ctx)).toEqual(["#4fb3d9", "#e35d5b"]); expect(draw([], [{ id: "e", x: 200, y: 200, angle: 0, mate: false, fade: 0.5 }]).rings).toEqual(["#e35d5b", "#e35d5b"]); }); test("three enemy sides are three colours on the map, the same frame after frame", () => { const three = [ body({ id: "a", side: "map-red", x: 100 }), body({ id: "b", side: "map-gold", x: 200 }), body({ id: "c", side: "map-violet", x: 300 }), ]; const first = dots(draw(three)); expect(new Set(first).size).toBe(3); expect(first).not.toContain("#4fb3d9"); expect(dots(draw([...three].reverse()))).toEqual(first); // A last-seen ring wears its side's colour, not the default enemy's. const ring = draw([], [{ id: "c", x: 300, y: 200, angle: 0, mate: false, side: "map-violet", fade: 0.5 }]).rings; expect(ring[0]).toBe(first[2]); });