返回 CodeWhale
web.ts
根目录 / pet / web.ts
1 // web.ts — the TypeScript/Canvas renderer for the pet.
2 //
3 // The renderer owns no simulation: the caller steps `sim` and passes the
4 // PetState that produced the frame — the same contract as the ratatui widget,
5 // the SwiftUI view, and the Compose composable. One pass:
6 //
7 // * filled dot per particle, colour and alpha from sim.frame
8 // * hollow frames stroke the dots instead of filling them
9 // * the caller (or the DOM caption) carries the non-colour label
10 //
11 // Reduced motion: step the sim with motion:false — the same contract as every
12 // other port.
13
14 import { PetSim, PetState, layout } from './PetSim.ts';
15
16 export function drawPet(ctx: CanvasRenderingContext2D, sim: PetSim, state: PetState, w: number, h: number): void {
17 const lay = layout(w, h, state);
18 const f = sim.frame;
19 ctx.globalAlpha = f.alpha;
20 const rgb = `rgb(${Math.round(f.r)},${Math.round(f.g)},${Math.round(f.b)})`;
21 ctx.lineWidth = 1;
22 const r = lay.dot / 2;
23 if (f.hollow) {
24 ctx.strokeStyle = rgb;
25 for (const q of sim.p) {
26 const x = lay.ox + q.x * lay.scale * lay.flipX;
27 const y = lay.oy + q.y * lay.scale;
28 ctx.beginPath();
29 ctx.arc(x, y, r, 0, 6.283);
30 ctx.stroke();
31 }
32 } else {
33 ctx.fillStyle = rgb;
34 for (const q of sim.p) {
35 const x = lay.ox + q.x * lay.scale * lay.flipX;
36 const y = lay.oy + q.y * lay.scale;
37 ctx.beginPath();
38 ctx.arc(x, y, r, 0, 6.283);
39 ctx.fill();
40 }
41 }
42 ctx.globalAlpha = 1;
43 }
44
44 lines TYPESCRIPT