pike/val Public Public: anyone can read this; nobody can change it.
forked from benjivers/val
workbenchthis machine
Prove the view from the keys: Tab, and W walking where you look
The headless client run now presses Tab and counts the rectangles a frame draws — the first-person view draws a slice a column, the big map draws a tile a tile — and holds W to check the direction that reaches the server is the way the camera faces, which is the one thing the new input path could silently get wrong. Co-Authored-By: Claude Opus 5 <[email protected]>
1 file
changed +21
−4
src/client.test.ts +21 −4
| @@ -186,10 +186,28 @@ test("the bundled client connects, paints the HUD and draws a frame", async () = | ||
| 186 | 186 | // And the buy panel prices itself off the agent's real kit. |
| 187 | 187 | expect(String(buys[1]!.title)).toContain("charge"); |
| 188 | 188 | |
| 189 | // A frame of the first-person view actually draws walls. | |
| 189 | // A frame of the first-person view actually draws walls: a slice a column, | |
| 190 | // far more rectangles than the map has tiles. | |
| 190 | 191 | drawn.length = 0; |
| 191 | 192 | runFrame(); |
| 192 | expect(drawn.filter((op) => op.startsWith("fillRect")).length).toBeGreaterThan(200); | |
| 193 | expect(drawn.filter((op) => op.startsWith("fillRect")).length).toBeGreaterThan(800); | |
| 194 | ||
| 195 | // Tab swaps that frame for the whole map — many fewer rectangles. | |
| 196 | for (const fn of listeners.get("keydown") ?? []) fn({ code: "Tab", key: "", target: {}, preventDefault: noop }); | |
| 197 | drawn.length = 0; | |
| 198 | runFrame(); | |
| 199 | expect(drawn.filter((op) => op.startsWith("fillRect")).length).toBeLessThan(800); | |
| 200 | for (const fn of listeners.get("keyup") ?? []) fn({ code: "Tab" }); | |
| 201 | drawn.length = 0; | |
| 202 | runFrame(); | |
| 203 | expect(drawn.filter((op) => op.startsWith("fillRect")).length).toBeGreaterThan(800); | |
| 204 | ||
| 205 | // Holding W reaches the server as a direction, and it is the way we face. | |
| 206 | const seat = (await import("./arena.ts")).match().players.find((p) => !p.bot)!; | |
| 207 | press("KeyW"); | |
| 208 | await Bun.sleep(160); | |
| 209 | expect(Math.hypot(seat.input.mx, seat.input.my)).toBeGreaterThan(0.9); | |
| 210 | expect(Math.atan2(seat.input.my, seat.input.mx)).toBeCloseTo(seat.input.angle, 4); | |
| 193 | 211 | |
| 194 | 212 | // V falls back to the top-down view, and it draws too. |
| 195 | 213 | press("KeyV"); |
| @@ -218,6 +236,5 @@ test("the bundled client connects, paints the HUD and draws a frame", async () = | ||
| 218 | 236 | expect(panel.contains("on")).toBe(!wasOpen); |
| 219 | 237 | |
| 220 | 238 | // And the socket really took a seat in the running match. |
| 221 | const { match } = await import("./arena.ts"); | |
| 222 | expect(match().players.some((p) => !p.bot)).toBe(true); | |
| 239 | expect(seat.bot).toBe(false); | |
| 223 | 240 | }, 15000); |