summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-21 23:45:22 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-22 00:07:01 -0700
commitdefc5f0712734f5decf5b7e174598d256cd6feb3 (patch)
treeddf0cfb03f0be4a3c941ab4b0f7ebd289ff4326e /src/sim
parenta216e61a00bde792a49a92593012f9baecf86f3d (diff)
better explosions
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/cell/materials/fire.rs3
-rw-r--r--src/sim/lib/force.rs76
-rw-r--r--src/sim/lib/mod.rs1
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;