diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/content/entities/entity_bullet_emitter.rs | 79 | ||||
| -rw-r--r-- | src/content/entities/mod.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 38 | ||||
| -rw-r--r-- | src/sim/entity/mod.rs | 18 | ||||
| -rw-r--r-- | src/sim/sim_manager/mod.rs | 15 | ||||
| -rw-r--r-- | src/sim/sim_manager/utils.rs | 75 |
6 files changed, 157 insertions, 69 deletions
diff --git a/src/content/entities/entity_bullet_emitter.rs b/src/content/entities/entity_bullet_emitter.rs new file mode 100644 index 0000000..c58bd6b --- /dev/null +++ b/src/content/entities/entity_bullet_emitter.rs @@ -0,0 +1,79 @@ +use glam::{IVec2, Vec2}; +use rapier2d::dynamics::RigidBodyBuilder; + +use crate::{ + content::materials::MaterialId, + input::Input, + sim::{ + cell::Cell, + entity::{EntityBehaviour, EntityCells, EntityDef, EntityUpdateCtx}, + lib::force::apply_bullet, + sim_manager::SimCtx, + }, +}; + +struct BulletEmitterEntityBehaviour { + shot_timer: f32, + life: f32, + target: Option<Vec2>, +} + +impl EntityBehaviour for BulletEmitterEntityBehaviour { + fn update(&mut self, update_ctx: &mut EntityUpdateCtx, ctx: &mut SimCtx, delta_time: f32) { + if self.target.is_none() && ctx.input_manager.pressed(Input::Action4) { + self.target = Some(ctx.input_manager.world_mouse_pos); + } + + if let Some(target) = self.target { + self.shot_timer -= delta_time; + if self.shot_timer <= 0.0 { + apply_bullet( + ctx, + update_ctx.entity_data.transform(ctx).unwrap().0, + target, + 400, + ); + self.shot_timer = 0.1; + } + + self.life -= delta_time; + if self.life <= 0.0 { + update_ctx.deferred_destroy(update_ctx.entity_data.id); + } + } + } +} + +pub fn entity_bullet_emitter_def(position: Vec2, life: f32) -> EntityDef { + let w = 6; + let h = 3; + let mut raw_cells = vec![Cell::void(); (w * h) as usize]; + + for x in 0..w { + for y in 0..h { + let cell_idx = x + y * w; + raw_cells[cell_idx as usize] = Cell::from_material(MaterialId::Steel); + raw_cells[cell_idx as usize].set_entity_integrated(true); + } + } + + let entity_cells = EntityCells { + cells: raw_cells, + size: IVec2::new(w, h), + }; + + let rb = RigidBodyBuilder::dynamic() + .translation(position / crate::config::CELLS_TO_METRES) + .gravity_scale(0.0) + .build(); + + EntityDef::from_cells_and_rb( + entity_cells, + rb, + Some(Box::new(BulletEmitterEntityBehaviour { + shot_timer: 0.0, + life, + target: None, + })), + ) +} diff --git a/src/content/entities/mod.rs b/src/content/entities/mod.rs index e78eb89..652ee6d 100644 --- a/src/content/entities/mod.rs +++ b/src/content/entities/mod.rs @@ -1,2 +1,3 @@ +pub mod entity_bullet_emitter; pub mod entity_cube; pub mod entity_grenade; diff --git a/src/main.rs b/src/main.rs index 704a276..967484f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,6 @@ mod renderer; mod sim; use futures::executor; -use glam::Vec2; use rand::random_range; use std::{collections::VecDeque, sync::Arc, time::Instant}; use winit::{ @@ -20,7 +19,10 @@ use crate::{ camera::Camera, config::WINDOW_TITLE, content::{ - entities::{entity_cube::entity_cube_def, entity_grenade::entity_grenade_def}, + entities::{ + entity_bullet_emitter::entity_bullet_emitter_def, entity_cube::entity_cube_def, + entity_grenade::entity_grenade_def, + }, materials::MaterialId, }, input::{ @@ -28,12 +30,7 @@ use crate::{ InputManager, }, renderer::RendererState, - sim::{ - cell::Cell, - lib::force::apply_bullet, - rb_manager::DebugRenderMode, - sim_manager::{SimCtx, SimManager}, - }, + sim::{cell::Cell, rb_manager::DebugRenderMode, sim_manager::SimManager}, }; pub type Error = Box<dyn std::error::Error>; @@ -59,9 +56,6 @@ struct App { window: Option<Arc<Window>>, renderer_state: Option<RendererState>, - // tests - bullet_origin: Option<Vec2>, - // game input_manager: InputManager, camera: Option<Camera>, @@ -98,22 +92,10 @@ impl App { } if self.input_manager.pressed(Input::Action3) { - if let Some(origin) = self.bullet_origin { - apply_bullet( - &mut SimCtx { - input_manager: &self.input_manager, - cell_manager: &mut sim.cell_manager, - particle_manager: &mut sim.particle_manager, - rb_manager: &mut sim.rb_manager, - }, - origin, - self.input_manager.world_mouse_pos, - 800, - ); - self.bullet_origin = None; - } else { - self.bullet_origin = Some(self.input_manager.world_mouse_pos); - } + sim.create_entity(entity_bullet_emitter_def( + self.input_manager.world_mouse_pos, + 3.0, + )); } // --TEST DRAWING-- @@ -166,8 +148,6 @@ impl Default for App { window: None, renderer_state: None, - bullet_origin: None, - input_manager: InputManager::new(), camera: None, 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); + } +} |
