mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-10 16:07:57 -06:00
refactor: update debug state management and rendering systems
This commit is contained in:
@@ -251,14 +251,13 @@ impl Game {
|
|||||||
backbuffer: NonSendMut<BackbufferResource>,
|
backbuffer: NonSendMut<BackbufferResource>,
|
||||||
debug_state: Res<DebugState>,
|
debug_state: Res<DebugState>,
|
||||||
mut dirty: ResMut<RenderDirty>| {
|
mut dirty: ResMut<RenderDirty>| {
|
||||||
if dirty.0 || *debug_state != DebugState::Off {
|
if dirty.0 || debug_state.enabled {
|
||||||
// Only copy backbuffer to main canvas if debug rendering is off
|
// Only copy backbuffer to main canvas if debug rendering is off
|
||||||
// (debug rendering draws directly to main canvas)
|
// (debug rendering draws directly to main canvas)
|
||||||
if *debug_state == DebugState::Off {
|
if !debug_state.enabled {
|
||||||
canvas.copy(&backbuffer.0, None, None).unwrap();
|
canvas.present();
|
||||||
}
|
}
|
||||||
dirty.0 = false;
|
dirty.0 = false;
|
||||||
canvas.present();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -16,22 +16,13 @@ use sdl2::render::{Canvas, Texture, TextureCreator};
|
|||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
use sdl2::video::{Window, WindowContext};
|
use sdl2::video::{Window, WindowContext};
|
||||||
|
|
||||||
#[derive(Resource, Default, Debug, Copy, Clone, PartialEq)]
|
#[derive(Resource, Default, Debug, Copy, Clone)]
|
||||||
pub enum DebugState {
|
pub struct DebugState {
|
||||||
#[default]
|
pub enabled: bool,
|
||||||
Off,
|
|
||||||
Graph,
|
|
||||||
Collision,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugState {
|
fn f32_to_u8(value: f32) -> u8 {
|
||||||
pub fn next(&self) -> Self {
|
(value * 255.0) as u8
|
||||||
match self {
|
|
||||||
DebugState::Off => DebugState::Graph,
|
|
||||||
DebugState::Graph => DebugState::Collision,
|
|
||||||
DebugState::Collision => DebugState::Off,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resource to hold the debug texture for persistent rendering
|
/// Resource to hold the debug texture for persistent rendering
|
||||||
@@ -110,7 +101,7 @@ pub fn debug_render_system(
|
|||||||
colliders: Query<(&Collider, &Position)>,
|
colliders: Query<(&Collider, &Position)>,
|
||||||
cursor: Res<CursorPosition>,
|
cursor: Res<CursorPosition>,
|
||||||
) {
|
) {
|
||||||
if *debug_state == DebugState::Off {
|
if !debug_state.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let scale =
|
let scale =
|
||||||
@@ -140,79 +131,86 @@ pub fn debug_render_system(
|
|||||||
// Draw debug info on the high-resolution debug texture
|
// Draw debug info on the high-resolution debug texture
|
||||||
canvas
|
canvas
|
||||||
.with_texture_canvas(&mut debug_texture.0, |debug_canvas| {
|
.with_texture_canvas(&mut debug_texture.0, |debug_canvas| {
|
||||||
match *debug_state {
|
// Find the closest node to the cursor
|
||||||
DebugState::Graph => {
|
|
||||||
// Find the closest node to the cursor
|
|
||||||
|
|
||||||
let closest_node = if let Some(cursor_world_pos) = cursor_world_pos {
|
let closest_node = if let Some(cursor_world_pos) = cursor_world_pos {
|
||||||
map.graph
|
map.graph
|
||||||
.nodes()
|
.nodes()
|
||||||
.map(|node| node.position.distance(cursor_world_pos))
|
.map(|node| node.position.distance(cursor_world_pos))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Less))
|
.min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Less))
|
||||||
.map(|(id, _)| id)
|
.map(|(id, _)| id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
debug_canvas.set_draw_color(Color::GREEN);
|
||||||
|
for (collider, position) in colliders.iter() {
|
||||||
|
let pos = position.get_pixel_position(&map.graph).unwrap();
|
||||||
|
|
||||||
|
// Transform position and size using common methods
|
||||||
|
let pos = (pos * scale).as_ivec2();
|
||||||
|
let size = (collider.size * scale) as u32;
|
||||||
|
|
||||||
|
let rect = Rect::from_center(Point::from((pos.x, pos.y)), size, size);
|
||||||
|
debug_canvas.draw_rect(rect).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_canvas.set_draw_color(Color {
|
||||||
|
a: f32_to_u8(0.4),
|
||||||
|
..Color::RED
|
||||||
|
});
|
||||||
|
debug_canvas.set_blend_mode(sdl2::render::BlendMode::Blend);
|
||||||
|
for (start_node, end_node) in map.graph.edges() {
|
||||||
|
let start_node_model = map.graph.get_node(start_node).unwrap();
|
||||||
|
let end_node = map.graph.get_node(end_node.target).unwrap().position;
|
||||||
|
|
||||||
|
// Transform positions using common method
|
||||||
|
let start = transform_position_with_offset(start_node_model.position, scale);
|
||||||
|
let end = transform_position_with_offset(end_node, scale);
|
||||||
|
|
||||||
|
debug_canvas
|
||||||
|
.draw_line(Point::from((start.x, start.y)), Point::from((end.x, end.y)))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id, node) in map.graph.nodes().enumerate() {
|
||||||
|
let pos = node.position;
|
||||||
|
|
||||||
|
// Set color based on whether the node is the closest to the cursor
|
||||||
|
debug_canvas.set_draw_color(Color {
|
||||||
|
a: f32_to_u8(if Some(id) == closest_node { 0.75 } else { 0.6 }),
|
||||||
|
..(if Some(id) == closest_node {
|
||||||
|
Color::YELLOW
|
||||||
} else {
|
} else {
|
||||||
None
|
Color::BLUE
|
||||||
};
|
})
|
||||||
|
});
|
||||||
|
|
||||||
debug_canvas.set_draw_color(Color::RED);
|
// Transform position using common method
|
||||||
for (start_node, end_node) in map.graph.edges() {
|
let pos = transform_position_with_offset(pos, scale);
|
||||||
let start_node_model = map.graph.get_node(start_node).unwrap();
|
let size = (2.0 * scale) as u32;
|
||||||
let end_node = map.graph.get_node(end_node.target).unwrap().position;
|
|
||||||
|
|
||||||
// Transform positions using common method
|
debug_canvas
|
||||||
let start = transform_position_with_offset(start_node_model.position, scale);
|
.fill_rect(Rect::new(pos.x - (size as i32 / 2), pos.y - (size as i32 / 2), size, size))
|
||||||
let end = transform_position_with_offset(end_node, scale);
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
debug_canvas
|
// Render node ID if a node is highlighted
|
||||||
.draw_line(Point::from((start.x, start.y)), Point::from((end.x, end.y)))
|
if let Some(closest_node_id) = closest_node {
|
||||||
.unwrap();
|
let node = map.graph.get_node(closest_node_id).unwrap();
|
||||||
}
|
let pos = transform_position_with_offset(node.position, scale);
|
||||||
|
|
||||||
for (id, node) in map.graph.nodes().enumerate() {
|
let surface = font
|
||||||
let pos = node.position;
|
.render(&closest_node_id.to_string())
|
||||||
|
.blended(Color {
|
||||||
// Set color based on whether the node is the closest to the cursor
|
a: f32_to_u8(0.4),
|
||||||
debug_canvas.set_draw_color(if Some(id) == closest_node {
|
..Color::WHITE
|
||||||
Color::YELLOW
|
})
|
||||||
} else {
|
.unwrap();
|
||||||
Color::BLUE
|
let texture = texture_creator.create_texture_from_surface(&surface).unwrap();
|
||||||
});
|
let dest = Rect::new(pos.x + 10, pos.y - 5, texture.query().width, texture.query().height);
|
||||||
|
debug_canvas.copy(&texture, None, dest).unwrap();
|
||||||
// Transform position using common method
|
|
||||||
let pos = transform_position_with_offset(pos, scale);
|
|
||||||
let size = (3.0 * scale) as u32;
|
|
||||||
|
|
||||||
debug_canvas
|
|
||||||
.fill_rect(Rect::new(pos.x - (size as i32 / 2), pos.y - (size as i32 / 2), size, size))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render node ID if a node is highlighted
|
|
||||||
if let Some(closest_node_id) = closest_node {
|
|
||||||
let node = map.graph.get_node(closest_node_id).unwrap();
|
|
||||||
let pos = transform_position_with_offset(node.position, scale);
|
|
||||||
|
|
||||||
let surface = font.render(&closest_node_id.to_string()).blended(Color::WHITE).unwrap();
|
|
||||||
let texture = texture_creator.create_texture_from_surface(&surface).unwrap();
|
|
||||||
let dest = Rect::new(pos.x + 10, pos.y - 5, texture.query().width, texture.query().height);
|
|
||||||
debug_canvas.copy(&texture, None, dest).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DebugState::Collision => {
|
|
||||||
debug_canvas.set_draw_color(Color::GREEN);
|
|
||||||
for (collider, position) in colliders.iter() {
|
|
||||||
let pos = position.get_pixel_position(&map.graph).unwrap();
|
|
||||||
|
|
||||||
// Transform position and size using common methods
|
|
||||||
let pos = (pos * scale).as_ivec2();
|
|
||||||
let size = (collider.size * scale) as u32;
|
|
||||||
|
|
||||||
let rect = Rect::from_center(Point::from((pos.x, pos.y)), size, size);
|
|
||||||
debug_canvas.draw_rect(rect).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render timing information in the top-left corner
|
// Render timing information in the top-left corner
|
||||||
@@ -222,4 +220,5 @@ pub fn debug_render_system(
|
|||||||
|
|
||||||
// Draw the debug texture directly onto the main canvas at full resolution
|
// Draw the debug texture directly onto the main canvas at full resolution
|
||||||
canvas.copy(&debug_texture.0, None, None).unwrap();
|
canvas.copy(&debug_texture.0, None, None).unwrap();
|
||||||
|
canvas.present();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ pub fn player_control_system(
|
|||||||
state.exit = true;
|
state.exit = true;
|
||||||
}
|
}
|
||||||
GameCommand::ToggleDebug => {
|
GameCommand::ToggleDebug => {
|
||||||
*debug_state = debug_state.next();
|
debug_state.enabled = !debug_state.enabled;
|
||||||
}
|
}
|
||||||
GameCommand::MuteAudio => {
|
GameCommand::MuteAudio => {
|
||||||
audio_state.muted = !audio_state.muted;
|
audio_state.muted = !audio_state.muted;
|
||||||
|
|||||||
@@ -120,4 +120,6 @@ pub fn render_system(
|
|||||||
})
|
})
|
||||||
.err()
|
.err()
|
||||||
.map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
|
.map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
|
||||||
|
|
||||||
|
canvas.copy(&backbuffer.0, None, None).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ fn create_test_world() -> World {
|
|||||||
|
|
||||||
// Add resources
|
// Add resources
|
||||||
world.insert_resource(GlobalState { exit: false });
|
world.insert_resource(GlobalState { exit: false });
|
||||||
world.insert_resource(DebugState::Off);
|
world.insert_resource(DebugState::default());
|
||||||
world.insert_resource(AudioState::default());
|
world.insert_resource(AudioState::default());
|
||||||
world.insert_resource(DeltaTime(1.0 / 60.0)); // 60 FPS
|
world.insert_resource(DeltaTime(1.0 / 60.0)); // 60 FPS
|
||||||
world.insert_resource(Events::<GameEvent>::default());
|
world.insert_resource(Events::<GameEvent>::default());
|
||||||
@@ -222,7 +222,7 @@ fn test_player_control_system_toggle_debug() {
|
|||||||
|
|
||||||
// Check that debug state changed
|
// Check that debug state changed
|
||||||
let debug_state = world.resource::<DebugState>();
|
let debug_state = world.resource::<DebugState>();
|
||||||
assert_eq!(*debug_state, DebugState::Graph);
|
assert_eq!(debug_state.enabled, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -565,7 +565,7 @@ fn test_player_state_persistence_across_systems() {
|
|||||||
let position = *query.single(&world).expect("Player should exist");
|
let position = *query.single(&world).expect("Player should exist");
|
||||||
|
|
||||||
// Check that the state changes persisted individually
|
// Check that the state changes persisted individually
|
||||||
assert_eq!(debug_state_after_toggle, DebugState::Graph, "Debug state should have toggled");
|
assert_eq!(debug_state_after_toggle.enabled, true, "Debug state should have toggled");
|
||||||
assert!(audio_muted_after_toggle, "Audio should be muted");
|
assert!(audio_muted_after_toggle, "Audio should be muted");
|
||||||
|
|
||||||
// Player position depends on actual map connectivity
|
// Player position depends on actual map connectivity
|
||||||
|
|||||||
Reference in New Issue
Block a user