From 180f50bdf6580419d4a6447917de86835913fdaf Mon Sep 17 00:00:00 2001 From: Thibaud Date: Tue, 5 Aug 2025 00:08:33 +0200 Subject: [PATCH] add game of life --- life.html | 12 +++++++++ life.ts | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 life.html create mode 100644 life.ts diff --git a/life.html b/life.html new file mode 100644 index 0000000..4611315 --- /dev/null +++ b/life.html @@ -0,0 +1,12 @@ + + + + + + Hello typescript + + + + + + diff --git a/life.ts b/life.ts new file mode 100644 index 0000000..aafefd3 --- /dev/null +++ b/life.ts @@ -0,0 +1,81 @@ +import { Point, resizeCanvas } from "./common.js" + +const WIDTH = 800; +const HEIGHT = 600; +const SCALING = 4; +const DIRECTIONS: Point[] = [ + { x: 0, y: -1}, // N + { x: -1, y: -1}, // NW + { x: 1, y: -1}, // NE + { x: -1, y: 0}, // W + { x: 1, y: 0}, // E + { x: 0, y: 1}, // S + { x: -1, y: 1}, // SW + { x: 1, y: 1}, // SE +] + +function add2(p1: Point, p2: Point) { + return { x: p1.x + p2.x, y: p1.y + p2.y }; +} + +function init() { + const canvas = document.getElementById("canvas") as HTMLCanvasElement | null; + if (!canvas) throw new Error("unable to get canvas HTML element"); + + const ctx = canvas.getContext("2d", { alpha: false }) as CanvasRenderingContext2D | null; + if (!ctx) throw new Error("unable to get canvas 2D context"); + + ctx.canvas.width = WIDTH + ctx.canvas.height = HEIGHT + + const cells = new Array(WIDTH * HEIGHT / SCALING) + cells.fill(0) + + const state = new Array(WIDTH * HEIGHT / SCALING) + state.fill(0) + + for (let i=0; i < WIDTH * HEIGHT / SCALING; i++) state[i] = +(Math.random() * 4 < 1) + + console.log(state.length) + + //window.addEventListener('resize', () => resizeCanvas(ctx)); + window.requestAnimationFrame(t => update(ctx, cells, state)); +} + +// update loop, called every frame +function update(ctx: CanvasRenderingContext2D, cells: number[], state: number[]) { + ctx.clearRect(0, 0, WIDTH, HEIGHT); + for (let i=0; i < WIDTH * HEIGHT / SCALING; i++) cells[i] = state[i]; + + const cell = (p: Point) => cells[p.y*WIDTH/SCALING + p.x] + + ctx.beginPath(); // batch draw calls, only once per frame + ctx.fillStyle = "white"; + for (let y=1; y < HEIGHT - 1; y++) { + for (let x=1; x < WIDTH - 1; x++) { + const p = { x, y }; + // count neighbors + let neighbors = 0; + for (const d of DIRECTIONS) { + const pos = add2(p, d); + neighbors += cell(pos); + } + + if (cell(p) == 1) { + state[p.y*WIDTH/SCALING+p.x] = +(neighbors == 2 || neighbors == 3) + } else { + state[p.y*WIDTH/SCALING+p.x] = +(neighbors == 3) + } + + if (cell(p) == 1) { + ctx.moveTo(p.x, p.y); + ctx.rect(p.x, p.y, SCALING, SCALING); + } + } + } + ctx.fill(); // draw only once per frame + + window.requestAnimationFrame(t => update(ctx, cells, state)); +} + +init();