feat: separate dirty rendering with flag resource

This commit is contained in:
2025-08-15 14:19:39 -05:00
parent 2f0c734d13
commit b88895e82f
3 changed files with 23 additions and 8 deletions

View File

@@ -14,13 +14,13 @@ use crate::systems::{
collision::collision_system, collision::collision_system,
components::{ components::{
Collider, CollisionLayer, DeltaTime, DirectionalAnimated, EntityType, GlobalState, ItemBundle, ItemCollider, Collider, CollisionLayer, DeltaTime, DirectionalAnimated, EntityType, GlobalState, ItemBundle, ItemCollider,
PacmanCollider, PlayerBundle, PlayerControlled, Renderable, Score, ScoreResource, PacmanCollider, PlayerBundle, PlayerControlled, RenderDirty, Renderable, Score, ScoreResource,
}, },
control::player_system, control::player_system,
input::input_system, input::input_system,
movement::movement_system, movement::movement_system,
profiling::{profile, SystemTimings}, 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 crate::texture::animated::AnimatedTexture;
use bevy_ecs::schedule::IntoScheduleConfigs; use bevy_ecs::schedule::IntoScheduleConfigs;
@@ -175,6 +175,7 @@ impl Game {
world.insert_resource(SystemTimings::default()); world.insert_resource(SystemTimings::default());
world.insert_resource(Bindings::default()); world.insert_resource(Bindings::default());
world.insert_resource(DeltaTime(0f32)); world.insert_resource(DeltaTime(0f32));
world.insert_resource(RenderDirty::default());
world.add_observer( world.add_observer(
|event: Trigger<GameEvent>, mut state: ResMut<GlobalState>, _score: ResMut<ScoreResource>| match *event { |event: Trigger<GameEvent>, mut state: ResMut<GlobalState>, _score: ResMut<ScoreResource>| match *event {
@@ -199,7 +200,7 @@ impl Game {
) )
.chain(), .chain(),
); );
schedule.add_systems(profile("render", render_system)); schedule.add_systems((profile("dirty_render", dirty_render_system), profile("render", render_system)).chain());
// Spawn player // Spawn player
world.spawn(player); world.spawn(player);

View File

@@ -109,3 +109,6 @@ pub struct ScoreResource(pub u32);
#[derive(Resource)] #[derive(Resource)]
pub struct DeltaTime(pub f32); pub struct DeltaTime(pub f32);
#[derive(Resource, Default)]
pub struct RenderDirty(pub bool);

View File

@@ -1,15 +1,25 @@
use crate::error::{GameError, TextureError}; use crate::error::{GameError, TextureError};
use crate::map::builder::Map; 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::systems::movement::{Movable, MovementState, Position};
use crate::texture::sprite::SpriteAtlas; use crate::texture::sprite::SpriteAtlas;
use bevy_ecs::entity::Entity; use bevy_ecs::entity::Entity;
use bevy_ecs::event::EventWriter; use bevy_ecs::event::EventWriter;
use bevy_ecs::prelude::{Changed, Or, RemovedComponents}; 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::render::{Canvas, Texture};
use sdl2::video::Window; use sdl2::video::Window;
pub fn dirty_render_system(
mut dirty: ResMut<RenderDirty>,
changed_renderables: Query<(), Or<(Changed<Renderable>, Changed<Position>)>>,
removed_renderables: RemovedComponents<Renderable>,
) {
if !changed_renderables.is_empty() || !removed_renderables.is_empty() {
dirty.0 = true;
}
}
/// Updates the directional animated texture of an entity. /// 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. /// 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<BackbufferResource>, mut backbuffer: NonSendMut<BackbufferResource>,
mut atlas: NonSendMut<SpriteAtlas>, mut atlas: NonSendMut<SpriteAtlas>,
map: Res<Map>, map: Res<Map>,
mut dirty: ResMut<RenderDirty>,
renderables: Query<(Entity, &Renderable, &Position)>, renderables: Query<(Entity, &Renderable, &Position)>,
changed_renderables: Query<(), Or<(Changed<Renderable>, Changed<Position>)>>,
removed_renderables: RemovedComponents<Renderable>,
mut errors: EventWriter<GameError>, mut errors: EventWriter<GameError>,
) { ) {
if changed_renderables.is_empty() && removed_renderables.is_empty() { if !dirty.0 {
return; return;
} }
// Clear the main canvas first // Clear the main canvas first
@@ -111,4 +120,6 @@ pub fn render_system(
.map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into())); .map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
canvas.present(); canvas.present();
dirty.0 = false;
} }