Browse Source

Refactor input usage into two separate systems, barebones physics

Getty Ritter 5 years ago
parent
commit
b77725ae4d
8 changed files with 141 additions and 70 deletions
  1. 12 12
      Cargo.lock
  2. 0 1
      src/components.rs
  3. 9 0
      src/game.rs
  4. 26 40
      src/main.rs
  5. 0 1
      src/res.rs
  6. 39 3
      src/sys/drawing.rs
  7. 28 13
      src/sys/input.rs
  8. 27 0
      src/sys/physics.rs

+ 12 - 12
Cargo.lock

@@ -648,18 +648,6 @@ dependencies = [
  "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "jeffersonia"
-version = "0.1.0"
-dependencies = [
- "ggez 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tiled 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "jpeg-decoder"
 version = "0.1.15"
@@ -1662,6 +1650,18 @@ name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "wenaglia"
+version = "0.1.0"
+dependencies = [
+ "ggez 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tiled 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "which"
 version = "1.0.5"

+ 0 - 1
src/components.rs

@@ -54,7 +54,6 @@ impl Sprite {
     }
 }
 
-
 #[derive(Component, Default, Debug)]
 #[storage(NullStorage)]
 pub struct Background;

+ 9 - 0
src/game.rs

@@ -0,0 +1,9 @@
+use sdl2::keyboard as sdl;
+
+/// The shared values that the game state needs, mostly contained in
+/// the specs ECS world
+pub struct MyGame {
+    pub world: specs::World,
+    pub sprites: ggez::graphics::spritebatch::SpriteBatch,
+    pub keys: std::collections::HashSet<sdl::Keycode>,
+}

+ 26 - 40
src/main.rs

@@ -1,58 +1,32 @@
 #[macro_use] extern crate specs_derive;
 
-use ggez::{Context, ContextBuilder, GameResult};
-use ggez::event::{self, EventHandler};
-use ggez::graphics;
-
-use specs::RunNow;
+use ggez::{
+    Context,
+    ContextBuilder,
+    GameResult,
+    event::{self, EventHandler},
+};
 
 use sdl2::keyboard as sdl;
 
 pub mod consts;
 pub mod components;
+pub mod game;
 pub mod res;
 pub mod sys;
 
-struct MyGame {
-    world: specs::World,
-    sprites: graphics::spritebatch::SpriteBatch,
-}
+use game::MyGame;
 
 impl EventHandler for MyGame {
 
     fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
+        sys::input::systems(self);
+        sys::physics::systems(self);
         Ok(())
     }
 
     fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
-        ggez::graphics::set_background_color(ctx, ggez::graphics::BLACK);
-        ggez::graphics::clear(ctx);
-
-        sys::Draw {
-            ctx,
-            sprites: &mut self.sprites,
-            _phase: components::Background,
-        }.run_now(&self.world.res);
-        sys::Draw {
-            ctx,
-            sprites: &mut self.sprites,
-            _phase: components::Foreground,
-        }.run_now(&self.world.res);
-        sys::Draw {
-            ctx,
-            sprites: &mut self.sprites,
-            _phase: components::Decoration,
-        }.run_now(&self.world.res);
-
-        ggez::graphics::draw(
-            ctx,
-            &self.sprites,
-            ggez::nalgebra::Point2::new(0.0, 0.0),
-            0.0
-        )?;
-        self.sprites.clear();
-        ggez::graphics::present(ctx);
-        Ok(())
+        sys::drawing::systems(self, ctx)
     }
 
     fn key_down_event(
@@ -65,7 +39,17 @@ impl EventHandler for MyGame {
         if keycode == sdl::Keycode::Escape {
             ctx.quit().expect("Should never fail");
         }
-        sys::Move { keycode }.run_now(&self.world.res);
+        self.keys.insert(keycode);
+    }
+
+    fn key_up_event(
+        &mut self,
+        _ctx: &mut Context,
+        keycode: sdl::Keycode,
+        _keymod: sdl::Mod,
+        _repeat: bool,
+    ) {
+        self.keys.remove(&keycode);
     }
 }
 
@@ -89,13 +73,15 @@ fn main() -> Result<(), ggez::error::GameError> {
             ..Default::default()
         })
         .build()?;
-    let image = graphics::Image::new(&mut ctx, "/spritesheet.png")?;
-    let mut sprites = graphics::spritebatch::SpriteBatch::new(image);
+    let image = ggez::graphics::Image::new(&mut ctx, "/spritesheet.png")?;
+    let mut sprites = ggez::graphics::spritebatch::SpriteBatch::new(image);
     sprites.set_filter(ggez::graphics::FilterMode::Nearest);
+    let keys = std::collections::HashSet::new();
 
     let mut my_game = MyGame {
         world,
         sprites,
+        keys,
     };
 
     event::run(&mut ctx, &mut my_game)

+ 0 - 1
src/res.rs

@@ -18,7 +18,6 @@ static DRAW_LAYERS: [DrawLayer;3] = [
     DrawLayer::Decoration,
 ];
 
-
 pub fn world_from_file<P: AsRef<Path>>(w: &mut specs::World, path: P) {
     let tiled::Map {
         layers,

+ 39 - 3
src/sys/drawing.rs

@@ -1,19 +1,23 @@
 use crate::consts;
-use crate::components::{Position,Sprite};
+use crate::components::{self,Position,Sprite};
+use crate::game::MyGame;
 
 use ggez::{
     Context,
+    graphics,
     graphics::spritebatch::SpriteBatch,
 };
-use ggez::graphics;
+use specs::RunNow;
 
+/// The `Draw` system is parameterized by which phase we want to draw
+/// in.
 pub struct Draw<'t, Phase> {
     pub ctx: &'t mut Context,
     pub sprites: &'t mut SpriteBatch,
     pub _phase: Phase,
 }
 
-impl<'a, 't, Phase: specs::Component> specs::System<'a> for Draw<'t, Phase> {
+impl<'a, 't, Phase : specs::Component> specs::System<'a> for Draw<'t, Phase> {
     type SystemData = (
         specs::ReadStorage<'a, Position>,
         specs::ReadStorage<'a, Sprite>,
@@ -40,3 +44,35 @@ impl<'a, 't, Phase: specs::Component> specs::System<'a> for Draw<'t, Phase> {
         }
     }
 }
+
+
+pub fn systems(game: &mut MyGame, ctx: &mut Context) -> ggez::GameResult<()> {
+    graphics::set_background_color(ctx, graphics::BLACK);
+    graphics::clear(ctx);
+
+    Draw {
+        ctx,
+        sprites: &mut game.sprites,
+        _phase: components::Background,
+    }.run_now(&game.world.res);
+    Draw {
+        ctx,
+        sprites: &mut game.sprites,
+        _phase: components::Foreground,
+    }.run_now(&game.world.res);
+    Draw {
+        ctx,
+        sprites: &mut game.sprites,
+        _phase: components::Decoration,
+    }.run_now(&game.world.res);
+
+    graphics::draw(
+        ctx,
+        &game.sprites,
+        ggez::nalgebra::Point2::new(0.0, 0.0),
+        0.0
+    )?;
+    game.sprites.clear();
+    graphics::present(ctx);
+    Ok(())
+}

+ 28 - 13
src/sys/input.rs

@@ -1,28 +1,43 @@
-use crate::components::{Movable, Position};
+use crate::components::{Movable, Velocity};
+use crate::game::MyGame;
 
 use sdl2::keyboard as sdl;
+use specs::RunNow;
 
-pub struct Move {
-    pub keycode: sdl::Keycode,
+pub struct Move<'t> {
+    keys: &'t std::collections::HashSet<sdl::Keycode>,
 }
 
-impl<'a> specs::System<'a> for Move {
+impl<'a, 't> specs::System<'a> for Move<'t> {
     type SystemData = (
         specs::ReadStorage<'a, Movable>,
-        specs::WriteStorage<'a, Position>,
+        specs::WriteStorage<'a, Velocity>,
     );
 
-    fn run(&mut self, (movable, mut position): Self::SystemData) {
+    fn run(&mut self, (movable, mut velocity): Self::SystemData) {
         use specs::Join;
 
-        for (_, pos) in (&movable, &mut position).join() {
-            match self.keycode {
-                sdl::Keycode::W => pos.y -= 1.0,
-                sdl::Keycode::A => pos.x -= 1.0,
-                sdl::Keycode::S => pos.y += 1.0,
-                sdl::Keycode::D => pos.x += 1.0,
-                _ => (),
+        for (_, vel) in (&movable, &mut velocity).join() {
+            vel.dx = 0.0;
+            vel.dy = 0.0;
+
+            if self.keys.contains(&sdl::Keycode::W) {
+                vel.dy -= 2.0;
+            }
+            if self.keys.contains(&sdl::Keycode::A) {
+                vel.dx -= 2.0;
+            }
+            if self.keys.contains(&sdl::Keycode::S) {
+                vel.dy += 2.0;
+            }
+            if self.keys.contains(&sdl::Keycode::D) {
+                vel.dx += 2.0;
             }
         }
     }
 }
+
+
+pub fn systems(game: &mut MyGame) {
+    Move { keys: &game.keys }.run_now(&game.world.res);
+}

+ 27 - 0
src/sys/physics.rs

@@ -0,0 +1,27 @@
+use crate::components::{Velocity, Position};
+use crate::game::MyGame;
+
+use specs::RunNow;
+
+struct Physics;
+
+impl <'a> specs::System<'a> for Physics {
+    type SystemData = (
+        specs::ReadStorage<'a, Velocity>,
+        specs::WriteStorage<'a, Position>,
+    );
+
+    fn run(&mut self, (velocity, mut position): Self::SystemData) {
+        use specs::Join;
+
+        for (vel, pos) in (&velocity, &mut position).join() {
+            pos.x += vel.dx;
+            pos.y += vel.dy;
+        }
+    }
+}
+
+
+pub fn systems(game: &mut MyGame) {
+    Physics.run_now(&game.world.res);
+}