A bilingual math-learning creature game for children. Math is the battle mechanic: answer money word problems to attack, defeat bosses step-by-step, and solve change questions when buying supplies.
- ✅ Phase 0 — pure TypeScript domain library
- ✅ Phase 1 — Cocos Creator gameplay-parity port
- ✅ Phase 2 — Cloudflare Workers + D1 saves — live at game.pokemath.fun
- ✅ Kids Playtest Preview (Woolly Meadows) — shipped and verified in live playtest (2026-07-18)
- ✅ Meadow Isle M1–M6 — shipped 2026-07-20.
- ⏸ M7 tuning and healthy return — evidence tooling is live; constants and the
journal wait on representative play data. Plan of record:
docs/islands/meadow-isle.md; live status: tracker issue #27.
See ROADMAP.md for the long-term plan history and completion
evidence; see docs/islands/meadow-isle.md for
the current design and status.
- Node.js 23.6+ (the current development machine uses Node 24)
- npm
- Cocos Creator 3.8.8
npm installThen open game/ in Cocos Creator 3.8.8, open
assets/main.scene, and start a browser preview. The committed Cocos project
already contains the current synced domain library.
The production game runs at https://game.pokemath.fun.
# Headless web build (exit code 36 is success) → game/build/web-mobile/
/Applications/Cocos/Creator/3.8.8/CocosCreator.app/Contents/MacOS/CocosCreator \
--project "$PWD/game" --build "platform=web-mobile"
npm run deploy # wrangler deploy: static assets + worker → game.pokemath.fun
npm run cf-types # regenerate worker Env types after wrangler.jsonc changesD1 schema changes go in worker/migrations/ and are applied with
wrangler d1 migrations apply pokemath-db --remote (wrangler defaults to
the local database without --remote).
npm test # project test suite
npm run typecheck # game + shared (Cocos 3.8.8 declarations) + worker
npm run demo # small command-line domain demonstration
npm run review:questions # regenerate the parent-facing question reviewnpm run sync copies the pure domain library from shared/ into
game/assets/shared/ and rewrites Node's explicit .ts import extensions
into the extensionless imports required by Cocos. Run it after changing
anything under shared/, then run both npm test and npm run typecheck.
| Context | Keyboard | Touch |
|---|---|---|
| Walk | Arrow keys or WASD | — |
| Advance a message | Enter or Space | Tap message panel |
| Default battle action | Enter or Space | Tap button |
| Choose an answer | 1–4 (top row or numpad) | Tap answer |
| Catch | C | Catch button |
| Run / back / leave shop | Escape | On-screen button |
The browser canvas focuses itself at startup and after pointer presses because
Cocos 3.8 listens for keyboard events directly on #GameCanvas.
pokemath/
├── shared/ Pure TypeScript domain — no DOM, canvas, or Cocos
│ ├── creature.ts Creature health, capture, XP and level-ups
│ ├── question-engine.ts Question selection, turns, choices and judgement
│ ├── battle-rules.ts Damage, difficulty bonuses and rewards
│ ├── shop-rules.ts Items and generated change questions
│ ├── save-types.ts Phase 1↔2 persistence contract
│ └── tests/ Node test suite
├── game/ Cocos Creator 3.8.8 project
│ └── assets/
│ ├── Main.ts Single scene bootstrap
│ ├── shared/ Generated by `npm run sync`
│ └── src/
│ ├── GameApp.ts Screen transitions and input routing
│ ├── state.ts In-memory player/team/inventory state
│ ├── world/ Tile map, movement, collision and HUDs
│ ├── battle/ Battle phase state machine and rendering
│ ├── questions/ Shared Cocos question UI
│ └── shop/ Shop and purchase flow
├── worker/ Cloudflare Worker — game.pokemath.fun
│ ├── src/index.ts Static-asset serving + /api/* routing
│ ├── src/api.ts Player/save/claim endpoints (D1)
│ ├── src/auth.ts Tokens (hash-only at rest) and save codes
│ └── migrations/ D1 schema
└── tools/ Shared-sync and Cocos UUID utilities
shared/owns game rules and must remain independent of Cocos and browser APIs.- Versioned question banks are JSON game assets under
game/assets/resources/question-banks/; TypeScript defines their runtime contract but does not contain authored questions. Parent-facing review files underdocs/question-banks/are generated from the same JSON source. - Cocos screens own rendering/input and call the shared domain; they do not duplicate battle or question arithmetic.
Main.tsboots onecc.Scene. World, battle, and shop are runtime-built TypeScript classes managed byGameApp, not separate editor scenes.SaveStateis the stable contract for persistence;shared/save-validate.tsguards it at the network boundary (worker validates writes, client validates server responses).game/assets/src/persistence.tsis the only client code that knows about HTTP and localStorage: offline-first boot from a cached save, checkpoint pushes on battle exit / respawn / shop leave,?code=XXXXXXdevice claim.
Google sign-in via better-auth. Saves are keyed per Google account and
server-side with an integer-version compare-and-swap. To test the game
locally without a Google account, see docs/local-testing.md.
Commit Cocos .meta files—they carry stable asset UUIDs. Do not commit generated
library/, temp/, local/, profiles/, build/, or native/ directories;
the repository .gitignore excludes them.
Downloaded or unlicensed visual references belong in the ignored
art-samples/ directory and must not be pushed. Published game art is
authoritative in private R2; see docs/art-assets.md.
The game began as a vanilla JavaScript/HTML prototype in the repository root; it was fully ported to the TypeScript domain library and Cocos client, then deleted. It remains available in git history if a behavioral question ever comes up. All product code is TypeScript.