mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-07 01:15:48 -06:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0630fc56ec | |||
| 98d8960c57 | |||
| 394344c11f | |||
| 93ba470ce9 | |||
| 129aed0ffb | |||
| e062ada301 | |||
| af57199915 | |||
| 538cf1efb5 | |||
| 03b2c5a659 | |||
| 64e226be70 | |||
| f998ddd344 | |||
| b2ad8e7afe |
@@ -1,4 +1,5 @@
|
|||||||
[target.wasm32-unknown-emscripten]
|
[target.wasm32-unknown-emscripten]
|
||||||
|
# TODO: Document what the fuck this is.
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-O", "-C", "link-args=-O2 --profiling",
|
"-O", "-C", "link-args=-O2 --profiling",
|
||||||
#"-C", "link-args=-O3 --closure 1",
|
#"-C", "link-args=-O3 --closure 1",
|
||||||
|
|||||||
8
.github/workflows/deploy.yaml
vendored
8
.github/workflows/deploy.yaml
vendored
@@ -1,13 +1,13 @@
|
|||||||
name: Github Pages
|
name: Github Pages
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-github-pages:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2 # repo checkout
|
- uses: actions/checkout@v2 # repo checkout
|
||||||
|
|
||||||
|
|||||||
7
BUILD.md
Normal file
7
BUILD.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Building Pac-Man
|
||||||
|
|
||||||
|
## GitHub Actions Workflow
|
||||||
|
|
||||||
|
1. Build workflow produces executables & WASM files for all platforms
|
||||||
|
2. Uploaded as artifacts
|
||||||
|
3. Deployment workflow downloads artifacts and uploads to GitHub Pages
|
||||||
@@ -23,6 +23,9 @@ at.
|
|||||||
- More than 4 ghosts
|
- More than 4 ghosts
|
||||||
- Custom Level Generation
|
- Custom Level Generation
|
||||||
- Multi-map tunnelling
|
- Multi-map tunnelling
|
||||||
|
- Online Scoreboard
|
||||||
|
- WebAssembly build contains a special API key for communicating with server.
|
||||||
|
- To prevent abuse, the server will only accept scores from the WebAssembly build.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|||||||
54
STORY.md
Normal file
54
STORY.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Story
|
||||||
|
|
||||||
|
This is living document that describes the story of the project, from inspiration to solution.
|
||||||
|
When a website is available, this document will help curate it's content.
|
||||||
|
|
||||||
|
## Inspiration
|
||||||
|
|
||||||
|
I initially got the idea for this project after finding a video about another Pac-Man clone on YouTube.
|
||||||
|
|
||||||
|
[![Code Review Thumbnail][code-review-thumbnail]][code-review-video]
|
||||||
|
|
||||||
|
This implementation was written in C++, used SDL2 for graphics, and was kinda weird - but it worked.
|
||||||
|
|
||||||
|
- I think it was weird because the way it linked files together is extremely non-standard.
|
||||||
|
Essentially, it was a single file that included all the other files. This is not how C++ projects are typically structured.
|
||||||
|
- This implementation was also extremely dependent on OOP; Rust has no real counterpart for OOP code, so writing my own implementation would be a challenge.
|
||||||
|
|
||||||
|
## Lifetimes
|
||||||
|
|
||||||
|
Rust's SDL2 implementation is a wrapper around the C library, so it's not as nice as the C++ implementation.
|
||||||
|
Additionally, lifetimes in this library are a bit weird, making them quite difficult to deal with.
|
||||||
|
|
||||||
|
I found a whole blog post complaining about this ([1][fighting-lifetimes-1], [2][fighting-lifetimes-2], [3][fighting-lifetimes-3]), so I'm not alone in this.
|
||||||
|
|
||||||
|
## Emscripten & RuggRogue
|
||||||
|
|
||||||
|
One of the targets for this project is to build a web-accessible version of the game. If you were watching at all during
|
||||||
|
the Rust hype, one of it's primary selling points was a growing community of Rust-based web applications, thanks to
|
||||||
|
WebAssembly.
|
||||||
|
|
||||||
|
The problem is that much of this work was done for pure-Rust applications - and SDL is C++.
|
||||||
|
This requires a C++ WebAssembly compiler such as Emscripten; and it's a pain to get working.
|
||||||
|
|
||||||
|
Luckily though, someone else has done this before, and they fully documented it - [RuggRouge][ruggrouge].
|
||||||
|
- Built with Rust
|
||||||
|
- Uses SDL2
|
||||||
|
- Compiling for WebAssembly with Emscripten
|
||||||
|
- Also compiles for Windows & Linux
|
||||||
|
|
||||||
|
This repository has been massively helpful in getting my WebAssembly builds working.
|
||||||
|
|
||||||
|
## Key Capturing Extensions in WASM Build
|
||||||
|
|
||||||
|
Some extensions I had installed were capturing keys.
|
||||||
|
The issue presented with some keys never being sent to the application.
|
||||||
|
To confirm, enter safe mode or switch to a different browser without said extensions.
|
||||||
|
If the issue disappears, it's because of an extension in your browser stealing keys in a way that is incompatible with the batshit insanity of Emscripten.
|
||||||
|
|
||||||
|
[code-review-video]: https://www.youtube.com/watch?v=OKs_JewEeOo
|
||||||
|
[code-review-thumbnail]: https://img.youtube.com/vi/OKs_JewEeOo/hqdefault.jpg
|
||||||
|
[fighting-lifetimes-1]: https://devcry.heiho.net/html/2022/20220709-rust-and-sdl2-fighting-with-lifetimes.html
|
||||||
|
[fighting-lifetimes-2]: https://devcry.heiho.net/html/2022/20220716-rust-and-sdl2-fighting-with-lifetimes-2.html
|
||||||
|
[fighting-lifetimes-3]: https://devcry.heiho.net/html/2022/20220724-rust-and-sdl2-fighting-with-lifetimes-3.html
|
||||||
|
[ruggrogue]: https://tung.github.io/ruggrogue/
|
||||||
@@ -3,16 +3,22 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
</head>
|
</head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<canvas id="canvas"></canvas>
|
<canvas id="canvas"></canvas>
|
||||||
<script>
|
<script>
|
||||||
var Module = {
|
var Module = {
|
||||||
'locateFile': function (path, prefix) {
|
|
||||||
if (path.endsWith(".data")) {
|
|
||||||
return prefix + "deps/" + path;
|
|
||||||
}
|
|
||||||
return prefix + path;
|
|
||||||
},
|
|
||||||
'canvas': document.getElementById('canvas'),
|
'canvas': document.getElementById('canvas'),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
& cargo build --target=wasm32-unknown-emscripten --release
|
|
||||||
|
|
||||||
mkdir -p dist -Force
|
|
||||||
|
|
||||||
cp ./target/wasm32-unknown-emscripten/release/Pac_Man.wasm ./dist
|
|
||||||
cp ./target/wasm32-unknown-emscripten/release/Pac-Man.js ./dist
|
|
||||||
cp index.html dist
|
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -eux
|
# set -eu
|
||||||
|
|
||||||
|
echo "Building WASM with Emscripten"
|
||||||
cargo build --target=wasm32-unknown-emscripten --release
|
cargo build --target=wasm32-unknown-emscripten --release
|
||||||
|
|
||||||
|
echo "Copying release files to dist/"
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
|
output_folder="target/wasm32-unknown-emscripten/release"
|
||||||
cp target/wasm32-unknown-emscripten/release/pacman.wasm dist
|
cp $output_folder/pacman.wasm dist
|
||||||
cp target/wasm32-unknown-emscripten/release/pacman.js dist
|
cp $output_folder/pacman.js dist
|
||||||
cp target/wasm32-unknown-emscripten/release/deps/pacman.data dist/deps
|
cp $output_folder/deps/pacman.data dist
|
||||||
cp assets/index.html dist
|
cp assets/index.html dist
|
||||||
28
scripts/build-windows.sh
Executable file
28
scripts/build-windows.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SDL_VERSION="2.28.3"
|
||||||
|
SDL_IMAGE_VERSION="2.6.3"
|
||||||
|
SDL_MIXER_VERSION="2.6.3"
|
||||||
|
SDL_TTF_VERSION="2.20.2"
|
||||||
|
|
||||||
|
SDL="https://github.com/libsdl-org/SDL/releases/download/release-${SDL_VERSION}/SDL2-devel-${SDL_VERSION}-mingw.tar.gz"
|
||||||
|
SLD_IMAGE="https://github.com/libsdl-org/SDL_image/releases/download/release-${SDL_IMAGE_VERSION}/SDL2_image-devel-${SDL_IMAGE_VERSION}-mingw.tar.gz"
|
||||||
|
SDL_MIXER="https://github.com/libsdl-org/SDL_mixer/releases/download/release-${SDL_MIXER_VERSION}/SDL2_mixer-devel-${SDL_MIXER_VERSION}-mingw.tar.gz"
|
||||||
|
SDL_TTF="https://github.com/libsdl-org/SDL_ttf/releases/download/release-${SDL_TTF_VERSION}/SDL_ttf-devel-${SDL_TTF_VERSION}-mingw.tar.gz"
|
||||||
|
|
||||||
|
# Verify that toolchain is installed
|
||||||
|
|
||||||
|
|
||||||
|
# EXTRACT_DIR="~/.rustup/"
|
||||||
|
EXTRACT_DIR="~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/"
|
||||||
|
# if [ ! -d "~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/" ]; then
|
||||||
|
# ls $EXTRACT_DIR
|
||||||
|
# echo "Toolchain not installed. Run rustup target add x86_64-pc-windows-gnu. This may not work on environments besides Linux GNU."
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
|
||||||
|
echo "Downloading..."
|
||||||
|
curl -L -o ./sdl2.tar.gz $SDL
|
||||||
|
curl -L -o ./sdl2_image.tar.gz $SLD_IMAGE
|
||||||
|
echo "Done."
|
||||||
@@ -92,6 +92,7 @@ impl<'a> AnimatedTexture<'a> {
|
|||||||
direction: Direction,
|
direction: Direction,
|
||||||
frame: u32,
|
frame: u32,
|
||||||
) {
|
) {
|
||||||
|
// TODO: If the frame we're targeting is in the opposite direction (due to self.reverse), we should pre-emptively reverse.
|
||||||
let current = self.current_frame();
|
let current = self.current_frame();
|
||||||
self.render_static(canvas, position, direction, Some(current));
|
self.render_static(canvas, position, direction, Some(current));
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use sdl2::keyboard::Keycode;
|
|||||||
use sdl2::render::{Texture, TextureCreator};
|
use sdl2::render::{Texture, TextureCreator};
|
||||||
use sdl2::video::WindowContext;
|
use sdl2::video::WindowContext;
|
||||||
use sdl2::{pixels::Color, render::Canvas, video::Window};
|
use sdl2::{pixels::Color, render::Canvas, video::Window};
|
||||||
use tracing::event;
|
|
||||||
|
|
||||||
use crate::constants::{MapTile, BOARD_HEIGHT, BOARD_WIDTH, RAW_BOARD};
|
use crate::constants::{MapTile, BOARD_HEIGHT, BOARD_WIDTH, RAW_BOARD};
|
||||||
use crate::direction::Direction;
|
use crate::direction::Direction;
|
||||||
|
|||||||
@@ -17,15 +17,13 @@ mod map;
|
|||||||
mod modulation;
|
mod modulation;
|
||||||
mod pacman;
|
mod pacman;
|
||||||
|
|
||||||
#[cfg(target_os = "emscripten")]
|
|
||||||
mod emscripten;
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
// Setup tracing
|
// Setup tracing
|
||||||
let subscriber = tracing_subscriber::fmt()
|
let subscriber = tracing_subscriber::fmt()
|
||||||
|
.with_ansi(cfg!(not(target_os = "emscripten")))
|
||||||
.with_max_level(tracing::Level::DEBUG)
|
.with_max_level(tracing::Level::DEBUG)
|
||||||
.finish()
|
.finish()
|
||||||
.with(ErrorLayer::default());
|
.with(ErrorLayer::default());
|
||||||
@@ -77,6 +75,7 @@ pub fn main() {
|
|||||||
|
|
||||||
// TODO: Fix key repeat delay issues by using VecDeque for instant key repeat
|
// TODO: Fix key repeat delay issues by using VecDeque for instant key repeat
|
||||||
for event in event_pump.poll_iter() {
|
for event in event_pump.poll_iter() {
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
// Handle quitting keys or window close
|
// Handle quitting keys or window close
|
||||||
Event::Quit { .. }
|
Event::Quit { .. }
|
||||||
|
|||||||
Reference in New Issue
Block a user