Refactor input usage into two separate systems, barebones physics
Getty Ritter
5 years ago
649 | 649 | ] |
650 | 650 | |
651 | 651 | [[package]] |
652 | name = "jeffersonia" | |
653 | version = "0.1.0" | |
654 | dependencies = [ | |
655 | "ggez 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | |
656 | "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
657 | "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
658 | "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", | |
659 | "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
660 | "tiled 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
661 | ] | |
662 | ||
663 | [[package]] | |
664 | 652 | name = "jpeg-decoder" |
665 | 653 | version = "0.1.15" |
666 | 654 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1661 | 1649 | name = "void" |
1662 | 1650 | version = "1.0.2" |
1663 | 1651 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1652 | ||
1653 | [[package]] | |
1654 | name = "wenaglia" | |
1655 | version = "0.1.0" | |
1656 | dependencies = [ | |
1657 | "ggez 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", | |
1658 | "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
1659 | "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
1660 | "specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", | |
1661 | "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
1662 | "tiled 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | |
1663 | ] | |
1664 | 1664 | |
1665 | 1665 | [[package]] |
1666 | 1666 | name = "which" |
54 | 54 | } |
55 | 55 | } |
56 | 56 | |
57 | ||
58 | 57 | #[derive(Component, Default, Debug)] |
59 | 58 | #[storage(NullStorage)] |
60 | 59 | pub struct Background; |
1 | use sdl2::keyboard as sdl; | |
2 | ||
3 | /// The shared values that the game state needs, mostly contained in | |
4 | /// the specs ECS world | |
5 | pub struct MyGame { | |
6 | pub world: specs::World, | |
7 | pub sprites: ggez::graphics::spritebatch::SpriteBatch, | |
8 | pub keys: std::collections::HashSet<sdl::Keycode>, | |
9 | } |
1 | 1 | #[macro_use] extern crate specs_derive; |
2 | 2 | |
3 | use ggez::{Context, ContextBuilder, GameResult}; | |
4 | use ggez::event::{self, EventHandler}; | |
5 | use ggez::graphics; | |
6 | ||
7 |
use |
|
3 | use ggez::{ | |
4 | Context, | |
5 | ContextBuilder, | |
6 | GameResult, | |
7 | event::{self, EventHandler}, | |
8 | }; | |
8 | 9 | |
9 | 10 | use sdl2::keyboard as sdl; |
10 | 11 | |
11 | 12 | pub mod consts; |
12 | 13 | pub mod components; |
14 | pub mod game; | |
13 | 15 | pub mod res; |
14 | 16 | pub mod sys; |
15 | 17 | |
16 | struct MyGame { | |
17 | world: specs::World, | |
18 | sprites: graphics::spritebatch::SpriteBatch, | |
19 | } | |
18 | use game::MyGame; | |
20 | 19 | |
21 | 20 | impl EventHandler for MyGame { |
22 | 21 | |
23 | 22 | fn update(&mut self, _ctx: &mut Context) -> GameResult<()> { |
23 | sys::input::systems(self); | |
24 | sys::physics::systems(self); | |
24 | 25 | Ok(()) |
25 | 26 | } |
26 | 27 | |
27 | 28 | fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { |
28 | ggez::graphics::set_background_color(ctx, ggez::graphics::BLACK); | |
29 | ggez::graphics::clear(ctx); | |
30 | ||
31 | sys::Draw { | |
32 | ctx, | |
33 | sprites: &mut self.sprites, | |
34 | _phase: components::Background, | |
35 | }.run_now(&self.world.res); | |
36 | sys::Draw { | |
37 | ctx, | |
38 | sprites: &mut self.sprites, | |
39 | _phase: components::Foreground, | |
40 | }.run_now(&self.world.res); | |
41 | sys::Draw { | |
42 | ctx, | |
43 | sprites: &mut self.sprites, | |
44 | _phase: components::Decoration, | |
45 | }.run_now(&self.world.res); | |
46 | ||
47 | ggez::graphics::draw( | |
48 | ctx, | |
49 | &self.sprites, | |
50 | ggez::nalgebra::Point2::new(0.0, 0.0), | |
51 | 0.0 | |
52 | )?; | |
53 | self.sprites.clear(); | |
54 | ggez::graphics::present(ctx); | |
55 | Ok(()) | |
29 | sys::drawing::systems(self, ctx) | |
56 | 30 | } |
57 | 31 | |
58 | 32 | fn key_down_event( |
65 | 39 | if keycode == sdl::Keycode::Escape { |
66 | 40 | ctx.quit().expect("Should never fail"); |
67 | 41 | } |
68 |
s |
|
42 | self.keys.insert(keycode); | |
43 | } | |
44 | ||
45 | fn key_up_event( | |
46 | &mut self, | |
47 | _ctx: &mut Context, | |
48 | keycode: sdl::Keycode, | |
49 | _keymod: sdl::Mod, | |
50 | _repeat: bool, | |
51 | ) { | |
52 | self.keys.remove(&keycode); | |
69 | 53 | } |
70 | 54 | } |
71 | 55 | |
89 | 73 | ..Default::default() |
90 | 74 | }) |
91 | 75 | .build()?; |
92 | let image = graphics::Image::new(&mut ctx, "/spritesheet.png")?; | |
93 | let mut sprites = graphics::spritebatch::SpriteBatch::new(image); | |
76 | let image = ggez::graphics::Image::new(&mut ctx, "/spritesheet.png")?; | |
77 | let mut sprites = ggez::graphics::spritebatch::SpriteBatch::new(image); | |
94 | 78 | sprites.set_filter(ggez::graphics::FilterMode::Nearest); |
79 | let keys = std::collections::HashSet::new(); | |
95 | 80 | |
96 | 81 | let mut my_game = MyGame { |
97 | 82 | world, |
98 | 83 | sprites, |
84 | keys, | |
99 | 85 | }; |
100 | 86 | |
101 | 87 | event::run(&mut ctx, &mut my_game) |
17 | 17 | DrawLayer::Foreground, |
18 | 18 | DrawLayer::Decoration, |
19 | 19 | ]; |
20 | ||
21 | 20 | |
22 | 21 | pub fn world_from_file<P: AsRef<Path>>(w: &mut specs::World, path: P) { |
23 | 22 | let tiled::Map { |
1 | 1 | use crate::consts; |
2 |
use crate::components::{ |
|
2 | use crate::components::{self,Position,Sprite}; | |
3 | use crate::game::MyGame; | |
3 | 4 | |
4 | 5 | use ggez::{ |
5 | 6 | Context, |
7 | graphics, | |
6 | 8 | graphics::spritebatch::SpriteBatch, |
7 | 9 | }; |
8 |
use |
|
10 | use specs::RunNow; | |
9 | 11 | |
12 | /// The `Draw` system is parameterized by which phase we want to draw | |
13 | /// in. | |
10 | 14 | pub struct Draw<'t, Phase> { |
11 | 15 | pub ctx: &'t mut Context, |
12 | 16 | pub sprites: &'t mut SpriteBatch, |
13 | 17 | pub _phase: Phase, |
14 | 18 | } |
15 | 19 | |
16 |
impl<'a, 't, Phase |
|
20 | impl<'a, 't, Phase : specs::Component> specs::System<'a> for Draw<'t, Phase> { | |
17 | 21 | type SystemData = ( |
18 | 22 | specs::ReadStorage<'a, Position>, |
19 | 23 | specs::ReadStorage<'a, Sprite>, |
40 | 44 | } |
41 | 45 | } |
42 | 46 | } |
47 | ||
48 | ||
49 | pub fn systems(game: &mut MyGame, ctx: &mut Context) -> ggez::GameResult<()> { | |
50 | graphics::set_background_color(ctx, graphics::BLACK); | |
51 | graphics::clear(ctx); | |
52 | ||
53 | Draw { | |
54 | ctx, | |
55 | sprites: &mut game.sprites, | |
56 | _phase: components::Background, | |
57 | }.run_now(&game.world.res); | |
58 | Draw { | |
59 | ctx, | |
60 | sprites: &mut game.sprites, | |
61 | _phase: components::Foreground, | |
62 | }.run_now(&game.world.res); | |
63 | Draw { | |
64 | ctx, | |
65 | sprites: &mut game.sprites, | |
66 | _phase: components::Decoration, | |
67 | }.run_now(&game.world.res); | |
68 | ||
69 | graphics::draw( | |
70 | ctx, | |
71 | &game.sprites, | |
72 | ggez::nalgebra::Point2::new(0.0, 0.0), | |
73 | 0.0 | |
74 | )?; | |
75 | game.sprites.clear(); | |
76 | graphics::present(ctx); | |
77 | Ok(()) | |
78 | } |
1 |
use crate::components::{Movable, |
|
1 | use crate::components::{Movable, Velocity}; | |
2 | use crate::game::MyGame; | |
2 | 3 | |
3 | 4 | use sdl2::keyboard as sdl; |
5 | use specs::RunNow; | |
4 | 6 | |
5 | pub struct Move { | |
6 | pub keycode: sdl::Keycode, | |
7 | pub struct Move<'t> { | |
8 | keys: &'t std::collections::HashSet<sdl::Keycode>, | |
7 | 9 | } |
8 | 10 | |
9 |
impl<'a |
|
11 | impl<'a, 't> specs::System<'a> for Move<'t> { | |
10 | 12 | type SystemData = ( |
11 | 13 | specs::ReadStorage<'a, Movable>, |
12 |
specs::WriteStorage<'a, |
|
14 | specs::WriteStorage<'a, Velocity>, | |
13 | 15 | ); |
14 | 16 | |
15 |
fn run(&mut self, (movable, mut |
|
17 | fn run(&mut self, (movable, mut velocity): Self::SystemData) { | |
16 | 18 | use specs::Join; |
17 | 19 | |
18 | for (_, pos) in (&movable, &mut position).join() { | |
19 | match self.keycode { | |
20 | sdl::Keycode::W => pos.y -= 1.0, | |
21 | sdl::Keycode::A => pos.x -= 1.0, | |
22 | sdl::Keycode::S => pos.y += 1.0, | |
23 | sdl::Keycode::D => pos.x += 1.0, | |
24 |
|
|
20 | for (_, vel) in (&movable, &mut velocity).join() { | |
21 | vel.dx = 0.0; | |
22 | vel.dy = 0.0; | |
23 | ||
24 | if self.keys.contains(&sdl::Keycode::W) { | |
25 | vel.dy -= 2.0; | |
26 | } | |
27 | if self.keys.contains(&sdl::Keycode::A) { | |
28 | vel.dx -= 2.0; | |
29 | } | |
30 | if self.keys.contains(&sdl::Keycode::S) { | |
31 | vel.dy += 2.0; | |
32 | } | |
33 | if self.keys.contains(&sdl::Keycode::D) { | |
34 | vel.dx += 2.0; | |
25 | 35 | } |
26 | 36 | } |
27 | 37 | } |
28 | 38 | } |
39 | ||
40 | ||
41 | pub fn systems(game: &mut MyGame) { | |
42 | Move { keys: &game.keys }.run_now(&game.world.res); | |
43 | } |
1 | use crate::components::{Velocity, Position}; | |
2 | use crate::game::MyGame; | |
3 | ||
4 | use specs::RunNow; | |
5 | ||
6 | struct Physics; | |
7 | ||
8 | impl <'a> specs::System<'a> for Physics { | |
9 | type SystemData = ( | |
10 | specs::ReadStorage<'a, Velocity>, | |
11 | specs::WriteStorage<'a, Position>, | |
12 | ); | |
13 | ||
14 | fn run(&mut self, (velocity, mut position): Self::SystemData) { | |
15 | use specs::Join; | |
16 | ||
17 | for (vel, pos) in (&velocity, &mut position).join() { | |
18 | pos.x += vel.dx; | |
19 | pos.y += vel.dy; | |
20 | } | |
21 | } | |
22 | } | |
23 | ||
24 | ||
25 | pub fn systems(game: &mut MyGame) { | |
26 | Physics.run_now(&game.world.res); | |
27 | } |