46dc9f2fad25df30cd293c9c17c3483b8bf8c5d0
Dungeon Crawl — Ranged / Melee
A dark fantasy dungeon crawler inspired by The Binding of Isaac. Built with TypeScript and Canvas 2D, bundled with Bun.
Quick Start
bun install # install deps (none currently required)
bun start # production build → dist/
open dist/index.html
Or for development with live reload:
bun run dev # starts dev server at http://localhost:3000 + watch mode
Controls
| Key | Action |
|---|---|
| WASD | Move |
| Arrow keys | Attack in direction |
| Space | Attack in facing direction |
| Tab / Q | Switch weapon (Ranged ↔ Melee) |
| R | Restart (on Game Over / Victory) |
Weapons
| Mode | Weapon | Speed | Damage | Effect |
|---|---|---|---|---|
| Ranged | Pistol | Fast (10cd) | 1 per shot | Ranged projectiles |
| Melee | Knife | Slow (22cd) | 2 + knockback | Wide swing arc |
Room Types
| Type | Description |
|---|---|
| Spawn | Starting room, no enemies |
| Normal | 2–4 enemies |
| Treasure | No enemies, loot room |
| Boss | 1 boss enemy, clearing wins the game |
Project Structure
src/
├── main.ts Entry point
├── constants.ts Grid, canvas, tile/door constants
├── types.ts Shared TypeScript types
├── math.ts Utility: shuffle, rand, dist, overlap
├── input.ts Keyboard state (global KEYS map)
├── doors.ts Door geometry helpers
├── room/
│ ├── Room.ts Room class (tiles, enemies, tears)
│ ├── RoomMap.ts Map generation (connected 7×7 grid)
│ └── tiles.ts Tile builders (wall/floor/door placement)
├── entities/
│ ├── Player.ts Player stat block
│ ├── Enemy.ts Enemy stat block + enemy type logic
│ ├── Tear.ts Ranged projectile
│ └── MeleeSwing.ts Melee hitbox
├── game/
│ ├── Game.ts Main orchestrator (loop, tick, render)
│ ├── collision.ts Wall collision (isBlocked, collidesWall)
│ ├── transitions.ts Room transition detection
│ └── spawner.ts Enemy placement logic
└── render/
├── roomRenderer.ts Tile rendering
├── entityRenderer.ts Player, enemy, tear, melee drawing
├── hudRenderer.ts HP bar, mode indicator, HUD
└── minimapRenderer.ts Minimap drawing
Build System
- Bun — runtime + bundler
bun build— bundlessrc/main.ts→dist/main.jsbuild.ts— production build with minification + HTML copy- No external libraries required (pure Canvas 2D)
Architecture
- Game owns the game loop (
requestAnimationFrame), the world (RoomMap,Player), and dispatches to render functions. - Tick processes input → movement → attack → enemy AI → room clear check → transitions → win condition.
- Transitions check player tile position + keypress against door
geometry; call
Game.enterRoom()which resets room state. - Collision allows bounding-box overlap at door openings (row/col outside normal bounds).
- Rendering is split into 4 pure functions that receive
ctx+ data.
Languages
TypeScript
60.9%
HTML
39.1%