logo
Scoreboard

gameplay

Scoreboard

Talks toScore
Free

Install with the CLI:

bjs download Scoreboard

Scoreboard

An event-driven on-screen score HUD — a roster of named, color-tinted rows that repaint whenever scores change.

What it does

ScoreboardSystem holds a fixed roster of players (id, label, tint) and a live score map. It subscribes to two public events: score.updated, whose allScores map it copies into the core, and score.reset, which clears every row back to zero. After each update it rebuilds the row snapshot — { title, fontSize, position, rows[] } — and emits scoreboard.updated carrying that snapshot and the source entity id. The HUD pixels are painted by the Solid panel in Scoreboard.panel.tsx, which reads the snapshot; the System never touches the 3D layer, so it does no per-frame work and runs identically wherever the events come from. It is decoupled from any specific point source: anything that emits score.updated with an allScores map drives it, which is the same shape Score rebroadcasts on score.changed.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Fastest path

bjs download scene Scoreboard

Pulls this exact scene into your project and runs it — no copy-paste. Add --all to grab the components and assets it needs too.

Or build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add Scoreboard
    bjs download Scoreboard

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Scoreboard": {
    "components": {
      "Scoreboard": {
        "title": "SCORE",
        "fontSize": 18,
        "position": "top-left",
        "players": [
          { "entityId": "Player", "name": "P1", "color": [0.3, 0.85, 0.95] },
          { "entityId": "Rival", "name": "P2", "color": [0.95, 0.4, 0.35] }
        ]
      }
    }
  }
}

Props

  • title (string, default "SCORE") — overlay heading shown above the rows.
  • fontSize (number, default 18) — base font size in CSS pixels.
  • position ("top-left" | "top-right" | "bottom-left" | "bottom-right", default "top-left") — which canvas corner the overlay anchors to.
  • players ({ entityId, name, color }[], default []) — the row roster. entityId must match the key used in score.updated's allScores map; color is RGB in [0,1], rendered as an rgb(...) swatch. A player with no score entry shows 0.

Events

  • Emits scoreboard.updated (ScoreboardEvents.UPDATED) after every rebuild — { entityId, snapshot }, where snapshot is { title, fontSize, position, rows } and each row is { entityId, name, colorCss, color, scoreText, score }.
  • Listens for score.updated (ScoreboardInputEvents.SCORE_CHANGED) — { ownerEntity?, score?, allScores? }. Only allScores is read; the snapshot is rebuilt from the whole map.
  • Listens for score.reset (ScoreboardInputEvents.SCORE_RESET) — { allScores? }. With an allScores map it sets those totals; without one it drops every row to 0.

Notes

  • The roster is fixed by players — only listed entityIds get a row. Scores in allScores for ids not in the roster are ignored, and roster ids absent from the map render as 0.
  • An update repaints every Scoreboard entity in the scene, so multiple boards (different corner, different title) stay in sync off the same events.
  • The roster's row order is the display order — it does not re-sort by score. Order players the way you want the rows stacked.
  • The component's input constant for the change event is score.updated. The bundled Score system rebroadcasts on score.changed with the same { allScores } payload, so bridge the two names (re-emit, or align the constant) when wiring Score directly into Scoreboard. The score.reset event matches on both sides as-is.

More like this

Score
SpaceShooterScore
AIGoalSeek
AIKick
AIZone
BallPossession
BallPursuit
BallReset
CardFan
Enemy
Goal
HealthBar
PlayerInputBridge
PokerHUD
PokerTableCards
RespawnTimer
RoundReset
SoccerDirector
SpaceShooterHUD
Waypoint

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search