diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-21 23:45:22 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-22 00:07:01 -0700 |
| commit | defc5f0712734f5decf5b7e174598d256cd6feb3 (patch) | |
| tree | ddf0cfb03f0be4a3c941ab4b0f7ebd289ff4326e /src/sim | |
| parent | a216e61a00bde792a49a92593012f9baecf86f3d (diff) | |
better explosions
Diffstat (limited to 'src/sim')
| -rw-r--r-- | src/sim/cell/materials/fire.rs | 3 | ||||
| -rw-r--r-- | src/sim/lib/force.rs | 76 | ||||
| -rw-r--r-- | src/sim/lib/mod.rs | 1 |
3 files changed, 78 insertions, 2 deletions
diff --git a/src/sim/cell/materials/fire.rs b/src/sim/cell/materials/fire.rs index f582a0c..2a1225e 100644 --- a/src/sim/cell/materials/fire.rs +++ b/src/sim/cell/materials/fire.rs @@ -34,11 +34,11 @@ pub fn sim_update(ctx: &mut UpdateCtx) { // we have a chance to live longer--roughly ?% chance of living an extra second if ctx.rng.random_range(0.0..1.0) > 0.9 { // kill ourselves, with a chance to turn into ash - ctx.do_rewrite = false; if ctx.rng.random_range(0.0..1.0) > 0.8 { // TODO ash material // ctx.set_cell(0, 0, Cell::from_material(MaterialId::Sand)); } else { + ctx.do_rewrite = false; ctx.set_cell(0, 0, Cell::void()); } return; @@ -77,5 +77,4 @@ pub fn sim_update(ctx: &mut UpdateCtx) { } ctx.cell.set_ticks_lived(ticks_lived + 1); - ctx.set_cell(0, 0, *ctx.cell); } diff --git a/src/sim/lib/force.rs b/src/sim/lib/force.rs new file mode 100644 index 0000000..50b5c70 --- /dev/null +++ b/src/sim/lib/force.rs @@ -0,0 +1,76 @@ +use glam::Vec2; +use rand::random_range; + +use crate::sim::{ + cell::{ + cell::Cell, + materials::{MaterialId, fire::FireCellView}, + }, + cell_sim::world::World, + particle_sim::{ParticleManager, particle::Particle}, + rb_sim::RbSimManager, +}; + +pub fn apply_explosion( + centre: Vec2, + radius: i32, + force_offset: Vec2, + force_multiplier: f32, + next_seqno: u64, + particle_manager: &mut ParticleManager, + world: &mut World, + rbsm: &mut RbSimManager, +) { + let get_vel = |pos: Vec2| { + let d = pos.distance(centre); + if d < 0.001 { + return Vec2::ZERO; + } + let dir = (pos - centre) / d; + let falloff = 1.0 - (d / radius as f32); + return (force_offset + dir) * force_multiplier * random_range(0.5..1.5) * falloff; + }; + + // cell grid + for x in -radius..radius { + for y in -radius..radius { + if x.pow(2) + y.pow(2) < radius.pow(2) { + // if there's a cell, convert it to a particle + let pos = Vec2::new(centre.x + x as f32, centre.y + y as f32); + let ipos = pos.round().as_ivec2(); + if let Some(cell) = world.get_cell_from_game_position(ipos.x, ipos.y) { + let mut fire = Cell::from_material(MaterialId::Fire); + fire.set_ticks_lived(300); + fire.match_parity(next_seqno); + + if cell.material == MaterialId::Void && random_range(0.0..1.0) > 0.5 { + if random_range(0.0..1.0) > 0.1 { + world.set_cell_from_game_position(ipos.x, ipos.y, fire, false); + } else { + let vel = get_vel(pos); + particle_manager.particles.push(Particle::new( + pos, + vel, + MaterialId::Fire, + 1.0, + )); + } + } else { + world.set_cell_from_game_position(ipos.x, ipos.y, fire, false); + if random_range(0.0..1.0) > 0.6 { + let vel = get_vel(pos); + particle_manager.particles.push(Particle::new( + pos, + vel, + cell.material, + 5.0, + )); + } + } + } + } + } + } + + // rigidbodies +} diff --git a/src/sim/lib/mod.rs b/src/sim/lib/mod.rs index 1d802dc..a00d7e6 100644 --- a/src/sim/lib/mod.rs +++ b/src/sim/lib/mod.rs @@ -1 +1,2 @@ +pub mod force; pub mod marching_squares; |
