Run a match with a game mode
Goal
Copy templates/blank. A deathmatch to 5 kills with a 3-minute limit, respawns after 2 seconds, and a scoreboard in the HUD. No match code of your own.
Files you will edit
src/game.tssrc/level.json
Steps
- Put a
GameModeand twoPlayerStarts insrc/level.json. The mode's props are the rules; every one has a default.
json
{
"format": 1,
"actors": [
{
"class": "GameMode",
"position": [0, 0, 0],
"props": { "scoreToWin": 5, "matchTime": 180, "respawnDelay": 2 }
},
{ "class": "PlayerStart", "position": [-6, 1, 0] },
{ "class": "PlayerStart", "position": [6, 1, 0], "yaw": 180 }
]
}- In
src/game.ts, spawn players at the starts, hurt withapplyDamage(the shooter's controller asinstigatorgets the kill), and showmatchSummary()in your HUD.
ts
import { applyDamage, defineGame, matchSummary, playerControllerOf, prefab } from 'gameable';
import type { GameContext } from 'gameable';
import level from './level.json';
const Hero = prefab({ name: 'hero', health: 100 });
/** Call from your weapon when a shot lands: the shooter's seat gets the kill. */
export function hit(ctx: GameContext, targetBody: number, shooterSeat: number): void {
applyDamage(ctx, targetBody, 25, { instigator: playerControllerOf(shooterSeat) ?? undefined });
}
export default defineGame({
level,
player: { prefab: Hero, spawn: 'playerStart' },
systems: [
(ctx) => {
ctx.hud.set({ match: matchSummary() });
},
],
});- To change one rule, derive a mode and use its class name in the level:
ts
import { defineGameMode, GameMode } from 'gameable';
defineGameMode('LastOneStanding', {
props: { ...GameMode.spec.props, respawnDelay: -1 },
onPlayerDied(self, victim, killer, ctx) {
// e.g. end when one seat is left: endMatch(ctx, [survivorSeat])
},
});Verify
matchSummary().state goes waitingToStart → inProgress → waitingPostMatch, and the winner's score reaches 5.