refactor: replace HashMap with fixed-size arrays for textures in DirectionalAnimatedTexture

This commit is contained in:
2025-08-11 11:13:46 -05:00
parent 6702b3723a
commit e0f8443e75
4 changed files with 26 additions and 34 deletions

View File

@@ -29,9 +29,9 @@ impl Direction {
self.into()
}
/// Returns the direction as a u8 (0-3). Constant time.
/// Returns the direction as a usize (0-3). Constant time.
/// This is useful for indexing into arrays.
pub const fn as_u8(self) -> u8 {
pub const fn as_usize(self) -> usize {
match self {
Direction::Up => 0,
Direction::Down => 1,
@@ -51,5 +51,3 @@ impl From<Direction> for IVec2 {
}
}
}
pub const DIRECTIONS: [Direction; 4] = [Direction::Up, Direction::Down, Direction::Left, Direction::Right];

View File

@@ -15,7 +15,6 @@ use crate::texture::directional::DirectionalAnimatedTexture;
use crate::texture::sprite::SpriteAtlas;
use sdl2::keyboard::Keycode;
use sdl2::render::{Canvas, RenderTarget};
use std::collections::HashMap;
/// Determines if Pac-Man can traverse a given edge.
///
@@ -41,8 +40,8 @@ impl Pacman {
/// Sets up animated textures for all four directions with moving and stopped states.
/// The moving animation cycles through open mouth, closed mouth, and full sprites.
pub fn new(graph: &Graph, start_node: NodeId, atlas: &SpriteAtlas) -> Self {
let mut textures = HashMap::new();
let mut stopped_textures = HashMap::new();
let mut textures = [None, None, None, None];
let mut stopped_textures = [None, None, None, None];
for direction in Direction::DIRECTIONS {
let moving_prefix = match direction {
@@ -59,14 +58,9 @@ impl Pacman {
let stopped_tiles = vec![SpriteAtlas::get_tile(atlas, &format!("{moving_prefix}_b.png")).unwrap()];
textures.insert(
direction,
AnimatedTexture::new(moving_tiles, 0.08).expect("Invalid frame duration"),
);
stopped_textures.insert(
direction,
AnimatedTexture::new(stopped_tiles, 0.1).expect("Invalid frame duration"),
);
textures[direction.as_usize()] = Some(AnimatedTexture::new(moving_tiles, 0.08).expect("Invalid frame duration"));
stopped_textures[direction.as_usize()] =
Some(AnimatedTexture::new(stopped_tiles, 0.1).expect("Invalid frame duration"));
}
Self {

View File

@@ -1,7 +1,6 @@
use anyhow::Result;
use sdl2::rect::Rect;
use sdl2::render::{Canvas, RenderTarget};
use std::collections::HashMap;
use crate::entity::direction::Direction;
use crate::texture::animated::AnimatedTexture;
@@ -9,12 +8,12 @@ use crate::texture::sprite::SpriteAtlas;
#[derive(Clone)]
pub struct DirectionalAnimatedTexture {
textures: HashMap<Direction, AnimatedTexture>,
stopped_textures: HashMap<Direction, AnimatedTexture>,
textures: [Option<AnimatedTexture>; 4],
stopped_textures: [Option<AnimatedTexture>; 4],
}
impl DirectionalAnimatedTexture {
pub fn new(textures: HashMap<Direction, AnimatedTexture>, stopped_textures: HashMap<Direction, AnimatedTexture>) -> Self {
pub fn new(textures: [Option<AnimatedTexture>; 4], stopped_textures: [Option<AnimatedTexture>; 4]) -> Self {
Self {
textures,
stopped_textures,
@@ -22,8 +21,10 @@ impl DirectionalAnimatedTexture {
}
pub fn tick(&mut self, dt: f32) {
for texture in self.textures.values_mut() {
texture.tick(dt);
for texture in self.textures.iter_mut() {
if let Some(texture) = texture {
texture.tick(dt);
}
}
}
@@ -34,7 +35,7 @@ impl DirectionalAnimatedTexture {
dest: Rect,
direction: Direction,
) -> Result<()> {
if let Some(texture) = self.textures.get(&direction) {
if let Some(texture) = &self.textures[direction.as_usize()] {
texture.render(canvas, atlas, dest)
} else {
Ok(())
@@ -48,7 +49,7 @@ impl DirectionalAnimatedTexture {
dest: Rect,
direction: Direction,
) -> Result<()> {
if let Some(texture) = self.stopped_textures.get(&direction) {
if let Some(texture) = &self.stopped_textures[direction.as_usize()] {
texture.render(canvas, atlas, dest)
} else {
Ok(())
@@ -58,24 +59,24 @@ impl DirectionalAnimatedTexture {
/// Returns true if the texture has a direction.
#[allow(dead_code)]
pub fn has_direction(&self, direction: Direction) -> bool {
self.textures.contains_key(&direction)
self.textures[direction.as_usize()].is_some()
}
/// Returns true if the texture has a stopped direction.
#[allow(dead_code)]
pub fn has_stopped_direction(&self, direction: Direction) -> bool {
self.stopped_textures.contains_key(&direction)
self.stopped_textures[direction.as_usize()].is_some()
}
/// Returns the number of textures.
#[allow(dead_code)]
pub fn texture_count(&self) -> usize {
self.textures.len()
self.textures.iter().filter(|t| t.is_some()).count()
}
/// Returns the number of stopped textures.
#[allow(dead_code)]
pub fn stopped_texture_count(&self) -> usize {
self.stopped_textures.len()
self.stopped_textures.iter().filter(|t| t.is_some()).count()
}
}

View File

@@ -4,7 +4,6 @@ use pacman::texture::animated::AnimatedTexture;
use pacman::texture::directional::DirectionalAnimatedTexture;
use pacman::texture::sprite::AtlasTile;
use sdl2::pixels::Color;
use std::collections::HashMap;
fn mock_atlas_tile(id: u32) -> AtlasTile {
AtlasTile {
@@ -20,10 +19,10 @@ fn mock_animated_texture(id: u32) -> AnimatedTexture {
#[test]
fn test_directional_texture_partial_directions() {
let mut textures = HashMap::new();
textures.insert(Direction::Up, mock_animated_texture(1));
let mut textures = [None, None, None, None];
textures[Direction::Up.as_usize()] = Some(mock_animated_texture(1));
let texture = DirectionalAnimatedTexture::new(textures, HashMap::new());
let texture = DirectionalAnimatedTexture::new(textures, [None, None, None, None]);
assert_eq!(texture.texture_count(), 1);
assert!(texture.has_direction(Direction::Up));
@@ -34,7 +33,7 @@ fn test_directional_texture_partial_directions() {
#[test]
fn test_directional_texture_all_directions() {
let mut textures = HashMap::new();
let mut textures = [None, None, None, None];
let directions = [
(Direction::Up, 1),
(Direction::Down, 2),
@@ -43,10 +42,10 @@ fn test_directional_texture_all_directions() {
];
for (direction, id) in directions {
textures.insert(direction, mock_animated_texture(id));
textures[direction.as_usize()] = Some(mock_animated_texture(id));
}
let texture = DirectionalAnimatedTexture::new(textures, HashMap::new());
let texture = DirectionalAnimatedTexture::new(textures, [None, None, None, None]);
assert_eq!(texture.texture_count(), 4);
for direction in &[Direction::Up, Direction::Down, Direction::Left, Direction::Right] {