mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-06 05:15:49 -06:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eaa4ab37f9 | |||
| 076275158e | |||
| 9f9ace0b16 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
6
rustfmt.toml
Normal file
6
rustfmt.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Rustfmt configuration
|
||||
edition = "2021"
|
||||
max_width = 130
|
||||
tab_spaces = 4
|
||||
newline_style = "Unix"
|
||||
use_small_heuristics = "Default"
|
||||
@@ -9,13 +9,7 @@ use crate::direction::Direction;
|
||||
|
||||
/// Trait for drawable atlas-based textures
|
||||
pub trait FrameDrawn {
|
||||
fn render(
|
||||
&self,
|
||||
canvas: &mut Canvas<Window>,
|
||||
position: (i32, i32),
|
||||
direction: Direction,
|
||||
frame: Option<u32>,
|
||||
);
|
||||
fn render(&self, canvas: &mut Canvas<Window>, position: (i32, i32), direction: Direction, frame: Option<u32>);
|
||||
}
|
||||
|
||||
/// A texture atlas abstraction for static (non-animated) rendering.
|
||||
@@ -28,13 +22,7 @@ pub struct AtlasTexture<'a> {
|
||||
}
|
||||
|
||||
impl<'a> AtlasTexture<'a> {
|
||||
pub fn new(
|
||||
texture: Texture<'a>,
|
||||
frame_count: u32,
|
||||
frame_width: u32,
|
||||
frame_height: u32,
|
||||
offset: Option<(i32, i32)>,
|
||||
) -> Self {
|
||||
pub fn new(texture: Texture<'a>, frame_count: u32, frame_width: u32, frame_height: u32, offset: Option<(i32, i32)>) -> Self {
|
||||
AtlasTexture {
|
||||
raw_texture: texture,
|
||||
frame_count,
|
||||
@@ -62,13 +50,7 @@ impl<'a> AtlasTexture<'a> {
|
||||
}
|
||||
|
||||
impl<'a> FrameDrawn for AtlasTexture<'a> {
|
||||
fn render(
|
||||
&self,
|
||||
canvas: &mut Canvas<Window>,
|
||||
position: (i32, i32),
|
||||
direction: Direction,
|
||||
frame: Option<u32>,
|
||||
) {
|
||||
fn render(&self, canvas: &mut Canvas<Window>, position: (i32, i32), direction: Direction, frame: Option<u32>) {
|
||||
let texture_source_frame_rect = self.get_frame_rect(frame.unwrap_or(0));
|
||||
let canvas_destination_rect = Rect::new(
|
||||
position.0 + self.offset.0,
|
||||
@@ -157,13 +139,7 @@ impl<'a> AnimatedAtlasTexture<'a> {
|
||||
}
|
||||
|
||||
impl<'a> FrameDrawn for AnimatedAtlasTexture<'a> {
|
||||
fn render(
|
||||
&self,
|
||||
canvas: &mut Canvas<Window>,
|
||||
position: (i32, i32),
|
||||
direction: Direction,
|
||||
frame: Option<u32>,
|
||||
) {
|
||||
fn render(&self, canvas: &mut Canvas<Window>, position: (i32, i32), direction: Direction, frame: Option<u32>) {
|
||||
let frame = frame.unwrap_or_else(|| self.current_frame());
|
||||
self.atlas.render(canvas, position, direction, Some(frame));
|
||||
}
|
||||
|
||||
28
src/audio.rs
28
src/audio.rs
@@ -15,6 +15,7 @@ pub struct Audio {
|
||||
_mixer_context: mixer::Sdl2MixerContext,
|
||||
sounds: Vec<Chunk>,
|
||||
next_sound_index: usize,
|
||||
muted: bool,
|
||||
}
|
||||
|
||||
impl Audio {
|
||||
@@ -24,6 +25,7 @@ impl Audio {
|
||||
let format = DEFAULT_FORMAT;
|
||||
let channels = 4;
|
||||
let chunk_size = 128;
|
||||
|
||||
mixer::open_audio(frequency, format, 1, chunk_size).expect("Failed to open audio");
|
||||
mixer::allocate_channels(channels);
|
||||
|
||||
@@ -39,8 +41,7 @@ impl Audio {
|
||||
.enumerate()
|
||||
.map(|(i, asset)| {
|
||||
let data = get_asset_bytes(*asset).expect("Failed to load sound asset");
|
||||
let rwops = RWops::from_bytes(&data)
|
||||
.unwrap_or_else(|_| panic!("Failed to create RWops for sound {}", i + 1));
|
||||
let rwops = RWops::from_bytes(&data).unwrap_or_else(|_| panic!("Failed to create RWops for sound {}", i + 1));
|
||||
rwops
|
||||
.load_wav()
|
||||
.unwrap_or_else(|_| panic!("Failed to load sound {} from asset API", i + 1))
|
||||
@@ -51,21 +52,16 @@ impl Audio {
|
||||
_mixer_context: mixer_context,
|
||||
sounds,
|
||||
next_sound_index: 0,
|
||||
muted: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Plays the "eat" sound effect.
|
||||
///
|
||||
/// This function also logs the time since the last sound effect was played.
|
||||
pub fn eat(&mut self) {
|
||||
if let Some(chunk) = self.sounds.get(self.next_sound_index) {
|
||||
match mixer::Channel(0).play(chunk, 0) {
|
||||
Ok(channel) => {
|
||||
tracing::info!(
|
||||
"Playing sound #{} on channel {:?}",
|
||||
self.next_sound_index + 1,
|
||||
channel
|
||||
);
|
||||
tracing::trace!("Playing sound #{} on channel {:?}", self.next_sound_index + 1, channel);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!("Could not play sound #{}: {}", self.next_sound_index + 1, e);
|
||||
@@ -74,4 +70,18 @@ impl Audio {
|
||||
}
|
||||
self.next_sound_index = (self.next_sound_index + 1) % self.sounds.len();
|
||||
}
|
||||
|
||||
/// Instantly mute or unmute all channels.
|
||||
pub fn set_mute(&mut self, mute: bool) {
|
||||
let channels = 4;
|
||||
let volume = if mute { 0 } else { 32 };
|
||||
for i in 0..channels {
|
||||
mixer::Channel(i).set_volume(volume);
|
||||
}
|
||||
self.muted = mute;
|
||||
}
|
||||
|
||||
pub fn is_muted(&self) -> bool {
|
||||
self.muted
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,18 +64,10 @@ pub fn reconstruct_edibles<'a>(
|
||||
let cell = (x, y);
|
||||
match tile {
|
||||
Some(MapTile::Pellet) => {
|
||||
edibles.push(Edible::new(
|
||||
EdibleKind::Pellet,
|
||||
cell,
|
||||
Rc::clone(&pellet_sprite),
|
||||
));
|
||||
edibles.push(Edible::new(EdibleKind::Pellet, cell, Rc::clone(&pellet_sprite)));
|
||||
}
|
||||
Some(MapTile::PowerPellet) => {
|
||||
edibles.push(Edible::new(
|
||||
EdibleKind::PowerPellet,
|
||||
cell,
|
||||
Rc::clone(&power_pellet_sprite),
|
||||
));
|
||||
edibles.push(Edible::new(EdibleKind::PowerPellet, cell, Rc::clone(&power_pellet_sprite)));
|
||||
}
|
||||
// Fruits can be added here if you have fruit positions
|
||||
_ => {}
|
||||
|
||||
@@ -108,10 +108,7 @@ impl Moving for MovableEntity {
|
||||
}
|
||||
fn next_cell(&self, direction: Option<Direction>) -> (i32, i32) {
|
||||
let (x, y) = direction.unwrap_or(self.direction).offset();
|
||||
(
|
||||
self.base.cell_position.0 as i32 + x,
|
||||
self.base.cell_position.1 as i32 + y,
|
||||
)
|
||||
(self.base.cell_position.0 as i32 + x, self.base.cell_position.1 as i32 + y)
|
||||
}
|
||||
fn is_wall_ahead(&self, direction: Option<Direction>) -> bool {
|
||||
let next_cell = self.next_cell(direction);
|
||||
@@ -119,10 +116,10 @@ impl Moving for MovableEntity {
|
||||
}
|
||||
fn handle_tunnel(&mut self) -> bool {
|
||||
if !self.in_tunnel {
|
||||
let current_tile = self.map.borrow().get_tile((
|
||||
self.base.cell_position.0 as i32,
|
||||
self.base.cell_position.1 as i32,
|
||||
));
|
||||
let current_tile = self
|
||||
.map
|
||||
.borrow()
|
||||
.get_tile((self.base.cell_position.0 as i32, self.base.cell_position.1 as i32));
|
||||
if matches!(current_tile, Some(MapTile::Tunnel)) {
|
||||
self.in_tunnel = true;
|
||||
}
|
||||
@@ -130,14 +127,12 @@ impl Moving for MovableEntity {
|
||||
if self.in_tunnel {
|
||||
if self.base.cell_position.0 == 0 {
|
||||
self.base.cell_position.0 = BOARD_WIDTH - 2;
|
||||
self.base.pixel_position =
|
||||
Map::cell_to_pixel((self.base.cell_position.0, self.base.cell_position.1));
|
||||
self.base.pixel_position = Map::cell_to_pixel((self.base.cell_position.0, self.base.cell_position.1));
|
||||
self.in_tunnel = false;
|
||||
true
|
||||
} else if self.base.cell_position.0 == BOARD_WIDTH - 1 {
|
||||
self.base.cell_position.0 = 1;
|
||||
self.base.pixel_position =
|
||||
Map::cell_to_pixel((self.base.cell_position.0, self.base.cell_position.1));
|
||||
self.base.pixel_position = Map::cell_to_pixel((self.base.cell_position.0, self.base.cell_position.1));
|
||||
self.in_tunnel = false;
|
||||
true
|
||||
} else {
|
||||
|
||||
63
src/game.rs
63
src/game.rs
@@ -1,5 +1,6 @@
|
||||
//! This module contains the main game logic and state.
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Not;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rand::seq::IteratorRandom;
|
||||
@@ -37,7 +38,7 @@ pub struct Game<'a> {
|
||||
map: Rc<RefCell<Map>>,
|
||||
debug_mode: DebugMode,
|
||||
score: u32,
|
||||
audio: Audio,
|
||||
pub audio: Audio,
|
||||
blinky: Blinky<'a>,
|
||||
edibles: Vec<Edible<'a>>,
|
||||
}
|
||||
@@ -64,11 +65,7 @@ impl<'a> Game<'a> {
|
||||
let pacman_atlas = texture_creator
|
||||
.load_texture_bytes(&pacman_bytes)
|
||||
.expect("Could not load pacman texture from asset API");
|
||||
let pacman = Rc::new(RefCell::new(Pacman::new(
|
||||
(1, 1),
|
||||
pacman_atlas,
|
||||
Rc::clone(&map),
|
||||
)));
|
||||
let pacman = Rc::new(RefCell::new(Pacman::new((1, 1), pacman_atlas, Rc::clone(&map))));
|
||||
|
||||
// Load ghost textures
|
||||
let ghost_body_bytes = get_asset_bytes(Asset::GhostBody).expect("Failed to load asset");
|
||||
@@ -111,21 +108,6 @@ impl<'a> Game<'a> {
|
||||
None,
|
||||
));
|
||||
|
||||
// Load font from asset API
|
||||
let font = {
|
||||
let font_bytes = get_asset_bytes(Asset::FontKonami)
|
||||
.expect("Failed to load asset")
|
||||
.into_owned();
|
||||
let font_bytes_static: &'static [u8] = Box::leak(font_bytes.into_boxed_slice());
|
||||
let font_rwops =
|
||||
RWops::from_bytes(font_bytes_static).expect("Failed to create RWops for font");
|
||||
ttf_context
|
||||
.load_font_from_rwops(font_rwops, 24)
|
||||
.expect("Could not load font from asset API")
|
||||
};
|
||||
|
||||
let audio = Audio::new();
|
||||
|
||||
// Load map texture from asset API
|
||||
let map_bytes = get_asset_bytes(Asset::Map).expect("Failed to load asset");
|
||||
let mut map_texture = texture_creator
|
||||
@@ -140,6 +122,18 @@ impl<'a> Game<'a> {
|
||||
Rc::clone(&pellet_texture), // placeholder for fruit sprite
|
||||
);
|
||||
|
||||
// Load font from asset API
|
||||
let font = {
|
||||
let font_bytes = get_asset_bytes(Asset::FontKonami).expect("Failed to load asset").into_owned();
|
||||
let font_bytes_static: &'static [u8] = Box::leak(font_bytes.into_boxed_slice());
|
||||
let font_rwops = RWops::from_bytes(font_bytes_static).expect("Failed to create RWops for font");
|
||||
ttf_context
|
||||
.load_font_from_rwops(font_rwops, 24)
|
||||
.expect("Could not load font from asset API")
|
||||
};
|
||||
|
||||
let audio = Audio::new();
|
||||
|
||||
Game {
|
||||
canvas,
|
||||
pacman,
|
||||
@@ -180,6 +174,12 @@ impl<'a> Game<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle mute
|
||||
if keycode == Keycode::M {
|
||||
self.audio.set_mute(self.audio.is_muted().not());
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset game
|
||||
if keycode == Keycode::R {
|
||||
self.reset();
|
||||
@@ -306,18 +306,9 @@ impl<'a> Game<'a> {
|
||||
// Draw the debug grid
|
||||
match self.debug_mode {
|
||||
DebugMode::Grid => {
|
||||
DebugRenderer::draw_debug_grid(
|
||||
self.canvas,
|
||||
&self.map.borrow(),
|
||||
self.pacman.borrow().base.base.cell_position,
|
||||
);
|
||||
let next_cell =
|
||||
<Pacman as crate::entity::Moving>::next_cell(&*self.pacman.borrow(), None);
|
||||
DebugRenderer::draw_next_cell(
|
||||
self.canvas,
|
||||
&self.map.borrow(),
|
||||
(next_cell.0 as u32, next_cell.1 as u32),
|
||||
);
|
||||
DebugRenderer::draw_debug_grid(self.canvas, &self.map.borrow(), self.pacman.borrow().base.base.cell_position);
|
||||
let next_cell = <Pacman as crate::entity::Moving>::next_cell(&*self.pacman.borrow(), None);
|
||||
DebugRenderer::draw_next_cell(self.canvas, &self.map.borrow(), (next_cell.0 as u32, next_cell.1 as u32));
|
||||
}
|
||||
DebugMode::ValidPositions => {
|
||||
DebugRenderer::draw_valid_positions(self.canvas, &mut self.map.borrow_mut());
|
||||
@@ -358,11 +349,7 @@ impl<'a> Game<'a> {
|
||||
|
||||
/// Renders text to the screen at the given position.
|
||||
fn render_text(&mut self, text: &str, position: (i32, i32), color: Color) {
|
||||
let surface = self
|
||||
.font
|
||||
.render(text)
|
||||
.blended(color)
|
||||
.expect("Could not render text surface");
|
||||
let surface = self.font.render(text).blended(color).expect("Could not render text surface");
|
||||
|
||||
let texture_creator = self.canvas.texture_creator();
|
||||
let texture = texture_creator
|
||||
|
||||
34
src/ghost.rs
34
src/ghost.rs
@@ -121,22 +121,14 @@ impl Ghost<'_> {
|
||||
let mut possible_moves = Vec::new();
|
||||
|
||||
// Check all four directions
|
||||
for dir in &[
|
||||
Direction::Up,
|
||||
Direction::Down,
|
||||
Direction::Left,
|
||||
Direction::Right,
|
||||
] {
|
||||
for dir in &[Direction::Up, Direction::Down, Direction::Left, Direction::Right] {
|
||||
// Don't allow reversing direction
|
||||
if *dir == self.base.direction.opposite() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let next_cell = self.base.next_cell(Some(*dir));
|
||||
if !matches!(
|
||||
self.base.map.borrow().get_tile(next_cell),
|
||||
Some(MapTile::Wall)
|
||||
) {
|
||||
if !matches!(self.base.map.borrow().get_tile(next_cell), Some(MapTile::Wall)) {
|
||||
possible_moves.push(next_cell);
|
||||
}
|
||||
}
|
||||
@@ -185,12 +177,7 @@ impl Ghost<'_> {
|
||||
successors.push(((1, p.1), 1));
|
||||
}
|
||||
}
|
||||
for dir in &[
|
||||
Direction::Up,
|
||||
Direction::Down,
|
||||
Direction::Left,
|
||||
Direction::Right,
|
||||
] {
|
||||
for dir in &[Direction::Up, Direction::Down, Direction::Left, Direction::Right] {
|
||||
let (dx, dy) = dir.offset();
|
||||
let next_p = (p.0 as i32 + dx, p.1 as i32 + dy);
|
||||
if let Some(tile) = map.get_tile(next_p) {
|
||||
@@ -209,9 +196,8 @@ impl Ghost<'_> {
|
||||
/// Changes the ghost's mode and handles direction reversal
|
||||
pub fn set_mode(&mut self, new_mode: GhostMode) {
|
||||
// Don't reverse if going to/from frightened or if in house
|
||||
let should_reverse = self.mode != GhostMode::House
|
||||
&& new_mode != GhostMode::Frightened
|
||||
&& self.mode != GhostMode::Frightened;
|
||||
let should_reverse =
|
||||
self.mode != GhostMode::House && new_mode != GhostMode::Frightened && self.mode != GhostMode::Frightened;
|
||||
|
||||
self.mode = new_mode;
|
||||
|
||||
@@ -224,8 +210,7 @@ impl Ghost<'_> {
|
||||
};
|
||||
|
||||
if should_reverse {
|
||||
self.base
|
||||
.set_direction_if_valid(self.base.direction.opposite());
|
||||
self.base.set_direction_if_valid(self.base.direction.opposite());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,9 +226,7 @@ impl Ghost<'_> {
|
||||
if !self.base.handle_tunnel() {
|
||||
// Pathfinding logic (only if not in tunnel)
|
||||
let target_tile = self.get_target_tile();
|
||||
if let Some((path, _)) =
|
||||
self.get_path_to_target((target_tile.0 as u32, target_tile.1 as u32))
|
||||
{
|
||||
if let Some((path, _)) = self.get_path_to_target((target_tile.0 as u32, target_tile.1 as u32)) {
|
||||
if path.len() > 1 {
|
||||
let next_move = path[1];
|
||||
let (x, y) = self.base.base.cell_position;
|
||||
@@ -318,7 +301,6 @@ impl<'a> Renderable for Ghost<'a> {
|
||||
Direction::Down => 3,
|
||||
}
|
||||
};
|
||||
self.eyes_sprite
|
||||
.render(canvas, pos, Direction::Right, Some(eye_frame));
|
||||
self.eyes_sprite.render(canvas, pos, Direction::Right, Some(eye_frame));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,7 @@ impl<'a> Blinky<'a> {
|
||||
pacman: Rc<RefCell<Pacman<'a>>>,
|
||||
) -> Blinky<'a> {
|
||||
Blinky {
|
||||
ghost: Ghost::new(
|
||||
GhostType::Blinky,
|
||||
starting_position,
|
||||
body_texture,
|
||||
eyes_texture,
|
||||
map,
|
||||
pacman,
|
||||
),
|
||||
ghost: Ghost::new(GhostType::Blinky, starting_position, body_texture, eyes_texture, map, pacman),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `a` - First position as (x, y) coordinates
|
||||
/// * `b` - Second position as (x, y) coordinates
|
||||
/// * `b` - Second position as (x, y) coordinates
|
||||
/// * `diagonal` - Whether to consider diagonal adjacency (true) or only orthogonal (false)
|
||||
///
|
||||
/// # Returns
|
||||
@@ -94,14 +94,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_commutative_property() {
|
||||
// The function should work the same regardless of parameter order
|
||||
assert_eq!(
|
||||
is_adjacent((1, 2), (2, 2), false),
|
||||
is_adjacent((2, 2), (1, 2), false)
|
||||
);
|
||||
assert_eq!(is_adjacent((1, 2), (2, 2), false), is_adjacent((2, 2), (1, 2), false));
|
||||
|
||||
assert_eq!(
|
||||
is_adjacent((1, 2), (2, 3), true),
|
||||
is_adjacent((2, 3), (1, 2), true)
|
||||
);
|
||||
assert_eq!(is_adjacent((1, 2), (2, 3), true), is_adjacent((2, 3), (1, 2), true));
|
||||
}
|
||||
}
|
||||
|
||||
25
src/main.rs
25
src/main.rs
@@ -53,6 +53,7 @@ unsafe fn attach_console() {
|
||||
}
|
||||
|
||||
mod animation;
|
||||
mod asset;
|
||||
mod audio;
|
||||
mod constants;
|
||||
mod debug;
|
||||
@@ -66,7 +67,6 @@ mod helper;
|
||||
mod map;
|
||||
mod modulation;
|
||||
mod pacman;
|
||||
mod asset;
|
||||
|
||||
/// The main entry point of the application.
|
||||
///
|
||||
@@ -99,26 +99,17 @@ pub fn main() {
|
||||
.build()
|
||||
.expect("Could not initialize window");
|
||||
|
||||
let mut canvas = window
|
||||
.into_canvas()
|
||||
.build()
|
||||
.expect("Could not build canvas");
|
||||
let mut canvas = window.into_canvas().build().expect("Could not build canvas");
|
||||
|
||||
canvas
|
||||
.set_logical_size(WINDOW_WIDTH, WINDOW_HEIGHT)
|
||||
.expect("Could not set logical size");
|
||||
|
||||
let texture_creator = canvas.texture_creator();
|
||||
let mut game = Game::new(
|
||||
&mut canvas,
|
||||
&texture_creator,
|
||||
&ttf_context,
|
||||
&audio_subsystem,
|
||||
);
|
||||
let mut game = Game::new(&mut canvas, &texture_creator, &ttf_context, &audio_subsystem);
|
||||
game.audio.set_mute(cfg!(debug_assertions));
|
||||
|
||||
let mut event_pump = sdl_context
|
||||
.event_pump()
|
||||
.expect("Could not get SDL EventPump");
|
||||
let mut event_pump = sdl_context.event_pump().expect("Could not get SDL EventPump");
|
||||
|
||||
// Initial draw and tick
|
||||
game.draw();
|
||||
@@ -169,11 +160,7 @@ pub fn main() {
|
||||
..
|
||||
} => {
|
||||
paused = !paused;
|
||||
event!(
|
||||
tracing::Level::INFO,
|
||||
"{}",
|
||||
if paused { "Paused" } else { "Unpaused" }
|
||||
);
|
||||
event!(tracing::Level::INFO, "{}", if paused { "Paused" } else { "Unpaused" });
|
||||
}
|
||||
Event::KeyDown { keycode, .. } => {
|
||||
game.keyboard_event(keycode.unwrap());
|
||||
|
||||
19
src/map.rs
19
src/map.rs
@@ -75,9 +75,7 @@ impl Map {
|
||||
'o' => MapTile::PowerPellet,
|
||||
' ' => MapTile::Empty,
|
||||
'T' => MapTile::Tunnel,
|
||||
c @ '0' | c @ '1' | c @ '2' | c @ '3' | c @ '4' => {
|
||||
MapTile::StartingPosition(c.to_digit(10).unwrap() as u8)
|
||||
}
|
||||
c @ '0' | c @ '1' | c @ '2' | c @ '3' | c @ '4' => MapTile::StartingPosition(c.to_digit(10).unwrap() as u8),
|
||||
'=' => MapTile::Empty,
|
||||
_ => panic!("Unknown character in board: {character}"),
|
||||
};
|
||||
@@ -94,12 +92,7 @@ impl Map {
|
||||
/// Resets the map to its original state.
|
||||
pub fn reset(&mut self) {
|
||||
// Restore the map to its original state
|
||||
for (x, col) in self
|
||||
.current
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.take(BOARD_WIDTH as usize)
|
||||
{
|
||||
for (x, col) in self.current.iter_mut().enumerate().take(BOARD_WIDTH as usize) {
|
||||
for (y, cell) in col.iter_mut().enumerate().take(BOARD_HEIGHT as usize) {
|
||||
*cell = self.default[x][y];
|
||||
}
|
||||
@@ -146,10 +139,7 @@ impl Map {
|
||||
///
|
||||
/// * `cell` - The cell coordinates, in grid coordinates.
|
||||
pub fn cell_to_pixel(cell: (u32, u32)) -> (i32, i32) {
|
||||
(
|
||||
(cell.0 * CELL_SIZE) as i32,
|
||||
((cell.1 + BOARD_OFFSET.1) * CELL_SIZE) as i32,
|
||||
)
|
||||
((cell.0 * CELL_SIZE) as i32, ((cell.1 + BOARD_OFFSET.1) * CELL_SIZE) as i32)
|
||||
}
|
||||
|
||||
/// Returns a reference to a cached vector of all valid playable positions in the maze.
|
||||
@@ -198,8 +188,7 @@ impl Map {
|
||||
] {
|
||||
let neighbor = pos + offset;
|
||||
if neighbor.x < BOARD_WIDTH && neighbor.y < BOARD_HEIGHT {
|
||||
let neighbor_tile =
|
||||
self.current[neighbor.x as usize][neighbor.y as usize];
|
||||
let neighbor_tile = self.current[neighbor.x as usize][neighbor.y as usize];
|
||||
if matches!(neighbor_tile, Empty | Pellet | PowerPellet) {
|
||||
queue.push_back(neighbor);
|
||||
}
|
||||
|
||||
@@ -58,11 +58,7 @@ impl<'a> Moving for Pacman<'a> {
|
||||
|
||||
impl Pacman<'_> {
|
||||
/// Creates a new `Pacman` instance.
|
||||
pub fn new<'a>(
|
||||
starting_position: (u32, u32),
|
||||
atlas: Texture<'a>,
|
||||
map: Rc<RefCell<Map>>,
|
||||
) -> Pacman<'a> {
|
||||
pub fn new<'a>(starting_position: (u32, u32), atlas: Texture<'a>, map: Rc<RefCell<Map>>) -> Pacman<'a> {
|
||||
let pixel_position = Map::cell_to_pixel(starting_position);
|
||||
Pacman {
|
||||
base: MovableEntity::new(
|
||||
|
||||
Reference in New Issue
Block a user