Gameplay Verbs

The gameplay layer gives a 2D body the actions and questions a game designer talks about: jump off a wall, bounce off a pad, drive along the floor, stick to it, align to it, aim at an angle, fall slower, predict where the ball lands, ask whether a jump can still reach a height. Game code then reads like its rules:

using Altruist.Gaming.TwoD;

if (jumpPressed && onSurface) car.JumpOff(surfaceNormal, cfg.JumpSpeed);
if (grounded)
{
    car.DriveAlong(tangent, throttle * cfg.MaxSpeed, cfg.Acceleration, dt);
    car.StickTo(groundNormal, cfg.Grip, dt);
    car.AlignToSurface(groundNormal, cfg.AlignRate);
}
else
{
    car.AimAt(stickAngle, cfg.AimGain, cfg.MaxSpin, cfg.SpinAcceleration, dt);
    car.ApplyDrag(cfg.AirDrag, dt);
}
car.ClampTopSpeed(cfg.TopSpeed);
ball.Fall(gravity, dt, gravityScale: superCharged ? 0.5f : 1f);

Verbs stay generic: they name what happens to the body, never which game it is. Each verb delegates to one physics-layer operation, which delegates to the math layer, keeping the exact operation order: a verb gives the same bits as the hand-written update it replaces. Conventions: +Y up, gravity is the pull toward -Y, counter-clockwise angles with the body's local +Y as its up.

Launching and Jumping

VerbEffect
JumpOff(surfaceNormal, speed)Cancel any motion into the surface, then add speed out along its normal (pass the body's own up for an air jump)
PushAlong(direction, speed)Add speed in a direction, keep the current motion
LaunchAlong(direction, speed)Replace the motion with speed along direction
LaunchForward(localForward, speed)LaunchAlong the body's own axis (e.g. Vector2.UnitX) in world space
CancelMotionAgainst(direction, fraction = 1)Cancel part of the motion opposing a thrust before applying it
BounceOff(normal, outSpeed, tangentKeep[, incoming])Rebound or launch pad: outSpeed out of the surface plus a share of the motion along it, from the current or a recorded velocity
AbsorbImpact(velocityBefore, spinBefore, keep)Keep only keep of the velocity change a hit caused (recoil)

Driving on Surfaces

VerbEffect
DriveAlong(tangent, targetSpeed, acceleration, dt)Speed up / slow down along the surface tangent, motion across it untouched
BrakeAlong(direction, deceleration, dt)Brake toward a stop along a direction
SetSpeedAlong(direction, speed)Set the speed along a direction (e.g. a fixed drift off a wall)
FollowSurface(tangent)Carry all speed along the tangent, so curves do not throw the body off
StickTo(surfaceNormal, acceleration, dt)Press into the surface (grip)

BodyMotionExtensions2D.SpeedAlong(direction) reads the current speed along a direction for the decisions between these verbs.

Horizontal and Vertical Motion

Each writes one component directly and keeps the other (a component along (1, 0) through SetSpeedAlong would round differently):

VerbEffect
SetVelocityX(x) / SetVelocityY(y)Set one component
ScaleVelocityX(factor) / ScaleVelocityY(factor)Scale one component (cut the run-up when launching up, damp the lift of a burst)
ClampVelocityY(min, max)MathF.Min(MathF.Max(v.Y, min), max): e.g. no fall and at most a small hop
// A flip burst: a fixed horizontal speed, the lift capped to a small hop.
body.SetVelocityX(flipDir * burstSpeed);
body.ClampVelocityY(0, cfg.HopSpeed);

Speed, Drag and Gravity

VerbEffect
ClampTopSpeed(maxSpeed)Never faster than maxSpeed
ApplyDrag(drag, dt)Linear (air) drag for one step
BleedSpeed(amount)Lose amount of speed, keep the direction
Fall(gravity, dt, gravityScale = 1)Per-body gravity for one step: below 1 floats / hovers, above 1 is heavier
KeepRolling(minSpeed, fallbackDirection)Never come to rest horizontally

Orientation

VerbEffect
AlignToSurface(normal, rate)Turn the body's up toward a surface normal
TurnToAngleIn(angle, time, minTime)Turn so the angle is reached in time seconds
AimAt(angle, gain, maxRate, angularAcceleration, dt)Stick-style steering: rate proportional to the error, capped, reached with limited angular acceleration
StopSpinning(angularAcceleration, dt)Slow the spin to zero
HoldAngle(angle, gain)Hold an angle with a proportional rate
UprightAngleOn(normal)The angle standing upright on that surface, nearest the current rotation (never an extra full turn)
LevelAngle()The level angle nearest the current rotation (after a spin)
SnapUprightOn(normal, sink = 0)Snap upright onto a surface, move sink into it, stop spinning
FlipHalfTurn()Half a turn on the spot (roof becomes underside), position and motion kept
JumpAsAimed(aimedRotation, speed)JumpOff(Rotation2D.UpAt(aimedRotation), speed): jump along where the player aims, not the half-turned body
ResetMotion(position, angle, velocity, spin)Place the body with a motion and wake it

Questions (Prediction, Reach, Aim)

Bots and assists ask these:

VerbAnswer
ImpactSpeedAgainst(normal)How hard the body hits a surface
VelocityAt(worldPoint)Velocity of a point of the body (spin included)
PredictPosition(t, gravity)Where a free-flying body is in t seconds
PredictLanding(gravity, dt, steps, floorY, restitution)Position and velocity after stepping, bouncing on a floor
RiseLeft(gravity)How much higher free flight still takes it
CanReachHeight(height, gravity, margin = 0)Whether free flight still reaches height above it
WillEnter(zone, gravity, lookahead, steps, marginX, marginY, velocity?)Whether its flight enters an Aabb2D (a goal, a hazard) within lookahead seconds
PredictZoneEntry(zones, gravity, dt, steps, floorY = -∞)(Zone, Step): which of several zones its flight enters first, and when; (-1, -1) if none or it lands first
UpDirection() / HeightAbove(point)The body's up in the world / how far a point is above its center along that up (a one-way platform: is the ball over the top face?)
VelocityToHit(target, gravity, time)The throw that lands on target in time seconds
TimeToReach(target, acceleration, maxSpeed)Seconds to get there in a straight line from the current speed toward it
BrakingDistanceAlong(direction, deceleration)Distance needed to stop the motion along a direction
IsWithinBox(point, halfW, halfH, padX, padY) / IsClearOfBox(point, halfW, halfH, gap)A point against the body's box (e.g. a nose tip against another car)
if (ball.WillEnter(ownGoal, gravity, lookahead: 1.2f, steps: 24, marginX: 1.3f))
    keeper.JumpOff(Vector2.UnitY, cfg.JumpSpeed);

var lob = striker.VelocityToHit(target, gravity, time: 0.9f);
if (!bot.CanReachHeight(ball.Position.Y - bot.Position.Y, gravity, margin: 1)) PlanAerial();

Facing Bodies (FacingFrame2D)

A box-shaped body that faces left or right (a side-view vehicle, a fighter): new FacingFrame2D(body, facing, halfWidth, halfHeight), with facing +1 for a nose on local +X and -1 for local -X. A view over the body, cheap to make whenever needed.

MemberAnswer
Nose / UpGetWorldVector((facing, 0)) / GetWorldVector((0, 1))
NoseTipPosition + Nose * halfWidth
IsInFront(point)GetLocalPoint(point).X * facing > 0: did it come in through the front?
NoseAlignment(direction)Nose · direction: how well the nose lines up with a direction
ZoneAt(point, axisBias) / ZoneToward(direction, axisBias)Which side (BoxSide2D.Front, Back, Top, Bottom, in facing terms) a contact point touched / a direction faces (Geometry2D.ClassifyBoxSide)
UndersideEnds()(Back, Front): the bottom corners, e.g. to cast rays down from both ends
AimRotationToward(direction)The body rotation that points the nose along direction (Rotation2D.AngleAligningForward)
var frame = new FacingFrame2D(car, facing, halfW, halfH);
var zone = frame.ZoneAt(contactPoint, axisBias: 1.35f);     // map to your own names: Front = nose, Bottom = wheels
if (zone == BoxSide2D.Bottom) RefillAirJump();
var (back, front) = frame.UndersideEnds();
var target = frame.AimRotationToward(stick);                 // then car.AimAt(target, ...)

Client Twin

The TypeScript package has the same verbs as functions taking the body first (jumpOff(body, normal, speed)), working directly on planck.js bodies, so a client-side prediction of the server simulation calls the same verbs.