- Isometric canvas renderer (depth-sorted, FOV/fog, additive lighting) - 3 classes x 20 skills, 4 acts x 4 floors + boss lairs, torment I-X - Diablo-style loot: rarities, affix tiers, 14 legendaries, vendor, stash - Rogue camp with 6 NPCs: Charsi/Akara/Kashya/Cain/Gheed/storage - NPC quest chain (accept -> hunt -> turn in) with rewards & gating - Procedural WebAudio SFX + generative music, EN/VI localization - Saves, settings, waypoints, hardcore mode, PWA manifest - 93-assertion headless suite + browser E2E via CDP
132 lines
5.5 KiB
Markdown
132 lines
5.5 KiB
Markdown
# Diablo2D — Shadows of Tristram
|
||
|
||
A dark, isometric **action-RPG that runs entirely in your browser** — no build step,
|
||
no server, no assets to download. Every tile, creature, spell effect, sound and
|
||
music track is generated procedurally in code. Inspired by classic Diablo and
|
||
modern browser ARPGs like Sephiria.
|
||
|
||
  
|
||
|
||
---
|
||
|
||
## Play
|
||
|
||
**Instant:** serve the folder with any static file server and open it.
|
||
|
||
```bash
|
||
cd diablo2d
|
||
python3 -m http.server 8080 # or: node server.js 8080
|
||
# open http://localhost:8080
|
||
```
|
||
|
||
It also runs straight from `file://` (double-click `index.html`) and can be
|
||
zipped as-is for **itch.io** (see *Publishing* below).
|
||
|
||
> Progress autosaves to `localStorage` every 90 seconds, on floor change,
|
||
> and when the tab closes. Export/import your hero as a code from Settings.
|
||
|
||
## Features
|
||
|
||
- **3 classes** — Crusader, Ranger, Sorceress — 20 hand-tuned skills across
|
||
3 talent branches each (actives + passives, 6-slot action bar).
|
||
- **4 acts × 4 floors** of procedurally generated dungeons:
|
||
room-and-corridor crypts, cellular cave systems, and a boss lair per act
|
||
(The Flesh Butcher, The Bone King, Aranea the Spider Queen, Malgor the
|
||
Lord of Terror) with multi-phase scripted attacks.
|
||
- **Diablo-style loot**: 40+ item bases, 4 rarities, ~30 affixes with
|
||
item-level tiers, 14 build-defining legendaries (Cleave Echo, Corpse Boom,
|
||
Voidstep…), vendor with rerolling stock, gamble-free sell/buy economy,
|
||
and a shared stash.
|
||
- **Elite monsters** with 10 random affixes (Frozen, Jailer, Necrotic…),
|
||
champion packs, and torment levels I–X for endless scaling after victory.
|
||
- **Full RPG systems**: strength/dex/vit/energy allocation, crit & crit damage,
|
||
elemental damage & resists, cooldown reduction, magic/gold find, shrines,
|
||
destructibles, health/mana potions on a potion belt.
|
||
- **Waypoint network** between acts, quest tracker, NPC dialogs
|
||
(blacksmith, healer, stash keeper), death penalty & hardcore mode.
|
||
- **Procedural audio**: WebAudio-synthesised SFX for every action and a
|
||
generative music sequencer with per-theme moods (town, crypt, cave, hell, boss).
|
||
- **English + Tiếng Việt**, damage numbers, screen shake, and label options.
|
||
|
||
## Controls
|
||
|
||
| Input | Action |
|
||
|---|---|
|
||
| **LMB** (hold) | Move / attack-move onto enemies / interact |
|
||
| **RMB, 1–3** | Cast bound skills |
|
||
| **Q / E** | Health / mana potion |
|
||
| **F or Space** | Interact — stairs, chests, shrines, NPCs |
|
||
| **Alt** | Toggle item labels |
|
||
| **I / C / T / J / M** | Inventory · Character · Skills · Quests · Map |
|
||
| **Esc** | Close panels / pause |
|
||
|
||
## Tech notes
|
||
|
||
- Pure vanilla ES3-style classic scripts (works from `file://`), global
|
||
`window.D2` namespace, ~10k lines across `js/core`, `js/data`, `js/game`,
|
||
`js/render`, `js/ui`.
|
||
- HTML5 Canvas isometric renderer (64×32 diamond tiles, painter's-algorithm
|
||
depth sort, raycast FOV + fog, additive lighting with torch flicker,
|
||
screen-space damage numbers).
|
||
- A\* pathfinding with per-frame budget, spatial-hash collision queries,
|
||
Bresenham line-of-sight, cellular-automata + room generator with
|
||
connectivity guarantees (stairs are never sealed off).
|
||
- WebAudio: zero audio files — every sound is a recipe of oscillators,
|
||
noise buffers and envelopes; music is a live sequencer per mood.
|
||
- i18n dictionary (EN/VI), settings + save slots in `localStorage`
|
||
under `d2d.*`, export/import via base64 code.
|
||
|
||
## Repository layout
|
||
|
||
```
|
||
index.html shell + HUD DOM + script load order
|
||
css/style.css full gothic UI theme
|
||
js/core/ util, i18n, save, input, audio
|
||
js/data/ balance, items, monsters, skills (all data-driven)
|
||
js/game/ world gen, entities, ai, combat, loot, player, orchestrator
|
||
js/render/ procedural sprites, isometric renderer, minimap
|
||
js/ui/ hud, panels, screens
|
||
js/main.js bootstrap + game loop
|
||
tools/ headless_test.js (81 assertions), browser E2E driver,
|
||
CDP runner, icon generator, zip packer
|
||
```
|
||
|
||
## Development
|
||
|
||
```bash
|
||
node tools/headless_test.js # 81-assertion simulation suite (no browser)
|
||
node tools/make_icons.mjs # regenerate PWA icons
|
||
node tools/build_zip.mjs # produce diablo2d-itch.zip
|
||
```
|
||
|
||
The headless suite boots the entire game in Node (stubbed DOM/canvas),
|
||
generates every floor, casts every skill of every class, kills every boss,
|
||
exercises economy/save-load, and soaks 3 600 combat frames.
|
||
|
||
### Browser smoke test (optional, needs the Playwright chromium shell)
|
||
|
||
```bash
|
||
python3 -m http.server 8942 &
|
||
chromium-headless-shell --no-sandbox --remote-debugging-port=9344 \
|
||
"http://127.0.0.1:8942/tools/browser_drive.html?phase=full&mute=1" &
|
||
node tools/cdp_run.mjs 9344 150 # polls the E2E log to completion
|
||
```
|
||
|
||
## Publishing
|
||
|
||
### itch.io
|
||
1. `node tools/build_zip.mjs` → `diablo2d-itch.zip`
|
||
2. Create a new project → kind of project: **HTML** → upload the zip.
|
||
3. Tick *This file will be played in the browser*, set viewport
|
||
**1280×720** or larger, enable fullscreen button. Done.
|
||
|
||
### Any static host (GitHub Pages, Netlify, S3…)
|
||
Upload the folder as-is. No build, no server code, no CORS issues —
|
||
everything is relative-path static files.
|
||
|
||
## License
|
||
|
||
Code and generated art: MIT (see `LICENSE`).
|
||
"Diablo" is a trademark of Blizzard Entertainment — this is an unaffiliated
|
||
fan-style homage; no Blizzard assets are used.
|