-
Notifications
You must be signed in to change notification settings - Fork 0
feat: update material types to include 'empty' and adjust related logic in simulation and tests #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,11 +2,11 @@ import { useRef, useEffect, useState, useCallback } from 'react' | |||||
| import './App.css' | ||||||
| import { DEFAULT_ZOOM, MAX_ZOOM } from './sim/constants' | ||||||
|
|
||||||
| type Material = 'sand' | 'water' | 'dirt' | 'stone' | 'plant' | 'fire' | 'gas' | 'fluff' | 'bug' | 'plasma' | 'nitro' | 'glass' | 'lightning' | 'slime' | 'ant' | 'alien' | 'quark' | 'crystal' | 'ember' | 'static' | 'bird' | 'gunpowder' | 'tap' | 'anthill' | 'bee' | 'flower' | 'hive' | 'honey' | 'nest' | 'gun' | 'cloud' | 'acid' | 'lava' | 'snow' | 'volcano' | 'mold' | 'mercury' | 'void' | 'seed' | 'rust' | 'spore' | 'algae' | 'poison' | 'dust' | 'firework' | 'bubble' | 'glitter' | 'star' | 'comet' | 'blackhole' | 'firefly' | 'worm' | 'fairy' | 'fish' | 'moth' | 'vent' | ||||||
| type Tool = Material | 'erase' | ||||||
| type Material = 'empty' | 'sand' | 'water' | 'dirt' | 'stone' | 'plant' | 'fire' | 'gas' | 'fluff' | 'bug' | 'plasma' | 'nitro' | 'glass' | 'lightning' | 'slime' | 'ant' | 'alien' | 'quark' | 'crystal' | 'ember' | 'static' | 'bird' | 'gunpowder' | 'tap' | 'anthill' | 'bee' | 'flower' | 'hive' | 'honey' | 'nest' | 'gun' | 'cloud' | 'acid' | 'lava' | 'snow' | 'volcano' | 'mold' | 'mercury' | 'void' | 'seed' | 'rust' | 'spore' | 'algae' | 'poison' | 'dust' | 'firework' | 'bubble' | 'glitter' | 'star' | 'comet' | 'blackhole' | 'firefly' | 'worm' | 'fairy' | 'fish' | 'moth' | 'vent' | ||||||
| type Tool = Material | ||||||
|
|
||||||
| const BUTTON_COLORS: Record<Tool, string> = { | ||||||
| erase: '#f87171', | ||||||
| empty: '#f87171', | ||||||
| sand: '#e6c86e', water: '#4a90d9', dirt: '#8b5a2b', stone: '#666666', | ||||||
| plant: '#228b22', fire: '#ff6600', gas: '#a8b844', fluff: '#f5e6d3', | ||||||
| bug: '#ff69b4', plasma: '#c8a2c8', nitro: '#39ff14', glass: '#a8d8ea', | ||||||
|
|
@@ -489,7 +489,7 @@ function App() { | |||||
| }, [dropdownOpen]) | ||||||
|
|
||||||
| const categories: Array<{ label: string; items: Tool[] }> = [ | ||||||
| { label: 'basic', items: ['erase', 'sand', 'water', 'dirt', 'stone', 'glass', 'snow', 'dust', 'fluff'] }, | ||||||
| { label: 'basic', items: ['empty', 'sand', 'water', 'dirt', 'stone', 'glass', 'snow', 'dust', 'fluff'] }, | ||||||
| { label: 'fluid', items: ['slime', 'acid', 'lava', 'mercury', 'honey', 'poison', 'gas', 'bubble'] }, | ||||||
| { label: 'energy', items: ['fire', 'ember', 'plasma', 'lightning', 'static', 'nitro', 'gunpowder', 'firework', 'quark', 'comet'] }, | ||||||
| { label: 'nature', items: ['plant', 'seed', 'flower', 'algae', 'mold', 'spore', 'rust', 'crystal', 'void', 'glitter'] }, | ||||||
|
|
@@ -542,6 +542,7 @@ function App() { | |||||
| className="material-dropdown-trigger" | ||||||
| style={{ '--material-color': BUTTON_COLORS[tool] } as React.CSSProperties} | ||||||
| onPointerDown={(e) => { | ||||||
| e.preventDefault(); | ||||||
| (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId) | ||||||
|
Comment on lines
+545
to
546
|
||||||
| brushDragRef.current = { startX: e.clientX, startSize: brushSizeRef.current, moved: false } | ||||||
| }} | ||||||
|
|
@@ -587,7 +588,7 @@ function App() { | |||||
| <button | ||||||
| key={m} | ||||||
| className={`material-dropdown-item ${tool === m ? 'active' : ''}`} | ||||||
| onClick={() => { if (m !== 'erase') lastMaterialRef.current = m as Material; setTool(m); setDropdownOpen(false) }} | ||||||
| onClick={() => { if (m !== 'empty') lastMaterialRef.current = m as Material; setTool(m); setDropdownOpen(false) }} | ||||||
|
||||||
| onClick={() => { if (m !== 'empty') lastMaterialRef.current = m as Material; setTool(m); setDropdownOpen(false) }} | |
| onClick={() => { setTool(m); setDropdownOpen(false) }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
| // Runs physics simulation and rendering off the main thread | ||
| // Uses two-canvas pipeline: world buffer (1px/cell) → GPU-scaled display canvas | ||
|
|
||
| import { MATERIAL_TO_ID, type Material, EMPTY, STONE, TAP, GUN, BLACK_HOLE, | ||
| import { MATERIAL_TO_ID, type Material, STONE, TAP, GUN, BLACK_HOLE, | ||
| DEFAULT_ZOOM, BG_COLOR } from './sim/constants' | ||
| import { ARCHETYPES } from './sim/archetypes' | ||
| import { renderSystem } from './sim/systems/render' | ||
|
|
@@ -22,7 +22,7 @@ let sim: Simulation | null = null | |
| let isPaused = false | ||
| let pauseAtStep: number | null = null | ||
| let debugChunks = false | ||
| let pendingInputs: Array<{ x: number; y: number; prevX: number; prevY: number; tool: Material | 'erase'; brushSize: number }> = [] | ||
| let pendingInputs: Array<{ x: number; y: number; prevX: number; prevY: number; tool: Material; brushSize: number }> = [] | ||
|
|
||
| // Camera state | ||
| let camX = 0 // top-left world cell (float) | ||
|
|
@@ -47,10 +47,10 @@ function initGrid(displayWidth: number, displayHeight: number, cols?: number, ro | |
| camY = 0 | ||
| } | ||
|
|
||
| function addParticles(cellX: number, cellY: number, tool: Material | 'erase', brushSize: number) { | ||
| function addParticles(cellX: number, cellY: number, tool: Material, brushSize: number) { | ||
| if (!sim) return | ||
| const { grid, cols, rows, rand, chunkMap } = sim | ||
| const matId = tool === 'erase' ? EMPTY : MATERIAL_TO_ID[tool as Material] | ||
| const matId = MATERIAL_TO_ID[tool] | ||
|
|
||
| if (matId === GUN) { | ||
| if (cellX >= 0 && cellX < cols && cellY >= 0 && cellY < rows) { | ||
|
|
@@ -70,7 +70,7 @@ function addParticles(cellX: number, cellY: number, tool: Material | 'erase', br | |
| if (nx >= 0 && nx < cols && ny >= 0 && ny < rows) { | ||
| const idx = ny * cols + nx | ||
| const spawnRate = ARCHETYPES[matId]?.spawnRate ?? 0.45 | ||
| if ((tool === 'erase' || (rand() < spawnRate && grid[idx] === EMPTY))) { | ||
| if (rand() < spawnRate) { | ||
| grid[idx] = matId | ||
| } | ||
|
Comment on lines
50
to
75
|
||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,7 +21,8 @@ test.describe('Control Buttons', () => { | |||||||||
|
|
||||||||||
| test('material dropdown opens and shows items', async ({ page }) => { | ||||||||||
| const trigger = page.locator('.material-dropdown-trigger') | ||||||||||
| await trigger.click() | ||||||||||
| const box = await trigger.boundingBox() | ||||||||||
| await page.mouse.click(box!.x + box!.width / 2, box!.y + box!.height / 2) | ||||||||||
|
Comment on lines
+24
to
+25
|
||||||||||
| const box = await trigger.boundingBox() | |
| await page.mouse.click(box!.x + box!.width / 2, box!.y + box!.height / 2) | |
| await expect(trigger).toBeVisible() | |
| await trigger.click() |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -37,7 +37,8 @@ test.describe('Particle Interactions', () => { | |||||||||
|
|
||||||||||
| test('selecting materials via dropdown works', async ({ page }) => { | ||||||||||
| const trigger = page.locator('.material-dropdown-trigger') | ||||||||||
| await trigger.click() | ||||||||||
| const box = await trigger.boundingBox() | ||||||||||
| await page.mouse.click(box!.x + box!.width / 2, box!.y + box!.height / 2) | ||||||||||
|
Comment on lines
+40
to
+41
|
||||||||||
| const box = await trigger.boundingBox() | |
| await page.mouse.click(box!.x + box!.width / 2, box!.y + box!.height / 2) | |
| await expect(trigger).toBeVisible() | |
| await trigger.click() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Materialis duplicated as a long union type in this file even thoughsrc/sim/constants.tsnow exportstype Material(including 'empty'). Duplicating this list risks the UI and worker diverging again; consider importing and reusing the sharedMaterialtype instead of redefining it here.