Added R key to reset game (#350)
* Added R key to reset game * Invaders, Shield, Player module processing * Improve the processing of Shield and Player modules
This commit is contained in:
parent
3d8c7bd0c9
commit
d85091847a
|
@ -18,6 +18,10 @@ cargo run --release --package invaders
|
||||||
|
|
||||||
<kbd>Pause</kbd> <kbd>P</kbd>: Pause
|
<kbd>Pause</kbd> <kbd>P</kbd>: Pause
|
||||||
|
|
||||||
|
<kbd>R</kbd>: Reset Game
|
||||||
|
|
||||||
|
<kbd>escape</kbd>: Quit
|
||||||
|
|
||||||
## GamePad Controls
|
## GamePad Controls
|
||||||
|
|
||||||
`D-Pad 🡰` `D-Pad 🡲`: Move tank
|
`D-Pad 🡰` `D-Pad 🡲`: Move tank
|
||||||
|
|
|
@ -15,7 +15,9 @@ use crate::collision::Collision;
|
||||||
pub use crate::controls::{Controls, Direction};
|
pub use crate::controls::{Controls, Direction};
|
||||||
use crate::geo::Point;
|
use crate::geo::Point;
|
||||||
use crate::loader::{load_assets, Assets};
|
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 core::time::Duration;
|
||||||
use randomize::PCG32;
|
use randomize::PCG32;
|
||||||
|
|
||||||
|
@ -24,6 +26,8 @@ mod controls;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod geo;
|
mod geo;
|
||||||
mod loader;
|
mod loader;
|
||||||
|
mod player;
|
||||||
|
mod shield;
|
||||||
mod sprites;
|
mod sprites;
|
||||||
|
|
||||||
/// The screen width is constant (units are in pixels)
|
/// The screen width is constant (units are in pixels)
|
||||||
|
@ -96,22 +100,6 @@ struct Bounds {
|
||||||
bottom_row: usize,
|
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.
|
/// The laser entity.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Laser {
|
struct Laser {
|
||||||
|
@ -184,31 +172,16 @@ impl World {
|
||||||
/// let world = World::new(seed, false);
|
/// let world = World::new(seed, false);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(seed: (u64, u64), debug: bool) -> World {
|
pub fn new(seed: (u64, u64), debug: bool) -> World {
|
||||||
use Frame::*;
|
|
||||||
|
|
||||||
// Load assets first
|
// Load assets first
|
||||||
let assets = load_assets();
|
let assets = load_assets();
|
||||||
|
|
||||||
// TODO: Create invaders one-at-a-time
|
// TODO: Create invaders one-at-a-time
|
||||||
let invaders = Invaders {
|
let invaders = Invaders::new(&assets);
|
||||||
grid: make_invader_grid(&assets),
|
|
||||||
stepper: Point::new(COLS - 1, 0),
|
|
||||||
direction: Direction::Right,
|
|
||||||
descend: false,
|
|
||||||
bounds: Bounds::default(),
|
|
||||||
};
|
|
||||||
let lasers = Vec::new();
|
let lasers = Vec::new();
|
||||||
let shields = (0..4)
|
let shields = (0..4)
|
||||||
.map(|i| Shield {
|
.map(|i| Shield::new(&assets, Point::new(i * 45 + 32, 192)))
|
||||||
sprite: Sprite::new(&assets, Shield1),
|
|
||||||
pos: Point::new(i * 45 + 32, 192),
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
let player = Player {
|
let player = Player::new(&assets);
|
||||||
sprite: SpriteRef::new(&assets, Player1, Duration::from_millis(100)),
|
|
||||||
pos: PLAYER_START,
|
|
||||||
dt: Duration::default(),
|
|
||||||
};
|
|
||||||
let bullet = None;
|
let bullet = None;
|
||||||
let collision = Collision::default();
|
let collision = Collision::default();
|
||||||
let _score = 0;
|
let _score = 0;
|
||||||
|
@ -459,6 +432,34 @@ impl World {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset_game(&mut self) {
|
||||||
|
// Recreate the alien
|
||||||
|
self.invaders = Invaders::new(&self.assets);
|
||||||
|
|
||||||
|
// Empty laser
|
||||||
|
self.lasers.clear();
|
||||||
|
|
||||||
|
// Recreate the shield
|
||||||
|
self.shields = (0..4)
|
||||||
|
.map(|i| Shield::new(&self.assets, 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.
|
/// Create a default `World` with a static PRNG seed.
|
||||||
|
@ -471,6 +472,22 @@ impl Default for World {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Invaders {
|
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.
|
/// Compute the bounding box for the Invader fleet.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -501,23 +518,15 @@ impl Invaders {
|
||||||
|
|
||||||
// Scan through the entire grid
|
// Scan through the entire grid
|
||||||
for (y, row) in self.grid.iter().enumerate() {
|
for (y, row) in self.grid.iter().enumerate() {
|
||||||
for (x, col) in row.iter().enumerate() {
|
row.iter()
|
||||||
if col.is_some() {
|
.enumerate()
|
||||||
// Build a boundary box of invaders in the grid
|
.filter(|(_, col)| col.is_some())
|
||||||
if top > y {
|
.for_each(|(x, _)| {
|
||||||
top = y;
|
top = top.min(y);
|
||||||
}
|
bottom = bottom.max(y);
|
||||||
if bottom < y {
|
left = left.min(x);
|
||||||
bottom = y;
|
right = right.max(x);
|
||||||
}
|
});
|
||||||
if left > x {
|
|
||||||
left = x;
|
|
||||||
}
|
|
||||||
if right < x {
|
|
||||||
right = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if top > bottom || left > right {
|
if top > bottom || left > right {
|
||||||
|
|
24
examples/invaders/simple-invaders/src/player.rs
Normal file
24
examples/invaders/simple-invaders/src/player.rs
Normal file
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
20
examples/invaders/simple-invaders/src/shield.rs
Normal file
20
examples/invaders/simple-invaders/src/shield.rs
Normal file
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,6 +95,10 @@ impl Game {
|
||||||
Controls { direction, fire }
|
Controls { direction, fire }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset_game(&mut self) {
|
||||||
|
self.world.reset_game();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
|
@ -165,6 +169,11 @@ fn main() -> Result<(), Error> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset game
|
||||||
|
if g.game.input.key_pressed(VirtualKeyCode::R) {
|
||||||
|
g.game.reset_game();
|
||||||
|
}
|
||||||
|
|
||||||
// Resize the window
|
// Resize the window
|
||||||
if let Some(size) = g.game.input.window_resized() {
|
if let Some(size) = g.game.input.window_resized() {
|
||||||
if let Err(err) = g.game.pixels.resize_surface(size.width, size.height) {
|
if let Err(err) = g.game.pixels.resize_surface(size.width, size.height) {
|
||||||
|
|
Loading…
Reference in a new issue