feat: entity type for proper edge permission calculations

This commit is contained in:
2025-08-15 10:06:09 -05:00
parent b9bae99a4c
commit 730daed20a
4 changed files with 37 additions and 12 deletions

View File

@@ -8,7 +8,7 @@ use crate::error::{GameError, GameResult, TextureError};
use crate::events::GameEvent;
use crate::map::builder::Map;
use crate::systems::components::{
DeltaTime, DirectionalAnimated, GlobalState, PlayerBundle, PlayerControlled, Position, Renderable, Velocity,
DeltaTime, DirectionalAnimated, EntityType, GlobalState, PlayerBundle, PlayerControlled, Position, Renderable, Velocity,
};
use crate::systems::control::player_system;
use crate::systems::movement::movement_system;
@@ -143,6 +143,7 @@ impl Game {
textures,
stopped_textures,
},
entity_type: EntityType::Player,
};
world.insert_non_send_resource(atlas);

View File

@@ -11,6 +11,16 @@ use crate::{
#[derive(Default, Component)]
pub struct PlayerControlled;
/// A tag component denoting the type of entity.
#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum EntityType {
Player,
Ghost,
Pellet,
PowerPellet,
Wall,
}
/// A component for entities that have a sprite, with a layer for ordering.
///
/// This is intended to be modified by other entities allowing animation.
@@ -127,6 +137,7 @@ pub struct PlayerBundle {
pub velocity: Velocity,
pub sprite: Renderable,
pub directional_animated: DirectionalAnimated,
pub entity_type: EntityType,
}
#[derive(Resource)]

View File

@@ -1,21 +1,25 @@
use crate::entity::graph::EdgePermissions;
use crate::entity::graph::{Edge, EdgePermissions, Graph};
use crate::error::{EntityError, GameError};
use crate::map::builder::Map;
use crate::systems::components::{DeltaTime, PlayerControlled, Position, Velocity};
use crate::systems::components::{DeltaTime, EntityType, Position, Velocity};
use bevy_ecs::event::EventWriter;
use bevy_ecs::system::{Query, Res};
fn can_traverse(_player: &mut PlayerControlled, edge: crate::entity::graph::Edge) -> bool {
matches!(edge.permissions, EdgePermissions::All)
fn can_traverse(entity_type: EntityType, edge: Edge) -> bool {
match entity_type {
EntityType::Player => matches!(edge.permissions, EdgePermissions::All),
EntityType::Ghost => matches!(edge.permissions, EdgePermissions::All | EdgePermissions::GhostsOnly),
_ => matches!(edge.permissions, EdgePermissions::All),
}
}
pub fn movement_system(
map: Res<Map>,
delta_time: Res<DeltaTime>,
mut entities: Query<(&mut PlayerControlled, &mut Velocity, &mut Position)>,
mut entities: Query<(&mut Velocity, &mut Position, &EntityType)>,
mut errors: EventWriter<GameError>,
) {
for (mut player, mut velocity, mut position) in entities.iter_mut() {
for (mut velocity, mut position, entity_type) in entities.iter_mut() {
let distance = velocity.speed * 60.0 * delta_time.0;
// Decrement the remaining frames for the next direction
@@ -32,7 +36,7 @@ pub fn movement_system(
// We're not moving, but a buffered direction is available.
if let Some((next_direction, _)) = velocity.next_direction {
if let Some(edge) = map.graph.find_edge_in_direction(node_id, next_direction) {
if can_traverse(&mut player, edge) {
if can_traverse(*entity_type, edge) {
// Start moving in that direction
*position = Position::BetweenNodes {
from: node_id,
@@ -90,7 +94,7 @@ pub fn movement_system(
// If we buffered a direction, try to find an edge in that direction
if let Some((next_dir, _)) = velocity.next_direction {
if let Some(edge) = map.graph.find_edge_in_direction(to, next_dir) {
if can_traverse(&mut player, edge) {
if can_traverse(*entity_type, edge) {
*position = Position::BetweenNodes {
from: to,
to: edge.target,
@@ -107,7 +111,7 @@ pub fn movement_system(
// If we didn't move, try to continue in the current direction
if !moved {
if let Some(edge) = map.graph.find_edge_in_direction(to, velocity.direction) {
if can_traverse(&mut player, edge) {
if can_traverse(*entity_type, edge) {
*position = Position::BetweenNodes {
from: to,
to: edge.target,

View File

@@ -9,6 +9,8 @@ use sdl2::render::{Canvas, Texture};
use sdl2::video::Window;
/// 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.
pub fn directional_render_system(
dt: Res<DeltaTime>,
mut renderables: Query<(&Velocity, &mut DirectionalAnimated, &mut Renderable, &Position)>,
@@ -34,7 +36,10 @@ pub fn directional_render_system(
}
}
/// A non-send resource for the map texture. This just wraps the texture with a type so it can be differentiated when exposed as a resource.
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>);
pub fn render_system(
@@ -43,7 +48,7 @@ pub fn render_system(
mut backbuffer: NonSendMut<BackbufferResource>,
mut atlas: NonSendMut<SpriteAtlas>,
map: Res<Map>,
mut renderables: Query<(Entity, &mut Renderable, &Position)>,
renderables: Query<(Entity, &mut Renderable, &Position)>,
mut errors: EventWriter<GameError>,
) {
// Clear the main canvas first
@@ -64,7 +69,11 @@ pub fn render_system(
.map(|e| errors.write(TextureError::RenderFailed(e.to_string()).into()));
// Render all entities to the backbuffer
for (_, mut renderable, position) in renderables.iter_mut() {
for (_, mut renderable, position) in renderables
// .iter_mut()
// .sort_by_key::<&mut Renderable, _, _>(|(renderable, renderable, renderable)| renderable.layer)
// .collect()
{
let pos = position.get_pixel_pos(&map.graph);
match pos {
Ok(pos) => {