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:
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:
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:
- 1Scaffold a project
World, renderer, and dev server — ready to run.
- 2Install dependencies
- 3Add WhiteHole
Copies its source into src/ so the scene resolves.
First time? Run bjs login once.
- 4Paste the scene into src/scenes/arcade-room.ts and run
SceneLoader builds the world from the JSON; reload to rebuild.
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, default400) — 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, default0.9) — the core a body crashes into, in world units. The sphere is scaled to match it.reachSpeed(number, default11) — 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
lenseson when it joins, so a GravityLens sky bends away from it with no extra setting. Set it back tofalseafter that to keep the sky still. - The drawn reach never shrinks inside the core. A
reachSpeedof 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.











































