forked from tutorials/rust-sokoban
Complete 3.4 Batch rendering
This commit is contained in:
parent
b9245a2dff
commit
5b94a0d5a9
@ -9,3 +9,4 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ggez = "0.5.1"
|
ggez = "0.5.1"
|
||||||
specs = { version="0.16.1", features=["specs-derive"] }
|
specs = { version="0.16.1", features=["specs-derive"] }
|
||||||
|
itertools = "0.9.0"
|
@ -1,9 +1,12 @@
|
|||||||
use ggez::graphics::Image;
|
use ggez::graphics::Image;
|
||||||
use ggez::graphics::{Color, DrawParam};
|
use ggez::graphics::{Color, DrawParam};
|
||||||
use ggez::nalgebra as na;
|
use ggez::{nalgebra as na, timer};
|
||||||
use ggez::{graphics, Context};
|
use ggez::{graphics, Context};
|
||||||
|
use ggez::graphics::spritebatch::SpriteBatch;
|
||||||
|
use itertools::Itertools;
|
||||||
use specs::{Join, Read, ReadStorage, System};
|
use specs::{Join, Read, ReadStorage, System};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
@ -31,7 +34,7 @@ impl RenderingSystem<'_> {
|
|||||||
.expect("expected drawing queued text");
|
.expect("expected drawing queued text");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image(&mut self, renderable: &Renderable, delta: Duration) -> Image {
|
pub fn get_image(&mut self, renderable: &Renderable, delta: Duration) -> String {
|
||||||
let path_index = match renderable.kind() {
|
let path_index = match renderable.kind() {
|
||||||
RenderableKind::Static => {
|
RenderableKind::Static => {
|
||||||
// We only have one image, so we just return that
|
// We only have one image, so we just return that
|
||||||
@ -47,9 +50,7 @@ impl RenderingSystem<'_> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let image_path = renderable.path(path_index);
|
renderable.path(path_index)
|
||||||
|
|
||||||
Image::new(self.context, image_path).expect("expected image")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,27 +68,52 @@ impl<'a> System<'a> for RenderingSystem<'a> {
|
|||||||
// Clear the screen/set the background
|
// Clear the screen/set the background
|
||||||
graphics::clear(self.context, graphics::Color::new(0.95, 0.95, 0.95, 1.0));
|
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
|
// Get all the renderables with their positions
|
||||||
// This will allow us to have entities layered visually.
|
let rendering_data = (&positions, &renderables).join().collect::<Vec<_>>();
|
||||||
let mut rendering_data = (&positions, &renderables).join().collect::<Vec<_>>();
|
let mut rendering_batches: HashMap<u8, HashMap<String, Vec<DrawParam>>> = HashMap::new();
|
||||||
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
|
// Iterate through all paris of positions & renderables, load the image
|
||||||
// and draw it at the specified position.
|
// and draw it at the specified position.
|
||||||
for (position, renderable) in rendering_data.iter() {
|
for (position, renderable) in rendering_data.iter() {
|
||||||
// Load the image
|
// Load the image
|
||||||
let image = self.get_image(renderable, time.delta);
|
let image_path = self.get_image(renderable, time.delta);
|
||||||
let x = position.x as f32 * TILE_WIDTH;
|
let x = position.x as f32 * TILE_WIDTH;
|
||||||
let y = position.y as f32 * TILE_WIDTH;
|
let y = position.y as f32 * TILE_WIDTH;
|
||||||
|
let z = position.z;
|
||||||
|
|
||||||
// draw
|
// Add to rendering batches
|
||||||
let draw_params = DrawParam::new().dest(na::Point2::new(x, y));
|
let draw_param = DrawParam::new().dest(na::Point2::new(x, y));
|
||||||
graphics::draw(self.context, &image, draw_params).expect("expected render");
|
rendering_batches
|
||||||
|
.entry(z)
|
||||||
|
.or_default()
|
||||||
|
.entry(image_path)
|
||||||
|
.or_default()
|
||||||
|
.push(draw_param);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate spritebatches ordered by z and actually render each of them
|
||||||
|
for (_z, group) in rendering_batches
|
||||||
|
.iter()
|
||||||
|
.sorted_by(|a, b| Ord::cmp(&a.0, &b.0)) {
|
||||||
|
|
||||||
|
for (image_path, draw_params) in group {
|
||||||
|
let image = Image::new(self.context, image_path).expect("expected image");
|
||||||
|
let mut sprite_batch = SpriteBatch::new(image);
|
||||||
|
|
||||||
|
for draw_param in draw_params.iter() {
|
||||||
|
sprite_batch.add(*draw_param);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::draw(self.context, &sprite_batch, graphics::DrawParam::new())
|
||||||
|
.expect("expected render");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render any text
|
// Render any text
|
||||||
self.draw_text(&gameplay.state.to_string(), 525.0, 80.0);
|
self.draw_text(&gameplay.state.to_string(), 525.0, 80.0);
|
||||||
self.draw_text(&gameplay.moves_count.to_string(), 525.0, 100.0);
|
self.draw_text(&gameplay.moves_count.to_string(), 525.0, 100.0);
|
||||||
|
let fps = format!("FPS: {:.0}", timer::fps(self.context));
|
||||||
|
self.draw_text(&fps, 525.0, 120.0);
|
||||||
|
|
||||||
// Finally, present the context, this will actually display everything
|
// Finally, present the context, this will actually display everything
|
||||||
// on the screen.
|
// on the screen.
|
||||||
|
Loading…
Reference in New Issue
Block a user