Skip to content

Architecture ​

This chapter reorganizes the project into systems. Gameplay is split into focused modules (waves, scoring, effects, HUD), and a SystemManager orchestrates them.

SystemManager (lib, ch14) ​

The new SystemManager is a minimal scheduler:

  • add(system, order) registers a system with an update order.
  • update(deltaTime) runs each system in order.
  • render() optionally runs render hooks.

This keeps large game logic out of the main class.

Why systems? ​

As the game grows, main.ts becomes too big to reason about. Systems let you group related logic and treat each group as a mini‑module. That makes it easier to test, tweak, and reuse.

Systems in this chapter ​

  • WaveSystem — controls wave progression and enemy/asteroid spawning.
  • ScoreSystem — handles scoring rules and exposes getScore().
  • EffectsSystem — listens to events and triggers sounds + particles.
  • HudSystem — builds UI layers and exposes show/hide for HUD and pause.

Each system is small, testable, and has a single responsibility.

Beginner tip: if a class does “too many different things,” it should probably be split into systems.

Events and systems ​

We keep the EventBus and let systems subscribe:

  • EffectsSystem plays audio and emits particles.
  • ScoreSystem updates points.
  • WaveSystem tracks remaining enemies/asteroids.

This reduces coupling between gameplay objects.

Centralized config ​

Gameplay tuning values are moved into config.ts so you can tweak balance without touching logic.

This is a classic separation: data in config, behavior in systems.

Library changes ​

  • Added lib/Systems with System and SystemManager.
  • ParticleSystem gains a clear() helper used during resets.