mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-09 04:07:57 -06:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c489f32908 | |||
| b91f70cf2f | |||
| 24a207be01 | |||
| 44e31d9b21 | |||
|
|
b67234765a | ||
|
|
d07498c30e |
18
.github/workflows/build.yaml
vendored
18
.github/workflows/build.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Rust Toolchain
|
- name: Setup Rust Toolchain
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
@@ -64,15 +64,16 @@ jobs:
|
|||||||
run: cargo build --release
|
run: cargo build --release
|
||||||
|
|
||||||
- name: Acquire Package Version
|
- name: Acquire Package Version
|
||||||
shell: bash
|
id: get_version
|
||||||
|
shell: bash # required to prevent Windows runners from failing
|
||||||
run: |
|
run: |
|
||||||
PACKAGE_VERSION=$(cargo metadata --format-version 1 --no-deps | jq '.packages[0].version' -r)
|
set -euo pipefail # exit on error
|
||||||
echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> $GITHUB_ENV
|
echo "version=$(cargo metadata --format-version 1 --no-deps | jq '.packages[0].version' -r)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: "pacman-${{ env.PACKAGE_VERSION }}-${{ matrix.target }}"
|
name: "pacman-${{ steps.get_version.outputs.version }}-${{ matrix.target }}"
|
||||||
path: ./target/release/${{ matrix.artifact_name }}
|
path: ./target/release/${{ matrix.artifact_name }}
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
@@ -83,10 +84,13 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pages: write
|
pages: write
|
||||||
id-token: write
|
id-token: write
|
||||||
|
# concurrency group is used to prevent multiple page deployments from being attempted at the same time
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-wasm
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Emscripten SDK
|
- name: Setup Emscripten SDK
|
||||||
uses: pyodide/setup-emsdk@v15
|
uses: pyodide/setup-emsdk@v15
|
||||||
@@ -98,7 +102,7 @@ jobs:
|
|||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
target: wasm32-unknown-emscripten
|
target: wasm32-unknown-emscripten
|
||||||
toolchain: 1.86.0 # we are unfortunately pinned to 1.86.0 for some reason, bulk-memory-opt related issues
|
toolchain: 1.86.0
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|||||||
2
.github/workflows/coverage.yaml
vendored
2
.github/workflows/coverage.yaml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
|
|||||||
2
.github/workflows/tests.yaml
vendored
2
.github/workflows/tests.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ emsdk/
|
|||||||
rust-sdl2-emscripten/
|
rust-sdl2-emscripten/
|
||||||
assets/site/build.css
|
assets/site/build.css
|
||||||
tailwindcss-*
|
tailwindcss-*
|
||||||
|
lcov.info
|
||||||
|
|||||||
42
Cargo.lock
generated
42
Cargo.lock
generated
@@ -13,9 +13,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.98"
|
version = "1.0.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
@@ -79,9 +79,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glam"
|
name = "glam"
|
||||||
version = "0.30.4"
|
version = "0.30.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11"
|
checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
@@ -128,9 +128,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.174"
|
version = "0.2.175"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
@@ -202,7 +202,7 @@ dependencies = [
|
|||||||
"spin_sleep",
|
"spin_sleep",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"thiserror 1.0.69",
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -220,7 +220,7 @@ dependencies = [
|
|||||||
"integer-sqrt",
|
"integer-sqrt",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"thiserror 2.0.12",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -380,9 +380,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.141"
|
version = "1.0.142"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -443,33 +443,13 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl 1.0.69",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.12"
|
version = "2.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 2.0.12",
|
"thiserror-impl",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "1.0.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ spin_sleep = "1.3.2"
|
|||||||
rand = { version = "0.9.2", default-features = false, features = ["small_rng", "os_rng"] }
|
rand = { version = "0.9.2", default-features = false, features = ["small_rng", "os_rng"] }
|
||||||
pathfinding = "4.14"
|
pathfinding = "4.14"
|
||||||
once_cell = "1.21.3"
|
once_cell = "1.21.3"
|
||||||
thiserror = "1.0"
|
thiserror = "2.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
glam = { version = "0.30.4", features = [] }
|
glam = { version = "0.30.5", features = [] }
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.141"
|
serde_json = "1.0.142"
|
||||||
smallvec = "1.15.1"
|
smallvec = "1.15.1"
|
||||||
strum = "0.27.2"
|
strum = "0.27.2"
|
||||||
strum_macros = "0.27.2"
|
strum_macros = "0.27.2"
|
||||||
@@ -56,4 +56,4 @@ x86_64-apple-darwin = { triplet = "x64-osx" }
|
|||||||
aarch64-apple-darwin = { triplet = "arm64-osx" }
|
aarch64-apple-darwin = { triplet = "arm64-osx" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "emscripten")'.dependencies]
|
[target.'cfg(target_os = "emscripten")'.dependencies]
|
||||||
libc = "0.2.16"
|
libc = "0.2.175"
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ I wanted to hit a log of goals and features, making it a 'perfect' project that
|
|||||||
|
|
||||||
Since this project is still in progress, I'm only going to cover non-obvious build details. By reading the code, build scripts, and copying the online build workflows, you should be able to replicate the build process.
|
Since this project is still in progress, I'm only going to cover non-obvious build details. By reading the code, build scripts, and copying the online build workflows, you should be able to replicate the build process.
|
||||||
|
|
||||||
|
- We use rustc 1.86.0 for the build, due to bulk-memory-opt related issues on wasm32-unknown-emscripten.
|
||||||
|
- Technically, we could probably use stable or even nightly on desktop targets, but using different versions for different targets is a pain, mainly because of clippy warnings changing between versions.
|
||||||
- Install `cargo-vcpkg` with `cargo install cargo-vcpkg`, then run `cargo vcpkg build` to build the requisite dependencies via vcpkg.
|
- Install `cargo-vcpkg` with `cargo install cargo-vcpkg`, then run `cargo vcpkg build` to build the requisite dependencies via vcpkg.
|
||||||
- For the WASM build, you need to have the Emscripten SDK cloned; you can do so with `git clone https://github.com/emscripten-core/emsdk.git`
|
- For the WASM build, you need to have the Emscripten SDK cloned; you can do so with `git clone https://github.com/emscripten-core/emsdk.git`
|
||||||
- The first time you clone, you'll need to install the appropriate SDK version with `./emsdk install 3.1.43` and then activate it with `./emsdk activate 3.1.43`. On Windows, use `./emsdk/emsdk.ps1` instead.
|
- The first time you clone, you'll need to install the appropriate SDK version with `./emsdk install 3.1.43` and then activate it with `./emsdk activate 3.1.43`. On Windows, use `./emsdk/emsdk.ps1` instead.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
|
# we are unfortunately pinned to 1.86.0 for some reason, bulk-memory-opt related issues on wasm32-unknown-emscripten
|
||||||
channel = "1.86.0"
|
channel = "1.86.0"
|
||||||
components = ["rustfmt", "llvm-tools-preview", "clippy"]
|
components = ["rustfmt", "llvm-tools-preview", "clippy"]
|
||||||
|
|||||||
36
src/app.rs
36
src/app.rs
@@ -4,8 +4,9 @@ use glam::Vec2;
|
|||||||
use sdl2::event::{Event, WindowEvent};
|
use sdl2::event::{Event, WindowEvent};
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
use sdl2::render::{Canvas, ScaleMode, Texture, TextureCreator};
|
use sdl2::render::{Canvas, ScaleMode, Texture, TextureCreator};
|
||||||
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
use sdl2::video::{Window, WindowContext};
|
use sdl2::video::{Window, WindowContext};
|
||||||
use sdl2::EventPump;
|
use sdl2::{AudioSubsystem, EventPump, Sdl, VideoSubsystem};
|
||||||
use tracing::{error, event};
|
use tracing::{error, event};
|
||||||
|
|
||||||
use crate::error::{GameError, GameResult};
|
use crate::error::{GameError, GameResult};
|
||||||
@@ -14,26 +15,31 @@ use crate::constants::{CANVAS_SIZE, LOOP_TIME, SCALE};
|
|||||||
use crate::game::Game;
|
use crate::game::Game;
|
||||||
use crate::platform::get_platform;
|
use crate::platform::get_platform;
|
||||||
|
|
||||||
pub struct App<'a> {
|
pub struct App {
|
||||||
game: Game,
|
game: Game,
|
||||||
canvas: Canvas<Window>,
|
canvas: Canvas<Window>,
|
||||||
event_pump: EventPump,
|
event_pump: &'static mut EventPump,
|
||||||
backbuffer: Texture<'a>,
|
backbuffer: Texture<'static>,
|
||||||
paused: bool,
|
paused: bool,
|
||||||
last_tick: Instant,
|
last_tick: Instant,
|
||||||
cursor_pos: Vec2,
|
cursor_pos: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App<'_> {
|
impl App {
|
||||||
pub fn new() -> GameResult<Self> {
|
pub fn new() -> GameResult<Self> {
|
||||||
|
let sdl_context: &'static Sdl = Box::leak(Box::new(sdl2::init().map_err(|e| GameError::Sdl(e.to_string()))?));
|
||||||
|
let video_subsystem: &'static VideoSubsystem =
|
||||||
|
Box::leak(Box::new(sdl_context.video().map_err(|e| GameError::Sdl(e.to_string()))?));
|
||||||
|
let audio_subsystem: &'static AudioSubsystem =
|
||||||
|
Box::leak(Box::new(sdl_context.audio().map_err(|e| GameError::Sdl(e.to_string()))?));
|
||||||
|
let ttf_context: &'static Sdl2TtfContext =
|
||||||
|
Box::leak(Box::new(sdl2::ttf::init().map_err(|e| GameError::Sdl(e.to_string()))?));
|
||||||
|
let event_pump: &'static mut EventPump =
|
||||||
|
Box::leak(Box::new(sdl_context.event_pump().map_err(|e| GameError::Sdl(e.to_string()))?));
|
||||||
|
|
||||||
// Initialize platform-specific console
|
// Initialize platform-specific console
|
||||||
get_platform().init_console()?;
|
get_platform().init_console()?;
|
||||||
|
|
||||||
let sdl_context = sdl2::init().map_err(|e| GameError::Sdl(e.to_string()))?;
|
|
||||||
let video_subsystem = sdl_context.video().map_err(|e| GameError::Sdl(e.to_string()))?;
|
|
||||||
let audio_subsystem = sdl_context.audio().map_err(|e| GameError::Sdl(e.to_string()))?;
|
|
||||||
let ttf_context = sdl2::ttf::init().map_err(|e| GameError::Sdl(e.to_string()))?;
|
|
||||||
|
|
||||||
let window = video_subsystem
|
let window = video_subsystem
|
||||||
.window(
|
.window(
|
||||||
"Pac-Man",
|
"Pac-Man",
|
||||||
@@ -50,18 +56,16 @@ impl App<'_> {
|
|||||||
.set_logical_size(CANVAS_SIZE.x, CANVAS_SIZE.y)
|
.set_logical_size(CANVAS_SIZE.x, CANVAS_SIZE.y)
|
||||||
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
||||||
|
|
||||||
let texture_creator_static: &'static TextureCreator<WindowContext> = Box::leak(Box::new(canvas.texture_creator()));
|
let texture_creator: &'static TextureCreator<WindowContext> = Box::leak(Box::new(canvas.texture_creator()));
|
||||||
|
|
||||||
let mut game = Game::new(texture_creator_static, &ttf_context, &audio_subsystem)?;
|
let mut game = Game::new(texture_creator, ttf_context, audio_subsystem)?;
|
||||||
game.audio.set_mute(cfg!(debug_assertions));
|
// game.audio.set_mute(cfg!(debug_assertions));
|
||||||
|
|
||||||
let mut backbuffer = texture_creator_static
|
let mut backbuffer = texture_creator
|
||||||
.create_texture_target(None, CANVAS_SIZE.x, CANVAS_SIZE.y)
|
.create_texture_target(None, CANVAS_SIZE.x, CANVAS_SIZE.y)
|
||||||
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
||||||
backbuffer.set_scale_mode(ScaleMode::Nearest);
|
backbuffer.set_scale_mode(ScaleMode::Nearest);
|
||||||
|
|
||||||
let event_pump = sdl_context.event_pump().map_err(|e| GameError::Sdl(e.to_string()))?;
|
|
||||||
|
|
||||||
// Initial draw
|
// Initial draw
|
||||||
game.draw(&mut canvas, &mut backbuffer)
|
game.draw(&mut canvas, &mut backbuffer)
|
||||||
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
.map_err(|e| GameError::Sdl(e.to_string()))?;
|
||||||
|
|||||||
14
src/game.rs
14
src/game.rs
@@ -25,7 +25,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
map::Map,
|
map::Map,
|
||||||
texture::{
|
texture::{
|
||||||
sprite::{self, AtlasMapper, AtlasTile, SpriteAtlas},
|
sprite::{AtlasMapper, AtlasTile, SpriteAtlas},
|
||||||
text::TextTexture,
|
text::TextTexture,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -59,7 +59,7 @@ pub struct Game {
|
|||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
texture_creator: &TextureCreator<WindowContext>,
|
texture_creator: &'static TextureCreator<WindowContext>,
|
||||||
_ttf_context: &sdl2::ttf::Sdl2TtfContext,
|
_ttf_context: &sdl2::ttf::Sdl2TtfContext,
|
||||||
_audio_subsystem: &sdl2::AudioSubsystem,
|
_audio_subsystem: &sdl2::AudioSubsystem,
|
||||||
) -> GameResult<Game> {
|
) -> GameResult<Game> {
|
||||||
@@ -74,19 +74,16 @@ impl Game {
|
|||||||
.ok_or_else(|| GameError::NotFound("Pac-Man starting position not found in graph".to_string()))?;
|
.ok_or_else(|| GameError::NotFound("Pac-Man starting position not found in graph".to_string()))?;
|
||||||
|
|
||||||
let atlas_bytes = get_asset_bytes(Asset::Atlas)?;
|
let atlas_bytes = get_asset_bytes(Asset::Atlas)?;
|
||||||
let atlas_texture = unsafe {
|
let atlas_texture = Box::leak(Box::new(texture_creator.load_texture_bytes(&atlas_bytes).map_err(|e| {
|
||||||
let texture = texture_creator.load_texture_bytes(&atlas_bytes).map_err(|e| {
|
|
||||||
if e.to_string().contains("format") || e.to_string().contains("unsupported") {
|
if e.to_string().contains("format") || e.to_string().contains("unsupported") {
|
||||||
GameError::Texture(TextureError::InvalidFormat(format!("Unsupported texture format: {e}")))
|
GameError::Texture(TextureError::InvalidFormat(format!("Unsupported texture format: {e}")))
|
||||||
} else {
|
} else {
|
||||||
GameError::Texture(TextureError::LoadFailed(e.to_string()))
|
GameError::Texture(TextureError::LoadFailed(e.to_string()))
|
||||||
}
|
}
|
||||||
})?;
|
})?));
|
||||||
sprite::texture_to_static(texture)
|
|
||||||
};
|
|
||||||
let atlas_json = get_asset_bytes(Asset::AtlasJson)?;
|
let atlas_json = get_asset_bytes(Asset::AtlasJson)?;
|
||||||
let atlas_mapper: AtlasMapper = serde_json::from_slice(&atlas_json)?;
|
let atlas_mapper: AtlasMapper = serde_json::from_slice(&atlas_json)?;
|
||||||
let atlas = SpriteAtlas::new(atlas_texture, atlas_mapper);
|
let atlas = SpriteAtlas::new(unsafe { std::mem::transmute_copy(atlas_texture) }, atlas_mapper);
|
||||||
|
|
||||||
let mut map_texture = SpriteAtlas::get_tile(&atlas, "maze/full.png")
|
let mut map_texture = SpriteAtlas::get_tile(&atlas, "maze/full.png")
|
||||||
.ok_or_else(|| GameError::Texture(TextureError::AtlasTileNotFound("maze/full.png".to_string())))?;
|
.ok_or_else(|| GameError::Texture(TextureError::AtlasTileNotFound("maze/full.png".to_string())))?;
|
||||||
@@ -255,6 +252,7 @@ impl Game {
|
|||||||
if !item.is_collected() {
|
if !item.is_collected() {
|
||||||
item.collect();
|
item.collect();
|
||||||
self.score += item.get_score();
|
self.score += item.get_score();
|
||||||
|
self.audio.eat();
|
||||||
|
|
||||||
// Handle energizer effects
|
// Handle energizer effects
|
||||||
if matches!(item.item_type, crate::entity::item::ItemType::Energizer) {
|
if matches!(item.item_type, crate::entity::item::ItemType::Energizer) {
|
||||||
|
|||||||
@@ -138,20 +138,3 @@ impl SpriteAtlas {
|
|||||||
self.default_color
|
self.default_color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Texture` to a `Texture<'static>` using transmute.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// This function is unsafe because it uses `std::mem::transmute` to change the lifetime
|
|
||||||
/// of the texture from the original lifetime to `'static`. The caller must ensure that:
|
|
||||||
///
|
|
||||||
/// - The original `Texture` will live for the entire duration of the program
|
|
||||||
/// - No references to the original texture exist that could become invalid
|
|
||||||
/// - The texture is not dropped while still being used as a `'static` reference
|
|
||||||
///
|
|
||||||
/// This is typically used when you have a texture that you know will live for the entire
|
|
||||||
/// program duration and need to store it in a structure that requires a `'static` lifetime.
|
|
||||||
pub unsafe fn texture_to_static(texture: Texture) -> Texture<'static> {
|
|
||||||
std::mem::transmute(texture)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ fn test_fruit_kind_increasing_score() {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
kinds.sort_unstable_by_key(|(index, _)| *index);
|
kinds.sort_unstable_by_key(|(index, _)| *index);
|
||||||
|
|
||||||
assert_eq!(kinds.len(), FruitKind::COUNT as usize);
|
assert_eq!(kinds.len(), FruitKind::COUNT);
|
||||||
|
|
||||||
// Check that the score increases as expected
|
// Check that the score increases as expected
|
||||||
for window in kinds.windows(2) {
|
for window in kinds.windows(2) {
|
||||||
|
|||||||
Reference in New Issue
Block a user