diff options
Diffstat (limited to 'dungeon/src/enemy.rs')
| -rw-r--r-- | dungeon/src/enemy.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/dungeon/src/enemy.rs b/dungeon/src/enemy.rs new file mode 100644 index 0000000..8c818f5 --- /dev/null +++ b/dungeon/src/enemy.rs @@ -0,0 +1,106 @@ +use crate::{Direction, Entity, FPos, Pos}; + +pub const ZOMBIE_HEALTH: u32 = 50; + +#[derive(Clone, Debug, PartialEq)] +pub enum EnemyMoveSpeed { + Slow, + Medium, + Fast, +} + +/// Every (value) seconds, an enemy with a (speed) can move one tile +pub const SLOW_SPEED_SEC_PER_TILE: f32 = 1.; +pub const MEDIUM_SPEED_SEC_PER_TILE: f32 = 0.5; +pub const FAST_SPEED_SEC_PER_TILE: f32 = 0.25; + +#[derive(Clone, Debug, PartialEq)] +pub enum EnemyAttackType { + Melee, + Ranged, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum EnemyType { + Zombie, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct Enemy { + pub entity: Entity, + pub enemy_type: EnemyType, + pub move_speed: EnemyMoveSpeed, + pub attack_type: EnemyAttackType, + time_acc: f32, +} + +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, + enemy_type: EnemyType, + move_speed: EnemyMoveSpeed, + attack_type: EnemyAttackType, + ) -> Self { + let entity = Entity::enemy(pos, health); + Self { + entity, + enemy_type, + move_speed, + attack_type, + time_acc: 0., + } + } + + fn zombie(pos: Pos) -> Self { + Self::_new( + pos, + ZOMBIE_HEALTH, + EnemyType::Zombie, + EnemyMoveSpeed::Slow, + EnemyAttackType::Melee, + ) + } + + fn is_there(&self) -> bool { + self.time_acc + >= match &self.move_speed { + EnemyMoveSpeed::Slow => SLOW_SPEED_SEC_PER_TILE, + EnemyMoveSpeed::Medium => MEDIUM_SPEED_SEC_PER_TILE, + EnemyMoveSpeed::Fast => FAST_SPEED_SEC_PER_TILE, + } + } + + /// + /// Rough concept for enemy "AI": + /// + /// State: Roam/Patrol + /// Moves around in a small area (2x2, 3x3, 4x4) randomly choosing direction and how much to move. + /// State: Attack + /// Sees player in facing direction (only in box/rectangle in dir) + /// (ex. facing north, if player is anywhere above monster and theres no walls in the way, attack) + /// Do A* pathing to player until enemy dead or player dead or floor change + /// + /// Current implementation below is just a test + /// + pub fn update(&mut self, player_pos: Pos, time_since_last_frame: f32) { + if self.entity.pos == player_pos { + return; + } + + self.time_acc += time_since_last_frame; + if self.is_there() { + let temp_pos = self.entity.pos.step(Direction::West).unwrap(); + self.entity.pos = temp_pos; + self.entity.fpos = FPos::from_pos(temp_pos); + + self.time_acc = 0.; + } + } +} |