From 5b94a0d5a9d108ba45c164ae67b827a819766dba Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Mon, 27 Jul 2020 10:52:48 -0400 Subject: [PATCH] Complete 3.4 Batch rendering --- Cargo.toml | 3 +- src/systems/rendering_system.rs | 52 ++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9fb6709..b192b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" [dependencies] ggez = "0.5.1" -specs = { version="0.16.1", features=["specs-derive"] } \ No newline at end of file +specs = { version="0.16.1", features=["specs-derive"] } +itertools = "0.9.0" \ No newline at end of file diff --git a/src/systems/rendering_system.rs b/src/systems/rendering_system.rs index f3fba17..d19a34f 100644 --- a/src/systems/rendering_system.rs +++ b/src/systems/rendering_system.rs @@ -1,9 +1,12 @@ use ggez::graphics::Image; use ggez::graphics::{Color, DrawParam}; -use ggez::nalgebra as na; +use ggez::{nalgebra as na, timer}; use ggez::{graphics, Context}; +use ggez::graphics::spritebatch::SpriteBatch; +use itertools::Itertools; use specs::{Join, Read, ReadStorage, System}; +use std::collections::HashMap; use std::time::Duration; use crate::components::*; @@ -31,7 +34,7 @@ impl RenderingSystem<'_> { .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() { RenderableKind::Static => { // We only have one image, so we just return that @@ -47,9 +50,7 @@ impl RenderingSystem<'_> { } }; - let image_path = renderable.path(path_index); - - Image::new(self.context, image_path).expect("expected image") + renderable.path(path_index) } } @@ -67,27 +68,52 @@ impl<'a> System<'a> for RenderingSystem<'a> { // 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::>(); - rendering_data.sort_by(|&a, &b| a.0.z.partial_cmp(&b.0.z).expect("expected comparison")); + // Get all the renderables with their positions + let rendering_data = (&positions, &renderables).join().collect::>(); + let mut rendering_batches: HashMap>> = HashMap::new(); // 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 - 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 y = position.y as f32 * TILE_WIDTH; + let z = position.z; - // draw - let draw_params = DrawParam::new().dest(na::Point2::new(x, y)); - graphics::draw(self.context, &image, draw_params).expect("expected render"); + // Add to rendering batches + let draw_param = DrawParam::new().dest(na::Point2::new(x, y)); + 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 self.draw_text(&gameplay.state.to_string(), 525.0, 80.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 // on the screen.