Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added R key to reset game #350

Merged
merged 9 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/invaders/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ cargo run --release --package invaders

<kbd>Pause</kbd> <kbd>P</kbd>: Pause

<kbd>R</kbd>: Reset Game

<kbd>escape</kbd>: Quit

## GamePad Controls

`D-Pad 🡰` `D-Pad 🡲`: Move tank
Expand Down
113 changes: 61 additions & 52 deletions examples/invaders/simple-invaders/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -184,31 +172,16 @@ 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;
Expand Down Expand Up @@ -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.
Expand All @@ -471,6 +472,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
Expand Down Expand Up @@ -501,23 +518,15 @@ impl Invaders {

// 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 {
Expand Down
24 changes: 24 additions & 0 deletions examples/invaders/simple-invaders/src/player.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions examples/invaders/simple-invaders/src/shield.rs
Original file line number Diff line number Diff line change
@@ -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 }
}
}
9 changes: 9 additions & 0 deletions examples/invaders/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ impl Game {
Controls { direction, fire }
};
}

fn reset_game(&mut self) {
self.world.reset_game();
}
}

fn main() -> Result<(), Error> {
Expand Down Expand Up @@ -165,6 +169,11 @@ fn main() -> Result<(), Error> {
return;
}

// Reset game
if g.game.input.key_pressed(VirtualKeyCode::R) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a binding for controller inputs as well. Maybe the "select" button? I don't actually know what it's called any more on XBox/PS/Switch!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the "select" button? I don't know!LOL ; )

But I believe that if add the selected operation interface, this problem will be solved!

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) {
Expand Down