summaryrefslogtreecommitdiff
path: root/dungeon/src/enemy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'dungeon/src/enemy.rs')
-rw-r--r--dungeon/src/enemy.rs194
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;
- }
- }
- };
- }
-}