Game · Isometric ARPG · Vanilla JS + Canvas
AFGROND — a browser action-RPG
A Diablo II-style isometric action-RPG that runs entirely in the browser — vanilla JavaScript on an HTML5 canvas with no build step, no dependencies and no art assets. Pick one of three classes and descend ten procedurally-generated levels of the abyss: kill hordes, hoover up loot with random affixes and gem sockets, fight champion packs and bosses, hire a mercenary, and face the final darkness. Every sprite is drawn procedurally and every sound is synthesised with WebAudio.
Live demo
The whole game runs right here in the page. Click Nuwe spel, pick a class, and descend. Click the frame first so it takes keyboard and mouse.
localStorage. Best on a desktop browser; touch controls appear automatically on phones.Overview
AFGROND is a from-scratch action-RPG in the Diablo II mould — no engine, no asset pipeline. The isometric world is a tile grid projected onto a 2:1 diamond; movement is click-to-move with A* pathfinding (and WASD), and dungeons are generated room-by-room with corridors, hazards, shrines and a boss room. Combat, AI, loot, the inventory and the UI are all hand-written, and the renderer caches procedurally-drawn character "models" and stone textures to stay smooth on low-end hardware.
What's in it
🪓 Three classes
Barbaar, Towenaar and Skadujagter — each with its own stats, starting gear and skill pool: cleave, whirlwind, warcry, leap, fireball, frost nova, chain-lightning, teleport, meteor, multishot, poison and more.
🗺️ Procedural dungeons
Infinitely-descending levels across three biomes — crypt, cavern and inferno — each with its own palette, monster pool, hazards and interactive shrines.
💎 Loot & gem sockets
Items roll normal → magic → rare → set → unique with random affixes; gear has sockets you fuse gems into — slot-aware, so a ruby adds fire damage to a weapon but life to armour.
👑 Champion packs
Named, glowing elite monsters with stacked modifiers — fast, tough, deadly, regenerating, armoured, fiery — that drop guaranteed boosted loot.
🛡️ Mercenary companion
Hire a hireling who fights at your side, draws monster aggro, levels with you, and can fall in battle and be revived in town.
⚔️ Difficulty tiers
Normaal → Helse → Hel, unlocked by clearing deep bosses, scaling monster HP and damage — and the quality of what they drop.
📜 Story & a finale
An intro legend, a quest-giver, and a final boss — Die Eerste Duister — at the bottom of the abyss, with a victory ending and persistent high scores.
🏰 A living town
A merchant who buys, sells and gambles; a shared stash; a waypoint network; and a hireling-master — all woven into a safe hub between runs.
🔊 Procedural everything
Every character and tile is drawn on a canvas at runtime, and every sound — swings, spells, an ambient drone — is synthesised with WebAudio. No images, no audio files ship.
How it works
- No build, no deps: plain ES modules served as static files —
index.html, one stylesheet and a smalljs/tree (~3,500 lines of vanilla JS). Open it over HTTP and it runs. - Isometric engine: a tile grid projected to a 2:1 diamond with a depth-sorted painter's render; A* gives click-to-move pathing for the hero, monsters and the mercenary.
- Procedural art: character "models" and stone/brick textures are drawn once into off-screen canvases and cached, so dozens of sprites stay cheap on a 2-core CPU.
- Game flow: generation, spawning, combat, loot rolls, champions, difficulty scaling, saves and the finale are all driven from a single
requestAnimationFrameloop.