summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dungeon/src/entity.rs5
-rw-r--r--dungeon/src/lib.rs50
-rw-r--r--dungeon/src/player_input.rs9
-rw-r--r--game/src/lib.rs36
-rw-r--r--graphics/src/lib.rs34
-rw-r--r--graphics/src/render.rs47
6 files changed, 145 insertions, 36 deletions
diff --git a/dungeon/src/entity.rs b/dungeon/src/entity.rs
index a0750dd..9af27bd 100644
--- a/dungeon/src/entity.rs
+++ b/dungeon/src/entity.rs
@@ -337,6 +337,7 @@ pub struct Player {
pub weapon: Weapon,
// How long until we reset potion effects?
pub potion_timer: Option<Instant>,
+ pub active_inv_slot: usize,
}
impl Player {
/// Instantiates the game player at a given `Pos`
@@ -354,11 +355,13 @@ impl Player {
let inventory = vec![];
let weapon = Weapon::RustyKnife;
let potion_timer = None;
+ let active_inv_slot = 0;
Self {
entity,
inventory,
weapon,
potion_timer,
+ active_inv_slot,
}
}
}
@@ -517,7 +520,7 @@ impl Dungeon {
};
updater.update_entity(&mut self.player.entity);
- for enemy in &mut self.enemies {
+ for enemy in &mut self.entities {
updater.update_entity(enemy);
}
}
diff --git a/dungeon/src/lib.rs b/dungeon/src/lib.rs
index 13ab397..0076f26 100644
--- a/dungeon/src/lib.rs
+++ b/dungeon/src/lib.rs
@@ -15,11 +15,11 @@ use std::time::Instant;
use rand::{Rng, SeedableRng, TryRngCore, rngs::OsRng};
use crate::{
- entity::{Entity, Player},
+ entity::{Entity, EntityKind, PLAYER_INVENTORY_SIZE_USIZE, Player},
map::{Floor, Tile},
msg::Message,
player_input::PlayerInput,
- pos::FPos,
+ pos::{Direction, FPos},
rng::DungeonRng,
};
@@ -43,7 +43,7 @@ pub enum UpdateResult {
pub struct Dungeon {
pub floor: Floor,
pub player: Player,
- pub enemies: Vec<Entity>,
+ pub entities: Vec<Entity>,
pub msg: Message,
seed: u64,
level_rng: DungeonRng,
@@ -66,12 +66,12 @@ impl Dungeon {
let mut level_rng = DungeonRng::seed_from_u64(game_rng.random());
let floor = bsp::generate(&mut level_rng);
let player = Player::new(floor.player_start());
- let enemies = vec![];
+ let entities = vec![];
let msg = Message::empty();
let mut dungeon = Self {
floor,
player,
- enemies,
+ entities,
msg,
seed,
level_rng,
@@ -121,12 +121,13 @@ impl Dungeon {
UpdateResult::MessageUpdated(changed)
} else {
self.update_entities(player_input, delta_time);
- self.update_player();
+ self.update_player(player_input);
if self.floor.get(self.player.entity.pos) == Tile::Stairs {
// we are moving to a new floor
self.floor = bsp::generate(&mut self.level_rng);
self.player.entity.teleport(self.floor.player_start());
+ self.entities.clear();
self.spawn_enimies();
return UpdateResult::NextFloor;
}
@@ -135,19 +136,50 @@ impl Dungeon {
}
}
- fn update_player(&mut self) {
+ fn update_player(&mut self, player_input: PlayerInput) {
+ // update potion timer
if let Some(timer) = self.player.potion_timer
&& Instant::now() > timer
{
self.player.potion_timer = None;
self.player.entity.speed = self.player.entity.kind.initial_speed();
}
+
+ // use item
+ if player_input.use_item
+ && self.player.active_inv_slot < self.player.inventory.len()
+ {
+ let item = self.player.inventory.remove(self.player.active_inv_slot);
+ item.consume(self);
+ }
+
+ // TODO: attack
+
+ // check for drop input
+ if player_input.drop && self.player.active_inv_slot < self.player.inventory.len() {
+ let item = self.player.inventory.remove(self.player.active_inv_slot);
+ self.entities.push(Entity::new(
+ self.player.entity.pos,
+ Direction::East,
+ EntityKind::Item(item),
+ ));
+ self.player.active_inv_slot = self
+ .player
+ .active_inv_slot
+ .max(self.player.inventory.len().saturating_sub(1));
+ }
+
+ // check for inv slot request
+ if let Some(slot) = player_input.inv_slot
+ && slot < PLAYER_INVENTORY_SIZE_USIZE
+ {
+ self.player.active_inv_slot = slot;
+ }
}
fn spawn_enimies(&mut self) {
// TODO: better entity spawning
let zombie = Entity::zombie(self.floor.random_walkable_pos(&mut self.level_rng));
- self.enemies.clear();
- self.enemies.push(zombie);
+ self.entities.push(zombie);
}
}
diff --git a/dungeon/src/player_input.rs b/dungeon/src/player_input.rs
index ddaad9f..7fe85c3 100644
--- a/dungeon/src/player_input.rs
+++ b/dungeon/src/player_input.rs
@@ -15,5 +15,12 @@ pub struct PlayerInput {
/// If the player is currently attempting to interact
/// with some object, entity, etc.
pub interact: bool,
- // other player actions are to be added later
+ /// If the player wants to use an item
+ pub use_item: bool,
+ /// If the player is currently attempting to attack
+ pub attack: bool,
+ /// If the player is attempting to drop an item
+ pub drop: bool,
+ /// If the player is attempting to switch the active inv slot
+ pub inv_slot: Option<usize>,
}
diff --git a/game/src/lib.rs b/game/src/lib.rs
index 77942b4..f123326 100644
--- a/game/src/lib.rs
+++ b/game/src/lib.rs
@@ -1,4 +1,7 @@
-use dungeon::{Dungeon, UpdateResult, player_input::PlayerInput, pos::Direction};
+use dungeon::{
+ Dungeon, UpdateResult, entity::PLAYER_INVENTORY_SIZE, player_input::PlayerInput,
+ pos::Direction,
+};
use graphics::{Key, Window};
pub struct Game {
@@ -57,6 +60,26 @@ impl Game {
None
}
+ fn get_player_input(&mut self) -> PlayerInput {
+ let direction = self.player_dir();
+ let interact = self.window.is_key_pressed(Key::Return);
+ let use_item = self.window.is_key_pressed(Key::E);
+ let attack = self.window.is_key_pressed(Key::F);
+ let drop = self.window.is_key_pressed(Key::Q);
+ let inv_slot = (0..PLAYER_INVENTORY_SIZE)
+ .filter_map(|u16| u8::try_from(u16).ok())
+ .find(|u8| self.window.is_key_pressed(Key::Number(*u8 + 1)))
+ .map(|u8| u8 as usize);
+ PlayerInput {
+ direction,
+ interact,
+ use_item,
+ attack,
+ drop,
+ inv_slot,
+ }
+ }
+
pub fn run(&mut self) {
// Main game loop
while self.window.is_open() {
@@ -70,12 +93,8 @@ impl Game {
.set_message("Lorem ipsum dolor sit amet consectetur adipiscing elit");
}
- let inputs = PlayerInput {
- direction: self.player_dir(),
- interact: self.window.is_key_pressed(Key::Return),
- };
-
// Update game state
+ let inputs = self.get_player_input();
let result = self
.dungeon
.update(inputs, self.window.delta_time().as_secs_f32());
@@ -91,11 +110,6 @@ impl Game {
}
}
- // Update on screen message
- if self.dungeon.msg.update(inputs) {
- self.window.audio().speak.play();
- }
-
// Draw a single frame
self.window.draw_frame(&self.dungeon);
}
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index 0fdcedb..02eb97f 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -34,6 +34,11 @@ pub enum Key {
Right,
// Interact
Return,
+ E,
+ F,
+ Q,
+ // Number
+ Number(u8),
// Debug keys
F3,
F4,
@@ -56,6 +61,20 @@ impl From<KeyboardKey> for Key {
K::KEY_RIGHT => Self::Right,
// Interact
K::KEY_ENTER => Self::Return,
+ K::KEY_E => Self::E,
+ K::KEY_F => Self::F,
+ K::KEY_Q => Self::Q,
+ // Number
+ K::KEY_ZERO | K::KEY_KP_0 => Self::Number(0),
+ K::KEY_ONE | K::KEY_KP_1 => Self::Number(1),
+ K::KEY_TWO | K::KEY_KP_2 => Self::Number(2),
+ K::KEY_THREE | K::KEY_KP_3 => Self::Number(3),
+ K::KEY_FOUR | K::KEY_KP_4 => Self::Number(4),
+ K::KEY_FIVE | K::KEY_KP_5 => Self::Number(5),
+ K::KEY_SIX | K::KEY_KP_6 => Self::Number(6),
+ K::KEY_SEVEN | K::KEY_KP_7 => Self::Number(7),
+ K::KEY_EIGHT | K::KEY_KP_8 => Self::Number(8),
+ K::KEY_NINE | K::KEY_KP_9 => Self::Number(9),
// Debug keys
K::KEY_F3 => Self::F3,
K::KEY_F4 => Self::F4,
@@ -79,6 +98,21 @@ impl From<Key> for KeyboardKey {
Key::Right => Self::KEY_RIGHT,
// Interact
Key::Return => Self::KEY_ENTER,
+ Key::E => Self::KEY_E,
+ Key::F => Self::KEY_F,
+ Key::Q => Self::KEY_Q,
+ // Number
+ Key::Number(0) => Self::KEY_ZERO,
+ Key::Number(1) => Self::KEY_ONE,
+ Key::Number(2) => Self::KEY_TWO,
+ Key::Number(3) => Self::KEY_THREE,
+ Key::Number(4) => Self::KEY_FOUR,
+ Key::Number(5) => Self::KEY_FIVE,
+ Key::Number(6) => Self::KEY_SIX,
+ Key::Number(7) => Self::KEY_SEVEN,
+ Key::Number(8) => Self::KEY_EIGHT,
+ Key::Number(9) => Self::KEY_NINE,
+ Key::Number(_) => Self::KEY_NULL,
// Debug keys
Key::F3 => Self::KEY_F3,
Key::F4 => Self::KEY_F4,
diff --git a/graphics/src/render.rs b/graphics/src/render.rs
index 5841a7b..89f9dc3 100644
--- a/graphics/src/render.rs
+++ b/graphics/src/render.rs
@@ -331,6 +331,7 @@ impl Renderer {
ys,
TEXTURE_SIZE,
0.0,
+ Color::WHITE,
);
// draw top wall borders
@@ -344,6 +345,7 @@ impl Renderer {
ys,
TEXTURE_SIZE,
0.0,
+ Color::WHITE,
);
}
if !is_wall(Direction::East) {
@@ -354,6 +356,7 @@ impl Renderer {
ys,
TEXTURE_SIZE,
90.0,
+ Color::WHITE,
);
}
if !is_wall(Direction::South) {
@@ -364,6 +367,7 @@ impl Renderer {
ys,
TEXTURE_SIZE,
180.0,
+ Color::WHITE,
);
}
if !is_wall(Direction::West) {
@@ -374,6 +378,7 @@ impl Renderer {
ys,
TEXTURE_SIZE,
270.0,
+ Color::WHITE,
);
}
}
@@ -404,6 +409,7 @@ impl Renderer {
y * TEXTURE_SIZE,
TEXTURE_SIZE,
0.0,
+ Color::WHITE,
);
if idx == ATLAS_FLOOR {
// add possible extentions
@@ -424,6 +430,7 @@ impl Renderer {
y * TEXTURE_SIZE,
TEXTURE_SIZE,
0.0,
+ Color::WHITE,
);
}
}
@@ -478,10 +485,10 @@ impl Renderer {
where
R: RaylibDraw,
{
- self.draw_entity(r, &dungeon.player.entity);
- for enemy in &dungeon.enemies {
+ for enemy in &dungeon.entities {
self.draw_entity(r, enemy);
}
+ self.draw_entity(r, &dungeon.player.entity);
}
/// Draws an entity
@@ -519,6 +526,7 @@ impl Renderer {
dest_rec.y - WALL_HEIGHT as f32,
size,
0.0,
+ Color::WHITE,
);
if self.debug {
@@ -592,9 +600,15 @@ impl Renderer {
);
};
- // Draw enemy dots
- for enemy in &dungeon.enemies {
- draw_dot(enemy.pos, Color::RED);
+ // Draw entity dots
+ for entity in &dungeon.entities {
+ use EntityKind as K;
+ let color = match entity.kind {
+ K::Player => Color::LIME,
+ K::Zombie(_) => Color::RED,
+ K::Item(_) => Color::TURQUOISE,
+ };
+ draw_dot(entity.pos, color);
}
// Draw player dot
@@ -630,6 +644,11 @@ impl Renderer {
let slot_x = SLOTS_X + SLOT_LEN * idx;
// Draw slot container
+ let tint = if (idx as usize) == player.active_inv_slot {
+ Color::YELLOW
+ } else {
+ Color::WHITE
+ };
r.draw_atlas(
&self.textures.atlas,
ATLAS_INV_CONTAINER,
@@ -637,6 +656,7 @@ impl Renderer {
UI_PADDING,
SLOT_LEN,
0.0,
+ tint,
);
if let Some(item) = player.inventory.get(idx as usize) {
@@ -682,6 +702,7 @@ impl Renderer {
HEART_Y,
ICON_WIDTH,
0.0,
+ Color::WHITE,
);
draw_text!(self, r, TEXT_X, HEART_Y, "x{health:02}");
@@ -694,6 +715,7 @@ impl Renderer {
DAMAGE_Y,
ICON_WIDTH,
0.0,
+ Color::WHITE,
);
draw_text!(self, r, TEXT_X, DAMAGE_Y, "x{damage:02}");
}
@@ -830,6 +852,7 @@ impl Renderer {
y,
FONT_SIZE,
0.0,
+ Color::WHITE,
);
}
}
@@ -886,6 +909,8 @@ where
Self: RaylibDraw,
{
/// Draw an atlas texture index
+ #[inline]
+ #[expect(clippy::too_many_arguments)]
fn draw_atlas(
&mut self,
tex: &Texture2D,
@@ -894,6 +919,7 @@ where
y: impl Into<f32>,
size: impl Into<f32>,
rotation: impl Into<f32>,
+ tint: Color,
) {
let size_into = size.into();
let source_rec = rect! {
@@ -912,14 +938,7 @@ where
dest_rec.width / 2.0,
dest_rec.height / 2.0,
};
- self.draw_texture_pro(
- tex,
- source_rec,
- dest_rec,
- origin,
- rotation.into(),
- Color::WHITE,
- );
+ self.draw_texture_pro(tex, source_rec, dest_rec, origin, rotation.into(), tint);
}
/// Draw dungeon tiles helper function
@@ -961,7 +980,7 @@ where
}
fn draw_pathing_deug(&mut self, dungeon: &Dungeon) {
- for enemy in &dungeon.enemies {
+ for enemy in &dungeon.entities {
let Some(ai) = enemy.get_ai() else {
continue;
};