Game Dev 101
Progress
0/22

Lesson 14 of 22, in world 5: Game Architecture

Scene Graphs & Entities

Time
About 20 min
Builds on
Coordinates & TransformsAngles & Trigonometry

A real game has hundreds of objects: players, enemies, bullets, pickups, particles, UI. How do you organise them? Two ideas do most of the work: the scene graph (objects arranged in a tree) and entities built from components.

The scene graph

Objects are arranged as a tree. Each node stores a transform relative to its parent(lesson 4). A tank’s turret is a child of the tank body, so when the body drives and turns, the turret comes along for free — and the turret only has to worry about its own rotation.

LiveParent–child transforms
Moon's parent

The Sun spins; the Planet is its child at local (150, 0); the Moon is the Planet's child at local (45, 0). No code moves the Moon around the Sun — it inherits that from its parents. Reparent the Moon to see what changes.

JavaScript
// world transform = parent's world transform × my local transform
function worldMatrix(node) {
  const local = translate(node.x, node.y).rotate(node.rotation).scale(node.scale)
  return node.parent ? worldMatrix(node.parent).multiply(local) : local
}

Entities and components

The naive way to model game objects is a deep class hierarchy: Entity → Character → Enemy → FlyingEnemy → FlyingShootingEnemy. It falls apart quickly (what about a walking shooting enemy?). Games prefer composition: an entity is a bag of small, reusable components.

JavaScript
const bat = {
  transform: { x: 100, y: 50 },
  velocity:  { x: 0, y: 0 },
  sprite:    { sheet: 'bat.png', anim: 'fly' },
  collider:  { r: 8 },
  health:    { hp: 3 },
  ai:        { kind: 'chase', speed: 90 },
}
// Systems process every entity that has the components they need:
for (const e of entities) if (e.velocity) movementSystem(e, dt)
for (const e of entities) if (e.ai) aiSystem(e, dt)

Entity lifecycle: spawning and destroying

Bullets, particles and enemies are created and destroyed constantly. Two practical rules:

  • Don’t remove from a list while iterating it forwards. Mark entities as dead during update, then filter them out at the end of the frame (or iterate backwards).
  • Pool hot objects. Creating thousands of bullets per second triggers garbage collection hitches; reusing a fixed pool of inactive bullets avoids it.
JavaScript
for (const e of entities) e.update(dt)          // may set e.dead = true
entities = entities.filter(e => !e.dead)        // clean up once per frame

Key takeaways

  • A scene graph is a tree; children inherit their parent’s transform.
  • world transform = parent world × local.
  • Build entities by composing components, not deep inheritance.
  • Remove dead entities after the update loop; pool objects that spawn often.

Check yourself

Q1. A gun is a child of the player at local (20, 0). The player moves to (300, 100), no rotation. Where is the gun in the world?

Q2. Why prefer components over a deep class hierarchy?

Q3. What’s the safe way to delete enemies that died during update?

Exercises

  1. Reparent the Moon to the Sun. Why does it now orbit the Sun at 45 px? Then set it to World — why does it stop moving?
  2. Draw the scene tree for a car with four wheels, a driver and a headlight.
  3. Describe a "spinning sawblade on a moving platform" as components. Which components does each entity need?