mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-06 11:15:46 -06:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90adaf9e84 |
@@ -47,7 +47,7 @@ use crate::{
|
|||||||
constants,
|
constants,
|
||||||
events::GameCommand,
|
events::GameCommand,
|
||||||
map::render::MapRenderer,
|
map::render::MapRenderer,
|
||||||
systems::input::Bindings,
|
systems::{debug::CursorPosition, input::Bindings},
|
||||||
texture::sprite::{AtlasMapper, SpriteAtlas},
|
texture::sprite::{AtlasMapper, SpriteAtlas},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,6 +198,7 @@ impl Game {
|
|||||||
world.insert_resource(RenderDirty::default());
|
world.insert_resource(RenderDirty::default());
|
||||||
world.insert_resource(DebugState::default());
|
world.insert_resource(DebugState::default());
|
||||||
world.insert_resource(AudioState::default());
|
world.insert_resource(AudioState::default());
|
||||||
|
world.insert_resource(CursorPosition::default());
|
||||||
|
|
||||||
world.add_observer(
|
world.add_observer(
|
||||||
|event: Trigger<GameEvent>, mut state: ResMut<GlobalState>, _score: ResMut<ScoreResource>| {
|
|event: Trigger<GameEvent>, mut state: ResMut<GlobalState>, _score: ResMut<ScoreResource>| {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//! Debug rendering system
|
//! Debug rendering system
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::constants::BOARD_PIXEL_OFFSET;
|
use crate::constants::BOARD_PIXEL_OFFSET;
|
||||||
use crate::map::builder::Map;
|
use crate::map::builder::Map;
|
||||||
use crate::systems::components::Collider;
|
use crate::systems::components::Collider;
|
||||||
@@ -6,11 +8,15 @@ use crate::systems::movement::Position;
|
|||||||
use crate::systems::profiling::SystemTimings;
|
use crate::systems::profiling::SystemTimings;
|
||||||
use crate::systems::render::BackbufferResource;
|
use crate::systems::render::BackbufferResource;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
|
use glam::Vec2;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use sdl2::render::{Canvas, Texture, TextureCreator};
|
use sdl2::render::{Canvas, Texture, TextureCreator};
|
||||||
use sdl2::video::{Window, WindowContext};
|
use sdl2::video::{Window, WindowContext};
|
||||||
|
|
||||||
|
#[derive(Resource, Default, Debug, Copy, Clone)]
|
||||||
|
pub struct CursorPosition(pub Vec2);
|
||||||
|
|
||||||
#[derive(Resource, Default, Debug, Copy, Clone, PartialEq)]
|
#[derive(Resource, Default, Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum DebugState {
|
pub enum DebugState {
|
||||||
#[default]
|
#[default]
|
||||||
@@ -36,10 +42,13 @@ pub struct DebugTextureResource(pub Texture<'static>);
|
|||||||
fn transform_position(pos: (f32, f32), output_size: (u32, u32), logical_size: (u32, u32)) -> (i32, i32) {
|
fn transform_position(pos: (f32, f32), output_size: (u32, u32), logical_size: (u32, u32)) -> (i32, i32) {
|
||||||
let scale_x = output_size.0 as f32 / logical_size.0 as f32;
|
let scale_x = output_size.0 as f32 / logical_size.0 as f32;
|
||||||
let scale_y = output_size.1 as f32 / logical_size.1 as f32;
|
let scale_y = output_size.1 as f32 / logical_size.1 as f32;
|
||||||
let scale = scale_x.min(scale_y); // Use the smaller scale to maintain aspect ratio
|
let scale = scale_x.min(scale_y);
|
||||||
|
|
||||||
let x = (pos.0 * scale) as i32;
|
let offset_x = (output_size.0 as f32 - logical_size.0 as f32 * scale) / 2.0;
|
||||||
let y = (pos.1 * scale) as i32;
|
let offset_y = (output_size.1 as f32 - logical_size.1 as f32 * scale) / 2.0;
|
||||||
|
|
||||||
|
let x = (pos.0 * scale + offset_x) as i32;
|
||||||
|
let y = (pos.1 * scale + offset_y) as i32;
|
||||||
(x, y)
|
(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,10 +56,13 @@ fn transform_position(pos: (f32, f32), output_size: (u32, u32), logical_size: (u
|
|||||||
fn transform_position_with_offset(pos: (f32, f32), output_size: (u32, u32), logical_size: (u32, u32)) -> (i32, i32) {
|
fn transform_position_with_offset(pos: (f32, f32), output_size: (u32, u32), logical_size: (u32, u32)) -> (i32, i32) {
|
||||||
let scale_x = output_size.0 as f32 / logical_size.0 as f32;
|
let scale_x = output_size.0 as f32 / logical_size.0 as f32;
|
||||||
let scale_y = output_size.1 as f32 / logical_size.1 as f32;
|
let scale_y = output_size.1 as f32 / logical_size.1 as f32;
|
||||||
let scale = scale_x.min(scale_y); // Use the smaller scale to maintain aspect ratio
|
let scale = scale_x.min(scale_y);
|
||||||
|
|
||||||
let x = ((pos.0 + BOARD_PIXEL_OFFSET.x as f32) * scale) as i32;
|
let offset_x = (output_size.0 as f32 - logical_size.0 as f32 * scale) / 2.0;
|
||||||
let y = ((pos.1 + BOARD_PIXEL_OFFSET.y as f32) * scale) as i32;
|
let offset_y = (output_size.1 as f32 - logical_size.1 as f32 * scale) / 2.0;
|
||||||
|
|
||||||
|
let x = ((pos.0 + BOARD_PIXEL_OFFSET.x as f32) * scale + offset_x) as i32;
|
||||||
|
let y = ((pos.1 + BOARD_PIXEL_OFFSET.y as f32) * scale + offset_y) as i32;
|
||||||
(x, y)
|
(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +141,7 @@ pub fn debug_render_system(
|
|||||||
timings: Res<SystemTimings>,
|
timings: Res<SystemTimings>,
|
||||||
map: Res<Map>,
|
map: Res<Map>,
|
||||||
colliders: Query<(&Collider, &Position)>,
|
colliders: Query<(&Collider, &Position)>,
|
||||||
|
cursor: Res<CursorPosition>,
|
||||||
) {
|
) {
|
||||||
if *debug_state == DebugState::Off {
|
if *debug_state == DebugState::Off {
|
||||||
return;
|
return;
|
||||||
@@ -153,28 +166,49 @@ pub fn debug_render_system(
|
|||||||
// Get texture creator before entering the closure to avoid borrowing conflicts
|
// Get texture creator before entering the closure to avoid borrowing conflicts
|
||||||
let mut texture_creator = canvas.texture_creator();
|
let mut texture_creator = canvas.texture_creator();
|
||||||
|
|
||||||
|
let cursor_world_pos = cursor.0 - BOARD_PIXEL_OFFSET.as_vec2();
|
||||||
|
|
||||||
// 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 {
|
match *debug_state {
|
||||||
DebugState::Graph => {
|
DebugState::Graph => {
|
||||||
|
// Find the closest node to the cursor
|
||||||
|
|
||||||
|
let closest_node = map
|
||||||
|
.graph
|
||||||
|
.nodes()
|
||||||
|
.map(|node| node.position.distance(cursor_world_pos))
|
||||||
|
.enumerate()
|
||||||
|
.min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Less))
|
||||||
|
.map(|(id, _)| id);
|
||||||
|
|
||||||
debug_canvas.set_draw_color(Color::RED);
|
debug_canvas.set_draw_color(Color::RED);
|
||||||
for (start_node, end_node) in map.graph.edges() {
|
for (start_node, end_node) in map.graph.edges() {
|
||||||
let start_node = map.graph.get_node(start_node).unwrap().position;
|
let start_node_model = map.graph.get_node(start_node).unwrap();
|
||||||
let end_node = map.graph.get_node(end_node.target).unwrap().position;
|
let end_node = map.graph.get_node(end_node.target).unwrap().position;
|
||||||
|
|
||||||
// Transform positions using common method
|
// Transform positions using common method
|
||||||
let (start_x, start_y) =
|
let (start_x, start_y) = transform_position_with_offset(
|
||||||
transform_position_with_offset((start_node.x, start_node.y), output_size, logical_size);
|
(start_node_model.position.x, start_node_model.position.y),
|
||||||
|
output_size,
|
||||||
|
logical_size,
|
||||||
|
);
|
||||||
let (end_x, end_y) = transform_position_with_offset((end_node.x, end_node.y), output_size, logical_size);
|
let (end_x, end_y) = transform_position_with_offset((end_node.x, end_node.y), output_size, logical_size);
|
||||||
|
|
||||||
debug_canvas.draw_line((start_x, start_y), (end_x, end_y)).unwrap();
|
debug_canvas.draw_line((start_x, start_y), (end_x, end_y)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_canvas.set_draw_color(Color::BLUE);
|
for (id, node) in map.graph.nodes().enumerate() {
|
||||||
for node in map.graph.nodes() {
|
|
||||||
let pos = node.position;
|
let pos = node.position;
|
||||||
|
|
||||||
|
// Set color based on whether the node is the closest to the cursor
|
||||||
|
if Some(id) == closest_node {
|
||||||
|
debug_canvas.set_draw_color(Color::YELLOW);
|
||||||
|
} else {
|
||||||
|
debug_canvas.set_draw_color(Color::BLUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Transform position using common method
|
// Transform position using common method
|
||||||
let (x, y) = transform_position_with_offset((pos.x, pos.y), output_size, logical_size);
|
let (x, y) = transform_position_with_offset((pos.x, pos.y), output_size, logical_size);
|
||||||
let size = transform_size(4.0, output_size, logical_size);
|
let size = transform_size(4.0, output_size, logical_size);
|
||||||
@@ -201,6 +235,28 @@ pub fn debug_render_system(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render node ID if a node is highlighted
|
||||||
|
if let DebugState::Graph = *debug_state {
|
||||||
|
if let Some(closest_node_id) = map
|
||||||
|
.graph
|
||||||
|
.nodes()
|
||||||
|
.map(|node| node.position.distance(cursor_world_pos))
|
||||||
|
.enumerate()
|
||||||
|
.min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Less))
|
||||||
|
.map(|(id, _)| id)
|
||||||
|
{
|
||||||
|
let node = map.graph.get_node(closest_node_id).unwrap();
|
||||||
|
let (x, y) = transform_position_with_offset((node.position.x, node.position.y), output_size, logical_size);
|
||||||
|
|
||||||
|
let ttf_context = sdl2::ttf::init().unwrap();
|
||||||
|
let font = ttf_context.load_font("assets/site/TerminalVector.ttf", 12).unwrap();
|
||||||
|
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(x + 10, y - 5, texture.query().width, texture.query().height);
|
||||||
|
debug_canvas.copy(&texture, None, dest).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Render timing information in the top-left corner
|
// Render timing information in the top-left corner
|
||||||
render_timing_display(debug_canvas, &mut texture_creator, &timings);
|
render_timing_display(debug_canvas, &mut texture_creator, &timings);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ use bevy_ecs::{
|
|||||||
resource::Resource,
|
resource::Resource,
|
||||||
system::{NonSendMut, ResMut},
|
system::{NonSendMut, ResMut},
|
||||||
};
|
};
|
||||||
|
use glam::Vec2;
|
||||||
use sdl2::{event::Event, keyboard::Keycode, EventPump};
|
use sdl2::{event::Event, keyboard::Keycode, EventPump};
|
||||||
|
|
||||||
|
use crate::systems::debug::CursorPosition;
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::direction::Direction,
|
entity::direction::Direction,
|
||||||
events::{GameCommand, GameEvent},
|
events::{GameCommand, GameEvent},
|
||||||
@@ -64,6 +66,7 @@ pub fn input_system(
|
|||||||
mut bindings: ResMut<Bindings>,
|
mut bindings: ResMut<Bindings>,
|
||||||
mut writer: EventWriter<GameEvent>,
|
mut writer: EventWriter<GameEvent>,
|
||||||
mut pump: NonSendMut<&'static mut EventPump>,
|
mut pump: NonSendMut<&'static mut EventPump>,
|
||||||
|
mut cursor: ResMut<CursorPosition>,
|
||||||
) {
|
) {
|
||||||
let mut movement_key_pressed = false;
|
let mut movement_key_pressed = false;
|
||||||
|
|
||||||
@@ -72,6 +75,9 @@ pub fn input_system(
|
|||||||
Event::Quit { .. } => {
|
Event::Quit { .. } => {
|
||||||
writer.write(GameEvent::Command(GameCommand::Exit));
|
writer.write(GameEvent::Command(GameCommand::Exit));
|
||||||
}
|
}
|
||||||
|
Event::MouseMotion { x, y, .. } => {
|
||||||
|
cursor.0 = Vec2::new(x as f32, y as f32);
|
||||||
|
}
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
repeat: false,
|
repeat: false,
|
||||||
keycode: Some(key),
|
keycode: Some(key),
|
||||||
|
|||||||
@@ -126,19 +126,6 @@ impl Position {
|
|||||||
Position::Moving { from, .. } => *from,
|
Position::Moving { from, .. } => *from,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `NodeId` of the destination node, if currently traveling.
|
|
||||||
pub fn target_node(&self) -> Option<NodeId> {
|
|
||||||
match self {
|
|
||||||
Position::Stopped { .. } => None,
|
|
||||||
Position::Moving { to, .. } => Some(*to),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the entity is traveling between nodes.
|
|
||||||
pub fn is_moving(&self) -> bool {
|
|
||||||
matches!(self, Position::Moving { .. })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn movement_system(
|
// pub fn movement_system(
|
||||||
|
|||||||
Reference in New Issue
Block a user