diff --git a/src/game/mod.rs b/src/game/mod.rs index a8d992d..ac1d83d 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -14,13 +14,13 @@ use crate::systems::{ collision::collision_system, components::{ Collider, CollisionLayer, DeltaTime, DirectionalAnimated, EntityType, GlobalState, ItemBundle, ItemCollider, - PacmanCollider, PlayerBundle, PlayerControlled, Renderable, Score, ScoreResource, + PacmanCollider, PlayerBundle, PlayerControlled, RenderDirty, Renderable, Score, ScoreResource, }, control::player_system, input::input_system, movement::movement_system, profiling::{profile, SystemTimings}, - render::{directional_render_system, render_system, BackbufferResource, MapTextureResource}, + render::{directional_render_system, dirty_render_system, render_system, BackbufferResource, MapTextureResource}, }; use crate::texture::animated::AnimatedTexture; use bevy_ecs::schedule::IntoScheduleConfigs; @@ -175,6 +175,7 @@ impl Game { world.insert_resource(SystemTimings::default()); world.insert_resource(Bindings::default()); world.insert_resource(DeltaTime(0f32)); + world.insert_resource(RenderDirty::default()); world.add_observer( |event: Trigger, mut state: ResMut, _score: ResMut| match *event { @@ -199,7 +200,7 @@ impl Game { ) .chain(), ); - schedule.add_systems(profile("render", render_system)); + schedule.add_systems((profile("dirty_render", dirty_render_system), profile("render", render_system)).chain()); // Spawn player world.spawn(player); diff --git a/src/systems/components.rs b/src/systems/components.rs index 847f033..2df22a0 100644 --- a/src/systems/components.rs +++ b/src/systems/components.rs @@ -109,3 +109,6 @@ pub struct ScoreResource(pub u32); #[derive(Resource)] pub struct DeltaTime(pub f32); + +#[derive(Resource, Default)] +pub struct RenderDirty(pub bool); diff --git a/src/systems/render.rs b/src/systems/render.rs index 1e73c66..23d64ea 100644 --- a/src/systems/render.rs +++ b/src/systems/render.rs @@ -1,15 +1,25 @@ use crate::error::{GameError, TextureError}; use crate::map::builder::Map; -use crate::systems::components::{DeltaTime, DirectionalAnimated, Renderable}; +use crate::systems::components::{DeltaTime, DirectionalAnimated, RenderDirty, Renderable}; use crate::systems::movement::{Movable, MovementState, Position}; use crate::texture::sprite::SpriteAtlas; use bevy_ecs::entity::Entity; use bevy_ecs::event::EventWriter; use bevy_ecs::prelude::{Changed, Or, RemovedComponents}; -use bevy_ecs::system::{NonSendMut, Query, Res}; +use bevy_ecs::system::{NonSendMut, Query, Res, ResMut}; use sdl2::render::{Canvas, Texture}; use sdl2::video::Window; +pub fn dirty_render_system( + mut dirty: ResMut, + changed_renderables: Query<(), Or<(Changed, Changed)>>, + removed_renderables: RemovedComponents, +) { + if !changed_renderables.is_empty() || !removed_renderables.is_empty() { + dirty.0 = true; + } +} + /// Updates the directional animated texture of an entity. /// /// This runs before the render system so it can update the sprite based on the current direction of travel, as well as whether the entity is moving. @@ -55,12 +65,11 @@ pub fn render_system( mut backbuffer: NonSendMut, mut atlas: NonSendMut, map: Res, + mut dirty: ResMut, renderables: Query<(Entity, &Renderable, &Position)>, - changed_renderables: Query<(), Or<(Changed, Changed)>>, - removed_renderables: RemovedComponents, mut errors: EventWriter, ) { - if changed_renderables.is_empty() && removed_renderables.is_empty() { + if !dirty.0 { return; } // Clear the main canvas first @@ -111,4 +120,6 @@ pub fn render_system( .map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into())); canvas.present(); + + dirty.0 = false; }