Skip to content

feat: Phaser.js game framework expansion — arcade games, lazy loading, GameManager#400

Merged
jbampton merged 7 commits intomainfrom
copilot/explore-codebase-phaser-js
Apr 3, 2026
Merged

feat: Phaser.js game framework expansion — arcade games, lazy loading, GameManager#400
jbampton merged 7 commits intomainfrom
copilot/explore-codebase-phaser-js

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 3, 2026

  • Identify bugs in code-breaker.js
  • Fix code-breaker tile speed (80 px/s → 180 px/s)
  • Fix d-key toggle (script.js line 659):
    • !isOpeningisOpening — the stored value was inverted so panel visibility was never correctly persisted across page loads
    • Added null-guard (if (!systemDash) return) to prevent crash on pages without #dev-tools
  • Finish remaining code-breaker improvements (spawn timing, pill opacity)

@jbampton jbampton marked this pull request as ready for review April 3, 2026 10:42
@jbampton jbampton self-requested a review as a code owner April 3, 2026 10:42
@jbampton jbampton added the enhancement New feature or request label Apr 3, 2026
@jbampton jbampton added this to the Hackfest milestone Apr 3, 2026
@jbampton jbampton added this to Next Apr 3, 2026
@github-project-automation github-project-automation bot moved this to In progress in Next Apr 3, 2026
@jbampton
Copy link
Copy Markdown
Member

jbampton commented Apr 3, 2026

/gemini review

@jbampton jbampton merged commit 4a5829d into main Apr 3, 2026
6 of 9 checks passed
@jbampton jbampton deleted the copilot/explore-codebase-phaser-js branch April 3, 2026 12:04
@github-project-automation github-project-automation bot moved this from In progress to Done in Next Apr 3, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive mini-game system called "Arcade," featuring three games: Space Invaders, Code Breaker, and Developer Duel. It includes a centralized GameManager for lifecycle and state management, an XP and achievement system integrated with the existing site, and a dedicated Arcade page. The review feedback focuses on improving performance and maintainability, specifically by dynamically loading game scripts, avoiding global namespace pollution, and replacing inline styles with Tailwind classes. There are also suggestions to optimize game loops by caching DOM queries and reducing event listeners, as well as standardizing variable declarations and error handling.

Comment on lines +7 to +11
<script src="/assets/js/games/config.js"></script>
<script src="/assets/js/games/game-manager.js"></script>
<script src="/assets/js/games/space-invaders.js"></script>
<script src="/assets/js/games/code-breaker.js"></script>
<script src="/assets/js/games/dev-duel.js"></script>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Including all game scripts on every page increases the initial load size and parse time. Consider modifying the GameManager to dynamically load a game's script only when it's about to be launched.

Comment on lines +73 to +74
var instance = new Phaser.Game(config);
GameManager.instances[GAME_ID] = instance;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Manually accessing and modifying GameManager.instances makes this code fragile. It would be better to use a method on GameManager for instance registration.

Comment on lines +261 to +264
closeBtn.style.cssText =
"position:absolute;top:1rem;right:1rem;padding:0.5rem 1rem;" +
"background:rgba(255,255,255,0.1);color:#fff;border:1px solid rgba(255,255,255,0.2);" +
"border-radius:0.5rem;cursor:pointer;font-weight:bold;font-size:0.75rem;z-index:1;";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of using style.cssText, apply styles using Tailwind utility classes via the className property to maintain consistency.

Suggested change
closeBtn.style.cssText =
"position:absolute;top:1rem;right:1rem;padding:0.5rem 1rem;" +
"background:rgba(255,255,255,0.1);color:#fff;border:1px solid rgba(255,255,255,0.2);" +
"border-radius:0.5rem;cursor:pointer;font-weight:bold;font-size:0.75rem;z-index:1;";
closeBtn.className = "absolute top-4 right-4 py-2 px-4 bg-white/10 text-white border border-white/20 rounded-lg cursor-pointer font-bold text-xs z-10";

Comment on lines +123 to +124
var icons = { first_blood: "🩸", code_wizard: "🧙", duelist: "⚔️" };
var labels = { first_blood: "First Blood", code_wizard: "Code Wizard", duelist: "Duelist" };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The achievement icons and labels are duplicated here and in src/assets/js/games/game-manager.js. To improve maintainability and have a single source of truth, consider exposing ACHIEVEMENT_META from GameManager and using it here.

Comment on lines +106 to +134
(function refreshGameStats() {
// High scores
var hs = {
"hs-si": localStorage.getItem("hs_space-invaders"),
"hs-cb": localStorage.getItem("hs_code-breaker"),
"hs-dd": localStorage.getItem("hs_dev-duel"),
};
Object.keys(hs).forEach(function (id) {
var el = document.getElementById(id);
if (el && hs[id]) el.textContent = hs[id];
});

// Achievement badges
var badgeContainer = document.getElementById("achievement-badges");
if (!badgeContainer) return;
var earned = {};
try { earned = JSON.parse(localStorage.getItem("gameAchievements") || "{}"); } catch (_) {}
var icons = { first_blood: "🩸", code_wizard: "🧙", duelist: "⚔️" };
var labels = { first_blood: "First Blood", code_wizard: "Code Wizard", duelist: "Duelist" };
Object.keys(icons).forEach(function (id) {
if (earned[id]) {
var badge = document.createElement("span");
badge.title = labels[id];
badge.className = "text-sm cursor-help";
badge.textContent = icons[id];
badgeContainer.appendChild(badge);
}
});
})();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This script uses var for variable declarations. It's recommended to use const for variables that are not reassigned and let for those that are. This improves code clarity by enforcing block scope and preventing accidental redeclaration.

Comment on lines +121 to +122
window.PROFILE_NAME = "{{ name }}";
window.PROFILE_SKILLS = "{{ languages | default('') }}".trim().split(/\s+/).filter(Boolean);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Attaching multiple properties directly to the window object can lead to global namespace pollution and potential naming conflicts. It's a better practice to group these properties under a single, namespaced object. For example: window.PROFILE_DATA = { ... };. You would then need to update the onclick handler on line 100 to use this new object.

Comment on lines +66 to +74
Object.assign(canvas.style, {
position: "fixed",
top: "0",
left: "0",
width: "100vw",
height: "100vh",
zIndex: "10000",
pointerEvents: "none", // non-interactive until explosion is done
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Applying numerous inline styles via JavaScript can make the code harder to read and maintain. Define a CSS class instead.

const XP_SPACE_INVADERS_WIN = 200; // Defeat all Space Invaders
const XP_CODE_BREAKER_WIN = 100; // Win a Code Breaker round
const XP_DEV_DUEL_PLAY = 25; // Play a Developer Duel
const XP_DEV_DUEL_WIN = 50; // Win a Developer Duel
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The constant XP_DEV_DUEL_WIN is defined but it's not used anywhere in the codebase. It should either be used or removed to avoid dead code.

Comment on lines +124 to +156
document.addEventListener("DOMContentLoaded", function () {
// Populate high scores
var scores = {
"space-invaders": document.getElementById("hs-space-invaders"),
"code-breaker": document.getElementById("hs-code-breaker"),
"dev-duel": document.getElementById("hs-dev-duel"),
};
Object.keys(scores).forEach(function (id) {
var val = parseInt(localStorage.getItem("hs_" + id)) || 0;
if (scores[id]) scores[id].textContent = val > 0 ? val : "—";
});

// Populate achievements
var achievements = {};
try {
achievements = JSON.parse(localStorage.getItem("gameAchievements") || "{}");
} catch (_) {}

document.querySelectorAll(".achievement-card").forEach(function (card) {
var id = card.dataset.id;
var statusEl = card.querySelector(".achievement-status");
if (achievements[id]) {
card.classList.add("border-accent");
card.style.opacity = "1";
if (statusEl) {
statusEl.textContent = "Earned ✓";
statusEl.style.color = "var(--accent)";
}
} else {
card.style.opacity = "0.5";
}
});
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This script uses var for variable declarations. It's recommended to use const for variables that are not reassigned and let for those that are.

// Populate achievements
var achievements = {};
try {
achievements = JSON.parse(localStorage.getItem("gameAchievements") || "{}");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Swallowing errors with an empty catch block can hide issues and make debugging difficult. Log the error to the console.

achievements = JSON.parse(localStorage.getItem("gameAchievements") || "{}"); } catch (e) { console.error("Failed to parse game achievements:", e); }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants