The pack
color
function color(): Pack<{ color: ColorApi }>
The color pack: puts colorApi on game.color. No columns, steps, hooks or options; requires nothing.
Helpers
contrast
function contrast(a: Hex, b: Hex): number
The WCAG contrast ratio between two colours, 1 (identical) to 21 (black on white). Order does not matter. WCAG asks 4.5 for body text and 3 for large or bold text; below 3 nothing is comfortably readable. Alpha is ignored — contrast is a question about what is actually painted.
gradient
function gradient(from: Hex, to: Hex, count: number): Hex[]
count RGB stops inclusive from from to to; one stop returns from.
hsv
function hsv(h: number, s = 1, v = 1): Hex
Hue in degrees (wraps), saturation and value in 0..1 (clamped; default 1) → #rrggbb.
lerp
function lerp(a: Hex, b: Hex, t: number): Hex
RGB blend from a to b at t (clamped to 0..1). Alpha is dropped. Throws on a malformed hex.
luminance
function luminance(hex: Hex): number
WCAG relative luminance, 0 (black) to 1 (white). Not the v of HSV and not the average of the channels:
the channels are gamma-decoded and then weighted the way an eye weights them, so pure green reads as far
brighter than pure blue. This is the number every legibility question actually turns on.
rainbow
function rainbow(count: number, opts: ColorOptions = {}): Hex[]
count evenly spaced hues that loop seamlessly (the last is one step short of the first).
ramp
function ramp(fromHue: number, toHue: number, count: number, opts: ColorOptions = {}): Hex[]
count hues spread inclusively from fromHue to toHue (degrees).
readableOn
function readableOn(background: Hex, candidates: ReadonlyArray<Hex> = ['#000000', '#ffffff']): Hex
The ink to write on background: whichever candidate contrasts with it most. Defaults to black or white,
which is the choice a label on a coloured chip, tile, badge or bar is really making.
Picking this by eye is how a palette ends up with one unreadable tile in it. Pale tints need dark ink and
saturated ones need light, the crossover is not where a v > 0.5 guess puts it, and the failure only ever
shows on the one value nobody screenshotted.
const ink = game.color.readableOn(tileTint); // '#000000' or '#ffffff'
const ink = game.color.readableOn(tileTint, ['#776e65', '#fffaf2']); // a warm pair, still chosen for you
wheel
function wheel(opts: ColorOptions = {}): Wheel
A Wheel at the given saturation and value (both default 1).
Functions
brighten
function brighten(hex: Hex, amount: number): Hex
Add amount (−1..1) to the value channel, clamped; negative darkens.
lifeRamp
function lifeRamp(ramp: RampName | ReadonlyArray<Hex>): ReadonlyArray<Hex>
A named life ramp's stops, or a custom list passed straight through, so code can take either. Throws on an unknown name.
pack
function pack(hex: Hex): number
Pack to the roster's 0xRRGGBBAA.
parse
function parse(hex: Hex): [number, number, number, number]
#rgb, #rrggbb or #rrggbbaa → [r, g, b, a] in 0..1. A malformed string is a loud error (a silent white hides a typo forever).
rampAt
function rampAt(r: Float32Array, t: number, out: Float32Array, o: number): void
Sample a baked ramp at t into out[o..o+2].
It lives here, beside RAMPS, because BOTH particle systems need it and a ramp sampled two
slightly different ways is a 2D effect and its 3D twin that do not match.
rgb
function rgb(r: number, g: number, b: number, a?: number): Hex
Components in 0..1 (clamped) → #rrggbb, or #rrggbbaa when a is given.
sample
function sample(stops: ReadonlyArray<Hex>, t: number): Hex
A multi-stop gradient sampled at t.
shift
function shift(hex: Hex, degrees: number): Hex
Rotate the hue by degrees, keeping saturation and value.
toHsv
function toHsv(hex: Hex): { h: number; s: number; v: number }
A hex colour → { h, s, v } with h in 0..360 and s, v in 0..1. Throws on a malformed hex.
withAlpha
function withAlpha(hex: Hex, alpha: number): Hex
The same colour with an alpha byte from alpha in 0..1 → #rrggbbaa.
Constants
colorApi
const colorApi: ColorApi
The single ColorApi instance; color() attaches this same object.
RAMPS
const RAMPS: Record<RampName, ReadonlyArray<Hex>>
The named life ramps: head is birth, the last stop is death.
SAMPLES
const SAMPLES: 64
Steps in a baked ramp: a table holds SAMPLES + 1 RGB entries, which rampAt reads.
Types
ColorApi
interface ColorApi
What game.color presents: every exported function of this module, by the same name.
parse: typeof parse— Hex →[r, g, b, a]in 0..1; throws on a malformed string.rgb: typeof rgb— Components 0..1 → hex.hsv: typeof hsv— Hue, saturation, value → hex.toHsv: typeof toHsv— Hex →{ h, s, v }.lerp: typeof lerp— RGB blend att.shift: typeof shift— Rotate hue by degrees.withAlpha: typeof withAlpha— Attach an alpha byte.brighten: typeof brighten— Add to the value channel.wheel: typeof wheel— A hue wheel at fixed S and V.rainbow: typeof rainbow— Evenly spaced hues that loop.ramp: typeof ramp— Hues inclusive between two angles.gradient: typeof gradient— RGB stops inclusive between two hexes.RAMPS: typeof RAMPS— The eight named life ramps, birth to death.lifeRamp: typeof lifeRamp— A named life ramp's stops, or a custom list passed through.sample: typeof sample— A multi-stop gradient att.pack: typeof pack— Hex → the roster's 0xRRGGBBAA.luminance: typeof luminance— WCAG relative luminance, 0..1 — gamma-decoded and eye-weighted, not HSV'sv.contrast: typeof contrast— The WCAG contrast ratio between two colours, 1..21.readableOn: typeof readableOn— The candidate ink that contrasts with a background most; black or white by default.
ColorOptions
interface ColorOptions
Saturation and value for the palette builders (wheel, rainbow, ramp).
saturation?: number— 0..1; default 1 (fully saturated).value?: number— 0..1; default 1 (full brightness).
Hex
type Hex = string
A hex colour string: #rgb, #rgba, #rrggbb or #rrggbbaa. The form a handle's tint takes.
RampName
type RampName = 'fire' | 'spark' | 'ember' | 'smoke' | 'ice' | 'magic' | 'toxic' | 'rainbow'
The eight named LIFE RAMPS — the colours a particle walks from birth to death.
They are here rather than in a particle pack because a ramp is a colour vocabulary, not a particle
feature: the same eight name a trail's gradient, a beam, a light that cools, a bar that heats. All but
rainbow run BRIGHT to DARK, which is what makes a burst read as energy leaving rather than arriving.
Wheel
interface Wheel
A hue wheel at fixed saturation and value, from wheel().
hue(deg: number): Hex— The colour at a hue in degrees (wraps).at(t: number): Hex— The colour attin 0..1 around the wheel (t · 360degrees).colors(count: number, t0?: number, t1?: number): Hex[]—countcolours spread inclusively fromt0(default 0) tot1(default 1) around the wheel.


