Game Build Breakdown
How Arena of Gods Turns Boss Fights into a Browser Game Course
Arena of Gods looks like a spectacle game, but its useful lesson is structure: one arena, one player verb set, many bosses, and clear telegraphs that make chaos readable.
Production context
This guide studies Arena of Gods, a published Supagames game. Repository source: biggames/arena-of-gods/index.html.
The snippets below are intentionally smaller than the production file. They isolate transferable systems so you can reuse the idea in your own browser game without copying every detail of the original project.
1. Start with a Boss Data Contract
A boss-rush game stays maintainable when each boss is data first and custom behavior second. Health, movement speed, arena color, attack names, cooldowns and phase thresholds can live in one compact definition. The game loop can then ask the active boss what it is allowed to do instead of spreading special cases across the whole file.
This also makes balancing easier. When wave 10 feels too hard, you can compare it with wave 5 as data: is the cooldown shorter, the projectile faster, the warning radius smaller, or the health pool too high?
const BOSSES = [
{
id: "ember-titan",
name: "Ember Titan",
maxHp: 900,
phaseAt: [0.66, 0.33],
attacks: [
{ type: "slam", cooldown: 3.2, warning: 0.9, radius: 7 },
{ type: "fireLine", cooldown: 2.4, warning: 0.55, speed: 18 },
],
},
];
2. Telegraph Before Damage
The player should lose because they ignored a readable warning, not because damage appeared under their feet. A telegraph object can be rendered as a ring, cone, line or decal before the real attack becomes active. In Three.js, keep this cheap: reuse geometry and material, update scale and opacity, then return the marker to a pool.
The important lesson is that attack timing has states. Warning, active damage and recovery are separate. That gives animation, sound and HUD hints enough time to support gameplay rather than decorate it after the hit.
function updateAttackWarning(warning, dt) {
warning.elapsed += dt;
const t = Math.min(1, warning.elapsed / warning.duration);
warning.mesh.scale.setScalar(THREE.MathUtils.lerp(0.3, warning.radius, t));
warning.material.opacity = 0.25 + Math.sin(t * Math.PI) * 0.35;
if (t >= 1) activateBossHitbox(warning);
}
3. Keep the Spellbook Cooldowns Visual
A boss-rush spellbook needs immediate answers: which spell is ready, which is cooling down, and what key triggers it. HTML is usually better than 3D text for this because it remains crisp, cheap and accessible. The game loop only has to publish normalized cooldown progress.
Avoid coupling button rendering to combat logic. Let combat own timers and let the HUD read a snapshot. That separation prevents UI bugs from changing gameplay rules.
function renderSpellHud(spells) {
for (const spell of spells) {
const slot = document.querySelector(`[data-spell="${spell.id}"]`);
const ratio = spell.cooldownLeft / spell.cooldown;
slot.style.setProperty("--cooldown", ratio.toFixed(3));
slot.classList.toggle("is-ready", ratio <= 0);
}
}
4. Use Phases to Change Pressure, Not Just Numbers
A phase change is most interesting when it changes the question the player is answering. Phase one can teach spacing, phase two can add movement pressure, and phase three can test whether the player can combine both. Simply adding more health or damage often feels like a longer version of the same fight.
The clean implementation is a small phase resolver. It converts health ratio into phase index and emits a one-time transition event for music, VFX, arena tint and new attack unlocks.
function resolveBossPhase(boss) {
const hpRatio = boss.hp / boss.maxHp;
const nextPhase = boss.phaseAt.filter((limit) => hpRatio <= limit).length;
if (nextPhase !== boss.phase) {
boss.phase = nextPhase;
boss.attackSet = buildAttackSetForPhase(boss.id, nextPhase);
showPhaseBanner(boss.name, nextPhase + 1);
}
}
5. Build checklist
- Define every boss with health, attacks, phase thresholds and readable names before tuning numbers.
- Pool warning meshes, projectiles and hit effects so the first dramatic attack does not hitch.
- Separate combat state from HUD rendering; the HUD should consume snapshots, not own rules.
- Make each phase change player behavior: positioning, timing, target priority or resource use.