fix(game): resolve race condition in render dirty flag using bitwise OR

The render dirty flag was being reset instead of accumulated, causing
the game to become stuck and unplayable in web builds. Changed from
assignment to bitwise OR to preserve all dirty state updates.

Also adds game layout component and updates Justfile to build frontend.
This commit is contained in:
Ryan Walters
2025-11-22 21:14:24 -06:00
parent 9bf8d0428c
commit c306e992c4
4 changed files with 14 additions and 9 deletions

View File

@@ -36,7 +36,8 @@ samply:
# Build the project for Emscripten
web *args:
bun run pacman/web.build.ts {{args}};
bun run pacman/web.build.ts {{args}}
bun run --cwd web build
caddy file-server --root web/dist/client
# Fix linting errors & formatting

View File

@@ -521,7 +521,7 @@ impl Game {
stage_system.in_set(GameplaySet::Respond),
(
(|mut dirty: ResMut<RenderDirty>, score: Res<ScoreResource>, stage: Res<GameStage>| {
dirty.0 = score.is_changed() || stage.is_changed();
dirty.0 |= score.is_changed() || stage.is_changed();
}),
dirty_render_system.run_if(|dirty: Res<RenderDirty>| dirty.0.not()),
combined_render_system,

View File

@@ -0,0 +1,9 @@
import "../../layouts/tailwind.css";
export default function GameLayout({ children }: { children: React.ReactNode }) {
return (
<div className="bg-black text-yellow-400 min-h-screen flex flex-col">
<main className="flex-1">{children}</main>
</div>
);
}

View File

@@ -2,32 +2,27 @@ import { useEffect } from "react";
export default function Page() {
useEffect(() => {
// Only setup Module if not already configured (prevents double-initialization on hot reload)
if (!(window as any).Module) {
const canvas = document.getElementById("canvas");
// Simple Module configuration matching the original working approach
(window as any).Module = {
canvas: canvas,
locateFile: (path: string) => {
// Return absolute paths for all resources
return path.startsWith("/") ? path : `/${path}`;
},
preRun: [],
};
// Load the Emscripten script
const script = document.createElement("script");
script.src = "/pacman.js";
script.async = false; // Load synchronously to ensure Module is configured first
script.async = false;
document.body.appendChild(script);
// Cleanup function (runs when component unmounts)
return () => {
script.remove();
};
}
}, []); // Empty dependency array = run once on mount
}, []);
return (
<div className="mt-4 flex justify-center h-[calc(100vh-120px)]">