Add delta time steps and a placeholder for control inputs
This commit is contained in:
parent
960bfb9b3f
commit
348533ee9a
|
@ -1,5 +1,7 @@
|
|||
use std::time::Instant;
|
||||
|
||||
use pixels::{Error, Pixels, SurfaceTexture};
|
||||
use simple_invaders::{World, SCREEN_HEIGHT, SCREEN_WIDTH};
|
||||
use simple_invaders::{Controls, Direction, World, SCREEN_HEIGHT, SCREEN_WIDTH};
|
||||
use winit::event;
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
|
||||
|
@ -26,6 +28,7 @@ fn main() -> Result<(), Error> {
|
|||
let surface_texture = SurfaceTexture::new(width, height, &surface);
|
||||
let mut fb = Pixels::new(224, 256, surface_texture)?;
|
||||
let mut invaders = World::new();
|
||||
let mut last = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| match event {
|
||||
event::Event::WindowEvent { event, .. } => match event {
|
||||
|
@ -43,7 +46,18 @@ fn main() -> Result<(), Error> {
|
|||
_ => (),
|
||||
},
|
||||
event::Event::EventsCleared => {
|
||||
invaders.update();
|
||||
// Get a new delta time.
|
||||
let now = Instant::now();
|
||||
let dt = now.duration_since(last);
|
||||
last = now;
|
||||
|
||||
// TODO: Keyboard and controller input.
|
||||
let controls = Controls {
|
||||
direction: Direction::Still,
|
||||
fire: false,
|
||||
};
|
||||
|
||||
invaders.update(dt, controls);
|
||||
window.request_redraw();
|
||||
}
|
||||
_ => (),
|
||||
|
|
17
simple-invaders/src/controls.rs
Normal file
17
simple-invaders/src/controls.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
/// Player control inputs.
|
||||
pub struct Controls {
|
||||
/// Move the player.
|
||||
pub direction: Direction,
|
||||
/// Shoot the cannon.
|
||||
pub fire: bool,
|
||||
}
|
||||
|
||||
/// The player can only move left or right, but can also be stationary.
|
||||
pub enum Direction {
|
||||
/// Do not move the player.
|
||||
Still,
|
||||
/// Move to the left.
|
||||
Left,
|
||||
/// Move to the right.
|
||||
Right,
|
||||
}
|
|
@ -1,9 +1,19 @@
|
|||
mod loader;
|
||||
mod sprites;
|
||||
//! A simple Space Invaders clone to demonstrate `pixels`.
|
||||
//!
|
||||
//! This doesn't use anything fancy like a game engine, so you may not want to build a game like
|
||||
//! this in practice. That said, the game is fully functional, and it should not be too difficult
|
||||
//! to understand the code.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
pub use controls::{Controls, Direction};
|
||||
use loader::{load_assets, Assets};
|
||||
use sprites::{blit, Sprite, SpriteRef, Sprites};
|
||||
|
||||
mod controls;
|
||||
mod loader;
|
||||
mod sprites;
|
||||
|
||||
/// The screen width is constant (units are in pixels)
|
||||
pub const SCREEN_WIDTH: usize = 224;
|
||||
/// The screen height is constant (units are in pixels)
|
||||
|
@ -25,6 +35,7 @@ pub struct World {
|
|||
score: u32,
|
||||
assets: Assets,
|
||||
screen: Vec<u8>,
|
||||
timing: Duration,
|
||||
}
|
||||
|
||||
/// A tiny position vector
|
||||
|
@ -132,11 +143,47 @@ impl World {
|
|||
score: 0,
|
||||
assets,
|
||||
screen,
|
||||
timing: Duration::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the internal state.
|
||||
pub fn update(&mut self) {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `dt`: The time delta since last update.
|
||||
/// * `controls`: The player inputs.
|
||||
pub fn update(&mut self, dt: Duration, controls: Controls) {
|
||||
let one_frame = Duration::from_secs_f64(1.0 / 60.0);
|
||||
|
||||
// Advance the timer by the delta time
|
||||
self.timing += dt;
|
||||
|
||||
// Step the game logic by one frame at a time
|
||||
while self.timing >= one_frame {
|
||||
self.timing -= one_frame;
|
||||
self.step(&controls);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the internal state to the screen.
|
||||
pub fn draw(&mut self) -> &[u8] {
|
||||
// Clear the screen
|
||||
self.clear();
|
||||
|
||||
// Draw the invaders
|
||||
for row in &self.invaders.grid {
|
||||
for col in row {
|
||||
if let Some(invader) = col {
|
||||
blit(&mut self.screen, &invader.pos, &invader.sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&self.screen
|
||||
}
|
||||
|
||||
fn step(&mut self, _controls: &Controls) {
|
||||
// Find the next invader
|
||||
let mut invader = None;
|
||||
while let None = invader {
|
||||
|
@ -159,23 +206,6 @@ impl World {
|
|||
invader.sprite.update_frame(frame);
|
||||
}
|
||||
|
||||
/// Draw the internal state to the screen.
|
||||
pub fn draw(&mut self) -> &[u8] {
|
||||
// Clear the screen
|
||||
self.clear();
|
||||
|
||||
// Draw the invaders
|
||||
for row in &self.invaders.grid {
|
||||
for col in row {
|
||||
if let Some(invader) = col {
|
||||
blit(&mut self.screen, &invader.pos, &invader.sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&self.screen
|
||||
}
|
||||
|
||||
/// Clear the screen
|
||||
fn clear(&mut self) {
|
||||
for (i, byte) in self.screen.iter_mut().enumerate() {
|
||||
|
|
Loading…
Reference in a new issue