/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { playerLevel: 1, playerDeck: undefined, collectedCards: undefined, currentOpponent: 1 }); /**** * Classes ****/ var Button = Container.expand(function (text) { var self = Container.call(this); var buttonBg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); self.buttonText = new Text2(text, { size: 50, fill: 0xFFFFFF }); self.buttonText.anchor.set(0.5, 0.5); self.addChild(self.buttonText); self.setText = function (newText) { self.buttonText.setText(newText); }; self.down = function (x, y, obj) { // Button press effect tween(self, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); LK.getSound('button_click').play(); }; return self; }); var DeckCard = Container.expand(function (monster, isSelected) { var self = Container.call(this); self.monster = monster; self.isSelected = isSelected || false; // Card background var cardBg = self.attachAsset('deck_select_bg', { anchorX: 0.5, anchorY: 0.5 }); // Highlight if selected if (self.isSelected) { cardBg.tint = 0x00AAFF; } // Monster name self.nameText = new Text2(monster.name, { size: 36, fill: 0xFFFFFF }); self.nameText.anchor.set(0.5, 0); self.nameText.y = -150; self.addChild(self.nameText); // Monster stats self.statsText = new Text2("ATK: " + monster.attack + " | HP: " + monster.health, { size: 32, fill: 0xFFFFFF }); self.statsText.anchor.set(0.5, 0); self.statsText.y = -100; self.addChild(self.statsText); // Energy cost self.costText = new Text2("Cost: " + monster.cost, { size: 32, fill: 0xFFFFFF }); self.costText.anchor.set(0.5, 0); self.costText.y = -50; self.addChild(self.costText); self.toggleSelected = function () { self.isSelected = !self.isSelected; if (self.isSelected) { cardBg.tint = 0x00AAFF; } else { cardBg.tint = 0xFFFFFF; } return self.isSelected; }; self.setSelected = function (selected) { self.isSelected = selected; if (self.isSelected) { cardBg.tint = 0x00AAFF; } else { cardBg.tint = 0xFFFFFF; } }; self.down = function (x, y, obj) { var result = self.toggleSelected(); if (result) { game.addToDeck(self.monster); } else { game.removeFromDeck(self.monster); } }; return self; }); var GridSlot = Container.expand(function (gridX, gridY) { var self = Container.call(this); self.gridX = gridX; self.gridY = gridY; self.card = null; var slotBg = self.attachAsset('monster_bg_slot', { anchorX: 0.5, anchorY: 0.5 }); // Make it slightly transparent slotBg.alpha = 0.5; self.highlight = function (active) { if (active) { slotBg.alpha = 0.8; } else { slotBg.alpha = 0.5; } }; self.setCard = function (card) { self.card = card; if (card) { card.inHand = false; card.gridPosition = { x: self.gridX, y: self.gridY }; } }; self.down = function (x, y, obj) { if (game.selectedCard && !self.card && game.currentTurn === "player") { // If we have a selected card from hand and this slot is empty game.placeCard(game.selectedCard, self); } else if (game.selectedCardOnBoard && !self.card) { // Move card on board to new position game.moveCardOnBoard(game.selectedCardOnBoard, self); } }; return self; }); var MonsterCard = Container.expand(function (monster, isPlayerCard) { var self = Container.call(this); self.monster = monster; self.isPlayerCard = isPlayerCard || false; self.inHand = true; self.gridPosition = null; self.currentHealth = monster.health; // Card background var cardBg = self.attachAsset('monster_card', { anchorX: 0.5, anchorY: 0.5 }); // Monster name self.nameText = new Text2(monster.name, { size: 40, fill: 0x000000 }); self.nameText.anchor.set(0.5, 0); self.nameText.y = -160; self.addChild(self.nameText); // Monster type self.typeText = new Text2(monster.type, { size: 30, fill: 0x555555 }); self.typeText.anchor.set(0.5, 0); self.typeText.y = -120; self.addChild(self.typeText); // Attack icon and value var attackIcon = self.attachAsset('attack_icon', { anchorX: 0.5, anchorY: 0.5, x: -80, y: 120 }); self.attackText = new Text2(monster.attack.toString(), { size: 40, fill: 0xFFFFFF }); self.attackText.anchor.set(0.5, 0.5); self.attackText.x = -80; self.attackText.y = 120; self.addChild(self.attackText); // Health icon and value var healthIcon = self.attachAsset('health_icon', { anchorX: 0.5, anchorY: 0.5, x: 80, y: 120 }); self.healthText = new Text2(self.currentHealth.toString(), { size: 40, fill: 0xFFFFFF }); self.healthText.anchor.set(0.5, 0.5); self.healthText.x = 80; self.healthText.y = 120; self.addChild(self.healthText); // Energy cost var energyIcon = self.attachAsset('energy_icon', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -80 }); self.energyText = new Text2(monster.cost.toString(), { size: 40, fill: 0xFFFFFF }); self.energyText.anchor.set(0.5, 0.5); self.energyText.x = 0; self.energyText.y = -80; self.addChild(self.energyText); // Ability text self.abilityText = new Text2(monster.ability, { size: 26, fill: 0x000000 }); self.abilityText.anchor.set(0.5, 0.5); self.abilityText.y = 40; self.abilityText.width = 230; self.addChild(self.abilityText); self.updateHealth = function (newHealth) { self.currentHealth = newHealth; self.healthText.setText(self.currentHealth.toString()); if (self.currentHealth <= 0) { tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); LK.getSound('card_destroyed').play(); } else { // Flash the card when damaged LK.effects.flashObject(self, 0xFF0000, 300); } }; self.attack = function (targetCard) { if (!targetCard) { return; } LK.getSound('card_attack').play(); // Apply damage targetCard.updateHealth(targetCard.currentHealth - self.monster.attack); // Flash the attacking card LK.effects.flashObject(self, 0xFFFF00, 300); }; self.down = function (x, y, obj) { if (self.isPlayerCard && self.inHand && game.currentTurn === "player" && !game.selectedCard) { game.selectCard(self); } else if (self.isPlayerCard && !self.inHand && game.selectedCard === null && game.currentTurn === "player") { // Select card on board game.selectCardOnBoard(self); } else if (!self.isPlayerCard && game.selectedCardOnBoard) { // Attack this enemy card game.attackCard(game.selectedCardOnBoard, self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x235789 }); /**** * Game Code ****/ // Game state variables game.currentScreen = "menu"; // menu, deck, battle game.selectedCard = null; game.selectedCardOnBoard = null; game.playerHand = []; game.playerEnergy = 0; game.maxPlayerEnergy = 0; game.playerDeck = []; game.playerBoard = []; // 3x3 grid for player game.enemyBoard = []; // 3x3 grid for enemy game.currentTurn = "player"; game.boardSlots = []; game.enemyCards = []; game.selectedDeck = []; game.availableCards = []; game.currentOpponent = 1; game.battleWon = false; // Define all monster cards data var monsterData = [{ id: 1, name: "Fire Wolf", type: "Fire", attack: 3, health: 4, cost: 3, ability: "Deals +1 damage to Plant types" }, { id: 2, name: "Water Sprite", type: "Water", attack: 2, health: 5, cost: 3, ability: "Heals 1 HP each turn" }, { id: 3, name: "Stone Golem", type: "Earth", attack: 2, health: 7, cost: 4, ability: "Takes 1 less damage from attacks" }, { id: 4, name: "Wind Eagle", type: "Air", attack: 4, health: 2, cost: 3, ability: "Can attack any position" }, { id: 5, name: "Leaf Guardian", type: "Plant", attack: 2, health: 6, cost: 3, ability: "Heals adjacent allies 1 HP per turn" }, { id: 6, name: "Shadow Thief", type: "Dark", attack: 5, health: 2, cost: 4, ability: "50% chance to dodge attacks" }, { id: 7, name: "Light Fairy", type: "Light", attack: 1, health: 3, cost: 1, ability: "Generates +1 energy per turn" }, { id: 8, name: "Thunder Drake", type: "Electric", attack: 4, health: 3, cost: 4, ability: "Can attack all enemies in a row" }, { id: 9, name: "Ice Bear", type: "Ice", attack: 3, health: 5, cost: 4, ability: "Freezes enemy for 1 turn on attack" }, { id: 10, name: "Lava Giant", type: "Fire", attack: 5, health: 5, cost: 6, ability: "Deals 1 damage to all adjacent enemies" }]; // Define opponent data var opponents = [{ id: 1, name: "Novice Trainer", level: 1, deck: [1, 2, 5, 7] }, { id: 2, name: "Forest Guardian", level: 2, deck: [4, 5, 5, 7, 8] }, { id: 3, name: "Flame Master", level: 3, deck: [1, 1, 6, 10, 10] }, { id: 4, name: "Guild Champion", level: 4, deck: [3, 6, 8, 9, 10] }]; // Initialize game state function initGame() { // Initialize default storage if not set if (!storage.collectedCards) { // Start with 6 basic cards storage.collectedCards = [1, 2, 3, 4, 5, 7]; } if (!storage.playerDeck) { // Default deck storage.playerDeck = [1, 2, 3, 4]; } // Load player data game.availableCards = storage.collectedCards; game.selectedDeck = storage.playerDeck; game.currentOpponent = storage.currentOpponent || 1; // Show main menu showMainMenu(); } // Create main menu function showMainMenu() { game.currentScreen = "menu"; clearScreen(); // Game title var titleText = new Text2("MONSTER GUILD", { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 500; game.addChild(titleText); // Battle button var battleButton = new Button("BATTLE"); battleButton.x = 1024; battleButton.y = 1200; battleButton.down = function () { LK.getSound('button_click').play(); showBattleScreen(); }; game.addChild(battleButton); // Deck button var deckButton = new Button("DECK BUILDER"); deckButton.x = 1024; deckButton.y = 1400; deckButton.down = function () { LK.getSound('button_click').play(); showDeckBuilder(); }; game.addChild(deckButton); // Opponent info var currentOpponent = opponents.find(function (o) { return o.id === game.currentOpponent; }); var opponentText = new Text2("Next Opponent: " + currentOpponent.name + " (Lvl " + currentOpponent.level + ")", { size: 50, fill: 0xFFFFFF }); opponentText.anchor.set(0.5, 0.5); opponentText.x = 1024; opponentText.y = 900; game.addChild(opponentText); } // Create deck builder screen function showDeckBuilder() { game.currentScreen = "deck"; clearScreen(); // Title var titleText = new Text2("DECK BUILDER", { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 200; game.addChild(titleText); // Instructions var instructionText = new Text2("Select 5 cards for your deck:", { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 300; game.addChild(instructionText); // Display available cards var cards = []; game.selectedDeck = []; for (var i = 0; i < game.availableCards.length; i++) { var cardId = game.availableCards[i]; var monster = monsterData.find(function (m) { return m.id === cardId; }); var isSelected = storage.playerDeck.includes(cardId); if (isSelected) { game.selectedDeck.push(cardId); } var deckCard = new DeckCard(monster, isSelected); deckCard.x = 400 + i % 3 * 600; deckCard.y = 600 + Math.floor(i / 3) * 450; deckCard.scale.set(0.8); game.addChild(deckCard); cards.push(deckCard); } // Save button var saveButton = new Button("SAVE DECK"); saveButton.x = 1024; saveButton.y = 2400; saveButton.down = function () { LK.getSound('button_click').play(); if (game.selectedDeck.length === 0) { // Can't save empty deck return; } storage.playerDeck = game.selectedDeck; showMainMenu(); }; game.addChild(saveButton); // Back button var backButton = new Button("BACK"); backButton.x = 1024; backButton.y = 2600; backButton.down = function () { LK.getSound('button_click').play(); showMainMenu(); }; game.addChild(backButton); // Selected count game.selectedCountText = new Text2("Selected: " + game.selectedDeck.length + " / 5", { size: 50, fill: 0xFFFFFF }); game.selectedCountText.anchor.set(0.5, 0.5); game.selectedCountText.x = 1024; game.selectedCountText.y = 2200; game.addChild(game.selectedCountText); } // Create battle screen function showBattleScreen() { game.currentScreen = "battle"; clearScreen(); // Play battle music LK.playMusic('battle_music'); // Initialize battle state game.playerEnergy = 3; game.maxPlayerEnergy = 3; game.currentTurn = "player"; game.playerHand = []; game.battleWon = false; // Create player deck for this battle game.playerDeck = []; for (var i = 0; i < storage.playerDeck.length; i++) { var cardId = storage.playerDeck[i]; var monster = monsterData.find(function (m) { return m.id === cardId; }); game.playerDeck.push(monster); } // Shuffle deck shuffleArray(game.playerDeck); // Create grid board createGameBoard(); // Deal initial hand for (var j = 0; j < 3; j++) { if (game.playerDeck.length > 0) { dealCard(); } } // Create enemy deck var opponent = opponents.find(function (o) { return o.id === game.currentOpponent; }); game.enemyDeck = []; for (var k = 0; k < opponent.deck.length; k++) { var enemyCardId = opponent.deck[k]; var enemyMonster = monsterData.find(function (m) { return m.id === enemyCardId; }); game.enemyDeck.push(enemyMonster); } // Shuffle enemy deck shuffleArray(game.enemyDeck); // Add opponent info var opponentAvatar = game.addChild(LK.getAsset('opponent_avatar', { anchorX: 0.5, anchorY: 0.5, x: 1750, y: 250 })); var opponentNameText = new Text2(opponent.name, { size: 40, fill: 0xFFFFFF }); opponentNameText.anchor.set(0.5, 0.5); opponentNameText.x = 1750; opponentNameText.y = 350; game.addChild(opponentNameText); // Add player avatar var playerAvatar = game.addChild(LK.getAsset('player_avatar', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 2400 })); // Add player energy display game.energyText = new Text2("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy, { size: 40, fill: 0xFFFFFF }); game.energyText.anchor.set(0, 0.5); game.energyText.x = 400; game.energyText.y = 2400; game.addChild(game.energyText); // Add end turn button game.endTurnButton = new Button("END TURN"); game.endTurnButton.x = 1750; game.endTurnButton.y = 2400; game.endTurnButton.down = function () { if (game.currentTurn === "player") { LK.getSound('button_click').play(); endPlayerTurn(); } }; game.addChild(game.endTurnButton); // Add turn indicator game.turnText = new Text2("YOUR TURN", { size: 60, fill: 0xFFFFFF }); game.turnText.anchor.set(0.5, 0.5); game.turnText.x = 1024; game.turnText.y = 250; game.addChild(game.turnText); } // Create the 3x3 game board function createGameBoard() { game.boardSlots = []; // Calculate board position var boardCenterX = 1024; var boardCenterY = 1366; var slotSpacing = 350; // Create 3x3 grid for player for (var y = 0; y < 3; y++) { for (var x = 0; x < 3; x++) { var slotX = boardCenterX + (x - 1) * slotSpacing; var slotY = boardCenterY + (1 - y) * slotSpacing; // Invert y so 0 is at the bottom var slot = new GridSlot(x, y); slot.x = slotX; slot.y = slotY; game.addChild(slot); game.boardSlots.push({ slot: slot, x: x, y: y, playerSide: y < 3 // First 3 rows are player side }); } } } // Deal a card to player's hand function dealCard() { if (game.playerDeck.length === 0 || game.playerHand.length >= 5) { return; } var monster = game.playerDeck.shift(); var card = new MonsterCard(monster, true); // Position in hand updateHandPositions(card); game.playerHand.push(card); game.addChild(card); } // Update positions of cards in hand function updateHandPositions(newCard) { var handWidth = Math.min(game.playerHand.length + 1, 5) * 280; var startX = 1024 - handWidth / 2 + 140; for (var i = 0; i < game.playerHand.length; i++) { var card = game.playerHand[i]; tween(card, { x: startX + i * 280, y: 2150, rotation: 0 }, { duration: 300 }); } if (newCard) { newCard.x = startX + game.playerHand.length * 280; newCard.y = 2150; } } // Select a card from hand game.selectCard = function (card) { // Check if player has enough energy if (game.playerEnergy < card.monster.cost) { // Flash red to indicate not enough energy LK.effects.flashObject(card, 0xFF0000, 300); return; } game.selectedCard = card; // Highlight card tween(card, { y: 2050 }, { duration: 200 }); // Highlight valid board positions highlightValidBoardPositions(); }; // Highlight valid positions on board function highlightValidBoardPositions() { // For simplicity, any empty slot is valid for (var i = 0; i < game.boardSlots.length; i++) { var slotInfo = game.boardSlots[i]; if (!slotInfo.slot.card) { slotInfo.slot.highlight(true); } } } // Unhighlight all board positions function unhighlightBoardPositions() { for (var i = 0; i < game.boardSlots.length; i++) { game.boardSlots[i].slot.highlight(false); } } // Place card on board game.placeCard = function (card, slot) { if (!card || !slot || game.playerEnergy < card.monster.cost) { return; } // Remove from hand var index = game.playerHand.indexOf(card); if (index !== -1) { game.playerHand.splice(index, 1); } // Use energy game.playerEnergy -= card.monster.cost; game.energyText.setText("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy); // Place on board tween(card, { x: slot.x, y: slot.y, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, onFinish: function onFinish() { slot.setCard(card); LK.getSound('card_place').play(); } }); // Update other cards in hand updateHandPositions(); // Clear selection game.selectedCard = null; // Unhighlight slots unhighlightBoardPositions(); }; // Select a card on the board game.selectCardOnBoard = function (card) { // If already had a selected card, deselect it if (game.selectedCardOnBoard) { unhighlightBoardPositions(); } game.selectedCardOnBoard = card; // Highlight valid targets highlightValidTargets(); }; // Highlight valid attack targets function highlightValidTargets() { // Highlight enemy cards for (var i = 0; i < game.boardSlots.length; i++) { var slotInfo = game.boardSlots[i]; if (slotInfo.slot.card && slotInfo.y >= 1.5) { // Enemy side slotInfo.slot.highlight(true); } } } // Attack an enemy card game.attackCard = function (attackerCard, targetCard) { if (!attackerCard || !targetCard) { return; } // Perform attack attackerCard.attack(targetCard); // Deselect game.selectedCardOnBoard = null; unhighlightBoardPositions(); // Check for win condition checkBattleEnd(); }; // Move a card on board to new position game.moveCardOnBoard = function (card, newSlot) { if (!card || !newSlot) { return; } // Find current slot var currentSlot = null; for (var i = 0; i < game.boardSlots.length; i++) { if (game.boardSlots[i].slot.card === card) { currentSlot = game.boardSlots[i].slot; break; } } if (currentSlot) { // Remove from current slot currentSlot.setCard(null); // Move to new slot tween(card, { x: newSlot.x, y: newSlot.y }, { duration: 300, onFinish: function onFinish() { newSlot.setCard(card); LK.getSound('card_place').play(); } }); // Deselect game.selectedCardOnBoard = null; unhighlightBoardPositions(); } }; // End player turn function endPlayerTurn() { game.currentTurn = "enemy"; game.turnText.setText("OPPONENT'S TURN"); // Deselect any cards game.selectedCard = null; game.selectedCardOnBoard = null; unhighlightBoardPositions(); // Schedule enemy turn LK.setTimeout(doEnemyTurn, 1000); } // Enemy AI turn function doEnemyTurn() { // Play cards from enemy deck playEnemyCards(); // Enemy attacks with all cards LK.setTimeout(function () { enemyAttack(); // End enemy turn LK.setTimeout(startPlayerTurn, 1000); }, 1000); } // Enemy plays cards function playEnemyCards() { // Simplified AI - place up to 2 cards if possible var cardsPlayed = 0; while (game.enemyDeck.length > 0 && cardsPlayed < 2) { // Find empty slots on enemy side var emptySlots = []; for (var i = 0; i < game.boardSlots.length; i++) { var slotInfo = game.boardSlots[i]; if (slotInfo.y >= 1.5 && !slotInfo.slot.card) { // Enemy side emptySlots.push(slotInfo.slot); } } if (emptySlots.length === 0) { break; } // Place an enemy card var monster = game.enemyDeck.shift(); var card = new MonsterCard(monster, false); game.addChild(card); // Choose a random empty slot var slot = emptySlots[Math.floor(Math.random() * emptySlots.length)]; // Place card card.x = 1750; card.y = 250; tween(card, { x: slot.x, y: slot.y, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, onFinish: function onFinish() { slot.setCard(card); LK.getSound('card_place').play(); } }); cardsPlayed++; } } // Enemy attacks function enemyAttack() { // Find all enemy cards var enemyCards = []; var playerCards = []; for (var i = 0; i < game.boardSlots.length; i++) { var slotInfo = game.boardSlots[i]; if (slotInfo.slot.card) { if (slotInfo.y >= 1.5) { // Enemy side enemyCards.push(slotInfo.slot.card); } else { playerCards.push(slotInfo.slot.card); } } } // Each enemy card attacks a random player card if available for (var j = 0; j < enemyCards.length; j++) { if (playerCards.length > 0) { var target = playerCards[Math.floor(Math.random() * playerCards.length)]; enemyCards[j].attack(target); // If target was destroyed, remove from player cards if (target.currentHealth <= 0) { var targetIndex = playerCards.indexOf(target); if (targetIndex !== -1) { playerCards.splice(targetIndex, 1); } } } } // Check for loss condition checkBattleEnd(); } // Start player turn function startPlayerTurn() { game.currentTurn = "player"; game.turnText.setText("YOUR TURN"); // Increase max energy if less than 10 if (game.maxPlayerEnergy < 10) { game.maxPlayerEnergy++; } // Replenish energy game.playerEnergy = game.maxPlayerEnergy; game.energyText.setText("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy); // Draw a card dealCard(); } // Check if battle is over function checkBattleEnd() { // Count cards for each side var enemyCardCount = 0; var playerCardCount = 0; for (var i = 0; i < game.boardSlots.length; i++) { var slotInfo = game.boardSlots[i]; if (slotInfo.slot.card) { if (slotInfo.y >= 1.5) { // Enemy side enemyCardCount++; } else { playerCardCount++; } } } // Check win/loss conditions if (enemyCardCount === 0 && game.enemyDeck.length === 0) { // Player wins game.battleWon = true; showBattleResult("YOU WIN!"); } else if (playerCardCount === 0 && game.playerDeck.length === 0 && game.playerHand.length === 0) { // Player loses showBattleResult("YOU LOSE!"); } } // Show battle result and return to main menu function showBattleResult(message) { // Create result overlay var resultText = new Text2(message, { size: 100, fill: 0xFFFFFF }); resultText.anchor.set(0.5, 0.5); resultText.x = 1024; resultText.y = 1366; game.addChild(resultText); // If won, update opponent and add a new card if (game.battleWon) { // Move to next opponent if (game.currentOpponent < opponents.length) { storage.currentOpponent = game.currentOpponent + 1; } // Add a new card to collection if not all collected if (game.availableCards.length < monsterData.length) { // Find uncollected cards var uncollectedCards = monsterData.filter(function (m) { return !game.availableCards.includes(m.id); }).map(function (m) { return m.id; }); if (uncollectedCards.length > 0) { // Add random new card var newCardId = uncollectedCards[Math.floor(Math.random() * uncollectedCards.length)]; storage.collectedCards.push(newCardId); var newCardText = new Text2("NEW CARD UNLOCKED!", { size: 60, fill: 0xFFFF00 }); newCardText.anchor.set(0.5, 0.5); newCardText.x = 1024; newCardText.y = 1500; game.addChild(newCardText); } } } // Return to main menu button var menuButton = new Button("MAIN MENU"); menuButton.x = 1024; menuButton.y = 1800; menuButton.down = function () { LK.getSound('button_click').play(); showMainMenu(); }; game.addChild(menuButton); } // Utility: Clear all children from screen function clearScreen() { while (game.children.length > 0) { game.children[0].destroy(); } } // Utility: Shuffle array function shuffleArray(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } } // Add to deck in deck builder game.addToDeck = function (monster) { // Check if we already have 5 cards if (game.selectedDeck.length >= 5) { // Remove another card to make room var lastCard = game.selectedDeck.pop(); } game.selectedDeck.push(monster.id); game.selectedCountText.setText("Selected: " + game.selectedDeck.length + " / 5"); }; // Remove from deck in deck builder game.removeFromDeck = function (monster) { var index = game.selectedDeck.indexOf(monster.id); if (index !== -1) { game.selectedDeck.splice(index, 1); game.selectedCountText.setText("Selected: " + game.selectedDeck.length + " / 5"); } }; // Update game logic game.update = function () { if (game.currentScreen === "battle") { // Any per-frame updates for battle screen } }; // Initialize game on start initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
playerLevel: 1,
playerDeck: undefined,
collectedCards: undefined,
currentOpponent: 1
});
/****
* Classes
****/
var Button = Container.expand(function (text) {
var self = Container.call(this);
var buttonBg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.buttonText = new Text2(text, {
size: 50,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
self.addChild(self.buttonText);
self.setText = function (newText) {
self.buttonText.setText(newText);
};
self.down = function (x, y, obj) {
// Button press effect
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
LK.getSound('button_click').play();
};
return self;
});
var DeckCard = Container.expand(function (monster, isSelected) {
var self = Container.call(this);
self.monster = monster;
self.isSelected = isSelected || false;
// Card background
var cardBg = self.attachAsset('deck_select_bg', {
anchorX: 0.5,
anchorY: 0.5
});
// Highlight if selected
if (self.isSelected) {
cardBg.tint = 0x00AAFF;
}
// Monster name
self.nameText = new Text2(monster.name, {
size: 36,
fill: 0xFFFFFF
});
self.nameText.anchor.set(0.5, 0);
self.nameText.y = -150;
self.addChild(self.nameText);
// Monster stats
self.statsText = new Text2("ATK: " + monster.attack + " | HP: " + monster.health, {
size: 32,
fill: 0xFFFFFF
});
self.statsText.anchor.set(0.5, 0);
self.statsText.y = -100;
self.addChild(self.statsText);
// Energy cost
self.costText = new Text2("Cost: " + monster.cost, {
size: 32,
fill: 0xFFFFFF
});
self.costText.anchor.set(0.5, 0);
self.costText.y = -50;
self.addChild(self.costText);
self.toggleSelected = function () {
self.isSelected = !self.isSelected;
if (self.isSelected) {
cardBg.tint = 0x00AAFF;
} else {
cardBg.tint = 0xFFFFFF;
}
return self.isSelected;
};
self.setSelected = function (selected) {
self.isSelected = selected;
if (self.isSelected) {
cardBg.tint = 0x00AAFF;
} else {
cardBg.tint = 0xFFFFFF;
}
};
self.down = function (x, y, obj) {
var result = self.toggleSelected();
if (result) {
game.addToDeck(self.monster);
} else {
game.removeFromDeck(self.monster);
}
};
return self;
});
var GridSlot = Container.expand(function (gridX, gridY) {
var self = Container.call(this);
self.gridX = gridX;
self.gridY = gridY;
self.card = null;
var slotBg = self.attachAsset('monster_bg_slot', {
anchorX: 0.5,
anchorY: 0.5
});
// Make it slightly transparent
slotBg.alpha = 0.5;
self.highlight = function (active) {
if (active) {
slotBg.alpha = 0.8;
} else {
slotBg.alpha = 0.5;
}
};
self.setCard = function (card) {
self.card = card;
if (card) {
card.inHand = false;
card.gridPosition = {
x: self.gridX,
y: self.gridY
};
}
};
self.down = function (x, y, obj) {
if (game.selectedCard && !self.card && game.currentTurn === "player") {
// If we have a selected card from hand and this slot is empty
game.placeCard(game.selectedCard, self);
} else if (game.selectedCardOnBoard && !self.card) {
// Move card on board to new position
game.moveCardOnBoard(game.selectedCardOnBoard, self);
}
};
return self;
});
var MonsterCard = Container.expand(function (monster, isPlayerCard) {
var self = Container.call(this);
self.monster = monster;
self.isPlayerCard = isPlayerCard || false;
self.inHand = true;
self.gridPosition = null;
self.currentHealth = monster.health;
// Card background
var cardBg = self.attachAsset('monster_card', {
anchorX: 0.5,
anchorY: 0.5
});
// Monster name
self.nameText = new Text2(monster.name, {
size: 40,
fill: 0x000000
});
self.nameText.anchor.set(0.5, 0);
self.nameText.y = -160;
self.addChild(self.nameText);
// Monster type
self.typeText = new Text2(monster.type, {
size: 30,
fill: 0x555555
});
self.typeText.anchor.set(0.5, 0);
self.typeText.y = -120;
self.addChild(self.typeText);
// Attack icon and value
var attackIcon = self.attachAsset('attack_icon', {
anchorX: 0.5,
anchorY: 0.5,
x: -80,
y: 120
});
self.attackText = new Text2(monster.attack.toString(), {
size: 40,
fill: 0xFFFFFF
});
self.attackText.anchor.set(0.5, 0.5);
self.attackText.x = -80;
self.attackText.y = 120;
self.addChild(self.attackText);
// Health icon and value
var healthIcon = self.attachAsset('health_icon', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: 120
});
self.healthText = new Text2(self.currentHealth.toString(), {
size: 40,
fill: 0xFFFFFF
});
self.healthText.anchor.set(0.5, 0.5);
self.healthText.x = 80;
self.healthText.y = 120;
self.addChild(self.healthText);
// Energy cost
var energyIcon = self.attachAsset('energy_icon', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -80
});
self.energyText = new Text2(monster.cost.toString(), {
size: 40,
fill: 0xFFFFFF
});
self.energyText.anchor.set(0.5, 0.5);
self.energyText.x = 0;
self.energyText.y = -80;
self.addChild(self.energyText);
// Ability text
self.abilityText = new Text2(monster.ability, {
size: 26,
fill: 0x000000
});
self.abilityText.anchor.set(0.5, 0.5);
self.abilityText.y = 40;
self.abilityText.width = 230;
self.addChild(self.abilityText);
self.updateHealth = function (newHealth) {
self.currentHealth = newHealth;
self.healthText.setText(self.currentHealth.toString());
if (self.currentHealth <= 0) {
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('card_destroyed').play();
} else {
// Flash the card when damaged
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.attack = function (targetCard) {
if (!targetCard) {
return;
}
LK.getSound('card_attack').play();
// Apply damage
targetCard.updateHealth(targetCard.currentHealth - self.monster.attack);
// Flash the attacking card
LK.effects.flashObject(self, 0xFFFF00, 300);
};
self.down = function (x, y, obj) {
if (self.isPlayerCard && self.inHand && game.currentTurn === "player" && !game.selectedCard) {
game.selectCard(self);
} else if (self.isPlayerCard && !self.inHand && game.selectedCard === null && game.currentTurn === "player") {
// Select card on board
game.selectCardOnBoard(self);
} else if (!self.isPlayerCard && game.selectedCardOnBoard) {
// Attack this enemy card
game.attackCard(game.selectedCardOnBoard, self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x235789
});
/****
* Game Code
****/
// Game state variables
game.currentScreen = "menu"; // menu, deck, battle
game.selectedCard = null;
game.selectedCardOnBoard = null;
game.playerHand = [];
game.playerEnergy = 0;
game.maxPlayerEnergy = 0;
game.playerDeck = [];
game.playerBoard = []; // 3x3 grid for player
game.enemyBoard = []; // 3x3 grid for enemy
game.currentTurn = "player";
game.boardSlots = [];
game.enemyCards = [];
game.selectedDeck = [];
game.availableCards = [];
game.currentOpponent = 1;
game.battleWon = false;
// Define all monster cards data
var monsterData = [{
id: 1,
name: "Fire Wolf",
type: "Fire",
attack: 3,
health: 4,
cost: 3,
ability: "Deals +1 damage to Plant types"
}, {
id: 2,
name: "Water Sprite",
type: "Water",
attack: 2,
health: 5,
cost: 3,
ability: "Heals 1 HP each turn"
}, {
id: 3,
name: "Stone Golem",
type: "Earth",
attack: 2,
health: 7,
cost: 4,
ability: "Takes 1 less damage from attacks"
}, {
id: 4,
name: "Wind Eagle",
type: "Air",
attack: 4,
health: 2,
cost: 3,
ability: "Can attack any position"
}, {
id: 5,
name: "Leaf Guardian",
type: "Plant",
attack: 2,
health: 6,
cost: 3,
ability: "Heals adjacent allies 1 HP per turn"
}, {
id: 6,
name: "Shadow Thief",
type: "Dark",
attack: 5,
health: 2,
cost: 4,
ability: "50% chance to dodge attacks"
}, {
id: 7,
name: "Light Fairy",
type: "Light",
attack: 1,
health: 3,
cost: 1,
ability: "Generates +1 energy per turn"
}, {
id: 8,
name: "Thunder Drake",
type: "Electric",
attack: 4,
health: 3,
cost: 4,
ability: "Can attack all enemies in a row"
}, {
id: 9,
name: "Ice Bear",
type: "Ice",
attack: 3,
health: 5,
cost: 4,
ability: "Freezes enemy for 1 turn on attack"
}, {
id: 10,
name: "Lava Giant",
type: "Fire",
attack: 5,
health: 5,
cost: 6,
ability: "Deals 1 damage to all adjacent enemies"
}];
// Define opponent data
var opponents = [{
id: 1,
name: "Novice Trainer",
level: 1,
deck: [1, 2, 5, 7]
}, {
id: 2,
name: "Forest Guardian",
level: 2,
deck: [4, 5, 5, 7, 8]
}, {
id: 3,
name: "Flame Master",
level: 3,
deck: [1, 1, 6, 10, 10]
}, {
id: 4,
name: "Guild Champion",
level: 4,
deck: [3, 6, 8, 9, 10]
}];
// Initialize game state
function initGame() {
// Initialize default storage if not set
if (!storage.collectedCards) {
// Start with 6 basic cards
storage.collectedCards = [1, 2, 3, 4, 5, 7];
}
if (!storage.playerDeck) {
// Default deck
storage.playerDeck = [1, 2, 3, 4];
}
// Load player data
game.availableCards = storage.collectedCards;
game.selectedDeck = storage.playerDeck;
game.currentOpponent = storage.currentOpponent || 1;
// Show main menu
showMainMenu();
}
// Create main menu
function showMainMenu() {
game.currentScreen = "menu";
clearScreen();
// Game title
var titleText = new Text2("MONSTER GUILD", {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 500;
game.addChild(titleText);
// Battle button
var battleButton = new Button("BATTLE");
battleButton.x = 1024;
battleButton.y = 1200;
battleButton.down = function () {
LK.getSound('button_click').play();
showBattleScreen();
};
game.addChild(battleButton);
// Deck button
var deckButton = new Button("DECK BUILDER");
deckButton.x = 1024;
deckButton.y = 1400;
deckButton.down = function () {
LK.getSound('button_click').play();
showDeckBuilder();
};
game.addChild(deckButton);
// Opponent info
var currentOpponent = opponents.find(function (o) {
return o.id === game.currentOpponent;
});
var opponentText = new Text2("Next Opponent: " + currentOpponent.name + " (Lvl " + currentOpponent.level + ")", {
size: 50,
fill: 0xFFFFFF
});
opponentText.anchor.set(0.5, 0.5);
opponentText.x = 1024;
opponentText.y = 900;
game.addChild(opponentText);
}
// Create deck builder screen
function showDeckBuilder() {
game.currentScreen = "deck";
clearScreen();
// Title
var titleText = new Text2("DECK BUILDER", {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 200;
game.addChild(titleText);
// Instructions
var instructionText = new Text2("Select 5 cards for your deck:", {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 300;
game.addChild(instructionText);
// Display available cards
var cards = [];
game.selectedDeck = [];
for (var i = 0; i < game.availableCards.length; i++) {
var cardId = game.availableCards[i];
var monster = monsterData.find(function (m) {
return m.id === cardId;
});
var isSelected = storage.playerDeck.includes(cardId);
if (isSelected) {
game.selectedDeck.push(cardId);
}
var deckCard = new DeckCard(monster, isSelected);
deckCard.x = 400 + i % 3 * 600;
deckCard.y = 600 + Math.floor(i / 3) * 450;
deckCard.scale.set(0.8);
game.addChild(deckCard);
cards.push(deckCard);
}
// Save button
var saveButton = new Button("SAVE DECK");
saveButton.x = 1024;
saveButton.y = 2400;
saveButton.down = function () {
LK.getSound('button_click').play();
if (game.selectedDeck.length === 0) {
// Can't save empty deck
return;
}
storage.playerDeck = game.selectedDeck;
showMainMenu();
};
game.addChild(saveButton);
// Back button
var backButton = new Button("BACK");
backButton.x = 1024;
backButton.y = 2600;
backButton.down = function () {
LK.getSound('button_click').play();
showMainMenu();
};
game.addChild(backButton);
// Selected count
game.selectedCountText = new Text2("Selected: " + game.selectedDeck.length + " / 5", {
size: 50,
fill: 0xFFFFFF
});
game.selectedCountText.anchor.set(0.5, 0.5);
game.selectedCountText.x = 1024;
game.selectedCountText.y = 2200;
game.addChild(game.selectedCountText);
}
// Create battle screen
function showBattleScreen() {
game.currentScreen = "battle";
clearScreen();
// Play battle music
LK.playMusic('battle_music');
// Initialize battle state
game.playerEnergy = 3;
game.maxPlayerEnergy = 3;
game.currentTurn = "player";
game.playerHand = [];
game.battleWon = false;
// Create player deck for this battle
game.playerDeck = [];
for (var i = 0; i < storage.playerDeck.length; i++) {
var cardId = storage.playerDeck[i];
var monster = monsterData.find(function (m) {
return m.id === cardId;
});
game.playerDeck.push(monster);
}
// Shuffle deck
shuffleArray(game.playerDeck);
// Create grid board
createGameBoard();
// Deal initial hand
for (var j = 0; j < 3; j++) {
if (game.playerDeck.length > 0) {
dealCard();
}
}
// Create enemy deck
var opponent = opponents.find(function (o) {
return o.id === game.currentOpponent;
});
game.enemyDeck = [];
for (var k = 0; k < opponent.deck.length; k++) {
var enemyCardId = opponent.deck[k];
var enemyMonster = monsterData.find(function (m) {
return m.id === enemyCardId;
});
game.enemyDeck.push(enemyMonster);
}
// Shuffle enemy deck
shuffleArray(game.enemyDeck);
// Add opponent info
var opponentAvatar = game.addChild(LK.getAsset('opponent_avatar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1750,
y: 250
}));
var opponentNameText = new Text2(opponent.name, {
size: 40,
fill: 0xFFFFFF
});
opponentNameText.anchor.set(0.5, 0.5);
opponentNameText.x = 1750;
opponentNameText.y = 350;
game.addChild(opponentNameText);
// Add player avatar
var playerAvatar = game.addChild(LK.getAsset('player_avatar', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2400
}));
// Add player energy display
game.energyText = new Text2("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy, {
size: 40,
fill: 0xFFFFFF
});
game.energyText.anchor.set(0, 0.5);
game.energyText.x = 400;
game.energyText.y = 2400;
game.addChild(game.energyText);
// Add end turn button
game.endTurnButton = new Button("END TURN");
game.endTurnButton.x = 1750;
game.endTurnButton.y = 2400;
game.endTurnButton.down = function () {
if (game.currentTurn === "player") {
LK.getSound('button_click').play();
endPlayerTurn();
}
};
game.addChild(game.endTurnButton);
// Add turn indicator
game.turnText = new Text2("YOUR TURN", {
size: 60,
fill: 0xFFFFFF
});
game.turnText.anchor.set(0.5, 0.5);
game.turnText.x = 1024;
game.turnText.y = 250;
game.addChild(game.turnText);
}
// Create the 3x3 game board
function createGameBoard() {
game.boardSlots = [];
// Calculate board position
var boardCenterX = 1024;
var boardCenterY = 1366;
var slotSpacing = 350;
// Create 3x3 grid for player
for (var y = 0; y < 3; y++) {
for (var x = 0; x < 3; x++) {
var slotX = boardCenterX + (x - 1) * slotSpacing;
var slotY = boardCenterY + (1 - y) * slotSpacing; // Invert y so 0 is at the bottom
var slot = new GridSlot(x, y);
slot.x = slotX;
slot.y = slotY;
game.addChild(slot);
game.boardSlots.push({
slot: slot,
x: x,
y: y,
playerSide: y < 3 // First 3 rows are player side
});
}
}
}
// Deal a card to player's hand
function dealCard() {
if (game.playerDeck.length === 0 || game.playerHand.length >= 5) {
return;
}
var monster = game.playerDeck.shift();
var card = new MonsterCard(monster, true);
// Position in hand
updateHandPositions(card);
game.playerHand.push(card);
game.addChild(card);
}
// Update positions of cards in hand
function updateHandPositions(newCard) {
var handWidth = Math.min(game.playerHand.length + 1, 5) * 280;
var startX = 1024 - handWidth / 2 + 140;
for (var i = 0; i < game.playerHand.length; i++) {
var card = game.playerHand[i];
tween(card, {
x: startX + i * 280,
y: 2150,
rotation: 0
}, {
duration: 300
});
}
if (newCard) {
newCard.x = startX + game.playerHand.length * 280;
newCard.y = 2150;
}
}
// Select a card from hand
game.selectCard = function (card) {
// Check if player has enough energy
if (game.playerEnergy < card.monster.cost) {
// Flash red to indicate not enough energy
LK.effects.flashObject(card, 0xFF0000, 300);
return;
}
game.selectedCard = card;
// Highlight card
tween(card, {
y: 2050
}, {
duration: 200
});
// Highlight valid board positions
highlightValidBoardPositions();
};
// Highlight valid positions on board
function highlightValidBoardPositions() {
// For simplicity, any empty slot is valid
for (var i = 0; i < game.boardSlots.length; i++) {
var slotInfo = game.boardSlots[i];
if (!slotInfo.slot.card) {
slotInfo.slot.highlight(true);
}
}
}
// Unhighlight all board positions
function unhighlightBoardPositions() {
for (var i = 0; i < game.boardSlots.length; i++) {
game.boardSlots[i].slot.highlight(false);
}
}
// Place card on board
game.placeCard = function (card, slot) {
if (!card || !slot || game.playerEnergy < card.monster.cost) {
return;
}
// Remove from hand
var index = game.playerHand.indexOf(card);
if (index !== -1) {
game.playerHand.splice(index, 1);
}
// Use energy
game.playerEnergy -= card.monster.cost;
game.energyText.setText("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy);
// Place on board
tween(card, {
x: slot.x,
y: slot.y,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
onFinish: function onFinish() {
slot.setCard(card);
LK.getSound('card_place').play();
}
});
// Update other cards in hand
updateHandPositions();
// Clear selection
game.selectedCard = null;
// Unhighlight slots
unhighlightBoardPositions();
};
// Select a card on the board
game.selectCardOnBoard = function (card) {
// If already had a selected card, deselect it
if (game.selectedCardOnBoard) {
unhighlightBoardPositions();
}
game.selectedCardOnBoard = card;
// Highlight valid targets
highlightValidTargets();
};
// Highlight valid attack targets
function highlightValidTargets() {
// Highlight enemy cards
for (var i = 0; i < game.boardSlots.length; i++) {
var slotInfo = game.boardSlots[i];
if (slotInfo.slot.card && slotInfo.y >= 1.5) {
// Enemy side
slotInfo.slot.highlight(true);
}
}
}
// Attack an enemy card
game.attackCard = function (attackerCard, targetCard) {
if (!attackerCard || !targetCard) {
return;
}
// Perform attack
attackerCard.attack(targetCard);
// Deselect
game.selectedCardOnBoard = null;
unhighlightBoardPositions();
// Check for win condition
checkBattleEnd();
};
// Move a card on board to new position
game.moveCardOnBoard = function (card, newSlot) {
if (!card || !newSlot) {
return;
}
// Find current slot
var currentSlot = null;
for (var i = 0; i < game.boardSlots.length; i++) {
if (game.boardSlots[i].slot.card === card) {
currentSlot = game.boardSlots[i].slot;
break;
}
}
if (currentSlot) {
// Remove from current slot
currentSlot.setCard(null);
// Move to new slot
tween(card, {
x: newSlot.x,
y: newSlot.y
}, {
duration: 300,
onFinish: function onFinish() {
newSlot.setCard(card);
LK.getSound('card_place').play();
}
});
// Deselect
game.selectedCardOnBoard = null;
unhighlightBoardPositions();
}
};
// End player turn
function endPlayerTurn() {
game.currentTurn = "enemy";
game.turnText.setText("OPPONENT'S TURN");
// Deselect any cards
game.selectedCard = null;
game.selectedCardOnBoard = null;
unhighlightBoardPositions();
// Schedule enemy turn
LK.setTimeout(doEnemyTurn, 1000);
}
// Enemy AI turn
function doEnemyTurn() {
// Play cards from enemy deck
playEnemyCards();
// Enemy attacks with all cards
LK.setTimeout(function () {
enemyAttack();
// End enemy turn
LK.setTimeout(startPlayerTurn, 1000);
}, 1000);
}
// Enemy plays cards
function playEnemyCards() {
// Simplified AI - place up to 2 cards if possible
var cardsPlayed = 0;
while (game.enemyDeck.length > 0 && cardsPlayed < 2) {
// Find empty slots on enemy side
var emptySlots = [];
for (var i = 0; i < game.boardSlots.length; i++) {
var slotInfo = game.boardSlots[i];
if (slotInfo.y >= 1.5 && !slotInfo.slot.card) {
// Enemy side
emptySlots.push(slotInfo.slot);
}
}
if (emptySlots.length === 0) {
break;
}
// Place an enemy card
var monster = game.enemyDeck.shift();
var card = new MonsterCard(monster, false);
game.addChild(card);
// Choose a random empty slot
var slot = emptySlots[Math.floor(Math.random() * emptySlots.length)];
// Place card
card.x = 1750;
card.y = 250;
tween(card, {
x: slot.x,
y: slot.y,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
slot.setCard(card);
LK.getSound('card_place').play();
}
});
cardsPlayed++;
}
}
// Enemy attacks
function enemyAttack() {
// Find all enemy cards
var enemyCards = [];
var playerCards = [];
for (var i = 0; i < game.boardSlots.length; i++) {
var slotInfo = game.boardSlots[i];
if (slotInfo.slot.card) {
if (slotInfo.y >= 1.5) {
// Enemy side
enemyCards.push(slotInfo.slot.card);
} else {
playerCards.push(slotInfo.slot.card);
}
}
}
// Each enemy card attacks a random player card if available
for (var j = 0; j < enemyCards.length; j++) {
if (playerCards.length > 0) {
var target = playerCards[Math.floor(Math.random() * playerCards.length)];
enemyCards[j].attack(target);
// If target was destroyed, remove from player cards
if (target.currentHealth <= 0) {
var targetIndex = playerCards.indexOf(target);
if (targetIndex !== -1) {
playerCards.splice(targetIndex, 1);
}
}
}
}
// Check for loss condition
checkBattleEnd();
}
// Start player turn
function startPlayerTurn() {
game.currentTurn = "player";
game.turnText.setText("YOUR TURN");
// Increase max energy if less than 10
if (game.maxPlayerEnergy < 10) {
game.maxPlayerEnergy++;
}
// Replenish energy
game.playerEnergy = game.maxPlayerEnergy;
game.energyText.setText("Energy: " + game.playerEnergy + "/" + game.maxPlayerEnergy);
// Draw a card
dealCard();
}
// Check if battle is over
function checkBattleEnd() {
// Count cards for each side
var enemyCardCount = 0;
var playerCardCount = 0;
for (var i = 0; i < game.boardSlots.length; i++) {
var slotInfo = game.boardSlots[i];
if (slotInfo.slot.card) {
if (slotInfo.y >= 1.5) {
// Enemy side
enemyCardCount++;
} else {
playerCardCount++;
}
}
}
// Check win/loss conditions
if (enemyCardCount === 0 && game.enemyDeck.length === 0) {
// Player wins
game.battleWon = true;
showBattleResult("YOU WIN!");
} else if (playerCardCount === 0 && game.playerDeck.length === 0 && game.playerHand.length === 0) {
// Player loses
showBattleResult("YOU LOSE!");
}
}
// Show battle result and return to main menu
function showBattleResult(message) {
// Create result overlay
var resultText = new Text2(message, {
size: 100,
fill: 0xFFFFFF
});
resultText.anchor.set(0.5, 0.5);
resultText.x = 1024;
resultText.y = 1366;
game.addChild(resultText);
// If won, update opponent and add a new card
if (game.battleWon) {
// Move to next opponent
if (game.currentOpponent < opponents.length) {
storage.currentOpponent = game.currentOpponent + 1;
}
// Add a new card to collection if not all collected
if (game.availableCards.length < monsterData.length) {
// Find uncollected cards
var uncollectedCards = monsterData.filter(function (m) {
return !game.availableCards.includes(m.id);
}).map(function (m) {
return m.id;
});
if (uncollectedCards.length > 0) {
// Add random new card
var newCardId = uncollectedCards[Math.floor(Math.random() * uncollectedCards.length)];
storage.collectedCards.push(newCardId);
var newCardText = new Text2("NEW CARD UNLOCKED!", {
size: 60,
fill: 0xFFFF00
});
newCardText.anchor.set(0.5, 0.5);
newCardText.x = 1024;
newCardText.y = 1500;
game.addChild(newCardText);
}
}
}
// Return to main menu button
var menuButton = new Button("MAIN MENU");
menuButton.x = 1024;
menuButton.y = 1800;
menuButton.down = function () {
LK.getSound('button_click').play();
showMainMenu();
};
game.addChild(menuButton);
}
// Utility: Clear all children from screen
function clearScreen() {
while (game.children.length > 0) {
game.children[0].destroy();
}
}
// Utility: Shuffle array
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
// Add to deck in deck builder
game.addToDeck = function (monster) {
// Check if we already have 5 cards
if (game.selectedDeck.length >= 5) {
// Remove another card to make room
var lastCard = game.selectedDeck.pop();
}
game.selectedDeck.push(monster.id);
game.selectedCountText.setText("Selected: " + game.selectedDeck.length + " / 5");
};
// Remove from deck in deck builder
game.removeFromDeck = function (monster) {
var index = game.selectedDeck.indexOf(monster.id);
if (index !== -1) {
game.selectedDeck.splice(index, 1);
game.selectedCountText.setText("Selected: " + game.selectedDeck.length + " / 5");
}
};
// Update game logic
game.update = function () {
if (game.currentScreen === "battle") {
// Any per-frame updates for battle screen
}
};
// Initialize game on start
initGame();