import { Universe, Cell } from "wasm-game-of-life"; // Import wasm memory import { memory } from "wasm-game-of-life/wasm_game_of_life_bg"; const CELL_SIZE = 5; // px const GRID_COLOR = "#444444"; const DEAD_COLOR = "#000000"; const ALIVE_COLOR = "#FFFFFF"; const seed = Math.random(); const universe = ((seed) => { if (seed < 1/3) return Universe.new_modulo(); else if (seed < 2/3) return Universe.new_random(); else return Universe.new_space_ship(); })(seed); const width = universe.width(); const height = universe.height(); const canvas = document.getElementById("game-of-life-canvas"); canvas.height = (CELL_SIZE + 1) * height + 1; canvas.width = (CELL_SIZE + 1) * width + 1; const ctx = canvas.getContext('2d'); const PERIODE = 100; // ms let start; const renderLoop = (timestamp) => { drawGrid(); drawCells(); if (start === undefined) start = timestamp; const elapsed = timestamp - start; if (elapsed > PERIODE) { universe.tick(); start = timestamp; } requestAnimationFrame(renderLoop); }; const drawGrid = () => { ctx.beginPath(); ctx.strokeStyle = GRID_COLOR; for (let i = 0; i <= width; i++) { ctx.moveTo(i * (CELL_SIZE + 1) + 1, 0); ctx.lineTo(i * (CELL_SIZE + 1) + 1, (CELL_SIZE + 1) * height + 1); } for (let j = 0; j <= height; j++) { ctx.moveTo(0, j * (CELL_SIZE + 1) + 1); ctx.lineTo((CELL_SIZE + 1) * width + 1, j * (CELL_SIZE + 1) + 1); } ctx.stroke(); } const getIndex = (row, column) => { return row * width + column; } const drawCells = () => { const cellsPtr = universe.cells(); const cells = new Uint8Array(memory.buffer, cellsPtr, width * height / 8); ctx.beginPath(); for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const i = getIndex(row, col); ctx.fillStyle = bitIsSet(i, cells) ? ALIVE_COLOR : DEAD_COLOR; ctx.fillRect( col * (CELL_SIZE + 1) + 1, row * (CELL_SIZE + 1) + 1, CELL_SIZE, CELL_SIZE ); } } ctx.stroke(); } const bitIsSet = (n, arr) => { const byte = Math.floor(n / 8); const mask = 1 << (n % 8); return (arr[byte] & mask) === mask; } requestAnimationFrame(renderLoop);