Thomas Verhave

Writing · Build Notes

I built a Diablo II-style ARPG in vanilla JS and Canvas — no engine, no build, no art assets

AFGROND (die afgrond wag — "the abyss waits") is a browser isometric action-RPG in the Diablo II mold: a town hub, infinitely-descending procedural dungeons across three biomes, three classes, a loot system with rarity tiers and affixes, gem sockets, skill trees, A* pathfinding, champion packs, a hireable mercenary, difficulty tiers, and a final boss at depth 10.

AFGROND (die afgrond wag — "the abyss waits") is a browser isometric action-RPG in the Diablo II mold: a town hub, infinitely-descending procedural dungeons across three biomes, three classes, a loot system with rarity tiers and affixes, gem sockets, skill trees, A* pathfinding, champion packs, a hireable mercenary, difficulty tiers, and a final boss at depth 10.

It's vanilla JavaScript and HTML5 Canvas 2D — no engine, no build step, no dependencies, and no art assets at all. Every sprite is drawn procedurally, every icon is an emoji, and it runs fine on low-end hardware. Building a genre this dense with zero libraries taught me more about scope than any tutorial.

The heart: isometric projection

An ARPG lives or dies on its isometric renderer. The whole illusion is one coordinate transform — tile space (grid) to screen space (diamonds). With 64×32 tiles it's four lines:

export const TILE_W = 64, TILE_H = 32;        // diamond width / height
export const HALF_W = 32, HALF_H = 16;

export function worldToScreen(tx, ty) {
  return { x: (tx - ty) * HALF_W,             // x spreads on the difference
           y: (tx + ty) * HALF_H };           // y stacks on the sum
}

(tx - ty) for x and (tx + ty) for y is the entire diamond grid. The inverse (screenToWorld) turns a mouse click back into a tile so you can click-to-move, and a small Camera adds the origin offset to keep the player centered. Get this right and depth-sort everything back-to-front, and a pile of 2D canvas draws reads as a 3D world.

Everything is procedural

With no art pipeline, the constraint is the same one that made my other projects portable: if you can't download it, generate it.

The systems that make it an ARPG

The genre is really a stack of interlocking systems, and the fun was seeing how few lines each actually needs once the data model is right:

What I learned

A build-story · see the live project → · more writing →