/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highestLevel: 0, completedCourses: 0, currentCourse: 0, currentBattleInCourse: 0 }); /**** * 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); // 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 = 105; // Position on element color background // Add dark stroke for better contrast damageText.stroke = 0x000000; damageText.strokeThickness = 3; self.addChild(damageText); self.down = function (x, y, obj) { if (!self.isUsed && gameState === 'playerTurn') { playCard(self); } }; 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.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 = []; for (var i = 0; i < 3; i++) { if (self.deck.length > 0) { var randomIndex = Math.floor(Math.random() * self.deck.length); var cardData = self.deck[randomIndex]; 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); } } }; 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; } if (self.hand.length > 0) { var cardIndex = Math.floor(Math.random() * self.hand.length); var card = self.hand[cardIndex]; // 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 ****/ // Astral purple hat (final) // Golden hat (penultimate) // Maroon hat // Dark red hat // Fire brick hat // Crimson hat // Red hat // Orange red hat // Tomato hat // Coral hat // Dark orange hat // Orange hat // Gold hat // Yellow hat // Green yellow hat // Lawn green hat // Lime green hat // Green hat // Adventure mode wizard sprites with different colored hats // Ice card images // Rock card images // Plant card images // Air card images // Water card images // Fire card images // Game state variables // Fire card images // Water card images // Air card images // Plant card images // Rock card images // Ice card images 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'; 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'; // Air cards case 'Vendaval': return 'vendaval'; case 'Brisa': return 'brisa'; case 'Huracán': return 'huracan'; // Plant cards case 'Arboleda': return 'arboleda'; case 'Serafín': return 'serafin'; 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'; 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'; 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 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 playerDeck = []; var playerHand = []; var currentEnemy = null; var enemies = []; var turnCounter = 0; // UI elements var menuContainer = new Container(); var battleContainer = new Container(); var playerHealthBar = null; var playerHealthText = 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' }]; for (var k = 0; k < airCards.length; k++) { playerDeck.push(airCards[k]); } // Add two more air cards to make 5 total playerDeck.push({ element: 'Air', damage: 1, name: 'Vendaval', effect: 'normal' }); playerDeck.push({ element: 'Air', damage: 1, name: 'Brisa', effect: 'normal' }); } 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: 2, name: 'Terremoto', effect: 'replaceAllCards' }]; for (var k = 0; k < rockCards.length; k++) { playerDeck.push(rockCards[k]); } // Add one more rock card to make 5 total playerDeck.push({ element: 'Rock', damage: 2, name: 'Pedrada', effect: 'normal' }); } 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' }]; for (var k = 0; k < iceCards.length; k++) { playerDeck.push(iceCards[k]); } // Add one more ice card to make 5 total playerDeck.push({ element: 'Ice', damage: 1, name: 'Bola de nieve', effect: 'normal' }); } 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'); }; game.addChild(menuContainer); } function createBattle() { battleContainer.removeChildren(); // Background var 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); // 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); 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 = []; for (var i = 0; i < 3; i++) { if (playerDeck.length > 0) { var randomIndex = Math.floor(Math.random() * playerDeck.length); var cardData = playerDeck[randomIndex]; 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); } } } function playCard(card) { if (gameState !== 'playerTurn') return; card.isUsed = true; LK.getSound('cardPlay').play(); playElementSound(card.element); // Apply card effects var damage = card.damage; var element = card.element; // 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']; 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 } 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 { // Vendaval and Brisa - standard damage without replacing cards } break; case 'Rock': // Handle special rock card effects 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(); // 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('damage').play(); // 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 if (currentEnemy.hand.length > 0 && playerHand.length < 3) { var stealIndex = Math.floor(Math.random() * currentEnemy.hand.length); var stolenCardData = currentEnemy.hand[stealIndex]; currentEnemy.removeCardFromHand(stealIndex); 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); } // Clean up LK.setTimeout(function () { battleContainer.removeChild(pirate); finishCardPlay(card); }, 600); } }); } }); break; case 'Sarcófago': // Create sand pile in center of battle var sandPile = LK.getAsset('tormenta_de_arena_card', { anchorX: 0.5, anchorY: 0.5, scaleX: 4.0, scaleY: 1.5, alpha: 0.8, tint: 0xC19A6B }); 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 var mummy = LK.getAsset('Momia', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, alpha: 0 }); mummy.x = centerX; mummy.y = centerY - 50; 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 '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('damage').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('damage').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 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); // 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); } } // 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() { gameState = 'enemyTurn'; turnText.setText('Enemy Turn - Turn ' + turnCounter); LK.setTimeout(function () { currentEnemy.playTurn(); }, 1000); } function enemyPlayCard(cardData, cardIndex) { playElementSound(cardData.element); var damage = cardData.damage; var element = cardData.element; // 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 'Air': drawPlayerHand(); break; case 'Ice': // Player frozen (skip next turn - handled in game flow) break; } 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; } LK.showGameOver(); return; } endEnemyTurn(); } function endEnemyTurn() { // Complete turn cycle - both player and enemy have played turnCounter++; gameState = 'playerTurn'; turnText.setText('Your Turn - Turn ' + turnCounter); // Both players draw new hands after a complete turn drawPlayerHand(); currentEnemy.drawHand(); } function updatePlayerHealth() { var healthPercentage = playerHealth / playerMaxHealth; playerHealthBar.scaleX = healthPercentage; playerHealthText.setText('HP: ' + playerHealth + '/' + playerMaxHealth); } function startBattle() { gameState = 'battle'; if (gameMode === 'adventure') { // Start from first uncompleted battle currentBattle = completedCourses * 3; // Always start each adventure battle with 10/10 health playerHealth = 10; playerMaxHealth = 10; } else { // Roguelike mode currentBattle = 0; playerHealth = 10; playerMaxHealth = 10; } turnCounter = 0; game.removeChild(menuContainer); createBattle(); gameState = 'playerTurn'; } 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' }]; 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: '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' }]; 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 };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highestLevel: 0,
completedCourses: 0,
currentCourse: 0,
currentBattleInCourse: 0
});
/****
* 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);
// 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 = 105; // Position on element color background
// Add dark stroke for better contrast
damageText.stroke = 0x000000;
damageText.strokeThickness = 3;
self.addChild(damageText);
self.down = function (x, y, obj) {
if (!self.isUsed && gameState === 'playerTurn') {
playCard(self);
}
};
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.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 = [];
for (var i = 0; i < 3; i++) {
if (self.deck.length > 0) {
var randomIndex = Math.floor(Math.random() * self.deck.length);
var cardData = self.deck[randomIndex];
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);
}
}
};
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;
}
if (self.hand.length > 0) {
var cardIndex = Math.floor(Math.random() * self.hand.length);
var card = self.hand[cardIndex];
// 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
****/
// Astral purple hat (final)
// Golden hat (penultimate)
// Maroon hat
// Dark red hat
// Fire brick hat
// Crimson hat
// Red hat
// Orange red hat
// Tomato hat
// Coral hat
// Dark orange hat
// Orange hat
// Gold hat
// Yellow hat
// Green yellow hat
// Lawn green hat
// Lime green hat
// Green hat
// Adventure mode wizard sprites with different colored hats
// Ice card images
// Rock card images
// Plant card images
// Air card images
// Water card images
// Fire card images
// Game state variables
// Fire card images
// Water card images
// Air card images
// Plant card images
// Rock card images
// Ice card images
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';
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';
// Air cards
case 'Vendaval':
return 'vendaval';
case 'Brisa':
return 'brisa';
case 'Huracán':
return 'huracan';
// Plant cards
case 'Arboleda':
return 'arboleda';
case 'Serafín':
return 'serafin';
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';
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';
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 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 playerDeck = [];
var playerHand = [];
var currentEnemy = null;
var enemies = [];
var turnCounter = 0;
// UI elements
var menuContainer = new Container();
var battleContainer = new Container();
var playerHealthBar = null;
var playerHealthText = 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'
}];
for (var k = 0; k < airCards.length; k++) {
playerDeck.push(airCards[k]);
}
// Add two more air cards to make 5 total
playerDeck.push({
element: 'Air',
damage: 1,
name: 'Vendaval',
effect: 'normal'
});
playerDeck.push({
element: 'Air',
damage: 1,
name: 'Brisa',
effect: 'normal'
});
} 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: 2,
name: 'Terremoto',
effect: 'replaceAllCards'
}];
for (var k = 0; k < rockCards.length; k++) {
playerDeck.push(rockCards[k]);
}
// Add one more rock card to make 5 total
playerDeck.push({
element: 'Rock',
damage: 2,
name: 'Pedrada',
effect: 'normal'
});
} 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'
}];
for (var k = 0; k < iceCards.length; k++) {
playerDeck.push(iceCards[k]);
}
// Add one more ice card to make 5 total
playerDeck.push({
element: 'Ice',
damage: 1,
name: 'Bola de nieve',
effect: 'normal'
});
} 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');
};
game.addChild(menuContainer);
}
function createBattle() {
battleContainer.removeChildren();
// Background
var 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);
// 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);
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 = [];
for (var i = 0; i < 3; i++) {
if (playerDeck.length > 0) {
var randomIndex = Math.floor(Math.random() * playerDeck.length);
var cardData = playerDeck[randomIndex];
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);
}
}
}
function playCard(card) {
if (gameState !== 'playerTurn') return;
card.isUsed = true;
LK.getSound('cardPlay').play();
playElementSound(card.element);
// Apply card effects
var damage = card.damage;
var element = card.element;
// 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'];
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
}
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 {
// Vendaval and Brisa - standard damage without replacing cards
}
break;
case 'Rock':
// Handle special rock card effects
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();
// 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('damage').play();
// 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
if (currentEnemy.hand.length > 0 && playerHand.length < 3) {
var stealIndex = Math.floor(Math.random() * currentEnemy.hand.length);
var stolenCardData = currentEnemy.hand[stealIndex];
currentEnemy.removeCardFromHand(stealIndex);
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);
}
// Clean up
LK.setTimeout(function () {
battleContainer.removeChild(pirate);
finishCardPlay(card);
}, 600);
}
});
}
});
break;
case 'Sarcófago':
// Create sand pile in center of battle
var sandPile = LK.getAsset('tormenta_de_arena_card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 1.5,
alpha: 0.8,
tint: 0xC19A6B
});
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
var mummy = LK.getAsset('Momia', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
alpha: 0
});
mummy.x = centerX;
mummy.y = centerY - 50;
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 '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('damage').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('damage').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 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);
// 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);
}
}
// 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() {
gameState = 'enemyTurn';
turnText.setText('Enemy Turn - Turn ' + turnCounter);
LK.setTimeout(function () {
currentEnemy.playTurn();
}, 1000);
}
function enemyPlayCard(cardData, cardIndex) {
playElementSound(cardData.element);
var damage = cardData.damage;
var element = cardData.element;
// 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 'Air':
drawPlayerHand();
break;
case 'Ice':
// Player frozen (skip next turn - handled in game flow)
break;
}
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;
}
LK.showGameOver();
return;
}
endEnemyTurn();
}
function endEnemyTurn() {
// Complete turn cycle - both player and enemy have played
turnCounter++;
gameState = 'playerTurn';
turnText.setText('Your Turn - Turn ' + turnCounter);
// Both players draw new hands after a complete turn
drawPlayerHand();
currentEnemy.drawHand();
}
function updatePlayerHealth() {
var healthPercentage = playerHealth / playerMaxHealth;
playerHealthBar.scaleX = healthPercentage;
playerHealthText.setText('HP: ' + playerHealth + '/' + playerMaxHealth);
}
function startBattle() {
gameState = 'battle';
if (gameMode === 'adventure') {
// Start from first uncompleted battle
currentBattle = completedCourses * 3;
// Always start each adventure battle with 10/10 health
playerHealth = 10;
playerMaxHealth = 10;
} else {
// Roguelike mode
currentBattle = 0;
playerHealth = 10;
playerMaxHealth = 10;
}
turnCounter = 0;
game.removeChild(menuContainer);
createBattle();
gameState = 'playerTurn';
}
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'
}];
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: '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'
}];
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
};
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