Skip to content

gamekit ​

Illustration: a forest workshop bench at night with gears, a small clockwork figure and wooden game pieces

gamekit gives a game its structure: entities and components, a world that runs your systems in phases, scenes, input actions, assets, saves, and tools for testing all of it without a window. It is a package written entirely in ThicketScript, with no native code, and it sits on top of willow.

You build the game. gamekit supplies small parts that each do one job and that you wire together yourself. There is no Game base class to inherit from and nothing runs until you call it.

A first taste ​

A world with one moving ball, stepped by the runtime's fixed tick:

ts
import { ComponentKey, Entity, PhaseSchedule, World } from "gamekit";

class Position {
    x: float;
    y: float;
    constructor(x: float, y: float) {
        this.x = x;
        this.y = y;
    }
}

class Velocity {
    dx: float;
    dy: float;
    constructor(dx: float, dy: float) {
        this.dx = dx;
        this.dy = dy;
    }
}

const POSITION: ComponentKey<Position> = new ComponentKey<Position>("position");
const VELOCITY: ComponentKey<Velocity> = new ComponentKey<Velocity>("velocity");

const world: World = new World();
world.registerStore(POSITION);
world.registerStore(VELOCITY);

const ball: Entity = world.createEntity();
world.put(ball, POSITION, new Position(0.0, 0.0));
world.put(ball, VELOCITY, new Velocity(60.0, 30.0));

const schedule: PhaseSchedule = new PhaseSchedule();
schedule.addPhase("simulate", [], true);
schedule.addSystem("simulate", (w: World, dt: float, tick: int): void => {
    w.query2(POSITION, VELOCITY).each((entity: Entity, p: Position, v: Velocity): void => {
        p.x += v.dx * dt;
        p.y += v.dy * dt;
    });
});

App.tps = 10.0;
App.onTick((): void => {
    schedule.run(world, App.tickDelta, App.tick);
    const p: Position = world.getRequired(ball, POSITION);
    console.log("tick " + App.tick + ": ball at " + p.x + ", " + p.y);
    if (App.tick >= 4) {
        App.quit();
    }
});
text
tick 0: ball at 6, 3
tick 1: ball at 12, 6
tick 2: ball at 18, 9
tick 3: ball at 24, 12
tick 4: ball at 30, 15

This is a console program: it needs no window, so it runs in a terminal and in tests. Getting started walks through it line by line and then puts it on screen.

What is in the box ​

gamekit is split into families. Use one, some or all of them.

FamilyWhat it gives youGuide
coreEntities and component keys, events and pipelines, attributes, state machines, effects, conditions, actions, interactions, definitions and prefabs, assets, gauges, weighted picks, 2D transforms and a spatial index.Entities
ecsA World with one store per component, queries, deferred commands, phase schedules and a ticker that steps the world on the runtime tick.World and systems
appScenes, a scene stack and a scene coordinator, screen layers, focus, and input actions with routing, recording and replay.Scenes, Input
saveCodecs, versioned save schemas with migrations, save slots with backups and autosaves, and a settings store.Saves
audioA music director that owns what is playing, on top of the core audio system.Utilities
willowBindings that draw your game records as willow nodes, and a pointer and key bridge.Drawing with willow
uiScene windows and screen windows on willowui.Windows
testingDeterministic clocks and schedulers, a fake asset loader, debug snapshots, scenarios and traces.Testing

Add it to a project ​

json5
{
    entry: "app.tks",
    systems: ["willow", "bitmap"],
    packages: { gamekit: "../gamekit-tks" },
}

packages points at the gamekit folder. You list the willow and bitmap systems yourself, because a package's systems are never inherited. gamekit brings willowui with it; list willowui yourself only when your own code imports it (see Windows with willowui). Add a window section when the game needs one; without it the program is a console app.

Most names come from the package root, import { World } from "gamekit";. The willow, ui and testing families import from their folders, for example import { SimulationClock } from "gamekit/src/testing";.

Where to go next ​

gamekit is at version 0.1.0-rc1, a release candidate, so its API can still change before its first release.