AI Skill Report Card

Developing Games

A-83·Nov 8, 2026·Source: Web
14 / 15

When asked to build a game or game system, follow this decision tree:

  1. Identify the platform/engine (explicit or inferred from context: web → HTML5/Canvas/Phaser, Python → Pygame, mentions of Unity/Godot/Unreal → that engine, no constraint → pick the simplest fit for the genre).
  2. Identify the genre (platformer, top-down shooter, puzzle, RPG, roguelike, etc.) — genre determines core loop, data structures, and physics needs.
  3. Scaffold with a proper game loop first, before any feature code:
JavaScript
// Fixed timestep game loop (prevents physics inconsistency across frame rates) const FPS = 60; const STEP = 1000 / FPS; let lastTime = 0, accumulator = 0; function gameLoop(timestamp) { accumulator += timestamp - lastTime; lastTime = timestamp; while (accumulator >= STEP) { update(STEP / 1000); // deterministic, delta in seconds accumulator -= STEP; } render(accumulator / STEP); // interpolation factor for smooth rendering requestAnimationFrame(gameLoop); }
  1. Build systems in this strict order: loop → input → entity/state model → physics/collision → rendering → audio → UI → polish (juice). Never start with graphics/art code.
Recommendation▾
Examples describe outputs abstractly rather than showing actual concrete code/output produced for each input — include a short real code snippet result for at least one example
14 / 15

Progress checklist for any non-trivial game feature or full game:

  • Step 1: Define the core loop (what does the player do every 5 seconds? every 5 minutes?)
  • Step 2: Choose architecture pattern (ECS for many entity types, OOP state machine for simple games, FSM per-entity for AI/player states)
  • Step 3: Implement game loop with fixed timestep
  • Step 4: Implement input handling (abstracted from action logic — map keys to actions, not actions to keys)
  • Step 5: Implement entity/world model and update logic
  • Step 6: Implement collision detection appropriate to need (AABB for simple, spatial hashing/quadtree if >100 entities)
  • Step 7: Implement rendering (separate from update logic — never mutate state in render)
  • Step 8: Add game feel/juice (screen shake, hit-stop, particle feedback, easing) — do this LAST
  • Step 9: Profile and optimize (object pooling, avoid GC pressure in hot loops)
  • Step 10: Playtest-driven tuning (numbers like jump height, enemy speed are never right on first guess)

Architecture decision guide

SituationPattern
Few entity types, simple gameClasses + inheritance or simple composition
Many entity types sharing partial behavior (position, health, AI...)Entity-Component-System (ECS)
Player/enemy with distinct behavior modes (idle/attack/stun)Finite State Machine per entity
Complex branching AIBehavior Tree
Game-wide modes (menu/playing/paused/gameover)Global State Machine / Scene Manager

Core systems reference

Collision (AABB, the default for 2D):

JavaScript
function aabbCollide(a, b) { return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y; }

Object pooling (avoid new in hot loops — biggest perf killer in JS/C# games):

JavaScript
class Pool { constructor(factory, size) { this.factory = factory; this.pool = Array.from({length: size}, factory); this.active = []; } spawn(...args) { const obj = this.pool.pop() || this.factory(); obj.init(...args); this.active.push(obj); return obj; } release(obj) { this.active.splice(this.active.indexOf(obj), 1); this.pool.push(obj); } }

Input abstraction (decouple keys from actions):

JavaScript
const keyMap = { ArrowLeft: 'moveLeft', ArrowRight: 'moveRight', Space: 'jump' }; const actions = new Set(); window.addEventListener('keydown', e => keyMap[e.code] && actions.add(keyMap[e.code])); window.addEventListener('keyup', e => keyMap[e.code] && actions.delete(keyMap[e.code])); // game logic checks actions.has('jump'), never e.code directly
Recommendation▾
Add guidance on testing/debugging strategies specific to games (e.g., deterministic replay testing, automated playtesting) to round out completeness
14 / 20

Example 1: Input: "اعملي لعبة Platformer بسيطة بالـ HTML5 Canvas فيها قفز وجاذبية" Output: Full single-file HTML5 game with: fixed-timestep loop, player entity with velocity/acceleration-based movement, gravity constant applied per-frame (not per-tick-dependent), AABB collision against tile array, coyote-time jump buffering (small window after leaving platform where jump still registers — critical for "feel"), camera follow with lerp smoothing, and a tile-based level defined as a 2D array for easy editing.

Example 2: Input: "عايز نظام Inventory في Unity بـ C#" Output: ScriptableObject-based item definitions (data decoupled from instances), Inventory MonoBehaviour using List<InventorySlot> with add/remove/stack logic, UnityEvent or C# event (OnInventoryChanged) to decouple UI from logic (UI subscribes, never polls), and a separate InventoryUI that rebuilds slots only on the event — not every frame.

Example 3: Input: "اللعبة بتلاج (lag) لما العدد بتاع الأعداء يزيد" Output: Diagnose first — is it collision (O(n²) pairwise checks → fix with spatial hashing/quadtree), GC pressure (allocating objects/arrays per frame → fix with pooling), or draw calls (too many individual sprite draws → fix with batching/sprite atlases). Never guess; profile first (performance.now() timestamps around suspect sections, or engine profiler).

Recommendation▾
Consider a brief engine-specific section (Unity/Godot/Unreal) since the description promises engine-specific best practices but content is heavily JS/HTML5-biased
  • Separate update from render. Update mutates state; render only reads state. Never do if (keyPressed) sprite.draw() logic mixed into physics.
  • Delta-time everything. Never hardcode position += 5 per frame — always position += speed * deltaTime, or use fixed timestep for determinism.
  • Data-driven design. Enemy stats, level layouts, item definitions belong in data (JSON, ScriptableObjects, config objects), not hardcoded in logic classes.
  • "Juice" comes last but matters most for feel. Screen shake, squash/stretch, particle bursts, sound on impact — these make a mechanically identical game feel 10x better. Add after core mechanics are solid.
  • Coyote time + input buffering for platformers. Players expect forgiveness: jump still works ~100ms after leaving a ledge, and jump input is buffered ~100ms before landing.
  • Pool anything spawned repeatedly (bullets, particles, enemies) — avoid garbage collection stutter.
  • Test with placeholder art (gray boxes) first. Never block mechanics work on final art/assets.
  • Keep camera logic separate from game logic. Camera follows/shakes independently of entity state.
  • Frame-rate-dependent movement (x += 5 without deltaTime) — breaks on different hardware/refresh rates.
  • Checking collisions every entity-pair naively (O(n²)) once entity count grows — use spatial partitioning early if count can exceed ~50-100.
  • Mixing rendering code into game logic — makes testing and porting impossible.
  • Hardcoding tunable values (jump force, damage, speed) deep in logic instead of exposing them as easily-tweakable constants/data — playtesting requires fast iteration on numbers.
  • Allocating new objects/arrays inside the game loop — causes GC pauses/stutter, especially in JS and C#.
  • Starting with art/animation before core mechanics are fun — a game must be fun as gray boxes before it's worth skinning.
  • Polling input state deep inside nested logic instead of abstracting to an action layer — makes rebinding and multi-input support painful later.
  • Ignoring fixed timestep for physics — variable timestep physics causes different outcomes across machines (critical bug for multiplayer/replays).
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
14/20
Completeness
17/20
Format
14/15
Conciseness
13/15