summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Symons <47405201+rsymons22@users.noreply.github.com>2025-11-04 22:24:23 -0500
committerRyan Symons <47405201+rsymons22@users.noreply.github.com>2025-11-04 22:24:23 -0500
commit574f3c694dcce927ac87dfb79276775f0904bdc8 (patch)
treebebe583ec5194c4a5a3187c04b79d0c84215e1b8
parentAdd SDL feature flag (fixes wayland issues) (diff)
downloadDungeonCrawl-574f3c694dcce927ac87dfb79276775f0904bdc8.tar.gz
DungeonCrawl-574f3c694dcce927ac87dfb79276775f0904bdc8.tar.bz2
DungeonCrawl-574f3c694dcce927ac87dfb79276775f0904bdc8.zip
Added enemy code structure and test movement
-rw-r--r--dungeon/src/enemy.rs106
-rw-r--r--dungeon/src/entity.rs7
-rw-r--r--dungeon/src/lib.rs16
-rw-r--r--dungeon/src/map.rs2
-rw-r--r--game/src/main.rs8
-rw-r--r--graphics/src/render.rs3
6 files changed, 139 insertions, 3 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.;
+ }
+ }
+}
diff --git a/dungeon/src/entity.rs b/dungeon/src/entity.rs
index 02184a9..5f0425f 100644
--- a/dungeon/src/entity.rs
+++ b/dungeon/src/entity.rs
@@ -21,6 +21,7 @@ pub enum Item {
pub enum EntityKind {
/// The main player
Player,
+ Enemy,
/// An item (not in an inventory) on the floor of the dungeon
Item(Item),
}
@@ -89,6 +90,12 @@ impl Entity {
let health = Some(PLAYER_FULL_HEALTH);
Self::new(pos, dir, kind, health)
}
+
+ pub const fn enemy(pos: Pos, health: u32) -> Self {
+ let dir = Direction::East;
+ let kind = EntityKind::Enemy;
+ Self::new(pos, dir, kind, Some(health))
+ }
}
/// The `Player` type represents the main player entity
diff --git a/dungeon/src/lib.rs b/dungeon/src/lib.rs
index 39d7c60..8119119 100644
--- a/dungeon/src/lib.rs
+++ b/dungeon/src/lib.rs
@@ -2,6 +2,7 @@
//! interacting with a `Dungeon` and its components.
mod bsp;
+mod enemy;
mod entity;
mod map;
mod pos;
@@ -11,12 +12,15 @@ pub use entity::*;
pub use map::*;
pub use pos::*;
+use crate::enemy::{Enemy, EnemyType};
+
/// The `Dungeon` type represents the game state of the
/// dungeon crawler.
#[derive(Clone, Debug, PartialEq)]
pub struct Dungeon {
pub floor: Floor,
pub player: Player,
+ pub enemies: Vec<Enemy>,
}
impl Dungeon {
/// Creates a new `Dungeon`.
@@ -65,6 +69,16 @@ impl From<Floor> for Dungeon {
// TODO: initalize rest of game state
- Self { floor, player }
+ // TODO: How will we randomize enemy type/number per floor?
+ let enemies = vec![Enemy::new(
+ EnemyType::Zombie,
+ Pos::new(player.entity.pos.x() + 4, player.entity.pos.y()).unwrap(),
+ )];
+
+ Self {
+ floor,
+ player,
+ enemies,
+ }
}
}
diff --git a/dungeon/src/map.rs b/dungeon/src/map.rs
index f4a8729..212dd00 100644
--- a/dungeon/src/map.rs
+++ b/dungeon/src/map.rs
@@ -52,7 +52,7 @@ impl Default for Tile {
/// The `Floor` type represents the current playing
/// grid of the dungeon. It contains the tiles of the
/// grid, and the starting position of the player.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq)]
pub struct Floor {
/// The dungeon grid
tiles: Box<[Tile; TILE_COUNT]>,
diff --git a/game/src/main.rs b/game/src/main.rs
index 22203c3..7e6c8bb 100644
--- a/game/src/main.rs
+++ b/game/src/main.rs
@@ -5,11 +5,17 @@ fn main() -> Result<()> {
// Load the window
let mut window = Window::new(720, 480, "game")?;
// Initial game state
- let dungeon = Dungeon::new();
+ let mut dungeon = Dungeon::new();
// Main game loop
while window.is_open() {
// TODO update game state
+
+ // Enemy Tick
+ for enemy in dungeon.enemies.iter_mut() {
+ enemy.update(dungeon.player.entity.pos, window.delta_time());
+ }
+
// Draw a single frame
window.renderer().draw_frame(&dungeon);
}
diff --git a/graphics/src/render.rs b/graphics/src/render.rs
index 499301c..4166a7a 100644
--- a/graphics/src/render.rs
+++ b/graphics/src/render.rs
@@ -411,6 +411,9 @@ where
/// Draws the entities on the map
fn draw_entities(&mut self, dungeon: &Dungeon) {
self.draw_entity(&dungeon.player.entity);
+ for enemy in &dungeon.enemies {
+ self.draw_entity(&enemy.entity);
+ }
}
/// Draws an entity