From defc5f0712734f5decf5b7e174598d256cd6feb3 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Fri, 21 Aug 2026 23:45:22 -0700 Subject: better explosions --- src/sim/lib/force.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/sim/lib/force.rs (limited to 'src/sim/lib/force.rs') 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 +} -- cgit v1.3.1