Skip to main content

How to Make a MOBA Game

Copied to clipboard!
No boilerplate memorization required

How to Vibe Code a Top-Down MOBA Arena Game

Stay in your creative flow. Direct AI models to wire lane minion waves, Q/W/E hero skillshots, defensive towers, and gold item upgrades—and ship a playable 5-minute MOBA prototype in your browser in under 25 minutes.

Core Stack

HTML5 Canvas + JS

Match Pace

3–5 Min Lane Push

AI Partner

Claude / Gemini

Target Time

20–25 Mins

The Philosophy

The Vibe Coding MOBA Philosophy

Amateur developers often stall on MOBAs because they try to build 100 heroes, a 45-minute 3-lane map, and dedicated socket servers on day one. Vibe coding unlocks the secret of indie MOBA prototyping: start with a fast-paced 3-to-5-minute ARAM / Single-Lane + Jungle arena against smart AI bots, where you act as the Hero & Balance Designer while AI synthesizes minion wave aggro, tower range rings, and Q/W/E/R cooldowns.

Old-School MOBA Trap

  • Spending months configuring NavMesh pathfinding and server replication before testing a single skillshot.
  • Designing 45-minute matches that are impossible to playtest and balance solo.
  • Getting stuck wiring complex shop inventory trees before minion last-hitting works.
  • Towers shooting heroes endlessly even when allied minions are tanking inside the ring.

The Vibe Coder Way

  • Self-contained Top-Down HTML5 Canvas arena with Blue vs. Red Bases, Towers, and Minion waves.
  • Describe the hero kit: "Click-to-move or WASD, Q skillshot fireball, W blink dash, E AoE heal, and gold on last-hit."
  • Tune tower aggro rules in plain English: "Towers target minions first unless an enemy hero damages an allied hero."
  • Scale up to Colyseus / WebSockets multiplayer only after your 1v1 or 3v3 arena loop feels amazing.
Execution

The 4-Step Blueprint

From an empty arena canvas to farming minions, dodging tower shots, and destroying the enemy Nexus.

Step 01

Build the Lane, Towers & Bases

Create a single index.html file. Lay out a Blue Base on the left, a Red Base on the right, defensive Lane Towers in between, and neutral Jungle Creep camps on the flanks.

💡 Pro Vibe Tip: Draw translucent range circles around every Tower so players immediately know when they are stepping into danger.
Step 02

The "One-Shot Architect" Prompt

Ask your AI for periodic minion wave spawners (every 10 seconds), auto-attack targeting, Hero XP leveling, and a Q/W/E ability bar with cooldown timers.

🔑 Key Constraint: Tell the AI: "Award bonus Gold (+25g) and XP whenever the player lands the killing blow on an enemy minion or jungle creep."
Step 03

Items Shop & Enemy Hero AI

Add a 1-click Base Shop to spend Gold on Attack Damage, Boots of Speed, or Lifesteal—and program an enemy AI Hero that pushes with its minion wave and retreats at low HP.

✨ Iteration Secret: Give each Base a green Healing Fountain aura that rapidly restores HP when a wounded hero walks back to spawn.
Step 04

Balance, Minimap & Web Share

Add a live tactical minimap in the bottom corner, tune match length to a crisp 3–5 minutes, and share your playable MOBA prototype in any browser.

🏆 The Grand Payoff: A complete Multiplayer Online Battle Arena loop—waves, towers, skillshots, levels, and Nexus destruction—in one portable file.
Interactive Tool

Vibe Prompt Configurator

Select your MOBA map layout, control scheme, and hero kit. Copy the generated prompt straight into Claude, Cursor, or Gemini.

Special Feature Vibe
Optional custom details added straight into your master prompt.
Generated Master Prompt
Ready to paste into Claude, Gemini, or ChatGPT Single-file HTML5 Canvas ready
Arena Spec

Essential Elements of a MOBA Game

From League of Legends and Dota 2 to fast mobile brawlers, every Multiplayer Online Battle Arena revolves around these core systems:

  • Lanes, Map & Jungle Layout

    Connect the two team bases with contested lanes guarded by towers, flanked by neutral jungle areas containing buff camps and shrines.

  • Heroes & Unique Skill Kits

    Players control a Hero with distinct Q/W/E/R abilities (damage skillshots, dashes, heals, or stuns) who levels up by earning combat XP.

  • Minions & Neutral Jungle Creeps

    AI-controlled Minions spawn in waves to march down lanes and soak tower fire, while tougher neutral Creeps reward extra gold and buffs in the jungle.

  • Defensive Lane Towers & Nexus

    Powerful defensive structures blast enemies who step into range without minion cover—protecting the final team Base (Nexus) that decides victory.

  • Gold Economy & Base Item Shop

    Farming creeps and scoring takedowns grants Gold to purchase stat-boosting Items at the base shop—creating a satisfying power curve each match.

  • Team Balance & Pacing

    Keep hero stats balanced and tune structure health so browser/mobile matches reach an exciting climax in 3 to 5 minutes.

UX Checklist Before Shipping: Draw clear health bars above every minion, tower, and hero, prioritize minions inside tower aggro logic, and show floating +25g popups on every last-hit.
Starter Template

The "Golden" Single-File MOBA Lane Arena Template

Save this as index.html and open it in any browser to play a Top-Down MOBA with Minion Waves, Towers, Q/W/E Skills, Item Upgrades, and an AI Enemy Hero.

index.html
HTML5 Canvas + Vanilla JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vibe MOBA: Nexus Lane Arena</title>
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; user-select: none; }
  body {
    background: #070b14;
    color: #f8fafc;
    font-family: system-ui, -apple-system, sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 10px;
  }
  .top-hud {
    width: 900px;
    max-width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #111827;
    border: 1px solid #263554;
    padding: 8px 14px;
    border-radius: 10px;
    margin-bottom: 8px;
    font-size: 13px;
  }
  .shop-btn {
    background: #facc15;
    color: #090d16;
    border: none;
    padding: 5px 12px;
    border-radius: 6px;
    font-weight: 800;
    cursor: pointer;
  }
  canvas {
    border: 2px solid #334155;
    border-radius: 14px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.7);
    max-width: 100%;
    height: auto;
    cursor: crosshair;
    background: #0f1d19;
  }
</style>
</head>
<body>
  <div class="top-hud">
    <span id="stats-el">⚔️ Lv.1 Hero  |  🪙 Gold: 100  |  ATK: 18</span>
    <span>Move: <kbd>WASD</kbd> • Auto-Shot: <kbd>Click</kbd> • <kbd>Q</kbd> Fireball • <kbd>W</kbd> Dash • <kbd>E</kbd> Heal</span>
    <button class="shop-btn" id="buy-btn">🛒 Buy Sword (+8 ATK / 100g)</button>
  </div>
  <canvas id="game" width="900" height="480"></canvas>

<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const statsEl = document.getElementById('stats-el');
const keys = {};
let mouse = { x: 450, y: 240 };

let state = {};

function initGame() {
  state = {
    over: false,
    winner: '',
    waveTimer: 60,
    player: {
      team: 'blue', x: 140, y: 240, r: 16,
      hp: 260, maxHp: 260, atk: 18, speed: 3.3,
      lvl: 1, xp: 0, gold: 100,
      cdQ: 0, cdW: 0, cdE: 0, atkCd: 0, respawn: 0
    },
    aiHero: {
      team: 'red', x: 760, y: 240, r: 16,
      hp: 260, maxHp: 260, atk: 16, speed: 2.8,
      cdQ: 0, atkCd: 0, respawn: 0
    },
    structures: [
      { id: 'b_nexus', team: 'blue', kind: 'nexus', x: 65, y: 240, r: 28, hp: 700, maxHp: 700, range: 150, cd: 0 },
      { id: 'b_tower', team: 'blue', kind: 'tower', x: 270, y: 240, r: 20, hp: 420, maxHp: 420, range: 155, cd: 0 },
      { id: 'r_tower', team: 'red', kind: 'tower', x: 630, y: 240, r: 20, hp: 420, maxHp: 420, range: 155, cd: 0 },
      { id: 'r_nexus', team: 'red', kind: 'nexus', x: 835, y: 240, r: 28, hp: 700, maxHp: 700, range: 150, cd: 0 }
    ],
    minions: [],
    projectiles: [],
    fx: []
  };
  spawnWave();
  updateHud();
}

function updateHud() {
  const p = state.player;
  statsEl.textContent = `⚔️ Lv.${p.lvl} Hero  |  🪙 Gold: ${p.gold}  |  ATK: ${p.atk}`;
}

function spawnWave() {
  for (let i = 0; i < 3; i++) {
    state.minions.push({
      team: 'blue', x: 110 - i * 24, y: 215 + i * 25, r: 10,
      hp: 75, maxHp: 75, atk: 8, cd: 0
    });
    state.minions.push({
      team: 'red', x: 790 + i * 24, y: 215 + i * 25, r: 10,
      hp: 75, maxHp: 75, atk: 8, cd: 0
    });
  }
}

function addFx(x, y, text, color) {
  state.fx.push({ x, y, text, color, life: 32 });
}

function fireProjectile(from, tx, ty, dmg, speed, radius, color, isSkill) {
  const ang = Math.atan2(ty - from.y, tx - from.x);
  state.projectiles.push({
    team: from.team,
    x: from.x, y: from.y,
    vx: Math.cos(ang) * speed,
    vy: Math.sin(ang) * speed,
    dmg, r: radius, color, life: isSkill ? 55 : 38
  });
}

window.addEventListener('keydown', e => {
  keys[e.code] = true;
  if (state.over && e.code === 'Space') { initGame(); return; }
  const p = state.player;
  if (p.respawn > 0 || state.over) return;

  // Q: Fireball Skillshot
  if (e.code === 'KeyQ' && p.cdQ <= 0) {
    p.cdQ = 180;
    fireProjectile(p, mouse.x, mouse.y, p.atk * 2.2, 8.5, 9, '#38bdf8', true);
    addFx(p.x, p.y - 20, 'Q: Arcane Blast!', '#38bdf8');
  }
  // W: Blink Dash toward cursor
  if (e.code === 'KeyW' && p.cdW <= 0) {
    p.cdW = 240;
    const ang = Math.atan2(mouse.y - p.y, mouse.x - p.x);
    p.x = Math.max(30, Math.min(870, p.x + Math.cos(ang) * 110));
    p.y = Math.max(30, Math.min(450, p.y + Math.sin(ang) * 110));
    addFx(p.x, p.y - 20, 'W: Dash!', '#a855f7');
  }
  // E: Heal Aura
  if (e.code === 'KeyE' && p.cdE <= 0) {
    p.cdE = 300;
    p.hp = Math.min(p.maxHp, p.hp + 75);
    addFx(p.x, p.y - 20, '+75 HP Heal!', '#10b981');
  }
});
window.addEventListener('keyup', e => { keys[e.code] = false; });

canvas.addEventListener('mousemove', e => {
  const rect = canvas.getBoundingClientRect();
  mouse.x = (e.clientX - rect.left) * (canvas.width / rect.width);
  mouse.y = (e.clientY - rect.top) * (canvas.height / rect.height);
});

canvas.addEventListener('mousedown', () => {
  if (state.over) { initGame(); return; }
  const p = state.player;
  if (p.respawn <= 0 && p.atkCd <= 0) {
    p.atkCd = 22;
    fireProjectile(p, mouse.x, mouse.y, p.atk, 7.5, 5, '#fde047', false);
  }
});

document.getElementById('buy-btn').addEventListener('click', () => {
  const p = state.player;
  if (p.gold >= 100) {
    p.gold -= 100;
    p.atk += 8;
    p.maxHp += 30;
    p.hp = Math.min(p.maxHp, p.hp + 30);
    addFx(p.x, p.y - 24, '+8 ATK Upgraded!', '#facc15');
    updateHud();
  }
});

function getTargetsFor(team) {
  const list = [];
  state.minions.forEach(m => { if (m.team !== team && m.hp > 0) list.push(m); });
  state.structures.forEach(s => { if (s.team !== team && s.hp > 0) list.push(s); });
  if (team === 'blue' && state.aiHero.respawn <= 0) list.push(state.aiHero);
  if (team === 'red' && state.player.respawn <= 0) list.push(state.player);
  return list;
}

function awardPlayerKill(gold, xp, x, y) {
  const p = state.player;
  p.gold += gold;
  p.xp += xp;
  addFx(x, y, `+${gold}g`, '#facc15');
  if (p.xp >= p.lvl * 60) {
    p.xp = 0;
    p.lvl++;
    p.maxHp += 35;
    p.hp = p.maxHp;
    p.atk += 4;
    addFx(p.x, p.y - 26, `LEVEL UP! Lv.${p.lvl}`, '#38bdf8');
  }
  updateHud();
}

function update() {
  if (state.over) return;

  state.waveTimer--;
  if (state.waveTimer <= 0) {
    spawnWave();
    state.waveTimer = 420;
  }

  const p = state.player;
  if (p.cdQ > 0) p.cdQ--;
  if (p.cdW > 0) p.cdW--;
  if (p.cdE > 0) p.cdE--;
  if (p.atkCd > 0) p.atkCd--;

  if (p.respawn > 0) {
    p.respawn--;
    if (p.respawn === 0) { p.x = 110; p.y = 240; p.hp = p.maxHp; }
  } else {
    if (keys['KeyW'] === false) {
      // WASD Movement (Note: W is both up and dash when tapped; Arrow keys also supported)
    }
    if (keys['KeyA'] || keys['ArrowLeft']) p.x -= p.speed;
    if (keys['KeyD'] || keys['ArrowRight']) p.x += p.speed;
    if (keys['ArrowUp']) p.y -= p.speed;
    if (keys['KeyS'] || keys['ArrowDown']) p.y += p.speed;
    p.x = Math.max(25, Math.min(875, p.x));
    p.y = Math.max(25, Math.min(455, p.y));

    // Base Fountain heal
    if (Math.hypot(p.x - 65, p.y - 240) < 75) {
      p.hp = Math.min(p.maxHp, p.hp + 0.6);
    }
  }

  // AI Hero Logic
  const ai = state.aiHero;
  if (ai.atkCd > 0) ai.atkCd--;
  if (ai.cdQ > 0) ai.cdQ--;
  if (ai.respawn > 0) {
    ai.respawn--;
    if (ai.respawn === 0) { ai.x = 780; ai.y = 240; ai.hp = ai.maxHp; }
  } else {
    const targets = getTargetsFor('red');
    let nearest = null;
    let minDist = 9999;
    targets.forEach(t => {
      const d = Math.hypot(t.x - ai.x, t.y - ai.y);
      if (d < minDist) { minDist = d; nearest = t; }
    });

    if (ai.hp < 75) {
      ai.x = Math.min(820, ai.x + ai.speed);
      if (ai.x > 760) ai.hp = Math.min(ai.maxHp, ai.hp + 0.8);
    } else if (nearest) {
      if (minDist > 135) {
        const ang = Math.atan2(nearest.y - ai.y, nearest.x - ai.x);
        ai.x += Math.cos(ang) * ai.speed;
        ai.y += Math.sin(ang) * ai.speed;
      } else if (ai.atkCd <= 0) {
        ai.atkCd = 32;
        fireProjectile(ai, nearest.x, nearest.y, ai.atk, 6.5, 6, '#fb7185', false);
      }
    }
  }

  // Minion AI
  state.minions.forEach(m => {
    if (m.cd > 0) m.cd--;
    const enemies = getTargetsFor(m.team);
    let target = null;
    let bestD = 9999;
    enemies.forEach(e => {
      const d = Math.hypot(e.x - m.x, e.y - m.y);
      if (d < bestD) { bestD = d; target = e; }
    });
    if (target) {
      if (bestD > m.r + target.r + 18) {
        const ang = Math.atan2(target.y - m.y, target.x - m.x);
        m.x += Math.cos(ang) * 1.4;
        m.y += Math.sin(ang) * 1.4;
      } else if (m.cd <= 0) {
        m.cd = 40;
        target.hp -= m.atk;
      }
    }
  });

  // Towers & Nexus defense fire
  state.structures.forEach(s => {
    if (s.hp <= 0) return;
    if (s.cd > 0) s.cd--;
    const enemies = getTargetsFor(s.team);
    const inRange = enemies.filter(e => Math.hypot(e.x - s.x, e.y - s.y) <= s.range);
    if (inRange.length > 0 && s.cd <= 0) {
      s.cd = 48;
      const tgt = inRange[0];
      fireProjectile(s, tgt.x, tgt.y, 26, 7, 7, s.team === 'blue' ? '#38bdf8' : '#f43f5e', false);
    }
  });

  // Projectiles
  for (let i = state.projectiles.length - 1; i >= 0; i--) {
    const pr = state.projectiles[i];
    pr.x += pr.vx;
    pr.y += pr.vy;
    pr.life--;
    let hit = false;
    const enemies = getTargetsFor(pr.team);
    for (let j = 0; j < enemies.length; j++) {
      const e = enemies[j];
      if (Math.hypot(e.x - pr.x, e.y - pr.y) < e.r + pr.r) {
        e.hp -= pr.dmg;
        if (e.hp <= 0 && pr.team === 'blue') {
          awardPlayerKill(e === state.aiHero ? 100 : 25, 30, e.x, e.y);
        }
        hit = true;
        break;
      }
    }
    if (hit || pr.life <= 0) state.projectiles.splice(i, 1);
  }

  // Cleanup dead minions & structures, handle Hero respawns
  state.minions = state.minions.filter(m => m.hp > 0);
  state.structures = state.structures.filter(s => {
    if (s.hp <= 0 && s.kind === 'nexus') {
      state.over = true;
      state.winner = s.team === 'red' ? 'VICTORY! RED NEXUS DESTROYED!' : 'DEFEAT! BLUE NEXUS FELL!';
    }
    return s.hp > 0;
  });

  if (p.hp <= 0 && p.respawn === 0) {
    p.respawn = 180;
    addFx(p.x, p.y, 'Respawning in 3s...', '#f43f5e');
  }
  if (ai.hp <= 0 && ai.respawn === 0) {
    ai.respawn = 200;
  }

  state.fx.forEach(f => { f.y -= 0.7; f.life--; });
  state.fx = state.fx.filter(f => f.life > 0);
}

function drawHealthBar(x, y, w, hp, maxHp, color) {
  ctx.fillStyle = '#090d16';
  ctx.fillRect(x - w / 2, y, w, 6);
  ctx.fillStyle = color;
  ctx.fillRect(x - w / 2, y, Math.max(0, (hp / maxHp) * w), 6);
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Lane Path
  ctx.fillStyle = '#1e293b';
  ctx.fillRect(40, 175, 820, 130);
  ctx.strokeStyle = '#334155';
  ctx.lineWidth = 2;
  ctx.strokeRect(40, 175, 820, 130);

  // Structures & Range Rings
  state.structures.forEach(s => {
    ctx.strokeStyle = s.team === 'blue' ? 'rgba(56,189,248,0.16)' : 'rgba(244,63,94,0.16)';
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    ctx.arc(s.x, s.y, s.range, 0, Math.PI * 2);
    ctx.stroke();

    ctx.fillStyle = s.team === 'blue' ? '#0284c7' : '#e11d48';
    ctx.beginPath();
    ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = '#f8fafc';
    ctx.stroke();
    drawHealthBar(s.x, s.y - s.r - 12, 48, s.hp, s.maxHp, s.team === 'blue' ? '#38bdf8' : '#f43f5e');
  });

  // Minions
  state.minions.forEach(m => {
    ctx.fillStyle = m.team === 'blue' ? '#60a5fa' : '#fb7185';
    ctx.beginPath();
    ctx.arc(m.x, m.y, m.r, 0, Math.PI * 2);
    ctx.fill();
    drawHealthBar(m.x, m.y - 18, 24, m.hp, m.maxHp, m.team === 'blue' ? '#38bdf8' : '#f43f5e');
  });

  // Player Hero
  const p = state.player;
  if (p.respawn <= 0) {
    ctx.fillStyle = '#38bdf8';
    ctx.beginPath();
    ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = '#facc15';
    ctx.lineWidth = 3;
    ctx.stroke();
    drawHealthBar(p.x, p.y - 26, 42, p.hp, p.maxHp, '#10b981');
  }

  // AI Hero
  const ai = state.aiHero;
  if (ai.respawn <= 0) {
    ctx.fillStyle = '#f43f5e';
    ctx.beginPath();
    ctx.arc(ai.x, ai.y, ai.r, 0, Math.PI * 2);
    ctx.fill();
    ctx.strokeStyle = '#fda4af';
    ctx.lineWidth = 2;
    ctx.stroke();
    drawHealthBar(ai.x, ai.y - 26, 42, ai.hp, ai.maxHp, '#f43f5e');
  }

  // Projectiles
  state.projectiles.forEach(pr => {
    ctx.fillStyle = pr.color;
    ctx.beginPath();
    ctx.arc(pr.x, pr.y, pr.r, 0, Math.PI * 2);
    ctx.fill();
  });

  // Bottom Ability Bar
  const skills = [
    { key: 'Q', name: 'Blast', cd: Math.ceil(p.cdQ / 60) },
    { key: 'W', name: 'Dash', cd: Math.ceil(p.cdW / 60) },
    { key: 'E', name: 'Heal', cd: Math.ceil(p.cdE / 60) }
  ];
  skills.forEach((sk, i) => {
    const bx = 355 + i * 66;
    const by = 420;
    ctx.fillStyle = sk.cd > 0 ? '#1e293b' : '#0284c7';
    ctx.strokeStyle = '#f8fafc';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.roundRect(bx, by, 56, 48, 8);
    ctx.fill();
    ctx.stroke();
    ctx.fillStyle = '#fff';
    ctx.font = 'bold 13px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText(sk.cd > 0 ? sk.cd + 's' : `${sk.key}: ${sk.name}`, bx + 28, by + 29);
  });

  // FX Popups
  state.fx.forEach(f => {
    ctx.fillStyle = f.color;
    ctx.font = 'bold 14px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText(f.text, f.x, f.y);
  });

  if (state.over) {
    ctx.fillStyle = 'rgba(7, 11, 20, 0.85)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#facc15';
    ctx.font = 'bold 34px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText(state.winner, canvas.width / 2, 220);
    ctx.fillStyle = '#e2e8f0';
    ctx.font = '18px sans-serif';
    ctx.fillText('Click or Press SPACE to Play Another Match', canvas.width / 2, 265);
  }

  requestAnimationFrame(() => {
    update();
    draw();
  });
}

initGame();
draw();
</script>
</body>
</html>
Troubleshooting

How to Debug Without Losing Your Vibe

MOBAs have lots of moving units on screen. Use these three vibe debugging rules to keep lane battles fair and readable:

Minion-First Tower Aggro

So players can push towers behind their minion wave without getting sniped, prompt: "Sort tower targets in range so enemy minions are targeted before enemy heroes."

Reward Player Last-Hits

Make farming lane creeps feel tactical by instructing your AI assistant: "Only grant the +25 Gold bonus when a projectile or skill owned by the player reduces the minion's HP to <= 0."

Smart AI Hero Retreat

Prevent the enemy AI Hero from suiciding into your towers at 10% HP by prompting: "When aiHero.hp < 30% of maxHp, override attack behavior and retreat toward the friendly Nexus fountain."

Extensions

The Vibe Prompt Vault

Copy-paste prompts to add 3-Lane Jungle Camps, Stealth Bushes, and a Hero Select Screen.

🌲 Prompt: Add Neutral Jungle Buff Camps & Stealth Brush
Prompt Template

"Extend my HTML5 Canvas MOBA in index.html with top and bottom Jungle areas above and below the main lane. Spawn a neutral Red Buff Golem and Blue Buff Guardian that respawn every 45 seconds and grant +25% Attack Damage or +50% Cooldown Reduction when slain, plus tall green Brush zones that hide heroes from enemy auto-targeting."

🦸 Prompt: Add a 3-Class Hero Draft Screen (Mage, Marksman, Tank)
Prompt Template

"Add a pre-match Hero Selection modal to my single-file MOBA with 3 distinct heroes: 1) Arcane Mage (long-range AoE burst Q, teleport W), 2) Swift Marksman (rapid auto-attacks, piercing arrow Q, tumble W), and 3) Iron Vanguard Tank (high HP, stun slam Q, reflective shield W)."

🗺️ Prompt: Expand to a Scrolling 3-Lane Map with Corner Minimap
Prompt Template

"Upgrade my MOBA arena to a 2000x2000 scrolling map with Top, Mid, and Bottom lanes connected by a river. Keep the camera centered on the player hero (with Spacebar lock/unlock) and draw a 160x160 live tactical Minimap in the bottom-right corner showing all towers, minion waves, and hero icons."

We use cookies for ads and analytics.