diff --git a/src/components.rs b/src/components.rs index 38bb5f6..c3d430b 100644 --- a/src/components.rs +++ b/src/components.rs @@ -21,6 +21,12 @@ pub struct Renderable { pub path: String, } +impl Renderable { + pub fn new(path: &str) -> Self { + Renderable { path: path.to_string() } + } +} + #[derive(Component)] #[storage(VecStorage)] pub struct Wall {} diff --git a/src/entities.rs b/src/entities.rs index be09727..f894184 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -5,9 +5,7 @@ pub fn create_wall(world: &mut World, position: Position) { world .create_entity() .with(Position { z: 10, ..position }) - .with(Renderable { - path: "/images/wall.png".to_string(), - }) + .with(Renderable::new("/images/wall.png")) .with(Wall {}) .with(Immovable) .build(); @@ -17,9 +15,7 @@ pub fn create_floor(world: &mut World, position: Position) { world .create_entity() .with(Position { z: 5, ..position }) - .with(Renderable { - path: "/images/floor.png".to_string(), - }) + .with(Renderable::new("/images/floor.png")) .build(); } @@ -27,9 +23,7 @@ pub fn create_box(world: &mut World, position: Position) { world .create_entity() .with(Position { z: 10, ..position }) - .with(Renderable { - path: "/images/box.png".to_string(), - }) + .with(Renderable::new("/images/box.png")) .with(Box {}) .with(Movable) .build(); @@ -39,9 +33,7 @@ pub fn create_box_spot(world: &mut World, position: Position) { world .create_entity() .with(Position { z: 9, ..position }) - .with(Renderable { - path: "/images/box_spot.png".to_string(), - }) + .with(Renderable::new("/images/box_spot.png")) .with(BoxSpot {}) .build(); } @@ -50,9 +42,7 @@ pub fn create_player(world: &mut World, position: Position) { world .create_entity() .with(Position { z: 10, ..position }) - .with(Renderable { - path: "/images/player.png".to_string(), - }) + .with(Renderable::new("/images/player.png")) .with(Player {}) .with(Movable) .build(); diff --git a/src/resources.rs b/src/resources.rs index 10e8023..7ed7618 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -1,12 +1,42 @@ use ggez::event::KeyCode; use specs::World; +use std::fmt; +use std::fmt::Display; -// Resources #[derive(Default)] pub struct InputQueue { pub keys_pressed: Vec, } -pub fn register_resources(world: &mut World) { - world.insert(InputQueue::default()) +#[derive(Default)] +pub struct Gameplay { + pub state: GameplayState, + pub moves_count: usize, +} + +pub enum GameplayState { + Playing, + Won, +} + +impl Default for GameplayState { + fn default() -> Self { + Self::Playing + } +} + +impl Display for GameplayState { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(match self { + GameplayState::Playing => "Playing", + GameplayState::Won => "Won", + })?; + + Ok(()) + } +} + +pub fn register_resources(world: &mut World) { + world.insert(InputQueue::default()); + world.insert(Gameplay::default()); } diff --git a/src/systems/input_system.rs b/src/systems/input_system.rs index e4f352a..03eb396 100644 --- a/src/systems/input_system.rs +++ b/src/systems/input_system.rs @@ -5,9 +5,9 @@ use specs::{Entities, ReadStorage, System, Write, WriteStorage}; use std::collections::HashMap; -use crate::components::{Immovable, Movable, Player, Position}; -use crate::constants::{MAP_HEIGHT, MAP_WIDTH}; -use crate::resources::InputQueue; +use crate::components::*; +use crate::constants::*; +use crate::resources::{Gameplay, InputQueue}; pub struct InputSystem {} @@ -15,6 +15,7 @@ impl<'a> System<'a> for InputSystem { // Data type SystemData = ( Write<'a, InputQueue>, + Write<'a, Gameplay>, Entities<'a>, WriteStorage<'a, Position>, ReadStorage<'a, Player>, @@ -23,7 +24,8 @@ impl<'a> System<'a> for InputSystem { ); fn run(&mut self, data: Self::SystemData) { - let (mut input_queue, entities, mut positions, players, movables, immovables) = data; + let (mut input_queue, mut gameplay, entities, mut positions, players, movables, immovables) = + data; let mut to_move = Vec::new(); @@ -82,6 +84,11 @@ impl<'a> System<'a> for InputSystem { } } + // We've just moved, so let's increase the number of moves + if to_move.len() > 0 { + gameplay.moves_count += 1; + } + // Now actually move what needs to be moved for (key, id) in to_move { let position = positions.get_mut(entities.entity(id)); diff --git a/src/systems/mod.rs b/src/systems/mod.rs index e574ced..622c5e3 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -1,5 +1,7 @@ +mod gameplay_state_sytem; mod input_system; mod rendering_system; +pub use self::gameplay_state_sytem::GameplayStateSystem; pub use self::input_system::InputSystem; pub use self::rendering_system::RenderingSystem; diff --git a/src/systems/rendering_system.rs b/src/systems/rendering_system.rs index 60e6236..6ca8fc5 100644 --- a/src/systems/rendering_system.rs +++ b/src/systems/rendering_system.rs @@ -1,21 +1,44 @@ -use ggez::graphics::DrawParam; use ggez::graphics::Image; +use ggez::graphics::{Color, DrawParam}; use ggez::nalgebra as na; use ggez::{graphics, Context}; -use specs::{Join, ReadStorage, System}; +use specs::{Join, Read, ReadStorage, System}; use crate::components::{Position, Renderable}; use crate::constants::TILE_WIDTH; +use crate::resources::Gameplay; pub struct RenderingSystem<'a> { pub context: &'a mut Context, } +impl RenderingSystem<'_> { + pub fn draw_text(&mut self, text_string: &str, x: f32, y: f32) { + let text = graphics::Text::new(text_string); + let destination = na::Point2::new(x, y); + let color = Some(Color::new(0.0, 0.0, 0.0, 1.0)); + let dimensions = na::Point2::new(0.0, 20.0); + + graphics::queue_text(self.context, &text, dimensions, color); + graphics::draw_queued_text( + self.context, + graphics::DrawParam::new().dest(destination), + None, + graphics::FilterMode::Linear, + ) + .expect("expected drawing queued text"); + } +} + impl<'a> System<'a> for RenderingSystem<'a> { - type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Renderable>); + type SystemData = ( + Read<'a, Gameplay>, + ReadStorage<'a, Position>, + ReadStorage<'a, Renderable>, + ); fn run(&mut self, data: Self::SystemData) { - let (positions, renderables) = data; + let (gameplay, positions, renderables) = data; // Clear the screen/set the background graphics::clear(self.context, graphics::Color::new(0.95, 0.95, 0.95, 1.0)); @@ -38,6 +61,10 @@ impl<'a> System<'a> for RenderingSystem<'a> { graphics::draw(self.context, &image, draw_params).expect("expected render"); } + // Render any text + self.draw_text(&gameplay.state.to_string(), 525.0, 80.0); + self.draw_text(&gameplay.moves_count.to_string(), 525.0, 100.0); + // Finally, present the context, this will actually display everything // on the screen. graphics::present(self.context).expect("expected to present");