2020-07-23 18:12:52 -04:00
|
|
|
use ggez::graphics::Image;
|
2020-07-23 20:25:16 -04:00
|
|
|
use ggez::graphics::{Color, DrawParam};
|
2020-07-23 18:12:52 -04:00
|
|
|
use ggez::nalgebra as na;
|
|
|
|
use ggez::{graphics, Context};
|
2020-07-23 20:25:16 -04:00
|
|
|
use specs::{Join, Read, ReadStorage, System};
|
2020-07-23 18:12:52 -04:00
|
|
|
|
2020-07-24 18:56:48 -04:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
use crate::components::*;
|
2020-07-23 18:12:52 -04:00
|
|
|
use crate::constants::TILE_WIDTH;
|
2020-07-24 18:56:48 -04:00
|
|
|
use crate::resources::*;
|
2020-07-23 18:12:52 -04:00
|
|
|
|
|
|
|
pub struct RenderingSystem<'a> {
|
|
|
|
pub context: &'a mut Context,
|
|
|
|
}
|
|
|
|
|
2020-07-23 20:25:16 -04:00
|
|
|
impl RenderingSystem<'_> {
|
|
|
|
pub fn draw_text(&mut self, text_string: &str, x: f32, y: f32) {
|
|
|
|
let text = graphics::Text::new(text_string);
|
|
|
|
let destination = na::Point2::new(x, y);
|
|
|
|
let color = Some(Color::new(0.0, 0.0, 0.0, 1.0));
|
|
|
|
let dimensions = na::Point2::new(0.0, 20.0);
|
|
|
|
|
|
|
|
graphics::queue_text(self.context, &text, dimensions, color);
|
|
|
|
graphics::draw_queued_text(
|
|
|
|
self.context,
|
|
|
|
graphics::DrawParam::new().dest(destination),
|
|
|
|
None,
|
|
|
|
graphics::FilterMode::Linear,
|
|
|
|
)
|
|
|
|
.expect("expected drawing queued text");
|
|
|
|
}
|
2020-07-24 18:56:48 -04:00
|
|
|
|
|
|
|
pub fn get_image(&mut self, renderable: &Renderable, delta: Duration) -> Image {
|
|
|
|
let path_index = match renderable.kind() {
|
|
|
|
RenderableKind::Static => {
|
|
|
|
// We only have one image, so we just return that
|
|
|
|
0
|
|
|
|
}
|
|
|
|
RenderableKind::Animated => {
|
|
|
|
// If we have multiple, we want to select the right one based on the delta time.
|
|
|
|
// First we get the delta in milliseconds, we % by 1000 to get the seconds only
|
|
|
|
// and finally we divide by 250 to get a number between 0 and 4. If it's 4
|
|
|
|
// we technically are on the next iteration of the loop (or on 0), but we will let
|
|
|
|
// the renderable handle this logic of wrapping frames.
|
|
|
|
((delta.as_millis() % 1000) / 250) as usize
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let image_path = renderable.path(path_index);
|
|
|
|
|
|
|
|
Image::new(self.context, image_path).expect("expected image")
|
|
|
|
}
|
2020-07-23 20:25:16 -04:00
|
|
|
}
|
|
|
|
|
2020-07-23 18:12:52 -04:00
|
|
|
impl<'a> System<'a> for RenderingSystem<'a> {
|
2020-07-23 20:25:16 -04:00
|
|
|
type SystemData = (
|
|
|
|
Read<'a, Gameplay>,
|
2020-07-24 18:56:48 -04:00
|
|
|
Read<'a, Time>,
|
2020-07-23 20:25:16 -04:00
|
|
|
ReadStorage<'a, Position>,
|
|
|
|
ReadStorage<'a, Renderable>,
|
|
|
|
);
|
2020-07-23 18:12:52 -04:00
|
|
|
|
|
|
|
fn run(&mut self, data: Self::SystemData) {
|
2020-07-24 18:56:48 -04:00
|
|
|
let (gameplay, time, positions, renderables) = data;
|
2020-07-23 18:12:52 -04:00
|
|
|
|
|
|
|
// Clear the screen/set the background
|
|
|
|
graphics::clear(self.context, graphics::Color::new(0.95, 0.95, 0.95, 1.0));
|
|
|
|
|
|
|
|
// Get all the renderables with their positions and sort by the position z
|
|
|
|
// This will allow us to have entities layered visually.
|
|
|
|
let mut rendering_data = (&positions, &renderables).join().collect::<Vec<_>>();
|
|
|
|
rendering_data.sort_by(|&a, &b| a.0.z.partial_cmp(&b.0.z).expect("expected comparison"));
|
|
|
|
|
|
|
|
// Iterate through all paris of positions & renderables, load the image
|
|
|
|
// and draw it at the specified position.
|
|
|
|
for (position, renderable) in rendering_data.iter() {
|
|
|
|
// Load the image
|
2020-07-24 18:56:48 -04:00
|
|
|
let image = self.get_image(renderable, time.delta);
|
2020-07-23 18:12:52 -04:00
|
|
|
let x = position.x as f32 * TILE_WIDTH;
|
|
|
|
let y = position.y as f32 * TILE_WIDTH;
|
|
|
|
|
|
|
|
// draw
|
|
|
|
let draw_params = DrawParam::new().dest(na::Point2::new(x, y));
|
|
|
|
graphics::draw(self.context, &image, draw_params).expect("expected render");
|
|
|
|
}
|
|
|
|
|
2020-07-23 20:25:16 -04:00
|
|
|
// Render any text
|
|
|
|
self.draw_text(&gameplay.state.to_string(), 525.0, 80.0);
|
|
|
|
self.draw_text(&gameplay.moves_count.to_string(), 525.0, 100.0);
|
|
|
|
|
2020-07-23 18:12:52 -04:00
|
|
|
// Finally, present the context, this will actually display everything
|
|
|
|
// on the screen.
|
|
|
|
graphics::present(self.context).expect("expected to present");
|
|
|
|
}
|
|
|
|
}
|