Add direct game URLs and input handling fixes

Torey Heinz committed Mar 14, 2026
commit c518c52f6d1e0cef05637c757e462f0648a87fcd
Showing 5 changed files with 44 additions and 2 deletions
assets/js/game.js +18 -1
@@ @@ -54,12 +54,21 @@ game.registry.set("miniChannel", miniChannel)
// Join hub channel
hubChannel.join()
- .receive("ok", () => console.log("Joined hub!"))
+ .receive("ok", () => {
+ console.log("Joined hub!")
+ // Auto-open game if navigated to a game URL (e.g. /projectile-pi)
+ if (window.AUTO_OPEN_GAME) {
+ setTimeout(() => window.piStation.openMiniGame(window.AUTO_OPEN_GAME), 500)
+ }
+ })
.receive("error", (resp) => console.error("Unable to join hub", resp))
// --- Mini-game Manager ---
window.piStation = {
openMiniGame(gameType) {
+ // Don't re-open if a game is already active
+ if (window.piStation._currentGame) return
+
const overlay = document.getElementById("mini-game-overlay")
const content = document.getElementById("mini-game-content")
overlay.classList.add("active")
@@ @@ -67,6 +76,10 @@ window.piStation = {
// Hide station prompt
document.getElementById("station-prompt").classList.remove("visible")
+ // Disable Phaser input while overlay is active
+ const scene = game.scene.getScene("HubScene")
+ if (scene) scene.input.enabled = false
+
hubChannel.push("enter_game", { game: gameType })
SoundFX.countdown()
@@ @@ -103,6 +116,10 @@ window.piStation = {
hubChannel.push("leave_game", {})
+ // Re-enable Phaser input
+ const scene = game.scene.getScene("HubScene")
+ if (scene) scene.input.enabled = true
+
if (window.piStation._currentChannel) {
window.piStation._currentChannel.leave()
window.piStation._currentChannel = null
assets/js/game/HubScene.js +2 -0
@@ @@ -139,6 +139,7 @@ export class HubScene extends Phaser.Scene {
// Larger interactive zone
const zone = this.add.zone(station.x, station.y, 100, 100).setInteractive()
zone.on("pointerdown", () => {
+ if (window.piStation._currentGame) return
const dist = Phaser.Math.Distance.Between(
this.player.x, this.player.y, station.x, station.y
)
@@ @@ -202,6 +203,7 @@ export class HubScene extends Phaser.Scene {
// Space to enter nearby station
this.input.keyboard.on("keydown-SPACE", () => {
+ if (window.piStation._currentGame) return
if (document.activeElement === document.getElementById("chat-input")) return
if (this.nearStation) {
window.piStation.openMiniGame(this.nearStation.game)
pi_day_web/controllers/game_controller.ex b/lib/pi_day_web/controllers/game_controller.ex +18 -1
@@ @@ -1,11 +1,28 @@
defmodule PiDayWeb.GameController do
use PiDayWeb, :controller
+ @url_to_game %{
+ "/projectile-pi" => "projectile_pi",
+ "/pi-memory" => "pi_memory",
+ "/monte-carlo" => "monte_carlo",
+ "/slice-the-pi" => "slice_the_pi",
+ "/pi-trivia" => "pi_trivia"
+ }
+
def play(conn, _params) do
player = conn.assigns.current_player
conn
|> put_layout(false)
- |> render(:play, player: player)
+ |> render(:play, player: player, auto_open_game: nil)
+ end
+
+ def game(conn, _params) do
+ player = conn.assigns.current_player
+ game_type = @url_to_game[conn.request_path]
+
+ conn
+ |> put_layout(false)
+ |> render(:play, player: player, auto_open_game: game_type)
end
end
pi_day_web/controllers/game_html/play.html.heex b/lib/pi_day_web/controllers/game_html/play.html.heex +1 -0
@@ @@ -177,6 +177,7 @@
window.PLAYER_ID = "<%= @player.id %>";
window.PLAYER_NAME = "<%= @player.name %>";
window.PLAYER_AVATAR = "<%= @player.avatar_key %>";
+ window.AUTO_OPEN_GAME = "<%= @auto_open_game || "" %>";
// Chat toggle
let chatVisible = false;
pi_day_web/router.ex b/lib/pi_day_web/router.ex +5 -0
@@ @@ -25,6 +25,11 @@ defmodule PiDayWeb.Router do
pipe_through [:browser, :require_player]
get "/play", GameController, :play
+ get "/projectile-pi", GameController, :game
+ get "/pi-memory", GameController, :game
+ get "/monte-carlo", GameController, :game
+ get "/slice-the-pi", GameController, :game
+ get "/pi-trivia", GameController, :game
end
scope "/", PiDayWeb do