ASCII dungeon raycaster. Navigate procedurally generated dungeons in first-person perspective, rendered entirely in colored ASCII characters. Find the exit (◊) to advance to the next level; collect health (♦) and treasure items; fight enemies (☠); survive.
╭────────────────────────────────────────╮
│ ▓▓▓ VOIDWALKER ▓▓▓ │
│ ASCII Raycaster Dungeon │
│ │
│ ████ wall ◊ exit │
│ ♦ health ☠ enemy │
│ ░ floor · ceiling │
│ │
│ 160×50 character resolution │
│ 160 rays · fish-eye correction │
│ Sprite rendering (items, enemies) │
│ Procedural dungeon generation │
╰────────────────────────────────────────╯
- Raycasting renderer — 160 rays, fish-eye correction via
dist * cos(deltaAngle), wall height derived from perpendicular distance; shade index by distance (9 depth steps from#e8e8e8to#0a0a0a) - Procedural dungeon generation — binary space partitioning for room placement; L-shaped corridors connecting room centers; 6–11 rooms per dungeon
- Sprite system — items (♦ health, ♦ treasure), enemies (☠), exit (◊) rendered via raycasting with z-buffer occlusion check
- Enemy AI — enemies track player within 10 units, move toward player every 0.8–1.3s, deal 1 damage on contact (player respawns at 0 HP)
- Minimap —
Mkey toggles 2px-per-cell ASCII minimap in top-left; player shown as cyan@, exit as green◊ - Progressive difficulty — each level increases dungeon size by +4 width / +3 height; enemies scale with level
- 9-level lighting — WALL_LIGHTS array maps distance to color index; ceiling/floor use 4-step gradient
- CRT flicker — CSS animation
opacity: 0.95–1.0at 100ms gives authentic retro feel
| Key | Action |
|---|---|
W / A / S / D |
Move forward/back/strafe |
Q / E |
Turn left/right |
F |
Interact (collect item / attack enemy in range) |
M |
Toggle minimap |
Tab |
Generate new dungeon (next level) |
- Single HTML file — Canvas-free, pure DOM text rendering
- No libraries — vanilla JS, no build step, no dependencies
- Raycasting — DDA (digital differential analyzer) algorithm for wall detection;
MAX_DEPTH = 20, step size0.02 - Collision — slide collision against walls via axis-separated movement checks
generateDungeon(w, h)
└─ Fill map with 1s (walls)
└─ Place numRooms (6–11) random non-overlapping rectangles
└─ Carve rooms to 0 (floor)
└─ Connect room centers with L-shaped corridors
└─ Place player in first room center
└─ Place exit in last room center
└─ Scatter items (health, treasure) in intermediate rooms
└─ Scatter enemies in rooms after the second
castRay(angle)
└─ Step along ray at t=0.01 increments
└─ Check map cell; return { dist, cell, mx, my }
└─ Fish-eye corrected: adjDist = dist * cos(rayAngle - playerAngle)
render()
└─ Ceiling gradient (0–halfH, 4 shade levels)
└─ Floor gradient (halfH–H, 4 shade levels)
└─ For each ray: compute wall strip, shade by distance
└─ Render sprites (items, enemies) with z-buffer occlusion
└─ Build HTML string → innerHTML (flicker animation via CSS)
MIT