Phaser AE

Fog of war

Free packv3.0.0-32DLogic

Fog of war on a tile grid: lights that cast shadows off walls, a brightness for every cell, and a memory of where the player has been. Your game asks each cell whether it is unseen, explored or visible and draws it however it likes.

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

Released October 14, 2026 · updated October 19, 2026

Fog of war: 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.

What it does

You create a grid with game.fog.create, mark which cells block light, and add lights with a position and a radius. compute() runs recursive shadowcasting from every light, so a torch lights a room but not the corridor behind the door, and each cell gets a brightness between 0 and 1. Brightness fades towards the edge of a light by a falloff you choose.

With memory on, any cell that has ever been lit stays explored after the light moves on. That gives a map its three regions: black where nobody has been, dimmed where the player has been, and lit where they can see now. state(c, r) returns 'unseen', 'explored' or 'visible', and lightAt(c, r) gives an alpha for a dark overlay.

The same grid answers the questions game logic asks. canSee traces a line of sight between two cells within a range, which suits a guard spotting the player or a turret choosing a target. reveal marks an area explored without lighting it, and revealAll is the map item that uncovers the whole level.

Features

  • Shadowcast lights — any number of lights, each with a radius, an intensity and its own falloff if you want one.
  • Four falloffs — none, linear, smooth (the default) and quadratic.
  • Explored memory — cells remember being lit, and resetMemory forgets them for a new floor.
  • Line of sight — canSee between two cells through open cells, with an optional range.
  • Reveals — reveal around a point for a scroll or a flare, and revealAll for a full map.
  • Walls from your map — blockFrom reads a 2D array of your level, or set cells one at a time.
  • Headless and standalone — the FogGrid class is exported, so it runs without a game and in tests.

Good for

  • Roguelikes and dungeon crawlers, where the player sees only what their torch reaches and remembers the rest.
  • Turn-based tactics, where units have sight ranges and enemies hide behind walls.
  • Real-time strategy and base-builders with a fog that lifts as units explore.
  • Stealth on a grid, using canSee for guards and the fog for what the player knows.
  • Exploration puzzles where a map item or a flare uncovers part of the level.

Make it yours

The grid's size, its default falloff and whether it remembers explored cells are set when you create it. Each light can have its own radius, intensity and falloff, and you move a light by changing its col and row and calling compute() again. How the fog looks is entirely yours: black tiles, a soft alpha from lightAt, a dimmed tint for explored cells, or nothing at all for cells in view.

Two very different uses: a dungeon crawler with one smooth torch on the player, memory on and explored cells drawn at 60 per cent dark; and a tactics game with memory off and a flat none falloff on every unit, so the board shows only what the squad can see this turn.

A quick look

A grid with walls from the level and a torch that follows the player:

const f = game.fog.create({ cols: 40, rows: 30, falloff: 'smooth', memory: true });
f.blockFrom(mapRows, 1);                 // walls from a 2D array
const torch = f.addLight(5, 5, 6, { intensity: 1 });
torch.col = 6; f.compute();              // after anything moves
f.state(c, r);                           // 'unseen' | 'explored' | 'visible'
f.lightAt(c, r);                         // 0..1, an alpha for the dark overlay
f.canSee(c0, r0, c1, r1, 8);             // line of sight within 8 cells

Works with

  • tiles-2d — the tile map the fog covers.
  • grid-move — the units that walk the grid and carry the lights.
  • lighting-2d — coloured 2D lights; draw the fog layer above the lit layers so a torch does not shine through it.
  • visibility-2d — the choice for a continuous world rather than a tiled one.

Good to know

  • compute() recomputes every light, at a cost of lights times radius squared cells, so call it when something has moved rather than every frame of a still scene.
  • Overlapping lights take the brighter value, not the sum.
  • Everything outside the grid counts as opaque.
  • The grid has no world units of its own: cellAt takes the cell size and origin you give it.

More Logic packs

Show all →