User prompt
Quiero que entre un turno completo y otro se mantengan las cartas del mazo de selección tanto del jugador como del rival
User prompt
Define mazo de selección a las 3 cartas que se tienen en el turno completo de las que poder elegir cuál usar
User prompt
Las cartas no usadas entre un turno completo y otro se mantendrán en los mazos de selección tanto del jugador como del mago rival controlado por la IA
User prompt
Las cartas que se dan al jugador al terminar un turno complemento serán las no usadas en su turno y las necesarias para llegar a 3, sin tener dos iguales ni la que usó en su último turno. La lógica del rival será igual, pero con sus cartas y sus turnos
User prompt
Mejora la resolución del asset clase2 para que se vea bien como fondo del segundo curso
User prompt
Usa el asset clase2 en el modo aventura para el segundo curso, ajusta la imagen para que ocupe todo el fondo
User prompt
Cuando termine un turno completo tanto el jugador como la IA mantendrán las cartas que no usaron en sus turnos, y se les dará tantas cartas como sean necesarias para que tengan 3, con las condiciones de que no podrán ser las que les queda ni la carta que usaron en su turno
User prompt
Haz que la carta oxígeno use el asset oxígeno
User prompt
Las 3 cartas que se obtienen al terminar cada turno completo se obtienen de la siguiente forma: cartas que ya tenías + cartas que faltan para llegar a 3 (esta no puede ser una carta que ya tenías, ni la carta usada en tu turno)
User prompt
Define turno del jugador como el turno donde el jugador decide que carta de las 3 que puede elegir usar, salvo que su turno se anule por una carta de la IA. Define turno de la IA como el turno donde la IA decide que carta de las 3 que puede elegir usar. Define turno completo a la acción de haber terminado el turno del jugador y el turno de la IA. Finalmente cuando un turno completo haya terminado ambos jugadores tendrán que tener un total de 3 cartas (las no usadas y completar con otra que no sea las no usadas ni la usada en el turno anterior). En el turno del jugador o el turno de la IA estos solo pueden quedarse sin una carta si el contrario usó pirata (se la ha robado), mechero (le ha quemado una carta, solo si es del elemento hielo) o si ha usado una carta de fuego que tiene la posibilidad de quemar
User prompt
Al terminar un turno completo, entendido como que el turno del jugador y del rival han ocurrido, ya sea usando o no una carta de su mazo de selección, los jugadores deberán tener 3 cartas en el mazo de selección, las que tenía que no usó o no fueron eliminadas y completarse con otra que no sea ninguna de las que no fueron ni usadas ni eliminadas, ni la usada en ese turno
User prompt
Usa el asset clase1 SOLO para el fondo del modo aventura en los TRES primeros niveles. Mejora la calidad para que se vea bien y ocupe todo el fondo
User prompt
Pon el costo del maná en los libros
User prompt
Crea una carte de aire llamada oxígeno que cure 2 de vida. Agrégale el maná que consideres que no sea igual o superior al maná de la carta agua oxigenada
User prompt
Mejora la calidad de la imagen Mazmorra para que el fondo del modo roguelite se vea bien, en vez de pixelado
User prompt
El asset Mazmorra SOLO será el fondo del modo roguelite
User prompt
Usa el asset Mazmorra para el fondo del modo roguelite, ajusta dicha imagen para que ocupe todo el fondo
User prompt
Al inicio de cada turno completo, tanto yo como el mago rival controlado por la IA debemos tener 3 cartas en la mano para elegir
User prompt
En cada turno completo, compuesto por el turno del jugador y del mago rival controlado por la IA, empezará actuando primero o el jugador o la IA, una vez su turno acabe da lugar el turno del contrario, tras esto ese turno completo se dará por finalizado y comenzará el siguiente turno completo, siguiendo la misma lógica y así con todos los demás turnos completos que se den
User prompt
Quiero que las cartas existentes sean infinitas al momento de jugar una batalla, es decir que no puedas quedarte sin estas
User prompt
Quiero que en cada turno completo le toque empezar a un jugador su turno y luego al otro, de forma aleatoria
User prompt
Quiero que en cada turno completo empiece el turno del jugador o del rival controlado por la IA de forma aleatoria
User prompt
Crea una carta del elemento hielo llamada Esquirla Helada, esta quitará 1 de vida, pero a cambio tendrá prioridad. Ponla el maná que consideres en función de ello
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highestLevel: 0,
completedCourses: 0,
currentCourse: 0,
currentBattleInCourse: 0,
playerMaxHealth: 10
});
/****
* Classes
****/
var Card = Container.expand(function (element, damage, name, effect) {
var self = Container.call(this);
self.element = element;
self.damage = damage;
self.name = name || element;
self.effect = effect || 'normal';
self.isUsed = false;
// Card border background (slightly larger than content)
var cardBorder = self.attachAsset('cardBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.05,
scaleY: 1.05,
tint: 0x444444
});
// Card main background
var cardBg = self.attachAsset('cardBase', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(cardBg);
// Use specific card name image if available, otherwise fallback to element graphic
var cardImageId = getCardImageId(self.name);
// TOP HALF: Card design image (scaled to fit top half of card)
var cardDesign = self.attachAsset(cardImageId, {
anchorX: 0.5,
anchorY: 0.5,
y: -105,
// Position in top half
scaleX: 0.93,
scaleY: cardImageId === 'agua_oxigenada' ? 0.32 : 0.5
});
// Get element color
var elementColor = getElementColor(element);
// BOTTOM HALF: Element color background (covers bottom half of card)
var elementColorBg = LK.getAsset('cardBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.93,
scaleY: 0.5,
tint: elementColor
});
elementColorBg.y = 105; // Position in bottom half
self.addChild(elementColorBg);
// Get mana cost for this card
self.manaCost = getCardManaCost(name, effect);
// Create damage/healing text in the format "damage/+heal" or just "damage"
var healAmount = getHealAmount(name, effect);
var damageDisplayText = damage.toString();
if ((effect === 'heal' || effect === 'damageAndHeal' || effect === 'increaseMaxHealth') && healAmount > 0) {
damageDisplayText = damage.toString() + '/+' + healAmount.toString();
}
// Damage/healing text on the element color background
var damageText = new Text2(damageDisplayText, {
size: 48,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif"
});
damageText.anchor.set(0.5, 0.5);
damageText.y = 85; // Position slightly higher to make room for mana cost
// Add dark stroke for better contrast
damageText.stroke = 0x000000;
damageText.strokeThickness = 3;
self.addChild(damageText);
// Mana cost text on the element color background
var manaText = new Text2('⚡' + self.manaCost.toString(), {
size: 36,
fill: 0xFFD700,
font: "'Arial Black', Arial, sans-serif"
});
manaText.anchor.set(0.5, 0.5);
manaText.y = 125; // Position below damage text
manaText.stroke = 0x000000;
manaText.strokeThickness = 3;
self.addChild(manaText);
self.down = function (x, y, obj) {
if (!self.isUsed && gameState === 'playerTurn') {
if (playerMana >= self.manaCost) {
playCard(self);
} else {
// Flash card red to indicate insufficient mana
tween(self, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200
});
}
});
}
}
};
return self;
});
var Enemy = Container.expand(function (name, health, difficulty, battleIndex) {
var self = Container.call(this);
self.name = name;
self.maxHealth = health;
self.health = health;
self.difficulty = difficulty;
self.battleIndex = battleIndex; // Store battle index for wizard assignment
self.isFrozen = false;
self.hasExtraAttack = false;
self.iceBlocked = false;
self.fogFailureChance = 0; // 0 = no fog, 10 = 10% failure chance
self.priorityBlocked = false; // Flag to indicate if enemy's priority is blocked
self.mana = 10;
self.maxMana = 10;
self.deck = createEnemyDeck(difficulty);
self.hand = [];
// Use wizard sprite based on battle index for adventure mode
var wizardSpriteId = 'academy'; // Default fallback
if (gameMode === 'adventure' && typeof battleIndex !== 'undefined') {
// Sequential mapping: battleIndex 0-17 maps to wizard1-wizard18
// Course 1 (battles 0-2): wizard1, wizard2, wizard3
// Course 2 (battles 3-5): wizard4, wizard5, wizard6
// Course 3 (battles 6-8): wizard7, wizard8, wizard9
// Course 4 (battles 9-11): wizard10, wizard11, wizard12
// Course 5 (battles 12-14): wizard13, wizard14, wizard15
// Course 6 (battles 15-17): wizard16, wizard17, wizard18
var wizardNumber = battleIndex + 1; // Direct 1:1 mapping
wizardNumber = Math.max(1, Math.min(wizardNumber, 18)); // Ensure range 1-18
wizardSpriteId = 'wizard' + wizardNumber;
}
var enemyGraphic = self.attachAsset(wizardSpriteId, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
var nameText = new Text2(name, {
size: 50,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -200;
self.addChild(nameText);
var healthText = new Text2('HP: ' + health, {
size: 40,
fill: 0xFFFFFF
});
healthText.anchor.set(0.5, 0.5);
healthText.y = 200;
self.addChild(healthText);
self.healthText = healthText;
self.drawHand = function () {
// Clear existing hand visuals
if (self.handCards) {
for (var j = 0; j < self.handCards.length; j++) {
if (self.handCards[j].parent) {
self.handCards[j].parent.removeChild(self.handCards[j]);
}
}
}
self.handCards = [];
self.hand = [];
var handCardNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (self.deck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * self.deck.length);
var cardData = self.deck[randomIndex];
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < handCardNames.length; j++) {
if (handCardNames[j] === (cardData.name || cardData.element)) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate
if (!isDuplicate) {
self.hand.push(cardData);
// Create visual card for enemy with same design as player cards
var enemyCard = new Card(cardData.element, cardData.damage, cardData.name || cardData.element, cardData.effect || 'normal');
enemyCard.x = -400 + i * 200;
enemyCard.y = -400;
enemyCard.scaleX = 0.6;
enemyCard.scaleY = 0.6;
self.addChild(enemyCard);
self.handCards.push(enemyCard);
handCardNames.push(cardData.name || cardData.element);
foundValidCard = true;
}
attempts++;
}
}
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health < 0) self.health = 0;
self.healthText.setText('HP: ' + self.health);
tween(self, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200
});
}
});
};
self.removeCardFromHand = function (cardIndex) {
if (cardIndex >= 0 && cardIndex < self.hand.length) {
// Remove from hand array
self.hand.splice(cardIndex, 1);
// Remove visual card
if (self.handCards && self.handCards[cardIndex]) {
self.removeChild(self.handCards[cardIndex]);
self.handCards.splice(cardIndex, 1);
}
}
};
self.playTurn = function () {
if (self.isFrozen) {
self.isFrozen = false;
endEnemyTurn();
return;
}
// Check if priority is blocked by Esquirla Helada
if (self.priorityBlocked) {
// Priority blocked - enemy loses turn
self.priorityBlocked = false; // Reset flag
endEnemyTurn();
return;
}
// Check for fog failure
if (self.fogFailureChance > 0 && Math.random() < self.fogFailureChance / 100) {
// Enemy fails turn due to fog
endEnemyTurn();
return;
}
if (self.hand.length > 0) {
// Check if enemy can afford any card
var affordableCards = [];
for (var i = 0; i < self.hand.length; i++) {
var cardCost = getCardManaCost(self.hand[i].name || self.hand[i].element, self.hand[i].effect || 'normal');
if (self.mana >= cardCost) {
affordableCards.push({
card: self.hand[i],
index: i,
cost: cardCost
});
}
}
// If no affordable cards, pass turn to restore mana
if (affordableCards.length === 0) {
self.mana = self.maxMana;
endEnemyTurn();
return;
}
var selectedCard = affordableCards[Math.floor(Math.random() * affordableCards.length)];
var cardIndex = selectedCard.index;
var card = selectedCard.card;
// If ice is blocked, find a non-ice card
if (self.iceBlocked && card.element === 'Ice') {
var nonIceCards = [];
for (var i = 0; i < self.hand.length; i++) {
if (self.hand[i].element !== 'Ice') {
nonIceCards.push({
card: self.hand[i],
index: i
});
}
}
if (nonIceCards.length > 0) {
var randomNonIce = nonIceCards[Math.floor(Math.random() * nonIceCards.length)];
card = randomNonIce.card;
cardIndex = randomNonIce.index;
}
}
// Reset ice block after turn
self.iceBlocked = false;
enemyPlayCard(card, cardIndex);
// Check for extra attack from hombre de nieve effect
if (self.hasExtraAttack && self.hand.length > 0) {
self.hasExtraAttack = false;
// Play another card with damage 1
LK.setTimeout(function () {
if (self.hand.length > 0) {
var extraCardIndex = Math.floor(Math.random() * self.hand.length);
var extraCard = {
element: 'Ice',
damage: 1
};
enemyPlayCard(extraCard, extraCardIndex);
}
}, 500);
}
} else {
endEnemyTurn();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2a1810
});
/****
* Game Code
****/
// Ice card images
// Rock card images
// Plant card images
// Air card images
// Water card images
// Fire card images
// Game state variables
var playerUsedCards = []; // Track cards used in current turn
var enemyUsedCards = []; // Track enemy cards used in current turn
var playerUnavailableCards = []; // Track cards that can't be drawn yet (with turn counters)
var playerShield = null; // Player's shield (Muralla Rocosa)
var playerShieldBar = null; // Shield health bar
var playerShieldText = null; // Shield health text
// Fire card images
// Water card images
// Air card images
// Plant card images
// Rock card images
// Ice card images
// Adventure mode wizard sprites with different colored hats
// Green hat
// Lime green hat
// Lawn green hat
// Green yellow hat
// Yellow hat
// Gold hat
// Orange hat
// Dark orange hat
// Coral hat
// Tomato hat
// Orange red hat
// Red hat
// Crimson hat
// Fire brick hat
// Dark red hat
// Maroon hat
// Golden hat (penultimate)
// Astral purple hat (final)
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
var gameState = 'menu'; // 'menu', 'modeSelect', 'battle', 'victory', 'defeat'
var gameMode = 'adventure'; // 'adventure', 'roguelike'
var roguelikeLevel = storage.highestLevel || 0;
var currentCourse = storage.currentCourse || 0;
var currentBattleInCourse = storage.currentBattleInCourse || 0;
var completedCourses = storage.completedCourses || 0;
// Helper function to map card names to image IDs
function getCardImageId(cardName) {
switch (cardName) {
// Fire cards
case 'Llamarada':
return 'llamarada';
case 'Fénix':
return 'fenix_invocation';
case 'Brasas':
return 'brasas';
case 'Llama':
return 'llama';
case 'Mechero':
return 'mechero';
// Water cards
case 'Gota de agua':
return 'gota_de_agua';
case 'Luna roja':
return 'luna_roja';
case 'Agua oxigenada':
return 'agua_oxigenada';
case 'Marea':
return 'marea';
case 'Pirata':
return 'pirata_invocation';
// Air cards
case 'Vendaval':
return 'vendaval';
case 'Brisa':
return 'brisa';
case 'Huracán':
return 'huracan';
case 'Niebla':
return 'niebla';
case 'Tormenta':
return 'tormenta';
// Plant cards
case 'Arboleda':
return 'arboleda';
case 'Serafín':
return 'serafin_invocation';
case 'Rama':
return 'rama';
case 'Vida extra':
return 'vida_extra';
case 'Aullidos del bosque':
return 'aullidos_del_bosque';
// Rock cards
case 'Pedrada':
return 'pedrada';
case 'Tormenta de arena':
return 'tormenta_de_arena';
case 'Sarcófago':
return 'sarcofago_invocation';
case 'Muralla Rocosa':
return 'muralla_rocosa';
case 'Terremoto':
return 'terremoto';
// Ice cards
case 'Nevada':
return 'nevada';
case 'Ventisca':
return 'ventisca';
case 'Bola de nieve':
return 'bola_de_nieve';
case 'Hombre de nieve':
return 'hombre_de_nieve_invocation';
case 'Esquirla Helada':
return 'esquirla_helada';
default:
return getElementCardId(cardName);
}
}
// Helper function to get fallback element card ID
function getElementCardId(element) {
switch (element) {
case 'Fire':
return 'fireCard';
case 'Water':
return 'waterCard';
case 'Air':
return 'airCard';
case 'Plant':
return 'plantCard';
case 'Rock':
return 'rockCard';
case 'Ice':
return 'iceCard';
default:
return 'cardBase';
}
}
// Helper function to get element colors
function getElementColor(element) {
switch (element) {
case 'Fire':
return 0xff4500;
case 'Water':
return 0x4169e1;
case 'Air':
return 0x87ceeb;
case 'Plant':
return 0x228b22;
case 'Rock':
return 0x696969;
case 'Ice':
return 0xb0e0e6;
default:
return 0xf5f5dc;
}
}
// Helper function to get healing amount for cards
function getHealAmount(cardName, effect) {
switch (cardName) {
case 'Fénix':
return 2;
case 'Agua oxigenada':
return 3;
case 'Serafín':
return 2;
case 'Sarcófago':
return 2;
case 'Vida extra':
return 1;
// Max health increase
default:
return 0;
}
}
// Helper function to get mana cost for cards based on their versatility
function getCardManaCost(cardName, effect) {
switch (cardName) {
// High cost cards (8-10 mana) - very versatile/powerful
case 'Muralla Rocosa':
// Shield with 4 health
return 7;
case 'Terremoto':
// Replaces all cards for both players
return 10;
case 'Huracán':
// Replaces enemy cards
return 8;
case 'Niebla':
// Damage + persistent failure chance
return 4;
case 'Tormenta':
// Damage + chance to skip enemy turn
return 6;
case 'Vida extra':
// Increases max health permanently
return 9;
case 'Aullidos del bosque':
// Damage + skip enemy turn
return 8;
case 'Ventisca':
// Damage + freeze chance
return 7;
// Medium-high cost cards (6-7 mana) - good versatility
case 'Fénix':
// Damage + heal
return 7;
case 'Llamarada':
// High damage + burn card
return 6;
case 'Pirata':
// Damage + steal card
return 6;
case 'Sarcófago':
// Damage + heal
return 6;
case 'Hombre de nieve':
// Damage + extra attack chance
return 6;
case 'Esquirla Helada':
// Priority damage (1 damage with priority)
return 3;
// Medium cost cards (4-5 mana) - moderate versatility
case 'Mechero':
// Damage + prevent ice
return 4;
case 'Nevada':
// Damage + freeze
return 5;
case 'Bola de nieve':
// Damage + freeze
return 4;
case 'Agua oxigenada':
// Pure healing
return 5;
case 'Serafín':
// Pure healing
return 4;
// Low-medium cost cards (2-3 mana) - basic with small effects
case 'Brasas':
// Damage + burn
return 3;
case 'Llama':
// Damage + burn
return 3;
case 'Luna roja':
// Pure damage (2)
return 3;
case 'Vendaval':
// Pure damage (2)
return 3;
case 'Arboleda':
// Pure damage (2)
return 3;
case 'Pedrada':
// Pure damage (2)
return 3;
case 'Tormenta de arena':
// Pure damage (2)
return 3;
case 'Marea':
// Pure damage (2)
return 3;
// Low cost cards (1-2 mana) - basic effects
case 'Gota de agua':
// Pure damage (1)
return 1;
case 'Brisa':
// Pure damage (1)
return 2;
case 'Rama':
// Pure damage (1)
return 1;
// Default costs for generic elements
default:
if (effect === 'heal' || effect === 'damageAndHeal') {
return 5;
} else if (effect === 'replaceCards' || effect === 'replaceAllCards') {
return 8;
} else if (effect === 'skipEnemyTurn' || effect === 'steal') {
return 6;
} else if (effect === 'chooseBurn' || effect === 'preventIce') {
return 4;
} else {
// Basic damage cards
return 2;
}
}
}
// Helper function to play element-specific sounds
function playElementSound(element) {
var soundNumber = Math.floor(Math.random() * 5) + 1;
var soundId = element.toLowerCase() + soundNumber;
LK.getSound(soundId).play();
}
var currentBattle = 0;
var playerHealth = 10;
var playerMaxHealth = 10;
var playerMana = 10;
var playerMaxMana = 10;
var playerDeck = [];
var playerHand = [];
var currentEnemy = null;
var enemies = [];
var turnCounter = 0;
var playerStartsFirst = true; // Track who starts the current turn
// UI elements
var menuContainer = new Container();
var battleContainer = new Container();
var playerHealthBar = null;
var playerHealthText = null;
var playerManaBar = null;
var playerManaText = null;
var passButton = null;
var turnText = null;
var battleText = null;
// Initialize player deck
function initializeDeck() {
var elements = ['Fire', 'Water', 'Air', 'Plant', 'Rock', 'Ice'];
playerDeck = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i] === 'Fire') {
// Add specific fire cards with names and effects
var fireCards = [{
element: 'Fire',
damage: 3,
name: 'Llamarada',
effect: 'chooseBurn'
}, {
element: 'Fire',
damage: 2,
name: 'Fénix',
effect: 'heal'
}, {
element: 'Fire',
damage: 2,
name: 'Brasas',
effect: 'normal'
}, {
element: 'Fire',
damage: 2,
name: 'Llama',
effect: 'normal'
}, {
element: 'Fire',
damage: 1,
name: 'Mechero',
effect: 'preventIce'
}];
for (var k = 0; k < fireCards.length; k++) {
playerDeck.push(fireCards[k]);
}
} else if (elements[i] === 'Air') {
// Add specific air cards with names and effects
var airCards = [{
element: 'Air',
damage: 2,
name: 'Vendaval',
effect: 'normal'
}, {
element: 'Air',
damage: 1,
name: 'Brisa',
effect: 'normal'
}, {
element: 'Air',
damage: 2,
name: 'Huracán',
effect: 'replaceCards'
}, {
element: 'Air',
damage: 3,
name: 'Tormenta',
effect: 'stormSkip'
}, {
element: 'Air',
damage: 1,
name: 'Niebla',
effect: 'fogFailure'
}];
for (var k = 0; k < airCards.length; k++) {
playerDeck.push(airCards[k]);
}
// Air deck now has 5 cards total (including Niebla)
} else if (elements[i] === 'Water') {
// Add specific water cards with names and effects
var waterCards = [{
element: 'Water',
damage: 1,
name: 'Gota de agua',
effect: 'normal'
}, {
element: 'Water',
damage: 2,
name: 'Luna roja',
effect: 'normal'
}, {
element: 'Water',
damage: 0,
name: 'Agua oxigenada',
effect: 'heal'
}, {
element: 'Water',
damage: 2,
name: 'Marea',
effect: 'normal'
}, {
element: 'Water',
damage: 1,
name: 'Pirata',
effect: 'steal'
}];
for (var k = 0; k < waterCards.length; k++) {
playerDeck.push(waterCards[k]);
}
} else if (elements[i] === 'Rock') {
// Add specific rock/earth cards with names and effects
var rockCards = [{
element: 'Rock',
damage: 2,
name: 'Pedrada',
effect: 'normal'
}, {
element: 'Rock',
damage: 2,
name: 'Tormenta de arena',
effect: 'normal'
}, {
element: 'Rock',
damage: 2,
name: 'Sarcófago',
effect: 'damageAndHeal'
}, {
element: 'Rock',
damage: 0,
name: 'Muralla Rocosa',
effect: 'shield'
}, {
element: 'Rock',
damage: 2,
name: 'Terremoto',
effect: 'replaceAllCards'
}];
for (var k = 0; k < rockCards.length; k++) {
playerDeck.push(rockCards[k]);
}
} else if (elements[i] === 'Plant') {
// Add specific plant cards with names and effects
var plantCards = [{
element: 'Plant',
damage: 2,
name: 'Arboleda',
effect: 'normal'
}, {
element: 'Plant',
damage: 0,
name: 'Serafín',
effect: 'heal'
}, {
element: 'Plant',
damage: 1,
name: 'Rama',
effect: 'normal'
}, {
element: 'Plant',
damage: 0,
name: 'Vida extra',
effect: 'increaseMaxHealth'
}, {
element: 'Plant',
damage: 2,
name: 'Aullidos del bosque',
effect: 'skipEnemyTurn'
}];
for (var k = 0; k < plantCards.length; k++) {
playerDeck.push(plantCards[k]);
}
} else if (elements[i] === 'Ice') {
// Add specific ice cards with names and effects
var iceCards = [{
element: 'Ice',
damage: 2,
name: 'Nevada',
effect: 'normal'
}, {
element: 'Ice',
damage: 2,
name: 'Ventisca',
effect: 'blizzard'
}, {
element: 'Ice',
damage: 1,
name: 'Bola de nieve',
effect: 'normal'
}, {
element: 'Ice',
damage: 2,
name: 'Hombre de nieve',
effect: 'snowmanAttack'
}, {
element: 'Ice',
damage: 1,
name: 'Esquirla Helada',
effect: 'priority'
}];
for (var k = 0; k < iceCards.length; k++) {
playerDeck.push(iceCards[k]);
}
} else {
for (var j = 0; j < 5; j++) {
var damage = 1;
playerDeck.push({
element: elements[i],
damage: damage
});
}
}
}
}
function createEnemyDeck(difficulty) {
var deck = [];
var elements = ['Fire', 'Water', 'Air', 'Plant', 'Rock', 'Ice'];
var cardCount = 15 + difficulty * 5;
for (var i = 0; i < cardCount; i++) {
var element = elements[Math.floor(Math.random() * elements.length)];
var damage = 1 + Math.floor(Math.random() * (difficulty + 1));
deck.push({
element: element,
damage: damage
});
}
return deck;
}
function initializeEnemies() {
if (gameMode === 'adventure') {
// Adventure mode: 6 courses with 3 battles each
enemies = [];
var courseNames = ['Apprentice', 'Novice', 'Scholar', 'Expert', 'Master', 'Grandmaster'];
var battleTitles = ['Guard', 'Defender', 'Champion'];
var battleIndex = 0;
for (var course = 0; course < 6; course++) {
for (var battle = 0; battle < 3; battle++) {
var health = 5 + course * 3 + battle * 2; // Increasing health per course and battle
var name = courseNames[course] + ' ' + battleTitles[battle];
enemies.push(new Enemy(name, health, course, battleIndex));
battleIndex++;
}
}
} else {
// Roguelike mode (original)
enemies = [new Enemy('Tutorial Apprentice', 5, 0), new Enemy('Novice Mage', 8, 1), new Enemy('Advanced Scholar', 12, 2), new Enemy('Master Wizard', 15, 3)];
}
}
function createMenu() {
menuContainer.removeChildren();
var bg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
menuContainer.addChild(bg);
// Magical school background
var magicSchool = LK.getAsset('magicSchool', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 900
});
menuContainer.addChild(magicSchool);
// Add magical towers and buildings
var leftTower = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 1,
x: 400,
y: 1200,
scaleX: 0.8,
scaleY: 1.2
});
menuContainer.addChild(leftTower);
var rightTower = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 1,
x: 1648,
y: 1200,
scaleX: 0.8,
scaleY: 1.2
});
menuContainer.addChild(rightTower);
var mainBuilding = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 1,
x: 1024,
y: 1300,
scaleX: 1.5,
scaleY: 1.0
});
menuContainer.addChild(mainBuilding);
var titleText = new Text2('MAGICAL ACADEMY', {
size: 120,
fill: 0xFFD700,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x4B0082,
strokeThickness: 25
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 200;
menuContainer.addChild(titleText);
// Add magical glow effect with pulsing animation
tween(titleText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Create infinite loop by calling the animation again
tween(titleText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 2000,
easing: tween.easeInOut
});
}
});
}
});
}
});
// Add magical color shifting effect
var _colorCycle = function colorCycle() {
tween(titleText, {
tint: 0xFF69B4
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
tint: 0x00FFFF
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
tint: 0xFFD700
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: _colorCycle
});
}
});
}
});
};
_colorCycle();
var adventureButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1450
});
menuContainer.addChild(adventureButton);
var adventureText = new Text2('Adventure Mode', {
size: 50,
fill: 0xFFFFFF
});
adventureText.anchor.set(0.5, 0.5);
adventureText.x = 1024;
adventureText.y = 1450;
menuContainer.addChild(adventureText);
adventureButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
LK.setTimeout(function () {
LK.playMusic('Academia3', {
fade: {
start: 0,
end: 1,
duration: 500
}
});
}, 500);
gameMode = 'adventure';
// Start from the next uncompleted course
currentBattle = completedCourses * 3;
startBattle();
};
var roguelikeButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1650
});
menuContainer.addChild(roguelikeButton);
var roguelikeText = new Text2('Roguelike Mode', {
size: 50,
fill: 0xFFFFFF
});
roguelikeText.anchor.set(0.5, 0.5);
roguelikeText.x = 1024;
roguelikeText.y = 1650;
menuContainer.addChild(roguelikeText);
roguelikeButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
LK.setTimeout(function () {
LK.playMusic('Roguelite', {
fade: {
start: 0,
end: 1,
duration: 500
}
});
}, 500);
gameMode = 'roguelike';
startBattle();
};
if (roguelikeLevel > 0) {
var recordText = new Text2('Roguelike Record: Level ' + roguelikeLevel, {
size: 40,
fill: 0xFFD700
});
recordText.anchor.set(0.5, 0.5);
recordText.x = 1024;
recordText.y = 1850;
menuContainer.addChild(recordText);
}
if (completedCourses > 0) {
var adventureText = new Text2('Adventure Progress: ' + completedCourses + '/6 Courses Completed', {
size: 40,
fill: 0x00FF00
});
adventureText.anchor.set(0.5, 0.5);
adventureText.x = 1024;
adventureText.y = 1900;
menuContainer.addChild(adventureText);
}
// Fire Book Button
var fireBookButton = LK.getAsset('fireCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2100
});
menuContainer.addChild(fireBookButton);
var fireBookText = new Text2('Fire\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
fireBookText.anchor.set(0.5, 0.5);
fireBookText.x = 200;
fireBookText.y = 2100;
menuContainer.addChild(fireBookText);
fireBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Fire');
};
// Water Book Button
var waterBookButton = LK.getAsset('waterCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2100
});
menuContainer.addChild(waterBookButton);
var waterBookText = new Text2('Water\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
waterBookText.anchor.set(0.5, 0.5);
waterBookText.x = 400;
waterBookText.y = 2100;
menuContainer.addChild(waterBookText);
waterBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Water');
};
// Air Book Button
var airBookButton = LK.getAsset('airCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 600,
y: 2100
});
menuContainer.addChild(airBookButton);
var airBookText = new Text2('Air\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
airBookText.anchor.set(0.5, 0.5);
airBookText.x = 600;
airBookText.y = 2100;
menuContainer.addChild(airBookText);
airBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Air');
};
// Plant Book Button
var plantBookButton = LK.getAsset('plantCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2100
});
menuContainer.addChild(plantBookButton);
var plantBookText = new Text2('Plant\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
plantBookText.anchor.set(0.5, 0.5);
plantBookText.x = 800;
plantBookText.y = 2100;
menuContainer.addChild(plantBookText);
plantBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Plant');
};
// Rock Book Button
var rockBookButton = LK.getAsset('rockCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 1000,
y: 2100
});
menuContainer.addChild(rockBookButton);
var rockBookText = new Text2('Rock\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
rockBookText.anchor.set(0.5, 0.5);
rockBookText.x = 1000;
rockBookText.y = 2100;
menuContainer.addChild(rockBookText);
rockBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Rock');
};
// Ice Book Button
var iceBookButton = LK.getAsset('iceCard', {
anchorX: 0.5,
anchorY: 0.5,
x: 1200,
y: 2100
});
menuContainer.addChild(iceBookButton);
var iceBookText = new Text2('Ice\nBook', {
size: 40,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
iceBookText.anchor.set(0.5, 0.5);
iceBookText.x = 1200;
iceBookText.y = 2100;
menuContainer.addChild(iceBookText);
iceBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Ice');
};
// Invocation Cards Book Button
var invocationBookButton = LK.getAsset('fenix_invocation_card', {
anchorX: 0.5,
anchorY: 0.5,
x: 1400,
y: 2100
});
menuContainer.addChild(invocationBookButton);
var invocationBookText = new Text2('Invocation\nBook', {
size: 35,
fill: 0x000000,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xffffff,
strokeThickness: 3
});
invocationBookText.anchor.set(0.5, 0.5);
invocationBookText.x = 1400;
invocationBookText.y = 2100;
menuContainer.addChild(invocationBookText);
invocationBookButton.down = function () {
LK.playMusic('Academia', {
fade: {
start: 1,
end: 0,
duration: 500
}
});
showElementBook('Invocation');
};
game.addChild(menuContainer);
}
function createBattle() {
battleContainer.removeChildren();
// Background
var bg;
if (gameMode === 'roguelike') {
bg = LK.getAsset('Mazmorra', {
anchorX: 0,
anchorY: 0,
scaleX: 20.48,
scaleY: 27.32
});
} else {
bg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
}
battleContainer.addChild(bg);
// Player health
playerHealthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
x: 100,
y: 100
});
battleContainer.addChild(playerHealthBar);
playerHealthText = new Text2('HP: ' + playerHealth + '/' + playerMaxHealth, {
size: 30,
fill: 0xFFFFFF
});
playerHealthText.anchor.set(0, 0.5);
playerHealthText.x = 420;
playerHealthText.y = 120;
battleContainer.addChild(playerHealthText);
// Player mana bar
playerManaBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
x: 100,
y: 200,
tint: 0x0066FF
});
battleContainer.addChild(playerManaBar);
playerManaText = new Text2('⚡: ' + playerMana + '/' + playerMaxMana, {
size: 30,
fill: 0xFFFFFF
});
playerManaText.anchor.set(0, 0.5);
playerManaText.x = 420;
playerManaText.y = 220;
battleContainer.addChild(playerManaText);
// Player shield bar (initially hidden)
playerShieldBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
x: 100,
y: 300,
tint: 0x696969,
alpha: 0
});
battleContainer.addChild(playerShieldBar);
playerShieldText = new Text2('🛡: 0/0', {
size: 30,
fill: 0xFFFFFF
});
playerShieldText.anchor.set(0, 0.5);
playerShieldText.x = 420;
playerShieldText.y = 320;
playerShieldText.alpha = 0;
battleContainer.addChild(playerShieldText);
// Pass turn button
passButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 350,
scaleX: 0.6,
scaleY: 0.6
});
battleContainer.addChild(passButton);
var passText = new Text2('Pass\n(+10 ⚡)', {
size: 25,
fill: 0xFFFFFF
});
passText.anchor.set(0.5, 0.5);
passText.x = 1750;
passText.y = 350;
battleContainer.addChild(passText);
passButton.down = function () {
if (gameState === 'playerTurn') {
// Restore full mana
playerMana = playerMaxMana;
updatePlayerMana();
endPlayerTurn();
}
};
// Exit button to return to menu
var exitButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 150,
scaleX: 0.6,
scaleY: 0.6
});
battleContainer.addChild(exitButton);
var exitText = new Text2('Exit', {
size: 30,
fill: 0xFFFFFF
});
exitText.anchor.set(0.5, 0.5);
exitText.x = 1750;
exitText.y = 150;
battleContainer.addChild(exitText);
exitButton.down = function () {
gameState = 'menu';
game.removeChild(battleContainer);
createMenu();
LK.playMusic('Academia', {
fade: {
start: 0,
end: 1,
duration: 500
}
});
};
// Reset button for adventure mode
if (gameMode === 'adventure') {
var resetButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 250,
scaleX: 0.6,
scaleY: 0.6
});
battleContainer.addChild(resetButton);
var resetText = new Text2('Reset', {
size: 25,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5, 0.5);
resetText.x = 1750;
resetText.y = 250;
battleContainer.addChild(resetText);
resetButton.down = function () {
// Reset adventure progress
completedCourses = 0;
currentBattle = 0;
storage.completedCourses = 0;
storage.currentCourse = 0;
storage.currentBattleInCourse = 0;
// Reset player health
playerHealth = 10;
playerMaxHealth = 10;
// Restart the first battle
gameState = 'menu';
game.removeChild(battleContainer);
createMenu();
LK.playMusic('Academia', {
fade: {
start: 0,
end: 1,
duration: 500
}
});
};
}
// Course and battle indicator for adventure mode
if (gameMode === 'adventure') {
var courseNumber = Math.floor(currentBattle / 3) + 1;
var battleInCourse = currentBattle % 3 + 1;
var courseText = new Text2('Course ' + courseNumber + ' - Battle ' + battleInCourse, {
size: 35,
fill: 0xFFD700
});
courseText.anchor.set(0.5, 0.5);
courseText.x = 1024;
courseText.y = 150;
battleContainer.addChild(courseText);
}
// Turn indicator
turnText = new Text2('Your Turn - Turn 1', {
size: 40,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0.5);
turnText.x = 1024;
turnText.y = 200;
battleContainer.addChild(turnText);
// Battle text (removed course/battle display for adventure mode)
if (gameMode === 'roguelike') {
battleText = new Text2('Battle ' + (currentBattle + 1), {
size: 60,
fill: 0xFFFFFF
});
battleText.anchor.set(0.5, 0.5);
battleText.x = 1024;
battleText.y = 300;
battleContainer.addChild(battleText);
}
// Enemy
currentEnemy = enemies[currentBattle];
currentEnemy.x = 1024;
currentEnemy.y = 800;
battleContainer.addChild(currentEnemy);
// Add deck pile (face down)
var deckPile = LK.getAsset('deckPile', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 1800
});
battleContainer.addChild(deckPile);
var deckText = new Text2('Deck', {
size: 30,
fill: 0xFFFFFF
});
deckText.anchor.set(0.5, 0.5);
deckText.x = 1750;
deckText.y = 1950;
battleContainer.addChild(deckText);
game.addChild(battleContainer);
updatePlayerMana();
drawPlayerHand();
currentEnemy.drawHand();
}
function drawPlayerHand() {
// Remove existing hand
for (var i = battleContainer.children.length - 1; i >= 0; i--) {
var child = battleContainer.children[i];
if (child instanceof Card) {
battleContainer.removeChild(child);
}
}
playerHand = [];
var handCardNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (playerDeck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * playerDeck.length);
var cardData = playerDeck[randomIndex];
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < handCardNames.length; j++) {
if (handCardNames[j] === cardData.name) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate
if (!isDuplicate) {
var card = new Card(cardData.element, cardData.damage, cardData.name, cardData.effect);
card.x = 400 + i * 350;
card.y = 1800;
playerHand.push(card);
battleContainer.addChild(card);
handCardNames.push(cardData.name);
foundValidCard = true;
}
attempts++;
}
}
}
}
function playCard(card) {
if (gameState !== 'playerTurn') return;
if (playerMana < card.manaCost) return;
card.isUsed = true;
// Consume mana
playerMana -= card.manaCost;
updatePlayerMana();
LK.getSound('cardPlay').play();
playElementSound(card.element);
// Apply card effects
var damage = card.damage;
var element = card.element;
// Check for priority effect
if (card.effect === 'priority') {
// Priority card - block enemy's next turn priority
currentEnemy.priorityBlocked = true;
}
// Fire element invocation animation
if (element === 'Fire') {
// Create the invoked asset that will fly to the enemy
var invokedAsset = LK.getAsset(getCardImageId(card.name), {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.9
});
// Start at card position
invokedAsset.x = card.x;
invokedAsset.y = card.y;
battleContainer.addChild(invokedAsset);
// Animate the asset flying to the enemy
tween(invokedAsset, {
x: currentEnemy.x,
y: currentEnemy.y,
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Impact effect - flash the asset and make it bigger momentarily
tween(invokedAsset, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0.3,
tint: 0xFFFFFF
}, {
duration: 200,
onFinish: function onFinish() {
// Remove the invoked asset after impact
battleContainer.removeChild(invokedAsset);
// Apply damage and effects after animation
applyFireCardEffects(card, damage);
}
});
}
});
} else {
// Non-fire cards apply effects immediately
applyCardEffects(card, damage, element);
}
}
// Helper function to apply fire card effects after animation
function applyFireCardEffects(card, damage) {
switch (card.effect) {
case 'chooseBurn':
// Llamarada - deal 3 damage and let player choose card to burn
if (currentEnemy.hand.length > 0) {
var burnIndex = Math.floor(Math.random() * currentEnemy.hand.length);
currentEnemy.removeCardFromHand(burnIndex);
}
break;
case 'heal':
// Fénix - deal 2 damage and heal 2 HP
playerHealth = Math.min(playerHealth + 2, playerMaxHealth);
updatePlayerHealth();
break;
case 'preventIce':
// Mechero - deal 1 damage and prevent enemy from using ice cards next turn
currentEnemy.iceBlocked = true;
break;
default:
// Brasas and Llama - deal 2 damage normally
if (currentEnemy.hand.length > 0) {
var burnIndex = Math.floor(Math.random() * currentEnemy.hand.length);
currentEnemy.removeCardFromHand(burnIndex);
}
break;
}
// Apply damage and continue with battle logic
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
finishCardPlay(card);
}
// Helper function to apply non-fire card effects immediately
function applyCardEffects(card, damage, element) {
// Check if this is an entity card that needs invocation animation
var entityCards = ['Fénix', 'Serafín', 'Aullidos del bosque', 'Pirata', 'Sarcófago', 'Hombre de nieve', 'Bola de nieve', 'Pedrada', 'Momia'];
if (entityCards.indexOf(card.name) !== -1) {
invokeEntityCard(card, damage, element);
return;
}
switch (element) {
case 'Water':
// Handle special water card effects
if (card.effect === 'heal') {
// Agua oxigenada - heal 3 HP (no damage)
playerHealth = Math.min(playerHealth + 3, playerMaxHealth);
updatePlayerHealth();
damage = 0; // No damage dealt
} else if (card.effect === 'steal') {
// Pirata - let player choose which card to steal
if (currentEnemy.hand.length > 0 && playerHand.length < 3) {
showCardStealInterface();
return; // Don't continue with normal card play flow yet
}
}
break;
case 'Plant':
// Handle special plant card effects
if (card.effect === 'increaseMaxHealth') {
// Vida extra - increase max health by 1
playerMaxHealth += 1;
updatePlayerHealth();
damage = 0; // No damage dealt
}
// Standard damage for arboleda and rama
break;
case 'Air':
// Handle special air card effects
if (card.effect === 'replaceCards') {
// Huracán - deal 2 damage and replace enemy's 3 cards with random ones from their deck
currentEnemy.drawHand();
} else if (card.effect === 'stormSkip') {
// Tormenta - deal 3 damage and 10% chance enemy can't attack next turn
if (Math.random() < 0.1) {
currentEnemy.isFrozen = true;
}
} else if (card.effect === 'fogFailure') {
// Niebla - deal 1 damage and set persistent 10% failure chance
if (currentEnemy.fogFailureChance === 0) {
currentEnemy.fogFailureChance = 10; // Set 10% failure chance for rest of battle
}
} else {
// Vendaval and Brisa - standard damage without replacing cards
}
break;
case 'Rock':
// Handle special rock card effects
if (card.effect === 'shield') {
// Muralla Rocosa - create shield with 4 health
if (!playerShield) {
playerShield = {
health: 4,
maxHealth: 4
};
updateShieldDisplay();
damage = 0; // No damage dealt
}
} else if (card.effect === 'replaceAllCards') {
// Terremoto - deal 2 damage to enemy and both players get new cards
currentEnemy.drawHand();
drawPlayerHand();
}
// Standard damage for all rock cards
break;
case 'Ice':
// Handle special ice card effects
if (card.effect === 'blizzard') {
// Ventisca - deal 2 damage and 10% chance enemy can't attack next turn
if (Math.random() < 0.1) {
currentEnemy.isFrozen = true;
}
} else {
// Nevada and Bola de nieve - freeze enemy for next turn + damage
currentEnemy.isFrozen = true;
}
break;
}
// Apply damage and finish card play
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
finishCardPlay(card);
}
// Helper function to invoke entity cards with special animations
function invokeEntityCard(card, damage, element) {
var centerX = 1024;
var centerY = 1366;
switch (card.name) {
case 'Fénix':
// Phoenix rises from ashes in center and attacks with fire
var ashes = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.2,
tint: 0x404040,
alpha: 0.8
});
ashes.x = centerX;
ashes.y = centerY;
battleContainer.addChild(ashes);
var phoenix = LK.getAsset('Fenix', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
phoenix.x = centerX;
phoenix.y = centerY;
battleContainer.addChild(phoenix);
// Phoenix emerges from ashes
tween(phoenix, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Phoenix breathes fire at enemy
tween(phoenix, {
rotation: -0.3,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 300,
onFinish: function onFinish() {
// Fire effect towards enemy
var fireBreath = LK.getAsset('llamarada', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0.9
});
fireBreath.x = centerX;
fireBreath.y = centerY;
battleContainer.addChild(fireBreath);
tween(fireBreath, {
x: currentEnemy.x,
y: currentEnemy.y,
scaleX: 1.5,
scaleY: 1.5,
rotation: Math.PI
}, {
duration: 500,
onFinish: function onFinish() {
// White healing aura for player
var healingAura = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFFFFFF,
alpha: 0.3
});
healingAura.x = 1024;
healingAura.y = 1800;
battleContainer.addChild(healingAura);
tween(healingAura, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
battleContainer.removeChild(healingAura);
}
});
// Apply effects
currentEnemy.takeDamage(damage);
playerHealth = Math.min(playerHealth + 2, playerMaxHealth);
updatePlayerHealth();
LK.getSound('damage').play();
// Clean up
battleContainer.removeChild(fireBreath);
battleContainer.removeChild(phoenix);
battleContainer.removeChild(ashes);
finishCardPlay(card);
}
});
}
});
}
});
break;
case 'Serafín':
// Seraph appears facing player and heals with green aura
var seraph = LK.getAsset('serafin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
seraph.x = centerX;
seraph.y = centerY;
battleContainer.addChild(seraph);
tween(seraph, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Green healing aura towards player
var greenAura = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0x00FF00,
alpha: 0.6
});
greenAura.x = 1024;
greenAura.y = 1800;
battleContainer.addChild(greenAura);
tween(greenAura, {
scaleX: 2.5,
scaleY: 2.5,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
battleContainer.removeChild(greenAura);
}
});
// Apply healing
playerHealth = Math.min(playerHealth + 2, playerMaxHealth);
updatePlayerHealth();
LK.getSound('Curar').play();
// Clean up
LK.setTimeout(function () {
battleContainer.removeChild(seraph);
finishCardPlay(card);
}, 800);
}
});
break;
case 'Aullidos del bosque':
// Environment becomes forest with wolf howls and two wolves attack
var forestBg = LK.getAsset('arboleda', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 7.0,
scaleY: 4.0,
alpha: 0
});
forestBg.x = centerX;
forestBg.y = centerY;
battleContainer.addChild(forestBg);
tween(forestBg, {
alpha: 0.7
}, {
duration: 500,
onFinish: function onFinish() {
// Two wolves appear and attack enemy (using Lobos asset without background)
var wolf1 = LK.getAsset('Lobos', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
});
wolf1.x = centerX - 200;
wolf1.y = centerY + 100;
battleContainer.addChild(wolf1);
var wolf2 = LK.getAsset('Lobos', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
});
wolf2.x = centerX + 200;
wolf2.y = centerY + 100;
battleContainer.addChild(wolf2);
// Wolves appear and leap at enemy
tween(wolf1, {
alpha: 1
}, {
duration: 300
});
tween(wolf2, {
alpha: 1
}, {
duration: 300
});
LK.setTimeout(function () {
tween(wolf1, {
x: currentEnemy.x - 100,
y: currentEnemy.y,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600
});
tween(wolf2, {
x: currentEnemy.x + 100,
y: currentEnemy.y,
scaleX: -1.2,
scaleY: 1.2
}, {
duration: 600,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
currentEnemy.isFrozen = true;
LK.getSound('Aullidos').play();
LK.getSound('Aullidos').play(null, 1.5);
// Clean up
LK.setTimeout(function () {
tween(forestBg, {
alpha: 0
}, {
duration: 500
});
battleContainer.removeChild(wolf1);
battleContainer.removeChild(wolf2);
LK.setTimeout(function () {
battleContainer.removeChild(forestBg);
finishCardPlay(card);
}, 500);
}, 800);
}
});
}, 500);
}
});
break;
case 'Pedrada':
// Rock throw appears in center and flies to enemy (reusing snowball animation)
var rock = LK.getAsset('pedrada', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
rock.x = centerX;
rock.y = centerY;
battleContainer.addChild(rock);
tween(rock, {
x: currentEnemy.x,
y: currentEnemy.y,
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
// Impact effect
tween(rock, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
battleContainer.removeChild(rock);
finishCardPlay(card);
}
});
}
});
break;
case 'Pirata':
// Pirate appears and strikes enemy with hook, then offers card steal choice
var pirate = LK.getAsset('Pirata', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
pirate.x = centerX;
pirate.y = centerY;
battleContainer.addChild(pirate);
tween(pirate, {
scaleX: 1.4,
scaleY: 1.4,
alpha: 1
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Pirate swings hook at enemy
tween(pirate, {
x: currentEnemy.x - 150,
y: currentEnemy.y,
rotation: -0.5
}, {
duration: 400,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
// Card steal effect - show interface for player to choose
if (currentEnemy.hand.length > 0 && playerHand.length < 3) {
LK.setTimeout(function () {
showCardStealInterface();
}, 800); // Delay to let pirate animation finish
}
// Clean up
LK.setTimeout(function () {
battleContainer.removeChild(pirate);
finishCardPlay(card);
}, 600);
}
});
}
});
break;
case 'Sarcófago':
// Create sand pile (Arena asset) in center of battle
var sandPile = LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
});
sandPile.x = centerX;
sandPile.y = centerY + 150;
battleContainer.addChild(sandPile);
// Sarcophagus starts buried under sand
var sarcophagus = LK.getAsset('sarcofago', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
sarcophagus.x = centerX;
sarcophagus.y = centerY + 150;
battleContainer.addChild(sarcophagus);
// Sarcophagus emerges from sand pile
tween(sarcophagus, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 1,
y: centerY - 50
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Sarcophagus opens with dramatic effect
tween(sarcophagus, {
scaleX: 1.8,
scaleY: 1.1
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Mummy emerges from the sarcophagus and appears on top of Arena
var mummy = LK.getAsset('Momia', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
mummy.x = centerX;
mummy.y = centerY + 100; // Position on top of Arena asset
battleContainer.addChild(mummy);
// Mummy appears with growing animation
tween(mummy, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Mummy attacks enemy with right hand (slight rotation and movement)
tween(mummy, {
rotation: -0.3,
x: centerX + 50
}, {
duration: 300,
onFinish: function onFinish() {
// Apply damage from mummy's right hand attack
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
// Mummy extends left hand with healing bandages toward player
tween(mummy, {
rotation: 0.3,
x: centerX - 50
}, {
duration: 400,
onFinish: function onFinish() {
// Healing bandages fly from mummy's left hand to player
var healingBandages = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 1.5,
tint: 0xF5DEB3,
alpha: 0.9
});
healingBandages.x = centerX - 50;
healingBandages.y = centerY - 50;
battleContainer.addChild(healingBandages);
// Animate bandages wrapping around player
tween(healingBandages, {
x: 1024,
y: 1800,
scaleX: 1.5,
scaleY: 2.5,
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create green healing aura around player
var greenAura = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
tint: 0x00FF00,
alpha: 0.7
});
greenAura.x = 1024;
greenAura.y = 1800;
battleContainer.addChild(greenAura);
// Green aura pulsing effect
tween(greenAura, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
battleContainer.removeChild(greenAura);
}
});
// Apply healing
playerHealth = Math.min(playerHealth + 2, playerMaxHealth);
updatePlayerHealth();
battleContainer.removeChild(healingBandages);
}
});
// Clean up after complete animation
LK.setTimeout(function () {
battleContainer.removeChild(mummy);
battleContainer.removeChild(sarcophagus);
battleContainer.removeChild(sandPile);
finishCardPlay(card);
}, 1500);
}
});
}
});
}
});
}
});
}
});
break;
case 'Momia':
// Mummy appears on top of Arena asset in battle center
var arenaBase = LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
});
arenaBase.x = centerX;
arenaBase.y = centerY;
battleContainer.addChild(arenaBase);
var mummy = LK.getAsset('Momia', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
mummy.x = centerX;
mummy.y = centerY;
battleContainer.addChild(mummy);
// Mummy appears with growing animation on Arena
tween(mummy, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
LK.getSound('damage').play();
// Clean up
LK.setTimeout(function () {
battleContainer.removeChild(mummy);
battleContainer.removeChild(arenaBase);
finishCardPlay(card);
}, 800);
}
});
break;
case 'Hombre de nieve':
// Snowman appears and throws snowball at enemy
var snowman = LK.getAsset('hombre_de_nieve', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
snowman.x = centerX;
snowman.y = centerY;
battleContainer.addChild(snowman);
tween(snowman, {
scaleX: 1.3,
scaleY: 1.3,
alpha: 1
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Snowman throws snowball
var snowball = LK.getAsset('bola_de_nieve', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
snowball.x = centerX;
snowball.y = centerY;
battleContainer.addChild(snowball);
tween(snowball, {
x: currentEnemy.x,
y: currentEnemy.y,
scaleX: 1.0,
scaleY: 1.0,
rotation: Math.PI * 3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
currentEnemy.hasExtraAttack = true;
LK.getSound('Bola_de_nieve').play();
// Impact effect
tween(snowball, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
battleContainer.removeChild(snowball);
}
});
// Clean up
LK.setTimeout(function () {
battleContainer.removeChild(snowman);
finishCardPlay(card);
}, 800);
}
});
}
});
break;
case 'Bola de nieve':
// Snowball appears in center and flies to enemy (reusing snowman animation)
var snowball = LK.getAsset('bola_de_nieve', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
snowball.x = centerX;
snowball.y = centerY;
battleContainer.addChild(snowball);
tween(snowball, {
x: currentEnemy.x,
y: currentEnemy.y,
scaleX: 1.2,
scaleY: 1.2,
rotation: Math.PI * 3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Apply effects
currentEnemy.takeDamage(damage);
currentEnemy.isFrozen = true;
LK.getSound('Bola_de_nieve').play();
// Impact effect
tween(snowball, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
battleContainer.removeChild(snowball);
finishCardPlay(card);
}
});
}
});
break;
}
}
// Helper function to show card steal interface when Pirata is used
function showCardStealInterface() {
if (currentEnemy.hand.length === 0) return;
// Create steal interface container
var stealContainer = new Container();
// Semi-transparent background
var stealBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
stealContainer.addChild(stealBg);
// Title text
var stealTitleText = new Text2('Choose a card to steal:', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
stealTitleText.anchor.set(0.5, 0.5);
stealTitleText.x = 1024;
stealTitleText.y = 600;
stealContainer.addChild(stealTitleText);
// Display enemy cards in center for selection
var stealCards = [];
for (var i = 0; i < currentEnemy.hand.length; i++) {
var enemyCardData = currentEnemy.hand[i];
var stealCard = new Card(enemyCardData.element, enemyCardData.damage, enemyCardData.name || enemyCardData.element, enemyCardData.effect || 'normal');
stealCard.x = 1024 + (i - 1) * 350; // Center cards around screen center
stealCard.y = 1200;
stealCard.cardIndex = i; // Store original index for removal
// Override down handler for stealing
stealCard.down = function (x, y, obj) {
var selectedIndex = obj.cardIndex;
var stolenCardData = currentEnemy.hand[selectedIndex];
// Remove card from enemy hand
currentEnemy.removeCardFromHand(selectedIndex);
// Add stolen card to player hand
var stolenCard = new Card(stolenCardData.element, stolenCardData.damage, stolenCardData.name || stolenCardData.element, stolenCardData.effect || 'normal');
stolenCard.x = 400 + playerHand.length * 350;
stolenCard.y = 1800;
playerHand.push(stolenCard);
battleContainer.addChild(stolenCard);
// Remove steal interface
game.removeChild(stealContainer);
// Continue with normal card play flow
currentEnemy.takeDamage(1); // Pirata deals 1 damage
LK.getSound('damage').play();
// Check if enemy is defeated
if (currentEnemy.health === 0) {
LK.getSound('victory').play();
currentBattle++;
// Handle victory logic...
if (gameMode === 'roguelike') {
playerHealth = Math.min(playerHealth + 1, 10);
if (currentBattle > roguelikeLevel) {
roguelikeLevel = currentBattle;
storage.highestLevel = roguelikeLevel;
}
} else {
var courseNumber = Math.floor((currentBattle - 1) / 3);
var battleInCourse = (currentBattle - 1) % 3 + 1;
playerHealth = playerMaxHealth;
if (battleInCourse === 3) {
completedCourses = courseNumber + 1;
storage.completedCourses = completedCourses;
showCourseCompletionAnimation(courseNumber + 1);
}
}
updatePlayerHealth();
if (currentBattle >= enemies.length) {
LK.showYouWin();
} else {
LK.setTimeout(function () {
createBattle();
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn 1');
}, 2000);
}
return;
}
// Continue to next turn
endPlayerTurn();
};
stealContainer.addChild(stealCard);
stealCards.push(stealCard);
}
game.addChild(stealContainer);
}
// Helper function for enemy pirata card steal interface
function showEnemyCardStealInterface() {
if (playerHand.length === 0) return;
// Create steal interface container
var enemyStealContainer = new Container();
// Semi-transparent background
var enemyStealBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
enemyStealContainer.addChild(enemyStealBg);
// Title text
var enemyStealTitleText = new Text2('Enemy is choosing a card to steal...', {
size: 60,
fill: 0xFF0000,
stroke: 0x000000,
strokeThickness: 3
});
enemyStealTitleText.anchor.set(0.5, 0.5);
enemyStealTitleText.x = 1024;
enemyStealTitleText.y = 600;
enemyStealContainer.addChild(enemyStealTitleText);
// Display player cards in center (non-interactive)
var displayCards = [];
for (var i = 0; i < playerHand.length; i++) {
var playerCardData = playerHand[i];
var displayCard = new Card(playerCardData.element, playerCardData.damage, playerCardData.name, playerCardData.effect);
displayCard.x = 1024 + (i - 1) * 350;
displayCard.y = 1200;
displayCard.isUsed = true; // Make non-interactive
enemyStealContainer.addChild(displayCard);
displayCards.push(displayCard);
}
game.addChild(enemyStealContainer);
// After 2 seconds, enemy makes selection and removes interface
LK.setTimeout(function () {
// Enemy steals a random card
var stealIndex = Math.floor(Math.random() * playerHand.length);
var stolenCard = playerHand[stealIndex];
var stolenCardData = {
element: stolenCard.element,
damage: stolenCard.damage,
name: stolenCard.name,
effect: stolenCard.effect
};
// Remove from player hand
playerHand.splice(stealIndex, 1);
battleContainer.removeChild(stolenCard);
// Add to enemy hand
currentEnemy.hand.push(stolenCardData);
var enemyCard = new Card(stolenCardData.element, stolenCardData.damage, stolenCardData.name, stolenCardData.effect);
enemyCard.x = -400 + currentEnemy.hand.length * 200 - 200;
enemyCard.y = -400;
enemyCard.scaleX = 0.6;
enemyCard.scaleY = 0.6;
currentEnemy.addChild(enemyCard);
if (!currentEnemy.handCards) currentEnemy.handCards = [];
currentEnemy.handCards.push(enemyCard);
// Remove steal interface
game.removeChild(enemyStealContainer);
}, 2000);
}
// Helper function to finish card play logic
function finishCardPlay(card) {
// Remove card from hand
var cardIndex = playerHand.indexOf(card);
if (cardIndex !== -1) {
playerHand.splice(cardIndex, 1);
}
battleContainer.removeChild(card);
// Add used card to tracking array with turn counter
playerUsedCards.push({
element: card.element,
damage: card.damage,
name: card.name,
effect: card.effect
});
// Check if enemy is defeated (must reach exactly 0 health)
if (currentEnemy.health === 0) {
LK.getSound('victory').play();
currentBattle++;
// Handle victory based on game mode
if (gameMode === 'roguelike') {
// Add 1 health for winning a battle
playerHealth = Math.min(playerHealth + 1, 10);
// Update roguelike progress
if (currentBattle > roguelikeLevel) {
roguelikeLevel = currentBattle;
storage.highestLevel = roguelikeLevel;
}
} else {
// Adventure mode - handle course progression
var courseNumber = Math.floor((currentBattle - 1) / 3);
var battleInCourse = (currentBattle - 1) % 3 + 1;
// Always restore full health after winning any battle in adventure mode
playerHealth = playerMaxHealth;
// If this was the third battle of a course, mark course as completed but don't change max health
if (battleInCourse === 3) {
completedCourses = courseNumber + 1;
storage.completedCourses = completedCourses;
// Course completion animation
showCourseCompletionAnimation(courseNumber + 1);
}
}
// Restore full mana after battle victory
playerMana = playerMaxMana;
updatePlayerMana();
// Update player health display after victory
updatePlayerHealth();
if (currentBattle >= enemies.length) {
// All battles won
LK.showYouWin();
} else {
// Next battle
LK.setTimeout(function () {
createBattle();
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn 1');
}, 2000);
}
return;
}
endPlayerTurn();
}
function endPlayerTurn() {
// Clear player used cards for this turn (don't return to deck yet)
playerUsedCards = [];
// Always give enemy their turn after player turn
gameState = 'enemyTurn';
turnText.setText('Enemy Turn - Turn ' + turnCounter);
LK.setTimeout(function () {
currentEnemy.playTurn();
}, 1000);
}
function enemyPlayCard(cardData, cardIndex) {
// Consume enemy mana
var manaCost = getCardManaCost(cardData.name || cardData.element, cardData.effect || 'normal');
currentEnemy.mana -= manaCost;
playElementSound(cardData.element);
var damage = cardData.damage;
var element = cardData.element;
// Track used card before removing
enemyUsedCards.push({
element: cardData.element,
damage: cardData.damage,
name: cardData.name || cardData.element,
effect: cardData.effect || 'normal'
});
// Remove the played card from enemy hand
currentEnemy.removeCardFromHand(cardIndex);
// Check for snowman effect - hombre de nieve deals 2 damage and sets up future 1 damage
if (cardData.name === 'Hombre de nieve') {
// Deal 2 damage now
playerHealth -= 2;
// Set up 10% chance for 1 damage next turn
currentEnemy.snowmanPendingDamage = true;
} else {
// Check if there's pending snowman damage from previous turn
if (currentEnemy.snowmanPendingDamage) {
if (Math.random() < 0.1) {
// 10% chance to deal 1 additional damage
playerHealth -= 1;
}
// Reset the pending damage flag
currentEnemy.snowmanPendingDamage = false;
}
switch (element) {
case 'Fire':
// Fire burns one random player card + damage
if (playerHand.length > 0) {
var burnIndex = Math.floor(Math.random() * playerHand.length);
var cardToBurn = playerHand[burnIndex];
playerHand.splice(burnIndex, 1);
battleContainer.removeChild(cardToBurn);
}
damage += 2;
break;
case 'Water':
// Handle water card effects
if (cardData.effect === 'steal') {
// Pirata - enemy shows card steal interface
if (playerHand.length > 0 && currentEnemy.hand.length < 3) {
showEnemyCardStealInterface();
return; // Don't continue with normal enemy turn flow yet
}
}
break;
case 'Air':
drawPlayerHand();
break;
case 'Ice':
// Player frozen (skip next turn - handled in game flow)
break;
}
// Apply damage through shield first
if (playerShield && playerShield.health > 0 && damage > 0) {
var shieldAbsorbed = Math.min(damage, playerShield.health);
playerShield.health -= shieldAbsorbed;
damage -= shieldAbsorbed;
updateShieldDisplay();
if (damage > 0) {
playerHealth -= damage;
}
} else if (damage > 0) {
playerHealth -= damage;
}
}
if (playerHealth < 0) playerHealth = 0;
updatePlayerHealth();
LK.getSound('damage').play();
if (playerHealth === 0) {
// In roguelike mode, track the level where player died
if (gameMode === 'roguelike' && currentBattle > roguelikeLevel) {
roguelikeLevel = currentBattle;
storage.highestLevel = roguelikeLevel;
}
// Reset mana to full when battle ends
playerMana = playerMaxMana;
updatePlayerMana();
LK.showGameOver();
return;
}
endEnemyTurn();
}
function endEnemyTurn() {
// Clear enemy used cards for this turn (no need to return to deck since infinite)
enemyUsedCards = [];
// Check if this is the end of a complete turn (both players have played)
// If enemy started first, complete turn ends here
// If player started first, we need to give player their turn
if (!playerStartsFirst) {
// Enemy started first, now it's player's turn to complete the turn
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn ' + turnCounter);
} else {
// Player started first and enemy just finished, complete turn ends here
// Complete turn cycle - both player and enemy have played, now start new complete turn
turnCounter++;
// Restore mana after complete turn cycle (except first turn)
if (turnCounter > 1) {
// Restore 3-5 mana for player, but never exceed max
var manaToRestore = 3 + Math.floor(Math.random() * 3); // Random between 3-5
playerMana = Math.min(playerMana + manaToRestore, playerMaxMana);
// Restore 3-5 mana for enemy, but never exceed max
var enemyManaToRestore = 3 + Math.floor(Math.random() * 3); // Random between 3-5
currentEnemy.mana = Math.min(currentEnemy.mana + enemyManaToRestore, currentEnemy.maxMana);
updatePlayerMana();
}
// Clear all remaining cards from both hands to start fresh
// Clear player hand
for (var i = playerHand.length - 1; i >= 0; i--) {
var card = playerHand[i];
battleContainer.removeChild(card);
}
playerHand = [];
// Clear enemy hand
if (currentEnemy.handCards) {
for (var i = 0; i < currentEnemy.handCards.length; i++) {
if (currentEnemy.handCards[i].parent) {
currentEnemy.handCards[i].parent.removeChild(currentEnemy.handCards[i]);
}
}
}
currentEnemy.handCards = [];
currentEnemy.hand = [];
// PLAYER CARD REDISTRIBUTION FOR NEW COMPLETE TURN - Always draw 3 unique cards
var playerHandNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (playerDeck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * playerDeck.length);
var cardData = playerDeck[randomIndex];
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < playerHandNames.length; j++) {
if (playerHandNames[j] === cardData.name) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate (cards are infinite, so no availability check)
if (!isDuplicate) {
var card = new Card(cardData.element, cardData.damage, cardData.name, cardData.effect);
card.x = 400 + i * 350;
card.y = 1800;
playerHand.push(card);
battleContainer.addChild(card);
playerHandNames.push(cardData.name);
foundValidCard = true;
}
attempts++;
}
}
}
// ENEMY CARD REDISTRIBUTION FOR NEW COMPLETE TURN - Always draw 3 unique cards
var enemyHandNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (currentEnemy.deck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * currentEnemy.deck.length);
var cardData = currentEnemy.deck[randomIndex];
var cardName = cardData.name || cardData.element;
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < enemyHandNames.length; j++) {
if (enemyHandNames[j] === cardName) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate (cards are infinite, so no deck removal)
if (!isDuplicate) {
currentEnemy.hand.push(cardData);
// Create visual card for enemy
var enemyCard = new Card(cardData.element, cardData.damage, cardData.name || cardData.element, cardData.effect || 'normal');
enemyCard.x = -400 + i * 200;
enemyCard.y = -400;
enemyCard.scaleX = 0.6;
enemyCard.scaleY = 0.6;
currentEnemy.addChild(enemyCard);
if (!currentEnemy.handCards) currentEnemy.handCards = [];
currentEnemy.handCards.push(enemyCard);
enemyHandNames.push(cardName);
foundValidCard = true;
}
attempts++;
}
}
}
// Clear all remaining cards from both hands to start fresh
// Clear player hand
for (var i = playerHand.length - 1; i >= 0; i--) {
var card = playerHand[i];
battleContainer.removeChild(card);
}
playerHand = [];
// Clear enemy hand
if (currentEnemy.handCards) {
for (var i = 0; i < currentEnemy.handCards.length; i++) {
if (currentEnemy.handCards[i].parent) {
currentEnemy.handCards[i].parent.removeChild(currentEnemy.handCards[i]);
}
}
}
currentEnemy.handCards = [];
currentEnemy.hand = [];
// PLAYER CARD REDISTRIBUTION FOR NEW COMPLETE TURN - Always draw 3 unique cards
var playerHandNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (playerDeck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * playerDeck.length);
var cardData = playerDeck[randomIndex];
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < playerHandNames.length; j++) {
if (playerHandNames[j] === cardData.name) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate (cards are infinite, so no availability check)
if (!isDuplicate) {
var card = new Card(cardData.element, cardData.damage, cardData.name, cardData.effect);
card.x = 400 + i * 350;
card.y = 1800;
playerHand.push(card);
battleContainer.addChild(card);
playerHandNames.push(cardData.name);
foundValidCard = true;
}
attempts++;
}
}
}
// ENEMY CARD REDISTRIBUTION FOR NEW COMPLETE TURN - Always draw 3 unique cards
var enemyHandNames = []; // Track card names to prevent duplicates
for (var i = 0; i < 3; i++) {
if (currentEnemy.deck.length > 0) {
var attempts = 0;
var foundValidCard = false;
while (attempts < 50 && !foundValidCard) {
// Limit attempts to prevent infinite loop
var randomIndex = Math.floor(Math.random() * currentEnemy.deck.length);
var cardData = currentEnemy.deck[randomIndex];
var cardName = cardData.name || cardData.element;
// Check if this card name is already in hand
var isDuplicate = false;
for (var j = 0; j < enemyHandNames.length; j++) {
if (enemyHandNames[j] === cardName) {
isDuplicate = true;
break;
}
}
// Use card if it's not a duplicate (cards are infinite, so no deck removal)
if (!isDuplicate) {
currentEnemy.hand.push(cardData);
// Create visual card for enemy
var enemyCard = new Card(cardData.element, cardData.damage, cardData.name || cardData.element, cardData.effect || 'normal');
enemyCard.x = -400 + i * 200;
enemyCard.y = -400;
enemyCard.scaleX = 0.6;
enemyCard.scaleY = 0.6;
currentEnemy.addChild(enemyCard);
if (!currentEnemy.handCards) currentEnemy.handCards = [];
currentEnemy.handCards.push(enemyCard);
enemyHandNames.push(cardName);
foundValidCard = true;
}
attempts++;
}
}
}
// Randomly determine who starts the new complete turn
playerStartsFirst = Math.random() < 0.5;
if (playerStartsFirst) {
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn ' + turnCounter);
} else {
gameState = 'enemyTurn';
turnText.setText('Enemy Turn - Turn ' + turnCounter);
// Start enemy turn after a delay
LK.setTimeout(function () {
currentEnemy.playTurn();
}, 1000);
}
}
}
function updatePlayerHealth() {
var healthPercentage = playerHealth / playerMaxHealth;
playerHealthBar.scaleX = healthPercentage;
playerHealthText.setText('HP: ' + playerHealth + '/' + playerMaxHealth);
}
function updatePlayerMana() {
var manaPercentage = playerMana / playerMaxMana;
playerManaBar.scaleX = manaPercentage;
playerManaText.setText('⚡: ' + playerMana + '/' + playerMaxMana);
}
function updateShieldDisplay() {
if (playerShield && playerShield.health > 0) {
var shieldPercentage = playerShield.health / playerShield.maxHealth;
playerShieldBar.scaleX = shieldPercentage;
playerShieldBar.alpha = 1;
playerShieldText.setText('🛡: ' + playerShield.health + '/' + playerShield.maxHealth);
playerShieldText.alpha = 1;
} else {
playerShieldBar.alpha = 0;
playerShieldText.alpha = 0;
playerShield = null;
}
}
function startBattle() {
gameState = 'battle';
if (gameMode === 'adventure') {
// Start from first uncompleted battle
currentBattle = completedCourses * 3;
// Set health based on last completed course's final wizard
if (completedCourses > 0) {
// Get the last wizard from the previous completed course
var lastCompletedCourse = completedCourses - 1;
var lastWizardIndex = lastCompletedCourse * 3 + 2; // Third wizard of the course (index 2)
if (lastWizardIndex < enemies.length) {
var lastWizard = enemies[lastWizardIndex];
playerHealth = lastWizard.maxHealth;
playerMaxHealth = lastWizard.maxHealth;
// Store the max health for future reference
storage.playerMaxHealth = playerMaxHealth;
} else {
playerHealth = 10;
playerMaxHealth = 10;
}
} else {
// First course - start with default health
playerHealth = 10;
playerMaxHealth = 10;
}
} else {
// Roguelike mode
currentBattle = 0;
playerHealth = 10;
playerMaxHealth = 10;
}
turnCounter = 0;
playerMana = playerMaxMana;
// Randomly determine who starts first
playerStartsFirst = Math.random() < 0.5;
game.removeChild(menuContainer);
createBattle();
// Ensure both players have 3 cards at start
drawPlayerHand();
currentEnemy.drawHand();
// Set initial game state based on random turn order
if (playerStartsFirst) {
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn 1');
} else {
gameState = 'enemyTurn';
turnText.setText('Enemy Turn - Turn 1');
// Start enemy turn after a delay
LK.setTimeout(function () {
currentEnemy.playTurn();
}, 1000);
}
}
function showElementBook(element) {
// Create book container
var bookContainer = new Container();
// Background
var bookBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
bookContainer.addChild(bookBg);
// Title
var titleText = new Text2(element + ' Element Cards', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
bookContainer.addChild(titleText);
// Get element cards based on element type
var elementCards = [];
switch (element) {
case 'Fire':
elementCards = [{
name: 'Llamarada',
damage: 3,
effect: 'Inflige 3 de daño y quema una carta enemiga'
}, {
name: 'Fénix',
damage: 2,
effect: 'Inflige 2 de daño y cura 2 puntos de vida'
}, {
name: 'Brasas',
damage: 2,
effect: 'Inflige 2 de daño y quema una carta enemiga'
}, {
name: 'Llama',
damage: 2,
effect: 'Inflige 2 de daño y quema una carta enemiga'
}, {
name: 'Mechero',
damage: 1,
effect: 'Inflige 1 de daño y evita que el enemigo use cartas de hielo'
}];
break;
case 'Water':
elementCards = [{
name: 'Gota de agua',
damage: 1,
effect: 'Inflige 1 de daño'
}, {
name: 'Luna roja',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Agua oxigenada',
damage: 0,
effect: 'Cura 3 puntos de vida'
}, {
name: 'Marea',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Pirata',
damage: 1,
effect: 'Inflige 1 de daño y roba una carta enemiga'
}];
break;
case 'Air':
elementCards = [{
name: 'Vendaval',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Brisa',
damage: 1,
effect: 'Inflige 1 de daño'
}, {
name: 'Huracán',
damage: 2,
effect: 'Inflige 2 de daño y reemplaza las cartas enemigas'
}, {
name: 'Tormenta',
damage: 3,
effect: 'Inflige 3 de daño, 10% de probabilidad de saltar turno enemigo'
}, {
name: 'Niebla',
damage: 1,
effect: 'Inflige 1 de daño, 10% de fallo permanente en turnos enemigos'
}];
break;
case 'Plant':
elementCards = [{
name: 'Arboleda',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Serafín',
damage: 0,
effect: 'Cura 2 puntos de vida'
}, {
name: 'Rama',
damage: 1,
effect: 'Inflige 1 de daño'
}, {
name: 'Vida extra',
damage: 0,
effect: 'Aumenta la vida máxima en 1'
}, {
name: 'Aullidos del bosque',
damage: 2,
effect: 'Inflige 2 de daño, el enemigo pierde su turno'
}];
break;
case 'Rock':
elementCards = [{
name: 'Pedrada',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Tormenta de arena',
damage: 2,
effect: 'Inflige 2 de daño'
}, {
name: 'Sarcófago',
damage: 2,
effect: 'Inflige 2 de daño y cura 2 puntos de vida'
}, {
name: 'Muralla Rocosa',
damage: 0,
effect: 'Crea escudo con 4 puntos de vida que absorbe daño'
}, {
name: 'Terremoto',
damage: 2,
effect: 'Inflige 2 de daño, ambos jugadores obtienen cartas nuevas'
}];
break;
case 'Ice':
elementCards = [{
name: 'Nevada',
damage: 2,
effect: 'Inflige 2 de daño y congela al enemigo'
}, {
name: 'Ventisca',
damage: 2,
effect: 'Inflige 2 de daño, 10% de probabilidad de congelar'
}, {
name: 'Bola de nieve',
damage: 1,
effect: 'Inflige 1 de daño y congela al enemigo'
}, {
name: 'Hombre de nieve',
damage: 2,
effect: 'Inflige 2 de daño, puede atacar de nuevo por 1 de daño'
}, {
name: 'Esquirla Helada',
damage: 1,
effect: 'Inflige 1 de daño con prioridad, el enemigo pierde su próximo turno'
}];
break;
case 'Invocation':
elementCards = [{
name: 'Fénix',
damage: 2,
effect: 'Inflige 2 de daño y cura 2 puntos de vida'
}, {
name: 'Pirata',
damage: 1,
effect: 'Inflige 1 de daño y roba una carta enemiga'
}, {
name: 'Serafín',
damage: 0,
effect: 'Cura 2 puntos de vida'
}, {
name: 'Sarcófago',
damage: 2,
effect: 'Inflige 2 de daño y cura 2 puntos de vida'
}, {
name: 'Hombre de nieve',
damage: 2,
effect: 'Inflige 2 de daño, puede atacar de nuevo por 1 de daño'
}];
break;
}
// Display cards
for (var i = 0; i < elementCards.length; i++) {
var cardInfo = elementCards[i];
var yPos = 500 + i * 320;
// Card name
var nameText = new Text2(cardInfo.name, {
size: 65,
fill: 0xffffff,
stroke: 0xffffff,
strokeThickness: 3
});
nameText.anchor.set(0, 0.5);
nameText.x = 200;
nameText.y = yPos;
bookContainer.addChild(nameText);
// Damage
var damageText = new Text2('Daño: ' + cardInfo.damage, {
size: 55,
fill: 0xffffff,
stroke: 0xffffff,
strokeThickness: 3
});
damageText.anchor.set(0, 0.5);
damageText.x = 200;
damageText.y = yPos + 60;
bookContainer.addChild(damageText);
// Effect
var effectText = new Text2('Efecto: ' + cardInfo.effect, {
size: 50,
fill: 0xffffff,
stroke: 0xffffff,
strokeThickness: 3
});
effectText.anchor.set(0, 0.5);
effectText.x = 200;
effectText.y = yPos + 120;
bookContainer.addChild(effectText);
}
// Back button
var backButton = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
});
bookContainer.addChild(backButton);
var backText = new Text2('Back to Menu', {
size: 40,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2400;
bookContainer.addChild(backText);
backButton.down = function () {
game.removeChild(bookContainer);
LK.playMusic('Academia', {
fade: {
start: 0,
end: 1,
duration: 500
}
});
};
game.addChild(bookContainer);
}
function showCourseCompletionAnimation(courseNumber) {
// Create animation container
var animContainer = new Container();
// Semi-transparent background
var animBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
animContainer.addChild(animBg);
// Course completed text
var completionText = new Text2('COURSE ' + courseNumber + ' COMPLETED!', {
size: 80,
fill: 0xFFD700,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x4B0082,
strokeThickness: 4
});
completionText.anchor.set(0.5, 0.5);
completionText.x = 1024;
completionText.y = 1366;
completionText.alpha = 0;
completionText.scaleX = 0.1;
completionText.scaleY = 0.1;
animContainer.addChild(completionText);
// Star effects
var stars = [];
for (var i = 0; i < 5; i++) {
var star = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xFFD700
});
star.x = 1024 + (i - 2) * 200;
star.y = 1000;
star.alpha = 0;
star.rotation = 0;
animContainer.addChild(star);
stars.push(star);
}
game.addChild(animContainer);
// Animate text appearance
tween(completionText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.elasticOut
});
// Animate stars
for (var i = 0; i < stars.length; i++) {
(function (star, delay) {
LK.setTimeout(function () {
tween(star, {
alpha: 1,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut
});
}, delay);
})(stars[i], i * 150);
}
// Pulsing effect
LK.setTimeout(function () {
tween(completionText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(completionText, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}, 1000);
// Remove animation after 3 seconds
LK.setTimeout(function () {
tween(animContainer, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
game.removeChild(animContainer);
// Check if all courses completed for graduation
if (completedCourses >= 6) {
showGraduationAnimation();
}
}
});
}, 3000);
}
function showGraduationAnimation() {
// Create graduation container
var gradContainer = new Container();
// Background
var gradBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
tint: 0x000050
});
gradContainer.addChild(gradBg);
// Graduation text
var gradText = new Text2('GRADUATION!', {
size: 120,
fill: 0xFFD700,
font: "'Arial Black', Arial, sans-serif",
stroke: 0xFFFFFF,
strokeThickness: 6
});
gradText.anchor.set(0.5, 0.5);
gradText.x = 1024;
gradText.y = 1000;
gradText.alpha = 0;
gradText.scaleX = 0.1;
gradText.scaleY = 0.1;
gradContainer.addChild(gradText);
// Congratulations text
var congratsText = new Text2('¡Congratulations, Master Wizard!', {
size: 60,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif"
});
congratsText.anchor.set(0.5, 0.5);
congratsText.x = 1024;
congratsText.y = 1200;
congratsText.alpha = 0;
gradContainer.addChild(congratsText);
// Academy building as graduation cap
var academy = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
tint: 0xFFD700
});
academy.x = 1024;
academy.y = 600;
academy.alpha = 0;
academy.rotation = -Math.PI / 4;
gradContainer.addChild(academy);
// Fireworks effects
var fireworks = [];
for (var i = 0; i < 8; i++) {
var firework = LK.getAsset('academy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFD700, 0xFF4500][i]
});
var angle = i / 8 * Math.PI * 2;
firework.x = 1024 + Math.cos(angle) * 400;
firework.y = 1366 + Math.sin(angle) * 400;
firework.alpha = 0;
firework.scaleX = 0.1;
firework.scaleY = 0.1;
gradContainer.addChild(firework);
fireworks.push(firework);
}
game.addChild(gradContainer);
// Animate academy
tween(academy, {
alpha: 1,
rotation: 0
}, {
duration: 1000,
easing: tween.elasticOut
});
// Animate main text
LK.setTimeout(function () {
tween(gradText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 1200,
easing: tween.bounceOut
});
}, 500);
// Animate congratulations text
LK.setTimeout(function () {
tween(congratsText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
}, 1500);
// Animate fireworks
LK.setTimeout(function () {
for (var i = 0; i < fireworks.length; i++) {
(function (firework, delay) {
LK.setTimeout(function () {
tween(firework, {
alpha: 1,
scaleX: 0.5,
scaleY: 0.5,
rotation: Math.PI * 4
}, {
duration: 1000,
easing: tween.easeOut
});
}, delay);
})(fireworks[i], i * 100);
}
}, 2000);
// Continuous celebration effects
function celebrationPulse() {
tween(gradText, {
scaleX: 1.1,
scaleY: 1.1,
tint: 0xFF69B4
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(gradText, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: celebrationPulse
});
}
});
}
LK.setTimeout(celebrationPulse, 3000);
// Remove animation after 8 seconds
LK.setTimeout(function () {
tween(gradContainer, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(gradContainer);
}
});
}, 8000);
}
// Initialize game
initializeDeck();
initializeEnemies();
createMenu();
// Play menu music with fade in
LK.playMusic('Academia', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
game.update = function () {
// Game loop handled by turn-based system
}; ===================================================================
--- original.js
+++ change.js
@@ -1327,14 +1327,22 @@
}
function createBattle() {
battleContainer.removeChildren();
// Background
- var bg = LK.getAsset('Mazmorra', {
- anchorX: 0,
- anchorY: 0,
- scaleX: 20.48,
- scaleY: 27.32
- });
+ var bg;
+ if (gameMode === 'roguelike') {
+ bg = LK.getAsset('Mazmorra', {
+ anchorX: 0,
+ anchorY: 0,
+ scaleX: 20.48,
+ scaleY: 27.32
+ });
+ } else {
+ bg = LK.getAsset('background', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ }
battleContainer.addChild(bg);
// Player health
playerHealthBar = LK.getAsset('healthBar', {
anchorX: 0,
Un bote de agua oxigenada. In-Game asset. 2d. High contrast. No shadows
Pila de cartas mágicas bocabajo. In-Game asset. 2d. High contrast. No shadows
Barra de vida. In-Game asset. 2d. High contrast. No shadows
Botón de videojuegos sin nada escrito. In-Game asset. 2d. High contrast. No shadows
Hombre de nieve con pipa y manos de ramas y tres botones negros verticalmente algo realista. In-Game asset. 2d. High contrast. No shadows
Llama fuego, algo realista. In-Game asset. 2d. High contrast. No shadows
Luna roja sobre cielo nocturno, sin bordes y algo realista, que se aprecie el fondo. In-Game asset. 2d. High contrast. No shadows
Terremoto, algo realista. In-Game asset. 2d. High contrast. No shadows
Howgarts, algo realista. In-Game asset. 2d. High contrast. No shadows
Noche estrellada, algo realista. In-Game asset. 2d. High contrast. No shadows
Marea, algo realista, sin nombre. In-Game asset. 2d. High contrast. No shadows
Mechero encendido, algo realista. In-Game asset. 2d. High contrast. No shadows
Nevada, evento atmosférico, algo realista. In-Game asset. 2d. High contrast. No shadows
Arboleda, con fondo, cielo nocturno, algo realista. In-Game asset. 2d. High contrast. No shadows
Aullidos del bosque, algo realista. In-Game asset. 2d. High contrast. No shadows
Bola de nieve, algo realista. In-Game asset. 2d. High contrast. No shadows
Brasas con llama, algo realista. In-Game asset. 2d. High contrast. No shadows
Fénix envuelto en llamas mirando al frente, algo realista, pero no poner un pájaro rojo cualquiera. In-Game asset. 2d. High contrast. No shadows
Pedrada, algo realista. In-Game asset. 2d. High contrast. No shadows
Pirata con sombrero pirata y garfio, en barco pirata, navegando sobre el mar en una noche estrellada, algo realista, pero fuera de lo caricaturesco. In-Game asset. 2d. High contrast. No shadows
Rama, algo realista. In-Game asset. 2d. High contrast. No shadows
Sarcófago, algo realista. In-Game asset. 2d. High contrast. No shadows
Tormenta de arena, algo realista. In-Game asset. 2d. High contrast. No shadows
Vendaval, algo realista. In-Game asset. 2d. High contrast. No shadows
Ventisca, algo realista. In-Game asset. 2d. High contrast. No shadows
Vida extra, algo realista. In-Game asset. 2d. High contrast. No shadows
Mago astral. In-Game asset. 2d. High contrast. No shadows
Mago principiante con sombrero verde y marrón. In-Game asset. 2d. High contrast. No shadows
Libro en la mano libre y cambiar la esfera de su varita por una estrella
Cambiar la esfera por una estrella y usar el diseño de varita de, cuarto asset
Mago con sombrero naranja y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Light wizard con cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Darkness wizard, con cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Quitar fondo blanco
Mago con sombrero naranja y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Mago con sombrero naranja y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Mago con sombrero rojo y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Mago con sombrero morado y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Mago con sombrero morado oscuro y marrón sin barba con varita con estrella, de cuerpo entero. In-Game asset. 2d. High contrast. No shadows
Momia realista en 2D. In-Game asset. 2d. High contrast. No shadows
Montículo de arena realista 2D. In-Game asset. 2d. High contrast. No shadows
Nubes moradas de las que cae un rayo amarillo más realista en 2D. In-Game asset. 2d. High contrast. No shadows
Muralla hecha de piedras y rocas realista en 2D. In-Game asset. 2d. High contrast. No shadows
Niebla muy realista en 2D. In-Game asset. 2d. High contrast. No shadows
Esquirla morada de hielo muy realista en 2D. In-Game asset. 2d. High contrast. No shadows
Mazmorra de ladrillos agrietados con lianas y escaleras que suben muy realista en 2D. In-Game asset. 2d. High contrast. No shadows
Oxigeno muy realista en 2D. In-Game asset. 2d. High contrast. No shadows
Clase mágica simple muy realista en 2D. In-Game asset. 2d. High contrast. No shadows
Clase estudiantil mágica algo más detallada muy realista en 2D. In-Game asset. 2d. High contrast. No shadows