mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-15 20:12:27 -06:00
feat: sprite enums for avoiding hardcoded string paths
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
pub mod animated;
|
||||
pub mod blinking;
|
||||
pub mod sprite;
|
||||
pub mod sprites;
|
||||
pub mod text;
|
||||
pub mod ttf;
|
||||
|
||||
@@ -20,7 +20,8 @@ pub struct MapperFrame {
|
||||
pub size: U16Vec2,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
/// A single tile within a sprite atlas, defined by its position and size.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||
pub struct AtlasTile {
|
||||
pub pos: U16Vec2,
|
||||
pub size: U16Vec2,
|
||||
@@ -89,9 +90,11 @@ pub struct SpriteAtlas {
|
||||
|
||||
impl SpriteAtlas {
|
||||
pub fn new(texture: Texture, mapper: AtlasMapper) -> Self {
|
||||
let tiles = mapper.frames.into_iter().collect();
|
||||
|
||||
Self {
|
||||
texture,
|
||||
tiles: mapper.frames,
|
||||
tiles,
|
||||
default_color: None,
|
||||
last_modulation: None,
|
||||
}
|
||||
@@ -103,11 +106,15 @@ impl SpriteAtlas {
|
||||
/// for the named sprite, or `None` if the sprite name is not found in the
|
||||
/// atlas. The returned tile can be used for immediate rendering or stored
|
||||
/// for repeated use in animations and entity sprites.
|
||||
pub fn get_tile(&self, name: &str) -> Option<AtlasTile> {
|
||||
self.tiles.get(name).map(|frame| AtlasTile {
|
||||
pub fn get_tile(&self, name: &str) -> Result<AtlasTile, TextureError> {
|
||||
let frame = self
|
||||
.tiles
|
||||
.get(name)
|
||||
.ok_or_else(|| TextureError::AtlasTileNotFound(name.to_string()))?;
|
||||
Ok(AtlasTile {
|
||||
pos: frame.pos,
|
||||
size: frame.size,
|
||||
color: None,
|
||||
color: self.default_color,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
104
src/texture/sprites.rs
Normal file
104
src/texture/sprites.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
//! A structured representation of all sprite assets in the game.
|
||||
//!
|
||||
//! This module provides a set of enums to represent every sprite, allowing for
|
||||
//! type-safe access to asset paths and avoiding the use of raw strings.
|
||||
//! The `GameSprite` enum is the main entry point, and its `to_path` method
|
||||
//! generates the correct path for a given sprite in the texture atlas.
|
||||
|
||||
use crate::map::direction::Direction;
|
||||
use crate::systems::components::Ghost;
|
||||
|
||||
/// Represents the different sprites for Pac-Man.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PacmanSprite {
|
||||
/// A moving Pac-Man sprite for a given direction and animation frame.
|
||||
Moving(Direction, u8),
|
||||
/// The full, closed-mouth Pac-Man sprite.
|
||||
Full,
|
||||
}
|
||||
|
||||
/// Represents the color of a frightened ghost.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum FrightenedColor {
|
||||
Blue,
|
||||
White,
|
||||
}
|
||||
|
||||
/// Represents the different sprites for ghosts.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum GhostSprite {
|
||||
/// The normal appearance of a ghost for a given type, direction, and animation frame.
|
||||
Normal(Ghost, Direction, u8),
|
||||
/// The frightened appearance of a ghost, with a specific color and animation frame.
|
||||
Frightened(FrightenedColor, u8),
|
||||
/// The "eyes only" appearance of a ghost after being eaten.
|
||||
Eyes(Direction),
|
||||
}
|
||||
|
||||
/// Represents the different sprites for the maze and collectibles.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum MazeSprite {
|
||||
/// A specific tile of the maze.
|
||||
Tile(u8),
|
||||
/// A standard pellet.
|
||||
Pellet,
|
||||
/// An energizer/power pellet.
|
||||
Energizer,
|
||||
}
|
||||
|
||||
/// A top-level enum that encompasses all game sprites.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum GameSprite {
|
||||
Pacman(PacmanSprite),
|
||||
Ghost(GhostSprite),
|
||||
Maze(MazeSprite),
|
||||
}
|
||||
|
||||
impl GameSprite {
|
||||
/// Generates the asset path for the sprite.
|
||||
///
|
||||
/// This path corresponds to the filename in the texture atlas JSON file.
|
||||
pub fn to_path(self) -> String {
|
||||
match self {
|
||||
GameSprite::Pacman(sprite) => match sprite {
|
||||
PacmanSprite::Moving(dir, frame) => {
|
||||
let frame_char = match frame {
|
||||
0 => 'a',
|
||||
1 => 'b',
|
||||
_ => panic!("Invalid animation frame"),
|
||||
};
|
||||
format!("pacman/{}_{}.png", dir.as_ref().to_lowercase(), frame_char)
|
||||
}
|
||||
PacmanSprite::Full => "pacman/full.png".to_string(),
|
||||
},
|
||||
GameSprite::Ghost(sprite) => match sprite {
|
||||
GhostSprite::Normal(ghost, dir, frame) => {
|
||||
let frame_char = match frame {
|
||||
0 => 'a',
|
||||
1 => 'b',
|
||||
_ => panic!("Invalid animation frame"),
|
||||
};
|
||||
format!("ghost/{}/{}_{}.png", ghost.as_str(), dir.as_ref().to_lowercase(), frame_char)
|
||||
}
|
||||
GhostSprite::Frightened(color, frame) => {
|
||||
let frame_char = match frame {
|
||||
0 => 'a',
|
||||
1 => 'b',
|
||||
_ => panic!("Invalid animation frame"),
|
||||
};
|
||||
let color_str = match color {
|
||||
FrightenedColor::Blue => "blue",
|
||||
FrightenedColor::White => "white",
|
||||
};
|
||||
format!("ghost/frightened/{}_{}.png", color_str, frame_char)
|
||||
}
|
||||
GhostSprite::Eyes(dir) => format!("ghost/eyes/{}.png", dir.as_ref().to_lowercase()),
|
||||
},
|
||||
GameSprite::Maze(sprite) => match sprite {
|
||||
MazeSprite::Tile(index) => format!("maze/tiles/{}.png", index),
|
||||
MazeSprite::Pellet => "maze/pellet.png".to_string(),
|
||||
MazeSprite::Energizer => "maze/energizer.png".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,10 +60,7 @@ use sdl2::pixels::Color;
|
||||
use sdl2::render::{Canvas, RenderTarget};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
error::{GameError, TextureError},
|
||||
texture::sprite::{AtlasTile, SpriteAtlas},
|
||||
};
|
||||
use crate::texture::sprite::{AtlasTile, SpriteAtlas};
|
||||
|
||||
/// Converts a character to its tile name in the atlas.
|
||||
fn char_to_tile_name(c: char) -> Option<String> {
|
||||
@@ -122,9 +119,7 @@ impl TextTexture {
|
||||
}
|
||||
|
||||
if let Some(tile_name) = char_to_tile_name(c) {
|
||||
let tile = atlas
|
||||
.get_tile(&tile_name)
|
||||
.ok_or(GameError::Texture(TextureError::AtlasTileNotFound(tile_name)))?;
|
||||
let tile = atlas.get_tile(&tile_name)?;
|
||||
self.char_map.insert(c, tile);
|
||||
Ok(self.char_map.get(&c))
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user