summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-23 16:40:46 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-23 16:40:46 -0700
commit1e0ad48c47f0c4b3c2eadc19d65e20123b931023 (patch)
tree7442dc8b13da815015a04d4093d385cac9cfc933 /src/sim
parentda45c5a7dbb017c8e579d0ab66a2259a70b28f40 (diff)
bullet emitter
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/entity/mod.rs18
-rw-r--r--src/sim/sim_manager/mod.rs15
-rw-r--r--src/sim/sim_manager/utils.rs75
3 files changed, 68 insertions, 40 deletions
diff --git a/src/sim/entity/mod.rs b/src/sim/entity/mod.rs
index 2a046c5..a86a51f 100644
--- a/src/sim/entity/mod.rs
+++ b/src/sim/entity/mod.rs
@@ -49,6 +49,7 @@ impl Marchable for EntityCells {
}
pub trait EntityBehaviour {
+ // TODO merge ctxs?
fn update(&mut self, _update_ctx: &mut EntityUpdateCtx, _ctx: &mut SimCtx, _delta_time: f32) {}
fn physics_update(
&mut self,
@@ -67,6 +68,23 @@ pub struct EntityDef {
}
impl EntityDef {
+ pub fn from_cells_and_rb(
+ cells: EntityCells,
+ rb: RigidBody,
+ behaviour: Option<Box<dyn EntityBehaviour>>,
+ ) -> Self {
+ let collider = RbManager::convex_hull_collider_from_marchable(&cells, Some(10))
+ .mass(mass_from_cells(&cells.cells))
+ .build();
+
+ EntityDef {
+ rb: Some(rb),
+ collider: Some(collider),
+ cells: Some(cells),
+ behaviour,
+ }
+ }
+
pub fn from_cells(
position: Vec2,
cells: EntityCells,
diff --git a/src/sim/sim_manager/mod.rs b/src/sim/sim_manager/mod.rs
index be75eeb..89ae528 100644
--- a/src/sim/sim_manager/mod.rs
+++ b/src/sim/sim_manager/mod.rs
@@ -7,10 +7,12 @@ use crate::{
config::{PHYSICS_DELTA_TIME, PHYSICS_FPS, SIM_FPS},
sim::{
cell_manager::manager::CellManager,
- entity::{Entity, EntityDef, EntityId},
+ entity::{Entity, EntityDef, EntityId, EntityUpdateResult},
particle_manager::ParticleManager,
rb_manager::RbManager,
- sim_manager::utils::{read_back_entities_from_world, write_entities_to_world},
+ sim_manager::utils::{
+ process_entity_update_result, read_back_entities_from_world, write_entities_to_world,
+ },
},
};
@@ -112,10 +114,7 @@ impl SimManager {
if let Some(entity) = entity
&& let Some(result) = entity.update(&mut ctx, delta_time)
{
- // process entity update results
- for d in result.deferred_destructions {
- self.destroy_entity(d);
- }
+ process_entity_update_result(self, result);
}
}
@@ -136,9 +135,7 @@ impl SimManager {
if let Some(entity) = entity
&& let Some(result) = entity.physics_update(&mut ctx, delta_time)
{
- for d in result.deferred_destructions {
- self.destroy_entity(d);
- }
+ process_entity_update_result(self, result);
}
}
// before we move the rigidbodies, upsert the current terrain state
diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs
index 506844c..e77f30a 100644
--- a/src/sim/sim_manager/utils.rs
+++ b/src/sim/sim_manager/utils.rs
@@ -2,7 +2,11 @@ use glam::IVec2;
use crate::{
content::materials::MaterialId,
- sim::{cell::Cell, entity::EntityId, sim_manager::SimManager},
+ sim::{
+ cell::Cell,
+ entity::{EntityId, EntityUpdateResult},
+ sim_manager::SimManager,
+ },
};
fn write_entity_to_world(sim: &mut SimManager, entity_id: EntityId) -> Vec<(u8, u8, i32, i32)> {
@@ -82,46 +86,55 @@ pub fn read_back_entities_from_world(
cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)>,
) {
for (entity_id, cells_written) in cells_written_by_entity {
- if let Some(entity) = sim.entities.get_mut(&entity_id) {
- let entity_cells = entity.data.cells.as_mut().unwrap();
- let mut should_update_entity = false;
+ let mut entity = sim.entities.get_mut(&entity_id);
+ let mut should_update_entity = false;
- for (lx, ly, x, y) in cells_written {
- // update the entity
- // TODO optimize
- let new_local_cell = sim.cell_manager.get_cell_from_game_position(x, y).unwrap();
- if !new_local_cell.entity_integrated() {
- // this means that the entity changed in some way, so we should recompute its shape
- // TODO wait N frames to debounce this
- should_update_entity = true;
- }
+ for (lx, ly, x, y) in cells_written {
+ // update the entity
+ // TODO optimize
+ let new_local_cell = sim.cell_manager.get_cell_from_game_position(x, y).unwrap();
+ if !new_local_cell.entity_integrated() {
+ // this means that the entity changed in some way, so we should recompute its shape
+ // TODO wait N frames to debounce this
+ should_update_entity = true;
+ }
+ if let Some(entity) = &mut entity {
+ let entity_cells = entity.data.cells.as_mut().unwrap();
// we do this unconditionally because it's cheaper than checking if it actually needs to be updated
// and because we don't have a good way to track changes to cell state
entity_cells
.set_cell_at_local_position(IVec2::new(lx as i32, ly as i32), new_local_cell);
-
- // update the world
- // TODO optimize
- sim.cell_manager
- .set_cell_from_game_position(x, y, Cell::void(), false);
}
- if should_update_entity {
- if let Some(new_collider) = entity.compute_collider() {
- sim.rb_manager
- .physics_manager
- .world
- .remove_collider(entity.data.collider_h.unwrap());
+ // update the world
+ // TODO optimize
+ sim.cell_manager
+ .set_cell_from_game_position(x, y, Cell::void(), false);
+ }
- let new_handle = sim
- .rb_manager
- .physics_manager
- .world
- .insert_collider(new_collider, Some(entity.data.rb_h.unwrap()));
+ if let Some(entity) = &mut entity
+ && should_update_entity
+ {
+ if let Some(new_collider) = entity.compute_collider() {
+ sim.rb_manager
+ .physics_manager
+ .world
+ .remove_collider(entity.data.collider_h.unwrap());
- entity.data.collider_h = Some(new_handle);
- }
+ let new_handle = sim
+ .rb_manager
+ .physics_manager
+ .world
+ .insert_collider(new_collider, Some(entity.data.rb_h.unwrap()));
+
+ entity.data.collider_h = Some(new_handle);
}
}
}
}
+
+pub fn process_entity_update_result(sim: &mut SimManager, result: EntityUpdateResult) {
+ for d in result.deferred_destructions {
+ sim.destroy_entity(d);
+ }
+}