Phaser AE

Interaction rules

Pro packv3.0.0-02DArcade

One table of "what happens when X meets Y", instead of a collision callback per pair scattered through an update loop. Rules are registered for pairs of kinds, run once a frame over your actors, and read like the game's design.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 19, 2026

Interaction rules: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

interactionRules

function interactionRules(): Pack<{ interactionRules: InteractionRulesApi }>

The interaction-rules pack. Pure logic, so it needs no backend and runs headless.

Helpers

createInteractions

function createInteractions<E extends Kinded, C = void>(): Interactions<E, C>

Creates an empty Interactions table.

where

const where: { sameLane: (tol?: number) => (a: { lane?: number; }, b: { lane?: number; }) => boolean; samePlane: (tol?: number) => (a: { plane?: number; }, b: { plane?: number; }) => boolean; facing: (arc: number) => (a: XY & { rot?: number; }, b: XY) => boolean; notOwn: () => (a: { owner?: unknown; }, b: unknown) => boolean; }

Spatial constraints for a rule's when. Combine them with &&.

Classes

Interactions

class Interactions<E extends Kinded, C = void>

The rule table. Add rules with on, then call resolve or pair each frame.

  • on(from: string, to: string, rule: Rule<E, C>): this — Adds a rule for kind from meeting kind to. Returns this, for chaining.
  • rulesFor(from: string, to: string): Rule<E, C>[] — Rules registered for a pair of kinds.
  • resolve(actors: readonly E[], ctx: C): number — Test every ordered pair in one list and run what matches. Returns how many rules fired. An actor whose alive turns false mid-sweep is skipped for the rest of it, so a shot cannot kill two things at once by accident.
  • pair(from: readonly E[], to: readonly E[], ctx: C): number — Two separate lists — shots against rocks, without testing rocks on rocks.
  • fire(verb: string, a: E, b: E, ctx: C): boolean — Fire a NAMED verb at a target — drill, dock, capture, rescue, kick, tow. These are pressed, not collided with, so they never come out of the sweep. Returns true if a rule matched and ran.
  • target(verb: string, a: E, candidates: readonly E[], ctx: C): E | null — The best target for a verb, nearest first.

Types

InteractionRulesApi

type InteractionRulesApi = typeof kit

game.interactionRules — every function and type this pack carries, as one namespace.

Kinded

interface Kinded extends XY

The one thing an interaction needs to know about an actor.

  • kind: string — The actor's kind name — the key the rules match on.
  • radius?: number — Collision radius. The overlap distance is the two radii added.
  • alive?: boolean — Anything falsy here is skipped. Default: treated as alive.

Rule

interface Rule<E extends Kinded, C>

One rule in an Interactions table: when two kinds meet, what happens.

  • verb?: string — Named so a verb can pick it out; omit for a plain collision rule.
  • when?(a: E, b: E, ctx: C): boolean — Extra test beyond the overlap — same lane, same plane, line of sight.
  • radius?: number — Overlap distance. Default: the two actors' radius added.
  • anyRange?: boolean — Skip the distance test entirely (a verb that works at any range).
  • then(a: E, b: E, ctx: C): void — Runs when the rule matches.

XY

interface XY

A 2D point: the x and y position.

  • x: number — The x position.
  • y: number — The y position.