/**** * 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();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,1056 @@
-/****
+/****
+* 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: 0x000000
-});
\ No newline at end of file
+ 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();
\ No newline at end of file