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::*; 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, } impl SysDraw { pub fn new(window: Window) -> Self { let mut canvas = window .into_canvas() .build() .expect("Unable to create canvas"); canvas.set_draw_color(Color::RGB(255, 255, 0)); 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 { type SystemData = (ReadStorage<'a, Pos>, ReadStorage<'a, StaticDrawable>); fn run(&mut self, (pos, drawable): Self::SystemData) { self.canvas.clear(); /* 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"); self.canvas .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(); } }