diff options
Diffstat (limited to 'src/sim/sim_manager')
| -rw-r--r-- | src/sim/sim_manager/mod.rs | 125 | ||||
| -rw-r--r-- | src/sim/sim_manager/utils.rs | 28 |
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; } |
