summaryrefslogtreecommitdiff
path: root/src/sim/lib/force.rs
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-23 02:48:43 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-23 02:48:43 -0700
commit80824a8b69b70e6e40577e4f0236c28c4ad5c15b (patch)
treebf3b72331c4ed9195bbe72d25d5e82c076d3220a /src/sim/lib/force.rs
parentd6664b9b5a9a3aab500b547e4d7448a8bc4ad416 (diff)
explosions affect rigidbodies, use "world" for rapier
Diffstat (limited to 'src/sim/lib/force.rs')
-rw-r--r--src/sim/lib/force.rs79
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,
+ ));
+ }
+ }
+ }
}