diff options
Diffstat (limited to 'dungeon/src/enemy.rs')
| -rw-r--r-- | dungeon/src/enemy.rs | 194 |
1 files changed, 0 insertions, 194 deletions
diff --git a/dungeon/src/enemy.rs b/dungeon/src/enemy.rs deleted file mode 100644 index 0d432dd..0000000 --- a/dungeon/src/enemy.rs +++ /dev/null @@ -1,194 +0,0 @@ -use crate::{Direction, Entity, EntityMoveSpeed, Pos, Tile, astar}; - -pub const MIN_ROAM_DIST: u16 = 1; -pub const MAX_ROAM_DIST: u16 = 4; - -pub const ZOMBIE_HEALTH: u32 = 50; -pub const ENEMY_VISION_RADIUS: u16 = 5; - -pub const IDLE_WAIT: f32 = 1.; - -#[derive(Clone, Debug, PartialEq)] -pub enum EnemyMoveState { - Idle(f32), - Roam(Vec<Pos>), - Attack(Vec<Pos>), -} - -impl EnemyMoveState { - pub fn new_idle() -> Self { - Self::Idle(0.) - } - - pub fn new_attack(starting_pos: Pos, player_pos: Pos, tiles: &[Tile]) -> Option<Self> { - if player_pos.manhattan(starting_pos) < ENEMY_VISION_RADIUS { - let data = astar::find_path(tiles, starting_pos, player_pos)?; - let mut path = data.0; - path.reverse(); - return Some(Self::Attack(path)); - } - None - } - - pub fn new_roam(starting_pos: Pos, tiles: &[Tile]) -> Self { - let mut rand_dir = Direction::get_random_dir(); - let mut rand_tiles = rand::random_range(MIN_ROAM_DIST..=MAX_ROAM_DIST); - let mut loop_index = 0; - loop { - if let Some(p) = starting_pos.step_by(rand_dir, rand_tiles) { - if !tiles[p.idx()].is_wall() { - if let Some(data) = astar::find_path(tiles, starting_pos, p) { - let mut path = data.0; - path.reverse(); - return Self::Roam(path); - } - } - } - - rand_dir = Direction::get_random_dir(); - rand_tiles = rand::random_range(MIN_ROAM_DIST..=MAX_ROAM_DIST); - - // Safety check - loop_index += 1; - assert!( - loop_index < 100, - "EnemyMoveState::new_roam couldn't find a valid spot around {starting_pos:?} in between {MIN_ROAM_DIST}-{MAX_ROAM_DIST} tiles", - ); - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum EnemyAttackType { - Melee, - Ranged, -} - -#[derive(Clone, Debug, PartialEq, Eq, Copy)] -pub enum EnemyType { - Zombie, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct Enemy { - pub entity: Entity, - pub enemy_type: EnemyType, - pub attack_type: EnemyAttackType, - move_state: EnemyMoveState, -} - -impl Enemy { - pub fn new(enemy_type: EnemyType, pos: Pos) -> Self { - match enemy_type { - EnemyType::Zombie => Self::zombie(pos), - } - } - - fn _new( - pos: Pos, - health: u32, - move_speed: EntityMoveSpeed, - enemy_type: EnemyType, - attack_type: EnemyAttackType, - ) -> Self { - let entity = Entity::enemy(pos, move_speed, health); - Self { - entity, - enemy_type, - attack_type, - move_state: EnemyMoveState::new_idle(), - } - } - - fn zombie(pos: Pos) -> Self { - Self::_new( - pos, - ZOMBIE_HEALTH, - EntityMoveSpeed::Slow, - EnemyType::Zombie, - EnemyAttackType::Melee, - ) - } - - pub fn handle_movement(&mut self, player_pos: Pos, delta_time: f32, tiles: &[Tile]) { - // Check if player is in range - if !matches!(self.move_state, EnemyMoveState::Attack { .. }) - && let Some(move_state) = - EnemyMoveState::new_attack(self.entity.pos, player_pos, tiles) - { - self.move_state = move_state; - return; - } - - match &mut self.move_state { - EnemyMoveState::Idle(idle_accum) => { - *idle_accum += delta_time; - if *idle_accum < IDLE_WAIT { - return; - } - - self.move_state = EnemyMoveState::new_roam(self.entity.pos, tiles); - } - EnemyMoveState::Roam(moves) => { - let p = if let Some(p) = moves.last() { - p - } else { - self.move_state = EnemyMoveState::new_idle(); - return; - }; - - Self::movement_helper(&mut self.entity, *p, moves, delta_time); - } - EnemyMoveState::Attack(moves) => { - // Stop at one move left so the enemy is flush with the player tile - if moves.len() == 1 { - return; - } - - Self::movement_helper( - &mut self.entity, - *moves.last().unwrap_or(&Pos::default()), - moves, - delta_time, - ); - } - } - } - - fn movement_helper( - entity: &mut Entity, - next_move: Pos, - moves: &mut Vec<Pos>, - delta_time: f32, - ) { - if entity.pos.y() > next_move.y() { - entity.move_by_dir(Direction::North, delta_time); - if entity.fpos.y() <= next_move.y() as f32 { - if let Some(p) = moves.pop() { - entity.pos = p; - } - } - } else if entity.pos.y() < next_move.y() { - entity.move_by_dir(Direction::South, delta_time); - if entity.fpos.y() >= next_move.y() as f32 { - if let Some(p) = moves.pop() { - entity.pos = p; - } - } - } else if entity.pos.x() < next_move.x() { - entity.move_by_dir(Direction::East, delta_time); - if entity.fpos.x() >= next_move.x() as f32 { - if let Some(p) = moves.pop() { - entity.pos = p; - } - } - } else { - entity.move_by_dir(Direction::West, delta_time); - if entity.fpos.x() <= next_move.x() as f32 { - if let Some(p) = moves.pop() { - entity.pos = p; - } - } - }; - } -} |