Skills game-quality-gates
Game development quality gates and mandatory checks. Activate when building, reviewing, debugging, or deploying any game project (H5/Canvas/WebGL/Phaser/Three.js/2D/3D). Covers state cleanup, lifecycle management, input handling, audio, persistence, networking, anti-cheat, and performance. Use as pre-deploy checklist or when diagnosing game-specific bugs (state leaks, phantom timers, buff conflicts, memory growth, touch issues).
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/abczsl520/game-quality-gates" ~/.claude/skills/clawdbot-skills-game-quality-gates && rm -rf "$T"
skills/abczsl520/game-quality-gates/SKILL.mdGame Quality Gates
Mandatory quality standards for all game projects. Based on 70+ real bugs and industry best practices.
Core Principle
Bugs come from cross-state interactions, not individual features. Each feature works alone; they break in combination.
12 Universal Rules (all games)
1. Single Cleanup Entry Point 🔄
All exit paths (death/level-complete/quit/pause/scene-switch) call ONE cleanup method with options.
cleanupGameState(opts) { // Fixed order: sub-objects → buffs+timers → UI → projectiles → (optional) enemies/controls/events } // Every exit: resetBall(), levelComplete(), gameOver(), onShutdown() → calls this
New feature = add one line here. Never scatter cleanup across exits.
2. Respect Active Buffs ⚡
Any code modifying attributes (speed/attack/size/defense) must check for active temporary effects first.
// ❌ speed = Math.max(speed, BASE_SPEED); // ignores slow buff // ✅ speed = Math.max(speed, this._currentBaseSpeed); // buff-aware baseline
3. Cache Before Destroy 📦
Extract all needed data before
destroy()/dispose()/remove().
const { x, y } = obj; const color = obj.getData('color'); obj.destroy(); spawnParticles(x, y, color);
4. Timers Follow Lifecycle ⏰
Track all
setTimeout/setInterval/delayedCall/rAF. Cancel in cleanup.
this.activeTimers.push(this.time.delayedCall(10000, cb)); // In cleanup: this.activeTimers.forEach(t => t.remove(false));
5. Frame-Rate Independent Logic 🖥️
Multiply all time-dependent logic by delta. Never assume 60fps.
// ✅ player.x += speed * (delta / 1000);
- Phaser
: delta in ms, divide by 1000update(time, delta) - Three.js
: returns secondsclock.getDelta() - Physics: prefer fixed timestep (accumulate delta, step every 16.67ms)
6. Scene Transition = Full Cleanup 🚪
On scene/level switch, clean: event listeners, timers, rAF, audio nodes, object pools, WebGL resources (geometry/material/texture dispose), global state, pending fetch/XHR.
Verify: Chrome DevTools → Memory → heap snapshots before/after transition.
7. Audio Lifecycle 🔊
- iOS: AudioContext must
inside a user interaction eventresume()
→ pause all audio when hidden, resume when visiblevisibilitychange- WeChat WebView:
before autoplayWeixinJSBridge.invoke('getNetworkType') - Pool short sound effects; manage background music separately
8. Input Safety 👆
- Purchase/consume actions: mutex lock + visual disable
- Attack/fire: cooldown timer
- State toggles (pause/resume): state machine guard
- See Phaser reference for multi-touch pointer ID tracking
9. Save State Persistence 💾
- Include
field for migration when game updatesversion - Only persist meaningful state (not particles/temp animations)
- Auto-save on: level end, manual save,
(hidden)visibilitychange - localStorage limit 5MB; use IndexedDB for larger saves
- WeChat: use
(not localStorage)wx.setStorage
10. Network Fault Tolerance 🌐
All network calls (leaderboard/share/ads/sync): 5s timeout + local cache fallback + no blocking game flow on failure.
11. Asset Loading Strategy 📦
Three tiers: critical (startup, <2s) → level assets (loading screen) → deferred (background lazy load). Fatal error only for critical failures; degrade gracefully for non-critical.
Compression: GLB+Draco, WebP images, MP3+OGG dual audio, sprite atlases.
12. Anti-Cheat Baseline 🛡️
Client is untrusted. Server validates:
- One-time raid tokens (bind user+timestamp, single use)
- Play duration sanity check (can't finish 30 levels in 3 seconds)
- Score range validation
- See
for implementation patternsreferences/anti-cheat.md
Engine-Specific Rules
For Phaser-specific rules (pointer ID tracking, physics group cleanup, OVERLAP_BIAS, time vs physics pause): → Read
references/phaser.md
For Three.js-specific rules (dispose trio, GLB compression pipeline, animation state machine, prune pitfalls): → Read
references/threejs.md
Pre-Deploy Checklist
Run this checklist before every deployment:
🔴 Universal (all games)
- New objects cleaned in
?cleanupGameState() - New timers cancelled in cleanup?
- Attribute changes respect active buffs?
- Data cached before destroy?
- Movement/animation uses delta time?
- No memory leaks across scene transitions? (DevTools verify)
- Audio pauses on background/lock?
- Purchase/consume has duplicate-click prevention?
- Save has version number + migration?
- Network calls have timeout + fallback?
- Asset load failure has graceful degradation?
- Critical operations (spend/settle) server-validated?
🟡 Mobile Extra
- Multi-touch: each finger tracked independently?
- iOS AudioContext resumed after first interaction?
- WeChat WebView compatible (no advanced CSS like backdrop-filter)?
- Virtual joystick/buttons don't overlap game area?
- Orientation change handled?
🔵 Engine-specific
→ See
references/phaser.md or references/threejs.md for engine checklists.