diff options
| author | Arne Dußin | 2021-05-07 18:06:02 +0200 |
|---|---|---|
| committer | Arne Dußin | 2021-05-07 18:06:02 +0200 |
| commit | 6de8cfc84edbc80196ad144f2886031a898f5ed7 (patch) | |
| tree | b51d5f147dacce69bbb70bf363067a2528a2601f /src/systems | |
| parent | f3178df0a92fb3b87087e78cad7b9313f947be6a (diff) | |
| download | pmd_coop-6de8cfc84edbc80196ad144f2886031a898f5ed7.tar.gz pmd_coop-6de8cfc84edbc80196ad144f2886031a898f5ed7.zip | |
Diffstat (limited to 'src/systems')
| -rw-r--r-- | src/systems/draw.rs | 40 | ||||
| -rw-r--r-- | src/systems/input.rs | 88 | ||||
| -rw-r--r-- | src/systems/mod.rs | 3 | ||||
| -rw-r--r-- | src/systems/movement.rs | 43 |
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(); + } + } +} |
