What it does
generateArena builds a room from a seed. It sizes a walled grid, places obstacles in one of five styles, puts the
start and the exit at a side, the centre or a cell you name, and keeps a clear space round each. Any obstacle that
would cut an open cell off from the start is dropped, so the whole room is always connected, and the layout comes
with a shortest route from the start to the exit. Options it refuses produce every fault at once, and
validateArena lists them without throwing, which suits an editor or a settings screen.
The layout is plain data: the wall rectangles to draw, the blocked cells, the centre of every open cell, the start,
the exit and the route. The movement helpers work on it directly. arenaField builds a flow field towards a goal, so
every open cell knows the way round the walls, and arenaSteer gives a unit direction towards the next cell's centre,
so a round body clears corners instead of cutting them. A crowd of enemies can share one field.
moveInArena moves a circle and slides it along walls, slipping round a corner it only clips, as players expect,
rather than stopping dead. circleFree tests a circle against the walls, lineClear walks the cells a segment
crosses to say whether a shot gets through without cutting a corner, and arenaSpawns picks open cells a set
distance from the start in a seeded order.
Features
- Seeded rooms — any size from 7 by 8 cells up to 200 by 200, with the cell size in world units.
- Five obstacle styles — pillars, courtyards, barricades, ruins and galleries, picked by seed or by name.
- Always connected — obstacles that would isolate any open cell are left out, and a start-to-exit route is returned.
- Start and exit placement — top, bottom, centre or a cell, with adjustable clearance round each.
- Flow fields —
arenaFieldtowards any point, witharenaSteerfor bodies of real size. - Wall sliding —
moveInArenaslides along walls and slips round clipped corners. - Shot and body tests —
lineClearfor shots,circleFreefor bodies,isBlockedfor cells. - Spawn points —
arenaSpawnspicks seeded open cells away from the start. - Validation —
validateArenalists every fault in a set of options.
Good for
- Room-by-room action games in the style of Archero, with a door that leads to the next room.
- Twin-stick shooters, where crowds of enemies flow round obstacles towards the player.
- Survivor-style arenas, with spawn points kept away from where the player starts.
- Stealth levels, with walls to hide behind and line tests for sight and shots.
- Roguelite runs, where every room is new but reproducible from its seed.
Make it yours
generateArena takes the seed, the columns and rows as a number or a range, the cell size, the style, how many
obstacles to try, where the start and exit go, and how much clear space to keep round each. The movement helpers take
the body's radius and, for wall sliding, how much of a corner a body may clip and still slip round it.
Two materially different uses: a tight early room of 12 by 16 cells in the pillars style with a handful of obstacles, the start at the bottom and the exit at the top; and a large open arena of 40 by 40 cells in the ruins style, the player starting in the centre and spawn points picked far from them, for a survivors game.
A quick look
A seeded room, and enemies that flow towards the hero round its walls:
const room = generateArena({ seed: 12, style: 'ruins', start: 'bottom', exit: 'top' });
const toHero = arenaField(room, hero);
for (const e of enemies) {
const v = arenaSteer(toHero, e, room.cell);
moveInArena(room, e, v.x * e.speed * dt, v.y * e.speed * dt, e.radius);
}
Works with
nav— its flow field is whatarenaFieldbuilds; use it directly for a grid of your own.visibility-2d— for line of sight round walls.room-runandstealth— game rules that stand on these rooms.arena— for a playfield's edges and shape, such as wrapping or bouncing.tiles-2d— for tile maps you design yourself.
Good to know
- An obstacle that would cut the room in two is left out, so a room may hold fewer obstacles than asked.
- Rooms are grids, so walls are whole cells, and bodies are circles.
- A flow field is rebuilt by calling
arenaField; for a goal that moves every step, rebuild it a few times a second rather than every step. - The pack draws nothing; your game draws the walls from the layout.






