Cómo Crear un Minijuego de Cartas en RPG Maker
Crear un minijuego de cartas en RPG Maker requiere JavaScript, diseño de mecánicas y mucho testing. Este artículo documenta cómo está construido «Duelo de Esencias» en Quintaesencia: tablero 3×3, IA con heurísticas, animaciones de vuelo, persistencia de cartas y conexión con el RPG principal.
La mecánica central: tablero 3×3 con tipos de celda
El tablero es una grilla de 3×3 celdas. Cada celda tiene un tipo que determina qué stat se usa en combate: ATQ (Ataque Físico), ATM (Ataque Mágico) o TEC (Técnica). Cuando el jugador coloca una carta en una celda, si hay una carta rival adyacente se resuelve combate inmediatamente.
| Tipo de celda | Stat de ataque | Stat de defensa | Color visual |
|---|---|---|---|
| ATQ (Ataque) | Ataque Físico | Defensa Física | Rojo |
| ATM (Ataque Mágico) | Ataque Mágico | Defensa Mágica | Azul |
| TEC (Técnica) | Técnica | Agilidad | Amarillo |
Cada carta tiene 6 stats numéricos (parámetros 2-7 en RPG Maker): ATQ, DEF, ATM, DFM, TEC y AGI. Un dragón con ATQ 50 pero DEF 10 es fuerte en ataque físico pero vulnerable en defensa. Los jugadores deben construir mazos balanceados considerando estas fortalezas y debilidades.
Sistema de fases: el flujo de un turno
El juego no es un flujo lineal. Hay múltiples fases y transiciones. El código las gestiona con una variable PHASE que indica en qué momento del turno estamos:
| PHASE | Descripción | Duración |
|---|---|---|
| SELECT_CARD | Jugador elige carta de la mano | Hasta click |
| SELECT_CELL | Jugador elige celda del tablero | Hasta click |
| WAITING | Pausa antes del turno de la IA | ~50 frames (0.8s) |
| IA_SELECT / IA_TARGET | La IA «elige» visualmente | ~60 frames (1s) |
| ATTACK_PREVIEW | Muestra stats de combate antes de resolver | 120 frames (2s) |
| GAME_OVER | Partida terminada, muestra resultado | Hasta siguiente acción |
La fase ATTACK_PREVIEW fue añadida después de testing. Sin ella, los combates se resolvían instantáneamente y el usuario no entendía qué había ocurrido. Con 2 segundos de preview mostrando el stat de ataque vs. el stat de defensa, el juego es completamente legible.
Dibujo procedural de cartas
Cada carta se dibuja como un bitmap de 163×185 píxeles generado dinámicamente. No usamos imágenes prehechas porque eso requeriría crear miles de archivos (6 stats × 50 criaturas). En cambio, todo se renderiza proceduralmente con el método _drawCard:
- Fondo coloreado (diferente para jugador y rival)
- Nombre de la criatura (extraído del actor/enemigo de RPG Maker)
- Los 6 stats como números grandes con barras de color
- Icono pequeño si la carta tiene habilidades pasivas
El mismo objeto de carta se dibuja diferente según el contexto:
| Contexto | Stats mostrados |
|---|---|
| Carta en mano | Todos los 6 stats |
| Carta en tablero | Solo defensa del tipo de celda |
| Preview de combate (atacante) | Solo el stat de ataque |
| Preview de combate (defensor) | Solo el stat de defensa relevante |
IA: cómo decide la computadora
La IA no es aleatoria. Evalúa todas las celdas libres con una función de puntuación y elige la mejor opción:
function _iaChooseMove() {
let bestScore = -Infinity;
let bestMove = null;
for (let cellIdx = 0; cellIdx < 9; cellIdx++) { if (!$gameScene._boardState[cellIdx]) { // celda libre let score = 0; // Prioridad máxima: ¿gano el combateif (checkWinsAdjacent(iaCarta, cellIdx)) { score += 100; } // Bonus: buena afinidad de stat con la celda let cellType = $gameScene._boardTypes[cellIdx]; let statForCell = iaCarta.attackByCellType(cellType); if (statForCell > 30) score += 20;
// Penalidad: celda donde la carta es débil
let defForCell = iaCarta.defenseByCellType(cellType);
if (defForCell < 15) score -= 30; if (score > bestScore) {
bestScore = score;
bestMove = cellIdx;
}
}
}
return bestMove;
}
El resultado: la IA juega de manera coherente pero no perfecta. Los jugadores notan que «piensa» y «toma decisiones», lo que hace el juego más inmersivo que si fuera azar puro. La dificultad se varía usando mazos más fuertes para rivales avanzados.
Persistencia: ganar y perder cartas de verdad
El minijuego no está sandboxeado. Las cartas que ganas se añaden a tu inventario permanente; las que pierdes desaparecen. Esto crea tensión real: no puedes simplemente recargar el juego.
// Las cartas del jugador se almacenan en $gameSystem
$gameSystem._dueloCartas = [1, 3, 5, 2, 1, 3];
// Array de IDs (pueden repetirse)
// Ganar una carta
_ganarCarta(cartaId) {
$gameSystem._dueloCartas.push(cartaId);
}
// Perder una carta
_perderCarta(cartaId) {
let idx = $gameSystem._dueloCartas.indexOf(cartaId);
if (idx >= 0) {
$gameSystem._dueloCartas.splice(idx, 1);
}
}
Cuando la partida comienza, se crea una «mano» copiando 6 cartas del inventario global. Al terminar, los cambios se reflejan en $gameSystem._dueloCartas, que persiste con el guardado del juego.
Pasivas: cartas con habilidades especiales
Algunas cartas tienen pasivas que modifican cómo juegan. La arquitectura las soporta aunque no todas están implementadas aún:
- repetirTurno: Después de ganar un combate, obtén turno extra
- bonus_atq / bonus_def: +5 a un stat específico
- bonus_todo: +2 a todos los stats
- sumarTodas: Suma los stats de cartas adyacentes en el tablero
- robarTablero: Si vences, ganas las 3 cartas adyacentes
Las pasivas se evalúan en resolveCombat() antes de comparar stats. Esto crea profundidad estratégica: no gana simplemente la carta con stats más altos, sino la combinación correcta de cartas y pasivas.
Integración con RPG Maker
El minijuego se invoca desde eventos del RPG principal mediante un comando de plugin:
// Registro del comando en el plugin
PluginManager.registerCommand("Angelus_Cartas", "iniciarPartida", args => {
const rivalActorId = parseInt(args.rivalId);
const scene = new Scene_Cartas();
scene.prepare(rivalActorId);
SceneManager.push(scene);
});
// En un evento de RPG Maker:
// Plugin Command: Angelus_Cartas iniciarPartida 5
// → Inicia partida contra el actor con ID 5
Cuando la partida termina, la escena se cierra y el evento puede verificar el resultado consultando $gameSystem._dueloCartas. Así el minijuego se integra con la narrativa: ganar cartas puede desbloquear diálogos, abrir zonas o avanzar la trama.
Lo que hace especial a este minijuego
- Legitimidad estratégica: No es aleatorio. Ganar requiere pensar en tipos de celda y sinergia de cartas.
- Persistencia real: Ganas y pierdes cartas para siempre. Construyes un mazo a lo largo del juego.
- Animaciones legibles: El preview de 2 segundos hace que los combates sean comprensibles. Sin él, sería caos visual.
- IA competente: No es aleatoria, pero tampoco perfecta. El jugador siente que juega contra alguien.
- Integración narrativa: Las cartas que ganas son enemigos que enfrentaste. El duelo es una mini-aventura dentro de la aventura.
Si copias solo la mecánica (tablero + stats + combates) sin estos detalles, obtendrás un minijuego técnicamente funcional pero superficial. Lo que diferencia un minijuego memorable es pulir esos detalles: el preview de combate, la IA coherente, la persistencia real.
Próximas mejoras planeadas
- Implementar todas las pasivas con valores de balance testados
- Estadísticas de juego: tasa de victoria, partidas jugadas, cartas ganadas
- Torneo de cartas: competir contra múltiples rivales en secuencia
- Cartas legendarias con stats extremos y pasivas únicas
- Refactorizar las animaciones para que sean parametrizables y reutilizables
La arquitectura modular está construida para soportar estas extensiones sin reescribir el núcleo del sistema.