Skip to content

Latest commit

 

History

History
552 lines (471 loc) · 34.6 KB

File metadata and controls

552 lines (471 loc) · 34.6 KB

Box2Dxt Kit Reference (b2k…)

The Kit (src/box2dxt-kit.livecodescript) is a batteries-included, pure-xTalk toolkit over the box2dxt extension. You work in pixels, screen coordinates and degrees; the Kit hides the world, the fixed-timestep loop, coordinate conversion, and the per-frame control updates — and it runs with the demo's performance practices built in.

Setup: paste the Kit into your card/stack script (or save it as a library stack and start using it). It requires the box2dxt extension loaded (put b2Version() should return 4).

New here? Read the Complete Guide first — it teaches the Kit start-to-finish with runnable examples. This page is the quick-lookup reference.


60-second start

on openCard
   b2kQuickStart                       -- world + gravity + card-edge walls + go
   b2kSpawnBall 200, 80, 50            -- create & drop a 50px ball
   b2kSpawnBox 260, 80, 60, 40, "orange"  -- (read `the result` for the ref)
   b2kContactTarget the long id of me  -- (optional) collision messages
end openCard
on mouseDown ; get b2kGrab(the mouseH, the mouseV) ; end mouseDown
on mouseUp   ; b2kRelease ; end mouseUp
on closeCard ; b2kStop ; end closeCard

Or attach controls you designed in the IDE (graphics rotate; other control types follow position):

b2kSetup                                       -- world + gravity, auto origin
b2kAddStatic the long id of graphic "Floor"
b2kAddBox    the long id of graphic "Crate"
b2kAddBall   the long id of graphic "Ball"
b2kContactTarget the long id of me             -- on b2kContact pA, pB
b2kStart

World & loop

Handler Purpose
b2kSetup [gx, gy] Create the world + gravity, auto-detect the origin.
b2kQuickStart [gy] One call: world + gravity + card-edge walls + start the loop.
b2kStart / b2kStop Begin / end the simulation loop.
b2kPause / b2kResume Freeze / resume stepping without tearing down.
b2kStepOnce Advance exactly one fixed step (even while paused) — drives a Step button.
b2kIsRunning() True while the loop is stepping (not stopped or paused).
b2kAddWalls Static walls around the current card edges.
b2kAddGround [screenY] A static floor across the card (optionally at a given Y).
b2kWall x1, y1, x2, y2 A static collision segment between two screen points (custom walls, ramps, ledges). Two-sided — bodies collide from both sides whichever way you list the points; for one-sided (jump-through) surfaces use b2kChain/b2kSmoothGround. Invisible — draw your own graphic to match. For level edges a character is driven against, prefer a thick invisible static box just outside the play space — it gives the solver a cleaner stop than a thin segment.
b2kKillFloor screenY Destroy any moving Kit body whose centre falls below this line (empty = off) — crates shoved into pits, enemies knocked off the level: removed instead of falling forever. The player's body is exempt (your game owns its respawn). Each removal first sends b2kFell ctrl to the frame target so you can clean up companions (bound sprites, table slots); don't delete the control inside that handler.
b2kClear Remove all bodies/controls the Kit created, keep the world.
b2kTeardown Stop and destroy the world and all Kit state.
b2kVersion() Native shim ABI version (4) — a load / in-sync check from Kit-only code.

Configuration

Handler Purpose
b2kSetScale px Pixels per metre (default 40).
b2kSetOrigin x, y Screen point that maps to the world origin.
b2kSetGravity gx, gy Change gravity (pixels-down is positive).
b2kSetSubsteps n Solver sub-steps per step (≈ 4).
b2kContactTarget obj Object that receives on b2kContact / on b2kEndContact messages.
b2kFrameTarget obj Object that receives an on b2kFrame message once per simulated frame.
b2kEnableSleeping flag Toggle island sleeping (saves CPU when bodies rest).
b2kEnableContinuous flag Toggle continuous collision (CCD) for the world.

Attach & spawn

Attach physics to existing controls, or spawn new ones. Pass controls by reference (the long id of … is safest). Add ,true/,false to force dynamic/static where a handler takes an optional dyn flag.

Any control type works — it falls, collides, and is draggable. How it's drawn to follow its body depends on the type:

Control Follows position Rotates
Graphic (box → polygon, or ball)
Image (dynamic) ✅ via the angle
Button / field / other ❌ rotation locked so the sim matches the upright render
Handler Purpose
b2kAddBox ctrl [,dyn] Treat a control as a dynamic (default) box.
b2kAddBall ctrl [,dyn] Treat a control as a circle.
b2kAddCapsule ctrl [,dyn] Treat a control as a capsule (pill); long side = axis, short side = diameter.
b2kAddPolygon ctrl [,dyn] Treat a graphic's points as a convex polygon.
b2kAddStatic ctrl Immovable body matching the control.
b2kAddGround [screenY] Static floor (see above).
b2kSpawnBox x, y, w, h [,color] → control Create a control and its box body.
b2kSpawnBall x, y, diam [,color] → control Create a control and its ball body.
b2kSpawnCapsule x, y, len, thick [,color] → control Create a pill-shaped control and its capsule body.
b2kReshape ctrl, "box"|"ball"|"capsule"|"poly" Rebuild a body's collision shape from the control's current size/points, on the same body (joints survive). Resets material + filter — re-apply them after.

Materials

Handler Purpose
b2kSetBounce ctrl, 0..1 Restitution.
b2kSetFriction ctrl, 0..1 Friction.
b2kSetDensity ctrl, d Density (affects mass).

Body settings

Handler Purpose
b2kSetBullet ctrl, flag Continuous collision for fast bodies.
b2kSetFixedRotation ctrl, flag Stop a body from rotating.
b2kSetGravityScale ctrl, s Per-body gravity multiplier.
b2kSetDamping ctrl, lin [,ang] Linear (and optional angular) damping.
b2kWake ctrl Wake a sleeping body.
b2kSleep ctrl Send a body to sleep until something wakes it.
b2kSetSleepEnabled ctrl, flag Allow / forbid this body ever sleeping (vs b2kEnableSleeping, which switches the whole world). The player controller forbids it on its body.
b2kSetSleepThreshold ctrl, pxPerSec Speed below which a body may fall asleep.
b2kSetStatic ctrl / b2kSetDynamic ctrl / b2kSetKinematic ctrl Change body type at runtime (freeze/unfreeze, moving platforms).
b2kSetType ctrl, "static"|"kinematic"|"dynamic" Set body type by name.
b2kDisable ctrl / b2kEnable ctrl Take a body out of / put it back into the simulation.

Act on bodies

Handler Purpose
b2kPush ctrl, dvx, dvy Add a one-shot impulse (change in velocity, px/s).
b2kForce ctrl, fx, fy Apply a continuous force (call each frame for thrust/wind).
b2kImpulse ctrl, ix, iy One-shot impulse, mass-aware (heavier bodies move less).
b2kTorque ctrl, torque Continuous turning force (call each frame); +/- sets direction.
b2kAngularImpulse ctrl, imp One-shot turning impulse, mass-aware (the angular partner of b2kImpulse).
b2kSetVelocity ctrl, vx, vy Set linear velocity (px/s). Wakes the body — setting a velocity means "move" (raw b2SetVelocity does not wake, which once froze a sleeping kinematic gate).
b2kSpin ctrl, degPerSec Set angular velocity.
b2kSpinBy ctrl, degPerSec Add to the current angular velocity.
b2kMoveTo ctrl, x, y [,deg] Teleport a body.
b2kExplode x, y [,radius] [,power] Radial impulse from a point.
b2kRemove ctrl Destroy a body (and the control if the Kit spawned it).

Read state

Handler Returns
b2kBodyOf(ctrl) The underlying b2… body handle.
b2kPosition(ctrl) Body centre as x,y in screen pixels (the position partner of b2kVelocity).
b2kWorldCenter(ctrl) Centre of mass as x,y in screen pixels (the true pivot for spin/torque).
b2kVelocity(ctrl) vx,vy in px/s.
b2kSpeed(ctrl) Scalar speed (px/s).
b2kAngle(ctrl) Rotation in degrees.
b2kMass(ctrl) Body mass (kg, sim units).
b2kGravityScale(ctrl) Per-body gravity multiplier (getter for b2kSetGravityScale).
b2kDamping(ctrl) Drag as linear,angular (getter for b2kSetDamping).
b2kBodyType(ctrl) Body type as a word: static / kinematic / dynamic.
b2kBodyCount() How many bodies the Kit is tracking.
b2kAwakeCount() How many dynamic bodies are currently awake (active).
b2kIsAwake(ctrl) Whether the body is awake.
b2kSpinRate(ctrl) Rotation speed in degrees/sec (getter for b2kSpin).
b2kIsBullet(ctrl) Whether continuous (CCD) collision is on.
b2kIsEnabled(ctrl) Whether the body is in the simulation.
b2kControlAt(x, y) The control whose body covers a screen point.
b2kControlContains(ctrl, x, y) True if a screen point is inside this control's actual (rotated) collision shape.
b2kRayHit(x1, y1, x2, y2) True if a ray hits; then read the result functions below.
b2kRayHitX() / b2kRayHitY() Hit point in screen pixels.
b2kRayHitNormalX() / b2kRayHitNormalY() Surface normal at the hit (screen-oriented unit vector).
b2kRayDist() Distance in pixels from the ray start to the hit.

Joints

All joint constructors return a joint handle; pass it to the motor/limit/spring helpers or to b2kRemoveJoint.

Handler Purpose
b2kHinge ctrlA, ctrlB, x, y → joint Revolute pivot at a screen point (ctrlB empty = pin ctrlA to the world).
b2kWeld ctrlA, ctrlB → joint Rigidly glue two controls.
b2kRope ctrlA, ctrlB [,len] → joint Maximum-distance link.
b2kSlider ctrlA, ctrlB, axisDeg → joint Prismatic: slide ctrlA along an axis (0 = horizontal, 90 = vertical) relative to ctrlB or the world.
b2kWheel chassis, wheel, x, y [,axisDeg] → joint Wheel joint: sprung sliding axis + free spin (vehicle wheels).
b2kRemoveJoint joint Remove a joint.

Motors, limits, springs & readouts:

Handler Purpose
b2kMotor joint, degPerSec [,maxTorque] Drive a hinge joint.
b2kHingeLimit joint, lowerDeg, upperDeg Constrain a hinge's angle.
b2kHingeAngle(joint) → degrees Current hinge angle.
b2kSliderMotor joint, pxPerSec [,maxForce] Drive a slider.
b2kSliderLimit joint, lowerPx, upperPx Constrain a slider's travel.
b2kSliderPos(joint) → pixels Current slider translation.
b2kWheelMotor joint, degPerSec [,maxTorque] Drive a wheel.
b2kWheelSpring joint, hertz [,damping] Tune wheel suspension.
b2kRopeRange joint, minPx, maxPx Set a distance joint's min/max length.
b2kRopeLength(joint) → pixels Current distance-joint length.
b2kRopeSetLength joint, px Set a distance joint's exact rest length.
b2kSpring joint, hertz [,damping] Make a rope (distance) joint springy.
b2kWeldSpring joint, hertz [,damping] Make a weld springy (0 hertz = rigid).
b2kMotorOff joint Turn a hinge motor off (free swing).
b2kHingeLimitOff joint Remove a hinge's angle limits.
b2kSliderMotorOff joint Turn a slider motor off.
b2kSliderLimitOff joint Remove a slider's travel limits.
b2kWheelMotorOff joint Turn a wheel motor off.

Input (keyboard)

Poll-based held-key input for games: arm it once, then read state from on b2kFrame. The Kit samples the keysDown once per frame and diffs against the previous frame, so held keys are smooth (no OS auto-repeat artifacts), no focus or message-path setup is needed, and pressed/released edges are exact. Key names: left right up down space return escape tab shift control alt backspace delete, single characters ("a""z", digits — letters match both shifted and unshifted), or raw keycodes.

Handler Purpose
b2kInputOn / b2kInputOff Arm / disarm the per-frame keyboard sample. b2kInputOn installs starter bindings: axis moveX (left,a / right,d), axis moveY (up,w / down,s), action jump (space).
b2kInputInject keys / b2kInputInjectOff Replace the keyboard with a scripted key set (friendly names or codes; empty = nothing held) until turned off. Deterministic input for the self-test harness, input replays, and cutscene "ghost" players — edges fall out of the normal frame diff exactly as with real keys.
b2kKeyIsDown(key) Key currently held.
b2kKeyPressed(key) / b2kKeyReleased(key) True only on the frame the key went down / came up.
b2kKeysHeld() Everything held now, as friendly names (debug HUDs).
b2kBindAction name, keyList Name a key set: b2kBindAction "jump", "space,up,w".
b2kActionIsDown(name) / b2kActionPressed(name) / b2kActionReleased(name) Action-level queries — any bound key counts; edges treat the set as one logical key.
b2kBindAxis name, negKeys, posKeys Define a -1/0/+1 axis.
b2kAxis(name) Read an axis; both directions held = 0.
b2kKeyCodes(key) / b2kKeyName(code) The name↔keycode maps the module uses (handy for debugging).
b2kFrameMS() Real elapsed ms folded into the last frame — drive animations and timers from this, not the step count.
on openCard
   b2kQuickStart
   b2kSpawnCapsule 200, 100, 64, 30, "gold"
   put the result into gHero
   b2kSetFixedRotation gHero, true
   b2kInputOn
   b2kFrameTarget the long id of me
end openCard

on b2kFrame
   b2kSetVelocity gHero, b2kAxis("moveX") * 240, item 2 of b2kVelocity(gHero)
   if b2kActionPressed("jump") then b2kPush gHero, 0, -420
end b2kFrame

See examples/box2dxt-platformer.livecodescript for the full pattern (grounded check, jump-cut, one-way ledge).

Sprites & animation

Spritesheet animation on the icon-button backend (chosen by the Phase 0 benchmarks): a sheet registers named or numbered frame regions of one hidden source image; each region is sliced into its own hidden image lazily, on first use; a sprite is a transparent button whose icon is the current frame — all sprites of a sheet share the same frame images. Sheets persist until b2kTeardown; sprites are Kit-created controls, so b2kClear removes them with everything else, and every teardown also sweeps orphaned sprite controls left over from a previous session (script state resets when a stack reopens; the controls don't — without the sweep they'd linger as ghost sprites frozen on their last frame).

Handler Purpose
b2kSheetLoad name, path, fw, fh [,count] [,margin] [,spacing] → count Register an image file as a uniform grid of fw×fh frames, numbered 1..N row-major. margin = outer border px, spacing = gap between cells (both default 0, edge-to-edge). Frame size 0 = no grid: name regions yourself with b2kSheetAddFrame.
b2kSheetLoadAtlas name, pngPath [,xmlPath] → count Register a packed atlas: PNG + TextureAtlas XML naming its regions (the Kenney format — see Spritesheets/ in this repo). Frames are addressed by name ("coin_gold"). XML path defaults to the PNG path with .xml.
b2kSheetFromImage name, imgRef, fw, fh [,count] [,margin] [,spacing] → count Register an image already in the stack (e.g. base64-embedded art) as a grid sheet. Same grid arguments as b2kSheetLoad.
b2kSheetAddFrame sheet, frame, x, y, w, h Name one region yourself — the no-XML path for packed sheets in any layout: load the source with frame size 0, then add each frame by name (any size/position; redefining re-bakes). Also works on top of a grid or atlas.
b2kSheetFrames(name) / b2kSheetHasFrame(name, frame) / b2kSheetFrameNames(name) Frame count / existence / every frame key one per line (introspect an atlas you didn't make).
b2kSheetScale name, factor Display scale for the sheet's frames (default 1, range 0.05–8) — the engine resamples at slice time, so any frame size displays at any sprite size. Set it right after loading, before creating sprites or anims.
b2kSheetFrameSize(name, frame) → "w,h" A frame's display size (region × scale) — lay out tiles and platforms from this instead of hard-coding pixels.
b2kAnimDef sheet, anim, frames, fps [,loop] Name an animation: frames is a comma list of names and/or indices, numeric ranges ("1-8") expand. loop defaults true.
b2kSpriteNew sheet [,frame, x, y] → control Create a sprite showing frame (default: the sheet's first), sized to the frame. An ordinary Kit control: give it a body (b2kAddCapsule …) or bind it to one.
b2kSpriteFromGIF path [,x, y] → control An animated-GIF sprite (the engine plays it; play/stop/frame map to repeatCount/currentFrame).
b2kSpritePlay spr, anim [,restart] Start a named animation — a no-op if already playing it, so calling it every frame from a state machine is free.
b2kSpriteStop spr / b2kSpriteAnim(spr) Freeze on the current frame / what's playing.
b2kSpriteSetFrame spr, frame / b2kSpriteFrame(spr) Manual frame control (stops any animation).
b2kSpriteFPS spr, fps Per-sprite speed override (empty = each animation's own fps).
b2kSpriteFlipH spr, flag / b2kSpriteFlipped(spr) Face left/right — mirrored frames are flip-cloned lazily, shared like the originals.
b2kSpriteOnFinish spr, message When a non-looping animation ends, send message spr, anim to the frame target (attack/death/effect chains).
b2kSpriteMoveTo spr, x, y Move any sprite/control to a world position, camera-correct — use this instead of set the loc for hand-animated paths (patrols, hovering).
b2kSpriteBind spr, bodyCtrl [,dx, dy] / b2kSpriteUnbind spr Pin the sprite to another control's position each frame — the standard "art bigger than the collision shape" pattern: an invisible control owns the body, the sprite follows it.
b2kSpriteRemove spr Remove the sprite (and its body, if it has one).
b2kSheetLoadAtlas "chars", tFolder & "/spritesheet-characters-default.png"
b2kAnimDef "chars", "walk", "character_beige_walk_a,character_beige_walk_b", 6, true
b2kSpriteNew "chars", "character_beige_idle", 200, 100
put the result into tSpr
b2kSpritePlay tSpr, "walk"
b2kSpriteFlipH tSpr, true       -- face left

Performance notes (Phase 0 measurements, modest Win32 hardware): a frame switch is one icon set; ~25 moving animated sprites ≈ 40 fps, a player plus a handful sits at the loop ceiling. Create sprites at scene load (not mid-play) and before enabling acceleratedRendering where possible — bulk control creation under the compositor caused the spike's one-time stall.

Player (the platformer controller)

A complete keyboard character controller for one player: a vertical capsule with fixed rotation, sleep disabled, and low friction, steered every frame from the Input module's axis moveX and action jump (rebind those names to remap the controls). Horizontal motion is velocity-driven — vx accelerates toward axis × moveSpeed — and grounding comes from three short downward rays whose surface normal must point up within maxSlopeDeg, so walkable slope vs wall is one comparison. The jump feel platformers expect is built in: coyote time (jump shortly after running off a ledge), jump buffering (press just before landing), jump-cut (tap = hop, hold = full height), and a terminal fall speed. With animations mapped, the controller drives b2kSpritePlay/b2kSpriteFlipH itself.

Handler Purpose
b2kPlayerMake x, y, w, h [,sheet] → control One call: a capsule body host (w×h collision box — a visible capsule graphic, or invisible with a bound sprite of sheet's first frame on top), controller armed, input on. Reports the player control.
b2kPlayerAttach ctrl Adopt an existing control (or sprite) as the player. A capsule body is added if it has none (then the controller also sets low friction); a body you made yourself keeps your material. Also sets fixed rotation + sleep-off and arms input.
b2kPlayerAnims idle, run, jump [,fall] [,land] Map states to the art's animation names (fall defaults to jump). land is an optional non-looping touch-down flourish, held for its own duration. The art is the player control itself if it is a sprite, else the first sprite b2kSpriteBind-pinned to it.
b2kPlayerSet key, value / b2kPlayerGet(key) Tuning knobs (table below). Settable any time; b2kClear keeps them (config, like input bindings), b2kTeardown/b2kPlayerRemove wipe them.
b2kPlayerOnGround() Grounded this frame (post-tick; false on the frame a jump launches).
b2kPlayerState() idle / run / jump / fall, plus land for exactly one frame on touch-down (dust puffs, sounds — read it in on b2kFrame).
b2kPlayerFacing() 1 right / -1 left — the last horizontal intent.
b2kPlayerJump [speed] Programmatic jump (springs, double-jump powerups): the same launch as a pressed jump but without the grounded/coyote gate — the caller decides when it is allowed.
b2kPlayerControl flag false = the controller only observes (state/ground/facing stay fresh) and writes neither velocity nor animations — cutscenes, knockback, hit poses. The maxFall clamp stays live. true re-asserts the state animation.
b2kPlayer() / b2kPlayerSprite() The player control / the art control the controller animates.
b2kPlayerRemove Tear down the controller (tuning included). The body and sprite remain yours — remove them with b2kRemove / b2kSpriteRemove.

Tuning keys (b2kPlayerSet), with defaults for a 32×48 px player at scale 40: moveSpeed 220 px/s · accel 1800 px/s² · airAccel 1100 px/s² · jumpSpeed 460 px/s · jumpCut 0.45 (velocity multiplier on early release) · coyoteMs 90 · bufferMs 110 · maxFall 900 px/s · maxSlopeDeg 50 (steeper than this is a wall, not ground).

-- a playable character in four lines (after b2kQuickStart + sheet load):
b2kPlayerMake 200, 100, 32, 48, "chars"
put the result into gHero
b2kPlayerAnims "idle", "walk", "jump", "jump"
b2kCamFollow gHero

One player at a time: attaching a new player replaces the old controller state (the old body/sprite stay). The platformer example adopts its own invisible body host with b2kPlayerAttach — its entire movement, ground-probe and animation code is these four calls.

Feel guarantees (all asserted by the self-test): the coyote/buffer windows run on sim time (frame-coherent on slow machines); bodies the controller creates get zero restitution and low friction (landings are dead, walls don't glue); a touchdown is a land only after real airtime (landing hysteresis — solver blips can't double-fire it); and a ground-snap removes the solver's post-landing rebound on flat ground — slopes are exempt via the surface normal, and external boosts must use b2kPlayerJump (a raw upward b2kSetVelocity on a grounded player is treated as solver noise and snapped).

Camera (scrolling levels)

A clipped viewport group the loop scrolls (the mechanism the Phase 0 spike benchmarked). While the camera is on, Kit-created controls — spawns and sprites — are placed inside the viewport, and their locs stay world pixels: contents of a scrolled group keep their coordinates, so physics and the body sync are untouched and the scroll is pure presentation. Chrome stays on the card; anything layered behind the (transparent) group reads as an infinite-distance parallax backdrop. Level coordinates should start at 0,0.

Handler Purpose
b2kCamOn [rect] Create the viewport (default: the card rect). Do this before building the level, after any static backdrop.
b2kCamOff Dissolve the viewport — children return to the card with their world locs. Called automatically by b2kTeardown.
b2kCamIsOn() / b2kCamGroup() State / the group's ref — build your own level controls inside it: create graphic "x" in b2kCamGroup().
b2kCamAdopt ctrl Move an existing control (IDE-designed levels, fallback shapes) into the viewport.
b2kCamFollow ctrl [,lerp] / b2kCamUnfollow Track a control; lerp 0.01–1 smooths (default 0.15).
b2kCamDeadzone w, h Chase only once the target leaves a centre box (0 = always centre).
b2kCamBounds x1, y1, x2, y2 Clamp the view to the level.
b2kCamGoto x, y / b2kCamPos() Cut to a world point / read the view centre.
b2kCamShake ampPx, ms A decaying random view offset (impacts, blasts).
b2kCamStatus() Empty = healthy; otherwise why the camera degraded (group/scroll failures). Check it after b2kCamOn and fall back gracefully.
b2kCamLocSemantics() "visual" or "content" — which grouped-loc coordinate model the startup probe detected. Diagnostic; the Kit compensates automatically.
b2kCamMouseX() / b2kCamMouseY() The mouse in world pixels — use for b2kGrab, click-picking, spawning at the pointer. (The Kit's own drag already uses them.)
b2kCamOn
b2kCamBounds 0, 0, 3072, 640
b2kCamDeadzone 140, 600
b2kCamFollow gHero, 0.18
-- in mouseDown:  get b2kGrab(b2kCamMouseX(), b2kCamMouseY())

The platformer example is a complete scrolling level on this module.

Sound (SFX — with or without asset files)

Named sounds over audioClips — the one LiveCode sound path with no external media-layer dependency. The engine plays one clip at a time (a new play cuts the previous); that's the classic LC limit, and short retro SFX suit it. b2kToneMake synthesizes a clip in pure script (8-bit mono WAV, square or sine, a comma list of note frequencies with a per-note decay), so a self-contained stack ships sound with zero files. Sounds are assets like sheets: b2kTeardown wipes them (names are stable, so re-making replaces rather than accumulates). Failures degrade to silence, never errors — the first play that throws trips a dead-flag.

Handler Purpose
b2kSoundLoad name, path Import a WAV/AIFF/AU file as a named sound (replaces any same name).
b2kToneMake name, freqs, msPerNote [,vol] [,shape] Synthesize a sound: freqs like "1319,1760" (Hz; 0 = a rest), vol 0–100 (default 60), shape "square" (default, retro) or "sine" (soft). ~22 KB per second — keep SFX short.
b2kSound name Play (cuts whatever is playing). Stale-safe: unknown names and dead audio no-op.
b2kSoundLoop name / b2kSoundStop Loop ambience until stopped / stop the current sound.
b2kSoundMute flag / b2kSoundMuted() Swallow play calls — a user preference that survives b2kTeardown.
b2kSoundVolume pct The engine-global playLoudness (0–100) — it affects every stack's audio, so expose it, don't hardcode it.
b2kSoundIsLoaded(name) / b2kSoundStatus() Loaded check / empty = healthy, else the most recent reason audio degraded.
b2kToneMake "coin", "1319,1760", 36          -- a two-note blip
b2kToneMake "win", "523,659,784,1047", 110   -- a little fanfare
-- in your coin handler:  b2kSound "coin"

The platformer's eight cues (jump, land, coin, stomp, hurt, checkpoint, gate, win) are all synthesized — no asset folder involved.

Drag & events

Handler Purpose
b2kGrab(x, y) → control Grab the body under a point (mouse joint). Returns the grabbed control, or empty.
b2kRelease Release a grabbed body.
on b2kContact pCtrlA, pCtrlB Sent to your b2kContactTarget when two attached controls begin touching. Long ids are empty for walls/ground.
on b2kEndContact pCtrlA, pCtrlB Sent when two attached controls stop touching.
on b2kFrame Sent to your b2kFrameTarget once per simulated frame (after bodies sync) — use it for motors, input, and custom drawing.
on b2kFell pCtrl Sent to your b2kFrameTarget just before the Kit removes a body that crossed the b2kKillFloor line.

Frame-exact events: contact and sensor events are harvested after every fixed step and buffered for the frame — a frame that ran two physics steps loses nothing, and a frame that ran zero repeats nothing. The messages and the polling accessors below both read the same frame buffer.

Polling contacts — instead of (or alongside) the messages above, read this frame's touch pairs directly, e.g. from on b2kFrame. Indices are 1-based; each accessor returns a control (empty for a wall, the ground, or any untracked body).

Handler Returns
b2kContactCount() How many pairs began touching this frame.
b2kContactA(i) / b2kContactB(i) The two controls of the i-th begin-touch pair.
b2kEndContactCount() How many pairs stopped touching this frame.
b2kEndContactA(i) / b2kEndContactB(i) The two controls of the i-th end-touch pair.

Sensors (trigger zones)

One-shots vs. presence: sensor enter/exit messages are ideal for one-shot triggers (coins, checkpoints, goals — consumed or guarded on first fire). For presence state that must stay true while something sits there (pressure plates, buttons, zones), poll b2kOverlap of the region each frame instead of counting enters minus exits: a poll is stateless (it cannot drift), and the broadphase still includes sleeping bodies — a crate that settles and sleeps keeps holding the plate. The platformer's plate works this way, with a ~0.2 s release debounce for feel.

Non-solid fixtures that report overlaps but never block. The Kit enables sensor events on every body it creates, so sensors detect them automatically.

Handler Purpose
b2kAddSensor ctrl [,shape] → body Attach a static sensor (shape = box/ball/capsule).
b2kSetSensor ctrl, flag Flip an existing body between solid and sensor (rebuilds the shape, keeping the new sensor state).
on b2kSensorEnter pSensorCtrl, pVisitorCtrl Sent to your b2kContactTarget when a body enters a sensor.
on b2kSensorExit pSensorCtrl, pVisitorCtrl Sent when it leaves.
b2kSensorCount() / b2kSensorEnterSensor(i) / b2kSensorEnterVisitor(i) Poll this frame's enters (1-based).
b2kSensorExitCount() / b2kSensorExitSensor(i) / b2kSensorExitVisitor(i) Poll this frame's leaves (1-based).

Collision filtering (named layers)

Up to 32 layers. Two shapes collide only if each one's category is in the other's mask (and no shared negative group forbids it).

Handler Purpose
b2kDefineLayer name → bit Define/fetch a named layer.
b2kSetCategory ctrl, layers Set which layer(s) a control is (comma/space list of names or numbers).
b2kSetMask ctrl, layers Set which layer(s) it collides with.
b2kSetCollisionGroup ctrl, n Negative = never collide with same group; positive = always.
b2kNoCollide ctrlA, ctrlB → joint Stop just these two from colliding (a filter joint).

Chains & terrain

Handler Purpose
b2kChain pointList [,loop] → chain Smooth static terrain from a list of x,y screen points (≥ 4). No inner corners for fast bodies to catch on. Invisible — draw a matching graphic.
b2kSmoothGround pointList → chain An open chain (alias for b2kChain …, false).
b2kAddChain ctrl, pointList [,loop] A smooth chain that tracks a control (move/draw the terrain as one graphic). Points are the control's own outline.

Winding: a chain's solid side is to the right of the point-travel direction. For ground you stand on, list the top surface right-to-left so the solid side faces up. (Bodies falling through everywhere? Reverse the point order.)

The ghost rule (open chains): Box2D treats an open chain's first and last segments as ghost anchors — they don't collide (N points ⇒ N−3 solid segments). Run the chain one segment past the surface you need on each side; over solid ground the tails can simply continue flat. Endpoints placed at a platform's edges leave its ends intangible — bodies fall through the outer tiles. (Bodies falling through near the ends? This, not winding.)

Region & ray queries

Handler Returns
b2kOverlap x1, y1, x2, y2 Newline list of controls whose body overlaps a screen rect.
b2kOverlapCircle x, y, r …overlapping a screen circle.
b2kRayHitAll x1, y1, x2, y2 Every control a ray crosses, nearest-first (vs b2kRayHit's single closest).

Motors & tuning

Handler Purpose
b2kMotorTo mover, ref, dxPx, dyPx, deg [,maxF, maxT] → joint Drive mover toward a pose offset from ref (a moving anchor; empty = world).
b2kExplode x, y [,radius] [,power] Native radial blast (shape-aware, affects all dynamic bodies). b2kExplodeLegacy keeps the old velocity-based feel.
b2kSetRestitutionThreshold px/s · b2kSetContactTuning hz, damp, pushPx · b2kSetJointTuning hz, damp · b2kSetMaxSpeed px/s · b2kEnableWarmStarting flag World solver tuning.
b2kProfile() "totalStep,collide,solve" ms for the last step (a perf HUD).
b2kAwakeBodyCount() Awake dynamic bodies (native count).

Tips

  • Keep moving objects a sensible on-screen size (default scale 40 px/m, so roughly 4–400 px).
  • Graphic boxes/polygons and dynamic images rotate with their body (images via the angle). Buttons, fields, and other controls follow position only and have their rotation locked, so the simulation stays consistent with the upright render.
  • The Kit render loop uses Box2D body-move events, so it only considers bodies that moved in the latest step, avoids per-body awake/position polling for sleeping objects, and skips redraws when the rounded screen pixel/angle did not change.
  • When you need something the Kit doesn't expose, drop to the core b2… API: b2kWorld() returns the world and b2kBodyOf(control) the body, and b2kToWorldX/Y(px) / b2kToScreenX/Y(m) convert between screen pixels and Box2D metres — so you can mix both layers.