import { createEngine, M, MATERIAL_NAMES, MATERIAL_COLORS } from "./engine"; import { Renderer } from "./renderer"; import { Input } from "./input"; import { Camera } from "./camera"; const GRID_WIDTH = 4096; const GRID_HEIGHT = 3072; const PAINT_MATERIALS = [M.SAND, M.WATER, M.LAVA, M.WOOD, M.FIRE, M.ICE, M.OIL, M.ACID, M.IRON, M.STONE, M.DIRT, M.GLASS]; async function main() { const canvas = document.getElementById("canvas") as HTMLCanvasElement; const renderer = new Renderer(canvas); const input = new Input(); const camera = new Camera(); camera.x = GRID_WIDTH / 2; camera.y = GRID_HEIGHT / 2; camera.zoom = 3; const engine = await createEngine(GRID_WIDTH, GRID_HEIGHT); // === EPIC WORLD: tiled 16 copies of the scene === function buildScene(ox: number, oy: number) { engine.fillRect(ox, oy + 740, 1024, 28, M.STONE); engine.fillRect(ox + 20, oy + 680, 80, 60, M.STONE); engine.fillRect(ox + 30, oy + 640, 60, 40, M.STONE); engine.fillRect(ox + 40, oy + 610, 40, 30, M.STONE); engine.fillCircle(ox + 60, oy + 600, 15, M.DIRT); engine.fillRect(ox + 50, oy + 660, 20, 20, M.DIRT); engine.fillRect(ox, oy + 720, 120, 20, M.STONE); engine.fillRect(ox + 85, oy + 705, 35, 15, M.STONE); engine.fillRect(ox + 5, oy + 705, 60, 15, M.STONE); engine.fillCircle(ox + 60, oy + 712, 12, M.LAVA); engine.fillCircle(ox + 70, oy + 708, 6, M.LAVA); engine.fillRect(ox + 60, oy + 695, 20, 10, M.DIRT); engine.fillRect(ox + 350, oy + 680, 100, 60, M.STONE); engine.fillRect(ox + 365, oy + 640, 70, 40, M.STONE); engine.fillRect(ox + 380, oy + 610, 40, 30, M.STONE); engine.fillRect(ox + 390, oy + 660, 20, 20, M.GLASS); engine.fillRect(ox + 370, oy + 700, 60, 40, M.WOOD); engine.fillCircle(ox + 400, oy + 690, 8, M.FIRE); engine.fillRect(ox + 395, oy + 675, 10, 5, M.FIRE); engine.fillRect(ox + 750, oy + 640, 50, 100, M.STONE); engine.fillRect(ox + 760, oy + 610, 30, 30, M.STONE); engine.fillRect(ox + 770, oy + 590, 10, 20, M.STONE); engine.fillCircle(ox + 775, oy + 580, 8, M.FIRE); engine.fillRect(ox + 760, oy + 650, 30, 40, M.WOOD); engine.fillRect(ox + 180, oy + 420, 100, 20, M.STONE); engine.fillRect(ox + 190, oy + 400, 80, 20, M.DIRT); engine.fillCircle(ox + 230, oy + 390, 15, M.SAND); engine.fillRect(ox + 200, oy + 380, 30, 20, M.WOOD); engine.fillCircle(ox + 215, oy + 385, 6, M.FIRE); engine.fillRect(ox + 240, oy + 410, 10, 10, M.GLASS); engine.fillRect(ox + 620, oy + 350, 80, 18, M.STONE); engine.fillRect(ox + 630, oy + 335, 60, 15, M.DIRT); engine.fillCircle(ox + 660, oy + 325, 12, M.SAND); engine.fillCircle(ox + 640, oy + 340, 8, M.ICE); engine.fillRect(ox, oy + 700, 100, 40, M.WATER); engine.fillRect(ox + 10, oy + 680, 80, 20, M.WATER); engine.fillRect(ox + 20, oy + 660, 60, 20, M.WATER); engine.fillRect(ox + 880, oy + 700, 80, 40, M.LAVA); engine.fillRect(ox + 890, oy + 680, 60, 20, M.LAVA); engine.fillRect(ox + 900, oy + 660, 40, 20, M.LAVA); engine.fillCircle(ox + 420, oy + 280, 30, M.ICE); engine.fillCircle(ox + 450, oy + 270, 20, M.ICE); engine.fillCircle(ox + 390, oy + 290, 18, M.ICE); engine.fillRect(ox + 420, oy + 300, 20, 15, M.ICE); engine.fillRect(ox + 100, oy + 720, 180, 20, M.SAND); engine.fillCircle(ox + 120, oy + 710, 25, M.SAND); engine.fillCircle(ox + 180, oy + 708, 30, M.SAND); engine.fillCircle(ox + 160, oy + 700, 18, M.SAND); engine.fillCircle(ox + 220, oy + 715, 20, M.SAND); engine.fillCircle(ox + 850, oy + 580, 22, M.OIL); engine.fillCircle(ox + 870, oy + 590, 14, M.OIL); engine.fillRect(ox + 840, oy + 600, 40, 20, M.OIL); engine.fillRect(ox + 470, oy + 660, 280, 10, M.WOOD); engine.fillRect(ox + 490, oy + 650, 40, 10, M.WOOD); engine.fillRect(ox + 710, oy + 650, 40, 10, M.WOOD); engine.fillRect(ox + 520, oy + 720, 180, 20, M.STONE); engine.fillRect(ox + 540, oy + 710, 140, 10, M.STONE); engine.fillCircle(ox + 600, oy + 718, 15, M.LAVA); engine.fillCircle(ox + 620, oy + 716, 10, M.LAVA); engine.fillRect(ox + 100, oy + 730, 40, 10, M.ACID); engine.fillCircle(ox + 120, oy + 732, 8, M.ACID); engine.fillRect(ox + 280, oy + 640, 40, 40, M.GLASS); engine.fillRect(ox + 290, oy + 650, 20, 30, M.STONE); engine.fillCircle(ox + 300, oy + 670, 5, M.FIRE); engine.fillCircle(ox + 550, oy + 520, 20, M.DIRT); engine.fillCircle(ox + 570, oy + 530, 14, M.DIRT); engine.fillCircle(ox + 200, oy + 520, 30, M.STONE); engine.fillCircle(ox + 220, oy + 500, 20, M.STONE); engine.fillRect(ox + 300, oy + 580, 12, 20, M.WATER); engine.fillRect(ox + 700, oy + 500, 10, 30, M.WATER); } for (let ty = 0; ty < 4; ty++) { for (let tx = 0; tx < 4; tx++) { buildScene(tx * 1024, ty * 768); } } engine.spawnActor(400, 550); camera.x = 400; camera.y = 550; const rw = engine.renderWidth(); const rh = engine.renderHeight(); function resize() { const dpr = window.devicePixelRatio || 1; renderer.resize(window.innerWidth, window.innerHeight, dpr); } window.addEventListener("resize", resize); resize(); let paintMat: number = M.SAND; function screenToGrid(sx: number, sy: number) { const mx = (sx / window.innerWidth - 0.5) * rw / camera.zoom + camera.x; const my = (sy / window.innerHeight - 0.5) * rh / camera.zoom + camera.y; return { x: Math.floor(mx), y: Math.floor(my) }; } function mouseWorld() { return { x: (input.mouseX / window.innerWidth - 0.5) * rw / camera.zoom + camera.x, y: (input.mouseY / window.innerHeight - 0.5) * rh / camera.zoom + camera.y, }; } const panel = document.getElementById("panel")!; function buildPanel() { panel.innerHTML = ""; PAINT_MATERIALS.forEach((mat, idx) => { const div = document.createElement("div"); div.className = "mat" + (mat === paintMat ? " active" : ""); div.dataset.mat = String(mat); div.innerHTML = `