/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Card = Container.expand(function (cardData) { var self = Container.call(this); self.cardData = cardData; self.isSelected = false; var cardBg = self.attachAsset(cardData.element.toLowerCase() + 'CardBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.15 }); var elementGraphic = self.attachAsset(cardData.name.toLowerCase() + 'Card', { anchorX: 0.5, anchorY: 0.5, y: -20 }); var textBg = self.attachAsset('textBackground', { anchorX: 0.5, anchorY: 0.5, y: 95, alpha: 0.7 }); var nameText = new Text2(cardData.name, { size: 24, fill: 0x000000 }); nameText.anchor.set(0.5, 0.5); nameText.x = 0; nameText.y = 70; self.addChild(nameText); var attackText = new Text2('ATK: ' + cardData.attack, { size: 20, fill: 0xcc1010, stroke: 0xFFFFFF, strokeThickness: 2 }); attackText.anchor.set(0.5, 0.5); attackText.y = 95; self.addChild(attackText); var defenseText = new Text2('DEF: ' + cardData.defense, { size: 20, fill: 0x2795c4, stroke: 0xFFFFFF, strokeThickness: 2 }); defenseText.anchor.set(0.5, 0.5); defenseText.y = 120; self.addChild(defenseText); self.setSelected = function (selected) { self.isSelected = selected; if (selected) { self.scaleX = 1.65; // 1.5 * 1.1 to maintain size increase with selection effect self.scaleY = 1.65; // 1.5 * 1.1 to maintain size increase with selection effect } else { self.scaleX = 1.5; // Return to the 50% increased base size to match enemy cards self.scaleY = 1.5; // Return to the 50% increased base size to match enemy cards } }; self.down = function (x, y, obj) { if (gameState === 'selectCard' && !self.isSelected || gameState === 'selectMode' && !self.isSelected) { selectCard(self); LK.getSound('cardSelect').play(); } }; return self; }); var ModeButton = Container.expand(function (mode, color) { var self = Container.call(this); self.mode = mode; var buttonBg = self.attachAsset(mode.toLowerCase() + 'Button', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(mode.toUpperCase(), { size: 45, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function (x, y, obj) { if (gameState === 'selectMode' && selectedCard) { playerMode = mode.toLowerCase(); startBattle(); } }; return self; }); var PlayButton = Container.expand(function () { var self = Container.call(this); var buttonBg = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2('PLAY', { size: 50, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function (x, y, obj) { if (gameState === 'menu') { startGame(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0f1419 }); /**** * Game Code ****/ // Card database // Individual card base assets // Individual card element graphics var cardDatabase = [{ name: 'Sea', element: 'Water', attack: 100, defense: 90 }, { name: 'Rain', element: 'Water', attack: 80, defense: 90 }, { name: 'Tsunami', element: 'Water', attack: 90, defense: 100 }, { name: 'River', element: 'Water', attack: 90, defense: 80 }, { name: 'Ice', element: 'Water', attack: 90, defense: 90 }, { name: 'Inferno', element: 'Fire', attack: 100, defense: 90 }, { name: 'Ember', element: 'Fire', attack: 90, defense: 80 }, { name: 'Lightning', element: 'Fire', attack: 90, defense: 100 }, { name: 'Flame', element: 'Fire', attack: 90, defense: 90 }, { name: 'Spark', element: 'Fire', attack: 80, defense: 90 }, { name: 'Mountain', element: 'Earth', attack: 100, defense: 90 }, { name: 'Stone', element: 'Earth', attack: 90, defense: 80 }, { name: 'Boulder', element: 'Earth', attack: 90, defense: 100 }, { name: 'Sand', element: 'Earth', attack: 80, defense: 90 }, { name: 'Crystal', element: 'Earth', attack: 90, defense: 90 }, { name: 'Tornado', element: 'Air', attack: 100, defense: 90 }, { name: 'Breeze', element: 'Air', attack: 80, defense: 90 }, { name: 'Gale', element: 'Air', attack: 90, defense: 90 }, { name: 'Wind', element: 'Air', attack: 90, defense: 80 }, { name: 'Storm', element: 'Air', attack: 90, defense: 100 }, { name: 'Metal', element: 'Earth', attack: 100, defense: 80 }, { name: 'Cave', element: 'Earth', attack: 80, defense: 100 }, { name: 'Glacier', element: 'Water', attack: 100, defense: 80 }, { name: 'Mist', element: 'Water', attack: 80, defense: 100 }, { name: 'Volcano', element: 'Fire', attack: 100, defense: 80 }, { name: 'Ashes', element: 'Fire', attack: 80, defense: 100 }, { name: 'Cloud', element: 'Air', attack: 80, defense: 100 }, { name: 'Whirlwind', element: 'Air', attack: 100, defense: 80 }, { name: 'Gaia', element: 'Earth', attack: 100, defense: 100 }, { name: 'Moon', element: 'Water', attack: 100, defense: 100 }, { name: 'Sun', element: 'Fire', attack: 100, defense: 100 }, { name: 'Ether', element: 'Air', attack: 100, defense: 100 }]; // Game state variables var gameState = 'menu'; // 'menu', 'selectCard', 'selectMode', 'battle', 'result' var playerHand = []; var enemyHand = []; var usedCards = []; // Track cards that have been used by both players var selectedCard = null; var enemySelectedCard = null; var playerMode = null; var enemyMode = null; var battleResult = null; var playerWins = 0; var enemyWins = 0; // UI elements var handContainer = new Container(); var modeButtons = new Container(); var battleArea = null; var battleSquares = []; var battleSquareContainer = new Container(); var statusText = null; var playerModeText = null; var enemyModeText = null; var enlargedCardContainer = new Container(); var enlargedCard = null; var enemyCardContainer = new Container(); var enemyCard = null; var playerWinsText = null; var enemyWinsText = null; var enemyHandContainer = new Container(); var enemyCardBacks = []; // Menu UI elements var menuContainer = new Container(); var playButton = null; var titleText = null; // Initialize game function initializeGame() { // Reset used cards list usedCards = []; // Deal 5 random cards to each player var shuffledDeck = shuffleArray([].concat(cardDatabase)); for (var i = 0; i < 5; i++) { playerHand.push(shuffledDeck[i]); enemyHand.push(shuffledDeck[i + 5]); // Mark initial cards as used usedCards.push(shuffledDeck[i]); usedCards.push(shuffledDeck[i + 5]); } setupUI(); displayPlayerHand(); displayEnemyHand(); LK.playMusic('backgroundMusic'); } 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; } return array; } function getUnusedCards() { var unused = []; for (var i = 0; i < cardDatabase.length; i++) { var isUsed = false; for (var j = 0; j < usedCards.length; j++) { if (cardDatabase[i].name === usedCards[j].name) { isUsed = true; break; } } if (!isUsed) { unused.push(cardDatabase[i]); } } return unused; } function drawNewCard() { var unusedCards = getUnusedCards(); if (unusedCards.length > 0) { var randomIndex = Math.floor(Math.random() * unusedCards.length); var newCard = unusedCards[randomIndex]; usedCards.push(newCard); return newCard; } return null; // No more unused cards available } function setupMenu() { // Add center background circle behind battle squares var centerBackground = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); centerBackground.x = 1024; centerBackground.y = 1200; game.addChild(centerBackground); // Create 4 squares in circular formation around screen center var radius = 200; var squareAssets = ['battleSquare1', 'battleSquare2', 'battleSquare3', 'battleSquare4']; for (var i = 0; i < 4; i++) { var square = LK.getAsset(squareAssets[i], { anchorX: 0.5, anchorY: 0.5 }); // Initial position in circle around screen center (1024, 1200) var angle = i * Math.PI * 2 / 4; // 90 degrees apart square.x = 1024 + Math.cos(angle) * radius; square.y = 1200 + Math.sin(angle) * radius; square.startAngle = angle; // Store initial angle for parametric motion game.addChild(square); battleSquares.push(square); } // Title text titleText = new Text2('ELEMENTAL BATTLE', { size: 150, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4, font: "serif" }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; menuContainer.addChild(titleText); // Play button playButton = new PlayButton(); playButton.x = 1024; playButton.y = 1600; menuContainer.addChild(playButton); game.addChild(menuContainer); } function setupUI() { // Hand container for player cards handContainer.x = 1024; handContainer.y = 2400; game.addChild(handContainer); // Mode selection buttons var attackButton = new ModeButton('Attack', 0xFF4444); attackButton.x = 800; attackButton.y = 1800; var defenseButton = new ModeButton('Defense', 0x4444FF); defenseButton.x = 1250; defenseButton.y = 1800; modeButtons.addChild(attackButton); modeButtons.addChild(defenseButton); game.addChild(modeButtons); modeButtons.visible = false; // Battle area with 4 rotating squares battleSquareContainer.x = 1024; battleSquareContainer.y = 1200; game.addChild(battleSquareContainer); // Status text statusText = new Text2('Select a card from your hand', { size: 100, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0.5); statusText.x = 1024; statusText.y = 2100; game.addChild(statusText); // Mode display texts playerModeText = new Text2('', { size: 72, fill: 0xFFFF00 }); playerModeText.anchor.set(0.5, 0.5); playerModeText.x = 800; playerModeText.y = 1700; game.addChild(playerModeText); enemyModeText = new Text2('', { size: 72, fill: 0xFF8800 }); enemyModeText.anchor.set(0.5, 0.5); enemyModeText.x = 1248; enemyModeText.y = 700; game.addChild(enemyModeText); // Enlarged card display area enlargedCardContainer.x = 350; enlargedCardContainer.y = 1200; game.addChild(enlargedCardContainer); // Enemy card display area enemyCardContainer.x = 1700; enemyCardContainer.y = 1200; game.addChild(enemyCardContainer); // Player wins counter playerWinsText = new Text2('Player Wins: 0', { size: 60, fill: 0x00FF00 }); playerWinsText.anchor.set(0.5, 0.5); playerWinsText.x = 400; playerWinsText.y = 150; game.addChild(playerWinsText); // Enemy wins counter enemyWinsText = new Text2('Enemy Wins: 0', { size: 60, fill: 0xFF0000 }); enemyWinsText.anchor.set(0.5, 0.5); enemyWinsText.x = 1648; enemyWinsText.y = 150; game.addChild(enemyWinsText); // Enemy hand container for card backs enemyHandContainer.x = 1024; enemyHandContainer.y = 400; game.addChild(enemyHandContainer); } function startGame() { gameState = 'selectCard'; menuContainer.visible = false; // Initialize game first to ensure UI elements exist initializeGame(); // Show all game UI elements (only if they exist) if (handContainer) { handContainer.visible = true; } if (enemyHandContainer) { enemyHandContainer.visible = true; } if (statusText) { statusText.visible = true; } if (playerModeText) { playerModeText.visible = true; } if (enemyModeText) { enemyModeText.visible = true; } if (enlargedCardContainer) { enlargedCardContainer.visible = true; } if (enemyCardContainer) { enemyCardContainer.visible = true; } if (playerWinsText) { playerWinsText.visible = true; } if (enemyWinsText) { enemyWinsText.visible = true; } } function displayPlayerHand() { // Clear existing cards for (var i = handContainer.children.length - 1; i >= 0; i--) { handContainer.removeChild(handContainer.children[i]); } // Display current hand for (var i = 0; i < playerHand.length; i++) { var card = new Card(playerHand[i]); card.scaleX = 1.5; // Match enemy card size card.scaleY = 1.5; // Match enemy card size card.x = (i - 2) * 350; // Increase spacing to 350 to prevent overlap with 1.5 scale card.handIndex = i; handContainer.addChild(card); } } function displayEnemyHand() { // Clear existing card backs for (var i = enemyHandContainer.children.length - 1; i >= 0; i--) { enemyHandContainer.removeChild(enemyHandContainer.children[i]); } enemyCardBacks = []; // Display individual card backs for each card in enemy hand for (var i = 0; i < enemyHand.length; i++) { var cardBack = LK.getAsset(enemyHand[i].element.toLowerCase() + 'CardBack', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); cardBack.x = (i - 2) * 280; // Same spacing as player cards cardBack.element = enemyHand[i].element; enemyHandContainer.addChild(cardBack); enemyCardBacks.push(cardBack); } } function selectCard(cardObj) { // If this card is already selected and we're in selectMode, don't do anything if (selectedCard === cardObj && gameState === 'selectMode') { return; } // Deselect all cards for (var i = 0; i < handContainer.children.length; i++) { handContainer.children[i].setSelected(false); } // Select this card cardObj.setSelected(true); selectedCard = cardObj; // Clear previous enlarged card with animation if it exists if (enlargedCard) { tween.stop(enlargedCard); tween(enlargedCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { enlargedCardContainer.removeChild(enlargedCard); enlargedCard = null; // Create new enlarged card after old one is removed createEnlargedCard(cardObj); } }); } else { // No previous enlarged card, create new one immediately createEnlargedCard(cardObj); } // Move to mode selection only if not already there if (gameState !== 'selectMode') { gameState = 'selectMode'; statusText.setText('Choose Attack or Defense mode'); modeButtons.visible = true; } } function createEnlargedCard(cardObj) { // Create enlarged version of selected card enlargedCard = new Card(cardObj.cardData); // If in battle, show bonus stats if (gameState === 'battle' && enemySelectedCard) { var hasAdvantage = hasTypeAdvantage(cardObj.cardData.element, enemySelectedCard.element); if (hasAdvantage) { // Update the card's display to show bonus stats for (var i = 0; i < enlargedCard.children.length; i++) { var child = enlargedCard.children[i]; if (child instanceof Text2) { if (child.text && child.text.indexOf('ATK:') !== -1) { var baseAttack = cardObj.cardData.attack; child.setText('ATK: ' + baseAttack + ' + 10'); } else if (child.text && child.text.indexOf('DEF:') !== -1) { var baseDefense = cardObj.cardData.defense; child.setText('DEF: ' + baseDefense + ' + 10'); } } } // Add large "+10" bonus text var bonusText = new Text2('+ 10', { size: 80, fill: 0x00FF00, stroke: 0xFFFFFF, strokeThickness: 3 }); bonusText.anchor.set(0.5, 0.5); bonusText.x = 0; bonusText.y = -80; enlargedCard.addChild(bonusText); } } enlargedCard.scaleX = 2.75; enlargedCard.scaleY = 2.75; enlargedCard.x = 0; enlargedCard.y = 0; // Start with enlarged card invisible and tween it in enlargedCard.alpha = 0; enlargedCard.scaleX = 0.5; enlargedCard.scaleY = 0.5; enlargedCardContainer.addChild(enlargedCard); // Animate enlarged card appearing tween(enlargedCard, { alpha: 1, scaleX: 2.75, scaleY: 2.75 }, { duration: 300, easing: tween.easeOut }); } function createEnemyCardPreview(cardData) { // Clear previous enemy card if it exists if (enemyCard) { tween.stop(enemyCard); tween(enemyCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { enemyCardContainer.removeChild(enemyCard); enemyCard = null; // Create new enemy card after old one is removed createNewEnemyCard(cardData); } }); } else { // No previous enemy card, create new one immediately createNewEnemyCard(cardData); } } function createNewEnemyCard(cardData) { // Create enlarged version of enemy's selected card enemyCard = new Card(cardData); // If in battle, show bonus stats if (gameState === 'battle' && selectedCard) { var hasAdvantage = hasTypeAdvantage(cardData.element, selectedCard.cardData.element); if (hasAdvantage) { // Update the card's display to show bonus stats for (var i = 0; i < enemyCard.children.length; i++) { var child = enemyCard.children[i]; if (child instanceof Text2) { if (child.text && child.text.indexOf('ATK:') !== -1) { var baseAttack = cardData.attack; child.setText('ATK: ' + baseAttack + ' + 10'); } else if (child.text && child.text.indexOf('DEF:') !== -1) { var baseDefense = cardData.defense; child.setText('DEF: ' + baseDefense + ' + 10'); } } } // Add large "+10" bonus text var bonusText = new Text2('+ 10', { size: 80, fill: 0x00FF00, stroke: 0xFFFFFF, strokeThickness: 3 }); bonusText.anchor.set(0.5, 0.5); bonusText.x = 0; bonusText.y = -80; enemyCard.addChild(bonusText); } } enemyCard.scaleX = 2.75; enemyCard.scaleY = 2.75; enemyCard.x = 0; enemyCard.y = 0; // Start with enemy card invisible and tween it in enemyCard.alpha = 0; enemyCard.scaleX = 0.5; enemyCard.scaleY = 0.5; enemyCardContainer.addChild(enemyCard); // Animate enemy card appearing tween(enemyCard, { alpha: 1, scaleX: 2.75, scaleY: 2.75 }, { duration: 300, easing: tween.easeOut }); } function startBattle() { gameState = 'battle'; modeButtons.visible = false; // Clear enlarged card display before battle starts if (enlargedCard) { tween(enlargedCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { enlargedCardContainer.removeChild(enlargedCard); enlargedCard = null; } }); } // Enemy AI selects card and mode var enemyCardIndex = Math.floor(Math.random() * enemyHand.length); enemySelectedCard = enemyHand[enemyCardIndex]; enemyMode = Math.random() < 0.5 ? 'attack' : 'defense'; // Display selected cards and modes statusText.setText('Battle in progress...'); playerModeText.setText('Player: ' + playerMode.toUpperCase()); enemyModeText.setText('Enemy: ' + enemyMode.toUpperCase()); // Show enlarged cards with battle stats after a brief delay LK.setTimeout(function () { // Update player enlarged card to show bonus stats if applicable if (selectedCard) { createEnlargedCard(selectedCard); } // Show enemy card preview createEnemyCardPreview(enemySelectedCard); }, 300); // Resolve battle after a delay LK.setTimeout(function () { resolveBattle(); }, 2500); LK.getSound('cardBattle').play(); } function resolveBattle() { var playerValue, enemyValue; var playerCard = selectedCard.cardData; var enemyCard = enemySelectedCard; // Check type advantages: Fire > Air > Water > Earth > Fire var playerAdvantage = hasTypeAdvantage(playerCard.element, enemyCard.element); var enemyAdvantage = hasTypeAdvantage(enemyCard.element, playerCard.element); // Determine values based on modes if (playerMode === 'attack') { playerValue = playerCard.attack; } else { playerValue = playerCard.defense; } if (enemyMode === 'attack') { enemyValue = enemyCard.attack; } else { enemyValue = enemyCard.defense; } // Apply type advantage bonuses if (playerAdvantage) { playerValue += 10; } if (enemyAdvantage) { enemyValue += 10; } // Resolve battle outcome var resultText = ''; if (playerMode === 'defense' && enemyMode === 'defense') { // Both defense - both cards return to hand resultText = 'Both defended - cards returned to hand'; battleResult = 'tie'; } else if (playerValue > enemyValue) { // Player wins resultText = 'You win this round!'; battleResult = 'playerWin'; playerWins++; playerWinsText.setText('Player Wins: ' + playerWins); // Discard both cards - add both to used cards and replace with new ones usedCards.push(enemySelectedCard); usedCards.push(selectedCard.cardData); // Replace enemy card var enemyIndex = enemyHand.indexOf(enemySelectedCard); var newEnemyCard = drawNewCard(); if (newEnemyCard) { enemyHand[enemyIndex] = newEnemyCard; } else { enemyHand.splice(enemyIndex, 1); } // Replace player card var playerIndex = selectedCard.handIndex; var newPlayerCard = drawNewCard(); if (newPlayerCard) { playerHand[playerIndex] = newPlayerCard; } else { playerHand.splice(playerIndex, 1); } displayEnemyHand(); LK.getSound('cardWin').play(); } else if (enemyValue > playerValue) { // Enemy wins resultText = 'Enemy wins this round!'; battleResult = 'enemyWin'; enemyWins++; enemyWinsText.setText('Enemy Wins: ' + enemyWins); // Discard both cards - add both to used cards and replace with new ones usedCards.push(selectedCard.cardData); usedCards.push(enemySelectedCard); // Replace player card var playerIndex = selectedCard.handIndex; var newPlayerCard = drawNewCard(); if (newPlayerCard) { playerHand[playerIndex] = newPlayerCard; } else { playerHand.splice(playerIndex, 1); } // Replace enemy card var enemyIndex = enemyHand.indexOf(enemySelectedCard); var newEnemyCard = drawNewCard(); if (newEnemyCard) { enemyHand[enemyIndex] = newEnemyCard; } else { enemyHand.splice(enemyIndex, 1); } displayEnemyHand(); LK.getSound('cardLose').play(); } else { // Tie - both cards return to hand resultText = 'Tie - both cards returned to hand'; battleResult = 'tie'; } statusText.setText(resultText); // Check win conditions LK.setTimeout(function () { checkWinCondition(); }, 2500); } function hasTypeAdvantage(attacker, defender) { // Fire > Air > Water > Earth > Fire var advantages = { 'Fire': 'Air', 'Air': 'Water', 'Water': 'Earth', 'Earth': 'Fire' }; return advantages[attacker] === defender; } function checkWinCondition() { if (playerWins >= 5) { statusText.setText('Victory - You won 5 rounds!'); LK.setScore(playerWins * 100); // Reset game state and return to menu LK.setTimeout(function () { resetGameToMenu(); }, 2000); return; } else if (enemyWins >= 5) { statusText.setText('Game Over - Enemy won 5 rounds!'); // Reset game state and return to menu LK.setTimeout(function () { resetGameToMenu(); }, 2000); return; } // Continue to next round resetForNextRound(); } function resetForNextRound() { selectedCard = null; enemySelectedCard = null; playerMode = null; enemyMode = null; battleResult = null; playerModeText.setText(''); enemyModeText.setText(''); gameState = 'selectCard'; statusText.setText('Select a card from your hand'); // Clear enlarged card display if (enlargedCard) { tween(enlargedCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { enlargedCardContainer.removeChild(enlargedCard); enlargedCard = null; } }); } // Clear enemy card display if (enemyCard) { tween(enemyCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { enemyCardContainer.removeChild(enemyCard); enemyCard = null; } }); } displayPlayerHand(); } // Initialize the menu setupMenu(); LK.playMusic('backgroundMusic'); game.update = function () { // Update battle squares using parametric circle equations (they rotate even in menu) var time = LK.ticks * 0.02; // Control animation speed var radius = 200; var centerX = 1024; var centerY = 1200; for (var i = 0; i < battleSquares.length; i++) { var square = battleSquares[i]; if (square && square.startAngle !== undefined) { // Parametric circle: x = centerX + radius * cos(angle + time), y = centerY + radius * sin(angle + time) var angle = square.startAngle + time; square.x = centerX + radius * Math.cos(angle); square.y = centerY + radius * Math.sin(angle); } } // Update game logic if needed }; function resetGameToMenu() { // Reset all game state variables gameState = 'menu'; playerHand = []; enemyHand = []; usedCards = []; selectedCard = null; enemySelectedCard = null; playerMode = null; enemyMode = null; battleResult = null; playerWins = 0; enemyWins = 0; // Clear all UI containers for (var i = handContainer.children.length - 1; i >= 0; i--) { handContainer.removeChild(handContainer.children[i]); } for (var i = enemyHandContainer.children.length - 1; i >= 0; i--) { enemyHandContainer.removeChild(enemyHandContainer.children[i]); } if (enlargedCard) { enlargedCardContainer.removeChild(enlargedCard); enlargedCard = null; } if (enemyCard) { enemyCardContainer.removeChild(enemyCard); enemyCard = null; } // Reset UI text (only if elements exist) if (statusText) { statusText.setText(''); statusText.visible = false; } if (playerModeText) { playerModeText.setText(''); playerModeText.visible = false; } if (enemyModeText) { enemyModeText.setText(''); enemyModeText.visible = false; } if (playerWinsText) { playerWinsText.setText('Player Wins: 0'); playerWinsText.visible = false; } if (enemyWinsText) { enemyWinsText.setText('Enemy Wins: 0'); enemyWinsText.visible = false; } // Hide game UI elements (only if they exist) if (modeButtons) { modeButtons.visible = false; } if (handContainer) { handContainer.visible = false; } if (enemyHandContainer) { enemyHandContainer.visible = false; } if (enlargedCardContainer) { enlargedCardContainer.visible = false; } if (enemyCardContainer) { enemyCardContainer.visible = false; } // Show menu menuContainer.visible = true; }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Card = Container.expand(function (cardData) {
var self = Container.call(this);
self.cardData = cardData;
self.isSelected = false;
var cardBg = self.attachAsset(cardData.element.toLowerCase() + 'CardBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.15
});
var elementGraphic = self.attachAsset(cardData.name.toLowerCase() + 'Card', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
var textBg = self.attachAsset('textBackground', {
anchorX: 0.5,
anchorY: 0.5,
y: 95,
alpha: 0.7
});
var nameText = new Text2(cardData.name, {
size: 24,
fill: 0x000000
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 0;
nameText.y = 70;
self.addChild(nameText);
var attackText = new Text2('ATK: ' + cardData.attack, {
size: 20,
fill: 0xcc1010,
stroke: 0xFFFFFF,
strokeThickness: 2
});
attackText.anchor.set(0.5, 0.5);
attackText.y = 95;
self.addChild(attackText);
var defenseText = new Text2('DEF: ' + cardData.defense, {
size: 20,
fill: 0x2795c4,
stroke: 0xFFFFFF,
strokeThickness: 2
});
defenseText.anchor.set(0.5, 0.5);
defenseText.y = 120;
self.addChild(defenseText);
self.setSelected = function (selected) {
self.isSelected = selected;
if (selected) {
self.scaleX = 1.65; // 1.5 * 1.1 to maintain size increase with selection effect
self.scaleY = 1.65; // 1.5 * 1.1 to maintain size increase with selection effect
} else {
self.scaleX = 1.5; // Return to the 50% increased base size to match enemy cards
self.scaleY = 1.5; // Return to the 50% increased base size to match enemy cards
}
};
self.down = function (x, y, obj) {
if (gameState === 'selectCard' && !self.isSelected || gameState === 'selectMode' && !self.isSelected) {
selectCard(self);
LK.getSound('cardSelect').play();
}
};
return self;
});
var ModeButton = Container.expand(function (mode, color) {
var self = Container.call(this);
self.mode = mode;
var buttonBg = self.attachAsset(mode.toLowerCase() + 'Button', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(mode.toUpperCase(), {
size: 45,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
if (gameState === 'selectMode' && selectedCard) {
playerMode = mode.toLowerCase();
startBattle();
}
};
return self;
});
var PlayButton = Container.expand(function () {
var self = Container.call(this);
var buttonBg = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2('PLAY', {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0f1419
});
/****
* Game Code
****/
// Card database
// Individual card base assets
// Individual card element graphics
var cardDatabase = [{
name: 'Sea',
element: 'Water',
attack: 100,
defense: 90
}, {
name: 'Rain',
element: 'Water',
attack: 80,
defense: 90
}, {
name: 'Tsunami',
element: 'Water',
attack: 90,
defense: 100
}, {
name: 'River',
element: 'Water',
attack: 90,
defense: 80
}, {
name: 'Ice',
element: 'Water',
attack: 90,
defense: 90
}, {
name: 'Inferno',
element: 'Fire',
attack: 100,
defense: 90
}, {
name: 'Ember',
element: 'Fire',
attack: 90,
defense: 80
}, {
name: 'Lightning',
element: 'Fire',
attack: 90,
defense: 100
}, {
name: 'Flame',
element: 'Fire',
attack: 90,
defense: 90
}, {
name: 'Spark',
element: 'Fire',
attack: 80,
defense: 90
}, {
name: 'Mountain',
element: 'Earth',
attack: 100,
defense: 90
}, {
name: 'Stone',
element: 'Earth',
attack: 90,
defense: 80
}, {
name: 'Boulder',
element: 'Earth',
attack: 90,
defense: 100
}, {
name: 'Sand',
element: 'Earth',
attack: 80,
defense: 90
}, {
name: 'Crystal',
element: 'Earth',
attack: 90,
defense: 90
}, {
name: 'Tornado',
element: 'Air',
attack: 100,
defense: 90
}, {
name: 'Breeze',
element: 'Air',
attack: 80,
defense: 90
}, {
name: 'Gale',
element: 'Air',
attack: 90,
defense: 90
}, {
name: 'Wind',
element: 'Air',
attack: 90,
defense: 80
}, {
name: 'Storm',
element: 'Air',
attack: 90,
defense: 100
}, {
name: 'Metal',
element: 'Earth',
attack: 100,
defense: 80
}, {
name: 'Cave',
element: 'Earth',
attack: 80,
defense: 100
}, {
name: 'Glacier',
element: 'Water',
attack: 100,
defense: 80
}, {
name: 'Mist',
element: 'Water',
attack: 80,
defense: 100
}, {
name: 'Volcano',
element: 'Fire',
attack: 100,
defense: 80
}, {
name: 'Ashes',
element: 'Fire',
attack: 80,
defense: 100
}, {
name: 'Cloud',
element: 'Air',
attack: 80,
defense: 100
}, {
name: 'Whirlwind',
element: 'Air',
attack: 100,
defense: 80
}, {
name: 'Gaia',
element: 'Earth',
attack: 100,
defense: 100
}, {
name: 'Moon',
element: 'Water',
attack: 100,
defense: 100
}, {
name: 'Sun',
element: 'Fire',
attack: 100,
defense: 100
}, {
name: 'Ether',
element: 'Air',
attack: 100,
defense: 100
}];
// Game state variables
var gameState = 'menu'; // 'menu', 'selectCard', 'selectMode', 'battle', 'result'
var playerHand = [];
var enemyHand = [];
var usedCards = []; // Track cards that have been used by both players
var selectedCard = null;
var enemySelectedCard = null;
var playerMode = null;
var enemyMode = null;
var battleResult = null;
var playerWins = 0;
var enemyWins = 0;
// UI elements
var handContainer = new Container();
var modeButtons = new Container();
var battleArea = null;
var battleSquares = [];
var battleSquareContainer = new Container();
var statusText = null;
var playerModeText = null;
var enemyModeText = null;
var enlargedCardContainer = new Container();
var enlargedCard = null;
var enemyCardContainer = new Container();
var enemyCard = null;
var playerWinsText = null;
var enemyWinsText = null;
var enemyHandContainer = new Container();
var enemyCardBacks = [];
// Menu UI elements
var menuContainer = new Container();
var playButton = null;
var titleText = null;
// Initialize game
function initializeGame() {
// Reset used cards list
usedCards = [];
// Deal 5 random cards to each player
var shuffledDeck = shuffleArray([].concat(cardDatabase));
for (var i = 0; i < 5; i++) {
playerHand.push(shuffledDeck[i]);
enemyHand.push(shuffledDeck[i + 5]);
// Mark initial cards as used
usedCards.push(shuffledDeck[i]);
usedCards.push(shuffledDeck[i + 5]);
}
setupUI();
displayPlayerHand();
displayEnemyHand();
LK.playMusic('backgroundMusic');
}
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;
}
return array;
}
function getUnusedCards() {
var unused = [];
for (var i = 0; i < cardDatabase.length; i++) {
var isUsed = false;
for (var j = 0; j < usedCards.length; j++) {
if (cardDatabase[i].name === usedCards[j].name) {
isUsed = true;
break;
}
}
if (!isUsed) {
unused.push(cardDatabase[i]);
}
}
return unused;
}
function drawNewCard() {
var unusedCards = getUnusedCards();
if (unusedCards.length > 0) {
var randomIndex = Math.floor(Math.random() * unusedCards.length);
var newCard = unusedCards[randomIndex];
usedCards.push(newCard);
return newCard;
}
return null; // No more unused cards available
}
function setupMenu() {
// Add center background circle behind battle squares
var centerBackground = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
centerBackground.x = 1024;
centerBackground.y = 1200;
game.addChild(centerBackground);
// Create 4 squares in circular formation around screen center
var radius = 200;
var squareAssets = ['battleSquare1', 'battleSquare2', 'battleSquare3', 'battleSquare4'];
for (var i = 0; i < 4; i++) {
var square = LK.getAsset(squareAssets[i], {
anchorX: 0.5,
anchorY: 0.5
});
// Initial position in circle around screen center (1024, 1200)
var angle = i * Math.PI * 2 / 4; // 90 degrees apart
square.x = 1024 + Math.cos(angle) * radius;
square.y = 1200 + Math.sin(angle) * radius;
square.startAngle = angle; // Store initial angle for parametric motion
game.addChild(square);
battleSquares.push(square);
}
// Title text
titleText = new Text2('ELEMENTAL BATTLE', {
size: 150,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4,
font: "serif"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
menuContainer.addChild(titleText);
// Play button
playButton = new PlayButton();
playButton.x = 1024;
playButton.y = 1600;
menuContainer.addChild(playButton);
game.addChild(menuContainer);
}
function setupUI() {
// Hand container for player cards
handContainer.x = 1024;
handContainer.y = 2400;
game.addChild(handContainer);
// Mode selection buttons
var attackButton = new ModeButton('Attack', 0xFF4444);
attackButton.x = 800;
attackButton.y = 1800;
var defenseButton = new ModeButton('Defense', 0x4444FF);
defenseButton.x = 1250;
defenseButton.y = 1800;
modeButtons.addChild(attackButton);
modeButtons.addChild(defenseButton);
game.addChild(modeButtons);
modeButtons.visible = false;
// Battle area with 4 rotating squares
battleSquareContainer.x = 1024;
battleSquareContainer.y = 1200;
game.addChild(battleSquareContainer);
// Status text
statusText = new Text2('Select a card from your hand', {
size: 100,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 1024;
statusText.y = 2100;
game.addChild(statusText);
// Mode display texts
playerModeText = new Text2('', {
size: 72,
fill: 0xFFFF00
});
playerModeText.anchor.set(0.5, 0.5);
playerModeText.x = 800;
playerModeText.y = 1700;
game.addChild(playerModeText);
enemyModeText = new Text2('', {
size: 72,
fill: 0xFF8800
});
enemyModeText.anchor.set(0.5, 0.5);
enemyModeText.x = 1248;
enemyModeText.y = 700;
game.addChild(enemyModeText);
// Enlarged card display area
enlargedCardContainer.x = 350;
enlargedCardContainer.y = 1200;
game.addChild(enlargedCardContainer);
// Enemy card display area
enemyCardContainer.x = 1700;
enemyCardContainer.y = 1200;
game.addChild(enemyCardContainer);
// Player wins counter
playerWinsText = new Text2('Player Wins: 0', {
size: 60,
fill: 0x00FF00
});
playerWinsText.anchor.set(0.5, 0.5);
playerWinsText.x = 400;
playerWinsText.y = 150;
game.addChild(playerWinsText);
// Enemy wins counter
enemyWinsText = new Text2('Enemy Wins: 0', {
size: 60,
fill: 0xFF0000
});
enemyWinsText.anchor.set(0.5, 0.5);
enemyWinsText.x = 1648;
enemyWinsText.y = 150;
game.addChild(enemyWinsText);
// Enemy hand container for card backs
enemyHandContainer.x = 1024;
enemyHandContainer.y = 400;
game.addChild(enemyHandContainer);
}
function startGame() {
gameState = 'selectCard';
menuContainer.visible = false;
// Initialize game first to ensure UI elements exist
initializeGame();
// Show all game UI elements (only if they exist)
if (handContainer) {
handContainer.visible = true;
}
if (enemyHandContainer) {
enemyHandContainer.visible = true;
}
if (statusText) {
statusText.visible = true;
}
if (playerModeText) {
playerModeText.visible = true;
}
if (enemyModeText) {
enemyModeText.visible = true;
}
if (enlargedCardContainer) {
enlargedCardContainer.visible = true;
}
if (enemyCardContainer) {
enemyCardContainer.visible = true;
}
if (playerWinsText) {
playerWinsText.visible = true;
}
if (enemyWinsText) {
enemyWinsText.visible = true;
}
}
function displayPlayerHand() {
// Clear existing cards
for (var i = handContainer.children.length - 1; i >= 0; i--) {
handContainer.removeChild(handContainer.children[i]);
}
// Display current hand
for (var i = 0; i < playerHand.length; i++) {
var card = new Card(playerHand[i]);
card.scaleX = 1.5; // Match enemy card size
card.scaleY = 1.5; // Match enemy card size
card.x = (i - 2) * 350; // Increase spacing to 350 to prevent overlap with 1.5 scale
card.handIndex = i;
handContainer.addChild(card);
}
}
function displayEnemyHand() {
// Clear existing card backs
for (var i = enemyHandContainer.children.length - 1; i >= 0; i--) {
enemyHandContainer.removeChild(enemyHandContainer.children[i]);
}
enemyCardBacks = [];
// Display individual card backs for each card in enemy hand
for (var i = 0; i < enemyHand.length; i++) {
var cardBack = LK.getAsset(enemyHand[i].element.toLowerCase() + 'CardBack', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
cardBack.x = (i - 2) * 280; // Same spacing as player cards
cardBack.element = enemyHand[i].element;
enemyHandContainer.addChild(cardBack);
enemyCardBacks.push(cardBack);
}
}
function selectCard(cardObj) {
// If this card is already selected and we're in selectMode, don't do anything
if (selectedCard === cardObj && gameState === 'selectMode') {
return;
}
// Deselect all cards
for (var i = 0; i < handContainer.children.length; i++) {
handContainer.children[i].setSelected(false);
}
// Select this card
cardObj.setSelected(true);
selectedCard = cardObj;
// Clear previous enlarged card with animation if it exists
if (enlargedCard) {
tween.stop(enlargedCard);
tween(enlargedCard, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
enlargedCardContainer.removeChild(enlargedCard);
enlargedCard = null;
// Create new enlarged card after old one is removed
createEnlargedCard(cardObj);
}
});
} else {
// No previous enlarged card, create new one immediately
createEnlargedCard(cardObj);
}
// Move to mode selection only if not already there
if (gameState !== 'selectMode') {
gameState = 'selectMode';
statusText.setText('Choose Attack or Defense mode');
modeButtons.visible = true;
}
}
function createEnlargedCard(cardObj) {
// Create enlarged version of selected card
enlargedCard = new Card(cardObj.cardData);
// If in battle, show bonus stats
if (gameState === 'battle' && enemySelectedCard) {
var hasAdvantage = hasTypeAdvantage(cardObj.cardData.element, enemySelectedCard.element);
if (hasAdvantage) {
// Update the card's display to show bonus stats
for (var i = 0; i < enlargedCard.children.length; i++) {
var child = enlargedCard.children[i];
if (child instanceof Text2) {
if (child.text && child.text.indexOf('ATK:') !== -1) {
var baseAttack = cardObj.cardData.attack;
child.setText('ATK: ' + baseAttack + ' + 10');
} else if (child.text && child.text.indexOf('DEF:') !== -1) {
var baseDefense = cardObj.cardData.defense;
child.setText('DEF: ' + baseDefense + ' + 10');
}
}
}
// Add large "+10" bonus text
var bonusText = new Text2('+ 10', {
size: 80,
fill: 0x00FF00,
stroke: 0xFFFFFF,
strokeThickness: 3
});
bonusText.anchor.set(0.5, 0.5);
bonusText.x = 0;
bonusText.y = -80;
enlargedCard.addChild(bonusText);
}
}
enlargedCard.scaleX = 2.75;
enlargedCard.scaleY = 2.75;
enlargedCard.x = 0;
enlargedCard.y = 0;
// Start with enlarged card invisible and tween it in
enlargedCard.alpha = 0;
enlargedCard.scaleX = 0.5;
enlargedCard.scaleY = 0.5;
enlargedCardContainer.addChild(enlargedCard);
// Animate enlarged card appearing
tween(enlargedCard, {
alpha: 1,
scaleX: 2.75,
scaleY: 2.75
}, {
duration: 300,
easing: tween.easeOut
});
}
function createEnemyCardPreview(cardData) {
// Clear previous enemy card if it exists
if (enemyCard) {
tween.stop(enemyCard);
tween(enemyCard, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
enemyCardContainer.removeChild(enemyCard);
enemyCard = null;
// Create new enemy card after old one is removed
createNewEnemyCard(cardData);
}
});
} else {
// No previous enemy card, create new one immediately
createNewEnemyCard(cardData);
}
}
function createNewEnemyCard(cardData) {
// Create enlarged version of enemy's selected card
enemyCard = new Card(cardData);
// If in battle, show bonus stats
if (gameState === 'battle' && selectedCard) {
var hasAdvantage = hasTypeAdvantage(cardData.element, selectedCard.cardData.element);
if (hasAdvantage) {
// Update the card's display to show bonus stats
for (var i = 0; i < enemyCard.children.length; i++) {
var child = enemyCard.children[i];
if (child instanceof Text2) {
if (child.text && child.text.indexOf('ATK:') !== -1) {
var baseAttack = cardData.attack;
child.setText('ATK: ' + baseAttack + ' + 10');
} else if (child.text && child.text.indexOf('DEF:') !== -1) {
var baseDefense = cardData.defense;
child.setText('DEF: ' + baseDefense + ' + 10');
}
}
}
// Add large "+10" bonus text
var bonusText = new Text2('+ 10', {
size: 80,
fill: 0x00FF00,
stroke: 0xFFFFFF,
strokeThickness: 3
});
bonusText.anchor.set(0.5, 0.5);
bonusText.x = 0;
bonusText.y = -80;
enemyCard.addChild(bonusText);
}
}
enemyCard.scaleX = 2.75;
enemyCard.scaleY = 2.75;
enemyCard.x = 0;
enemyCard.y = 0;
// Start with enemy card invisible and tween it in
enemyCard.alpha = 0;
enemyCard.scaleX = 0.5;
enemyCard.scaleY = 0.5;
enemyCardContainer.addChild(enemyCard);
// Animate enemy card appearing
tween(enemyCard, {
alpha: 1,
scaleX: 2.75,
scaleY: 2.75
}, {
duration: 300,
easing: tween.easeOut
});
}
function startBattle() {
gameState = 'battle';
modeButtons.visible = false;
// Clear enlarged card display before battle starts
if (enlargedCard) {
tween(enlargedCard, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
enlargedCardContainer.removeChild(enlargedCard);
enlargedCard = null;
}
});
}
// Enemy AI selects card and mode
var enemyCardIndex = Math.floor(Math.random() * enemyHand.length);
enemySelectedCard = enemyHand[enemyCardIndex];
enemyMode = Math.random() < 0.5 ? 'attack' : 'defense';
// Display selected cards and modes
statusText.setText('Battle in progress...');
playerModeText.setText('Player: ' + playerMode.toUpperCase());
enemyModeText.setText('Enemy: ' + enemyMode.toUpperCase());
// Show enlarged cards with battle stats after a brief delay
LK.setTimeout(function () {
// Update player enlarged card to show bonus stats if applicable
if (selectedCard) {
createEnlargedCard(selectedCard);
}
// Show enemy card preview
createEnemyCardPreview(enemySelectedCard);
}, 300);
// Resolve battle after a delay
LK.setTimeout(function () {
resolveBattle();
}, 2500);
LK.getSound('cardBattle').play();
}
function resolveBattle() {
var playerValue, enemyValue;
var playerCard = selectedCard.cardData;
var enemyCard = enemySelectedCard;
// Check type advantages: Fire > Air > Water > Earth > Fire
var playerAdvantage = hasTypeAdvantage(playerCard.element, enemyCard.element);
var enemyAdvantage = hasTypeAdvantage(enemyCard.element, playerCard.element);
// Determine values based on modes
if (playerMode === 'attack') {
playerValue = playerCard.attack;
} else {
playerValue = playerCard.defense;
}
if (enemyMode === 'attack') {
enemyValue = enemyCard.attack;
} else {
enemyValue = enemyCard.defense;
}
// Apply type advantage bonuses
if (playerAdvantage) {
playerValue += 10;
}
if (enemyAdvantage) {
enemyValue += 10;
}
// Resolve battle outcome
var resultText = '';
if (playerMode === 'defense' && enemyMode === 'defense') {
// Both defense - both cards return to hand
resultText = 'Both defended - cards returned to hand';
battleResult = 'tie';
} else if (playerValue > enemyValue) {
// Player wins
resultText = 'You win this round!';
battleResult = 'playerWin';
playerWins++;
playerWinsText.setText('Player Wins: ' + playerWins);
// Discard both cards - add both to used cards and replace with new ones
usedCards.push(enemySelectedCard);
usedCards.push(selectedCard.cardData);
// Replace enemy card
var enemyIndex = enemyHand.indexOf(enemySelectedCard);
var newEnemyCard = drawNewCard();
if (newEnemyCard) {
enemyHand[enemyIndex] = newEnemyCard;
} else {
enemyHand.splice(enemyIndex, 1);
}
// Replace player card
var playerIndex = selectedCard.handIndex;
var newPlayerCard = drawNewCard();
if (newPlayerCard) {
playerHand[playerIndex] = newPlayerCard;
} else {
playerHand.splice(playerIndex, 1);
}
displayEnemyHand();
LK.getSound('cardWin').play();
} else if (enemyValue > playerValue) {
// Enemy wins
resultText = 'Enemy wins this round!';
battleResult = 'enemyWin';
enemyWins++;
enemyWinsText.setText('Enemy Wins: ' + enemyWins);
// Discard both cards - add both to used cards and replace with new ones
usedCards.push(selectedCard.cardData);
usedCards.push(enemySelectedCard);
// Replace player card
var playerIndex = selectedCard.handIndex;
var newPlayerCard = drawNewCard();
if (newPlayerCard) {
playerHand[playerIndex] = newPlayerCard;
} else {
playerHand.splice(playerIndex, 1);
}
// Replace enemy card
var enemyIndex = enemyHand.indexOf(enemySelectedCard);
var newEnemyCard = drawNewCard();
if (newEnemyCard) {
enemyHand[enemyIndex] = newEnemyCard;
} else {
enemyHand.splice(enemyIndex, 1);
}
displayEnemyHand();
LK.getSound('cardLose').play();
} else {
// Tie - both cards return to hand
resultText = 'Tie - both cards returned to hand';
battleResult = 'tie';
}
statusText.setText(resultText);
// Check win conditions
LK.setTimeout(function () {
checkWinCondition();
}, 2500);
}
function hasTypeAdvantage(attacker, defender) {
// Fire > Air > Water > Earth > Fire
var advantages = {
'Fire': 'Air',
'Air': 'Water',
'Water': 'Earth',
'Earth': 'Fire'
};
return advantages[attacker] === defender;
}
function checkWinCondition() {
if (playerWins >= 5) {
statusText.setText('Victory - You won 5 rounds!');
LK.setScore(playerWins * 100);
// Reset game state and return to menu
LK.setTimeout(function () {
resetGameToMenu();
}, 2000);
return;
} else if (enemyWins >= 5) {
statusText.setText('Game Over - Enemy won 5 rounds!');
// Reset game state and return to menu
LK.setTimeout(function () {
resetGameToMenu();
}, 2000);
return;
}
// Continue to next round
resetForNextRound();
}
function resetForNextRound() {
selectedCard = null;
enemySelectedCard = null;
playerMode = null;
enemyMode = null;
battleResult = null;
playerModeText.setText('');
enemyModeText.setText('');
gameState = 'selectCard';
statusText.setText('Select a card from your hand');
// Clear enlarged card display
if (enlargedCard) {
tween(enlargedCard, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
enlargedCardContainer.removeChild(enlargedCard);
enlargedCard = null;
}
});
}
// Clear enemy card display
if (enemyCard) {
tween(enemyCard, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
enemyCardContainer.removeChild(enemyCard);
enemyCard = null;
}
});
}
displayPlayerHand();
}
// Initialize the menu
setupMenu();
LK.playMusic('backgroundMusic');
game.update = function () {
// Update battle squares using parametric circle equations (they rotate even in menu)
var time = LK.ticks * 0.02; // Control animation speed
var radius = 200;
var centerX = 1024;
var centerY = 1200;
for (var i = 0; i < battleSquares.length; i++) {
var square = battleSquares[i];
if (square && square.startAngle !== undefined) {
// Parametric circle: x = centerX + radius * cos(angle + time), y = centerY + radius * sin(angle + time)
var angle = square.startAngle + time;
square.x = centerX + radius * Math.cos(angle);
square.y = centerY + radius * Math.sin(angle);
}
}
// Update game logic if needed
};
function resetGameToMenu() {
// Reset all game state variables
gameState = 'menu';
playerHand = [];
enemyHand = [];
usedCards = [];
selectedCard = null;
enemySelectedCard = null;
playerMode = null;
enemyMode = null;
battleResult = null;
playerWins = 0;
enemyWins = 0;
// Clear all UI containers
for (var i = handContainer.children.length - 1; i >= 0; i--) {
handContainer.removeChild(handContainer.children[i]);
}
for (var i = enemyHandContainer.children.length - 1; i >= 0; i--) {
enemyHandContainer.removeChild(enemyHandContainer.children[i]);
}
if (enlargedCard) {
enlargedCardContainer.removeChild(enlargedCard);
enlargedCard = null;
}
if (enemyCard) {
enemyCardContainer.removeChild(enemyCard);
enemyCard = null;
}
// Reset UI text (only if elements exist)
if (statusText) {
statusText.setText('');
statusText.visible = false;
}
if (playerModeText) {
playerModeText.setText('');
playerModeText.visible = false;
}
if (enemyModeText) {
enemyModeText.setText('');
enemyModeText.visible = false;
}
if (playerWinsText) {
playerWinsText.setText('Player Wins: 0');
playerWinsText.visible = false;
}
if (enemyWinsText) {
enemyWinsText.setText('Enemy Wins: 0');
enemyWinsText.visible = false;
}
// Hide game UI elements (only if they exist)
if (modeButtons) {
modeButtons.visible = false;
}
if (handContainer) {
handContainer.visible = false;
}
if (enemyHandContainer) {
enemyHandContainer.visible = false;
}
if (enlargedCardContainer) {
enlargedCardContainer.visible = false;
}
if (enemyCardContainer) {
enemyCardContainer.visible = false;
}
// Show menu
menuContainer.visible = true;
}
Un tsunami
A Stone
A boulder
An ember
A spark
Three small ember
A river
A wind symbol
Ice floe
A purple cristal rock
Columnas de fuego rojo y azul
Big storm
A cold gale
El margen para una carta que representa el tipo tierra
Un marco para una carta que represente al tipo aire
Un marco para una carta que represente al tipo agua
The rain
A big mountain
Pile of yellow sand
El margen para una carta que representa el tipo fuego
A tornado
The sea
El margen de un botón que indica ataque de un juego de mesa, color rojo sin texto
Crea una versión de este marco en color azul
Marco cuadrado, delgado color dorado con un fondo blanco. In-Game asset. 2d. High contrast. No shadows. card
Símbolo del elemento aire
Símbolo de la tierra color verde
Símbolo del fuego color rojo
Símbolo del agua color azul
A lightning
Crea la parte inversa de una carta que representa el elemento agua, no debe tener texto ni espacio vacío, deben ser corrientes de agua y rocas en la parte inferior
Crea la parte inversa de una carta que representa el elemento fuego, no debe tener texto ni espacio vacío, deben ser flamas y montículos rojos en la parte inferior
Crea la parte inversa de una carta que representa el elemento tierra, no debe tener texto ni espacio vacío, deben ser montículos de tierra y algunas hierbas verdes repartidas
A whirlwind
A cloud
A volcano with lava
Un cubo de hielo
Una niebla densa
an ashes
A brown cave
Una pieza en forma de prisma hexagonal de metal
4 segmentos de flecha que forman un circulo en sentido horario, color morado
The ether
The moon
El símbolo de Gaia, sin texto, color verde y café
The sun