Add a checkpoint and kill zone
Goal
Copy templates/blank. Enter a checkpoint, then a kill box, and respawn at the checkpoint with velocity cleared. No custom respawn system is needed.
Files you will edit
src/game.tssrc/level.json
Steps
- Create
src/level.json. The checkpoint is a box with fixed [1,1,1] half extents; its root position and yaw are the respawn pose. The kill volume can have custom half extents.
json
{
"format": 1,
"actors": [
{ "class": "LevelSettings", "position": [0, 0, 0], "props": { "killHeight": -10 } },
{
"class": "PlayerStart",
"position": [0, 1.2, 0]
},
{
"class": "MeshActor",
"position": [0, -0.5, 0],
"props": {
"asset": "cube-muted",
"scale": [20, 1, 20],
"collision": "block",
"halfExtents": [10, 0.5, 10]
}
},
{
"class": "CheckpointVolume",
"name": "checkpoint",
"position": [0, 1.2, -3],
"yaw": 90,
"props": {
"order": 1,
"once": true
}
},
{
"class": "KillVolume",
"name": "pit",
"position": [0, 1.2, -7],
"props": {
"halfExtents": [2, 2, 0.5]
}
}
]
}- Replace
src/game.ts.player.spawn: 'playerStart'waits until level andinitactors exist before selecting a start.LevelSettings.killHeightadds a global fallback for falling off the floor; null = auto (50 m under the level), false = off.
ts
import {
defineGame,
prefab,
PlayerStart,
LevelSettings,
MeshActor,
validateLevel,
CheckpointVolume,
KillVolume,
type GameContext,
} from 'gameable';
import settings from '../settings.json';
import data from './level.json';
// Register the level's classes in the guest bundle.
void PlayerStart;
void LevelSettings;
void MeshActor;
void CheckpointVolume;
void KillVolume;
const Hero = prefab({
asset: 'cube-mint',
scale: [0.6, 1.8, 0.6],
body: { shape: 'capsule', dims: [0.4, 0.5], kind: 'character' },
});
function walk(ctx: GameContext): void {
const move = ctx.input.axis2('KeyA', 'KeyD', 'KeyS', 'KeyW');
ctx.physics.moveCharacter(ctx.player, move.x * 4, 0, -move.y * 4);
}
export default defineGame({
features: settings.features,
world: settings.world,
assets: ['cube-mint', 'cube-muted'],
level: validateLevel(data),
player: { prefab: Hero, spawn: 'playerStart', camera: 'thirdPerson' },
systems: [walk],
});- Add later CheckpointVolume entries with increasing
order. A lower order cannot replace a higher checkpoint.onceremembers use per seat. KillHeight respawns players; non-player actors entering its box requireoverlaps: trueand are destroyed with reasonkillHeight. The global height plane does not require that opt-in.
Verify
From the copied game root run npx tsc --noEmit -p tsconfig.json, then npm run build (in this checkout use npm run build -w templates/blank). Blank is a bundle template, with no dev-server script: open the resulting bundle in the common Gameable player used by your app (examples/play/README.md describes local hosting).
Check it: hold W to pass through the checkpoint at Z=-3, then enter the kill box at Z=-7. The player returns to [0,1.2,-3] before settling onto the floor. A snapshot/restore preserves that checkpoint. Reload and enter the kill box by going around the checkpoint: respawn uses PlayerStart instead.