Game Engine
Manages the game lifecycle from lobby to completion — state transitions, question progression, answer tracking, scoring, iframe communication, and real-time coordination between host and players.
Overview
- State Machine: lobby → playing → question → results → complete
- Host Controls: Start game, next question, show results
- Player Flow: Join lobby, play AI-generated game in sandboxed iframe, see feedback, view leaderboard
- Iframe Architecture: Parent owns game state, iframe is a dumb renderer, communication via MessageChannel
- Scoring: Points based on correctness + speed (validated server-side, not in iframe)
- Real-time: All state changes sync instantly via Convex
When to Use This Skill
- Building or modifying the game state machine
- Implementing host controls (start, next, results)
- Building the iframe sandbox and MessageChannel communication
- Building the player answer flow (iframe → parent → Convex)
- Implementing scoring logic (server-side validation)
- Handling edge cases (disconnects, late joins, timeouts, iframe errors)
Key Concepts
State Machine
lobby → playing → question ←→ results → complete
↑ |
└──────────────┘ (next question)
- lobby: Players joining, host waiting to start
- playing: Transitional state when game starts
- question: Active question, players submitting answers
- results: Showing answer results + leaderboard for current question
- complete: All questions done, final results displayed
State Transitions
| From |
To |
Trigger |
| lobby |
question |
Host clicks "Start Game" |
| question |
results |
Host clicks "Show Results" OR timer expires |
| results |
question |
Host clicks "Next Question" (if questions remain) |
| results |
complete |
Host clicks "Next Question" on last question |
Scoring Formula
Points = correctness_points + speed_bonus
correctness_points = correct ? 1000 : 0
speed_bonus = correct ? max(0, 500 * (1 - timeMs / timerDuration)) : 0
Max points per question: 1500 (correct + fastest possible)
Timer
- Default: 30 seconds per question
- Timer runs in the parent app (authoritative), not in the iframe
- iframe can display a visual countdown, but parent enforces the actual limit
- When timer expires, parent sends
TIME_UP to iframe via MessageChannel
Iframe Communication
Parent and iframe communicate via a private MessageChannel:
- Parent creates
MessageChannel, transfers one port to iframe via initial postMessage
- All subsequent communication flows through the private channel port
- Never combine
allow-scripts + allow-same-origin in sandbox
Parent as Source of Truth
- Parent owns game state — iframe is a rendering engine
- Scoring happens server-side (Convex), not in the iframe
- If iframe crashes, parent still has game state and can recover
- iframe cannot be trusted for authoritative state (it runs AI-generated code)
Related Files
convex/games.ts — Game state mutations
convex/answers.ts — Answer submission and scoring
convex/players.ts — Player management and scores
components/GameIframe.tsx — Sandboxed iframe wrapper with MessageChannel
Reference Files
- reference.md — Code patterns for state management and iframe communication
1---2name: game-engine3description: Game state machine, lobby system, question flow, scoring, and real-time game coordination4---56# Game Engine78Manages the game lifecycle from lobby to completion — state transitions, question progression, answer tracking, scoring, iframe communication, and real-time coordination between host and players.910## Overview1112- **State Machine**: lobby → playing → question → results → complete13- **Host Controls**: Start game, next question, show results14- **Player Flow**: Join lobby, play AI-generated game in sandboxed iframe, see feedback, view leaderboard15- **Iframe Architecture**: Parent owns game state, iframe is a dumb renderer, communication via MessageChannel16- **Scoring**: Points based on correctness + speed (validated server-side, not in iframe)17- **Real-time**: All state changes sync instantly via Convex1819## When to Use This Skill2021- Building or modifying the game state machine22- Implementing host controls (start, next, results)23- Building the iframe sandbox and MessageChannel communication24- Building the player answer flow (iframe → parent → Convex)25- Implementing scoring logic (server-side validation)26- Handling edge cases (disconnects, late joins, timeouts, iframe errors)2728## Key Concepts2930### State Machine3132```33lobby → playing → question ←→ results → complete34 ↑ |35 └──────────────┘ (next question)36```3738- **lobby**: Players joining, host waiting to start39- **playing**: Transitional state when game starts40- **question**: Active question, players submitting answers41- **results**: Showing answer results + leaderboard for current question42- **complete**: All questions done, final results displayed4344### State Transitions4546| From | To | Trigger |47|------|----|---------|48| lobby | question | Host clicks "Start Game" |49| question | results | Host clicks "Show Results" OR timer expires |50| results | question | Host clicks "Next Question" (if questions remain) |51| results | complete | Host clicks "Next Question" on last question |5253### Scoring Formula5455```56Points = correctness_points + speed_bonus57correctness_points = correct ? 1000 : 058speed_bonus = correct ? max(0, 500 * (1 - timeMs / timerDuration)) : 059```6061Max points per question: 1500 (correct + fastest possible)6263### Timer6465- Default: 30 seconds per question66- Timer runs in the **parent app** (authoritative), not in the iframe67- iframe can display a visual countdown, but parent enforces the actual limit68- When timer expires, parent sends `TIME_UP` to iframe via MessageChannel6970### Iframe Communication7172Parent and iframe communicate via a private MessageChannel:731. Parent creates `MessageChannel`, transfers one port to iframe via initial `postMessage`742. All subsequent communication flows through the private channel port753. Never combine `allow-scripts` + `allow-same-origin` in sandbox7677### Parent as Source of Truth7879- Parent owns game state — iframe is a rendering engine80- Scoring happens server-side (Convex), not in the iframe81- If iframe crashes, parent still has game state and can recover82- iframe cannot be trusted for authoritative state (it runs AI-generated code)8384## Related Files8586- `convex/games.ts` — Game state mutations87- `convex/answers.ts` — Answer submission and scoring88- `convex/players.ts` — Player management and scores89- `components/GameIframe.tsx` — Sandboxed iframe wrapper with MessageChannel9091## Reference Files9293- [reference.md](reference.md) — Code patterns for state management and iframe communication