Game Development
Overview
Patterns and practices for building games across platforms. Covers architecture, rendering, physics, AI, multiplayer, and optimization.
Game Architecture
Game Loop
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Game Loop β
β β
β βββββββββββ βββββββββββ βββββββββββ βββββββββββ β
β β Input β ββ β Update β ββ β Physics β ββ β Render β β
β β Process β β Logic β β Step β β Frame β β
β βββββββββββ βββββββββββ βββββββββββ βββββββββββ β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββ β
β Next Frame β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Fixed vs Variable Timestep
| Type |
Use Case |
Code Pattern |
| Fixed |
Physics, determinism |
while (accumulator >= dt) { update(dt); } |
| Variable |
Rendering, animations |
update(deltaTime); |
| Hybrid |
Most games |
Fixed physics, variable render |
let accumulator = 0;
const FIXED_DT = 1/60;
function gameLoop(currentTime: number) {
const deltaTime = currentTime - lastTime;
accumulator += deltaTime;
while (accumulator >= FIXED_DT) {
physicsUpdate(FIXED_DT);
accumulator -= FIXED_DT;
}
const alpha = accumulator / FIXED_DT;
render(alpha);
requestAnimationFrame(gameLoop);
}
Entity Component System (ECS)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ECS Architecture β
β β
β Entity: Just an ID β
β βββββββ βββββββ βββββββ β
β β 1 β β 2 β β 3 β β
β βββββββ βββββββ βββββββ β
β β
β Components: Pure Data β
β ββββββββββββ ββββββββββββ ββββββββββββ β
β β Position β β Velocity β β Sprite β β
β β x, y, z β β vx, vy β β texture β β
β ββββββββββββ ββββββββββββ ββββββββββββ β
β β
β Systems: Logic β
β ββββββββββββββββββ ββββββββββββββββββ β
β β MovementSystem β β RenderSystem β β
β β Position+Vel β β Position+Spriteβ β
β ββββββββββββββββββ ββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
interface Position { x: number; y: number; }
interface Velocity { vx: number; vy: number; }
interface Sprite { texture: string; width: number; height: number; }
function movementSystem(entities: Entity[], dt: number) {
for (const entity of entities) {
if (entity.has(Position) && entity.has(Velocity)) {
const pos = entity.get(Position);
const vel = entity.get(Velocity);
pos.x += vel.vx * dt;
pos.y += vel.vy * dt;
}
}
}
2D Game Development
Sprite Animation
interface Animation {
frames: string[];
frameDuration: number;
loop: boolean;
}
class AnimatedSprite {
private currentFrame = 0;
private elapsed = 0;
update(dt: number) {
this.elapsed += dt;
if (this.elapsed >= this.animation.frameDuration) {
this.elapsed = 0;
this.currentFrame++;
if (this.currentFrame >= this.animation.frames.length) {
this.currentFrame = this.animation.loop ? 0 : this.animation.frames.length - 1;
}
}
}
get texture(): string {
return this.animation.frames[this.currentFrame];
}
}
Collision Detection
| Method |
Complexity |
Use Case |
| AABB |
O(nΒ²) β O(n log n) |
Boxes, simple shapes |
| Circle |
O(nΒ²) |
Projectiles, characters |
| SAT |
O(nΒ²) |
Complex convex polygons |
| Pixel Perfect |
Expensive |
Precise collision |
function aabbIntersect(a: AABB, b: AABB): boolean {
return a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y;
}
class SpatialHash {
private cells = new Map<string, Entity[]>();
private cellSize: number;
insert(entity: Entity) {
const key = this.getKey(entity.position);
if (!this.cells.has(key)) this.cells.set(key, []);
this.cells.get(key)!.push(entity);
}
query(position: Vector2): Entity[] {
const nearby: Entity[] = [];
for (let dx = -1; dx <=