Skip to content

Movement for a game's builder ​

One page for someone building a game: what a character does with no code, the calls there are, what it costs and what is not right yet. The whole system is described on the movement page.

What a character gets with no code ​

A character exported from the Gameable Studio is moved by whole takes of a performer. Give it a velocity, as a game always has (character.setState), and:

  • it stands, moves off, walks, runs, turns, slows and stops as the performer did;
  • the take carries its walker (physics.moveCharacter), so nothing slides; up and down stay the game's;
  • a foot that is down is held where it landed, and each landing is an anim-event named step on the clip left-foot or right-foot, said the moment the foot has come to rest on the floor (or as it lifts, in a run's short stance);
  • its own walk, run and standing clips still go round underneath a take, unseen, and say nothing meanwhile: an anim-event named loop on one of them comes only while that clip is what is drawn (its own stance at rest). For the beat of a stride under a take, listen for step. A clip the game names itself (character.setClipWeights) says loop and ended as ever. (Such a loop is handed over once the takes have run that frame, so in one frame's events it can come after an event it used to come before.)
  • at rest it stands in its own captured stance;
  • it stands and idles at once; its takes arrive after it stands and take the body over by a blend, never a jump. A motion-event of kind ready says when.

A character that is not on the shared skeleton (the sample character, a plain body) walks by its clips, as before.

A character a person straightened by hand in the studio ("Adjust pose", holding under every animation) keeps that while it walks: its package states the adjustment (poseAdjust in its character.json) and the engine lays it on every take. Nothing for a game to do; a package without it is drawn exactly as before.

The two switches ​

Both go in src/game.ts. Off for the whole game:

ts
export default defineGame({
  features: { characters: { motion: false } },
});

Actions (hurdle, jump, vault) are off unless the game asks for them:

ts
export default defineGame({
  features: { characters: { motion: { actions: true } } },
});

Two ways to drive a character ​

A character is driven ONE of two ways. Pick one per character and do not mix them.

A. The take carries the character (the default). The game asks a velocity; the character travels at its take's own speed, and the game moves its walker by that speed.

  • A game on the SDK does nothing more than it always did: character.setState with the velocity it wants and physics.moveCharacter with the same velocity. The engine swaps in the take's speed.

  • A page that drives the bridge itself does that swap by hand, every step:

    ts
    characters.setState(rider, 'run', { x: vx, y: 0, z: vz }, true); // WORLD axes, metres a second
    const carried = characters.carriedVelocity?.(rider, out) === true; // out: [x, z]
    physics.moveCharacter(walker, carried ? [out[0], vy, out[1]] : [vx, vy, vz]);
    // then put the character's own object (its `parent`) where the walker is, facing as you like

    What carriedVelocity gives is the take's own travel. Where the walker could not go as far as it was carried (a slope, a step, a wall), the character is drawn back to it.

  • standing: 'set' (the character stands on the takes' own standing instead of its own stance): with it a standing character used to glide over the ground. The cause is cured by the numbers; it is to be seen cured in a game before the option is recommended.

  • stand (how a walk is stood on the floor: which height the hips are drawn at; no joint is touched). Left out, or 'middle': as always, by the middle of the joints of the feet the set marks down, which leaves the landing heel's tip under the floor through a heel strike. 'sole': on the character's own lowest sole point of those feet. 'bearing': on the lowest sole point, the toe's end too, of every foot that bears: from the frame a point of its sole is down to the frame its toes leave, whatever the set's marks say, so the body is held down over the rear foot while it rolls from its heel's lift onto its toes. Where the two feet do not agree about the floor, the floor goes from the rear toes to the front heel while both bear, and each foot keeps a share of the difference. Stated in the game's features, under characters, as motion: { stand: 'bearing' }, or by the page in the same words. Counted in simulation only. Not yet seen in a game: off until it is.

  • feet (how a move's ankle and toe turns are laid on a character's feet). Left out, or 'performed': as always, the performer's joint turns as they stand; a character whose foot joint rests turned otherwise than the performer's flat foot (made on a raised heel, or in a shoe) then walks with its sole tilted toes up on every frame, the ball off the floor and no heel-off. 'own': the same turns laid on the character's own stand's sole by one fixed turn a foot joint; the roll of the step, the toes' bend and where the feet point stay the move's. Stated like stand: motion: { feet: 'own' }. Walk and run takes only: actions, get-ups and moves from the seat play their feet as before. Not yet seen in a game: off until it is.

  • legs (how straight a leg the foot hold moves may be). Left out, or 'bent': as always, never over 0.995 of its length; a leg the move has straighter is bent a little as soon as the hold moves it, and the pelvis is lowered by what that takes: once a walking step, for the front leg just before its heel lands, the hips dip about 4 mm in four updates and come back in five. 'performed': where the move has a leg straighter than that, as straight as the move has it at that moment and no straighter, so the knee is bent no more than the move bends it and the pelvis is not lowered for it. A leg is never made longer than its bones. Stated like stand: motion: { legs: 'performed' }. Not yet seen in a game: off until it is.

  • What you get: the drawn body on its object within 0.09 m, feet that do not slide, and the performer's own starts, turns and stops. From standing to a run takes about 1.5 s to 3.3 m/s and 3 s to top speed; a quarter turn at a run drops to about 1 m/s for 1.25 s; a start right behind the character stands 0.75 s, then curves round. It is not the way for a dash to a spot a few metres behind.

  • Do not add your own velocity on top, and do not set carry: false.

B. The game owns the place and the facing; the system only poses the body.

ts
characters.setMotion?.(rider, { carry: false, naturalness: 0 }); // once, after the spawn
// every step: move and turn the character's own object (its `parent`) yourself, and say
// the velocity you move it at, in WORLD axes
characters.setState(rider, 'run', { x: vx, y: 0, z: vz }, true);

(on the SDK: character.motion(rider, { carry: false, naturalness: 0 }).)

  • carriedVelocity then answers false: the walker goes exactly as the game moves it.
  • naturalness is how far the drawn body may leave the game's place to move as its take does. At 5.2 m/s through starts, turns and a dead stop: 0 keeps the hips within 0.27 m (a few centimetres at a steady run); 0.1 within 0.57 m; the default 0.6 within 1.35 m. For this way use 0.
  • The body turns by its take, not with the game's facing: at a sharp turn or a start it faces up to 65 degrees behind the way it goes for under a second (naturalness: 0).
  • responsiveness (0 to 1, default 0.6) is how soon sharper takes are chosen for what is asked; it changes which take plays, never where the body is.
  • What it costs: where the game moves faster or sooner than the take does, the feet slide by the difference.

Both ways

  • The object you spawn the character under (parent) IS its place. position in spawn is a WORLD place, not an offset inside the parent: put the object where the character stands, and state that same place.

    ts
    group.position.set(x, 0, z);
    characters.spawn({ entity, bundle, parent: group, position: { x, y: 0, z }, rotation });

    A character stated anywhere else (the world's middle, meant as "the middle of the group"; or its place, with the group left at the world's middle) keeps that distance from its object for good and swings round it as the object turns. The console says so at the spawn.

  • A velocity is in world axes. { x: 0, y: 0, z: speed } is "north at that speed", not "ahead".

  • Who writes the facing: one hand a frame.

    • A walk to a spot, a turn on the spot, a performed get-up: the engine. moved gives the point and the facing; put the object there and write nothing else to it. A turn is stepped whole in one frame; the body is drawn turning by its take.
    • A velocity each step, way A: the game. Turn the object toward the way you ask, at once or at your own turning speed. Left where it was, the body is turned by its start and drawn back to the object's facing (measured: 104 degrees). Never in a frame in which moved gave a point.
    • A velocity each step, way B: the game, the place and the facing, every step.
  • Every frame, in this order: characters.stepWalks(dt, moved), then characters.update(dt). moved gives at most ONE point per character per frame, and only while the engine itself moves it (a walk to a spot, a turn on the spot, a performed get-up): put the character's object there. The rest of the time the object is yours.

  • A frame's length. Hand both calls the frame's real seconds. Under way A the walker goes at the last speed carried for the whole frame, so cap a long frame (the engine's own loop never steps more than 0.083 s).

  • A fall. Put the character's object under the body where it lies, then characters.recover: both may be done in the same step. While a performed get-up has the body, take moved's point for its object and do not move it yourself; a walk to a spot asked then is kept and begins the moment the body is up.

How fast the shared set runs. Its fastest performed run is 4.40 m/s, played up to 15 % faster and with no longer steps: 5.06 m/s at most (a walk: 0.68 to 1.75 m/s; a run: 2.11 to 5.06 m/s; a speed in between is given 1.75 m/s at a walk). A game that asks more is told once: motion-event, kind limited, name run, amount 5.06.

  • Under way A a character asked 5.2 m/s, or 8, goes at 5.06 m/s.
  • Under way B it goes as fast as the game moves it, the run played at 5.06 m/s under it: at 5.2 m/s the feet slide 3 %, which is not seen; at 7 m/s they slide 28 %, which is.
  • A sprint faster than 5 m/s that looks right needs sprint takes in the set.

With a sprint part in the set (takes the set keeps in a part named sprint: a fast run and a flat-out sprint, each with its start, and the sprint's stop) the character has a third gait. Nothing changes in the calls: pace and the velocity are still plain numbers. The run is then played at most 5 % faster than it was performed and ends at about 4.6 m/s; above that the sprint part answers: 5.2 m/s is the fast run at its own steps, 6.6 m/s the sprint, and from a stand the drive-off takes about 2.5 s to full speed. Over the fastest sprint (about 7.1 m/s) the game is told limited, name sprint. A sprinting character asked to stop takes the sprint's own stop, about 2.3 s and 3 to 4 m. A go-to (walkTo) at a sprint's pace sprints when there is room: measured on the shared set with the part (two characters, 5.2 m/s asked, 15 m): to a spot ahead, travelling after 0.9 s, 5.3 m/s at its fastest, its stop begun at 3.7 s, standing at 6.1 s, 11 to 13 cm from the spot; to a spot behind, the same after a quick turn, 2 to 8 cm. 8 m is done in 4.8 s, 20 m in 7.2 s, 30 m at 6.4 m/s in 8.1 s. It is stopped by the fast run's own stop or the sprint's skid, never by a run's or a walk's. A set without the part behaves exactly as described above (a pace above the run's goes at the run's top and says limited).

The calls ​

All of them go out with the frame's other commands. What happens comes back in ctx.events.

How one character is moved (off, or sharper, or not carried by its take):

ts
character.motion(hero, { responsiveness: 0.9 }); // 0 to 1, default 0.6
character.motion(guard, { on: false }); // this one by its clips
character.motion(boss, { carry: false }); // the game moves its walker itself

Send it to a spot: it turns, walks or runs there with the takes' own start and stop, and arrives. pace is metres a second; arrive: 'quick' picks the shortest stops and turns the set has:

ts
character.walkTo(rider, { x: 2, y: 0, z: -3 }); // the set's own walk
character.walkTo(rider, bikeSide, { pace: 1.2, arrive: 'quick' }); // at a pace, a short stop
character.walkTo(rider, bikeSide, { facing: Math.PI }); // arrive facing a way
character.walkTo(rider, bikeSide, { pace: 3.4 }); // a run's pace: it runs there

The pace decides the gait. Inside the speeds the set's walk covers (0.7 to 1.75 m/s on the shared set) it walks; above them it runs, kept to what the set's run covers (2.1 to 5.1 m/s); between the two it goes in the nearer. A run needs room to start and to stop (its stop may begin the moment it is up to speed): on the shared set a spot from 5 m away is run to at 3.4 m/s, 4 m at 3.2 m/s, 3 m at 2.4 m/s, and 1 m is walked. Whenever the speed it is given is not the pace asked, the game is told once per walk: motion-event kind limited, name the gait it goes in, amount the speed given. A set with no run walks at its walk's fastest and says limited.

Measured on the shared set, two characters, level floor, 3.4 m/s asked: 8 m in 5.0 s, landing 12 to 13 cm from the spot (to one side: the stop's own drift); 20 m in 8.2 s, 5 to 6 cm from it, at a real 3.37 m/s (184 steps a minute, 1.10 m a step, the strides at the performer's own rate); 10 to 15 m, 11 to 22 cm from it. The stop begins 2.0 to 2.8 m short of the spot. At a walk (1.2 m/s asked): 3 m in 4.2 to 4.6 s, 8 m in 8.2 to 8.8 s, 20 m in 18.7 s, 2 to 6 cm from the spot; the steady part is the walk a velocity gets (114 steps a minute, 0.60 to 0.62 m a step). A spot nearer than about 3 m is a few steps played as one take at the performer's own rate, its steps made up to a quarter longer or shorter to land. It does not pass the spot and come back; the body leans up to 12 cm past it as it stops and settles back over its feet.

A spot behind or beside it. A standing character sent to a spot off its facing turns as its set turns: by a quick turn on the spot, going as the last of it is made, or by a take that turns as it starts, whichever has it travelling sooner. Measured on the shared set (revision 6e, two characters, 5 m, 3.4 m/s asked): to a spot behind, travelling toward it 1.0 s after the ask and arrived at 4.3 s (27 to 29 cm from it); to a spot to its left, 0.7 s and 4.0 s (19 to 22 cm); to its right, 0.7 to 0.8 s and 4.2 to 4.4 s (5 to 10 cm). At a walk (1.2 m/s): 1.1 to 1.4 s and 6.4 to 6.8 s, 1 to 17 cm. The turning is the takes' own (173 of 180 degrees behind; the rest is the walk's steering as it moves off). A set may state its quick starts that turn (a take's turnStart); they are chosen by the angle asked, in a walk to a spot and under a velocity, only where the page turns it on (motion: { turnStarts: true }, off by default).

When it must be there now. arrive: 'quick' at a run takes the stop that has the body still soonest, and motion-event done named stop says that moment: 5 m straight ahead, stop begun at 1.7 s, still at 3.1 s, settled and arrived at 3.4 s; 4 m still at 2.1 s, 6 m at 2.7 s, 8 m at 3.2 s, 10 m at 3.9 s (the quick stop from a run ends with a settling step, which is why arrived can come up to 1.7 s after done). No take of the set runs 5 m from a stand to a stand (the shortest is 11.8 m), so a 5 m run is a move-off cut into a stop.

Out of a get-up. Ask the go-to with recover or any time after (kept until up). A run to a spot 5 m behind asked the moment a character is handed back standing: travelling toward it 1.0 s later, arrived 4.3 s later, 13 to 16 cm from it. Asked at 4 m/s with a quick arrival to a spot 4.5 m away, 34 to 180 degrees off its facing on either side (twenty get-ups, two characters): travelling toward it 0.6 to 1.25 s after recovered, arrived 3.5 to 5.4 s after (once 7.1 s), 11 to 42 cm from it. This is sooner than a speed asked each step: from a stand that travels the way asked after 0.4 s straight ahead, but 0.8 s to the left, 1.7 s to the right and 1.0 to 1.3 s at 40 degrees, because the set's move-offs that turn as they start are slow ones; a go-to turns first by a quick turn and runs off straight.

A character's own takes. A character's own part replaces the shared part of the same name: a package that brings its own run brings its stops too.

From a tap. In templates/visit, the rule tapSends: 'character' sends the character to a tapped spot by character.walkTo (templates/visit/src/sent.ts is the worked example).

Turn it on the spot (radians about up, 0 faces +z):

ts
character.face(rider, Math.PI / 2);
character.face(rider, 0, 'quick');
// `motion-event` kind `arrived`, name `face`, says when it faces there

Give up a walk (it stops as its takes stop, and says arrived where that leaves it):

ts
if (ctx.input.pressed('X')) {
  character.stopWalk(rider);
}

An action of its set, at an object when the action needs one (with actions on):

ts
const bar = { id: 7, position: barAt, yaw: 0, height: 0.6, width: 1.2, depth: 0.05 };
character.do(hero, 'hurdle', bar);
character.do(hero, 'jump');

Take an action back (not between its gathering and its landing):

ts
if (tooLate) {
  character.cancelAction(hero);
}

What comes back, the motion-event: kind is ready, arrived, limited (the speed asked is one the set does not cover: it moves at amount metres a second instead), an action's started / contact / release / landed / done, or failed with a reason a game can branch on. Something that cannot be done is always said, never silence.

A walk to a spot says three moments, in order: started named stop (its stop begins; amount is the metres still to the spot), done named stop (it no longer travels: under 10 cm a second for a tenth of a second; amount is the metres it is from the spot), then arrived named walk when it has settled (a quick stop from a run ends with a settling step, so arrived can come a second or more after done). The first two ride on kinds the contract already has; a later revision of the contract may give them a kind of their own.

ts
for (const event of ctx.events)
  if (event.tag === 'motion-event' && event.val.kind === 'arrived') mount(event.val.entity);
  else if (event.tag === 'motion-event' && event.val.kind === 'failed') retry(event.val.reason);

From a fall, to getting up, to walking ​

A fall is the character's physics body. With no more said, the rise is that body's own:

ts
character.hit(rider, { at: where, direction: travel, strength: 'big' }); // it falls
// `anim-event` on the clip `ragdoll`, name `fell`: it lies still. Move its entity to where it lies.
character.recover(rider); // it rises where its entity is, over about a second
// `anim-event` on the clip `ragdoll`, name `recovered`: now it can be sent somewhere
character.walkTo(rider, bikeSide, { arrive: 'quick' });

While the body is reacting or down, the takes leave it alone; they take it back when recovered comes. Ask for the walk after recovered (a performed get-up keeps one).

A performed get-up (the character getting to its feet as a performer did) is in this version, off by default. A game's page turns it on where it makes the bridge, in src/main.ts, by saying where the get-ups are:

ts
const FEATURES = clientFeatures({
  characters: { motion: { getUps: 'sets/getups.motion.bin' } },
});
  • The game's code does not change. character.recover on a character that is down plays the get-up where it lies, and the engine brings its entity there: with get-ups on, do not move the entity yourself.
  • What comes back: motion-event started and arrived, both named get-up (arrived carries point and facing: where it stands now, for the game's own record of its place), and the anim-event recovered once the body is up, before the last frame. A walk asked sooner is kept (getUps: { upAndRunning: false }: as before).
  • It needs a set that has get-ups. The shared set carries five from revision 6c on (from the back, the front, the right and the left side, and a quick one from the back, about 2.7 s), so getUps: true reads them from the shared set; or give the address of another set that has them.
  • Not every fall has one. A body no take lies like (propped up on an arm; further than half a metre from every take) is blended back as before, said once in the console. Floored again while it rises, it lets go and falls.
  • style: 'quick' plays the set's quick get-up where it fits the body, else the ordinary one. On revision 6c the quick one does not fit a body flat on its back (its lying frame was read tilted), so quick gets the ordinary get-up, about 2.7 s; the next revision's fits.
  • Measured on revision 6c: from the back 2.7 to 2.8 s from asked to standing, from the front 1.9 s, from a side 5.7 s; it stands 0.4 to 0.9 m from where the hips lay. Known faults: a hand can go 4 to 10 cm under the floor for a moment at the push-off from the front; while the body is handed back into a walk or a run a foot that is down can slide 20 to 45 cm.
  • A game's own features has no word for it yet: the page turns it on.

Seated or riding ​

A character sat on something (things.getOn(thing, entity) in a made world) is its seat's. The movement system leaves it alone until it gets off:

  • its takes write nothing and its feet are not held: the seated pose is exactly what it is with the system off;
  • no take carries its walker;
  • a walk under way when it sits down is given up (arrived says where it stopped), an action asked or playing is taken back (failed), and a get-up under way lets go;
  • character.walkTo, character.face and character.do asked while it sits come back as failed with the reason seated;
  • when it gets off (things.getOff(thing)), its takes take the body back by a blend from the pose it stands in, exactly as a character that never sat moves off. Getting off itself is a cut: there is no performed dismount;
  • one thing can be asked of it: a performed move from the seat, when the page has named a riding set (the next section).
ts
things.getOn(bike, rider); // seated: the movement system lets go
things.getOff(bike); // standing on its entity again
character.walkTo(rider, { x: 0, y: 0, z: 4 }); // fine again from here

A rider's pose on its machine ​

A seat pins the hips, the hands and the feet. Everything else the seated pose decides by itself, the same on both sides, as a direct function of the machine. A seat may say more (CharacterSeat, each part optional; with none given the pose is the same to the last bit as before):

GivenWhat it does
kneesWhere each knee rests on the machine's side (two objects on the machine). A knee the leg cannot bring there stays against that side.
poseOne reference pose: how THIS rider sits on THIS machine (SeatedReference).
posesSeveral poses mixed by the machine's lean (SeatedPoses): straight, left, right. Used in place of pose.
feelThe trunk and the head follow the machine's lean, bars and changes of speed by springs ({ mass }, kilograms: a heavier rider is slower).

poses may also carry upright (sitting up when slow) and brake (the pose under braking), and a seat may give keepOut (no part of the rider inside the machine): see below.

A reference pose is a small record of named amounts, each optional:

  • angles in degrees (within 60): hipsTurn, hipsTilt, chestTurn, chestTilt, lean (the back further forward than the least that reaches the grips), backRound, shoulderLeft/Right, elbowLeft/Right, wristLeft/Right, headTurn, headTilt, headNod, footLeft/Right (toes out), heelLeft/Right (heel up);
  • where the hips sit, in HUNDREDTHS OF THE RIDER'S OWN HEIGHT (so one record holds at any size): hipsBack along the saddle, hipsSide off its middle (to the left is positive), hipsDown;
  • ballLeft/Right, 0 to 100: the rest under the ball of the foot (100) and not under the arch (0), so that with a heel angle the foot stands on its ball;
  • ankleLeft/Right, 0 to 100: the foot follows its shin, so that seen from behind the knee, the ankle and the bottom of the foot lie on one line (measured on one rider: 9 degrees of sideways bend at the ankle without it, 0.0 with it);
  • armsStraight, 0 to 100: the reach to a grip uses up to 0.9975 of an arm, so the back stands as upright as the arms allow;
  • kneeLeft/Right: where the knee rests in THIS pose, metres in the seat's own frame (+x the rider's left, +y up, +z forward, from the seat spot). It is used in place of the seat's knees: closed on the tank in one pose, opened out in another.

A person writes one, or readSeatedReference measures the angles off a frame of a performed take (not the places, not how far the back leans). mirrorSeatedReference gives the same pose to the other side, as a start for that side's own record.

ts
import { mirrorSeatedReference, type SeatedPoses } from 'gameable/animation';

const left = {
  hipsSide: 7.5,
  chestTurn: 8,
  headTurn: 15,
  heelLeft: 38,
  ballLeft: 100,
  kneeLeft: [0.5, -0.2, 0.15] as const,
  kneeRight: [-0.23, -0.08, 0.27] as const,
};
const poses: SeatedPoses = {
  straight: {
    hipsBack: 7.5,
    backRound: 22,
    kneeLeft: [0.23, -0.08, 0.27],
    kneeRight: [-0.23, -0.08, 0.27],
  },
  left,
  right: mirrorSeatedReference(left),
  leanFull: 40,
};
characters.seat(rider, { seat, hands, feet, floor: bike, poses, feel: { mass: 58 } });
  • The mix. A turn's pose is in full once the machine leans leanFull degrees (35 unless stated) and beyond; between, every amount is mixed, smoothly, so a small lean on a straight moves next to nothing. The hips and the head are in full at firstShare (0.6) of that lean already: they go into a turn before the rest of the body.
  • With the feel the mix is followed by springs of its own: the hips and the head run lead seconds (0.15) ahead of a lean that grows, everything lags a lean that falls, and the body passes the pose it goes to by a little and settles. Without the feel the mix is a direct function of the lean.
  • Never off its spots. The hands and the feet stay on their spots whatever a pose asks. A pose a holding hand could not reach from (hips too far back or to a side) is taken back as far as needed: seated.kept is then under 1.
  • State a knee in every pose of a set, or in none: a knee's place is mixed only where both poses state it.
  • Measured (one game's rider and sport bike, the engine's riding page, 5 Oct 2026): a straight pose with the hips 10 cm back, the back 15 degrees from level, the knees on the tank and the heels up; a turn pose with the hips 10 cm to the inside; over 11 seconds of a left turn and a right turn of 40 degrees no hand or foot left its spot (0.00 mm), the hips were half way into the turn 0.12 s before the machine and half way out 0.2 s after it, and passed the saddle's middle by 10 mm before coming to rest.
  • What limits a pose is the rider against the machine, not the solver: an arm shorter than the reach to the outside grip stops the body going further inside a turn; foot rests wider than the hips make an opened knee rise and not drop; a shin lies back when the thigh must reach forward to a wide tank.
  • Upright when slow, lower with speed (poses.upright). The speed is read off the seat's own path. All of upright at speedUpright (0 m/s) and none at speedTuck (30 m/s) unless stated: a fifth of the way down at 30 km/h, six tenths at 60 and nine tenths at 90. A turn's pose is laid on top as its difference from the pose at speed: turnSlow (0.4) of it when slow, all of it at speed. With the feel the mix follows a spring (0.35 to 0.4 s behind the speed). A set without upright is unchanged.
  • Under braking (poses.brake). The braking is read off the seat's own path: not at all under brakeFrom (1.5 m/s2), in full from brakeFull (6 m/s2); a turn's pose stays laid on top, and with the feel a spring of its own follows the braking.
  • Never through the machine (keepOut: { frame, map, sides, body, clearance, field }). frame is the object the machine is drawn with. map is the machine's top as a grid of heights and sides how far it reaches to each side, both made from its own model by python packages/animation/tools/keepout_shape.py <thing.glb> <keepout.json>; without sides everything under the top counts as inside. body is the rider's body as balls on its joints, measured off its own package by python packages/animation/tools/measure_body.py <package> <body.json> --fine; without it, balls from the skeleton's proportions. clearance is the gap left, metres (0.01 unless stated). Then, whatever a pose or the feel asks: the trunk, the neck and the head come to rest on the shape; the back is raised at most to the least lean that lets the hands reach; a head inside is tipped back up, an elbow raised outward, a knee, thigh or shin moved outward until the leg lies against the side. Not held off, by construction: the hips, the first half of each thigh, the hands and the last quarter of each forearm, the boots and the last 15 % of each shin (they are on the seat, the grips and the rests).
  • What the pose says back: heldUp (how far the back is held up from the lean asked), keepGap (under 0 where a part is inside: nothing was left to give way) and gapAt(middle, radius) (any ball against the shape, for a caller that moves a limb itself). With field (the same shape as distances, made by python packages/animation/tools/keepout_field.py <keepout.json> <keepout.json>) the two gaps are true distances to the surface, always a number; without it they are without an end until a part is over the shape. The pose itself is the same with the field and without.
  • Measured with the limit (one rider on one sport bike, the engine's riding page; her body 116 balls): no part inside in any frame of a ride from standing to 126 km/h with a brake of 10 m/s2 (960 frames), nor of the turns at 60 and at 108 km/h with 40 degrees of lean (810 frames each); smallest gaps 0.1 to 0.3 cm. What is drawn outside her body's mesh (a dress's frills and skirt) is not held off: up to 7.7 cm in the tank at the belly. Cost: the trunk tried at up to about 25 leans a frame, each ball at 49 places (not profiled in a game).
  • Not built: cloth is not kept out of the machine; a limb that a move from the seat drives is not moved out of the machine by the pose (the caller asks gapAt); the seat spot's height is not found from the body; the bars' turn and the suspension's travel do not move the shape (it is made with the bars straight), nor does the bars' turn enter the mix; a pose read off a take gives a head nod measured against level, which the solver adds on top of its own tip past 55 degrees of lean (set the nod by hand there).

Moves from the seat ​

A rider can play a performed move from the seat (a kick, a punch, a grab, a throw, a reaction to a hit) as a layer over the riding pose. It is in this version, off by default, and for a game's page only (a compiled game has no command for it yet).

The performed takes do not exist yet. The engine's part is built and proven with stand-in takes cut from everyday takes; when the performed takes come they only need to be named in a set file.

A page turns it on where it makes the bridge, by saying where the seated takes are, and then asks for a move by name:

ts
const characters = createCharacterBridge({ engine, motion: { riding: 'sets/riding.motion.bin' } });
const answer = characters.seatedMove?.(rider, 'kick', { side: 'right', target: rivalBody });
if (answer && !answer.ok) console.log(answer.reason, answer.words);
  • What plays. One take, on the limb it was performed with: an arm (with its shoulder, hand and fingers) or a leg (with its foot). That limb leaves its grip or rest for the take and is eased back onto it when the take ends, wherever the grip has gone meanwhile (a handlebar that turned). The trunk and head take a share of what the take turns them (a half unless the take says), laid on the rider's own lean, so one take serves a rider bent low over one machine and upright on another. The other three limbs stay held to their spots and the hips stay on the seat.

  • The set is a file of its own. Its takes are in the part riding, each with its own seated block: limb (left-arm, right-arm, left-leg, right-leg), move (the name a game asks by), strikeFrame, releaseFrame (frames into the take), reachM and trunk. Never put that part in the set a character walks by: a take added there changes what its search chooses.

  • The side. A move performed on the right is stored also as its mirror, as another take; side picks between them. The engine does not mirror a take.

  • A target is an object with x, y, z in the world, read every frame: keep it and move it with what is struck. Around the take's strike frame the acting wrist or ankle is bent to it by a two-joint solve, in over 0.2 s before the strike and out over 0.25 s after. Only when the target lies within the take's reachM of where the take itself puts the limb; outside it the take plays as performed, and its contact says out-of-range. A limb is never made longer: a target beyond its length is reached for, and amount says how far short it fell.

  • What comes back, as motion records in clipEnds, named by the move:

    kindwhenwhat it carries
    startedthe move is takenlimb (0 left hand, 1 right hand, 2 left foot, 3 right foot)
    contactthe take's strike framepoint: the wrist or ankle; amount: metres from the target; reason: out-of-range or empty
    releasea throw's let-go framepoint and velocity of the wrist, what it rides on included: give them to the thing thrown
    donethe take's last framethe limb then settles onto its spot
    faileda move that had started was cut shortreason: replaced, cancelled (stopSeatedMove) or unseated
  • A request refused at once is the answer alone (no record): not-seated, not-available (the character's seated takes have not been read yet, or the set holds none it can play), unknown-move (no such move on that side; the sentence lists what the set has). A move asked while another plays replaces it: the limb is carried over, never cut.

  • Nothing changes without it. With no riding named nothing is read and the bridge has no seatedMove. With it named and no move asked, a rider is drawn the same to the last bit (300 frames, the bars turning).

  • Measured with the stand-ins (one character, a bench at a sport bike's seat, grips and rests, 60 frames a second): the three other limbs stay within 0.001 mm of their spots, also while the bars turn; a strike and a let-go are said on the drawn frame that reaches their frame of the take; a target 16 to 20 cm from where the take strikes is hit to under 0.001 mm; on a move's first frame no joint turns more than 1.6 degrees. The stand-ins end 24 to 65 cm from their spots and still moving: the limb is back within 2 cm after one second and within 1.5 mm after 1.5 s. A performed take that ends near its grip settles sooner.

  • For a fight between two machines. A rival's body is usually 0.9 to 2.3 m to the side: beyond a limb. Give as the target the point of the rival you want struck; when it is out of the take's reach the take plays as performed, and the game judges the hit from the contact's point, as it does today.

  • Not built: a command for a compiled game (the next number would be 36); a reaction to a hit chosen by the engine (the game asks for the reaction take itself, by the same call); a move for a character that is not seated; a thing held in the hand (the game's own, with attach).

  • A seated pose's own miss is the solver's: for the limb that acts it says how far the limb underneath is from its spot, not the limb drawn.

A page without the new graphics path, and phones ​

  • Without the new graphics path (a page on the older one) the movement is the same: it is bones, not drawing. Four characters were moved by their takes the same way there, at 0.26 ms a frame for all four on a desk.
  • Phones. No phone has been measured. With the browser's four-times slow-down on a loaded desk (which measured about ten times slower, so worse than a mid-range phone): one character 1.2 ms a frame for the movement and 0.6 ms for the feet; eight, 8.2 and 3.2 ms; one search 0.36 to 0.47 ms.

What it costs ​

  • The shared set is one file, packages/animation/assets/everyday-v1.motion.bin: 6.3 MB as stored, 1.95 MB as a compressing host sends it, for 7.5 minutes of motion (it will be rebuilt from the next revision). A newer set drops in by replacing that file, with no code change. Without the file every character moves exactly as before, with one line in the console.

  • First sight is not delayed. On a 40 Mbit/s line a character stood at 47.5 s with the system off and at 46.8 s with it on. Its takes took the body 4.3 s after it stood, with the file sent uncompressed by a development server (about 0.4 s of download when compressed). The longest gap between two frames while the set came was 40 ms: the set is read and its table built on a thread of its own.

  • Per frame, on a desk:

    CharactersMovementFeet
    10.12 ms0.06 ms
    40.33 ms0.16 ms
    80.63 ms0.32 ms

    One search is 0.07 ms; a character makes about ten a second, and they are spread over the frames.

Known faults ​

  • Level floors today. On a step or a slope the feet's hold reads wrong: at a step's edge the swinging foot goes through the step's top and the body lunges (hips 20 cm low), and on a slope the legs pop. Keep a character moved by the system on level ground, or switch the hold off there (footPlant: false).
  • The walk is not approved. An earlier walk was called robotic, and the walking takes are being replaced. Before this version a walk asked at 1.2 m/s came out at about 1.0 m/s and 104 steps a minute, because the stride was slowed. This version keeps a steady walk on one take going round, at the performer's own steps a minute; it has not been measured or judged on this page.
  • A walk to a spot lands 2 to 20 cm from it at a walk and 5 to 22 cm at a run straight ahead (a spot 0.4 m to one side of a 3 m way: 17 to 20 cm; 3 m walked at the walk's fastest because it is too near to run to: 22 to 26 cm, to one side); with a facing asked, the turn on the spot at the end holds its place as far as the feet's hold reaches (see the taps below). Three spots tapped 6.3 s apart: it stood 0.6 to 0.9 s after reaching each.
  • A run to a spot behind or beside it lands 5 to 29 cm from it over 5 m (the body goes with the last 20 degrees of its turn still to make, and a 5 m run leaves little way to steer), and its quick half turn still stands 0.3 s before it turns. At the very edges of what the run covers a stride is played up to 13 % slower or 11 % faster than performed (2.1 and 5.1 m/s on the shared set); a character whose own run takes carry no quick stop lands 12 to 61 cm from the spot.
  • A walk with no pace named goes at the set's main walking take's own pace (1.43 m/s on the shared set: 1.2 to 1.4 m/s for these two characters, 114 to 120 steps a minute); a way of 2 m or more is the walk itself, a shorter one a take of a few steps. 2 m takes 3.1 to 3.5 s, 3 m 3.9 to 4.5 s, 4 m 4.8 to 4.9 s; 1.5 m takes 2.6 s and can end 20 to 27 cm to one side.
  • Six taps on the floor, to arrive facing the visitor (the visit page's go-to; two characters, 1.17 m/s): standing turned to the visitor 5.0 to 10.5 s after the tap (1 m to 8 m away), 0 to 15 cm from the spot. The turn to face the visitor moves the game's place 2 to 16 cm (a quick half turn of the set travels up to 24 cm as performed; what the feet's hold cannot take stays), and the body goes up to 15 cm past the spot before it settles back over its feet.
  • A move of one metre to the side takes about 5 seconds: the set has forward steps and one back step, no side step, so it turns toward the spot, takes two steps and turns back.
  • A go-to to a near spot well off its facing (3 m away, 75 to 135 degrees off) turns on the spot first: 4.4 to 4.8 s, 4 to 13 cm from the spot (it no longer circles the spot); given while it walks, it stops first.
  • The walk and the run to a spot are measured on a level floor only.
  • A walk to a spot keeps the level the character stands on.
  • Actions are off by default. Hurdle and jump work; the vault reads as a crouch over the box; throw and tumble are designed only.
  • A performed get-up is off by default and needs a set with get-ups (the shared set carries five from revision 6c on: getUps: true); without one a body that has fallen is raised by the physics body's own rise.
  • On a headless server there are no takes.

For a racing and combat game, in order of worth ​

  1. Get-up after a fall: in, off by default: getUps: true on the page reads the five the shared set carries. Without it, the physics body's rise.
  2. Go to a spot, with natural starts, turns and stops: in, by walk and by run (character.walkTo, with pace and arrive: 'quick'): a pace above the walk's speeds runs there ({ pace: 3.4 }), when the spot is far enough to run to.
  3. The default walk and run under a stick: in, on by default, with the walk's faults above.
  4. The abilities (actions): in, off by default.
  5. A kick, a punch, a throw from the seat: the engine's part is in, off by default, for a page (motion.riding, seatedMove); proven with stand-in takes: the performed takes are not made yet.