logo
WhiteHole

physics · physics-puzzle

WhiteHole

2
Unlock

Install with the CLI:

bjs download WhiteHole

WhiteHole

A point in space that pushes everything away: a black hole turned inside out.

What it does

A white hole needs no new physics. GravityMass already pulls with mass · d / (|d|² + softening²)^1.5, and with a negative mass the same sum points away. So WhiteHoleSystem holds the GravityMass beside it at -strength, and GravityBody and the aim line push rocks with the arithmetic they already run, agreeing to the decimal.

Every frame it also pins the GravityMass radius to the core's and turns absorbs off, so a rock that does reach the core crashes into it instead of falling in. Whatever a scene or another system wrote to those three fields is put back. The System runs before GravityBody (priority 55 against 50), so a strength a level sets this frame is the push this frame.

The rest is the look: a bright core, rays streaming out, and ripples that run out to the edge of the push, so a player can see how wide a berth to give it. That edge is where a rock coming straight in at reachSpeed stops and turns back, from ½v² = strength / r:

TypeScript
stopDistance(400, 11); // 6.61, which is 2 · strength / speed²

A rock that passes off-centre turns away further out. Head-on is the closest anything at that speed gets.

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 { registerWhiteHoleExtension } from './Components/WhiteHole/adapter/register';

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

Without it the white hole is a bare sphere that pushes the same, and the System warns once: [WhiteHole] 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 WhiteHole
    bjs download WhiteHole

    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
{
  "Pusher": {
    "tags": ["whitehole"],
    "components": {
      "MeshPrimitive": {
        "primitive": "sphere",
        "diameter": 1,
        "segments": 24,
        "position": [0, 0, 6],
        "material": { "diffuseColor": [1, 1, 1], "specularColor": [0, 0, 0], "emissiveColor": [1, 1, 1] }
      },
      "GravityMass": { "softening": 0.6 },
      "WhiteHole": { "strength": 220, "radius": 0.9 }
    }
  },
  "Rock": {
    "tags": ["rock"],
    "components": {
      "MeshPrimitive": { "primitive": "sphere", "diameter": 1, "position": [-28, 0, 0] },
      "GravityBody": { "velocity": [11, 0, 0], "radius": 0.42, "maxSpeed": 45 }
    }
  }
}

Aimed to pass 6 units from the white hole, the rock is pushed about 30° off its line, toward −z, and never comes closer than 7.5 units. The GravityMass only needs softening, since the System writes the rest.

Props

  • strength (number, default 400) — how hard it pushes: the mass of a black hole that would pull as hard. Stored as a size, so a negative value still pushes.
  • radius (number, default 0.9) — the core a body crashes into, in world units. The sphere is scaled to match it.
  • reachSpeed (number, default 11) — only for drawing. The ripples run out to where a body at this speed, coming straight in, would turn back. 11 is SpaceGolf's launch speed.
  • coreColor ([r, g, b], default [1, 1, 1]) — the glare hugging the core.
  • haloColor ([r, g, b], default [0.62, 0.86, 1]) — the rays, the ripples and the line at the reach.

Events

None either way. The push travels through the GravityMass. A rock that hits the core is reported by GravityBody as gravity.body.contact, with swallowed: false.

Dependencies

  • GravityMass — on the same entity, and it is the push. Without one the System ignores the entity.
  • MeshPrimitive — the core sphere and its position.

Notes

  • WhiteHole turns lenses on when it joins, so a GravityLens sky bends away from it with no extra setting. Set it back to false after that to keep the sky still.
  • The drawn reach never shrinks inside the core. A reachSpeed of 0 has no edge to draw, so the ripples hug the core.
  • The System writes only the sphere's scale, so it never races MeshPrimitive, which places and shows it.
  • With no renderer at all it still pushes. Only the look needs one.

More like this

GravityMass
MeshPrimitive
AxisViewCamera
BlackHole
BoatMode
BoatWater
Bumper
CaptureZone
ContactDamage
ContactImpulse
DirectionalLight
EnvironmentTexture
Flash
GravityBody
GravityLens
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
Wormhole

Was this page helpful?

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

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search