logo
By Lawrence

5 minutes

Assemble the Whole Arena

Every piece works on its own; now it's time to make them one game. The ship drives, the gun fires, bullets fly out and get reused, an enemy spots you past cover and falls when you hit it, waves spawn from a pool, and the score goes up. So far you've met these pieces one lesson at a time, each proving itself in the panels while the others stayed off. You have not yet started all of them together in one arena. That's the only job left, and it adds no new component — it starts what you already have and lets the events connect.

The bootstrap in main.ts

One file runs the whole thing. src/main.ts builds the game on the Babylon renderer. It mounts the debug panels, loads the scene you've built, and starts the loop:

import { ArcadeGame } from '@babylonjsmarket/arcade';
import { BabylonAdapter } from '@babylonjsmarket/ecs/babylon';
import { REGISTRY } from './registry';
import arena from './scenes/TwinStickArena.json';

const canvas = document.getElementById('renderCanvas') as HTMLCanvasElement;
const game = new ArcadeGame(new BabylonAdapter(), { componentRegistry: REGISTRY });
await game.init(canvas);

if (import.meta.env.DEV) {
  const { mountArcadeViz } = await import('@babylonjsmarket/arcade/viz');
  const { mountViz } = await import('@babylonjsmarket/viz/solid');
  await import('@babylonjsmarket/viz/themes/flat.css');
  mountArcadeViz(game.world, { sceneName: 'TwinStickArena' }); // Entities (`) + EventBus debugger (≈F4) + FPS
  mountViz(game.world, { sceneName: 'TwinStickArena' });        // panel renderer + StateStepper + gear menu
}

await game.loadScene(arena);
game.start();

window.addEventListener('resize', () => game.renderer.resize());

new ArcadeGame(new BabylonAdapter(), …) picks the rendering engine one time, right here at boot. Every component you've added reaches Babylon only through that adapter, so the same scene would run on Three if you swapped this one line. The viz mount is wrapped in import.meta.env.DEV and dynamic imports, so a production build drops the panels, the renderer, and the theme CSS completely — and it mounts on the live World, adding zero entities to the scene. REGISTRY, the component registry create-arcade made back in Lesson 1, maps each JSON component name to its class, so loadScene(arena) reads the entities map and looks up each named component through it ("TwinStickShooter"TwinStickShooterComponent). No game logic lives in this file; it only starts everything running.

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