Crypt How to Make a Dungeon Crawler (Browser Room Loop 2026)

By Arron R.11 min read
How to make a dungeon crawler in 2026: model a room graph with FOV and encounter tables, wire move-attack-loot in WizardGenie, then add Tileset Forge floors, Qu

Most searchers who type “how to make a dungeon crawler” want a room-based crawl they can finish in a weekend: enter a chamber, fight or loot, open a door, descend a floor, repeat until the boss room. A browser room loop is different from a full Diablo clone. A coding agent scaffolds the room graph, FOV, and move-attack-loot loop from one prompt, and AI generation covers floor tiles, party sprites, and delve audio. On desktop or web, that means WizardGenie for the crawl loop, Tileset Forge for stone floors and walls, Quick Sprites for the party and enemies, SFX Gen for hit and open cues, and optional Music Gen for a quiet delve bed. This guide is the honest end-to-end for how to make a dungeon crawler in 2026, as a room-graph build you can ship once.

How to make a dungeon crawler browser pipeline: model a room graph, wire move-attack-loot in WizardGenie, add Tileset Forge floors and Quick Sprites
The 2026 how to make a dungeon crawler recipe: model a room graph with FOV and encounters, wire move-attack-loot in WizardGenie, then add Tileset Forge floors, sprites, and delve audio.

What how to make a dungeon crawler actually means in 2026

The query “how to make a dungeon crawler” hides three intents. Some searchers want a sprawling open-world ARPG with skill trees, crafting, and always-online loot economies — that is a studio roadmap, not a weekend jam. A second intent is a full first-person blobber with automapping and multi-hour labyrinths — a serious content and UX problem. The third intent, and the one this guide targets, is a browser dungeon: a small graph of rooms, fog on unexplored doors, turn-based move and attack, loot chests, stairs between floors, and a clear win when the final room clears. That is a weekend build, it demos the Sorceress toolset, and it is the format most dungeon crawler tutorial and javascript dungeon crawl searchers actually want.

Keep dungeon crawler and roguelike straight so you don’t rebuild the wrong sibling. A dungeon crawler owns rooms, encounters, loot, and descend — the fantasy loop described in the Wikipedia dungeon crawl overview (verified 2026-08-21). A roguelike usually adds permadeath, seed-based runs, and meta progression between deaths — our how to make a roguelike guide owns that run-meta path. If you already shipped a broader quest loop, the how to make an RPG guide covers party stats and towns; this post owns the room-fight-loot-descend core instead. For map-authoring alone, the sibling dungeon map generator post pairs well once the combat loop is solid.

The dungeon crawler loop in one minute (enter room, fight or loot, descend)

Five moving parts, repeated until the final floor clears. First, enter — the party steps into a room; mark it explored and light its tiles. Second, explore — show fog on closed doors to neighbors; optional FOV dims tiles behind walls if you add it later. Third, fight or loot — resolve turn-based attacks against monsters, or open a chest and roll the room’s loot table. Fourth, open — spend a move to unlock an adjacent door and reveal the next room node. Fifth, descend — if the room has stairs and the floor is clear enough (or you allow early exits), load the next floor’s graph. That is the entire dungeon crawler loop. Procedural biomes, online co-op, and deep crafting trees are polish layered after one honest solo delve already feels sticky.

Dungeon crawler loop state machine diagram showing enter room, explore FOV, fight or loot, open door, and descend stairs
The dungeon crawler loop: enter a room, explore FOV, fight or loot, open a door, then descend stairs.

Pick your engine for how to make a dungeon crawler: tilemap, Phaser, or WizardGenie

Three good targets in 2026, each with a different trade-off. Vanilla JavaScript on a 2D canvas tilemap is the honest default and the pick this guide recommends for a first build. Draw floor and wall cells with fillRect or drawn tile images, map pointer and arrow keys to grid moves, keep rooms as a graph of nodes. Total code footprint for a working browser dungeon with FOV-lite, turn combat, loot, and stairs is under 600 lines. No engine to install, ships as a static HTML file, deploys anywhere. The MDN Canvas API docs (verified 2026-08-21) cover the draw surface; the MDN 2D collision detection guide covers hitboxes when you later add projectile traps.

A DOM grid of room cards becomes the right pick if you want accessibility first and art second — each room is a panel, doors are buttons, combat is a short list of actions. You trade atmospheric tile art for focus rings and screen-reader-friendly structure. Fine for a puzzle-forward room based rpg; heavier once you want torch flicker and sliding cameras.

Phaser 4.1.0 (verified 2026-08-21 on the official Phaser API documentation page) becomes the right pick if you want Scene lifecycle for title-play-win, Tilemap helpers, or tweens when a door opens. Phaser does not invent your room graph — you still need nodes, edges, encounter tables, and turn order. Use Phaser when motion polish is the product; use a bare canvas when the product is a procedural dungeon browser people can tap on a phone.

WizardGenie is not a separate rendering engine — it scaffolds whichever of the three you pick from a single natural-language prompt. WizardGenie ships as both a desktop app (Windows installer with auto-update, available to Early Access supporters and above) and a no-install web build. Its coding-model lineup covers Claude Opus 4.7, GPT-5.5, Gemini 3.1 Pro, DeepSeek V4 Pro, Kimi K2.5, Grok 4.2, and MiniMax M2.7 (verified 2026-08-21 in src/app/_home-v2/_data/tools.ts). For a dungeon crawl, any frontier model scaffolds the room graph, turn combat, and door FOV in one prompt. Pair a frontier planner with a budget executor like DeepSeek V4 Pro or Kimi K2.5 for the typing pass — the Dual-agent pattern lands most projects at roughly one-fifth the single-frontier cost.

Step 1 — model room graph, FOV, and encounter tables

Nothing else in the pipeline matters if rooms disconnect, or if fog reveals the whole map on load. Start with a small, testable model for a turn based dungeon:

const FLOOR = 0, WALL = 1, DOOR = 2, STAIRS = 3;

function makeRoom(id, kind = 'combat') {
  return {
    id,
    kind, // 'start' | 'combat' | 'loot' | 'boss' | 'exit'
    edges: [], // neighbor room ids
    explored: false,
    cleared: false,
    monsters: [],
    loot: null,
    lit: false,
  };
}

function link(a, b) {
  if (!a.edges.includes(b.id)) a.edges.push(b.id);
  if (!b.edges.includes(a.id)) b.edges.push(a.id);
}

function buildFloor(seed = 1) {
  const rooms = [
    makeRoom(0, 'start'),
    makeRoom(1, 'combat'),
    makeRoom(2, 'loot'),
    makeRoom(3, 'combat'),
    makeRoom(4, 'boss'),
    makeRoom(5, 'exit'),
  ];
  link(rooms[0], rooms[1]);
  link(rooms[1], rooms[2]);
  link(rooms[1], rooms[3]);
  link(rooms[3], rooms[4]);
  link(rooms[4], rooms[5]);
  const table = {
    combat: [{ id: 'rat', hp: 4, atk: 1, xp: 2 }, { id: 'goblin', hp: 8, atk: 2, xp: 5 }],
    boss: [{ id: 'ogre', hp: 24, atk: 4, xp: 30 }],
    loot: [{ id: 'potion', heal: 8 }, { id: 'sword', atkBonus: 1 }],
  };
  for (const room of rooms) {
    if (room.kind === 'combat' || room.kind === 'boss') {
      const pool = table[room.kind === 'boss' ? 'boss' : 'combat'];
      const pick = pool[(seed + room.id) % pool.length];
      room.monsters = [{ ...pick, hp: pick.hp }];
    }
    if (room.kind === 'loot' || room.kind === 'boss') {
      room.loot = table.loot[(seed + room.id) % table.loot.length];
    }
  }
  rooms[0].explored = true;
  rooms[0].lit = true;
  rooms[0].cleared = true;
  return { floor: 1, rooms, current: 0, party: { hp: 20, atk: 3, gold: 0 } };
}

function visibleDoors(state) {
  const room = state.rooms[state.current];
  return room.edges.map((id) => ({
    id,
    known: state.rooms[id].explored,
    label: state.rooms[id].explored ? state.rooms[id].kind : '???',
  }));
}

function enterRoom(state, nextId) {
  const from = state.rooms[state.current];
  if (!from.edges.includes(nextId)) return false;
  if (!from.cleared && from.monsters.some((m) => m.hp > 0)) return false;
  const room = state.rooms[nextId];
  state.current = nextId;
  room.explored = true;
  room.lit = true;
  return true;
}

Game state is { floor, rooms, current, party, turn }. Unit-test four asserts before you paint UI: start room is lit and cleared; enter through a non-edge fails; enter while living monsters remain fails; visibleDoors labels unexplored neighbors as ???. Those asserts are the difference between a dungeon crawler tutorial people trust and one that soft-locks on a dead-end door.

Keep infinite procedural sprawl, multiplayer fog sync, and per-tile shadowcasting out of v1 — they are schema variants on top of the same room graph. Cap the first floor at six rooms so a phone can redraw every turn and a first playthrough finishes in under fifteen minutes. Room-lit FOV (current room bright, unexplored doors fogged) is enough; classic recursive shadowcasting can wait until move-attack-loot already feels good.

Step 2 — wire move-attack-loot in WizardGenie

With the model solid, open WizardGenie. Drop in a bare index.html with a full-window canvas, a HUD for HP / gold / floor, and a door list. Give the agent one paragraph: Build a browser dungeon crawler. Use a room graph of six rooms with start, combat, loot, boss, and exit kinds. Current room is fully lit; unexplored neighbors show as ??? doors. Player moves with arrow keys inside a small 9×7 tile room; bumping a monster starts turn-based attack (player then monster). Clearing monsters marks the room cleared and unlocks doors. Chests apply loot once. Stairs on the exit room load floor 2 with a fresh graph. Draw with canvas fillRect and simple palette colors. Show win when floor 2 exit clears. Use canvas and keyboard. Feed that to any coding model and the scaffold lands in under five minutes.

The remaining afternoon is polish via follow-ups. Keep combat and door helpers thin and testable:

function attack(state, monsterIndex) {
  const room = state.rooms[state.current];
  const m = room.monsters[monsterIndex];
  if (!m || m.hp <= 0) return null;
  m.hp -= state.party.atk;
  let log = `You hit ${m.id} for ${state.party.atk}.`;
  if (m.hp <= 0) {
    m.hp = 0;
    state.party.gold += m.xp || 0;
    log += ` ${m.id} falls.`;
  } else {
    state.party.hp -= m.atk;
    log += ` ${m.id} hits back for ${m.atk}.`;
  }
  if (room.monsters.every((x) => x.hp <= 0)) {
    room.cleared = true;
    log += ' Room cleared.';
  }
  if (state.party.hp <= 0) log += ' You fall.';
  return log;
}

function openChest(state) {
  const room = state.rooms[state.current];
  if (!room.loot || room.loot.taken) return null;
  const item = room.loot;
  room.loot = { ...item, taken: true };
  if (item.heal) state.party.hp += item.heal;
  if (item.atkBonus) state.party.atk += item.atkBonus;
  return item;
}

function tryMove(state, dx, dy) {
  const room = state.rooms[state.current];
  const next = { x: state.party.x + dx, y: state.party.y + dy };
  if (next.x < 0 || next.y < 0 || next.x > 8 || next.y > 6) return 'bump-wall';
  const foe = room.monsters.findIndex(
    (m) => m.hp > 0 && m.x === next.x && m.y === next.y
  );
  if (foe >= 0) return attack(state, foe);
  state.party.x = next.x;
  state.party.y = next.y;
  return 'moved';
}

Wire movement with keydown for arrows and WASD so desktop and laptop share one path; add on-screen D-pad buttons for touch. Call door buttons only when room.cleared is true so players cannot skip a living combat room. Freeze input when party.hp <= 0 and show a Restart card. Persist the active run with localStorage if you want Refresh to resume mid-delve — serialize floor, room flags, and party stats, not the canvas bitmap. Keep monster AI trivial in v1: after the player acts, each living monster steps one tile toward the party or attacks if adjacent.

Step 3 — Tileset Forge floors, Quick Sprites party, SFX Gen hits, Music Gen delve bed

Solid-color cells prove the loop. Art and audio make the delve feel intentional. Open Tileset Forge and generate a top-down dungeon sheet — stone floor, cracked floor variant, wall edge, wall corner, door closed, door open, chest, stairs down. Align to a 32×32 grid and export a strip you can slice into your tile palette. Budget one Nano Banana Pro pass at 18 credits plus a retry if edges do not weld (verified 2026-08-21 in src/lib/models.ts) — roughly 36 credits for a clean floor pack.

Open Quick Sprites at 9 credits per generation (verified 2026-08-21 in src/app/quick-sprites/page.tsx) and make three packs: a hero, a rat or goblin, and a boss ogre. Keep silhouettes readable at 32×32 — busy detail loses to clear outline for a browser dungeon. Drop the PNGs onto your party and monster draw calls; do not regenerate mid-session unless a silhouette fails the glance test.

Open SFX Gen (1 credit per second of audio, verified 2026-08-21 in src/app/sfx-gen/page.tsx) and generate four short clips: sword hit, monster hurt, door open, chest open. Trigger hits inside attack, door open on successful enterRoom, and chest on openChest. Keep volumes moderate so a long delve does not fatigue.

Optional but nice: open Music Gen (10 credits per generation, verified 2026-08-21 in src/app/music-gen/page.tsx) and prompt a quiet delve bed — “low drone dungeon ambience, no vocals, slow pulse for turn-based exploration.” One or two tries is enough. Mute music by default so players who want silence stay in flow. Browse the rest of the stack from the tools guide if you later add speech barks or animated props. The asset stack for a weekend how to make a dungeon crawler project stays under a dollar of credits; see the cost section below for the line-item math.

Dungeon crawler asset stack diagram showing Tileset Forge floors, Quick Sprites party, SFX Gen hits, optional Music Gen bed, and total credit cost under one dollar
The dungeon asset stack: Tileset Forge for floors, Quick Sprites for party and enemies, SFX Gen for hits, optional Music Gen bed — roughly 89 credits on the 2026 Sorceress rate card.

What a how to make a dungeon crawler project costs on Sorceress in 2026

Here is an honest first-project budget against the live Sorceress rate card (verified 2026-08-21 against local source). One Tileset Forge dungeon sheet with a Nano Banana Pro retry at 18 credits each = 36 credits ($0.36). Three Quick Sprites packs at 9 credits each = 27 credits ($0.27). Four SFX clips totaling about 6 billable seconds at 1 credit/sec = 6 credits ($0.06). Optional Music Gen bed with a retry at 10 credits each = 20 credits ($0.20). Coding-model API time for the WizardGenie scaffold and polish pass is typically under $0.40 when you pair a frontier planner with DeepSeek V4 Pro or Kimi K2.5 as executor. Grand total: roughly 89 credits ($0.89) plus sub-dollar agent time. The free 100-credit signup grant (verified 2026-08-21 in src/app/api/admin/credits/route.ts) covers the entire art and audio stack on day one. Credit packs and supporter tiers live on Plans if you outgrow the grant or want a second biome tileset.

That is the whole pipeline for how to make a dungeon crawler in 2026: a room graph with FOV-lite and encounter tables, turn-based move-attack-loot, canvas doors and stairs, one Tileset Forge floor pack, and a thin Sorceress asset layer so the delve feels finished. Ship the static build, clear floor 1 without soft-locking on a door, then decide whether per-tile FOV, a third floor, or a full roguelike meta is worth another afternoon — only after the first room loop already feels sticky.

Frequently Asked Questions

How is a dungeon crawler different from a roguelike?

A dungeon crawler is the room-fight-loot-descend fantasy loop — fixed or lightly varied floors, clear encounters, and loot tables. A roguelike usually adds permadeath, procedural runs, and meta progression between deaths. You can ship a satisfying browser dungeon without a full run-meta layer. If you want permadeath and seed-based runs next, follow our how to make a roguelike guide after this room loop already feels sticky.

Do I need full field-of-view for a first crawl?

No. A room-lit model is enough for v1: the current room is fully visible, adjacent unexplored rooms stay fogged until you open a door. Classic shadowcasting FOV is a polish pass once move-attack-loot already works. Many great browser dungeon prototypes ship with room lighting first and never need per-tile FOV.

Should combat be turn-based or real-time?

For a weekend how to make a dungeon crawler project, turn-based is the honest default. Player move or attack, then each monster acts — no collision timing bugs, easy undo, and readable UI on a phone. Real-time action combat is a different product; keep it out of v1 unless that is the whole pitch.

How big should the first dungeon be?

Six to ten rooms across two floors is plenty. Graph connectivity (every room reachable, one stairs-down on floor 1, one exit on floor 2) matters more than raw room count. Cap the first map so a phone can redraw every turn and so a first playthrough finishes in under fifteen minutes.

How much does it cost to build a dungeon crawler on Sorceress?

A first-project browser room loop budgets like this against the 2026 Sorceress rate card (verified 2026-08-21 against local source). One Tileset Forge dungeon sheet with a Nano Banana Pro retry at 18 credits each = 36 credits or 0.36 USD. Three Quick Sprites party and enemy packs at 9 credits each = 27 credits or 0.27 USD. Four SFX clips totaling about 6 billable seconds at 1 credit per second = 6 credits or 0.06 USD. Optional Music Gen delve bed with a retry at 10 credits each = 20 credits or 0.20 USD. Total roughly 89 credits or 0.89 USD plus under 0.40 USD in coding-model API time. The free 100-credit signup grant covers the full stack.

Sources

  1. Wikipedia — Dungeon crawl
  2. MDN — Canvas API
  3. MDN — 2D collision detection
  4. Phaser 4.1.0 API Documentation
Written by Arron R.·2,474 words·11 min read

Related posts