use glam::{IVec2, Vec2}; use rapier2d::{ dynamics::{RigidBody, RigidBodyBuilder, RigidBodyHandle}, geometry::{Collider, ColliderHandle}, }; use crate::{ config::CELLS_TO_METRES, sim::{ cell::{cell::Cell, materials::MaterialId}, lib::marching_squares::Marchable, rb_manager::RbManager, sim_manager::SimManager, }, }; pub mod entities; pub struct EntityCells { pub size: IVec2, pub cells: Vec, } impl EntityCells { #[inline] pub fn get_cell_at_local_position(&self, pos: IVec2) -> Cell { self.cells[pos.x as usize + pos.y as usize * self.size.x as usize] } #[inline] pub fn set_cell_at_local_position(&mut self, pos: IVec2, cell: Cell) { self.cells[pos.x as usize + pos.y as usize * self.size.x as usize] = cell; } } impl Marchable for EntityCells { fn occupied(&self, pos: IVec2) -> bool { if pos.x < 0 || pos.x >= self.size.x || pos.y < 0 || pos.y >= self.size.y { false } else { self.get_cell_at_local_position(pos).material != MaterialId::Void } } fn size(&self) -> IVec2 { self.size } } pub trait EntityBehaviour { fn update(&mut self, sim: &mut SimManager, delta_time: f32) -> (); fn physics_update(&mut self, sim: &mut SimManager, delta_time: f32) -> (); } pub struct EntityDef { pub position: Vec2, pub rb: Option, pub collider: Option, pub cells: Option, pub behaviour: Option>, } impl EntityDef { pub fn from_cells( position: Vec2, cells: EntityCells, behaviour: Option>, ) -> Self { let rb = RigidBodyBuilder::dynamic() .translation(position / CELLS_TO_METRES) .build(); let collider = RbManager::convex_hull_collider_from_marchable(&cells, None).build(); EntityDef { position, rb: Some(rb), collider: Some(collider), cells: Some(cells), behaviour, } } } pub struct Entity { pub id: u32, pub rb_h: Option, pub collider_h: Option, pub cells: Option, behaviour: Option>, } impl Entity { pub fn transform(&self, sim: &SimManager) -> Option<(Vec2, (f32, f32))> { self.rb_h .map(|rb_h| { sim.rb_manager .physics_manager .rigid_body_set .get(rb_h) .map(|rb| { ( rb.translation() * CELLS_TO_METRES, (rb.rotation().cos(), rb.rotation().sin()), ) }) }) .flatten() } // TODO use drop? pub fn destroy(&mut self, sim: &mut SimManager) -> () {} pub fn update(&mut self, sim: &mut SimManager, delta_time: f32) -> () { if let Some(behaviour) = &mut self.behaviour { behaviour.update(sim, delta_time); } } pub fn physics_update(&mut self, sim: &mut SimManager, delta_time: f32) -> () { if let Some(behaviour) = &mut self.behaviour { behaviour.physics_update(sim, delta_time); } } pub fn new( id: u32, rb_h: Option, collider_h: Option, cells: Option, behaviour: Option>, ) -> Self { Entity { id, rb_h, collider_h, cells, behaviour, } } }