NET FORGE DOCS

Kart racer template (TORQUEBAY)

Last updated Checked against @netforge/engine 0.2.0View as Markdown

Net Forge, the open-source multiplayer browser game engine built for AI coding agents, is published on npm under @netforge with source at github.com/netnetdev/net-forge.

TORQUEBAY is a complete online kart racer for up to eight players: hold the throttle, drift through bends to charge a mini-turbo, hit boost pads, collect coins that raise your top speed and keep off the grass. A round is one race of a few laps on one of three harbour circuits, and seat bots fill the grid so one person alone still has a field.

npm create netforge@latest my-game -- --template racer --yes
cd my-game
npm run play

--template kart works too. Keys: W or Up to accelerate, S or Down to brake, A D or arrows to steer, hold Space or Shift through a bend to drift and release for the boost, R or Enter to ready the next race.

What you get

PartWhat it doesWhere
Circuits1 to 8 tracks from a closed centreline of control points, with width, laps, boost pads and coin rowstracks in game({...})
Kart handlingTop speed, acceleration, turn rate, grip, drift grip, grass loss, boost strengthkart in game({...})
Drift mini-turboThree charge tiers (blue, orange, purple) for a 0.5, 0.9 or 1.4 s boostthe engine's kart mode
Laps and placesFour quarter checkpoints in order per lap, a race clock, places, resultsthe engine's race runner
Seat botsDrive the racing line, pass, hold drifts through long bends, shaded by skill, never earnplayers.bots
Streamed trackThe client builds road, kerbs, barriers and scenery in chunks near the camera onlythe template client
Netcode60 Hz kart physics on a 1/1024 grid; your kart is predicted; kart bumps run on the serverthe template package
Playtest botsFour drivers plus seat bots for four minutes: races finished, wall hits, earnnpm test

Measured on an Apple M2 Pro, Node 22: four playtest drivers plus seat bots over four minutes (14,400 ticks at 60 Hz) ran two full races, every driver finished both, nobody hit a wall hard, and the server tick stayed under 0.09 ms at p99.

1. Add a circuit

points is the closed centreline in driving order, in metres on the ground plane; a smooth curve runs through them. boosts and coins are [lap fraction 0..1, lateral -1..1].

src/game.ts
import { game } from "@netforge/engine";

const coinRow = (f: number, lateral: number, n: number, gap = 0.006): [number, number][] =>
  Array.from({ length: n }, (_, i) => [f + i * gap, lateral]);

export default game({
  template: "racer",
  style: "lowpoly",
  tickRate: 60,
  places: { harbour: { chunks: "places/harbour", spawn: [0, 0, 0] } },
  players: { prefab: "style.lowpoly.kart_a", max: 8, bots: 6 },
  round: { seconds: 240 },
  tracks: [
    {
      name: "Pier Sprint",
      laps: 3,
      width: 14,
      points: [[0, 0], [90, 0], [150, 15], [175, 65], [150, 120], [90, 135], [50, 175], [-20, 190], [-85, 160], [-110, 100], [-90, 35]],
      boosts: [[0.12, 0], [0.47, -0.4], [0.78, 0.4]],
      coins: [...coinRow(0.04, 0.5, 5), ...coinRow(0.3, -0.5, 5)],
    },
  ],
});

A track has 4 to 64 control points at least 6 m apart and is at least 200 m round. As a rule of thumb, 500 to 900 m a lap at 14 m wide runs 25 to 40 s a lap, a hairpin needs about 25 m of radius, and boosts belong on the exits of bends.

2. Tune the handling

Add kart: { topSpeed: 30, turn: 2.6, grip: 10, driftGrip: 1.5 } to game({...}). The ranges are topSpeed 10 to 45 m/s (default 26), accel 8 to 80, turn 1 to 4, grip 3 to 20, driftGrip 0.5 to 6, grass 0.2 to 1 and boostSpeed 1 to 1.8.

3. Reward a clean race

src/game.ts
import { earn, system } from "@netforge/engine";

system("clean_line", ({ on, emit }) => {
  const scrapes = new Map<number, number>();
  on("kart.bumped", (ids) => {
    for (const id of ids) scrapes.set(id, (scrapes.get(id) ?? 0) + 1);
  });
  on("player.finished", (ids) => {
    const clean = ids.filter((id) => (scrapes.get(id) ?? 0) === 0);
    if (clean.length > 0) emit("race.clean", clean);
  });
  on("run.started", (ids) => {
    for (const id of ids) scrapes.delete(id);
  });
});

earn.rule("clean_line", { when: "race.clean", n: 1, pay: 12, oncePer: "run" });

Other events include player.finished, race.won and race.podium (which count only with another person in the round), lap.completed, coin.collected, drift.boosted and drift.ultra.

4. Check it with bots

npm test

How it works

The simulation is @netforge/engine-sim's kart mode: arcade vehicle physics on a 1/1024 grid at 60 Hz. Each tick, velocity splits into forward and sideways parts; the engine pushes the forward part toward top speed, grip bleeds the sideways part (much less while drifting), and steering turns with speed. Your browser predicts your own kart; kart-to-kart bumps run only on the server and the next snapshot corrects them. The client streams the track in chunks of about 40 m within 170 m of the camera, so long circuits stay light. See Netcode and prediction.

The full guide is Build a multiplayer kart racer in the browser.

Alternatives

  • Babylon.js is a full 3D engine for the web with physics plugins and a node material editor. Pick it when you want to build your own vehicle physics and scene from engine primitives.
  • PlayCanvas is a WebGL and WebGPU engine with a hosted visual editor. Pick it when your team wants to build tracks and scenes in an editor.
  • Net Forge fits when you want an eight-player kart racer with drift, boosts, laps, prediction and bots already working, and circuits you declare as data.

FAQ

How does drifting work in the kart racer?

Hold Space or Shift while steering through a bend. The mini-turbo charges in three tiers (blue, orange, purple) and fires a 0.5, 0.9 or 1.4 s boost when you release.

Do karts collide with each other?

Yes, on the server. Your browser predicts your own kart alone, and the next snapshot corrects your position after a bump.

How many players can race?

Up to eight per room. Seat bots fill the grid up to players.bots (six in the template) and leave as people join.

Can I design my own track?

Yes. A track is a list of control points in metres plus width, laps, boost pads and coin rows. Add it to tracks; the room draws one circuit per round.

How are laps counted?

Through four quarter checkpoints in order. Skipping a checkpoint does not count the lap.