From de86f383bfbd4097c1393ee38c7b85f0b2622334 Mon Sep 17 00:00:00 2001 From: Xevion Date: Fri, 15 Aug 2025 12:50:07 -0500 Subject: [PATCH] refactor: improve representation of movement system --- src/entity/graph.rs | 30 +++--- src/game/mod.rs | 25 +++-- src/map/builder.rs | 45 +------- src/systems/components.rs | 133 +++++++++++++---------- src/systems/control.rs | 14 +-- src/systems/movement.rs | 217 +++++++++++++++++++++----------------- src/systems/render.rs | 14 +-- tests/graph.rs | 12 +-- 8 files changed, 259 insertions(+), 231 deletions(-) diff --git a/src/entity/graph.rs b/src/entity/graph.rs index 0bf3021..e99ed67 100644 --- a/src/entity/graph.rs +++ b/src/entity/graph.rs @@ -4,14 +4,18 @@ use crate::systems::components::NodeId; use super::direction::Direction; -/// Defines who can traverse a given edge. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -pub enum EdgePermissions { - /// Anyone can use this edge. - #[default] - All, - /// Only ghosts can use this edge. - GhostsOnly, +use bitflags::bitflags; + +bitflags! { + /// Defines who can traverse a given edge using flags for fast checking. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] + pub struct TraversalFlags: u8 { + const PACMAN = 1 << 0; + const GHOST = 1 << 1; + + /// Convenience flag for edges that all entities can use + const ALL = Self::PACMAN.bits() | Self::GHOST.bits(); + } } /// Represents a directed edge from one node to another with a given weight (e.g., distance). @@ -24,7 +28,7 @@ pub struct Edge { /// The cardinal direction of this edge. pub direction: Direction, /// Defines who is allowed to traverse this edge. - pub permissions: EdgePermissions, + pub traversal_flags: TraversalFlags, } /// Represents a node in the graph, defined by its position. @@ -132,8 +136,8 @@ impl Graph { return Err("To node does not exist."); } - let edge_a = self.add_edge(from, to, replace, distance, direction, EdgePermissions::default()); - let edge_b = self.add_edge(to, from, replace, distance, direction.opposite(), EdgePermissions::default()); + let edge_a = self.add_edge(from, to, replace, distance, direction, TraversalFlags::ALL); + let edge_b = self.add_edge(to, from, replace, distance, direction.opposite(), TraversalFlags::ALL); if edge_a.is_err() && edge_b.is_err() { return Err("Failed to connect nodes in both directions."); @@ -161,7 +165,7 @@ impl Graph { replace: bool, distance: Option, direction: Direction, - permissions: EdgePermissions, + traversal_flags: TraversalFlags, ) -> Result<(), &'static str> { let edge = Edge { target: to, @@ -180,7 +184,7 @@ impl Graph { } }, direction, - permissions, + traversal_flags, }; if from >= self.adjacency_list.len() { diff --git a/src/game/mod.rs b/src/game/mod.rs index bff78bd..25d7ec6 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -12,8 +12,8 @@ use crate::systems::{ blinking::blinking_system, collision::collision_system, components::{ - Collider, CollisionLayer, DeltaTime, DirectionalAnimated, EntityType, GlobalState, ItemBundle, ItemCollider, - PacmanCollider, PlayerBundle, PlayerControlled, Position, Renderable, Score, ScoreResource, Velocity, + Collider, CollisionLayer, DeltaTime, DirectionalAnimated, EntityType, GlobalState, ItemBundle, ItemCollider, Movable, + MovementState, PacmanCollider, PlayerBundle, PlayerControlled, Position, Renderable, Score, ScoreResource, }, control::player_system, input::input_system, @@ -133,11 +133,15 @@ impl Game { let player = PlayerBundle { player: PlayerControlled, - position: Position::AtNode(pacman_start_node), - velocity: Velocity { - direction: Direction::Left, - next_direction: Some((Direction::Left, 90)), + position: Position { + node: pacman_start_node, + edge_progress: None, + }, + movement_state: MovementState::Stopped, + movable: Movable { speed: 1.15, + current_direction: Direction::Left, + requested_direction: Some(Direction::Left), // Start moving left immediately }, sprite: Renderable { sprite: SpriteAtlas::get_tile(&atlas, "pacman/full.png") @@ -170,14 +174,14 @@ impl Game { world.insert_resource(DeltaTime(0f32)); world.add_observer( - |event: Trigger, mut state: ResMut, mut score: ResMut| match *event { + |event: Trigger, mut state: ResMut, _score: ResMut| match *event { GameEvent::Command(command) => match command { GameCommand::Exit => { state.exit = true; } _ => {} }, - GameEvent::Collision(a, b) => {} + GameEvent::Collision(_a, _b) => {} }, ); @@ -218,7 +222,10 @@ impl Game { }; let mut item = world.spawn(ItemBundle { - position: Position::AtNode(node_id), + position: Position { + node: node_id, + edge_progress: None, + }, sprite: Renderable { sprite, layer: 1, diff --git a/src/map/builder.rs b/src/map/builder.rs index 4d39fa4..880d244 100644 --- a/src/map/builder.rs +++ b/src/map/builder.rs @@ -1,8 +1,7 @@ //! Map construction and building functionality. - use crate::constants::{MapTile, BOARD_CELL_SIZE, CELL_SIZE}; use crate::entity::direction::Direction; -use crate::entity::graph::{EdgePermissions, Graph, Node}; +use crate::entity::graph::{Graph, Node, TraversalFlags}; use crate::map::parser::MapTileParser; use crate::map::render::MapRenderer; use crate::systems::components::NodeId; @@ -166,44 +165,6 @@ impl Map { }) } - /// Generates Item entities for pellets and energizers from the parsed map. - // pub fn generate_items(&self, atlas: &SpriteAtlas) -> GameResult> { - // // Pre-load sprites to avoid repeated texture lookups - // let pellet_sprite = SpriteAtlas::get_tile(atlas, "maze/pellet.png") - // .ok_or_else(|| MapError::InvalidConfig("Pellet texture not found".to_string()))?; - // let energizer_sprite = SpriteAtlas::get_tile(atlas, "maze/energizer.png") - // .ok_or_else(|| MapError::InvalidConfig("Energizer texture not found".to_string()))?; - - // // Pre-allocate with estimated capacity (typical Pac-Man maps have ~240 pellets + 4 energizers) - // let mut items = Vec::with_capacity(250); - - // // Parse the raw board once - // let parsed_map = MapTileParser::parse_board(RAW_BOARD)?; - // let map = parsed_map.tiles; - - // // Iterate through the map and collect items more efficiently - // for (x, row) in map.iter().enumerate() { - // for (y, tile) in row.iter().enumerate() { - // match tile { - // MapTile::Pellet | MapTile::PowerPellet => { - // let grid_pos = IVec2::new(x as i32, y as i32); - // if let Some(&node_id) = self.grid_to_node.get(&grid_pos) { - // let (item_type, sprite) = match tile { - // MapTile::Pellet => (ItemType::Pellet, Sprite::new(pellet_sprite)), - // MapTile::PowerPellet => (ItemType::Energizer, Sprite::new(energizer_sprite)), - // _ => unreachable!(), // We already filtered for these types - // }; - // items.push(Item::new(node_id, item_type, sprite)); - // } - // } - // _ => {} - // } - // } - // } - - // Ok(items) - // } - /// Renders a debug visualization with cursor-based highlighting. /// /// This function provides interactive debugging by highlighting the nearest node @@ -304,7 +265,7 @@ impl Map { false, None, Direction::Down, - EdgePermissions::GhostsOnly, + TraversalFlags::GHOST, ) .map_err(|e| MapError::InvalidConfig(format!("Failed to create ghost-only entrance to house: {e}")))?; @@ -315,7 +276,7 @@ impl Map { false, None, Direction::Up, - EdgePermissions::GhostsOnly, + TraversalFlags::GHOST, ) .map_err(|e| MapError::InvalidConfig(format!("Failed to create ghost-only exit from house: {e}")))?; diff --git a/src/systems/components.rs b/src/systems/components.rs index 75635c4..e114d36 100644 --- a/src/systems/components.rs +++ b/src/systems/components.rs @@ -3,7 +3,10 @@ use bitflags::bitflags; use glam::Vec2; use crate::{ - entity::{direction::Direction, graph::Graph}, + entity::{ + direction::Direction, + graph::{Graph, TraversalFlags}, + }, error::{EntityError, GameResult}, texture::{animated::AnimatedTexture, sprite::AtlasTile}, }; @@ -22,6 +25,17 @@ pub enum EntityType { Wall, } +impl EntityType { + /// Returns the traversal flags for this entity type. + pub fn traversal_flags(&self) -> TraversalFlags { + match self { + EntityType::Player => TraversalFlags::PACMAN, + EntityType::Ghost => TraversalFlags::GHOST, + _ => TraversalFlags::empty(), // Static entities don't traverse + } + } +} + /// A component for entities that have a sprite, with a layer for ordering. /// /// This is intended to be modified by other entities allowing animation. @@ -42,21 +56,36 @@ pub struct DirectionalAnimated { /// A unique identifier for a node, represented by its index in the graph's storage. pub type NodeId = usize; -/// Represents the current position of an entity traversing the graph. -/// -/// This enum allows for precise tracking of whether an entity is exactly at a node -/// or moving along an edge between two nodes. +/// Progress along an edge between two nodes. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct EdgeProgress { + pub target_node: NodeId, + /// Progress from 0.0 (at source node) to 1.0 (at target node) + pub progress: f32, +} + +/// Pure spatial position component - works for both static and dynamic entities. #[derive(Component, Debug, Copy, Clone, PartialEq)] -pub enum Position { - /// The traverser is located exactly at a node. - AtNode(NodeId), - /// The traverser is on an edge between two nodes. - BetweenNodes { - from: NodeId, - to: NodeId, - /// The floating-point distance traversed along the edge from the `from` node. - traversed: f32, - }, +pub struct Position { + /// The current/primary node this entity is at or traveling from + pub node: NodeId, + /// If Some, entity is traveling between nodes. If None, entity is stationary at node. + pub edge_progress: Option, +} + +/// Explicit movement state - only for entities that can move. +#[derive(Component, Debug, Clone, Copy, PartialEq)] +pub enum MovementState { + Stopped, + Moving { direction: Direction }, +} + +/// Movement capability and parameters - only for entities that can move. +#[derive(Component, Debug, Clone, Copy)] +pub struct Movable { + pub speed: f32, + pub current_direction: Direction, + pub requested_direction: Option, } impl Position { @@ -69,18 +98,26 @@ impl Position { /// /// Returns an `EntityError` if the node or edge is not found. pub fn get_pixel_pos(&self, graph: &Graph) -> GameResult { - let pos = match self { - Position::AtNode(node_id) => { - let node = graph.get_node(*node_id).ok_or(EntityError::NodeNotFound(*node_id))?; + let pos = match &self.edge_progress { + None => { + // Entity is stationary at a node + let node = graph.get_node(self.node).ok_or(EntityError::NodeNotFound(self.node))?; node.position } - Position::BetweenNodes { from, to, traversed } => { - let from_node = graph.get_node(*from).ok_or(EntityError::NodeNotFound(*from))?; - let to_node = graph.get_node(*to).ok_or(EntityError::NodeNotFound(*to))?; - let edge = graph - .find_edge(*from, *to) - .ok_or(EntityError::EdgeNotFound { from: *from, to: *to })?; - from_node.position + (to_node.position - from_node.position) * (traversed / edge.distance) + Some(edge_progress) => { + // Entity is traveling between nodes + let from_node = graph.get_node(self.node).ok_or(EntityError::NodeNotFound(self.node))?; + let to_node = graph + .get_node(edge_progress.target_node) + .ok_or(EntityError::NodeNotFound(edge_progress.target_node))?; + + // For zero-distance edges (tunnels), progress >= 1.0 means we're at the target + if edge_progress.progress >= 1.0 { + to_node.position + } else { + // Interpolate position based on progress + from_node.position + (to_node.position - from_node.position) * edge_progress.progress + } } }; @@ -93,49 +130,36 @@ impl Position { impl Default for Position { fn default() -> Self { - Position::AtNode(0) + Position { + node: 0, + edge_progress: None, + } } } #[allow(dead_code)] impl Position { - /// Returns `true` if the position is exactly at a node. + /// Returns `true` if the position is exactly at a node (not traveling). pub fn is_at_node(&self) -> bool { - matches!(self, Position::AtNode(_)) + self.edge_progress.is_none() } - /// Returns the `NodeId` of the current or most recently departed node. - #[allow(clippy::wrong_self_convention)] - pub fn from_node_id(&self) -> NodeId { - match self { - Position::AtNode(id) => *id, - Position::BetweenNodes { from, .. } => *from, - } + /// Returns the `NodeId` of the current node (source of travel if moving). + pub fn current_node(&self) -> NodeId { + self.node } - /// Returns the `NodeId` of the destination node, if currently on an edge. - #[allow(clippy::wrong_self_convention)] - pub fn to_node_id(&self) -> Option { - match self { - Position::AtNode(_) => None, - Position::BetweenNodes { to, .. } => Some(*to), - } + /// Returns the `NodeId` of the destination node, if currently traveling. + pub fn target_node(&self) -> Option { + self.edge_progress.as_ref().map(|ep| ep.target_node) } - /// Returns `true` if the traverser is stopped at a node. - pub fn is_stopped(&self) -> bool { - matches!(self, Position::AtNode(_)) + /// Returns `true` if the entity is traveling between nodes. + pub fn is_moving(&self) -> bool { + self.edge_progress.is_some() } } -/// A component for entities that have a velocity, with a direction and speed. -#[derive(Default, Component)] -pub struct Velocity { - pub direction: Direction, - pub next_direction: Option<(Direction, u8)>, - pub speed: f32, -} - bitflags! { #[derive(Component, Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CollisionLayer: u8 { @@ -168,7 +192,8 @@ pub struct Score(pub u32); pub struct PlayerBundle { pub player: PlayerControlled, pub position: Position, - pub velocity: Velocity, + pub movement_state: MovementState, + pub movable: Movable, pub sprite: Renderable, pub directional_animated: DirectionalAnimated, pub entity_type: EntityType, diff --git a/src/systems/control.rs b/src/systems/control.rs index fcfb755..765d947 100644 --- a/src/systems/control.rs +++ b/src/systems/control.rs @@ -8,19 +8,19 @@ use bevy_ecs::{ use crate::{ error::GameError, events::{GameCommand, GameEvent}, - systems::components::{GlobalState, PlayerControlled, Velocity}, + systems::components::{GlobalState, Movable, PlayerControlled}, }; -// Handles +// Handles player input and control pub fn player_system( mut events: EventReader, mut state: ResMut, - mut players: Query<&mut Velocity, With>, + mut players: Query<&mut Movable, With>, mut errors: EventWriter, ) { - // Get the player's velocity (handling to ensure there is only one player) - let mut velocity = match players.single_mut() { - Ok(velocity) => velocity, + // Get the player's movable component (ensuring there is only one player) + let mut movable = match players.single_mut() { + Ok(movable) => movable, Err(e) => { errors.write(GameError::InvalidState(format!("No/multiple entities queried for player system: {}", e)).into()); return; @@ -32,7 +32,7 @@ pub fn player_system( match event { GameEvent::Command(command) => match command { GameCommand::MovePlayer(direction) => { - velocity.next_direction = Some((*direction, 90)); + movable.requested_direction = Some(*direction); } GameCommand::Exit => { state.exit = true; diff --git a/src/systems/movement.rs b/src/systems/movement.rs index 0f5d3e2..87581f1 100644 --- a/src/systems/movement.rs +++ b/src/systems/movement.rs @@ -1,131 +1,160 @@ -use crate::entity::graph::{Edge, EdgePermissions}; +use crate::entity::graph::Edge; use crate::error::{EntityError, GameError}; use crate::map::builder::Map; -use crate::systems::components::{DeltaTime, EntityType, Position, Velocity}; +use crate::systems::components::{DeltaTime, EdgeProgress, EntityType, Movable, MovementState, Position}; use bevy_ecs::event::EventWriter; use bevy_ecs::system::{Query, Res}; 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), - } + let entity_flags = entity_type.traversal_flags(); + edge.traversal_flags.contains(entity_flags) } pub fn movement_system( map: Res, delta_time: Res, - mut entities: Query<(&mut Velocity, &mut Position, &EntityType)>, + mut entities: Query<(&mut MovementState, &mut Movable, &mut Position, &EntityType)>, mut errors: EventWriter, ) { - for (mut velocity, mut position, entity_type) in entities.iter_mut() { - let distance = velocity.speed * 60.0 * delta_time.0; + for (mut movement_state, mut movable, mut position, entity_type) in entities.iter_mut() { + let distance = movable.speed * 60.0 * delta_time.0; - // Decrement the remaining frames for the next direction - if let Some((direction, remaining)) = velocity.next_direction { - if remaining > 0 { - velocity.next_direction = Some((direction, remaining - 1)); - } else { - velocity.next_direction = None; - } - } - - match *position { - Position::AtNode(node_id) => { - // 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) { + match *movement_state { + MovementState::Stopped => { + // Check if we have a requested direction to start moving + if let Some(requested_direction) = movable.requested_direction { + if let Some(edge) = map.graph.find_edge_in_direction(position.node, requested_direction) { if can_traverse(*entity_type, edge) { - // Start moving in that direction - *position = Position::BetweenNodes { - from: node_id, - to: edge.target, - traversed: distance, + // Start moving in the requested direction + let progress = if edge.distance > 0.0 { + distance / edge.distance + } else { + // Zero-distance edge (tunnels) - immediately teleport + tracing::debug!("Entity entering tunnel from node {} to node {}", position.node, edge.target); + 1.0 + }; + + position.edge_progress = Some(EdgeProgress { + target_node: edge.target, + progress, + }); + movable.current_direction = requested_direction; + movable.requested_direction = None; + *movement_state = MovementState::Moving { + direction: requested_direction, }; - velocity.direction = next_direction; - velocity.next_direction = None; } } else { errors.write( EntityError::InvalidMovement(format!( "No edge found in direction {:?} from node {}", - next_direction, node_id + requested_direction, position.node )) .into(), ); } } } - Position::BetweenNodes { from, to, traversed } => { - // There is no point in any of the next logic if we don't travel at all - if distance <= 0.0 { - return; - } + MovementState::Moving { direction } => { + // Continue moving or handle node transitions + let current_node = position.node; + if let Some(edge_progress) = &mut position.edge_progress { + // Extract target node before mutable operations + let target_node = edge_progress.target_node; - let edge = map - .graph - .find_edge(from, to) - .ok_or_else(|| { + // Get the current edge for distance calculation + let edge = map.graph.find_edge(current_node, target_node); + + if let Some(edge) = edge { + // Update progress along the edge + if edge.distance > 0.0 { + edge_progress.progress += distance / edge.distance; + } else { + // Zero-distance edge (tunnels) - immediately complete + edge_progress.progress = 1.0; + } + + if edge_progress.progress >= 1.0 { + // Reached the target node + let overflow = if edge.distance > 0.0 { + (edge_progress.progress - 1.0) * edge.distance + } else { + // Zero-distance edge - use remaining distance for overflow + distance + }; + position.node = target_node; + position.edge_progress = None; + + let mut continued_moving = false; + + // Try to use requested direction first + if let Some(requested_direction) = movable.requested_direction { + if let Some(next_edge) = map.graph.find_edge_in_direction(position.node, requested_direction) { + if can_traverse(*entity_type, next_edge) { + let next_progress = if next_edge.distance > 0.0 { + overflow / next_edge.distance + } else { + // Zero-distance edge - immediately complete + 1.0 + }; + + position.edge_progress = Some(EdgeProgress { + target_node: next_edge.target, + progress: next_progress, + }); + movable.current_direction = requested_direction; + movable.requested_direction = None; + *movement_state = MovementState::Moving { + direction: requested_direction, + }; + continued_moving = true; + } + } + } + + // If no requested direction or it failed, try to continue in current direction + if !continued_moving { + if let Some(next_edge) = map.graph.find_edge_in_direction(position.node, direction) { + if can_traverse(*entity_type, next_edge) { + let next_progress = if next_edge.distance > 0.0 { + overflow / next_edge.distance + } else { + // Zero-distance edge - immediately complete + 1.0 + }; + + position.edge_progress = Some(EdgeProgress { + target_node: next_edge.target, + progress: next_progress, + }); + // Keep current direction and movement state + continued_moving = true; + } + } + } + + // If we couldn't continue moving, stop + if !continued_moving { + *movement_state = MovementState::Stopped; + movable.requested_direction = None; + } + } + } else { + // Edge not found - this is an inconsistent state errors.write( EntityError::InvalidMovement(format!( - "Inconsistent state: Traverser is on a non-existent edge from {} to {}.", - from, to + "Inconsistent state: Moving on non-existent edge from {} to {}", + current_node, target_node )) .into(), ); - return; - }) - .unwrap(); - - let new_traversed = traversed + distance; - - if new_traversed < edge.distance { - // Still on the same edge, just update the distance. - *position = Position::BetweenNodes { - from, - to, - traversed: new_traversed, - }; + *movement_state = MovementState::Stopped; + position.edge_progress = None; + } } else { - let overflow = new_traversed - edge.distance; - let mut moved = false; - - // 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(*entity_type, edge) { - *position = Position::BetweenNodes { - from: to, - to: edge.target, - traversed: overflow, - }; - - velocity.direction = next_dir; // Remember our new direction - velocity.next_direction = None; // Consume the buffered direction - moved = true; - } - } - } - - // 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(*entity_type, edge) { - *position = Position::BetweenNodes { - from: to, - to: edge.target, - traversed: overflow, - }; - } else { - *position = Position::AtNode(to); - velocity.next_direction = None; - } - } else { - *position = Position::AtNode(to); - velocity.next_direction = None; - } - } + // Movement state says moving but no edge progress - this shouldn't happen + errors.write(EntityError::InvalidMovement("Entity in Moving state but no edge progress".to_string()).into()); + *movement_state = MovementState::Stopped; } } } diff --git a/src/systems/render.rs b/src/systems/render.rs index 27b9727..8b02ebf 100644 --- a/src/systems/render.rs +++ b/src/systems/render.rs @@ -1,6 +1,6 @@ use crate::error::{GameError, TextureError}; use crate::map::builder::Map; -use crate::systems::components::{DeltaTime, DirectionalAnimated, Position, Renderable, Velocity}; +use crate::systems::components::{DeltaTime, DirectionalAnimated, Movable, MovementState, Position, Renderable}; use crate::texture::sprite::SpriteAtlas; use bevy_ecs::entity::Entity; use bevy_ecs::event::EventWriter; @@ -13,15 +13,17 @@ use sdl2::video::Window; /// 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, - mut renderables: Query<(&Velocity, &mut DirectionalAnimated, &mut Renderable, &Position)>, + mut renderables: Query<(&MovementState, &Movable, &mut DirectionalAnimated, &mut Renderable)>, mut errors: EventWriter, ) { - for (velocity, mut texture, mut renderable, position) in renderables.iter_mut() { - let stopped = matches!(position, Position::AtNode(_)); + for (movement_state, movable, mut texture, mut renderable) in renderables.iter_mut() { + let stopped = matches!(movement_state, MovementState::Stopped); + let current_direction = movable.current_direction; + let texture = if stopped { - texture.stopped_textures[velocity.direction.as_usize()].as_mut() + texture.stopped_textures[current_direction.as_usize()].as_mut() } else { - texture.textures[velocity.direction.as_usize()].as_mut() + texture.textures[current_direction.as_usize()].as_mut() }; if let Some(texture) = texture { diff --git a/tests/graph.rs b/tests/graph.rs index b9d4477..bb888c3 100644 --- a/tests/graph.rs +++ b/tests/graph.rs @@ -1,5 +1,5 @@ use pacman::entity::direction::Direction; -use pacman::entity::graph::{EdgePermissions, Graph, Node}; +use pacman::entity::graph::{Graph, Node, TraversalFlags}; fn create_test_graph() -> Graph { let mut graph = Graph::new(); @@ -78,11 +78,11 @@ fn test_graph_edge_permissions() { }); graph - .add_edge(node1, node2, false, None, Direction::Right, EdgePermissions::GhostsOnly) + .add_edge(node1, node2, false, None, Direction::Right, TraversalFlags::GHOST) .unwrap(); let edge = graph.find_edge_in_direction(node1, Direction::Right).unwrap(); - assert_eq!(edge.permissions, EdgePermissions::GhostsOnly); + assert_eq!(edge.traversal_flags, TraversalFlags::GHOST); } #[test] @@ -118,21 +118,21 @@ fn should_error_on_negative_edge_distance() { position: glam::Vec2::new(16.0, 0.0), }); - let result = graph.add_edge(node1, node2, false, Some(-1.0), Direction::Right, EdgePermissions::All); + let result = graph.add_edge(node1, node2, false, Some(-1.0), Direction::Right, TraversalFlags::ALL); assert!(result.is_err()); } #[test] fn should_error_on_duplicate_edge_without_replace() { let mut graph = create_test_graph(); - let result = graph.add_edge(0, 1, false, None, Direction::Right, EdgePermissions::All); + let result = graph.add_edge(0, 1, false, None, Direction::Right, TraversalFlags::ALL); assert!(result.is_err()); } #[test] fn should_allow_replacing_an_edge() { let mut graph = create_test_graph(); - let result = graph.add_edge(0, 1, true, Some(42.0), Direction::Right, EdgePermissions::All); + let result = graph.add_edge(0, 1, true, Some(42.0), Direction::Right, TraversalFlags::ALL); assert!(result.is_ok()); let edge = graph.find_edge(0, 1).unwrap();