mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-16 14:12:40 -06:00
refactor: intentionally unsafe leak to drop annoying lifetimes, use IVec2 in all remaining spots
This commit is contained in:
@@ -11,18 +11,18 @@ use crate::entity::{Entity, Moving, Renderable, StaticEntity};
|
||||
use crate::map::Map;
|
||||
use glam::{IVec2, UVec2};
|
||||
|
||||
pub struct Blinky<'a> {
|
||||
ghost: Ghost<'a>,
|
||||
pub struct Blinky {
|
||||
ghost: Ghost,
|
||||
}
|
||||
|
||||
impl<'a> Blinky<'a> {
|
||||
impl Blinky {
|
||||
pub fn new(
|
||||
starting_position: UVec2,
|
||||
body_texture: Texture<'a>,
|
||||
eyes_texture: Texture<'a>,
|
||||
body_texture: Texture<'_>,
|
||||
eyes_texture: Texture<'_>,
|
||||
map: Rc<RefCell<Map>>,
|
||||
pacman: Rc<RefCell<Pacman<'a>>>,
|
||||
) -> Blinky<'a> {
|
||||
pacman: Rc<RefCell<Pacman>>,
|
||||
) -> Blinky {
|
||||
Blinky {
|
||||
ghost: Ghost::new(GhostType::Blinky, starting_position, body_texture, eyes_texture, map, pacman),
|
||||
}
|
||||
@@ -44,19 +44,19 @@ impl<'a> Blinky<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Entity for Blinky<'a> {
|
||||
impl Entity for Blinky {
|
||||
fn base(&self) -> &StaticEntity {
|
||||
self.ghost.base.base()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Renderable for Blinky<'a> {
|
||||
impl Renderable for Blinky {
|
||||
fn render(&self, canvas: &mut Canvas<Window>) {
|
||||
self.ghost.render(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Moving for Blinky<'a> {
|
||||
impl Moving for Blinky {
|
||||
fn move_forward(&mut self) {
|
||||
self.ghost.move_forward();
|
||||
}
|
||||
@@ -81,15 +81,15 @@ impl<'a> Moving for Blinky<'a> {
|
||||
}
|
||||
|
||||
// Allow direct access to ghost fields
|
||||
impl<'a> std::ops::Deref for Blinky<'a> {
|
||||
type Target = Ghost<'a>;
|
||||
impl std::ops::Deref for Blinky {
|
||||
type Target = Ghost;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.ghost
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::ops::DerefMut for Blinky<'a> {
|
||||
impl std::ops::DerefMut for Blinky {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.ghost
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! This module defines the `Direction` enum, which is used to represent the
|
||||
//! direction of an entity.
|
||||
use glam::IVec2;
|
||||
use sdl2::keyboard::Keycode;
|
||||
|
||||
/// An enum representing the direction of an entity.
|
||||
@@ -23,12 +24,12 @@ impl Direction {
|
||||
}
|
||||
|
||||
/// Returns the offset of the direction as a tuple of (x, y).
|
||||
pub fn offset(&self) -> (i32, i32) {
|
||||
pub fn offset(&self) -> IVec2 {
|
||||
match self {
|
||||
Direction::Right => (1, 0),
|
||||
Direction::Down => (0, 1),
|
||||
Direction::Left => (-1, 0),
|
||||
Direction::Up => (0, -1),
|
||||
Direction::Right => IVec2::new(1, 0),
|
||||
Direction::Down => IVec2::new(0, 1),
|
||||
Direction::Left => IVec2::new(-1, 0),
|
||||
Direction::Up => IVec2::new(0, -1),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ pub enum EdibleKind {
|
||||
Fruit(FruitType),
|
||||
}
|
||||
|
||||
pub struct Edible<'a> {
|
||||
pub struct Edible {
|
||||
pub base: StaticEntity,
|
||||
pub kind: EdibleKind,
|
||||
pub sprite: Rc<AtlasTexture<'a>>,
|
||||
pub sprite: Rc<AtlasTexture>,
|
||||
}
|
||||
|
||||
impl<'a> Edible<'a> {
|
||||
pub fn new(kind: EdibleKind, cell_position: UVec2, sprite: Rc<AtlasTexture<'a>>) -> Self {
|
||||
impl Edible {
|
||||
pub fn new(kind: EdibleKind, cell_position: UVec2, sprite: Rc<AtlasTexture>) -> Self {
|
||||
let pixel_position = Map::cell_to_pixel(cell_position);
|
||||
Edible {
|
||||
base: StaticEntity::new(pixel_position, cell_position),
|
||||
@@ -39,26 +39,26 @@ impl<'a> Edible<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Entity for Edible<'a> {
|
||||
impl Entity for Edible {
|
||||
fn base(&self) -> &StaticEntity {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Renderable for Edible<'a> {
|
||||
impl Renderable for Edible {
|
||||
fn render(&self, canvas: &mut Canvas<Window>) {
|
||||
let pos = self.base.pixel_position;
|
||||
self.sprite.render(canvas, (pos.x, pos.y), Direction::Right, Some(0));
|
||||
self.sprite.render(canvas, pos, Direction::Right, Some(0));
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconstruct all edibles from the original map layout
|
||||
pub fn reconstruct_edibles<'a>(
|
||||
pub fn reconstruct_edibles(
|
||||
map: Rc<RefCell<Map>>,
|
||||
pellet_sprite: Rc<AtlasTexture<'a>>,
|
||||
power_pellet_sprite: Rc<AtlasTexture<'a>>,
|
||||
_fruit_sprite: Rc<AtlasTexture<'a>>,
|
||||
) -> Vec<Edible<'a>> {
|
||||
pellet_sprite: Rc<AtlasTexture>,
|
||||
power_pellet_sprite: Rc<AtlasTexture>,
|
||||
_fruit_sprite: Rc<AtlasTexture>,
|
||||
) -> Vec<Edible> {
|
||||
let mut edibles = Vec::new();
|
||||
for x in 0..BOARD_WIDTH {
|
||||
for y in 0..BOARD_HEIGHT {
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::entity::{Entity, MovableEntity, Moving, Renderable};
|
||||
use crate::map::Map;
|
||||
use crate::modulation::{SimpleTickModulator, TickModulator};
|
||||
use crate::texture::animated::AnimatedAtlasTexture;
|
||||
use crate::texture::atlas::{texture_to_static, AtlasTexture};
|
||||
use crate::texture::FrameDrawn;
|
||||
use glam::{IVec2, UVec2};
|
||||
use sdl2::pixels::Color;
|
||||
@@ -53,7 +54,7 @@ impl GhostType {
|
||||
}
|
||||
|
||||
/// Base ghost struct that contains common functionality
|
||||
pub struct Ghost<'a> {
|
||||
pub struct Ghost {
|
||||
/// Shared movement and position fields.
|
||||
pub base: MovableEntity,
|
||||
/// The current mode of the ghost
|
||||
@@ -61,23 +62,30 @@ pub struct Ghost<'a> {
|
||||
/// The type/personality of this ghost
|
||||
pub ghost_type: GhostType,
|
||||
/// Reference to Pac-Man for targeting
|
||||
pub pacman: Rc<RefCell<Pacman<'a>>>,
|
||||
pub body_sprite: AnimatedAtlasTexture<'a>,
|
||||
pub eyes_sprite: AnimatedAtlasTexture<'a>,
|
||||
pub pacman: Rc<RefCell<Pacman>>,
|
||||
pub body_sprite: AnimatedAtlasTexture,
|
||||
pub eyes_sprite: AnimatedAtlasTexture,
|
||||
}
|
||||
|
||||
impl Ghost<'_> {
|
||||
impl Ghost {
|
||||
/// Creates a new ghost instance
|
||||
pub fn new<'a>(
|
||||
pub fn new(
|
||||
ghost_type: GhostType,
|
||||
starting_position: UVec2,
|
||||
body_texture: Texture<'a>,
|
||||
eyes_texture: Texture<'a>,
|
||||
body_texture: Texture<'_>,
|
||||
eyes_texture: Texture<'_>,
|
||||
map: Rc<RefCell<Map>>,
|
||||
pacman: Rc<RefCell<Pacman<'a>>>,
|
||||
) -> Ghost<'a> {
|
||||
pacman: Rc<RefCell<Pacman>>,
|
||||
) -> Ghost {
|
||||
let color = ghost_type.color();
|
||||
let mut body_sprite = AnimatedAtlasTexture::new(body_texture, 8, 2, 32, 32, Some((-4, -4)));
|
||||
let mut body_sprite = AnimatedAtlasTexture::new(
|
||||
unsafe { texture_to_static(body_texture) },
|
||||
8,
|
||||
2,
|
||||
32,
|
||||
32,
|
||||
Some(IVec2::new(-4, -4)),
|
||||
);
|
||||
body_sprite.set_color_modulation(color.r, color.g, color.b);
|
||||
let pixel_position = Map::cell_to_pixel(starting_position);
|
||||
Ghost {
|
||||
@@ -93,7 +101,14 @@ impl Ghost<'_> {
|
||||
ghost_type,
|
||||
pacman,
|
||||
body_sprite,
|
||||
eyes_sprite: AnimatedAtlasTexture::new(eyes_texture, 1, 4, 32, 32, Some((-4, -4))),
|
||||
eyes_sprite: AnimatedAtlasTexture::new(
|
||||
unsafe { texture_to_static(eyes_texture) },
|
||||
1,
|
||||
4,
|
||||
32,
|
||||
32,
|
||||
Some((-4, -4).into()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +196,8 @@ impl Ghost<'_> {
|
||||
}
|
||||
}
|
||||
for dir in &[Direction::Up, Direction::Down, Direction::Left, Direction::Right] {
|
||||
let (dx, dy) = dir.offset();
|
||||
let next_p = IVec2::new(p.x as i32 + dx, p.y as i32 + dy);
|
||||
let offset = dir.offset();
|
||||
let next_p = IVec2::new(p.x as i32 + offset.x, p.y as i32 + offset.y);
|
||||
if let Some(tile) = map.get_tile(next_p) {
|
||||
if tile == MapTile::Wall {
|
||||
continue;
|
||||
@@ -267,7 +282,7 @@ impl Ghost<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Moving for Ghost<'a> {
|
||||
impl Moving for Ghost {
|
||||
fn move_forward(&mut self) {
|
||||
self.base.move_forward();
|
||||
}
|
||||
@@ -291,10 +306,10 @@ impl<'a> Moving for Ghost<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Renderable for Ghost<'a> {
|
||||
impl Renderable for Ghost {
|
||||
fn render(&self, canvas: &mut sdl2::render::Canvas<sdl2::video::Window>) {
|
||||
let pos = self.base.base.pixel_position;
|
||||
self.body_sprite.render(canvas, (pos.x, pos.y), Direction::Right, None);
|
||||
self.body_sprite.render(canvas, pos, Direction::Right, None);
|
||||
// Inline the eye_frame logic here
|
||||
let eye_frame = if self.mode == GhostMode::Frightened {
|
||||
4 // Frightened frame
|
||||
@@ -306,7 +321,6 @@ impl<'a> Renderable for Ghost<'a> {
|
||||
Direction::Down => 3,
|
||||
}
|
||||
};
|
||||
self.eyes_sprite
|
||||
.render(canvas, (pos.x, pos.y), Direction::Right, Some(eye_frame));
|
||||
self.eyes_sprite.render(canvas, pos, Direction::Right, Some(eye_frame));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ impl Moving for MovableEntity {
|
||||
);
|
||||
}
|
||||
fn next_cell(&self, direction: Option<Direction>) -> IVec2 {
|
||||
let (x, y) = direction.unwrap_or(self.direction).offset();
|
||||
let IVec2 { x, y } = direction.unwrap_or(self.direction).offset();
|
||||
IVec2::new(self.base.cell_position.x as i32 + x, self.base.cell_position.y as i32 + y)
|
||||
}
|
||||
fn is_wall_ahead(&self, direction: Option<Direction>) -> bool {
|
||||
|
||||
@@ -18,23 +18,23 @@ use crate::{
|
||||
use glam::{IVec2, UVec2};
|
||||
|
||||
/// The Pac-Man entity.
|
||||
pub struct Pacman<'a> {
|
||||
pub struct Pacman {
|
||||
/// Shared movement and position fields.
|
||||
pub base: MovableEntity,
|
||||
/// The next direction of Pac-Man, which will be applied when Pac-Man is next aligned with the grid.
|
||||
pub next_direction: Option<Direction>,
|
||||
/// Whether Pac-Man is currently stopped.
|
||||
pub stopped: bool,
|
||||
pub sprite: AnimatedAtlasTexture<'a>,
|
||||
pub sprite: AnimatedAtlasTexture,
|
||||
}
|
||||
|
||||
impl<'a> Entity for Pacman<'a> {
|
||||
impl Entity for Pacman {
|
||||
fn base(&self) -> &StaticEntity {
|
||||
&self.base.base
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Moving for Pacman<'a> {
|
||||
impl Moving for Pacman {
|
||||
fn move_forward(&mut self) {
|
||||
self.base.move_forward();
|
||||
}
|
||||
@@ -58,9 +58,9 @@ impl<'a> Moving for Pacman<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Pacman<'_> {
|
||||
impl Pacman {
|
||||
/// Creates a new `Pacman` instance.
|
||||
pub fn new<'a>(starting_position: UVec2, atlas: Texture<'a>, map: Rc<RefCell<Map>>) -> Pacman<'a> {
|
||||
pub fn new(starting_position: UVec2, atlas: Texture<'_>, map: Rc<RefCell<Map>>) -> Pacman {
|
||||
let pixel_position = Map::cell_to_pixel(starting_position);
|
||||
Pacman {
|
||||
base: MovableEntity::new(
|
||||
@@ -73,7 +73,14 @@ impl Pacman<'_> {
|
||||
),
|
||||
next_direction: None,
|
||||
stopped: false,
|
||||
sprite: AnimatedAtlasTexture::new(atlas, 2, 3, 32, 32, Some((-4, -4))),
|
||||
sprite: AnimatedAtlasTexture::new(
|
||||
unsafe { crate::texture::atlas::texture_to_static(atlas) },
|
||||
2,
|
||||
3,
|
||||
32,
|
||||
32,
|
||||
Some(IVec2::new(-4, -4)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,14 +126,14 @@ impl Pacman<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for Pacman<'_> {
|
||||
impl Renderable for Pacman {
|
||||
fn render(&self, canvas: &mut Canvas<Window>) {
|
||||
let pos = self.base.base.pixel_position;
|
||||
let dir = self.base.direction;
|
||||
if self.stopped {
|
||||
self.sprite.render(canvas, (pos.x, pos.y), dir, Some(2));
|
||||
self.sprite.render(canvas, pos, dir, Some(2));
|
||||
} else {
|
||||
self.sprite.render(canvas, (pos.x, pos.y), dir, None);
|
||||
self.sprite.render(canvas, pos, dir, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user