Platform rules a game must follow
Hard requirements for shipping on GAMEE — distilled from the legacy wiki.
These rules pre-date the SDK and still apply. A game that violates them either won’t pass review or will get a poor user experience on the platform.
Package size#
≤ 5 MB total, including all assets. Larger games are rejected.
- Ship a separate dev/prod build. Dev can be readable; prod must be minified and atlased.
- Cap textures to display size — a 2048² atlas to render at 320 px is wasted bandwidth.
- Use codecs the platform actually decodes (Opus/MP3 for audio; PNG/WebP/JPEG for images).
Loading budgets#
| Phase | Budget |
|---|---|
Cold load → gameReady() resolves | ≤ 2.5 s |
start event → first interactive frame | ≤ 250 ms |
If your game streams large content mid-session, document the exception with the
GAMEE team. Async-decode audio (decodeAudioData) is slow on some devices —
defer non-essential audio to after gameReady().
Networking#
- No external network calls. The game runs offline-capable inside the platform.
- No
localStorage, nosessionStorage, no cookies. Persist via thesaveStatecapability instead. - No third-party scripts. Bundle everything you ship.
Rendering#
- A single
<canvas>element. Avoid HTML/CSS overlays in the gameplay area. - Target 60 FPS on low-end mobile hardware. WebGL is fine; Canvas2D is fine.
- Be sparing with CSS3 animations, large particle systems, and exotic WebGL extensions.
Frame-rate-independent logic#
Tie movement, physics, and scoring to elapsed time, not to frame count. A 30 FPS device must not be able to score higher (or lower) than a 60 FPS device on the same input.
function loop(now: DOMHighResTimeStamp) {
const dt = (now - lastFrame) / 1000;
lastFrame = now;
player.x += player.vx * dt; // ✅ time-based
// player.x += player.vx; // ❌ frame-based
}
Scoring#
- Call
updateScore({ score, playTime, checksum })(orupdateScore(score)) on every score change. The platform uses the most recent value atgameOverfor the leaderboard. - Score progression must be roughly linear. The anti-cheat pipeline flags large discontinuous jumps. Don’t ship a feature that grants 1 000 000 points in one frame.
- Checksum is required. Compute it however you want — the platform treats it as opaque. The point is reproducibility: the same run with the same inputs produces the same checksum.
Lifecycle discipline#
init()first, exactly once per SDK instance. Subsequent calls throwINVALID_STATE.- Subscribe to events before
gameReady()or you may miss the firststart. - Never call APIs in the wrong state. Calling
updateScoreaftergameOveris a bug; the platform may ignore the call or report it. pausestops everything (logic + audio).muteonly silences audio.
Audio#
- The SDK does not auto-unlock audio on mobile. Bind your unlock to the first
user interaction inside the game (a tap on the canvas, the first
keydown). - Avoid
AudioContext.suspend()/.resume()— they interact poorly with iOS background-tab handling. PreferAudioNode.connect()/.disconnect()to silence individual sources. - Honor
mute/unmuteevents; they reflect the platform UI state.
UX principles#
- No intro menus. The player should land in playable state as fast as possible. The platform’s UI handles meta-flow.
- Minimize text. The same build ships globally — assume the player can’t read English (or any specific language).
- All-ages appropriate content.
- Default to portrait fullscreen. Landscape is allowed when the gameplay demands it; declare the orientation in your project metadata.
Asset specs (cover art, marketing)#
| Asset | Dimensions |
|---|---|
| Cover (square) | 640 × 640 |
| Social preview | 600 × 315 |
| Web cover | 640 × 360 |
| Animated GIF (promo) | 320 × 180 |
In short#
If your game (a) loads in under 2.5 s, (b) starts gameplay in under 250 ms,
(c) ships under 5 MB, (d) honors pause/resume/mute, and (e) updates the
score linearly, you are 90 % of the way to passing review.