From e09c2213d798191dec548b8338124befff836eb5 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 15:41:04 +0800 Subject: [PATCH 1/9] Added R key to reset game --- examples/invaders/simple-invaders/src/lib.rs | 79 ++++++++++++++------ examples/invaders/src/main.rs | 9 +++ 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index 97921fb9..f4deaf7a 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -459,6 +459,43 @@ impl World { }); } } + + pub fn reset_game(&mut self) { + // Recreate the alien + self.invaders = Invaders { + grid: make_invader_grid(&self.assets), + stepper: Point::new(COLS - 1, 0), + direction: Direction::Right, + descend: false, + bounds: Bounds::default(), + }; + + // Empty laser + self.lasers.clear(); + + // Recreate the shield + self.shields = (0..4) + .map(|i| Shield { + sprite: Sprite::new(&self.assets, Frame::Shield1), + pos: Point::new(i * 45 + 32, 192), + }) + .collect(); + + // Reset player position + self.player.pos = PLAYER_START; + + // Remove bullet + self.bullet = None; + + // Reset collision state + self.collision.clear(); + + // Reset game score + self._score = 0; + + // Set gameover to false + self.gameover = false; + } } /// Create a default `World` with a static PRNG seed. @@ -498,46 +535,40 @@ impl Invaders { let mut right = 0; let mut bottom = 0; let mut left = COLS; - + // Scan through the entire grid for (y, row) in self.grid.iter().enumerate() { - for (x, col) in row.iter().enumerate() { - if col.is_some() { - // Build a boundary box of invaders in the grid - if top > y { - top = y; - } - if bottom < y { - bottom = y; - } - if left > x { - left = x; - } - if right < x { - right = x; - } - } - } + row.iter().enumerate().filter(|(_, col)| col.is_some()).for_each(|(x, _)| { + top = top.min(y); + bottom = bottom.max(y); + left = left.min(x); + right = right.max(x); + }); } - + if top > bottom || left > right { // No more invaders left alive return true; } - + + let bounds_changed = self.bounds.left_col != left + || self.bounds.right_col != right + || self.bounds.top_row != top + || self.bounds.bottom_row != bottom; + // Adjust the bounding box position self.bounds.pos.x += (left - self.bounds.left_col) * GRID.x; self.bounds.pos.y += (top - self.bounds.top_row) * GRID.y; - + // Adjust the bounding box columns and rows self.bounds.left_col = left; self.bounds.right_col = right; self.bounds.top_row = top; self.bounds.bottom_row = bottom; - - // No more changes - false + + bounds_changed } + fn get_closest_invader(&self, mut col: usize) -> &Invader { let mut row = ROWS - 1; diff --git a/examples/invaders/src/main.rs b/examples/invaders/src/main.rs index 299bfd63..5edb6783 100644 --- a/examples/invaders/src/main.rs +++ b/examples/invaders/src/main.rs @@ -95,6 +95,10 @@ impl Game { Controls { direction, fire } }; } + + fn reset_game(&mut self) { + self.world.reset_game(); + } } fn main() -> Result<(), Error> { @@ -165,6 +169,11 @@ fn main() -> Result<(), Error> { return; } + // Reset game + if g.game.input.key_pressed(VirtualKeyCode::R) { + g.game.reset_game(); + } + // Resize the window if let Some(size) = g.game.input.window_resized() { if let Err(err) = g.game.pixels.resize_surface(size.width, size.height) { From aa94512b16c1ce4af28c192018533a94e777f885 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 15:58:21 +0800 Subject: [PATCH 2/9] Format code --- examples/invaders/simple-invaders/src/lib.rs | 28 +++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index f4deaf7a..0e8cac5a 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -535,40 +535,42 @@ impl Invaders { let mut right = 0; let mut bottom = 0; let mut left = COLS; - + // Scan through the entire grid for (y, row) in self.grid.iter().enumerate() { - row.iter().enumerate().filter(|(_, col)| col.is_some()).for_each(|(x, _)| { - top = top.min(y); - bottom = bottom.max(y); - left = left.min(x); - right = right.max(x); - }); + row.iter() + .enumerate() + .filter(|(_, col)| col.is_some()) + .for_each(|(x, _)| { + top = top.min(y); + bottom = bottom.max(y); + left = left.min(x); + right = right.max(x); + }); } - + if top > bottom || left > right { // No more invaders left alive return true; } - + let bounds_changed = self.bounds.left_col != left || self.bounds.right_col != right || self.bounds.top_row != top || self.bounds.bottom_row != bottom; - + // Adjust the bounding box position self.bounds.pos.x += (left - self.bounds.left_col) * GRID.x; self.bounds.pos.y += (top - self.bounds.top_row) * GRID.y; - + // Adjust the bounding box columns and rows self.bounds.left_col = left; self.bounds.right_col = right; self.bounds.top_row = top; self.bounds.bottom_row = bottom; - + bounds_changed } - fn get_closest_invader(&self, mut col: usize) -> &Invader { let mut row = ROWS - 1; From 42f82d7cd1302d3379e5da845f5d8e4312ce4dc8 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 17:05:39 +0800 Subject: [PATCH 3/9] Restore 'false' --- examples/invaders/simple-invaders/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index 0e8cac5a..cd3240b6 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -554,11 +554,6 @@ impl Invaders { return true; } - let bounds_changed = self.bounds.left_col != left - || self.bounds.right_col != right - || self.bounds.top_row != top - || self.bounds.bottom_row != bottom; - // Adjust the bounding box position self.bounds.pos.x += (left - self.bounds.left_col) * GRID.x; self.bounds.pos.y += (top - self.bounds.top_row) * GRID.y; @@ -569,7 +564,7 @@ impl Invaders { self.bounds.top_row = top; self.bounds.bottom_row = bottom; - bounds_changed + false } fn get_closest_invader(&self, mut col: usize) -> &Invader { From b7fe9bb351a5134769758ff69c5db2f804b84114 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 17:07:01 +0800 Subject: [PATCH 4/9] Restore 'false' --- examples/invaders/simple-invaders/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index cd3240b6..f824c10b 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -564,6 +564,7 @@ impl Invaders { self.bounds.top_row = top; self.bounds.bottom_row = bottom; + // No more changes false } From 04f9100dc3e27c9437e0093990139bbc169da9c3 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 17:49:16 +0800 Subject: [PATCH 5/9] [Fix] /examples/invaders/README.md --- examples/invaders/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/invaders/README.md b/examples/invaders/README.md index 43970d22..7f9f73d9 100644 --- a/examples/invaders/README.md +++ b/examples/invaders/README.md @@ -18,6 +18,8 @@ cargo run --release --package invaders Pause P: Pause +Reset R: Reset Game + ## GamePad Controls `D-Pad 🡰` `D-Pad 🡲`: Move tank From 62359c5fdd0d148e0b113e61da5e9deb3cd59f21 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sat, 25 Mar 2023 18:05:39 +0800 Subject: [PATCH 6/9] [Fix] /examples/invaders/README.md --- examples/invaders/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/invaders/README.md b/examples/invaders/README.md index 7f9f73d9..18c2f898 100644 --- a/examples/invaders/README.md +++ b/examples/invaders/README.md @@ -18,7 +18,9 @@ cargo run --release --package invaders Pause P: Pause -Reset R: Reset Game +R: Reset Game + +escape: Quit ## GamePad Controls From 9a545f7b1ee23707ed9eb3f9526750d28d3e441c Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sun, 26 Mar 2023 12:14:50 +0800 Subject: [PATCH 7/9] Invaders, Shield, Player module processing --- examples/invaders/simple-invaders/src/lib.rs | 69 ++++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index f824c10b..6686e850 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -140,6 +140,17 @@ trait DeltaTime { } } +impl Player { + pub fn new(assets: &Assets) -> Self { + let sprite = SpriteRef::new(assets, Frame::Player1, Duration::from_millis(100)); + let pos = PLAYER_START; + let dt = Duration::default(); + + Player { sprite, pos, dt } + } +} + + impl DeltaTime for Player { fn update(&mut self) -> usize { Self::update_dt(&mut self.dt, ONE_FRAME) @@ -184,31 +195,17 @@ impl World { /// let world = World::new(seed, false); /// ``` pub fn new(seed: (u64, u64), debug: bool) -> World { - use Frame::*; // Load assets first let assets = load_assets(); // TODO: Create invaders one-at-a-time - let invaders = Invaders { - grid: make_invader_grid(&assets), - stepper: Point::new(COLS - 1, 0), - direction: Direction::Right, - descend: false, - bounds: Bounds::default(), - }; + let invaders = Invaders::new(&assets); let lasers = Vec::new(); let shields = (0..4) - .map(|i| Shield { - sprite: Sprite::new(&assets, Shield1), - pos: Point::new(i * 45 + 32, 192), - }) + .map(|i| Shield::new(&assets, Point::new(i * 45 + 32, 192))) .collect(); - let player = Player { - sprite: SpriteRef::new(&assets, Player1, Duration::from_millis(100)), - pos: PLAYER_START, - dt: Duration::default(), - }; + let player = Player::new(&assets); let bullet = None; let collision = Collision::default(); let _score = 0; @@ -462,23 +459,14 @@ impl World { pub fn reset_game(&mut self) { // Recreate the alien - self.invaders = Invaders { - grid: make_invader_grid(&self.assets), - stepper: Point::new(COLS - 1, 0), - direction: Direction::Right, - descend: false, - bounds: Bounds::default(), - }; + self.invaders = Invaders::new(&self.assets); // Empty laser self.lasers.clear(); // Recreate the shield self.shields = (0..4) - .map(|i| Shield { - sprite: Sprite::new(&self.assets, Frame::Shield1), - pos: Point::new(i * 45 + 32, 192), - }) + .map(|i| Shield::new(&self.assets, Point::new(i * 45 + 32, 192))) .collect(); // Reset player position @@ -508,6 +496,22 @@ impl Default for World { } impl Invaders { + // New + pub fn new(assets: &Assets) -> Self { + let grid = make_invader_grid(assets); + let stepper = Point::new(COLS - 1, 0); + let direction = Direction::Right; + let descend = false; + let bounds = Bounds::default(); + + Invaders { + grid, + stepper, + direction, + descend, + bounds, + } + } /// Compute the bounding box for the Invader fleet. /// /// # Returns @@ -588,6 +592,15 @@ impl Invaders { } } +impl Shield { + // New + pub fn new(assets: &Assets, pos: Point) -> Self { + let sprite = Sprite::new(assets, Frame::Shield1); + + Shield { sprite, pos } + } +} + impl Default for Bounds { fn default() -> Self { Self { From 2d68f03bd159472414b314ac1f36fda8ab7fea16 Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sun, 26 Mar 2023 12:24:34 +0800 Subject: [PATCH 8/9] [Fix] The check --- examples/invaders/simple-invaders/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index 6686e850..833e2268 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -145,12 +145,10 @@ impl Player { let sprite = SpriteRef::new(assets, Frame::Player1, Duration::from_millis(100)); let pos = PLAYER_START; let dt = Duration::default(); - Player { sprite, pos, dt } } } - impl DeltaTime for Player { fn update(&mut self) -> usize { Self::update_dt(&mut self.dt, ONE_FRAME) @@ -195,7 +193,6 @@ impl World { /// let world = World::new(seed, false); /// ``` pub fn new(seed: (u64, u64), debug: bool) -> World { - // Load assets first let assets = load_assets(); From 93d0a1c374559e56b9f273cd60f2d183320f854b Mon Sep 17 00:00:00 2001 From: imizao <2313466338@qq.com> Date: Sun, 26 Mar 2023 13:07:43 +0800 Subject: [PATCH 9/9] Improve the processing of Shield and Player modules --- examples/invaders/simple-invaders/src/lib.rs | 40 +++---------------- .../invaders/simple-invaders/src/player.rs | 24 +++++++++++ .../invaders/simple-invaders/src/shield.rs | 20 ++++++++++ 3 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 examples/invaders/simple-invaders/src/player.rs create mode 100644 examples/invaders/simple-invaders/src/shield.rs diff --git a/examples/invaders/simple-invaders/src/lib.rs b/examples/invaders/simple-invaders/src/lib.rs index 833e2268..92cb9efd 100644 --- a/examples/invaders/simple-invaders/src/lib.rs +++ b/examples/invaders/simple-invaders/src/lib.rs @@ -15,7 +15,9 @@ use crate::collision::Collision; pub use crate::controls::{Controls, Direction}; use crate::geo::Point; use crate::loader::{load_assets, Assets}; -use crate::sprites::{blit, Animation, Drawable, Frame, Sprite, SpriteRef}; +use crate::player::Player; +use crate::shield::Shield; +use crate::sprites::{blit, Animation, Drawable, Frame, SpriteRef}; use core::time::Duration; use randomize::PCG32; @@ -24,6 +26,8 @@ mod controls; mod debug; mod geo; mod loader; +mod player; +mod shield; mod sprites; /// The screen width is constant (units are in pixels) @@ -96,22 +100,6 @@ struct Bounds { bottom_row: usize, } -/// The player entity. -#[derive(Debug)] -struct Player { - sprite: SpriteRef, - pos: Point, - dt: Duration, -} - -/// The shield entity. -#[derive(Debug)] -struct Shield { - // Shield sprite is not referenced because we want to deform it when it gets shot - sprite: Sprite, - pos: Point, -} - /// The laser entity. #[derive(Debug)] struct Laser { @@ -140,15 +128,6 @@ trait DeltaTime { } } -impl Player { - pub fn new(assets: &Assets) -> Self { - let sprite = SpriteRef::new(assets, Frame::Player1, Duration::from_millis(100)); - let pos = PLAYER_START; - let dt = Duration::default(); - Player { sprite, pos, dt } - } -} - impl DeltaTime for Player { fn update(&mut self) -> usize { Self::update_dt(&mut self.dt, ONE_FRAME) @@ -589,15 +568,6 @@ impl Invaders { } } -impl Shield { - // New - pub fn new(assets: &Assets, pos: Point) -> Self { - let sprite = Sprite::new(assets, Frame::Shield1); - - Shield { sprite, pos } - } -} - impl Default for Bounds { fn default() -> Self { Self { diff --git a/examples/invaders/simple-invaders/src/player.rs b/examples/invaders/simple-invaders/src/player.rs new file mode 100644 index 00000000..35ac1999 --- /dev/null +++ b/examples/invaders/simple-invaders/src/player.rs @@ -0,0 +1,24 @@ +use crate::geo::Point; +use crate::loader::Assets; +use crate::sprites::{Frame, SpriteRef}; +use core::time::Duration; + +// Player positioning +const PLAYER_START: Point = Point::new(80, 216); + +/// The player entity. +#[derive(Debug)] +pub(crate) struct Player { + pub sprite: SpriteRef, + pub pos: Point, + pub dt: Duration, +} + +impl Player { + pub fn new(assets: &Assets) -> Self { + let sprite = SpriteRef::new(assets, Frame::Player1, Duration::from_millis(100)); + let pos = PLAYER_START; + let dt = Duration::default(); + Player { sprite, pos, dt } + } +} diff --git a/examples/invaders/simple-invaders/src/shield.rs b/examples/invaders/simple-invaders/src/shield.rs new file mode 100644 index 00000000..c44f5b60 --- /dev/null +++ b/examples/invaders/simple-invaders/src/shield.rs @@ -0,0 +1,20 @@ +use crate::geo::Point; +use crate::loader::Assets; +use crate::sprites::{Frame, Sprite}; + +/// The shield entity. +#[derive(Debug)] +pub(crate) struct Shield { + // Shield sprite is not referenced because we want to deform it when it gets shot + pub sprite: Sprite, + pub pos: Point, +} + +impl Shield { + // New + pub fn new(assets: &Assets, pos: Point) -> Self { + let sprite = Sprite::new(assets, Frame::Shield1); + + Shield { sprite, pos } + } +}