Gauges, picks and spatial helpers
Small helpers that many games need. Each one is independent; use whichever you like.
ts
import { Gauge, LinearSpatialIndex, Transform2D, WeightedPick } from "gamekit";
// Gauge: a value that fills with time you give it. Good for cooldowns and charge bars.
const dash: Gauge = new Gauge(1.0, 0.5); // capacity 1, fills 0.5 per second
const ready: boolean = dash.advance(2.0); // true when it reaches full
console.log("dash ready: " + ready);
dash.consume(1.0);
// WeightedPick: a weighted random choice from a seeded Random.
const loot: WeightedPick<string> = new WeightedPick<string>(new Random(42));
loot.add("coin", 80.0);
loot.add("gem", 19.0);
loot.add("crown", 1.0);
console.log("drop: " + loot.pick());
// Transform2D: plain position, rotation and scale data for simulation code.
const t: Transform2D = new Transform2D(Vec2{ x: 10.0, y: 20.0 });
t.rotation = 0.5;
console.log("at " + t.position.x + ", " + t.position.y);
// LinearSpatialIndex: find things by point, area or nearest.
const index: LinearSpatialIndex<string> = new LinearSpatialIndex<string>();
index.upsert("tree", Rect{ x: 0.0, y: 0.0, width: 10.0, height: 10.0 });
index.upsert("rock", Rect{ x: 50.0, y: 50.0, width: 5.0, height: 5.0 });
console.log("at (5, 5): " + index.point(Vec2{ x: 5.0, y: 5.0 }).join(", "));
console.log("nearest to (40, 40): " + (index.nearest(Vec2{ x: 40.0, y: 40.0 }) ?? "none"));text
dash ready: true
drop: coin
at 10, 20
at (5, 5): tree
nearest to (40, 40): rockGauge
A value between 0 and capacity that fills at rate per unit of time you pass to advance(dt). Use it for cooldowns, charge bars and stamina.
| Member | Meaning |
|---|---|
new Gauge(capacity, rate, start = 0) | Throws InvalidArgument if capacity is not above zero or rate is negative. |
advance(dt) | Fills and returns true when this call makes it full. Does nothing while paused. |
consume(amount), fill() | Spend some, or fill it at once. |
value, capacity, rate, paused | Plain fields. |
Because time is passed in, a crossing happens on the same tick in every run. The cooldown recipe uses one in a system.
WeightedPick
new WeightedPick<T>(random) picks items with probability proportional to their weight, from the seeded core Random you give it. fork(name) copies the entries onto a new picker that draws from random.fork(name); later add calls on either one do not affect the other.
Transform2D and the spatial index
Transform2D(position, rotation, scale)is plain simulation data. It never touches a willow node; copy it onto the screen in your presentation code.LinearSpatialIndex<T>implementsISpatialIndex<T>:upsert(value, rect),remove,point,area,nearest(point, maxDistance?)andswept(rect, delta). It checks every entry, which is fine for small sets; implementISpatialIndexfor a grid or tree when you have many.
Music
The audio family's MusicDirector owns what music is playing. play(track) changes it (and skips a change to the track already playing), push(track) plays one on top and pop() returns to the one below, with a crossfade of the length you choose. It talks to sound through an IMusicBackend, so tests can pass a fake. In a game, forward to the core Audio system:
ts
import { Audio, MusicTrack } from "audio";
import { IMusicBackend, MusicDirector } from "gamekit";
// Forwards to the core Audio system.
class CoreMusic implements IMusicBackend {
async loadMusic(trackId: string): Promise<any> { return await Audio.loadMusic(trackId); }
playMusicHandle(handle: any, volume: float, loop: boolean): void { Audio.playMusicHandle(handle as MusicTrack, volume, loop); }
crossfadeTo(handle: any, durationMs: int, volume: float, loop: boolean): void { Audio.crossfadeTo(handle as MusicTrack, durationMs, volume, loop); }
unloadMusic(handle: any): void { Audio.unloadMusic(handle as MusicTrack); }
}
const music: MusicDirector = new MusicDirector(new CoreMusic(), 800);
async function main(): Promise<void> {
await music.play("music/town.ogg");
await music.push("music/battle.ogg"); // town is kept underneath
await music.pop(); // crossfades back to town
}
await main();The project lists the audio system: systems: ["willow", "bitmap", "audio"].
Reference: Gauge, WeightedPick, Transform2D, LinearSpatialIndex, MusicDirector.