logo
Wormhole

physics · physics-puzzle

Wormhole

Listens toGravityBody
2
Unlock

Install with the CLI:

bjs download Wormhole

Wormhole

Two mouths that are one place: a body that flies into one comes out of the other.

What it does

Give two sphere entities a Wormhole with the same link and they are the two ends of one wormhole. A GravityBody whose centre comes inside either mouth comes out of the other at the same spot relative to it, with the same velocity, so its path carries on as if the two mouths were one hole in space. Either end leads to the other.

That drops the body inside the far mouth, which would send it straight back. A latch stops it: the mouth a body came out of stays closed to that body until it has left. The latch belongs to the body and lasts across frames, so a slow rock that sits in the exit for a while is never bounced home.

The jump is not made here. GravityBody makes it after every 1/120 s step, with throughWormholes from Wormhole.core, at the same point in the step where the aim line makes it for its ghost. A line that runs into one mouth comes out of the other exactly where the rock will. Checked once a frame instead, a rock lingered a step inside a mouth, and a black hole parked beside the mouth swallowed rocks the line showed passing through.

WormholeSystem is the mouths themselves. It pairs them, scales each sphere to the throat (0.42 of the catch radius), and flashes both ends when gravity.body.jumped names them. A mouth with no partner is drawn dim and slowed.

Setup

The engine work ships with the component, in adapter/register.ts. A project made with bjs create installs it for you: src/main.ts calls every adapter/register.ts that bjs download puts in the project, before the scene loads. If you boot the game from your own code, call it once, right after building the adapter:

TypeScript
import { registerWormholeExtension } from './Components/Wormhole/adapter/register';

const adapter = new BabylonAdapter();
registerWormholeExtension(adapter);
const game = new ArcadeGame(adapter, { … });

Without it the mouths are bare spheres, the jumps work the same, and the System warns once: [Wormhole] no adapter plugin registered. The plugin is Babylon only. On Three or babylon-lite the call registers nothing.

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.

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

    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
{
  "MouthA": {
    "tags": ["wormhole"],
    "components": {
      "MeshPrimitive": {
        "primitive": "sphere",
        "diameter": 1,
        "position": [-8, 0, -2],
        "material": { "diffuseColor": [0, 0, 0], "specularColor": [0, 0, 0] }
      },
      "Wormhole": { "link": "first-jump", "radius": 2.4, "color": [0.4, 0.8, 1] }
    }
  },
  "MouthB": {
    "tags": ["wormhole"],
    "components": {
      "MeshPrimitive": {
        "primitive": "sphere",
        "diameter": 1,
        "position": [21, 0, -6],
        "material": { "diffuseColor": [0, 0, 0], "specularColor": [0, 0, 0] }
      },
      "Wormhole": { "link": "first-jump", "radius": 2.4, "color": [0.4, 0.8, 1] }
    }
  },
  "Rock": {
    "tags": ["rock"],
    "components": {
      "MeshPrimitive": { "primitive": "sphere", "diameter": 1, "position": [-28, 0, -2] },
      "GravityBody": { "velocity": [11, 0, 0], "radius": 0.42, "maxSpeed": 45 }
    }
  },
  "Plant": {
    "components": {
      "MeshPrimitive": { "primitive": "torus", "diameter": 4.6, "thickness": 0.5, "position": [27, 0, -6] },
      "CaptureZone": { "radius": 2.5, "acceptTag": "rock", "points": 100 }
    }
  }
}

The rock flies along z = −2 into A and out of B, moved by B − A = (29, 0, −4), then carries on along z = −6 into the plant. The positions are SpaceGolf's First Jump level.

Props

  • link (string, default '') — mouths that share a link are the two ends of one wormhole. It takes exactly two: a link held by one mouth, or by three, opens nothing. An empty link never pairs.
  • radius (number, default 1.6) — how close a body's centre must come to the mouth's centre to be taken, in world units.
  • color ([r, g, b], default [0.45, 0.75, 1]) — the swirl's colour. Give both ends of a pair the same one, so a player can tell which mouth leads where.
  • spin (number, default 0.3) — swirl turns per second.

Events

  • gravity.body.jumped (listens) — flashes the two mouths it names as fromId and toId.

Wormhole emits nothing. The jump is announced by GravityBody.

Dependencies

GravityBody does the moving and depends on Wormhole, not the other way round. Mouths in a scene with no GravityBody move nothing.

Notes

  • A mouth takes a body by its centre. Unlike a mass surface, the body's own radius does not count.
  • Without the plugin only the throat is drawn, at 0.42 of the catch radius, so a rock is taken before it touches anything you can see.
  • A parked partner closes the pair until it is handed out again. Give each pair its own link: SpaceGolf uses spacegolf-<level>-<index>, so a pair never meets a mouth from another level.
  • MotionTrail also listens to gravity.body.jumped and restarts the rock's trail at the far mouth, so no streak crosses the field.

More like this

GravityBody
MeshPrimitive
AxisViewCamera
BlackHole
BoatMode
BoatWater
Bumper
CaptureZone
ContactDamage
ContactImpulse
DirectionalLight
EnvironmentTexture
Flash
GravityLens
GravityMass
HemisphericLight
LensFlare
MassDriver
Mesh
MotionTrail
MouseHole
NebulaSky
Obstacle
Physics
PointerDrag
Renderable
RoadTreadmill
Shadow
ShipDamageFX
Skybox
SmokeScreen
SpaceDust
SpaceGolfDirector
SpaceGolfHUD
SpaceRock
SpaceShooterFX
Spin
Spinner
SurfacePatch
ToneMapping
TrajectoryPreview
Velocity6DOF
WhiteHole

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search