diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-23 02:48:43 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-23 02:48:43 -0700 |
| commit | 80824a8b69b70e6e40577e4f0236c28c4ad5c15b (patch) | |
| tree | bf3b72331c4ed9195bbe72d25d5e82c076d3220a /src/sim/lib/force.rs | |
| parent | d6664b9b5a9a3aab500b547e4d7448a8bc4ad416 (diff) | |
explosions affect rigidbodies, use "world" for rapier
Diffstat (limited to 'src/sim/lib/force.rs')
| -rw-r--r-- | src/sim/lib/force.rs | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/src/sim/lib/force.rs b/src/sim/lib/force.rs index db8e076..e99817c 100644 --- a/src/sim/lib/force.rs +++ b/src/sim/lib/force.rs @@ -1,9 +1,11 @@ use glam::Vec2; use rand::random_range; +use rapier2d::{dynamics::RigidBodyHandle, parry::bounding_volume::Aabb, pipeline::QueryFilter}; use crate::{ + config::CELLS_TO_METRES, content::materials::{MaterialForm, MaterialId, fire::FireCellView}, - sim::{cell::cell::Cell, particle_manager::particle::Particle, sim_manager::SimCtx}, + sim::{cell::Cell, lib::ray::AwDda, particle_manager::particle::Particle, sim_manager::SimCtx}, }; pub fn apply_explosion( @@ -15,7 +17,7 @@ pub fn apply_explosion( ) { let get_vel = |pos: Vec2| { let d = pos.distance(centre); - if d < 0.001 { + if d < 0.001 || d > radius as f32 { return Vec2::ZERO; } let dir = (pos - centre) / d; @@ -46,6 +48,7 @@ pub fn apply_explosion( vel, MaterialId::Fire, 1.0, + 0.0, )); } } else if [ @@ -64,6 +67,7 @@ pub fn apply_explosion( vel, cell.material, 5.0, + 0.0, )); } } @@ -73,4 +77,75 @@ pub fn apply_explosion( } // rigidbodies + let colliders = ctx + .rb_manager + .physics_manager + .world + .intersect_aabb_conservative( + Aabb::new( + (centre - radius as f32) / CELLS_TO_METRES, + (centre + radius as f32) / CELLS_TO_METRES, + ), + QueryFilter::only_dynamic(), + ); + + let body_handles: Vec<Option<RigidBodyHandle>> = colliders.map(|(_, c)| c.parent()).collect(); + + for h in body_handles { + if let Some(h) = h + && let Some(body) = ctx.rb_manager.physics_manager.world.bodies.get_mut(h) + { + // magic divisor number for good vibes + body.apply_impulse(get_vel(body.translation() * CELLS_TO_METRES) / 3.0, true); + } + } +} + +// TODO profile packing entity ID into cells? +// might improve performance by a lot if we don't have to raycast for hit entities +pub fn apply_bullet(ctx: &mut SimCtx, from: Vec2, to: Vec2, power: u32) { + let dda = AwDda::new(from, to); + let mut p = power as i32; + + let dir = (to - from).normalize(); + + for collision in dda { + if let Some(cell) = ctx + .cell_manager + .get_cell_from_game_position(collision.x, collision.y) + { + let m = cell.material.def(); + if ![ + MaterialForm::Solid, + MaterialForm::Powder, + MaterialForm::Liquid, + ] + .contains(&m.form) + { + continue; + } + + p -= m.density as i32; + if p <= 0 { + break; + } + + ctx.cell_manager.set_cell_from_game_position( + collision.x, + collision.y, + Cell::void(), + false, + ); + + if random_range(0.0..1.0) > 0.8 { + ctx.particle_manager.particles.push(Particle::new( + collision.as_vec2(), + (dir + Vec2::new(random_range(-0.15..0.15), random_range(-0.15..0.15))) * 150.0, + cell.material, + 5.0, + 0.2, + )); + } + } + } } |
