logo
FreighterHead

shooter · space-combat-sim

FreighterHead

1
Unlock

Install with the CLI:

bjs download FreighterHead

FreighterHead

The locomotive of a snake-style freighter convoy — the escort target your mission keeps alive. The cars behind it trace the exact arc it drew a few seconds ago.

What it does

FreighterHeadComponent is pure data. Each tick the FreighterChainSystem (which ships with the FreighterChain component) records the head's pose into a ring buffer — sized to capacity — so trailing FreighterCar entities can sample the buffer at increasing time offsets and follow the head's historic path exactly, snake-style. FreighterHelmSystem steers the head: toward the current waypoint gate when a track is set (advancing currentWaypointIndex as it enters each gate's sphere), or a gentle sinusoidal drift when there's no mission, phased off the head's clock.

The motion lives in FreighterChain, which this component pulls in as a dependency. What the head owns is the mission's two outcomes.

Killing it is failure: the shared destroyShip path emits spaceshooter.freighter.killed, which MissionDirector treats as an instant loss.

Delivering it is the win, and that is FreighterHeadDeliverySystem's job. Each tick it checks whether the head has entered the final gate's sphere and, the first time it has, emits spaceshooter.freighter.delivered; MissionDirector turns that into a won run. The final gate is the highest-index waypoint, not the last one the scene lists — gates carry an explicit index so they can be declared in any order, and reading scene order would make the finish line depend on how the JSON happens to be written.

Use it in a scene

A head plus two trailing cars, steering down +Z:

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 FreighterHead

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 FreighterHead
    bjs download FreighterHead

    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
{
  "FreighterHead": {
    "tags": ["freighter-head"],
    "components": {
      "Transform6DOF": { "x": 0, "y": 0, "z": 100 },
      "Velocity6DOF": {},
      "FreighterHead": { "carSpacingSeconds": 0.7 },
      "Renderable": { "shape": "freighter-head", "sx": 6, "sy": 5, "sz": 16 },
      "ShipLoadout": { "loadout": "freighter-head" }
    }
  },
  "FreighterCar0": {
    "tags": ["freighter-car"],
    "components": {
      "Transform6DOF": { "x": 0, "y": 0, "z": 65 },
      "FreighterCar": { "index": 0, "headEntityId": "FreighterHead" },
      "Renderable": { "shape": "freighter-car", "sx": 5, "sy": 4, "sz": 10 },
      "ShipLoadout": { "loadout": "freighter-car" }
    }
  }
}

Each car names its head with headEntityId; the chain system resolves it each tick to sample the pose history.

Props

  • carSpacingSeconds (number, default 0.7) — per-car age offset in seconds. Car i samples the head's pose at clock − (i+1)·carSpacingSeconds, so a bigger value stretches the convoy out.
  • capacity (number, default 480) — ring-buffer length in samples the chain system allocates for this head's pose history. Must cover the furthest car's age offset at the tick rate.
  • clock (number, default 0) — wall-clock seconds the head has been alive. Advanced by the chain system; also the phase source for the helm's drift weave. Runtime state, not a tuning knob.
  • currentWaypointIndex (number, default 0) — the waypoint the helm is steering toward. Advanced by FreighterHelmSystem; -1 falls back to sinusoidal drift.

Events

  • emits spaceshooter.freighter.delivered { freighterId, waypointIndex } — the convoy reached the final gate. Fires once per run.
  • listens for nothing.

Dependencies

  • FreighterChain — defines FreighterHeadComponent + FreighterCarComponent and the two systems (FreighterChainSystem, FreighterHelmSystem) that record the pose history and steer the head. The head is inert data without it.
  • Waypoint — the gates the helm steers toward and the delivery watcher measures against. With no gates in the scene there is no finish line, so the run can only be lost.
  • MissionDirector — turns delivered into a won run and killed into a lost one. Without it both events are emitted and nothing acts on them.

Notes

  • The head and cars are one system, two scene keys. FreighterHead and FreighterCar are split only so a scene can place the locomotive and each car as separate entities; both classes and all the motion live in FreighterChain, downloaded as a dependency of either.
  • The chain isn't compacted on death. A destroyed car leaves its index gap — surviving cars keep their original offsets, so damage shows as visible holes in the convoy rather than the tail sliding forward.
  • Head death ends the run. destroyShip distinguishes the freighter-head tag and emits spaceshooter.freighter.killed (instant mission loss) rather than the incidental spaceshooter.freighter.car.lost a car emits.
  • Delivery fires once. Arriving is not a state you can re-enter — re-emitting it every frame the convoy sits in the gate would have the mission brain win the same run repeatedly.
  • The delivery check runs at priority 54, after the helm has steered and the chain has moved, so arrival is judged on where the convoy actually ended up this frame.
  • An escort scene wants killQuota: 0 on MissionDirector. With a quota set, clearing enough fighters wins the run before the convoy ever arrives.

More like this

FreighterChain
AiPilot
Animation
ArcCamera
Asteroid
AsteroidField
Bullet
CameraFollow
ChaseCamera6DOF
ChaseCameraTarget
DirectionalLight
EnemySpawner
EnvironmentTexture
FlightIntent
FreighterCar
GameConfig
Hand
Health
HemisphericLight
Jump
KeyboardInput
KeyboardMover
LensFlare
Lifetime
LineOfSight
MachineGun
Mesh
MeshPrimitive
Missile
MissileLauncher
MissionDirector
MoneyField
MouseInput
Movement
NebulaSky
Obstacle
ObstacleField
OilBlob
Parts
Physics
PlayerFlightInput
PlayerInput
PlayerWalkAnimator
RespawnTimer
RoundReset
Score
Shadow
ShipDamageFX
ShipFlight
ShipLoadout
ShooterCamera
SkeletonAnimator
SpaceDust
SpaceShooterBullet
SpaceShooterFX
SpaceShooterHUD
SpaceShooterHealth
SpaceShooterScore
TwinStickEnemy
TwinStickShooter
WaveDirector
Waypoint
WaypointTrack
WorldOriginAnchor

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search