fix: fire chain reaction — newly ignited cells now have updated_this_tick=true

Root cause: when update_fire ignited a neighbor via grid.set(), the new Fire
cell had updated_this_tick=false. If the dirty rect iteration hadn't reached
that cell yet, it was processed in the same tick, igniting ITS neighbors,
creating exponential spread within a single tick.

Fix: set updated_this_tick=true on all newly created Fire cells so they
wait until the next tick before spreading.

Applied to:
- update_fire: igniting flammable neighbors
- lava_interact: lava igniting wood/grass/flesh
- update_flesh: flesh turning to fire from heat
- update_grass: grass turning to fire from heat
- update_water: water turning to steam from heat
- projectile.rs: fireball impact igniting cells

Result: fire spreads 1 cell per tick (linear, not exponential).
171 FPS avg, p99 14ms — no lag when spamming fireballs.
This commit is contained in:
Emil
2026-06-22 16:35:17 +03:00
parent 93a6bcb35c
commit 01a350aebd
3 changed files with 26 additions and 14 deletions
+11 -11
View File
@@ -1,17 +1,17 @@
{
"mode": "graphics",
"ticks": 600,
"total_time_ms": 3483.9,
"avg_fps": 172.2,
"avg_frame_time_ms": 5.78,
"p99_frame_time_ms": 14.20,
"min_frame_time_ms": 4.20,
"total_time_ms": 3437.1,
"avg_fps": 174.6,
"avg_frame_time_ms": 5.70,
"p99_frame_time_ms": 13.96,
"min_frame_time_ms": 4.45,
"subsystems": {
"ca_step_avg_us": 1397,
"ca_step_p99_us": 10172,
"ca_step_min_us": 303,
"render_avg_us": 3668,
"render_p99_us": 5514,
"render_min_us": 3259
"ca_step_avg_us": 1259,
"ca_step_p99_us": 8885,
"ca_step_min_us": 670,
"render_avg_us": 3737,
"render_p99_us": 5483,
"render_min_us": 3221
}
}
+4 -1
View File
@@ -136,13 +136,16 @@ impl Projectile {
}
let cell = grid.get(x, y);
if cell.is_empty() {
grid.set(x, y, Cell::new(MaterialId::Fire));
let mut fire = Cell::new(MaterialId::Fire);
fire.updated_this_tick = true;
grid.set(x, y, fire);
} else if cell.material == MaterialId::Wood
|| cell.material == MaterialId::Grass
|| cell.material == MaterialId::Flesh
{
let mut ignited = cell;
ignited.material = MaterialId::Fire;
ignited.updated_this_tick = true;
grid.set(x, y, ignited);
grid.set_temp(x, y, 400.0);
}
+11 -2
View File
@@ -243,6 +243,7 @@ impl CellularAutomaton {
if temp > 100.0 {
let mut new = grid.get(x, y);
new.material = MaterialId::Steam;
new.updated_this_tick = true;
grid.set(x, y, new);
grid.set_temp(x, y, 110.0);
}
@@ -301,7 +302,10 @@ impl CellularAutomaton {
grid.set_temp(x, y, lava_temp - 50.0);
}
MaterialId::Wood | MaterialId::Grass | MaterialId::Flesh if n_temp < 300.0 => {
grid.set(nx, ny, Cell::new(MaterialId::Fire));
let mut new_n = neighbor;
new_n.material = MaterialId::Fire;
new_n.updated_this_tick = true;
grid.set(nx, ny, new_n);
grid.set_temp(nx, ny, 400.0);
}
MaterialId::Sand if n_temp > 1700.0 => {
@@ -377,6 +381,7 @@ impl CellularAutomaton {
if mat.flammable && n_temp < mat.ignition_temp {
let mut new_n = neighbor;
new_n.material = MaterialId::Fire;
new_n.updated_this_tick = true;
grid.set(nx, ny, new_n);
grid.set_temp(nx, ny, 400.0);
}
@@ -473,6 +478,7 @@ impl CellularAutomaton {
if temp > 200.0 {
let mut new = grid.get(x, y);
new.material = MaterialId::Fire;
new.updated_this_tick = true;
grid.set(x, y, new);
grid.set_temp(x, y, 400.0);
}
@@ -481,7 +487,10 @@ impl CellularAutomaton {
fn update_grass(&mut self, grid: &mut ChunkedGrid, x: i32, y: i32) {
let temp = grid.get_temp(x, y);
if temp > 250.0 {
grid.set(x, y, Cell::new(MaterialId::Fire));
let mut new = grid.get(x, y);
new.material = MaterialId::Fire;
new.updated_this_tick = true;
grid.set(x, y, new);
grid.set_temp(x, y, 400.0);
}
}