Mecánica básica de la experiencia y los niveles
En el corazón de cualquier sistema de progresión hay una idea simple: el jugador realiza acciones, gana experiencia y, cuando se acumula suficiente experiencia, se produce una transición a un nuevo nivel. Comencemos con la versión más simple en JavaScript:
class Player {
constructor() {
this.level = 1;
this.experience = 0;
this.experienceToNextLevel = 100;
}
gainExperience(amount) {
this.experience += amount;
while (this.experience >= this.experienceToNextLevel) {
this.levelUp();
}
}
levelUp() {
this.experience -= this.experienceToNextLevel;
this.level++;
this.experienceToNextLevel = Math.floor(this.experienceToNextLevel * 1.5);
console.log(`Congratulations! You have reached ${this.level} level!`);
}
}
const player = new Player();
player.gainExperience(150); // Ganamos experiencia y subimos de nivelPresta atención a la fórmula para calcular la experiencia para el siguiente nivel. Multiplicamos el valor actual por 1,5, lo que crea una curva de crecimiento exponencial. Este es un punto importante: si cada nivel requiere la misma cantidad de experiencia, el juego se volverá aburrido rápidamente.
Diferentes curvas de progresión
Hay varios enfoques populares para calcular la experiencia requerida. La progresión lineal, cuando cada nivel requiere una cantidad fija de experiencia adicional, es adecuada para juegos cortos. La curva exponencial, como en el ejemplo anterior, crea una sensación de complejidad gradual. La curva logarítmica hace que los primeros niveles sean rápidos y los siguientes más lentos.
Aquí hay un ejemplo con diferentes fórmulas:
class ProgressionSystem {
// Progresión lineal: 100, 200, 300, 400...
static linear(level, baseXP = 100) {
return baseXP * level;
}
// Exponencial: 100, 150, 225, 337,5...
static exponential(level, baseXP = 100, multiplier = 1.5) {
return Math.floor(baseXP * Math.pow(multiplier, level - 1));
}
// Polinomial: 100, 400, 900, 1600...
static polynomial(level, baseXP = 100) {
return baseXP * Math.pow(level, 2);
}
// Fórmula híbrida (como en Pokémon)
static hybrid(level) {
return Math.floor(1.2 * Math.pow(level, 3));
}
}
// Veamos cómo crece la demanda de experiencia
for (let level = 1; level <= 5; level++) {
console.log(`Level ${level}:`);
console.log(` Linear: ${ProgressionSystem.linear(level)}`);
console.log(` Exponential: ${ProgressionSystem.exponential(level)}`);
console.log(` Polynomial: ${ProgressionSystem.polynomial(level)}`);
}¿Qué fórmula elegir?
Depende de tu juego. Para los juegos casuales móviles, a menudo se utiliza una progresión rápida al principio para capturar al jugador, luego se ralentiza el ritmo. En los RPG hardcore, la progresión puede ser lenta y exigente desde el principio.
Añadimos premios por nivel
Subir de nivel sin recompensas es una oportunidad perdida. Los jugadores deben sentir que su progreso significa algo. Añadamos un sistema de recompensas:
class Player {
constructor() {
this.level = 1;
this.experience = 0;
this.health = 100;
this.attack = 10;
this.defense = 5;
this.skillPoints = 0;
}
levelUp() {
this.level++;
// Aumentamos las características básicas
this.health += 20;
this.attack += 3;
this.defense += 2;
this.skillPoints += 5;
// Cada 5º nivel da una recompensa especial
if (this.level % 5 === 0) {
this.unlockNewAbility();
}
// Recuperamos la salud al subir de nivel
this.currentHealth = this.health;
console.log(`
🎉 Level ${this.level}!
Health: ${this.health}
Attack: ${this.attack}
Defense: ${this.defense}
Skill points: ${this.skillPoints}
`);
}
unlockNewAbility() {
const abilities = [
'Fireball',
'Ice Arrow',
'Shield of Power',
'Lightning strike'
];
const abilityIndex = Math.floor(this.level / 5) - 1;
if (abilityIndex < abilities.length) {
console.log(`✨ Ability unlocked: ${abilities[abilityIndex]}`);
}
}
}Visualización del progreso
No basta con almacenar números, los jugadores necesitan ver su progreso. Vamos a crear una barra de progreso simple:
class ProgressBar {
static draw(current, required, width = 20) {
const percentage = current / required;
const filledWidth = Math.floor(percentage * width);
const emptyWidth = width - filledWidth;
const filled = '█'.repeat(filledWidth);
const empty = '░'.repeat(emptyWidth);
const percentText = Math.floor(percentage * 100);
return `[${filled}${empty}] ${percentText}% (${current}/${required})`;
}
}
const player = new Player();
console.log('Experience:', ProgressBar.draw(player.experience, player.experienceToNextLevel));
player.gainExperience(75);
console.log('Experience:', ProgressBar.draw(player.experience, player.experienceToNextLevel));Para los juegos web, puedes usar HTML y CSS para crear barras de progreso más bonitas. Aquí tienes un ejemplo rápido:
class UIManager {
static updateExpBar(player) {
const percentage = (player.experience / player.experienceToNextLevel) * 100;
const expBar = document.getElementById('exp-bar');
const expText = document.getElementById('exp-text');
expBar.style.width = `${percentage}%`;
expText.textContent = `${player.experience} / ${player.experienceToNextLevel} XP`;
}
static showLevelUp(player) {
const notification = document.createElement('div');
notification.className = 'level-up-notification';
notification.textContent = `Level ${player.level}!`;
document.body.appendChild(notification);
// Animación de aparición y desaparición
setTimeout(() => notification.classList.add('show'), 10);
setTimeout(() => {
notification.classList.remove('show');
setTimeout(() => notification.remove(), 300);
}, 2000);
}
}Sistema de prestigio y renacimientos
Muchos juegos modernos utilizan un sistema de prestigio: cuando el jugador alcanza el nivel máximo, puede empezar de nuevo, pero con bonificaciones. Esto añade rejugabilidad:
class PrestigeSystem {
constructor() {
this.prestigeLevel = 0;
this.prestigePoints = 0;
}
canPrestige(player) {
return player.level >= 100;
}
prestige(player) {
if (!this.canPrestige(player)) {
console.log('Insufficient level for prestige!');
return false;
}
this.prestigeLevel++;
this.prestigePoints += Math.floor(player.level / 10);
// Se elimina al jugador, pero se conservan las bonificaciones
const expBonus = 1 + (this.prestigeLevel * 0.1); // +10% de experiencia por cada prestigio
const statBonus = this.prestigeLevel * 5; // +5 a las características iniciales
player.reset(expBonus, statBonus);
console.log(`
🌟 Prestige ${this.prestigeLevel}!
Experience bonus: +${(expBonus - 1) * 100}%
Bonus to characteristics: +${statBonus}
Prestige points: ${this.prestigePoints}
`);
return true;
}
// Mejoras permanentes con puntos de prestigio
buyPermanentUpgrade(upgrade) {
const upgrades = {
'double_xp': { cost: 10, effect: 'Double experience' },
'start_level_10': { cost: 15, effect: 'Start from level 10' },
'bonus_gold': { cost: 20, effect: '+50% gold' }
};
const selected = upgrades[upgrade];
if (!selected) return false;
if (this.prestigePoints >= selected.cost) {
this.prestigePoints -= selected.cost;
console.log(`Purchased: ${selected.effect}`);
return true;
}
return false;
}
}Equilibrio de la progresión
La parte más difícil es equilibrar el sistema correctamente. El jugador debe sentir el progreso, pero no demasiado rápido. Algunos consejos: los primeros cinco niveles deben ser rápidos para atrapar al jugador y mostrar la mecánica. Los niveles intermedios son el contenido principal, aquí el ritmo debe ser cómodo. Los niveles posteriores pueden requerir un gran esfuerzo, lo que crea una sensación de logro.
Es importante probar con jugadores reales. Lo que parece equilibrado para el desarrollador puede ser demasiado rápido o lento para el jugador promedio. Utiliza la analítica para hacer un seguimiento de los niveles en los que los jugadores se atascan o abandonan el juego.
Aquí hay un sistema de registro simple para el análisis:
class Analytics {
static logLevelUp(player, timeSpent) {
const data = {
level: player.level,
timeSpent: timeSpent,
timestamp: new Date().toISOString()
};
// En el juego real, enviamos al servidor
console.log('Analytics:', data);
// Guardar localmente para su análisis
const history = JSON.parse(localStorage.getItem('levelHistory') || '[]');
history.push(data);
localStorage.setItem('levelHistory', JSON.stringify(history));
}
static getAverageLevelTime() {
const history = JSON.parse(localStorage.getItem('levelHistory') || '[]');
if (history.length === 0) return 0;
const total = history.reduce((sum, entry) => sum + entry.timeSpent, 0);
return total / history.length;
}
}Técnicas avanzadas
Los juegos modernos a menudo utilizan varios sistemas de progresión paralelos. Por ejemplo, el nivel del personaje, el nivel de habilidad, la clasificación de combate, el progreso estacional. Cada sistema le da al jugador algo nuevo y mantiene la participación en diferentes etapas del juego. También son populares los objetivos diarios y semanales, que proporcionan experiencia y recompensas adicionales, lo que anima a los jugadores a volver al juego con regularidad.
No te olvides de la retroalimentación. Cada acción del jugador debe mostrar el progreso: números de experiencia, animaciones, efectos de sonido, efectos visuales a medida que aumenta el nivel. Todo esto crea una sensación de satisfacción y motiva a seguir jugando.
Conclusión: El sistema de niveles y progresión es toda una ciencia que combina la programación, el diseño de juegos y la psicología del jugador. Un sistema correctamente implementado mantiene a los jugadores involucrados durante horas, creando el mismo efecto de «un nivel más». Experimenta con fórmulas, prueba con jugadores reales y no tengas miedo de cambiar el equilibrio después del lanzamiento.
🎓 ¡Sigue aprendiendo!
Para estudiar este tema más a fondo, así como dominar el desarrollo de juegos, aplicaciones web y mucho más, puedes Codice — nuestra plataforma educativa con cursos para desarrolladores principiantes.
Y también tenemos un genial canal de Telegram con una comunidad amistosa donde los desarrolladores discuten el código, comparten experiencias y se ayudan mutuamente a crecer.
