logo
By Lawrence

5 minutes

Spinners and Saucers

A bumper pays instantly and identically. Touch it, collect 500, done — and after a few minutes of that, every shot on the table feels the same. Real machines break the rhythm with elements that pay over time: a spinner that keeps ticking long after the ball has gone, and a saucer that swallows the ball, makes you wait, and throws it back.

Both attach to the World entity as two empty lines of JSON.

Two systems with nothing to run on yet

Find the World entity — it already carries Plunger from lesson 5 — and add two neighbours:

"World": {
  "components": {
    "Spinner": {},
    "MouseHole": {},
    "Plunger": {
      "ballTag": "ball",
      "spawnPosition": [0, 0.42, -14.5],
      "gravity": [0, -12, 14],
      "launchVelocityZ": 16,
      "launchJitterX": 2.5,
      "drainY": -3,
      "drainZMargin": 2,
      "triggerKey": "Space"
    }
  }
}

The empty {} is doing real work. SceneLoader looks up each component name in the registry and adds the matching System to the world the first time it sees that name. Both systems require a MeshPrimitive alongside their own component — SpinnerSystem queries [SpinnerComponent, MeshPrimitiveComponent] — and World has no mesh, so World itself never matches either query. The declaration exists to switch the systems on. The entities they act on get placed at runtime by the builder in the next lesson.

Continue reading

Unlock the Full Course

Every lesson, the runnable examples, and the finished build — yours to keep.

$9one-time

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search