summaryrefslogtreecommitdiff
path: root/src/systems
diff options
context:
space:
mode:
authorArne Dußin2021-05-07 18:06:02 +0200
committerArne Dußin2021-05-07 18:06:02 +0200
commit6de8cfc84edbc80196ad144f2886031a898f5ed7 (patch)
treeb51d5f147dacce69bbb70bf363067a2528a2601f /src/systems
parentf3178df0a92fb3b87087e78cad7b9313f947be6a (diff)
downloadpmd_coop-6de8cfc84edbc80196ad144f2886031a898f5ed7.tar.gz
pmd_coop-6de8cfc84edbc80196ad144f2886031a898f5ed7.zip
Add player movementHEADmain
Diffstat (limited to 'src/systems')
-rw-r--r--src/systems/draw.rs40
-rw-r--r--src/systems/input.rs88
-rw-r--r--src/systems/mod.rs3
-rw-r--r--src/systems/movement.rs43
4 files changed, 165 insertions, 9 deletions
diff --git a/src/systems/draw.rs b/src/systems/draw.rs
index 1d5ee6b..fd0185e 100644
--- a/src/systems/draw.rs
+++ b/src/systems/draw.rs
@@ -1,4 +1,8 @@
+use std::thread;
+use std::time::{Duration, Instant};
+
use sdl2::pixels::Color;
+use sdl2::rect::Rect;
use sdl2::render::WindowCanvas;
use sdl2::video::{Window, WindowContext};
use specs::prelude::*;
@@ -6,8 +10,14 @@ use specs::prelude::*;
use crate::components::{Pos, StaticDrawable};
use crate::texture_manager::TextureManager;
+/// The minimum time in micro a frame should take to limit the number of
+/// frames drawn to the screen. 5000 microseconds for a maximum of 200 frames
+/// per second.
+pub const FRAME_TIME_MIN_US: u64 = (1_000_000. / 200.) as u64;
+
pub struct SysDraw
{
+ last_frame_time: Instant,
canvas: WindowCanvas,
texture_manager: TextureManager<WindowContext>,
}
@@ -25,10 +35,20 @@ impl SysDraw
let texture_manager = TextureManager::new(canvas.texture_creator());
Self {
+ last_frame_time: Instant::now(),
canvas,
texture_manager,
}
}
+
+ pub fn delay_for_min_frametime(&mut self)
+ {
+ let frame_duration_us = (Instant::now() - self.last_frame_time).as_micros() as u64;
+ if frame_duration_us < FRAME_TIME_MIN_US {
+ thread::sleep(Duration::from_micros(FRAME_TIME_MIN_US - frame_duration_us));
+ }
+ self.last_frame_time = Instant::now();
+ }
}
impl<'a> System<'a> for SysDraw
@@ -39,20 +59,30 @@ impl<'a> System<'a> for SysDraw
{
self.canvas.clear();
- // XXX: This is so slow.. yaaaawn. Replace with ids and texture manager
- // lifetime?
- for (_pos, drawable) in (&pos, &drawable).join() {
+ /* XXX: This is so slow.. yaaaawn. Replace with ids and texture manager
+ * lifetime? */
+ for (pos, drawable) in (&pos, &drawable).join() {
let texture = self
.texture_manager
.get(&drawable.texture_name)
.expect("Unable to load texture");
- // let texture_info = texture.query();
self.canvas
- .copy(&texture, None, None)
+ .copy(
+ &texture,
+ Some(drawable.source_rect),
+ Rect::new(
+ pos.0.x as i32,
+ pos.0.y as i32,
+ drawable.source_rect.width(),
+ drawable.source_rect.height(),
+ ),
+ )
.expect("Unable to draw texture");
}
+ self.delay_for_min_frametime();
+
self.canvas.present();
}
}
diff --git a/src/systems/input.rs b/src/systems/input.rs
index 96ac3b8..13942e0 100644
--- a/src/systems/input.rs
+++ b/src/systems/input.rs
@@ -1,10 +1,21 @@
use sdl2::event::{Event, WindowEvent};
+use sdl2::keyboard::Scancode;
use sdl2::{EventPump, Sdl};
use specs::prelude::*;
+use crate::components::{Player, Velocity};
+
+pub const PLAYER_SPEED: f64 = 150.;
+
+pub const ACTION_KEY_UP: u8 = 0b0001;
+pub const ACTION_KEY_LEFT: u8 = 0b0010;
+pub const ACTION_KEY_DOWN: u8 = 0b0100;
+pub const ACTION_KEY_RIGHT: u8 = 0b1000;
+
pub struct SysInput
{
- event_pump: EventPump,
+ pressed_action_keys: u8,
+ event_pump: EventPump,
}
impl SysInput
@@ -12,17 +23,19 @@ impl SysInput
pub fn new(sdl: &Sdl) -> Self
{
Self {
- event_pump: sdl.event_pump().unwrap(),
+ pressed_action_keys: 0b0,
+ event_pump: sdl.event_pump().unwrap(),
}
}
}
impl<'a> System<'a> for SysInput
{
- type SystemData = ();
+ type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Player>);
- fn run(&mut self, (): Self::SystemData)
+ fn run(&mut self, (mut vel, player): Self::SystemData)
{
+ let mut player_movement_changed = false;
for event in self.event_pump.poll_iter() {
match event {
Event::Quit { .. } => {
@@ -34,8 +47,75 @@ impl<'a> System<'a> for SysInput
} => {
println!("Window resized to {}x{}", x, y);
},
+ Event::KeyDown { scancode, .. } => match scancode {
+ Some(Scancode::W) => {
+ self.pressed_action_keys |= ACTION_KEY_UP;
+ player_movement_changed = true;
+ },
+ Some(Scancode::A) => {
+ self.pressed_action_keys |= ACTION_KEY_LEFT;
+ player_movement_changed = true;
+ },
+ Some(Scancode::S) => {
+ self.pressed_action_keys |= ACTION_KEY_DOWN;
+ player_movement_changed = true;
+ },
+ Some(Scancode::D) => {
+ self.pressed_action_keys |= ACTION_KEY_RIGHT;
+ player_movement_changed = true;
+ },
+ key => {
+ println!("keydown received: {:?}", key)
+ },
+ },
+ Event::KeyUp { scancode, .. } => match scancode {
+ Some(Scancode::W) => {
+ self.pressed_action_keys &= !ACTION_KEY_UP;
+ player_movement_changed = true;
+ },
+ Some(Scancode::A) => {
+ self.pressed_action_keys &= !ACTION_KEY_LEFT;
+ player_movement_changed = true;
+ },
+ Some(Scancode::S) => {
+ self.pressed_action_keys &= !ACTION_KEY_DOWN;
+ player_movement_changed = true;
+ },
+ Some(Scancode::D) => {
+ self.pressed_action_keys &= !ACTION_KEY_RIGHT;
+ player_movement_changed = true;
+ },
+ _ => {},
+ },
_ => {},
}
}
+
+ /* Update player movement */
+ if player_movement_changed {
+ for (vel, _player) in (&mut vel, &player).join() {
+ /* Vertical movement */
+ if (self.pressed_action_keys & ACTION_KEY_UP) != 0 {
+ vel.0.y = -PLAYER_SPEED;
+ }
+ else if (self.pressed_action_keys & ACTION_KEY_DOWN) != 0 {
+ vel.0.y = PLAYER_SPEED;
+ }
+ else {
+ vel.0.y = 0.;
+ }
+
+ /* Horizontal movement */
+ if (self.pressed_action_keys & ACTION_KEY_LEFT) != 0 {
+ vel.0.x = -PLAYER_SPEED;
+ }
+ else if (self.pressed_action_keys & ACTION_KEY_RIGHT) != 0 {
+ vel.0.x = PLAYER_SPEED;
+ }
+ else {
+ vel.0.x = 0.;
+ }
+ }
+ }
}
}
diff --git a/src/systems/mod.rs b/src/systems/mod.rs
index 2c2af6c..5101a83 100644
--- a/src/systems/mod.rs
+++ b/src/systems/mod.rs
@@ -3,3 +3,6 @@ pub use self::draw::*;
pub mod input;
pub use self::input::*;
+
+pub mod movement;
+pub use self::movement::*;
diff --git a/src/systems/movement.rs b/src/systems/movement.rs
new file mode 100644
index 0000000..61c572a
--- /dev/null
+++ b/src/systems/movement.rs
@@ -0,0 +1,43 @@
+use std::time::{Duration, Instant};
+
+use specs::prelude::*;
+
+use crate::components::{Pos, Velocity};
+
+pub struct SysMovement
+{
+ delta_time: Duration,
+ last_run: Instant,
+}
+
+impl SysMovement
+{
+ pub fn new() -> Self
+ {
+ Self {
+ delta_time: Duration::ZERO,
+ last_run: Instant::now(),
+ }
+ }
+}
+
+impl Default for SysMovement
+{
+ fn default() -> Self { Self::new() }
+}
+
+impl<'a> System<'a> for SysMovement
+{
+ type SystemData = (WriteStorage<'a, Pos>, ReadStorage<'a, Velocity>);
+
+ fn run(&mut self, (mut pos, vel): Self::SystemData)
+ {
+ let now = Instant::now();
+ self.delta_time = now - self.last_run;
+ self.last_run = now;
+
+ for (pos, vel) in (&mut pos, &vel).join() {
+ pos.0 += vel.0 * self.delta_time.as_secs_f64();
+ }
+ }
+}