ConicPath
The exact orbit of a MassDriver's next shot round one mass, drawn dashed from the equations instead of stepped.
What it does
Every frame ConicPath takes the shot the driver on its entity is about to fire: the muzzle position, the launch velocity, and where the named mass is now. From those it works out the orbit. With one mass pulling, every path is a conic: a circle, an ellipse, a parabola or a hyperbola. One formula draws all four:
Here ν is the angle round from the nearest point, e is the eccentricity, and p is the semi-latus rectum: the distance from the centre to the orbit a quarter turn round from the nearest point. The code works in p and never in the semi-major axis a. At exactly escape speed the energy is 0, and a = −μ/2ε divides by zero. p = h²/μ stays finite there, so the parabola between the ellipses and the hyperbolas needs no special case.
The dashes run forward from the muzzle along the direction of motion. They stop where the shot comes down on the mass (its radius plus the ball's bodyRadius), or after one lap, or at maxDistance for a shot that never comes back. A bound orbit that swings out past maxDistance is drawn as two arms, going out and coming back.
Two overlays show where simpler models stop working:
galileoadds Galileo's parabola from the same muzzle. It holds gravity at its muzzle strength and "down" at the muzzle's direction, and lands on flat ground that touches the round ground under the muzzle. Close in, it lies on the orbit. Its error shows where it comes down.ticksputs a short bar across the orbit at equal time steps over one lap. Each tick comes from Kepler's equation, M = E − e·sin E, solved by Newton's method until a step is smaller than a tolerance. Near the mass the ball is fast and the ticks spread out. Far away it is slow and they bunch up.
Nothing else pulls in this picture. Beside a second mass the drawn orbit and the real flight part, which is the three-body problem made visible.
When the orbit's kind or any of its numbers change, the System emits conicpath.changed. The numbers are rounded to 4 decimals, and that is also the smallest change it announces. It carries where the shot comes down and where Galileo's parabola does, so a difference of a few pixels on screen still reads as a number in the EventBus panel.
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:
The plugin draws the lines thick and sets them in depth: the orbit sits behind an aim line drawn in the same place, and Galileo and the ticks sit in front of both. Without the plugin the System draws the same lines one pixel wide with the engine's plain line system, and warns once. The plugin is for BabylonAdapter only.
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 ConicPath
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.
With this planet a sideways shot from 11 units out circles at 10, swings out to 28.29 at 12, and escapes at 14.14.
Props
around(string, default"Planet"): id of the entity to orbit, its key in the scene. It needs a GravityMass and a MeshPrimitive.bodyRadius(number, default0.3): the launched ball's radius. Match its GravityBody, or the drawn landing and the real one differ.maxDistance(number, default100): nothing is drawn farther than this from the mass's centre.segments(number, default240): points the orbit is sampled at.dashes(number, default90): the most dashes the orbit is cut into. A short path gets fewer, none shorter than six line widths.dashFill(number, default0.45): share of each dash slot that is drawn, kept between 0.05 and 1.galileo(boolean, defaultfalse): draw Galileo's flat-ground parabola too.ticks(number, default0): bars across the orbit at this many equal time steps per lap.tickLength(number, default1.4): length of a tick bar, in world units.color([r, g, b], default[1, 0.78, 0.25]): the orbit.galileoColor([r, g, b], default[0.92, 0.95, 1]): Galileo's parabola.tickColor([r, g, b], default[1, 0.5, 0.12]): the ticks.width(number, default0.2): line width in world units, read by the plugin.visible(boolean, defaulttrue): draw the lines. The event fires either way.
Events
Emits:
conicpath.changed:{ entityId, aroundId, kind, eccentricity, semiLatusRectum, energy, period, periapsis, apoapsis, landAngle, landX, galileoX }.kindiscircle,ellipse,parabola,hyperbolaorradial(a launch straight up or down).periodandapoapsisare 0 for a shot that never comes back.landAngleis the degrees round the mass to where the shot comes down.landXandgalileoXare where the orbit and Galileo's parabola come down, measured sideways from the muzzle. All three are 0 when the shot never comes down, andgalileoXis 0 withgalileooff. It fires on the first frame, when a number changes in its 4th decimal, and when a pooled driver comes back into play.
Listens to nothing.
Dependencies
MassDriver: required on the same entity, for the muzzle, direction and speed.MeshPrimitive: the driver's position and the mass's.GravityMass: the mass'smass(G = 1) andradius.
Notes
- The orbit is the centre of the launch cone. With MassDriver
spreadabove 0, real balls scatter round it. - Softening is ignored on purpose. A softened mass pulls less than mass/r² close in, so its real orbits turn a little every lap while the drawn ellipse stays put.
- The game's integrator stores velocity half a step behind, so a real shot comes down a little short of the drawn landing: under 0.1° for most shots, 2.1° for one that grazes the ground.
- A mass of 0 or less, or a launch from the mass's centre, draws nothing. A launch from inside the ground draws nothing and reports a landing at the muzzle.
- Parking the driver hides its lines until it is handed out again; destroying it, or taking the ConicPath off, disposes them.















































