//! The `entity` module contains structures of all entities including players and enimies. use crate::{Direction, FPos, Pos, const_pos}; /// `PLAYER_FULL_HEALTH` is the starting health of the player entity pub const PLAYER_FULL_HEALTH: u32 = 10; /// `PLAYER_INVENTORY_SIZE` is the maximum size of the inventory pub const PLAYER_INVENTORY_SIZE: usize = 5; /// The `Item` type represents any item an entity may be using #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Item { Potion { heal: u32 }, Weapon { atack: u32 }, Armor { defense: u32 }, } /// The `EntityKind` represents what kind of entity this is. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum EntityKind { /// The main player Player, Enemy, /// An item (not in an inventory) on the floor of the dungeon Item(Item), } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum EntityMoveSpeed { Slow, Medium, Fast, } impl EntityMoveSpeed { /// Returns value in tiles/second pub fn value(&self) -> f32 { match &self { Self::Slow => 1., Self::Medium => 2., Self::Fast => 3., } } } /// The `Entity` kind represents the main player, or any other /// ai autonomous character that can move freely across the /// dungeon. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Entity { /// The fixed grid position of the entity pub pos: Pos, /// The floating (real) current position of the entity pub fpos: FPos, /// Which direction this entity is facing pub dir: Direction, /// Which kind this entity is (along with entity kind specific data) pub kind: EntityKind, /// Move speed of this entity pub move_speed: EntityMoveSpeed, /// The amount of health this entity has (None if this Entity does not use health) pub health: Option, } impl Entity { /// Creates a new `Entity` at a given `Pos`, `Direction`, and `EntityKind`. /// /// # Examples /// /// ``` /// use dungeon::{Pos, Direction, Entity, EntityKind, EntityMoveSpeed}; /// /// let pos = Pos::new(0, 0).unwrap(); /// let dir = Direction::North; /// let kind = EntityKind::Player; /// let health = Some(10); /// let move_speed = EntityMoveSpeed::Medium; /// let entity = Entity::new(pos, dir, kind, move_speed, health); /// ``` #[must_use] pub const fn new( pos: Pos, dir: Direction, kind: EntityKind, move_speed: EntityMoveSpeed, health: Option, ) -> Self { let fpos = FPos::from_pos(pos); Self { pos, fpos, dir, kind, move_speed, health, } } /// Creates the Player version of the `Entity` /// /// # Examples /// /// ``` /// use dungeon::{Pos, Entity}; /// /// let pos = Pos::new(0, 0).unwrap(); /// let player = Entity::player(pos); /// ``` #[must_use] pub const fn player(pos: Pos) -> Self { let dir = Direction::East; let kind = EntityKind::Player; let move_speed = EntityMoveSpeed::Medium; let health = Some(PLAYER_FULL_HEALTH); Self::new(pos, dir, kind, move_speed, health) } /// Creates an Enemy version of the `Entity` /// /// # Examples /// /// ``` /// use dungeon::{Pos, Entity, EntityMoveSpeed}; /// /// let pos = Pos::new(0, 0).unwrap(); /// let move_speed = EntityMoveSpeed::Medium; /// let health = 8; /// let enemy = Entity::enemy(pos, move_speed, health); /// ``` #[must_use] pub const fn enemy(pos: Pos, move_speed: EntityMoveSpeed, health: u32) -> Self { let dir = Direction::East; let kind = EntityKind::Enemy; Self::new(pos, dir, kind, move_speed, Some(health)) } pub fn move_by_dir(&mut self, dir: Direction, delta_time: f32) { if let Some(fp) = self.fpos.step_by(dir, delta_time * self.move_speed.value()) { // TODO: collision self.fpos = fp; } } } /// The `Player` type represents the main player entity #[derive(Clone, Debug, PartialEq)] pub struct Player { pub entity: Entity, pub inventory: Vec, } impl Player { /// Instantiates the game player at a given `Pos` /// /// # Examples /// /// ``` /// use dungeon::{Pos, Player}; /// /// let pos = Pos::new(1, 2).unwrap(); /// let player = Player::new(pos); /// ``` pub fn new(pos: Pos) -> Self { let entity = Entity::player(pos); let inventory = vec![]; Self { entity, inventory } } } impl Default for Player { fn default() -> Self { let pos = const_pos!(1, 1); Self::new(pos) } }