feat: create hud rendering system

This commit is contained in:
Ryan Walters
2025-08-27 22:43:57 -05:00
parent bf65c34b28
commit f14b3d38a4
4 changed files with 61 additions and 2 deletions

View File

@@ -25,7 +25,9 @@ use crate::systems::{
item::item_system,
player::player_control_system,
profiling::{profile, SystemTimings},
render::{directional_render_system, dirty_render_system, render_system, BackbufferResource, MapTextureResource},
render::{
directional_render_system, dirty_render_system, hud_render_system, render_system, BackbufferResource, MapTextureResource,
},
};
use crate::texture::animated::AnimatedTexture;
use bevy_ecs::event::EventRegistry;
@@ -243,6 +245,7 @@ impl Game {
profile(SystemId::Blinking, blinking_system),
profile(SystemId::DirectionalRender, directional_render_system),
profile(SystemId::DirtyRender, dirty_render_system),
profile(SystemId::HudRender, hud_render_system),
profile(SystemId::Render, render_system),
profile(SystemId::DebugRender, debug_render_system),
profile(

View File

@@ -27,6 +27,7 @@ pub enum SystemId {
Blinking,
DirectionalRender,
DirtyRender,
HudRender,
Render,
DebugRender,
Present,

View File

@@ -1,8 +1,9 @@
use crate::error::{GameError, TextureError};
use crate::map::builder::Map;
use crate::systems::components::{DeltaTime, DirectionalAnimated, RenderDirty, Renderable};
use crate::systems::components::{DeltaTime, DirectionalAnimated, RenderDirty, Renderable, ScoreResource};
use crate::systems::movement::{Position, Velocity};
use crate::texture::sprite::SpriteAtlas;
use crate::texture::text::TextTexture;
use bevy_ecs::entity::Entity;
use bevy_ecs::event::EventWriter;
use bevy_ecs::prelude::{Changed, Or, RemovedComponents};
@@ -61,6 +62,34 @@ pub struct MapTextureResource(pub Texture<'static>);
/// A non-send resource for the backbuffer texture. This just wraps the texture with a type so it can be differentiated when exposed as a resource.
pub struct BackbufferResource(pub Texture<'static>);
/// Renders the HUD (score, lives, etc.) on top of the game.
pub fn hud_render_system(
mut canvas: NonSendMut<&mut Canvas<Window>>,
mut atlas: NonSendMut<SpriteAtlas>,
score: Res<ScoreResource>,
mut errors: EventWriter<GameError>,
) {
let mut text_renderer = TextTexture::new(1.0);
// Render lives and high score text
let lives = 3; // TODO: Get from actual lives resource
let lives_text = format!("{lives}UP HIGH SCORE ");
let lives_position = glam::UVec2::new(4 + 8 * 3, 2); // x_offset + lives_offset * 8, y_offset
if let Err(e) = text_renderer.render(&mut canvas, &mut atlas, &lives_text, lives_position) {
errors.write(TextureError::RenderFailed(format!("Failed to render lives text: {}", e)).into());
}
// Render score text
let score_text = format!("{:02}", score.0);
let score_offset = 7 - (score_text.len() as i32);
let score_position = glam::UVec2::new(4 + 8 * score_offset as u32, 10); // x_offset + score_offset * 8, 8 + y_offset
if let Err(e) = text_renderer.render(&mut canvas, &mut atlas, &score_text, score_position) {
errors.write(TextureError::RenderFailed(format!("Failed to render score text: {}", e)).into());
}
}
#[allow(clippy::too_many_arguments)]
pub fn render_system(
mut canvas: NonSendMut<&mut Canvas<Window>>,

26
tests/hud.rs Normal file
View File

@@ -0,0 +1,26 @@
use bevy_ecs::{event::Events, world::World};
use pacman::{error::GameError, systems::components::ScoreResource};
fn create_test_world() -> World {
let mut world = World::new();
// Add required resources
world.insert_resource(Events::<GameError>::default());
world.insert_resource(ScoreResource(1230)); // Test score
world
}
#[test]
fn test_hud_render_system_runs_without_error() {
let world = create_test_world();
// The HUD render system requires SDL2 resources that aren't available in tests,
// but we can at least verify it doesn't panic when called
// In a real test environment, we'd need to mock the SDL2 canvas and atlas
// For now, just verify the score resource is accessible
let score = world.resource::<ScoreResource>();
assert_eq!(score.0, 1230);
}