Abaixo está um framework JavaScript fundamental para RPG DBZ por turnos rodando em console (Node.js ou dev tools do navegador). Cobre sistemas centrais: stats, inimigos, loop de combate e progressão.
// Estado do Jogo
const player = { name: "Goku", level: 1, maxHp: 100, hp: 100, atk: 10, def: 5, ki: 0, xp: 0, inventory: [] };
const enemies = [
{ name: "Raditz", maxHp: 150, hp: 150, atk: 15, def: 8, xpReward: 50 },
{ name: "Nappa", maxHp: 200, hp: 200, atk: 20, def: 12, xpReward: 100 },
{ name: "Vegeta", maxHp: 250, hp: 250, atk: 25, def: 15, xpReward: 200 }
];
let currentEnemy = null;
const readline = require('readline').createInterface({ input: process.stdin, output: process.stdout });
// Utilitários
const log = (...args) => console.log(...args);
const waitForInput = (promptText) => new Promise(resolve => readline.question(promptText, resolve));
// Loop Principal
async function startGame() {
log("\n=== DRAGON BALL Z: CONSOLE RPG ===");
log(`Bem-vindo, ${player.name}. Sua jornada começa.`);
await mainMenu();
}
async function mainMenu() {
log(`\n--- ${player.name} | Nv.${player.level} | HP: ${player.hp}/${player.maxHp} | Ki: ${player.ki} ---`);
log("1. Treinar\n2. Lutar\n3. Status\n4. Sair");
const choice = await waitForInput("Escolha ação: ");
switch (choice) {
case "1": await train(); break;
case "2": await selectEnemy(); break;
case "3": showStatus(); await mainMenu(); break;
case "4": log("Adeus, guerreiro."); readline.close(); process.exit(); break;
default: log("Entrada inválida."); await mainMenu();
}
}
// Sistemas
async function train() {
log("\nVocê treina intensamente... seu poder sobe!");
player.level++; player.atk += 2; player.def += 1; player.maxHp += 10; player.hp = player.maxHp; player.ki += 5;
log(`Level Up! -> Nv.${player.level} | ATK: ${player.atk} | DEF: ${player.def} | MAX HP: ${player.maxHp}`);
await mainMenu();
}
function showStatus() {
log(`\n--- STATUS ---\nNível: ${player.level}\nATK: ${player.atk}\nDEF: ${player.def}\nHP: ${player.hp}/${player.maxHp}\nKi: ${player.ki}\nXP: ${player.xp}`);
}
async function selectEnemy() {
log("\nEscolha um oponente:");
enemies.forEach((e, i) => log(`${i+1}. ${e.name} (HP: ${e.maxHp}, ATK: ${e.atk})`));
const idx = parseInt(await waitForInput("Número: ")) - 1;
if (enemies[idx]) {
currentEnemy = { ...enemies[idx] };
log(`\n>>> BATALHA INICIADA: ${currentEnemy.name} <<<`);
await battleLoop();
} else { log("Seleção inválida."); await mainMenu(); }
}
async function battleLoop() {
while (player.hp > 0 && currentEnemy.hp > 0) {
// Turno do Jogador
log(`\n--- SEU TURNO (HP: ${player.hp}) ---`);
log("1. Atacar\n2. Carregar Ki\n3. Curar (Custa 20 Ki)");
const action = await waitForInput("Ação: ");
let dmg = 0;
if (action === "1") dmg = calcDamage(player.atk, currentEnemy.def);
else if (action === "2") { player.ki += 10; log("Ki carregado (+10)."); }
else if (action === "3") {
if (player.ki >= 20) { player.ki -= 20; player.hp = Math.min(player.maxHp, player.hp + 30); log("Curou 30 HP."); }
else log("Ki insuficiente!");
} else { log("Hesitação..."); }
if (dmg > 0) { currentEnemy.hp -= dmg; log(`Você atingiu ${currentEnemy.name} por ${dmg} de dano! (HP Inimigo: ${Math.max(0, currentEnemy.hp)})`); }
if (currentEnemy.hp <= 0) break;
// Turno do Inimigo
const eDmg = calcDamage(currentEnemy.atk, player.def);
player.hp -= eDmg;
log(`\n${currentEnemy.name} contra-ataca por ${eDmg} de dano! (Seu HP: ${Math.max(0, player.hp)})`);
}
if (player.hp <= 0) { log("\n>>> VOCÊ CAIU. GAME OVER <<<"); readline.close(); process.exit(); }
else { log(`\n>>> VITÓRIA! ${currentEnemy.name} DERROTADO <<<`); player.xp += currentEnemy.xpReward; log(`Ganhou ${currentEnemy.xpReward} XP. Total: ${player.xp}`); currentEnemy = null; await mainMenu(); }
}
function calcDamage(atk, def) { return Math.max(atk - def + Math.floor(Math.random() * 3), 1); }
// Iniciar
startGame();
Este esqueleto é intencionalmente minimalista. Expanda peça por peça — adicione lista de golpes, depois transformações, depois mapa-múndi — para construir um fan game completo.