Phaser AE

Arena rooms

Free packv3.0.0-12DArcade

Seeded rooms for top-down action games: a walled grid with obstacles, a start, an exit and every open cell reachable. And the movement such rooms need, so enemies find their way round walls and the player slides along them.

This is a Free pack. Every phaser.io account can use it in their games.

Released October 19, 2026

Arena rooms: 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

arenaLayout

function arenaLayout(): Pack<{ arenaLayout: ArenaLayoutApi }>

The arena-layout pack: game.arenaLayout. Pure functions; no options.

Helpers

arenaField

function arenaField(a: ArenaLayout, goal: ArenaPoint): FlowGrid

The flow field towards a goal: every open cell knows the way, round the walls.

arenaSpawns

function arenaSpawns(a: ArenaLayout, count: number, seed: number, minDistance = 180): ArenaPoint[]

count open cells at least minDistance from the start, chosen and ordered by a stream seeded with seed.

arenaSteer

function arenaSteer(field: FlowGrid, p: ArenaPoint, cell = 40): ArenaPoint

The way to go from p on a flow field: towards the next cell's centre, so a round body clears corners.

arenaStyles

const arenaStyles: readonly ["pillars", "courtyards", "barricades", "ruins", "galleries"]

The obstacle styles.

circleFree

function circleFree(a: ArenaLayout, p: ArenaPoint, r = 12): boolean

True when a circle of radius r at p touches no wall and is inside the room.

generateArena

function generateArena(options: ArenaOptions = {}): ArenaLayout

Generate a room. Throws, with every fault, on options validateArena refuses. Every open cell is reachable from the start.

isBlocked

function isBlocked(a: ArenaLayout, col: number, row: number): boolean

True when the cell is a wall.

lineClear

function lineClear(a: ArenaLayout, x0: number, y0: number, x1: number, y1: number): boolean

True when the straight line between two points crosses no wall cell: an exact walk of every cell the line passes through, so sight and anything flying along the line agree.

moveInArena

function moveInArena(a: ArenaLayout, p: ArenaPoint, dx: number, dy: number, r = 12, corner = 0.5): void

Move a circle by (dx, dy), sliding along walls rather than stopping at them. Changes p in place. Moving straight at a wall's corner that it overlaps by no more than corner of its radius (0.5), it slips round the corner instead of stopping; 0 turns that off.

validateArena

function validateArena(options: ArenaOptions = {}): string[]

Check a room's options. Empty when one can be generated.

Types

ArenaLayout

interface ArenaLayout

A generated room.

  • seed: number — The seed the room was generated from (a whole number, 0 to 2^32 - 1).
  • style: ArenaStyle — The obstacle style used, whether chosen or picked by seed.
  • cols: number — Columns across the room, the wall border included.
  • rows: number — Rows down the room, the wall border included.
  • cell: number — Side of one square cell, in world units.
  • walls: ArenaRect[] — Every wall cell, the border included.
  • blocked: number[] — Wall cells by index (row * cols + col), sorted.
  • start: ArenaPoint — Where the player starts, in world units: the centre of a cell.
  • exit: ArenaPoint — Where the exit is, in world units: the centre of a cell.
  • open: ArenaPoint[] — Every open cell's centre, the border excluded.
  • route: ArenaPoint[] — A shortest route of cell centres from the start to the exit.

ArenaLayoutApi

interface ArenaLayoutApi

What the arena-layout pack adds to a game: game.arenaLayout.

  • generate: typeof generateArena — Generate a room.
  • validate: typeof validateArena — Check a room's options.
  • field: typeof arenaField — The flow field towards a goal.
  • steer: typeof arenaSteer — The way to go on a flow field.
  • free: typeof circleFree — A circle clear of the walls?
  • move: typeof moveInArena — Move a circle, sliding along walls.
  • spawns: typeof arenaSpawns — Spawn points away from the start.
  • styles: typeof arenaStyles — The obstacle styles.

ArenaOptions

interface ArenaOptions

How a room is generated.

  • seed?: number — The seed. Default 1.
  • cols?: ArenaRange — Columns, walls included. Default [12, 15].
  • rows?: ArenaRange — Rows, walls included. Default [16, 19].
  • cell?: number — A cell's size in world units. Default 40.
  • style?: ArenaStyle — The obstacle style. Default picked by seed.
  • obstacles?: ArenaRange — How many obstacles are tried (those that would cut the room off are left out). Default [9, 14].
  • start?: ArenaPlace — Where the player starts. Default 'bottom'.
  • exit?: ArenaPlace — Where the exit is. Default 'top', its column picked by seed.
  • clearance?: { start?: number; exit?: number } — Clear room kept round the start and the exit, in cells. Default 2.75 round the start, 2.25 round the exit.

ArenaPlace

type ArenaPlace = 'top' | 'bottom' | 'centre' | { col: number; row: number }

A place in the room: a side, the middle, or a cell.

ArenaPoint

interface ArenaPoint

A point, in world units.

  • x: number — Horizontal position in world units, 0 at the room's left edge.
  • y: number — Vertical position in world units, 0 at the room's top edge; grows downwards.

ArenaRange

type ArenaRange = number | [number, number]

A number, or [min, max] picked by seed.

ArenaRect

interface ArenaRect extends ArenaPoint

A wall cell's rectangle.

  • w: number — Width in world units; one cell.
  • h: number — Height in world units; one cell.

ArenaStyle

type ArenaStyle = typeof arenaStyles[number]

An obstacle style.