summaryrefslogtreecommitdiff
path: root/src/sim/sim_manager
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/sim_manager')
-rw-r--r--src/sim/sim_manager/mod.rs125
-rw-r--r--src/sim/sim_manager/utils.rs28
2 files changed, 120 insertions, 33 deletions
diff --git a/src/sim/sim_manager/mod.rs b/src/sim/sim_manager/mod.rs
index a98f3b2..b6d2528 100644
--- a/src/sim/sim_manager/mod.rs
+++ b/src/sim/sim_manager/mod.rs
@@ -1,14 +1,18 @@
use std::time::Instant;
+use fxhash::FxHashMap;
+use glam::IVec2;
+
use crate::{
Config,
config::{PHYSICS_DELTA_TIME, PHYSICS_FPS, SIM_FPS},
sim::{
cell::{cell::Cell, materials::MaterialId},
cell_manager::manager::CellManager,
+ entity::{Entity, EntityDef},
particle_manager::ParticleManager,
rb_manager::RbManager,
- sim_manager::utils::write_rb_entity_to_world,
+ sim_manager::utils::write_entity_to_world,
},
};
@@ -27,53 +31,116 @@ pub struct SimManager {
pub cell_manager: CellManager,
pub rb_manager: RbManager,
pub particle_manager: ParticleManager,
+
+ // entities
+ // TODO entity manager?
+ next_entity_id: u32,
+ pub entities: FxHashMap<u32, Entity>,
}
impl SimManager {
- pub fn new() -> Self {
- SimManager {
- paused: false,
- ignore_pause_next_tick: false,
- last_cell_update: Instant::now(),
- cell_updates_due: 0.0,
- last_physics_update: Instant::now(),
- physics_updates_due: 0.0,
- cell_manager: CellManager::from_default_size(),
- rb_manager: RbManager::new(),
- particle_manager: ParticleManager::new(),
+ pub fn create_entity(&mut self, def: EntityDef) -> u32 {
+ let (rb_h, collider_h) = if let Some(rb) = def.rb {
+ let rb_h = self.rb_manager.physics_manager.rigid_body_set.insert(rb);
+
+ if let Some(collider) = def.collider {
+ let collider_h = self
+ .rb_manager
+ .physics_manager
+ .collider_set
+ .insert_with_parent(
+ collider,
+ rb_h,
+ &mut self.rb_manager.physics_manager.rigid_body_set,
+ );
+ (Some(rb_h), Some(collider_h))
+ } else {
+ (Some(rb_h), None)
+ }
+ } else if let Some(collider) = def.collider {
+ let collider_h = self
+ .rb_manager
+ .physics_manager
+ .collider_set
+ .insert(collider);
+ (None, Some(collider_h))
+ } else {
+ (None, None)
+ };
+
+ let entity = Entity::new(
+ self.next_entity_id,
+ rb_h,
+ collider_h,
+ def.cells,
+ def.behaviour,
+ );
+
+ let id = self.next_entity_id;
+ self.entities.insert(id, entity);
+ self.next_entity_id += 1;
+ id
+ }
+
+ pub fn destroy_entity(&mut self, id: u32) {
+ if let Some(entity) = self.entities.get(&id) {
+ if let Some(rb_h) = entity.rb_h {
+ self.rb_manager.physics_manager.rigid_body_set.remove(
+ rb_h,
+ &mut self.rb_manager.physics_manager.island_manager,
+ &mut self.rb_manager.physics_manager.collider_set,
+ &mut self.rb_manager.physics_manager.impulse_joint_set,
+ &mut self.rb_manager.physics_manager.multibody_joint_set,
+ true,
+ );
+ } else if let Some(collider_h) = entity.collider_h {
+ self.rb_manager.physics_manager.collider_set.remove(
+ collider_h,
+ &mut self.rb_manager.physics_manager.island_manager,
+ &mut self.rb_manager.physics_manager.rigid_body_set,
+ true,
+ );
+ }
+
+ self.entities.remove(&id);
}
}
fn cell_update(&mut self, config: &Config) {
- // before we tick, write all the rb entities into the sim world
+ // before we tick, write all the entities into the sim world
// TODO optimize
- let entity_ids: Vec<u32> = self.rb_manager.rb_entities.keys().copied().collect();
+ let entity_ids: Vec<u32> = self.entities.keys().copied().collect();
let mut cells_written_by_entity: Vec<(u32, Vec<(u8, u8, i32, i32)>)> = Vec::new();
for entity_id in entity_ids {
- let cells_written = write_rb_entity_to_world(self, entity_id, self.cell_manager.seqno);
+ let cells_written = write_entity_to_world(self, entity_id, self.cell_manager.seqno);
cells_written_by_entity.push((entity_id, cells_written));
}
self.cell_manager.tick(config.use_threading);
- // after we tick, remove the written rb cells and update the entities
+ // after we tick, remove the written entity cells and update the entities
// TODO optimize
for (entity_id, cells_written) in cells_written_by_entity {
- let rb_entity = self.rb_manager.rb_entities.get_mut(&entity_id).unwrap();
+ let entity = self.entities.get_mut(&entity_id).unwrap();
for (lx, ly, x, y) in cells_written {
// update the entity
// TODO we should skip cells that weren't changed?
// TODO optimize
let new_local_cell = self.cell_manager.get_cell_from_game_position(x, y).unwrap();
- if new_local_cell.material != MaterialId::Void && !new_local_cell.rb() {
+ if new_local_cell.material != MaterialId::Void && !new_local_cell.entity() {
panic!(
- "Someone swapped into this rb's cell! ({x}, {y}, {m:#?}, {f})",
+ "Someone swapped into this entity's cell! ({x}, {y}, {m:#?}, {f})",
m = new_local_cell.material,
f = new_local_cell.flags
);
}
- rb_entity.set_cell_at_local_position(lx, ly, new_local_cell);
+ if let Some(cells) = &mut entity.cells {
+ cells.set_cell_at_local_position(
+ IVec2::new(lx as i32, ly as i32),
+ new_local_cell,
+ );
+ }
// update the world
self.cell_manager
.set_cell_from_game_position(x, y, Cell::void(), false);
@@ -149,4 +216,22 @@ impl SimManager {
self.ignore_pause_next_tick = false;
}
+
+ pub fn new() -> Self {
+ SimManager {
+ paused: false,
+ ignore_pause_next_tick: false,
+ last_cell_update: Instant::now(),
+ cell_updates_due: 0.0,
+ last_physics_update: Instant::now(),
+ physics_updates_due: 0.0,
+
+ cell_manager: CellManager::from_default_size(),
+ rb_manager: RbManager::new(),
+ particle_manager: ParticleManager::new(),
+
+ next_entity_id: 0,
+ entities: FxHashMap::default(),
+ }
+ }
}
diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs
index b636186..1565ced 100644
--- a/src/sim/sim_manager/utils.rs
+++ b/src/sim/sim_manager/utils.rs
@@ -1,28 +1,30 @@
+use glam::IVec2;
+
use crate::sim::{cell::materials::MaterialId, sim_manager::SimManager};
-pub fn write_rb_entity_to_world(
+pub fn write_entity_to_world(
sim: &mut SimManager,
- rb_entity_id: u32,
+ entity_id: u32,
// make sure these cells will be simulated
seqno: u64,
// (entity_x, entity_y, cell_x, cell_y)
) -> Vec<(u8, u8, i32, i32)> {
let mut cells_written: Vec<(u8, u8, i32, i32)> = Vec::new();
- if let Some(rb_entity) = sim.rb_manager.rb_entities.get(&rb_entity_id)
- && let Some((rb_x, rb_y, cos, sin)) = sim.rb_manager.get_rb_entity_transform(rb_entity_id)
+ if let Some(entity) = sim.entities.get(&entity_id)
+ && let Some(cells) = &entity.cells
+ && let Some((pos, (cos, sin))) = entity.transform(sim)
{
- let (half_size_x, half_size_y) =
- (rb_entity.width as f32 / 2.0, rb_entity.height as f32 / 2.0);
+ let (half_size_x, half_size_y) = (cells.size.x as f32 / 2.0, cells.size.y as f32 / 2.0);
// half-extent of the rotated grid's axis-aligned bounding box, plus a cell of margin
let (radius_x, radius_y) = (
half_size_x * (cos.abs() + sin.abs()) + 1.0,
half_size_y * (cos.abs() + sin.abs()) + 1.0,
);
- let world_xl = (rb_x - radius_x).floor() as i32;
- let world_xu = (rb_x + radius_x).ceil() as i32;
- let world_yl = (rb_y - radius_y).floor() as i32;
- let world_yu = (rb_y + radius_y).ceil() as i32;
+ let world_xl = (pos.x - radius_x).floor() as i32;
+ let world_xu = (pos.x + radius_x).ceil() as i32;
+ let world_yl = (pos.y - radius_y).floor() as i32;
+ let world_yu = (pos.y + radius_y).ceil() as i32;
for world_x in world_xl..=world_xu {
for world_y in world_yl..=world_yu {
@@ -32,18 +34,18 @@ pub fn write_rb_entity_to_world(
&& cur_world_cell.material == MaterialId::Void
{
// same as shader
- let d = (world_x as f32 + 0.5 - rb_x, world_y as f32 + 0.5 - rb_y);
+ let d = (world_x as f32 + 0.5 - pos.x, world_y as f32 + 0.5 - pos.y);
let q = (d.0.floor() + 0.5, d.1.floor() + 0.5);
let (lx, ly) = (
(q.0 * cos + q.1 * sin + half_size_x).floor() as i32,
(-q.0 * sin + q.1 * cos + half_size_y).floor() as i32,
);
- if lx < 0 || ly < 0 || lx >= rb_entity.width || ly >= rb_entity.height {
+ if lx < 0 || ly < 0 || lx >= cells.size.x || ly >= cells.size.y {
continue;
}
- let mut cell = rb_entity.get_cell_at_local_position(lx as u8, ly as u8);
+ let mut cell = cells.get_cell_at_local_position(IVec2::new(lx, ly));
if cell.material == MaterialId::Void {
continue;
}