Add a locomotion state
Goal
A sixth state in the hero's state machine — a crouch on Ctrl that halves the walk speed — reported to the animator through character.setState and shown on the HUD, with the state machine still allocating nothing.
Files you will edit
src/systems/locomotion.tssrc/game.ts
Steps
Name it. The states are exported string constants, because they cross the wasm boundary as the
statefield ofset-character-stateand a rig will match on them. Insrc/systems/locomotion.ts:ts/** Moving low and slow. */ export const CROUCH = 'crouch';Read the key and pick the speed. Inside
locomotionSystem, beside the existingrunning:tsconst crouching = !frozen && ctx.input.isDown('Control'); const running = !frozen && !crouching && ctx.input.isDown('Shift'); const speed = crouching ? Number(ctx.rules.crouchSpeed ?? 1.5) : running ? runSpeed : walkSpeed;Nothing here allocates:
isDownis a shift and a mask over a preallocated bitset, and the speed is a number.Tell the character controller.
moveCharacteralready takes a crouch request; the host character controller is what decides what a crouch does to the capsule:tsctx.physics.moveCharacter(hero, vx, 0, vz, wantsJump, crouching);Put it in the state machine. The ternary chain is ordered by priority — in the air beats on the ground, and crouching beats running:
tslocomotionState.state = grounded ? planar < STILL_SPEED ? IDLE : crouching ? CROUCH : running ? RUN : WALK : wantsJump || vy > 0 ? JUMP : FALL;character.setState(hero, locomotionState.state, vx, vy, vz, grounded)at the bottom of the system already sends it, andsrc/hud.tsalready drawslocomotionState.statein thestaterow. Neither needs a change.Add the number. One line in the
rulesblock ofsrc/game.ts, so the speed is tunable without opening a system:tsrules: { walkSpeed: 3.2, runSpeed: 6, crouchSpeed: 1.5, },
Verify
sh
npm test -w templates/third-personAdd a case beside walks at the walk speed and runs at the run speed: hold Control, step five frames, and assert locomotionState.state is 'crouch' and locomotionState.speed is 1.5. In the browser, the HUD's state row follows what you are doing, and the end-to-end suite reads the same value back out of the host with adapter.animationOf(hero).state.
See also
- Build your first adventure — the state machine this extends
- Tune the follow camera — the other half of the same system
- Play an animation on a character — what the state will drive
- Animation — the locomotion blend behind the states