/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AchievementSystem = Container.expand(function () { var self = Container.call(this); // Achievement definitions self.achievements = { firstBlackjackWin: { unlocked: false, title: "First Victory", description: "Win your first hand of Blackjack", reward: 100 }, cascade5x: { unlocked: false, title: "Cascade Master", description: "Get a 5x cascade in slots", reward: 250 }, reach10k: { unlocked: false, title: "High Roller", description: "Reach $10,000", reward: 500 }, bigSpender: { unlocked: false, title: "Big Spender", description: "Bet $500 in one hand", reward: 200 }, luckyStreak: { unlocked: false, title: "Lucky Streak", description: "Win 3 hands in a row", reward: 300 } }; // Load achievements from storage var savedAchievements = storage.achievements || {}; for (var key in savedAchievements) { if (self.achievements[key]) { self.achievements[key].unlocked = savedAchievements[key]; } } self.checkAchievement = function (type, value) { var achievement = self.achievements[type]; if (!achievement || achievement.unlocked) return; var shouldUnlock = false; switch (type) { case 'firstBlackjackWin': shouldUnlock = value === true; break; case 'cascade5x': shouldUnlock = value >= 5; break; case 'reach10k': shouldUnlock = value >= 10000; break; case 'bigSpender': shouldUnlock = value >= 500; break; case 'luckyStreak': shouldUnlock = value >= 3; break; } if (shouldUnlock) { self.unlockAchievement(type); } }; self.unlockAchievement = function (type) { var achievement = self.achievements[type]; if (achievement.unlocked) return; achievement.unlocked = true; // Save to storage - only save the unlocked status as literals var achievementsToSave = {}; for (var key in self.achievements) { achievementsToSave[key] = self.achievements[key].unlocked; } storage.achievements = achievementsToSave; // Show achievement notification self.showAchievementNotification(achievement); // Award money playerMoney += achievement.reward; updateMoneyDisplay(); }; self.showAchievementNotification = function (achievement) { var notification = new Text2('π ACHIEVEMENT UNLOCKED! π', { size: 48, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); notification.anchor.set(0.5, 0.5); notification.x = 1024; notification.y = 400; notification.alpha = 0; notification.scaleX = 0.5; notification.scaleY = 0.5; game.addChild(notification); var titleText = new Text2(achievement.title, { size: 36, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 480; titleText.alpha = 0; titleText.scaleX = 0.5; titleText.scaleY = 0.5; game.addChild(titleText); var rewardText = new Text2('+$' + achievement.reward, { size: 32, fill: '#00FF00', font: "'Arial Black', Arial, sans-serif" }); rewardText.anchor.set(0.5, 0.5); rewardText.x = 1024; rewardText.y = 540; rewardText.alpha = 0; rewardText.scaleX = 0.5; rewardText.scaleY = 0.5; game.addChild(rewardText); // Animate in tween(notification, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.bounceOut }); tween(titleText, { alpha: 1, scaleX: 1.0, scaleY: 1.0 }, { duration: 500, delay: 200, easing: tween.bounceOut }); tween(rewardText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, delay: 400, easing: tween.bounceOut }); // Animate out after 3 seconds LK.setTimeout(function () { tween(notification, { alpha: 0, scaleX: 0.8, scaleY: 0.8, y: notification.y - 100 }, { duration: 800, easing: tween.easeIn, onFinish: function onFinish() { notification.destroy(); } }); tween(titleText, { alpha: 0, scaleX: 0.8, scaleY: 0.8, y: titleText.y - 100 }, { duration: 800, delay: 100, easing: tween.easeIn, onFinish: function onFinish() { titleText.destroy(); } }); tween(rewardText, { alpha: 0, scaleX: 0.8, scaleY: 0.8, y: rewardText.y - 100 }, { duration: 800, delay: 200, easing: tween.easeIn, onFinish: function onFinish() { rewardText.destroy(); } }); }, 3000); }; return self; }); var AnimatedHand = Container.expand(function (isDealer) { var self = Container.call(this); self.isDealer = isDealer || false; var handGraphic = self.attachAsset(isDealer ? 'dealerHand' : 'playerHand', { anchorX: 0.5, anchorY: 0.5, width: isDealer ? 216 : 285.66, height: isDealer ? 324 : 428.49, alpha: 0.8 }); // Deal card animation (player - face up) self.dealCardToPlayer = function (targetX, targetY, onComplete) { var movingCard = LK.getAsset('movingCard', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); movingCard.x = self.x; movingCard.y = self.y; game.addChild(movingCard); // Animate hand dealing tween(handGraphic, { scaleX: 1.1, scaleY: 1.1, rotation: 0.1 }, { duration: 200 }); // Play card dealing sound LK.getSound('Carta_1').play(); // Move card to target tween(movingCard, { x: targetX, y: targetY, rotation: (Math.random() - 0.5) * 0.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { movingCard.destroy(); // Reset hand tween(handGraphic, { scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 200 }); if (onComplete) onComplete(); } }); }; // Deal card face down (dealer) self.dealCardFaceDown = function (targetX, targetY, onComplete) { var movingCard = LK.getAsset('movingCard', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); movingCard.x = self.x; movingCard.y = self.y; game.addChild(movingCard); // Animate hand dealing tween(handGraphic, { scaleX: 1.1, scaleY: 1.1, rotation: -0.1 }, { duration: 200 }); // Play card dealing sound LK.getSound('Carta_1').play(); // Move card to target tween(movingCard, { x: targetX, y: targetY, rotation: (Math.random() - 0.5) * 0.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { movingCard.destroy(); // Reset hand tween(handGraphic, { scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 200 }); if (onComplete) onComplete(); } }); }; // Hit gesture animation self.hitGesture = function (targetX, targetY, onComplete) { var movingCard = LK.getAsset('movingCard', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); movingCard.x = self.x; movingCard.y = self.y; game.addChild(movingCard); // Quick dealing animation tween(handGraphic, { scaleX: 1.05, scaleY: 1.05 }, { duration: 150 }); // Quick card movement tween(movingCard, { x: targetX, y: targetY }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { movingCard.destroy(); tween(handGraphic, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150 }); if (onComplete) onComplete(); } }); }; // Stand gesture animation self.standGesture = function () { tween(handGraphic, { rotation: 0.3, scaleX: 1.1, scaleY: 1.1 }, { duration: 300, onFinish: function onFinish() { tween(handGraphic, { rotation: 0, scaleX: 1.0, scaleY: 1.0 }, { duration: 300 }); } }); }; // Double down gesture with chips and card self.doubleDownGesture = function (targetX, targetY, onComplete) { // Animate placing chips first var chip = LK.getAsset('chipBet', { anchorX: 0.5, anchorY: 0.5 }); chip.x = self.x; chip.y = self.y; chip.alpha = 0; game.addChild(chip); tween(chip, { x: targetX - 100, y: targetY + 100, alpha: 1 }, { duration: 500, onFinish: function onFinish() { // Then deal final card face down var movingCard = LK.getAsset('movingCard', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); movingCard.x = self.x; movingCard.y = self.y; game.addChild(movingCard); tween(movingCard, { x: targetX, y: targetY }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { movingCard.destroy(); chip.destroy(); if (onComplete) onComplete(); } }); } }); }; // Card flip animation self.flipCard = function (cardX, cardY, onComplete) { // Create card back for flip animation var flippingCardBack = LK.getAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 300 }); flippingCardBack.x = cardX; flippingCardBack.y = cardY; game.addChild(flippingCardBack); // Create card front for flip animation (hidden initially) var flippingCardFront = LK.getAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 300, scaleX: 0, alpha: 0 }); flippingCardFront.x = cardX; flippingCardFront.y = cardY; game.addChild(flippingCardFront); // Animate hand moving to card with dramatic gesture tween(handGraphic, { x: cardX - self.x, y: cardY - self.y, scaleX: 1.2, scaleY: 1.2, rotation: 0.3 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { // First half of flip - shrink card back horizontally tween(flippingCardBack, { scaleX: 0, rotation: 0.1 }, { duration: 250, easing: tween.easeIn, onFinish: function onFinish() { // Play card flip sound when revealing LK.getSound('Carta_2').play(); // Hide card back, show card front flippingCardBack.alpha = 0; flippingCardFront.alpha = 1; // Second half of flip - expand card front horizontally tween(flippingCardFront, { scaleX: 1, rotation: 0 }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { // Add subtle bounce effect tween(flippingCardFront, { scaleX: 1.05, scaleY: 1.05 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(flippingCardFront, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { // Clean up animation cards flippingCardBack.destroy(); flippingCardFront.destroy(); // Return hand to original position with flourish tween(handGraphic, { x: 0, y: 0, scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 400, easing: tween.easeOut }); if (onComplete) onComplete(); } }); } }); } }); } }); } }); }; // Collect cards animation self.collectCards = function (cardPositions, actualCards, onComplete) { var collectCount = 0; var totalCards = cardPositions.length; for (var i = 0; i < cardPositions.length; i++) { var pos = cardPositions[i]; var actualCard = actualCards ? actualCards[i] : null; var collectingCard = LK.getAsset('movingCard', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); collectingCard.x = pos.x; collectingCard.y = pos.y; game.addChild(collectingCard); // Create closure to capture current card index (function (cardIndex, actualCardRef) { // Play card collection sound for each card LK.getSound('Carta_3').play(); tween(collectingCard, { x: self.x, y: self.y, scaleX: 0.5, scaleY: 0.5, alpha: 0 }, { duration: 400, delay: cardIndex * 0, easing: tween.easeIn, onFinish: function onFinish() { collectingCard.destroy(); // Make actual card disappear when collected if (actualCardRef) { actualCardRef.alpha = 0; } collectCount++; if (collectCount >= totalCards && onComplete) { onComplete(); } } }); })(i, actualCard); } // Animate hand collecting tween(handGraphic, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, onFinish: function onFinish() { tween(handGraphic, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); }; // Shuffle animation self.shuffleAnimation = function () { var shuffleDuration = 1200; var shuffleSteps = 8; var stepDuration = shuffleDuration / shuffleSteps; // First, move hand to deck position var deckPosition = { x: 200, y: 1366 }; // Deck position from gamecode var handStartX = self.x; var handStartY = self.y; // Move hand to deck pile tween(self, { x: deckPosition.x, y: deckPosition.y }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Play shuffle sound when hand reaches deck LK.getSound('Baraja').play(); // Now perform shuffle animation at deck position for (var i = 0; i < shuffleSteps; i++) { LK.setTimeout(function () { tween(handGraphic, { rotation: (Math.random() - 0.5) * 0.4, scaleX: 0.9 + Math.random() * 0.2, scaleY: 0.9 + Math.random() * 0.2 }, { duration: stepDuration / 2, onFinish: function onFinish() { tween(handGraphic, { rotation: 0, scaleX: 1.0, scaleY: 1.0 }, { duration: stepDuration / 2 }); } }); }, i * stepDuration); } // After shuffle animation completes, return hand to original position LK.setTimeout(function () { tween(self, { x: handStartX, y: handStartY }, { duration: 300, easing: tween.easeOut }); }, shuffleDuration + 300); } }); }; return self; }); var Card = Container.expand(function (suit, value) { var self = Container.call(this); self.suit = suit || 'hearts'; self.value = value || 1; self.faceUp = false; self.getDisplayValue = function () { if (self.value === 1) return 'A'; if (self.value === 11) return 'J'; if (self.value === 12) return 'Q'; if (self.value === 13) return 'K'; return self.value.toString(); }; self.getSuitSymbol = function () { switch (self.suit) { case 'hearts': return 'β₯'; case 'diamonds': return 'β¦'; case 'clubs': return 'β£'; case 'spades': return 'β '; default: return 'β₯'; } }; self.getColor = function () { return self.suit === 'hearts' || self.suit === 'diamonds' ? '#FF0000' : '#000000'; }; var cardShadow = self.attachAsset('cardShadow', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 380, alpha: 0.3 }); cardShadow.x = 5; cardShadow.y = 5; var cardBack = self.attachAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); // Get the specific card face asset based on suit and value var cardFaceAsset = 'card_' + self.suit + '_' + (self.value === 1 ? 'A' : self.value === 11 ? 'J' : self.value === 12 ? 'Q' : self.value === 13 ? 'K' : self.value.toString()); var cardFront = self.attachAsset(cardFaceAsset, { anchorX: 0.5, anchorY: 0.5, alpha: 0, width: 240, height: 360 }); // Top left corner value var topLeftValue = new Text2(self.getDisplayValue(), { size: 40, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); topLeftValue.anchor.set(0, 0); topLeftValue.x = -115; topLeftValue.y = -170; topLeftValue.alpha = 0; cardFront.addChild(topLeftValue); // Bottom right corner value (rotated 180 degrees) var bottomRightValue = new Text2(self.getDisplayValue(), { size: 40, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); bottomRightValue.anchor.set(1, 1); bottomRightValue.x = 75; bottomRightValue.y = 120; bottomRightValue.rotation = Math.PI; bottomRightValue.alpha = 0; cardFront.addChild(bottomRightValue); // Center symbols for numbered cards (2-10) var centerSymbols = []; if (self.value >= 2 && self.value <= 10) { for (var i = 0; i < self.value; i++) { var centerSymbol = new Text2(self.getSuitSymbol(), { size: 60, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); centerSymbol.anchor.set(0.5, 0.5); // Aesthetic positioning based on card number var positions = []; if (self.value === 2) { positions = [{ x: 0, y: -60 }, { x: 0, y: 60 }]; } else if (self.value === 3) { positions = [{ x: 0, y: -80 }, { x: 0, y: 0 }, { x: 0, y: 80 }]; } else if (self.value === 4) { positions = [{ x: -40, y: -60 }, { x: 40, y: -60 }, { x: -40, y: 60 }, { x: 40, y: 60 }]; } else if (self.value === 5) { positions = [{ x: -40, y: -60 }, { x: 40, y: -60 }, { x: 0, y: 0 }, { x: -40, y: 60 }, { x: 40, y: 60 }]; } else if (self.value === 6) { positions = [{ x: -40, y: -80 }, { x: 40, y: -80 }, { x: -40, y: 0 }, { x: 40, y: 0 }, { x: -40, y: 80 }, { x: 40, y: 80 }]; } else if (self.value === 7) { positions = [{ x: -40, y: -80 }, { x: 40, y: -80 }, { x: 0, y: -40 }, { x: -40, y: 0 }, { x: 40, y: 0 }, { x: -40, y: 80 }, { x: 40, y: 80 }]; } else if (self.value === 8) { positions = [{ x: -40, y: -80 }, { x: 40, y: -80 }, { x: -40, y: -30 }, { x: 40, y: -30 }, { x: -40, y: 30 }, { x: 40, y: 30 }, { x: -40, y: 80 }, { x: 40, y: 80 }]; } else if (self.value === 9) { positions = [{ x: -40, y: -80 }, { x: 40, y: -80 }, { x: -40, y: -40 }, { x: 40, y: -40 }, { x: 0, y: 0 }, { x: -40, y: 40 }, { x: 40, y: 40 }, { x: -40, y: 80 }, { x: 40, y: 80 }]; } else if (self.value === 10) { positions = [{ x: -40, y: -80 }, { x: 40, y: -80 }, { x: -40, y: -50 }, { x: 40, y: -50 }, { x: -40, y: -20 }, { x: 40, y: -20 }, { x: -40, y: 20 }, { x: 40, y: 20 }, { x: -40, y: 80 }, { x: 40, y: 80 }]; } centerSymbol.x = positions[i].x; centerSymbol.y = positions[i].y; centerSymbol.alpha = 0; cardFront.addChild(centerSymbol); centerSymbols.push(centerSymbol); } } // Main suit symbol for face cards var suitText = new Text2(self.getSuitSymbol(), { size: 60, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); suitText.anchor.set(0.5, 0.5); suitText.y = 0; suitText.alpha = 0; // Special center symbol for Jack - create a servant/knave figure if (self.value === 11) { // Create a simple servant figure using text symbols var servantFigure = new Text2('β', { size: 180, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); servantFigure.anchor.set(0.5, 0.5); servantFigure.y = 0; servantFigure.alpha = 0; cardFront.addChild(servantFigure); // Store references for flip animation centerSymbols.push(servantFigure); } else if (self.value === 12) { // Special center symbol for Queen - create a queen figure var queenFigure = new Text2('β', { size: 180, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); queenFigure.anchor.set(0.5, 0.5); queenFigure.y = 0; queenFigure.alpha = 0; cardFront.addChild(queenFigure); // Store references for flip animation centerSymbols.push(queenFigure); } else if (self.value === 13) { // Special center symbol for King - create a king figure var kingFigure = new Text2('β', { size: 180, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); kingFigure.anchor.set(0.5, 0.5); kingFigure.y = 0; kingFigure.alpha = 0; cardFront.addChild(kingFigure); // Store references for flip animation centerSymbols.push(kingFigure); } else if (self.value < 2 || self.value > 9 && self.value !== 11 && self.value !== 12 && self.value !== 13) { cardFront.addChild(suitText); } self.getBlackjackValue = function () { if (self.value === 1) return 11; // Ace high initially if (self.value > 10) return 10; // Face cards return self.value; }; self.flip = function () { self.faceUp = !self.faceUp; LK.getSound('cardFlip').play(); if (self.faceUp) { tween(cardBack, { alpha: 0 }, { duration: 200 }); tween(cardFront, { alpha: 1 }, { duration: 200 }); tween(topLeftValue, { alpha: 1 }, { duration: 200 }); tween(bottomRightValue, { alpha: 1 }, { duration: 200 }); for (var i = 0; i < centerSymbols.length; i++) { tween(centerSymbols[i], { alpha: 1 }, { duration: 200 }); } if (self.value < 2 || self.value > 9) { tween(suitText, { alpha: 1 }, { duration: 200 }); } } else { tween(cardBack, { alpha: 1 }, { duration: 200 }); tween(cardFront, { alpha: 0 }, { duration: 200 }); tween(topLeftValue, { alpha: 0 }, { duration: 200 }); tween(bottomRightValue, { alpha: 0 }, { duration: 200 }); for (var i = 0; i < centerSymbols.length; i++) { tween(centerSymbols[i], { alpha: 0 }, { duration: 200 }); } if (self.value < 2 || self.value > 9) { tween(suitText, { alpha: 0 }, { duration: 200 }); } } }; return self; }); var Chip = Container.expand(function (value) { var self = Container.call(this); self.value = value || 1; // Get appropriate chip asset based on value var chipAsset; switch (self.value) { case 1: chipAsset = 'chip1'; break; case 5: chipAsset = 'chip5'; break; case 10: chipAsset = 'chip10'; break; case 25: chipAsset = 'chip25'; break; case 100: chipAsset = 'chip100'; break; case 500: chipAsset = 'chip500'; break; default: chipAsset = 'chip1'; } var chipGraphic = self.attachAsset(chipAsset, { anchorX: 0.5, anchorY: 0.5 }); // Add value text on chip var valueText = new Text2('$' + self.value, { size: 18, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); valueText.anchor.set(0.5, 0.5); chipGraphic.addChild(valueText); self.enabled = true; // Make chip interactive self.interactive = true; self.buttonMode = true; self.setEnabled = function (enabled) { self.enabled = enabled; chipGraphic.alpha = enabled ? 1.0 : 0.5; }; self.down = function (x, y, obj) { if (!self.enabled) return; if (gameMode !== 'blackjack') return; if (gamePhase !== 'betting') return; // Check if player has enough money for this chip value when added to current bet if (playerMoney >= currentBet + self.value) { currentBet += self.value; updateChipSelection(); LK.getSound('Ficha_1').play(); // Create animated chip that moves to Apuesta center var animatedChip = LK.getAsset(chipAsset, { anchorX: 0.5, anchorY: 0.5 }); // Get chip's global position var chipGlobalPos = self.parent.toGlobal(self.position); var gameLocalPos = game.toLocal(chipGlobalPos); animatedChip.x = gameLocalPos.x; animatedChip.y = gameLocalPos.y; animatedChip.alpha = 0.8; game.addChild(animatedChip); // Animate chip moving to center of Apuesta asset tween(animatedChip, { x: apuestaAsset.x, y: apuestaAsset.y, scaleX: 0.7, scaleY: 0.7, alpha: 1.0 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { // Fade out and destroy the animated chip tween(animatedChip, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, onFinish: function onFinish() { animatedChip.destroy(); } }); } }); // Visual feedback on original chip tween(chipGraphic, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(chipGraphic, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); } }; return self; }); var DealerCard = Container.expand(function (suit, value) { var self = Container.call(this); self.suit = suit || 'hearts'; self.value = value || 1; self.faceUp = false; self.getDisplayValue = function () { if (self.value === 1) return 'A'; if (self.value === 11) return 'J'; if (self.value === 12) return 'Q'; if (self.value === 13) return 'K'; return self.value.toString(); }; self.getSuitSymbol = function () { switch (self.suit) { case 'hearts': return 'β₯'; case 'diamonds': return 'β¦'; case 'clubs': return 'β£'; case 'spades': return 'β '; default: return 'β₯'; } }; self.getColor = function () { return self.suit === 'hearts' || self.suit === 'diamonds' ? '#FF0000' : '#000000'; }; var cardShadow = self.attachAsset('dealerCardShadow', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 320, alpha: 0.3 }); cardShadow.x = 4; cardShadow.y = 4; var cardBack = self.attachAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 300 }); // Get the specific card face asset based on suit and value for dealer cards var dealerCardFaceAsset = 'card_' + self.suit + '_' + (self.value === 1 ? 'A' : self.value === 11 ? 'J' : self.value === 12 ? 'Q' : self.value === 13 ? 'K' : self.value.toString()); var cardFront = self.attachAsset(dealerCardFaceAsset, { anchorX: 0.5, anchorY: 0.5, alpha: 0, width: 200, height: 300 }); // Top left corner value var topLeftValue = new Text2(self.getDisplayValue(), { size: 32, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); topLeftValue.anchor.set(0, 0); topLeftValue.x = -95; topLeftValue.y = -140; topLeftValue.alpha = 0; cardFront.addChild(topLeftValue); // Bottom right corner value (rotated 180 degrees) var bottomRightValue = new Text2(self.getDisplayValue(), { size: 32, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); bottomRightValue.anchor.set(1, 1); bottomRightValue.x = 55; bottomRightValue.y = 90; bottomRightValue.rotation = Math.PI; bottomRightValue.alpha = 0; cardFront.addChild(bottomRightValue); // Center symbols for numbered cards (2-10) var centerSymbols = []; if (self.value >= 2 && self.value <= 10) { for (var i = 0; i < self.value; i++) { var centerSymbol = new Text2(self.getSuitSymbol(), { size: 48, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); centerSymbol.anchor.set(0.5, 0.5); // Aesthetic positioning based on card number var positions = []; if (self.value === 2) { positions = [{ x: 0, y: -45 }, { x: 0, y: 45 }]; } else if (self.value === 3) { positions = [{ x: 0, y: -60 }, { x: 0, y: 0 }, { x: 0, y: 60 }]; } else if (self.value === 4) { positions = [{ x: -30, y: -45 }, { x: 30, y: -45 }, { x: -30, y: 45 }, { x: 30, y: 45 }]; } else if (self.value === 5) { positions = [{ x: -30, y: -45 }, { x: 30, y: -45 }, { x: 0, y: 0 }, { x: -30, y: 45 }, { x: 30, y: 45 }]; } else if (self.value === 6) { positions = [{ x: -30, y: -60 }, { x: 30, y: -60 }, { x: -30, y: 0 }, { x: 30, y: 0 }, { x: -30, y: 60 }, { x: 30, y: 60 }]; } else if (self.value === 7) { positions = [{ x: -30, y: -60 }, { x: 30, y: -60 }, { x: 0, y: -30 }, { x: -30, y: 0 }, { x: 30, y: 0 }, { x: -30, y: 60 }, { x: 30, y: 60 }]; } else if (self.value === 8) { positions = [{ x: -30, y: -60 }, { x: 30, y: -60 }, { x: -30, y: -20 }, { x: 30, y: -20 }, { x: -30, y: 20 }, { x: 30, y: 20 }, { x: -30, y: 60 }, { x: 30, y: 60 }]; } else if (self.value === 9) { positions = [{ x: -30, y: -60 }, { x: 30, y: -60 }, { x: -30, y: -30 }, { x: 30, y: -30 }, { x: 0, y: 0 }, { x: -30, y: 30 }, { x: 30, y: 30 }, { x: -30, y: 60 }, { x: 30, y: 60 }]; } else if (self.value === 10) { positions = [{ x: -30, y: -60 }, { x: 30, y: -60 }, { x: -30, y: -40 }, { x: 30, y: -40 }, { x: -30, y: -15 }, { x: 30, y: -15 }, { x: -30, y: 15 }, { x: 30, y: 15 }, { x: -30, y: 60 }, { x: 30, y: 60 }]; } centerSymbol.x = positions[i].x; centerSymbol.y = positions[i].y; centerSymbol.alpha = 0; cardFront.addChild(centerSymbol); centerSymbols.push(centerSymbol); } } // Main suit symbol for face cards var suitText = new Text2(self.getSuitSymbol(), { size: 48, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); suitText.anchor.set(0.5, 0.5); suitText.y = 0; suitText.alpha = 0; // Special center symbol for Jack - create a servant/knave figure if (self.value === 11) { // Create a simple servant figure using text symbols var servantFigure = new Text2('β', { size: 144, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); servantFigure.anchor.set(0.5, 0.5); servantFigure.y = 0; servantFigure.alpha = 0; cardFront.addChild(servantFigure); // Store references for flip animation centerSymbols.push(servantFigure); } else if (self.value === 12) { // Special center symbol for Queen - create a queen figure var queenFigure = new Text2('β', { size: 144, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); queenFigure.anchor.set(0.5, 0.5); queenFigure.y = 0; queenFigure.alpha = 0; cardFront.addChild(queenFigure); // Store references for flip animation centerSymbols.push(queenFigure); } else if (self.value === 13) { // Special center symbol for King - create a king figure var kingFigure = new Text2('β', { size: 144, fill: self.getColor(), font: "'Arial Black', Arial, sans-serif" }); kingFigure.anchor.set(0.5, 0.5); kingFigure.y = 0; kingFigure.alpha = 0; cardFront.addChild(kingFigure); // Store references for flip animation centerSymbols.push(kingFigure); } else if (self.value < 2 || self.value > 9 && self.value !== 11 && self.value !== 12 && self.value !== 13) { cardFront.addChild(suitText); } self.getBlackjackValue = function () { if (self.value === 1) return 11; // Ace high initially if (self.value > 10) return 10; // Face cards return self.value; }; self.flip = function () { self.faceUp = !self.faceUp; LK.getSound('cardFlip').play(); if (self.faceUp) { tween(cardBack, { alpha: 0 }, { duration: 200 }); tween(cardFront, { alpha: 1 }, { duration: 200 }); tween(topLeftValue, { alpha: 1 }, { duration: 200 }); tween(bottomRightValue, { alpha: 1 }, { duration: 200 }); for (var i = 0; i < centerSymbols.length; i++) { tween(centerSymbols[i], { alpha: 1 }, { duration: 200 }); } if (self.value < 2 || self.value > 9) { tween(suitText, { alpha: 1 }, { duration: 200 }); } } else { tween(cardBack, { alpha: 1 }, { duration: 200 }); tween(cardFront, { alpha: 0 }, { duration: 200 }); tween(topLeftValue, { alpha: 0 }, { duration: 200 }); tween(bottomRightValue, { alpha: 0 }, { duration: 200 }); for (var i = 0; i < centerSymbols.length; i++) { tween(centerSymbols[i], { alpha: 0 }, { duration: 200 }); } if (self.value < 2 || self.value > 9) { tween(suitText, { alpha: 0 }, { duration: 200 }); } } }; return self; }); var Deck = Container.expand(function () { var self = Container.call(this); // Create multiple stacked cards for deck appearance var stackedCards = []; for (var i = 0; i < 5; i++) { var cardLayer = self.attachAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); cardLayer.x = i * 3; // Slight offset for stacking effect cardLayer.y = i * -2; // Vertical stacking cardLayer.alpha = 0.9 - i * 0.1; // Fade slightly for depth stackedCards.push(cardLayer); } self.cardCount = 52; var countText = new Text2('52', { size: 24, fill: '#FFFFFF' }); countText.anchor.set(0.5, 0.5); countText.y = -200; self.addChild(countText); // Start deck breathing animation self.startDeckAnimation = function () { // Create a subtle breathing animation for the entire deck function breatheAnimation() { tween(self, { scaleX: 1.02, scaleY: 1.02, y: self.y - 2 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1.0, scaleY: 1.0, y: self.y + 2 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { breatheAnimation(); // Loop the animation } }); } }); } breatheAnimation(); // Add subtle rotation animation to individual cards for depth for (var i = 0; i < stackedCards.length; i++) { (function (cardLayer, index) { function cardFloatAnimation() { var randomOffset = (Math.random() - 0.5) * 0.02; // Small random rotation tween(cardLayer, { rotation: randomOffset, y: cardLayer.y + (Math.random() - 0.5) * 1 }, { duration: 3000 + index * 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(cardLayer, { rotation: -randomOffset * 0.5, y: cardLayer.y - (Math.random() - 0.5) * 1 }, { duration: 3000 + index * 200, easing: tween.easeInOut, onFinish: function onFinish() { cardFloatAnimation(); // Loop the animation } }); } }); } cardFloatAnimation(); })(stackedCards[i], i); } }; // Stop deck animation self.stopDeckAnimation = function () { tween.stop(self, { scaleX: true, scaleY: true, y: true }); for (var i = 0; i < stackedCards.length; i++) { tween.stop(stackedCards[i], { rotation: true, y: true }); } }; self.updateCount = function (count) { self.cardCount = count; countText.setText(count.toString()); if (count <= 0) { for (var i = 0; i < stackedCards.length; i++) { stackedCards[i].alpha = 0.1; } } else { for (var i = 0; i < stackedCards.length; i++) { stackedCards[i].alpha = 0.9 - i * 0.1; } } }; self.dealAnimation = function (targetX, targetY, onComplete) { if (self.cardCount <= 0) { if (onComplete) onComplete(); return; } self.cardCount--; self.updateCount(self.cardCount); var dealingCard = LK.getAsset('casinoCardBack', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 360 }); dealingCard.x = self.x; dealingCard.y = self.y; game.addChild(dealingCard); tween(dealingCard, { x: targetX, y: targetY, rotation: (Math.random() - 0.5) * 0.2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { dealingCard.destroy(); if (onComplete) onComplete(); } }); // Animate the entire stack slightly when dealing for (var i = 0; i < stackedCards.length; i++) { tween(stackedCards[i], { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(stackedCards[i], { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); } }; return self; }); var GameButton = Container.expand(function (text, width, height) { var self = Container.call(this); var buttonShadow = self.attachAsset('buttonShadow', { anchorX: 0.5, anchorY: 0.5, width: (width || 200) * 2 + 20, height: (height || 80) * 2 + 20, alpha: 0.4 }); buttonShadow.x = 6; buttonShadow.y = 6; var buttonBg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: (width || 200) * 2, height: (height || 80) * 2 }); var buttonText = new Text2(text || 'Button', { size: 48, fill: '#000000', font: "'Arial Black', Arial, sans-serif" }); buttonText.anchor.set(0.5, 0.5); buttonBg.addChild(buttonText); self.enabled = true; self.setText = function (newText) { buttonText.setText(newText); }; self.setEnabled = function (enabled) { self.enabled = enabled; buttonBg.alpha = enabled ? 1.0 : 0.5; }; self.down = function (x, y, obj) { if (!self.enabled) return; LK.getSound('buttonClick').play(); tween(buttonBg, { scaleX: 0.85, scaleY: 0.85 }, { duration: 100, easing: tween.easeOut }); }; self.up = function (x, y, obj) { if (!self.enabled) return; tween(buttonBg, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { tween(buttonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeOut }); } }); }; return self; }); var MegawaysReel = Container.expand(function (reelIndex) { var self = Container.call(this); self.reelIndex = reelIndex || 0; self.symbols = []; self.symbolTypes = ['megawaysSymbolA', 'megawaysSymbolB', 'megawaysSymbolC', 'megawaysSymbolD', 'megawaysSymbolE', 'megawaysSymbolF', 'megawaysWild', 'megawaysScatter']; self.spinning = false; self.currentSymbolCount = 4; // Start with 4 symbols self.maxSymbols = 4; // Maximum symbols per reel self.minSymbols = 4; // Minimum symbols per reel self.isSpinning = false; self.spinEndCallback = null; // Reel container background var reelBorder = self.attachAsset('megawaysReelBorder', { anchorX: 0.5, anchorY: 0.5 }); var reelContainer = self.attachAsset('megawaysReelContainer', { anchorX: 0.5, anchorY: 0.5 }); // Symbol frequency weights for balanced RTP (higher weight = more frequent) self.symbolWeights = { 'megawaysSymbolF': 35, // Most frequent (lowest paying) 'megawaysSymbolE': 25, // Very frequent 'megawaysSymbolD': 20, // Frequent 'megawaysSymbolC': 12, // Less frequent 'megawaysSymbolB': 6, // Rare 'megawaysSymbolA': 2 // Very rare (highest paying) }; // Get weighted random symbol based on frequency self.getWeightedRandomSymbol = function () { // Improved symbol distribution with more balanced frequencies var adjustedWeights = {}; var cascadeCount = self.cascadeCount || 0; // Use cascade count from reel property // More balanced distribution - reduce dominance of F and E symbols if (cascadeCount >= 15) { adjustedWeights = { 'megawaysSymbolF': 28, // Reduced dominance from 32 'megawaysSymbolE': 22, // Reduced from 23 'megawaysSymbolD': 22, // Increased from 20 'megawaysSymbolC': 16, // Increased from 14 'megawaysSymbolB': 9, // Increased from 8 'megawaysSymbolA': 3 // Same }; } else if (cascadeCount >= 10) { adjustedWeights = { 'megawaysSymbolF': 30, // Reduced from 33 'megawaysSymbolE': 22, // Reduced from 24 'megawaysSymbolD': 22, // Increased from 20 'megawaysSymbolC': 15, // Increased from 13 'megawaysSymbolB': 8, // Increased from 7 'megawaysSymbolA': 3 // Same }; } else { // More balanced base weights adjustedWeights = { 'megawaysSymbolF': 30, // Reduced from 35 'megawaysSymbolE': 22, // Reduced from 25 'megawaysSymbolD': 22, // Increased from 20 'megawaysSymbolC': 15, // Increased from 12 'megawaysSymbolB': 8, // Increased from 6 'megawaysSymbolA': 3 // Increased from 2 }; } var totalWeight = 0; for (var symbol in adjustedWeights) { totalWeight += adjustedWeights[symbol]; } var randomValue = Math.random() * totalWeight; var currentWeight = 0; for (var symbol in adjustedWeights) { currentWeight += adjustedWeights[symbol]; if (randomValue <= currentWeight) { return symbol; } } // Fallback to most common symbol return 'megawaysSymbolF'; }; // Initialize reel with random symbol count self.generateRandomSymbolCount = function () { self.currentSymbolCount = self.minSymbols + Math.floor(Math.random() * (self.maxSymbols - self.minSymbols + 1)); return self.currentSymbolCount; }; // Create symbols for this reel self.createSymbols = function () { // Clear existing symbols for (var i = 0; i < self.symbols.length; i++) { if (self.symbols[i] && self.symbols[i].destroy) { self.symbols[i].destroy(); } } self.symbols = []; // Create new symbols based on current count for (var i = 0; i < self.currentSymbolCount; i++) { var symbolType = self.getWeightedRandomSymbol(); var symbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType)); // Position symbols vertically within reel with no spacing between them var symbolHeight = 105; // Height of each symbol (60 * 1.4 scale + padding to fill 420px height completely) symbol.y = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight; // Scale symbols to fill available space better symbol.scaleX = 1; symbol.scaleY = 1; self.addChild(symbol); self.symbols.push(symbol); } }; // Calculate total ways to win based on symbol counts self.calculateWays = function (reelSymbolCounts) { var totalWays = 1; for (var i = 0; i < reelSymbolCounts.length; i++) { totalWays *= reelSymbolCounts[i]; } return totalWays; }; // Spin reel with enhanced Megaways animations self.spin = function (duration, onComplete) { if (self.isSpinning) return; self.isSpinning = true; self.spinEndCallback = onComplete; // Generate new symbol count for this spin self.generateRandomSymbolCount(); // Store old symbols for cascading animation var oldSymbols = self.symbols.slice(); // Start spin animation with reel shake and blur tween(reelContainer, { scaleY: 0.6, scaleX: 1.1, alpha: 0.7 }, { duration: 300, easing: tween.easeOut }); // Animate old symbols falling out for (var i = 0; i < oldSymbols.length; i++) { (function (symbol, index) { tween(symbol, { y: symbol.y + 500, alpha: 0, rotation: (Math.random() - 0.5) * Math.PI }, { duration: 400 + index * 50, easing: tween.easeIn, onFinish: function onFinish() { if (symbol && symbol.destroy) { symbol.destroy(); } } }); })(oldSymbols[i], i); } // Clear symbols array after starting fall animation self.symbols = []; var spinInterval; var spinCount = 0; var maxSpins = Math.floor(duration / 120); var tempSymbols = []; spinInterval = LK.setInterval(function () { spinCount++; // Create temporary spinning symbols for visual effect if (spinCount % 2 === 0) { // Clear temp symbols for (var i = 0; i < tempSymbols.length; i++) { if (tempSymbols[i] && tempSymbols[i].destroy) { tempSymbols[i].destroy(); } } tempSymbols = []; // Create new temp symbols for (var i = 0; i < self.currentSymbolCount; i++) { var symbolType = self.symbolTypes[Math.floor(Math.random() * self.symbolTypes.length)]; var tempSymbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType)); // Position temp symbols with no spacing between them var symbolHeight = 105; // Height of each symbol with no gaps tempSymbol.y = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight; tempSymbol.alpha = 0.6; // Scale temp symbols to match final ones tempSymbol.scaleX = 1.0; tempSymbol.scaleY = 1.0; self.addChild(tempSymbol); tempSymbols.push(tempSymbol); } } // Add intense shake effect during spin reelContainer.x = (Math.random() - 0.5) * 12; reelContainer.y = (Math.random() - 0.5) * 8; if (spinCount >= maxSpins) { LK.clearInterval(spinInterval); // Clear temp symbols for (var i = 0; i < tempSymbols.length; i++) { if (tempSymbols[i] && tempSymbols[i].destroy) { tempSymbols[i].destroy(); } } tempSymbols = []; // Create final symbols with drop-in animation self.createFinalSymbols(); } }, 120); }; // Create final symbols with drop-in animation self.createFinalSymbols = function () { // Create new symbols above the reel for (var i = 0; i < self.currentSymbolCount; i++) { var symbolType = self.getWeightedRandomSymbol(); var symbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType)); // Position symbols with no spacing between them var symbolHeight = 105; // Height of each symbol with no gaps var finalY = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight; // Place symbols directly at final position instead of starting above symbol.y = finalY; symbol.alpha = 1; // Scale symbols to match spinning symbols symbol.scaleX = 1.0; symbol.scaleY = 1.0; self.addChild(symbol); self.symbols.push(symbol); } // Wait for the same duration as the original animation to maintain timing LK.setTimeout(function () { self.finalizeSpin(); }, 600 + (self.currentSymbolCount - 1) * 100); }; // Finalize spin animation self.finalizeSpin = function () { // Reset reel container position and scale tween(reelContainer, { x: 0, y: 0, scaleY: 1.0, scaleX: 1.0, alpha: 1.0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { self.isSpinning = false; if (self.spinEndCallback) { self.spinEndCallback(); self.spinEndCallback = null; } } }); }; // Get all symbols in this reel self.getSymbols = function () { return self.symbols; }; // Get symbol count for ways calculation self.getSymbolCount = function () { return self.currentSymbolCount; }; // Check for winning combinations in this reel self.checkForWins = function (targetSymbol, position) { var winningSymbols = []; for (var i = 0; i < self.symbols.length; i++) { var symbol = self.symbols[i]; if (symbol.getSymbolValue() === targetSymbol || symbol.isWild) { winningSymbols.push(symbol); } } return winningSymbols; }; // Mark symbols for cascade removal self.markSymbolsForRemoval = function (symbolsToRemove) { for (var i = 0; i < symbolsToRemove.length; i++) { var symbol = symbolsToRemove[i]; symbol.markForWin(); } }; // Initialize with symbols self.generateRandomSymbolCount(); self.createSymbols(); return self; }); var MegawaysSlotMachine = Container.expand(function () { var self = Container.call(this); self.reels = []; self.isSpinning = false; self.currentWays = 0; self.cascadeCount = 0; self.totalWinAmount = 0; // Create 6 reels for Megaways self.createReels = function () { for (var i = 0; i < 6; i++) { var reel = new MegawaysReel(i); // Position reels horizontally with proper spacing reel.x = (i - 2.5) * 200; // Center 6 reels reel.y = 0; self.addChild(reel); self.reels.push(reel); } }; // Calculate total ways to win self.calculateTotalWays = function () { var symbolCounts = []; for (var i = 0; i < self.reels.length; i++) { symbolCounts.push(self.reels[i].getSymbolCount()); } var ways = 1; for (var i = 0; i < symbolCounts.length; i++) { ways *= symbolCounts[i]; } self.currentWays = ways; return ways; }; // Spin all reels with staggered timing self.spinAllReels = function (onComplete) { if (self.isSpinning) return; self.isSpinning = true; self.cascadeCount = 0; self.totalWinAmount = 0; var completedReels = 0; var totalReels = self.reels.length; // Calculate when each reel will stop spinning var reelStopTimes = []; for (var i = 0; i < self.reels.length; i++) { var startDelay = i * 150; // When this reel starts spinning var spinDuration = 1200 + i * 200; // How long this reel spins var stopTime = startDelay + spinDuration; // When this reel stops reelStopTimes.push(stopTime); } // Schedule Detencion sound for each reel when it stops for (var i = 0; i < reelStopTimes.length; i++) { (function (reelIndex, stopTime) { LK.setTimeout(function () { // Play Detencion sound when this specific reel stops LK.getSound('Detencion').play(); }, stopTime); })(i, reelStopTimes[i]); } // Spin each reel with increasing delay for realistic effect for (var i = 0; i < self.reels.length; i++) { (function (reelIndex) { LK.setTimeout(function () { // Play Rodillos sound only once when first reel starts spinning if (reelIndex === 0) { LK.getSound('Rodillos').play(); } self.reels[reelIndex].spin(1200 + reelIndex * 200, function () { completedReels++; if (completedReels === totalReels) { self.isSpinning = false; self.calculateTotalWays(); if (onComplete) onComplete(); } }); }, reelIndex * 150); })(i); } }; // Check for winning combinations across all reels self.checkForWins = function () { var winningCombinations = []; var symbolTypes = ['megawaysSymbolA', 'megawaysSymbolB', 'megawaysSymbolC', 'megawaysSymbolD', 'megawaysSymbolE', 'megawaysSymbolF']; // Check each symbol type for consecutive matches from left for (var s = 0; s < symbolTypes.length; s++) { var symbolType = symbolTypes[s]; var consecutiveReels = 0; var winningSymbols = []; // Check from leftmost reel for (var r = 0; r < self.reels.length; r++) { var reelMatches = self.reels[r].checkForWins(symbolType, r); if (reelMatches.length > 0) { consecutiveReels++; winningSymbols = winningSymbols.concat(reelMatches); } else { break; // Must be consecutive from left } } // Need at least 4 consecutive reels for a win if (consecutiveReels >= 4) { winningCombinations.push({ symbolType: symbolType, reelCount: consecutiveReels, symbols: winningSymbols, multiplier: self.getSymbolMultiplier(symbolType, consecutiveReels) }); } } return winningCombinations; }; // Get multiplier for symbol and reel count self.getSymbolMultiplier = function (symbolType, reelCount) { var baseMultipliers = { 'megawaysSymbolA': 54, // Significantly increased to make rare appearances more exciting (was 30) 'megawaysSymbolB': 39, // Increased to provide better variety when it appears (was 24) 'megawaysSymbolC': 26, // Slightly increased to improve mid-tier rewards (was 18) 'megawaysSymbolD': 18, // Slightly increased (was 12) 'megawaysSymbolE': 12, // Same - balanced for frequency 'megawaysSymbolF': 8 // Same - maintains balance as most frequent symbol }; var reelMultiplier = Math.pow(2, reelCount - 4); // 4 reels = 1x, 5 reels = 2x, 6 reels = 4x var betFactor = currentBet / 25; // Scale rewards based on bet amount (25 is base bet) var cascadeBonus = 1; if (self.cascadeCount > 1) { if (self.cascadeCount >= 15) { // High cascades get moderate bonus with smoother curve cascadeBonus = Math.pow(self.cascadeCount, 1.6); // Slightly reduced growth } else if (self.cascadeCount >= 5) { // Improved mid-range cascades - better rewards for x5-x14 cascadeBonus = Math.pow(self.cascadeCount, 1.8); // Better progression for mid-range } else { // Early cascades get better bonus cascadeBonus = self.cascadeCount * 1.5 + 1; // Better early cascade rewards } } var baseWin = Math.floor((baseMultipliers[symbolType] || 1) * reelMultiplier * betFactor * cascadeBonus); // Improved guaranteed minimums with better mid-range coverage if (self.cascadeCount >= 20) { var guaranteedMinimum = currentBet * 20; // Reduced from 25x to prevent excessive long spins baseWin = Math.max(baseWin, guaranteedMinimum); } else if (self.cascadeCount >= 15) { var guaranteedMinimum = currentBet * 15; // New tier for x15+ cascades baseWin = Math.max(baseWin, guaranteedMinimum); } else if (self.cascadeCount >= 10) { var guaranteedMinimum = currentBet * 8; // New tier for x10+ cascades baseWin = Math.max(baseWin, guaranteedMinimum); } else if (self.cascadeCount >= 5) { var guaranteedMinimum = currentBet * 4; // New tier for x5+ cascades to make them more exciting baseWin = Math.max(baseWin, guaranteedMinimum); } return baseWin; }; // Process winning combinations self.processWins = function (winningCombinations, onComplete) { if (winningCombinations.length === 0) { if (onComplete) onComplete(0); return; } var totalWin = 0; // Calculate total win amount for (var i = 0; i < winningCombinations.length; i++) { var combo = winningCombinations[i]; totalWin += combo.multiplier; // Mark symbols for removal for (var j = 0; j < combo.symbols.length; j++) { combo.symbols[j].markForWin(); } } self.totalWinAmount += totalWin; // Animate win highlighting LK.setTimeout(function () { self.cascadeWinningSymbols(winningCombinations, function () { if (onComplete) onComplete(totalWin); }); }, 1000); return totalWin; }; // Cascade (remove) winning symbols and drop remaining ones self.cascadeWinningSymbols = function (winningCombinations, onComplete) { self.cascadeCount++; var symbolsToRemove = []; // Collect all winning symbols for (var i = 0; i < winningCombinations.length; i++) { symbolsToRemove = symbolsToRemove.concat(winningCombinations[i].symbols); } // Animate symbol removal var removedCount = 0; for (var i = 0; i < symbolsToRemove.length; i++) { (function (symbol) { symbol.explode(function () { removedCount++; if (removedCount === symbolsToRemove.length) { // All symbols removed, now cascade remaining symbols down self.cascadeRemainingSymbols(function () { // Check for new wins after cascade LK.setTimeout(function () { var newWins = self.checkForWins(); if (newWins.length > 0) { // More wins found, process them self.processWins(newWins, onComplete); } else { // No more wins, cascade complete if (onComplete) onComplete(); } }, 300); }); } }); })(symbolsToRemove[i]); } }; // Drop remaining symbols and fill gaps self.cascadeRemainingSymbols = function (onComplete) { var cascadeComplete = 0; var totalReels = self.reels.length; for (var r = 0; r < self.reels.length; r++) { (function (reelIndex) { var reel = self.reels[reelIndex]; var remainingSymbols = []; // Collect non-destroyed symbols for (var i = 0; i < reel.symbols.length; i++) { if (reel.symbols[i] && !reel.symbols[i].marked) { remainingSymbols.push(reel.symbols[i]); } } // Fill reel back to current symbol count var newSymbolsNeeded = reel.currentSymbolCount - remainingSymbols.length; // Pass cascade count to reel for weighted symbol selection reel.cascadeCount = self.cascadeCount; for (var n = 0; n < newSymbolsNeeded; n++) { var symbolType = reel.getWeightedRandomSymbol(); var newSymbol = new MegawaysSymbol(symbolType, reel.symbolTypes.indexOf(symbolType)); newSymbol.y = -400 - n * 70; // Start above screen reel.addChild(newSymbol); remainingSymbols.unshift(newSymbol); // Add to beginning } // Update reel's symbols array reel.symbols = remainingSymbols; // Animate all symbols to their final positions var symbolHeight = 105; // Height of each symbol with no gaps for (var i = 0; i < remainingSymbols.length; i++) { (function (symbol, index, finalReel) { var targetY = (index - (reel.currentSymbolCount - 1) / 2) * symbolHeight; // Scale new symbols to match existing ones symbol.scaleX = 1; symbol.scaleY = 1; symbol.startFalling(targetY, function () { if (index === remainingSymbols.length - 1) { cascadeComplete++; if (cascadeComplete === totalReels) { if (onComplete) onComplete(); } } }); })(remainingSymbols[i], i, reelIndex); } })(r); } }; // Get current ways display text self.getWaysText = function () { return self.currentWays + ' WAYS'; }; // Initialize reels self.createReels(); return self; }); var MegawaysSymbol = Container.expand(function (symbolType, symbolIndex) { var self = Container.call(this); self.symbolType = symbolType || 'megawaysSymbolA'; self.symbolIndex = symbolIndex || 0; self.isWild = symbolType === 'megawaysWild'; self.isScatter = symbolType === 'megawaysScatter'; self.marked = false; self.falling = false; // Symbol graphics var symbolGraphic = self.attachAsset(self.symbolType, { anchorX: 0.5, anchorY: 0.5 }); // Ensure clean state - no tinting symbolGraphic.tint = 0xFFFFFF; // Symbol assets for identification instead of text var symbolAssetNames = ['A', 'B', 'C', 'D', 'E', 'F', 'Wild', 'Scatter']; var symbolAsset = LK.getAsset(self.isWild ? 'Wild' : self.isScatter ? 'Scatter' : symbolAssetNames[self.symbolIndex], { anchorX: 0.5, anchorY: 0.5 }); symbolGraphic.addChild(symbolAsset); // Mark symbol for win combination self.markForWin = function () { if (self.marked) return; if (self.falling) return; // Don't mark while falling during cascade self.marked = true; // Play Simbolo sound when marking winning symbol LK.getSound('Simbolo').play(); tween(symbolGraphic, { tint: 0xffff00, scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.bounceOut }); }; // Start falling animation for cascade self.startFalling = function (targetY, onComplete) { if (self.falling) return; self.falling = true; // Reset any win markings and tint when falling self.marked = false; tween.stop(symbolGraphic, { tint: true, scaleX: true, scaleY: true }); symbolGraphic.tint = 0xFFFFFF; // Reset to white // Keep original scale instead of forcing 1.4 to prevent growth during cascade symbolGraphic.scaleX = 1.0; symbolGraphic.scaleY = 1.0; tween(self, { y: targetY }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { self.falling = false; if (onComplete) onComplete(); } }); }; // Explode and remove symbol self.explode = function (onComplete) { // Play Explosion sound when symbol explodes LK.getSound('Explosion').play(); tween(symbolGraphic, { scaleX: 0, scaleY: 0, alpha: 0, rotation: Math.PI * 2 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.destroy(); if (onComplete) onComplete(); } }); }; // Get symbol value for matching self.getSymbolValue = function () { if (self.isWild) return 'WILD'; if (self.isScatter) return 'SCATTER'; return self.symbolType; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0F4C3A }); /**** * Game Code ****/ // Hide blinking text when leaving menu if (spinHereText) { spinHereText.destroy(); spinHereText = null; } if (spinHereTextTimer) { LK.clearTimeout(spinHereTextTimer); spinHereTextTimer = null; } if (spinHereBlinkTimer) { LK.clearInterval(spinHereBlinkTimer); spinHereBlinkTimer = null; } // Card display removed from menu // Spades (Black Suit) - 13 cards // Clubs (Black Suit) - 13 cards // Diamonds (Red Suit) - 13 cards // Hearts (Red Suit) - 13 cards // Add background // Luxury slot machine frame assets - "La TentaciΓ³n Dorada" styling // Dark wood main frame // Gold inner border // Dark inlay // Dark blue/black reels background // Gold border around reels // Luxury SPIN button // Button border // Luxury MENU button // Corner decorations var fondoM = LK.getAsset('FondoM', { anchorX: 0.5, anchorY: 0.5 }); fondoM.x = 1024; fondoM.y = 1366; game.addChild(fondoM); // Add table background var tableBackground = LK.getAsset('fondo', { anchorX: 0.5, anchorY: 0.5 }); tableBackground.x = 1024; tableBackground.y = 1366; tableBackground.alpha = 0; game.addChild(tableBackground); // Add blackjack background var blackjackBackground = LK.getAsset('fondo', { anchorX: 0.5, anchorY: 0.5 }); blackjackBackground.x = 1024; blackjackBackground.y = 1366; blackjackBackground.alpha = 0; game.addChild(blackjackBackground); // Add slots background var slotsBackground = LK.getAsset('FondoS', { anchorX: 0.5, anchorY: 0.5 }); slotsBackground.x = 1024; slotsBackground.y = 1366; slotsBackground.alpha = 0; game.addChild(slotsBackground); // Add tragamonedas asset first (lower z-index) var tragamonedasAsset = LK.getAsset('tragamonedas', { anchorX: 0.5, anchorY: 0.5 }); tragamonedasAsset.x = 1024; tragamonedasAsset.y = 1200; // Moved higher up to overlap with slot machine tragamonedasAsset.alpha = 0; // Start hidden game.addChild(tragamonedasAsset); // Add Monedero asset in bottom left corner below tragamonedas var monederoAsset = LK.getAsset('Monedero', { anchorX: 0.5, anchorY: 0.5 }); monederoAsset.x = 280; // Left side position (270 + 10 pixels to the right) monederoAsset.y = 2590; // Below tragamonedas asset (2600 - 10 pixels up) monederoAsset.alpha = 0; // Start hidden game.addChild(monederoAsset); // Add Monedero2 asset in bottom right corner at same height as Monedero var monedero2Asset = LK.getAsset('Monedero2', { anchorX: 0.5, anchorY: 0.5 }); monedero2Asset.x = 1648; // Right side position moved 60 pixels left (1708 - 60) monedero2Asset.y = 2590; // Same height as Monedero monedero2Asset.alpha = 0; // Start hidden game.addChild(monedero2Asset); // Add mas asset to top right of Monedero var masAsset = LK.getAsset('mas', { anchorX: 0.5, anchorY: 0.5 }); masAsset.x = 570; // Right side of Monedero moved 20 pixels right (550 + 20) masAsset.y = 2510; // Above Monedero moved 60 pixels down (2450 + 60) masAsset.alpha = 0; // Start hidden game.addChild(masAsset); // Add click handler for mas asset masAsset.down = function (x, y, obj) { if (gameMode !== 'slots') return; if (currentBet * 2 <= playerMoney) { currentBet *= 2; totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); } }; // Add menos asset to bottom right of Monedero var menosAsset = LK.getAsset('menos', { anchorX: 0.5, anchorY: 0.5 }); menosAsset.x = 570; // Right side of Monedero moved 20 pixels right (550 + 20) menosAsset.y = 2680; // Below Monedero moved 10 pixels up (2690 - 10) menosAsset.alpha = 0; // Start hidden game.addChild(menosAsset); // Add click handler for menos asset menosAsset.down = function (x, y, obj) { if (gameMode !== 'slots') return; if (currentBet / 2 >= 25) { currentBet = currentBet / 2; totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); } }; // Add Megaways slot machine above tragamonedas (higher z-index) var megawaysSlotMachine = game.addChild(new MegawaysSlotMachine()); megawaysSlotMachine.x = 954; // Moved right by 60 pixels (894 + 60) megawaysSlotMachine.y = 1250; // Moved down by 200 pixels total (1050 + 200) megawaysSlotMachine.scaleX = 1.6; // Scale by 1.6 times larger megawaysSlotMachine.scaleY = 2.73; // Scale by 2.73 times larger (2.53 + 0.20 for additional 50px stretch) megawaysSlotMachine.alpha = 0; // Megaways display (hidden by default) var waysDisplay = new Text2('117,649 WAYS', { size: 48, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); waysDisplay.anchor.set(0.5, 0.5); waysDisplay.x = 1024; waysDisplay.y = 900; waysDisplay.alpha = 0; game.addChild(waysDisplay); // Win amount display var winAmountDisplay = new Text2('WIN: $0', { size: 56, fill: '#00FF00', font: "'Arial Black', Arial, sans-serif" }); winAmountDisplay.anchor.set(0.5, 0.5); winAmountDisplay.x = 1648; winAmountDisplay.y = 2590; winAmountDisplay.alpha = 0; game.addChild(winAmountDisplay); // Disclaimer UI elements // Use black background instead of warning asset game.setBackgroundColor(0x000000); var disclaimerTitle = new Text2('β οΈ IMPORTANT WARNING β οΈ', { size: 126, fill: '#FF0000', font: "'Arial Black', Arial, sans-serif" }); disclaimerTitle.anchor.set(0.5, 0.5); disclaimerTitle.x = 1024; disclaimerTitle.y = 650; disclaimerTitle.alpha = 1; game.addChild(disclaimerTitle); var disclaimerText1 = new Text2('β’ This game features a save system', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText1.anchor.set(0.5, 0.5); disclaimerText1.x = 1024; disclaimerText1.y = 950; disclaimerText1.alpha = 1; game.addChild(disclaimerText1); var disclaimerText2 = new Text2('β’ If you run out of virtual money,', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText2.anchor.set(0.5, 0.5); disclaimerText2.x = 1024; disclaimerText2.y = 1060; disclaimerText2.alpha = 1; game.addChild(disclaimerText2); var disclaimerText3 = new Text2('the only way to earn more is with the wheel', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText3.anchor.set(0.5, 0.5); disclaimerText3.x = 1024; disclaimerText3.y = 1170; disclaimerText3.alpha = 1; game.addChild(disclaimerText3); var disclaimerText4 = new Text2('β’ This game is for entertainment only', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText4.anchor.set(0.5, 0.5); disclaimerText4.x = 1024; disclaimerText4.y = 1280; disclaimerText4.alpha = 1; game.addChild(disclaimerText4); var disclaimerText5 = new Text2('β’ NO real money is involved', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText5.anchor.set(0.5, 0.5); disclaimerText5.x = 1024; disclaimerText5.y = 1390; disclaimerText5.alpha = 1; game.addChild(disclaimerText5); var disclaimerText6 = new Text2('β’ Gambling can be addictive', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText6.anchor.set(0.5, 0.5); disclaimerText6.x = 1024; disclaimerText6.y = 1500; disclaimerText6.alpha = 1; game.addChild(disclaimerText6); var disclaimerText7 = new Text2('β’ Real gambling can be harmful', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText7.anchor.set(0.5, 0.5); disclaimerText7.x = 1024; disclaimerText7.y = 1610; disclaimerText7.alpha = 1; game.addChild(disclaimerText7); var disclaimerText8 = new Text2('β’ Please seek help if needed', { size: 62, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); disclaimerText8.anchor.set(0.5, 0.5); disclaimerText8.x = 1024; disclaimerText8.y = 1720; disclaimerText8.alpha = 1; game.addChild(disclaimerText8); var continueButton = game.addChild(new GameButton('I UNDERSTAND - CONTINUE', 400, 100)); continueButton.x = 1024; continueButton.y = 2140; continueButton.alpha = 1; // Create larger invisible hit area for better touch responsiveness var continueButtonHitArea = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 600, // 50% wider than original height: 150, // 50% taller than original alpha: 0 // Invisible }); continueButtonHitArea.x = 0; continueButtonHitArea.y = 0; continueButton.addChild(continueButtonHitArea); // Make the hit area interactive and forward events to the button continueButtonHitArea.interactive = true; continueButtonHitArea.buttonMode = true; continueButtonHitArea.down = function (x, y, obj) { if (continueButton.down) continueButton.down(x, y, obj); }; continueButtonHitArea.up = function (x, y, obj) { if (continueButton.up) continueButton.up(x, y, obj); }; // Cascade counter (hidden by default) var cascadeDisplay = new Text2('', { size: 84, fill: '#FF6347', font: "'Arial Black', Arial, sans-serif" }); cascadeDisplay.anchor.set(0.5, 0.5); cascadeDisplay.x = 1024; cascadeDisplay.y = 1366; cascadeDisplay.alpha = 0; game.addChild(cascadeDisplay); // Cascade animation variables var lastCascadeCount = 0; var cascadeAnimationDisplay = null; // Game state var playerMoney = storage.playerMoney || 1000; var currentBet = 0; var gameMode = 'disclaimer'; // 'disclaimer', 'menu', 'blackjack', 'slots' var wheelScreenOpen = false; // Track if wheel screen is currently open var freeSpins = storage.freeSpins || 0; // Track free spins available var isBlackjack = false; // Track if current hand is a blackjack // Blinking text variables var spinHereText = null; var spinHereTextTimer = null; var spinHereBlinkTimer = null; // SpinI blinking variables var spinITimer = null; var spinIBlinkTimer = null; var spinIRecurringTimer = null; var spinISoundToggle = false; // Track when to play sound (alternating) // Initialize achievement system var achievementSystem = new AchievementSystem(); // Achievement tracking variables var consecutiveWins = storage.consecutiveWins || 0; var confirmedHighBet = false; // Chip system var chips = []; var chipContainer = game.addChild(new Container()); chipContainer.x = 1004; // Move 20 pixels left (1024 - 20) chipContainer.y = 2300; // Position below player cards chipContainer.alpha = 0; var moneyAfterBet = 0; var moneyAfterSpin = 0; var deck = []; var playerCards = []; var dealerCards = []; var gamePhase = 'betting'; // 'betting', 'dealing', 'playing', 'dealer', 'finished' var handInProgress = false; // Track if a hand is currently in progress var lastWaysCount = 0; var waysAnimationDisplay = null; // Total bet display for slots (positioned in center of Monedero) var totalBetDisplay = new Text2('$' + currentBet, { size: 108, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); totalBetDisplay.anchor.set(0.5, 0.5); totalBetDisplay.x = 280; // Same x position as Monedero totalBetDisplay.y = 2590; // Same y position as Monedero totalBetDisplay.alpha = 0; // Start hidden game.addChild(totalBetDisplay); // UI Elements var moneyDisplay = new Text2('$1000', { size: 112, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); moneyDisplay.anchor.set(0.5, 0.5); moneyDisplay.x = 974; moneyDisplay.y = 2596; // Position to overlap BalanceB asset (moved 30 pixels down) moneyDisplay.alpha = 0; game.addChild(moneyDisplay); // Add Remove asset positioned above TotalA asset var removeAsset = LK.getAsset('Remove', { anchorX: 0.5, anchorY: 0.5 }); removeAsset.x = 1724; // Same x position as totalA asset removeAsset.y = 2375; // Positioned above totalA asset (2475 - 100) removeAsset.alpha = 0; game.addChild(removeAsset); // Add click handler for Remove button removeAsset.down = function (x, y, obj) { if (gameMode !== 'blackjack') return; if (gamePhase !== 'betting') return; // Reset bet to 0 currentBet = 0; updateChipSelection(); LK.getSound('Ficha_2').play(); }; // Add TotalA asset at same horizontal height as chips and same vertical height as Home var totalAAsset = LK.getAsset('TotalA', { anchorX: 0.5, anchorY: 0.5 }); totalAAsset.x = 1724; // Move 200 pixels right from previous position (1524 + 200) totalAAsset.y = 2550; // Move 150 pixels down from previous position (2400 + 150) totalAAsset.alpha = 0; game.addChild(totalAAsset); // Add bet value display positioned at center of TotalA asset var betValueDisplay = new Text2('$' + currentBet, { size: 83, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); betValueDisplay.anchor.set(0.5, 0.5); betValueDisplay.x = 1814; // Move 10 pixels left (1824 - 10) betValueDisplay.y = 2545; // Move 5 pixels down (2540 + 5) betValueDisplay.alpha = 0; game.addChild(betValueDisplay); // Add BalanceB asset positioned in the middle of money display var balanceBAsset = LK.getAsset('BalanceB', { anchorX: 0.5, anchorY: 0.5 }); balanceBAsset.x = 974; // Same x position as money display balanceBAsset.y = 2566; // Moved 20 pixels down (2546 + 20) balanceBAsset.alpha = 0; game.addChild(balanceBAsset); // Add BalanceBJ asset positioned at same height as TotalA but on left side var balanceBJAsset = LK.getAsset('BalanceBJ', { anchorX: 0.5, anchorY: 0.5 }); balanceBJAsset.x = 324; // Left side position (mirroring TotalA position) balanceBJAsset.y = 2500; // Moved 30 pixels up (2530 - 30) balanceBJAsset.alpha = 0; game.addChild(balanceBJAsset); // Add Apuesta asset below deal button in blackjack mode var apuestaAsset = LK.getAsset('Apuesta', { anchorX: 0.5, anchorY: 0.5 }); apuestaAsset.x = 1024; // Same x position as deal button apuestaAsset.y = 1650; // Position below deal button (1450 + 200) apuestaAsset.alpha = 0; game.addChild(apuestaAsset); // Add player money display in center of BalanceBJ asset var playerMoneyDisplay = new Text2('$' + playerMoney, { size: 75, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); playerMoneyDisplay.anchor.set(0.5, 0.5); playerMoneyDisplay.x = 324; // Same x position as BalanceBJ asset playerMoneyDisplay.y = 2530; // Moved 10 pixels up (2540 - 10) playerMoneyDisplay.alpha = 0; game.addChild(playerMoneyDisplay); // Move money display after BalanceB so it renders on top game.removeChild(moneyDisplay); game.addChild(moneyDisplay); // Create message display for game feedback var messageDisplay = new Text2('', { size: 56, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); messageDisplay.anchor.set(0.5, 0.5); messageDisplay.x = 1024; messageDisplay.y = 800; messageDisplay.alpha = 0; game.addChild(messageDisplay); // Add welcome asset to main menu var welcomeAsset = LK.getAsset('Welcome', { anchorX: 0.5, anchorY: 0.5 }); welcomeAsset.x = 1024; welcomeAsset.y = 400; // 700 pixels above blackjack button (1100 - 700) game.addChild(welcomeAsset); // Menu buttons var blackjackButton = game.addChild(new GameButton('BLACKJACK', 300, 100)); blackjackButton.x = 1024; blackjackButton.y = 1100; // Replace the default button background with BlackJ asset var blackjackAsset = LK.getAsset('BlackJ', { anchorX: 0.5, anchorY: 0.5 }); blackjackButton.removeChild(blackjackButton.children[1]); // Remove default background blackjackButton.addChildAt(blackjackAsset, 1); // Add new asset as background var slotsButton = game.addChild(new GameButton('SLOT MACHINE', 300, 100)); slotsButton.x = 1004; slotsButton.y = 1750; // Replace the default button background with MaquinaB asset var slotAsset = LK.getAsset('MaquinaB', { anchorX: 0.5, anchorY: 0.5, width: 550, height: 550 }); slotsButton.removeChild(slotsButton.children[1]); // Remove default background slotsButton.addChildAt(slotAsset, 1); // Add new asset as background // Blackjack UI var hitButton = LK.getAsset('hit', { anchorX: 0.5, anchorY: 0.5 }); hitButton.x = 770; // Move 100 pixels right (670 + 100) hitButton.y = 2400; hitButton.alpha = 0; game.addChild(hitButton); var standButton = LK.getAsset('stand', { anchorX: 0.5, anchorY: 0.5 }); standButton.x = 1000; // Move 100 pixels right (900 + 100) standButton.y = 2400; standButton.alpha = 0; standButton.interactive = true; standButton.buttonMode = true; game.addChild(standButton); var doubleButton = LK.getAsset('double', { anchorX: 0.5, anchorY: 0.5 }); doubleButton.x = 1230; // Move 100 pixels right (1130 + 100) doubleButton.y = 2400; doubleButton.alpha = 0; game.addChild(doubleButton); // Deal button for blackjack var dealButton = LK.getAsset('DealB', { anchorX: 0.5, anchorY: 0.5 }); dealButton.x = 1024; // Center of table dealButton.y = 1300; // Move 500 pixels up from previous position (1800 - 500) dealButton.alpha = 0; game.addChild(dealButton); // Slots UI (classic slots removed - using Megaways only) var spinButton = game.addChild(new GameButton('SPIN $25', 200, 80)); spinButton.x = 974; spinButton.y = 2230; spinButton.alpha = 0; // Replace the default button background with circular assets spinButton.removeChild(spinButton.children[0]); // Remove shadow spinButton.removeChild(spinButton.children[0]); // Remove background (index shifts after first removal) var circularButton = LK.getAsset('circularSpinButton', { anchorX: 0.5, anchorY: 0.5 }); spinButton.addChildAt(circularButton, 0); // Create money difference display in center of Monedero2 asset var moneyDifferenceDisplay = new Text2('$0', { size: 79, fill: '#00FF00', font: "'Arial Black', Arial, sans-serif" }); moneyDifferenceDisplay.anchor.set(0.5, 0.5); moneyDifferenceDisplay.x = 1648; // Same x position as Monedero2 asset moneyDifferenceDisplay.y = 2590; // Same y position as Monedero2 asset moneyDifferenceDisplay.alpha = 0; // Add to game to position in center of Monedero2 game.addChild(moneyDifferenceDisplay); // Create new Home button with Home asset in upper right corner var homeButton = game.addChild(new GameButton('', 100, 100)); homeButton.x = 1850; // Upper right corner position (2048 - 198 to avoid top left menu area) homeButton.y = 200; // Near top of screen but below status bar homeButton.alpha = 0; // Replace the default button background with Home asset homeButton.removeChild(homeButton.children[0]); // Remove shadow homeButton.removeChild(homeButton.children[0]); // Remove background (index shifts after first removal) var homeAsset = LK.getAsset('Home', { anchorX: 0.5, anchorY: 0.5 }); homeButton.addChildAt(homeAsset, 0); // Create Logros button in bottom left of main menu var logrosButton = game.addChild(new GameButton('', 100, 100)); logrosButton.x = 200; // Bottom left corner position logrosButton.y = 2500; // Bottom of screen logrosButton.alpha = 0; // Replace the default button background with Logros asset logrosButton.removeChild(logrosButton.children[0]); // Remove shadow logrosButton.removeChild(logrosButton.children[0]); // Remove background (index shifts after first removal) var logrosAsset = LK.getAsset('Logros', { anchorX: 0.5, anchorY: 0.5 }); logrosButton.addChildAt(logrosAsset, 0); // Create RuedaP button at Sugerencia position var ruedaPButton = game.addChild(new GameButton('', 100, 100)); ruedaPButton.x = 1848; // Same position as Sugerencia asset ruedaPButton.y = 2500; // Same position as Sugerencia asset ruedaPButton.alpha = 0; // Replace the default button background with RuedaP asset ruedaPButton.removeChild(ruedaPButton.children[0]); // Remove shadow ruedaPButton.removeChild(ruedaPButton.children[0]); // Remove background (index shifts after first removal) var ruedaPAsset = LK.getAsset('RuedaP', { anchorX: 0.5, anchorY: 0.5 }); ruedaPButton.addChildAt(ruedaPAsset, 0); // Declare wheelTimerDisplay variable var wheelTimerDisplay; // Create wheel timer display above RuedaP button wheelTimerDisplay = new Text2('', { size: 48, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); wheelTimerDisplay.anchor.set(0.5, 0.5); wheelTimerDisplay.x = 1848; // Same x position as RuedaP button wheelTimerDisplay.y = 2300; // 100 pixels above RuedaP button (moved up 100px from 2400) wheelTimerDisplay.alpha = 0; game.addChild(wheelTimerDisplay); // Create Statistics button in top right corner var statisticsButton = game.addChild(new GameButton('', 100, 100)); statisticsButton.x = 1850; // Top right position (same as home button x) statisticsButton.y = 450; // Below home button (200 + 150 + 100) statisticsButton.alpha = 0; // Replace the default button background with Estadisticas asset statisticsButton.removeChild(statisticsButton.children[0]); // Remove shadow statisticsButton.removeChild(statisticsButton.children[0]); // Remove background (index shifts after first removal) var estadisticasAsset = LK.getAsset('Estadisticas', { anchorX: 0.5, anchorY: 0.5 }); statisticsButton.addChildAt(estadisticasAsset, 0); // Create SpinI button to the left of RuedaP var spinIButton = game.addChild(new GameButton('', 100, 100)); spinIButton.x = 1488; // Moved 40 pixels to the right (1448 + 40) spinIButton.y = 2500; // Same height as RuedaP spinIButton.alpha = 0; // Replace the default button background with SpinI asset spinIButton.removeChild(spinIButton.children[0]); // Remove shadow spinIButton.removeChild(spinIButton.children[0]); // Remove background (index shifts after first removal) var spinIAsset = LK.getAsset('SpinI', { anchorX: 0.5, anchorY: 0.5 }); spinIButton.addChildAt(spinIAsset, 0); // Add deck and hands var gameDeck = game.addChild(new Deck()); gameDeck.x = 200; gameDeck.y = 1366; gameDeck.alpha = 0; // Add animated hands for dealing animations var dealerAnimatedHand = game.addChild(new AnimatedHand(true)); dealerAnimatedHand.x = 300; dealerAnimatedHand.y = 600; dealerAnimatedHand.alpha = 0; var playerAnimatedHand = game.addChild(new AnimatedHand(false)); playerAnimatedHand.x = 300; playerAnimatedHand.y = 2000; playerAnimatedHand.alpha = 0; // Score displays var playerScoreText = new Text2('Player: 0', { size: 36, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); playerScoreText.anchor.set(0.5, 0.5); playerScoreText.x = 1024; playerScoreText.y = 1850; playerScoreText.alpha = 0; game.addChild(playerScoreText); var dealerScoreText = new Text2('Dealer: 0', { size: 36, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); dealerScoreText.anchor.set(0.5, 0.5); dealerScoreText.x = 1024; dealerScoreText.y = 750; dealerScoreText.alpha = 0; game.addChild(dealerScoreText); // Create betting chips function createChips() { // Clear existing chips for (var i = 0; i < chips.length; i++) { chips[i].destroy(); } chips = []; var chipValues = [1, 5, 10, 25, 100, 500]; for (var i = 0; i < chipValues.length; i++) { var chip = new Chip(chipValues[i]); chip.x = (i - 2.5) * 120; // Spread chips horizontally with 20 more pixels separation chip.y = 300; // Move chips 300 pixels down chipContainer.addChild(chip); chips.push(chip); } updateChipSelection(); } function updateChipSelection() { // Update chip availability based on player money for (var i = 0; i < chips.length; i++) { chips[i].setEnabled(playerMoney >= chips[i].value); } // Update bet value display at center of TotalA asset betValueDisplay.setText('$' + currentBet); // Update deal button state based on bet amount - only show once per hand if (gameMode === 'blackjack' && !handInProgress) { if (currentBet === 0) { // Hide deal button when bet is zero tween(dealButton, { alpha: 0 }, { duration: 200 }); // Hide remove button when bet is zero tween(removeAsset, { alpha: 0 }, { duration: 200 }); } else { // Show deal button when bet is greater than zero and no hand in progress tween(dealButton, { alpha: 1 }, { duration: 200 }); // Show remove button when bet is greater than zero and no hand in progress tween(removeAsset, { alpha: 1 }, { duration: 200 }); } } } // Button event handlers blackjackButton.up = function () { if (gameMode !== 'menu') return; if (!blackjackButton.enabled) return; switchToBlackjack(); }; slotsButton.up = function () { if (gameMode !== 'menu') return; if (!slotsButton.enabled) return; switchToSlots(); }; hitButton.down = function (x, y, obj) { if (gameMode !== 'blackjack') return; if (gamePhase !== 'playing') return; playerHit(); }; standButton.down = function (x, y, obj) { if (gameMode !== 'blackjack') return; if (gamePhase !== 'playing') return; // Don't call playerStand() on down event to prevent double calls LK.getSound('buttonClick').play(); }; standButton.up = function (x, y, obj) { // Stand button up handler - only call playerStand here if (gameMode !== 'blackjack') return; if (gamePhase !== 'playing') return; // Only trigger if we haven't already processed this action if (gamePhase === 'playing') { playerStand(); } }; doubleButton.down = function (x, y, obj) { if (gameMode !== 'blackjack') return; if (gamePhase !== 'playing') return; if (playerMoney < currentBet) return; playerDouble(); }; homeButton.up = function () { if (!homeButton.enabled) return; // Prevent leaving blackjack if hand is in progress if (gameMode === 'blackjack' && handInProgress) return; // Prevent leaving slots if spin is in progress if (gameMode === 'slots' && slotsSpinInProgress) return; switchToMenu(); }; logrosButton.up = function () { if (gameMode !== 'menu') return; if (!logrosButton.enabled) return; showAchievementsScreen(); }; ruedaPButton.up = function () { if (gameMode !== 'menu') return; if (!ruedaPButton.enabled) return; if (wheelScreenOpen) return; // Prevent re-entry if wheel is already open if (!isWheelAvailable()) return; // Prevent opening if wheel is on cooldown showWheelScreen(); }; statisticsButton.up = function () { if (gameMode !== 'menu') return; if (!statisticsButton.enabled) return; showStatisticsScreen(); }; // SpinI button has no functionality - purely aesthetic continueButton.up = function () { if (gameMode !== 'disclaimer') return; if (!continueButton.enabled) return; switchToMenu(); }; dealButton.down = function (x, y, obj) { if (gameMode !== 'blackjack') return; if (gamePhase !== 'betting') return; if (currentBet === 0) return; // Can't deal with zero bet // Hide deal button immediately when pressed dealButton.alpha = 0; startNewBlackjackHand(); }; spinButton.up = function () { if (gameMode !== 'slots') return; if (!spinButton.enabled) return; spinSlots(); }; // Game functions function updateMoneyDisplay() { moneyDisplay.setText('$' + playerMoney); playerMoneyDisplay.setText('$' + playerMoney); storage.playerMoney = playerMoney; updateMoneyDifferenceDisplay(); achievementSystem.checkAchievement('reach10k', playerMoney); // Update chip availability if in blackjack mode if (gameMode === 'blackjack' && chips.length > 0) { updateChipSelection(); } // Reset bet to 25 if current bet exceeds player money and we're in slots mode if (gameMode === 'slots' && currentBet > playerMoney) { currentBet = 25; totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); spinButton.setEnabled(playerMoney >= currentBet); } // Reset bet in blackjack if current bet exceeds player money if (gameMode === 'blackjack' && currentBet > playerMoney) { // Find highest affordable chip value var affordableChips = [1, 5, 10, 25, 100, 500].filter(function (value) { return value <= playerMoney; }); if (affordableChips.length > 0) { currentBet = affordableChips[affordableChips.length - 1]; } else { currentBet = 1; } updateChipSelection(); } if (playerMoney >= 1000000) { LK.showYouWin(); } } function updateMoneyDifferenceDisplay() { var difference = moneyAfterSpin - moneyAfterBet; moneyDifferenceDisplay.setText('$' + difference); // Clear any existing spin here text if (spinHereText) { spinHereText.destroy(); spinHereText = null; } if (spinHereTextTimer) { LK.clearTimeout(spinHereTextTimer); spinHereTextTimer = null; } if (spinHereBlinkTimer) { LK.clearInterval(spinHereBlinkTimer); spinHereBlinkTimer = null; } // Create blinking "spin here" text after 2 seconds in main menu spinHereTextTimer = LK.setTimeout(function () { if (gameMode !== 'menu') return; // Only show if still in menu // Create "spin here" text spinHereText = new Text2('SPIN HERE', { size: 48, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); spinHereText.anchor.set(0.5, 0.5); spinHereText.x = 1848; spinHereText.y = 2350; // Position above RuedaP button at new location (2500 - 150) spinHereText.alpha = 1; game.addChild(spinHereText); // Make it blink var blinkVisible = true; spinHereBlinkTimer = LK.setInterval(function () { if (!spinHereText) return; blinkVisible = !blinkVisible; tween(spinHereText, { alpha: blinkVisible ? 1 : 0.3 }, { duration: 500, easing: tween.easeInOut }); }, 600); }, 2000); // Clear any existing SpinI timers when entering menu if (spinITimer) { LK.clearTimeout(spinITimer); spinITimer = null; } if (spinIBlinkTimer) { LK.clearInterval(spinIBlinkTimer); spinIBlinkTimer = null; } // Card display removed from menu } function createDeck() { deck = []; var suits = ['hearts', 'diamonds', 'clubs', 'spades']; for (var s = 0; s < suits.length; s++) { for (var v = 1; v <= 13; v++) { deck.push({ suit: suits[s], value: v }); } } // Shuffle deck for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } function dealCard(isDealer, callback) { if (deck.length === 0) createDeck(); var cardData = deck.pop(); var card = isDealer ? new DealerCard(cardData.suit, cardData.value) : new Card(cardData.suit, cardData.value); var targetX, targetY; if (isDealer) { dealerCards.push(card); targetX = 930 + (dealerCards.length - 1) * 240; // Move dealer cards 20 pixels left (950 - 20) targetY = 500; } else { playerCards.push(card); targetX = 850 + (playerCards.length - 1) * 280; // Move player cards 50 pixels right (800 + 50) targetY = 2100; } card.x = targetX; card.y = targetY; card.alpha = 0; game.addChild(card); // Use animated hand for dealing var animatedHand = isDealer ? dealerAnimatedHand : playerAnimatedHand; if (isDealer) { animatedHand.dealCardFaceDown(targetX, targetY, function () { tween(card, { alpha: 1 }, { duration: 200, onFinish: function onFinish() { card.flip(); if (callback) callback(); } }); }); } else { animatedHand.dealCardToPlayer(targetX, targetY, function () { tween(card, { alpha: 1 }, { duration: 200, onFinish: function onFinish() { card.flip(); if (callback) callback(); } }); }); } return card; } function calculateHandValue(cards) { var value = 0; var aces = 0; for (var i = 0; i < cards.length; i++) { var cardValue = cards[i].getBlackjackValue(); if (cardValue === 11) aces++; value += cardValue; } // Adjust for aces while (value > 21 && aces > 0) { value -= 10; aces--; } return value; } function updateScoreDisplays() { var playerScore = calculateHandValue(playerCards); var dealerScore = calculateHandValue(dealerCards); playerScoreText.setText('Player: ' + playerScore); if (dealerCards.length > 0 && dealerCards[0].faceUp) { dealerScoreText.setText('Dealer: ' + dealerScore); } else if (dealerCards.length > 1) { var visibleScore = dealerCards[1].getBlackjackValue(); dealerScoreText.setText('Dealer: ' + visibleScore + ' + ?'); } } function crossFadeTransition(hideElements, showElements, callback) { var fadeOutComplete = 0; var totalFadeOut = hideElements.length; // Fade out old elements for (var i = 0; i < hideElements.length; i++) { tween(hideElements[i], { alpha: 0 }, { duration: 400, easing: tween.easeInOut, onFinish: function onFinish() { fadeOutComplete++; if (fadeOutComplete === totalFadeOut) { // Start fading in new elements for (var j = 0; j < showElements.length; j++) { tween(showElements[j], { alpha: showElements[j].targetAlpha || 1 }, { duration: 400, delay: j * 50, easing: tween.easeInOut }); } if (callback) callback(); } } }); } } function switchToMenu() { gameMode = 'menu'; // Set background to match fondoM to prevent green strip game.setBackgroundColor(0x000000); // Play random crupier menu sound on first entry to menu if (isFirstMenuEntry) { var menuSounds = ['Cuprier_Menu_1', 'Cuprier_Menu_2', 'Cuprier_Menu_3']; var randomSound = menuSounds[Math.floor(Math.random() * menuSounds.length)]; LK.getSound(randomSound).play(); isFirstMenuEntry = false; // Set to false after first play } // Re-enable buttons when entering menu (they were disabled during disclaimer) blackjackButton.setEnabled(true); slotsButton.setEnabled(true); logrosButton.setEnabled(true); ruedaPButton.setEnabled(true); spinIButton.setEnabled(true); statisticsButton.setEnabled(true); // Clear SpinI timers when switching modes if (spinITimer) { LK.clearTimeout(spinITimer); spinITimer = null; } if (spinIBlinkTimer) { LK.clearInterval(spinIBlinkTimer); spinIBlinkTimer = null; } // Start SpinI visibility timer - show SpinI after 3 seconds in menu (only if wheel timer is not running) spinITimer = LK.setTimeout(function () { if (gameMode !== 'menu') return; // Only show if still in menu // Skip SpinI verification when wheel timer is active if (wheelCooldownTimer) return; // Don't show SpinI if wheel timer is running // Show SpinI button first spinIButton.alpha = 1; // Make button visible immediately // Reset sound toggle when starting new animation sequence spinISoundToggle = false; // Start continuous alpha alternation between 1 and 0 every second function alternateAlpha() { tween(spinIAsset, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { tween(spinIAsset, { alpha: 1 }, { duration: 1000, onFinish: function onFinish() { // Toggle sound - play only every other time spinISoundToggle = !spinISoundToggle; if (spinISoundToggle && gameMode === 'menu') { LK.getSound('SpinHere').play(); } alternateAlpha(); } }); } }); } alternateAlpha(); }, 3000); // Add recurring check every 3 seconds to ensure SpinI is visible in menu spinIRecurringTimer = LK.setInterval(function () { if (gameMode !== 'menu') return; // Only check if in menu // Skip SpinI verification when wheel timer is active if (wheelCooldownTimer) return; // Don't restart SpinI if wheel timer is running if (spinIButton.alpha === 0 || spinIAsset.alpha === 0) { // Restart the blinking animation var _alternateAlpha = function alternateAlpha() { tween(spinIAsset, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { tween(spinIAsset, { alpha: 1 }, { duration: 1000, onFinish: function onFinish() { // Toggle sound - play only every other time spinISoundToggle = !spinISoundToggle; if (spinISoundToggle && gameMode === 'menu') { LK.getSound('SpinHere').play(); } _alternateAlpha(); } }); } }); }; // SpinI is not visible, make it visible and restart animation spinIButton.alpha = 1; spinIAsset.alpha = 1; // Reset sound toggle when restarting animation spinISoundToggle = false; _alternateAlpha(); } else { // SpinI is visible, stop the recurring timer LK.clearInterval(spinIRecurringTimer); spinIRecurringTimer = null; } }, 3000); // Disable buttons from other game modes hitButton.interactive = false; hitButton.buttonMode = false; standButton.interactive = false; standButton.buttonMode = false; doubleButton.interactive = false; doubleButton.buttonMode = false; dealButton.interactive = false; dealButton.buttonMode = false; spinButton.setEnabled(false); for (var i = 0; i < chips.length; i++) { if (chips[i] && chips[i].setEnabled) { chips[i].setEnabled(false); } } masAsset.interactive = false; masAsset.buttonMode = false; menosAsset.interactive = false; menosAsset.buttonMode = false; removeAsset.interactive = false; removeAsset.buttonMode = false; // Stop any currently playing music and play Menu music LK.stopMusic(); LK.playMusic('Menu'); tween(disclaimerTitle, { alpha: 0 }, { duration: 300 }); tween(disclaimerText1, { alpha: 0 }, { duration: 300 }); tween(disclaimerText2, { alpha: 0 }, { duration: 300 }); tween(disclaimerText3, { alpha: 0 }, { duration: 300 }); tween(disclaimerText4, { alpha: 0 }, { duration: 300 }); tween(disclaimerText5, { alpha: 0 }, { duration: 300 }); tween(disclaimerText6, { alpha: 0 }, { duration: 300 }); tween(disclaimerText7, { alpha: 0 }, { duration: 300 }); tween(disclaimerText8, { alpha: 0 }, { duration: 300 }); tween(continueButton, { alpha: 0 }, { duration: 300 }); // Hide all game elements tween(hitButton, { alpha: 0 }, { duration: 300 }); tween(standButton, { alpha: 0 }, { duration: 300 }); tween(doubleButton, { alpha: 0 }, { duration: 300 }); tween(playerScoreText, { alpha: 0 }, { duration: 300 }); tween(dealerScoreText, { alpha: 0 }, { duration: 300 }); // Classic slot reels removed (using Megaways only) tween(spinButton, { alpha: 0 }, { duration: 300 }); tween(gameDeck, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { // Stop deck animation when leaving blackjack mode if (gameDeck.stopDeckAnimation) { gameDeck.stopDeckAnimation(); } } }); tween(dealerAnimatedHand, { alpha: 0 }, { duration: 300 }); tween(playerAnimatedHand, { alpha: 0 }, { duration: 300 }); // Show main menu background tween(fondoM, { alpha: 1 }, { duration: 300 }); // Show menu buttons tween(blackjackButton, { alpha: 1 }, { duration: 300 }); tween(slotsButton, { alpha: 1 }, { duration: 300 }); tween(welcomeAsset, { alpha: 1 }, { duration: 300 }); // Show new menu buttons tween(logrosButton, { alpha: 1 }, { duration: 300 }); tween(ruedaPButton, { alpha: 1 }, { duration: 300 }); tween(statisticsButton, { alpha: 1 }, { duration: 300 }); // Show wheel timer display tween(wheelTimerDisplay, { alpha: 1 }, { duration: 300 }); // Start wheel cooldown timer when entering menu startWheelCooldownTimer(); // SpinI button will be shown after 3 seconds via timer spinIButton.alpha = 0; // Keep hidden initially // Card display removed from menu // Hide blackjack background tween(blackjackBackground, { alpha: 0 }, { duration: 300 }); // Hide table background tween(tableBackground, { alpha: 0 }, { duration: 300 }); // Hide slots background tween(slotsBackground, { alpha: 0 }, { duration: 300 }); // Hide tragamonedas asset in menu mode tween(tragamonedasAsset, { alpha: 0 }, { duration: 300 }); // Hide Monedero asset in menu mode tween(monederoAsset, { alpha: 0 }, { duration: 300 }); // Hide Monedero2 asset in menu mode tween(monedero2Asset, { alpha: 0 }, { duration: 300 }); // Hide total bet display in menu mode tween(totalBetDisplay, { alpha: 0 }, { duration: 300 }); // Hide mas asset in menu mode tween(masAsset, { alpha: 0 }, { duration: 300 }); // Hide menos asset in menu mode tween(menosAsset, { alpha: 0 }, { duration: 300 }); // Hide Megaways slot machine // Show Home button in blackjack mode tween(homeButton, { alpha: 1 }, { duration: 300 }); tween(megawaysSlotMachine, { alpha: 0 }, { duration: 300 }); // Hide Megaways displays tween(waysDisplay, { alpha: 0 }, { duration: 300 }); tween(winAmountDisplay, { alpha: 0 }, { duration: 300 }); tween(cascadeDisplay, { alpha: 0 }, { duration: 300 }); // Hide win amount display in menu mode tween(winAmountDisplay, { alpha: 0 }, { duration: 300 }); // Hide ways animation if showing if (waysAnimationDisplay) { tween(waysAnimationDisplay, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (waysAnimationDisplay) { waysAnimationDisplay.destroy(); waysAnimationDisplay = null; } } }); } // Hide cascade animation if showing if (cascadeAnimationDisplay) { tween(cascadeAnimationDisplay, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { if (cascadeAnimationDisplay) { cascadeAnimationDisplay.destroy(); cascadeAnimationDisplay = null; } } }); } // Hide money display in menu mode tween(moneyDisplay, { alpha: 0 }, { duration: 300 }); // Hide BalanceB asset in menu mode tween(balanceBAsset, { alpha: 0 }, { duration: 300 }); // Clear cards // Hide money difference display in menu mode tween(moneyDifferenceDisplay, { alpha: 0 }, { duration: 300 }); // Hide chips in menu mode tween(chipContainer, { alpha: 0 }, { duration: 300 }); // Hide Home button in menu mode tween(homeButton, { alpha: 0 }, { duration: 300 }); // Hide deal button in menu mode tween(dealButton, { alpha: 0 }, { duration: 300 }); // Hide Remove asset in menu mode tween(removeAsset, { alpha: 0 }, { duration: 300 }); // Hide TotalA asset in menu mode tween(totalAAsset, { alpha: 0 }, { duration: 300 }); // Hide bet value display in menu mode tween(betValueDisplay, { alpha: 0 }, { duration: 300 }); // Hide BalanceBJ asset in menu mode tween(balanceBJAsset, { alpha: 0 }, { duration: 300 }); // Hide player money display in menu mode tween(playerMoneyDisplay, { alpha: 0 }, { duration: 300 }); // Hide Apuesta asset in menu mode tween(apuestaAsset, { alpha: 0 }, { duration: 300 }); clearTable(); } function switchToBlackjack() { gameMode = 'blackjack'; gamePhase = 'betting'; // Reset bet to 0 when switching to blackjack currentBet = 0; // Stop any currently playing music and play BJ music LK.stopMusic(); LK.playMusic('BJ'); // Play random croupier BlackJack greeting sound var bjSounds = ['Cuprier_BJ_1', 'Cuprier_BJ_2', 'Cuprier_BJ_3']; var randomBJSound = bjSounds[Math.floor(Math.random() * bjSounds.length)]; LK.getSound(randomBJSound).play(); // Hide menu buttons tween(blackjackButton, { alpha: 0 }, { duration: 300 }); tween(slotsButton, { alpha: 0 }, { duration: 300 }); tween(welcomeAsset, { alpha: 0 }, { duration: 300 }); // Hide new menu buttons tween(logrosButton, { alpha: 0 }, { duration: 300 }); tween(ruedaPButton, { alpha: 0 }, { duration: 300 }); tween(statisticsButton, { alpha: 0 }, { duration: 300 }); tween(spinIButton, { alpha: 0 }, { duration: 300 }); // Hide wheel timer display in blackjack mode tween(wheelTimerDisplay, { alpha: 0 }, { duration: 300 }); // Stop wheel cooldown timer when leaving menu if (wheelCooldownTimer) { LK.clearInterval(wheelCooldownTimer); wheelCooldownTimer = null; } // Disable menu buttons functionality in blackjack mode blackjackButton.setEnabled(false); slotsButton.setEnabled(false); logrosButton.setEnabled(false); ruedaPButton.setEnabled(false); spinIButton.setEnabled(false); statisticsButton.setEnabled(false); // Enable blackjack buttons hitButton.interactive = true; hitButton.buttonMode = true; standButton.interactive = true; standButton.buttonMode = true; doubleButton.interactive = true; doubleButton.buttonMode = true; dealButton.interactive = true; dealButton.buttonMode = true; removeAsset.interactive = true; removeAsset.buttonMode = true; // Disable slots buttons functionality in blackjack mode spinButton.setEnabled(false); masAsset.interactive = false; masAsset.buttonMode = false; menosAsset.interactive = false; menosAsset.buttonMode = false; // Hide blinking text when leaving menu if (spinHereText) { spinHereText.destroy(); spinHereText = null; } if (spinHereTextTimer) { LK.clearTimeout(spinHereTextTimer); spinHereTextTimer = null; } if (spinHereBlinkTimer) { LK.clearInterval(spinHereBlinkTimer); spinHereBlinkTimer = null; } // Clear SpinI timers when switching modes if (spinITimer) { LK.clearTimeout(spinITimer); spinITimer = null; } if (spinIBlinkTimer) { LK.clearInterval(spinIBlinkTimer); spinIBlinkTimer = null; } if (spinIRecurringTimer) { LK.clearInterval(spinIRecurringTimer); spinIRecurringTimer = null; } // Create blinking "spin here" text after 2 seconds in main menu spinHereTextTimer = LK.setTimeout(function () { if (gameMode !== 'menu') return; // Only show if still in menu // Create "spin here" text spinHereText = new Text2('SPIN HERE', { size: 48, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); spinHereText.anchor.set(0.5, 0.5); spinHereText.x = 1848; spinHereText.y = 2350; // Position above RuedaP button at new location (2500 - 150) spinHereText.alpha = 1; game.addChild(spinHereText); // Make it blink var blinkVisible = true; spinHereBlinkTimer = LK.setInterval(function () { if (!spinHereText) return; blinkVisible = !blinkVisible; tween(spinHereText, { alpha: blinkVisible ? 1 : 0.3 }, { duration: 500, easing: tween.easeInOut }); }, 600); }, 2000); // Card display removed from menu // Hide main menu background tween(fondoM, { alpha: 0 }, { duration: 300 }); // Show blackjack background tween(blackjackBackground, { alpha: 1 }, { duration: 300 }); // Show table background tween(tableBackground, { alpha: 1 }, { duration: 300 }); // Ensure no unwanted coloring tableBackground.tint = 0xffffff; // Show blackjack UI tween(playerScoreText, { alpha: 1 }, { duration: 300 }); tween(dealerScoreText, { alpha: 1 }, { duration: 300 }); // Ensure stand button is properly interactive standButton.interactive = true; standButton.buttonMode = true; tween(gameDeck, { alpha: 1 }, { duration: 300, onFinish: function onFinish() { // Start deck animation when it becomes visible if (gameDeck.startDeckAnimation) { gameDeck.startDeckAnimation(); } } }); tween(dealerAnimatedHand, { alpha: 1 }, { duration: 300 }); tween(playerAnimatedHand, { alpha: 1 }, { duration: 300 }); // Hide total bet display in blackjack mode tween(totalBetDisplay, { alpha: 0 }, { duration: 300 }); // Hide Monedero2 asset in blackjack mode tween(monedero2Asset, { alpha: 0 }, { duration: 300 }); // Hide mas asset in blackjack mode tween(masAsset, { alpha: 0 }, { duration: 300 }); // Hide menos asset in blackjack mode tween(menosAsset, { alpha: 0 }, { duration: 300 }); // Hide money display in blackjack mode tween(moneyDisplay, { alpha: 0 }, { duration: 300 }); // Hide money difference display in blackjack mode tween(moneyDifferenceDisplay, { alpha: 0 }, { duration: 300 }); // Hide BalanceB asset in blackjack mode tween(balanceBAsset, { alpha: 0 }, { duration: 300 }); // Show Home button in blackjack mode tween(homeButton, { alpha: 1 }, { duration: 300 }); // Show Remove asset in blackjack mode tween(removeAsset, { alpha: 1 }, { duration: 300 }); // Show TotalA asset in blackjack mode tween(totalAAsset, { alpha: 1 }, { duration: 300 }); // Show bet value display in blackjack mode tween(betValueDisplay, { alpha: 1 }, { duration: 300 }); // Show BalanceBJ asset in blackjack mode tween(balanceBJAsset, { alpha: 1 }, { duration: 300 }); // Show player money display in blackjack mode tween(playerMoneyDisplay, { alpha: 1 }, { duration: 300 }); // Show Apuesta asset in blackjack mode tween(apuestaAsset, { alpha: 1 }, { duration: 300 }); // Show deal button in blackjack mode only if bet is greater than zero if (currentBet > 0) { tween(dealButton, { alpha: 1 }, { duration: 300 }); } else { dealButton.alpha = 0; // Keep hidden if no bet } // Show chips and bet display tween(chipContainer, { alpha: 1 }, { duration: 300 }); // Create chips if not already created if (chips.length === 0) { createChips(); } else { updateChipSelection(); } } function switchToSlots() { gameMode = 'slots'; // Stop any currently playing music and play SpinM music LK.stopMusic(); LK.playMusic('SpinM'); // Hide menu buttons tween(blackjackButton, { alpha: 0 }, { duration: 300 }); tween(slotsButton, { alpha: 0 }, { duration: 300 }); tween(welcomeAsset, { alpha: 0 }, { duration: 300 }); // Hide new menu buttons tween(logrosButton, { alpha: 0 }, { duration: 300 }); tween(ruedaPButton, { alpha: 0 }, { duration: 300 }); tween(statisticsButton, { alpha: 0 }, { duration: 300 }); tween(spinIButton, { alpha: 0 }, { duration: 300 }); // Hide wheel timer display in slots mode tween(wheelTimerDisplay, { alpha: 0 }, { duration: 300 }); // Stop wheel cooldown timer when leaving menu if (wheelCooldownTimer) { LK.clearInterval(wheelCooldownTimer); wheelCooldownTimer = null; } // Disable menu buttons functionality in slots mode blackjackButton.setEnabled(false); slotsButton.setEnabled(false); logrosButton.setEnabled(false); ruedaPButton.setEnabled(false); spinIButton.setEnabled(false); statisticsButton.setEnabled(false); // Disable blackjack buttons functionality in slots mode hitButton.interactive = false; hitButton.buttonMode = false; standButton.interactive = false; standButton.buttonMode = false; doubleButton.interactive = false; doubleButton.buttonMode = false; dealButton.interactive = false; dealButton.buttonMode = false; removeAsset.interactive = false; removeAsset.buttonMode = false; for (var i = 0; i < chips.length; i++) { if (chips[i] && chips[i].setEnabled) { chips[i].setEnabled(false); } } // Enable slots buttons masAsset.interactive = true; masAsset.buttonMode = true; menosAsset.interactive = true; menosAsset.buttonMode = true; // Card display removed from menu // Hide main menu background tween(fondoM, { alpha: 0 }, { duration: 300 }); // Hide blackjack background tween(blackjackBackground, { alpha: 0 }, { duration: 300 }); // Show slots background (same as main menu) tween(fondoM, { alpha: 1 }, { duration: 300 }); // Show tragamonedas asset in slots mode tween(tragamonedasAsset, { alpha: 1 }, { duration: 300 }); // Show Monedero asset in slots mode tween(monederoAsset, { alpha: 1 }, { duration: 300 }); // Show Monedero2 asset in slots mode tween(monedero2Asset, { alpha: 1 }, { duration: 300 }); // Show total bet display in slots mode tween(totalBetDisplay, { alpha: 1 }, { duration: 300 }); // Show mas asset in slots mode tween(masAsset, { alpha: 1 }, { duration: 300 }); // Show menos asset in slots mode tween(menosAsset, { alpha: 1 }, { duration: 300 }); // Show Megaways slot machine tween(megawaysSlotMachine, { alpha: 1 }, { duration: 300 }); // Hide win amount display in slots mode tween(winAmountDisplay, { alpha: 0 }, { duration: 300 }); // Keep cascade display hidden (will show via animation when needed) // Show slots UI (classic reels removed - using Megaways only) tween(spinButton, { alpha: 1 }, { duration: 300 }); // Set minimum bet to 25 when switching to slots if (currentBet < 25) { currentBet = 25; } // Reset bet to 25 if current bet exceeds player money when switching to slots if (currentBet > playerMoney) { currentBet = 25; } // Set bet to 25 when entering slots, but display FREE if free spins available currentBet = 25; if (freeSpins > 0) { totalBetDisplay.setText('FREE'); spinButton.setText('SPIN FREE'); } else { totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); } console.log('Setting spin button enabled - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabled:', playerMoney >= currentBet); spinButton.setEnabled(playerMoney >= currentBet); // Show money difference display in slots mode tween(moneyDifferenceDisplay, { alpha: 1 }, { duration: 300 }); // Show Home button in slots mode tween(homeButton, { alpha: 1 }, { duration: 300 }); // Show money display in slots mode tween(moneyDisplay, { alpha: 1 }, { duration: 300 }); // Show BalanceB asset in slots mode tween(balanceBAsset, { alpha: 1 }, { duration: 300 }); // Hide deal button in slots mode tween(dealButton, { alpha: 0 }, { duration: 300 }); // Stop deck animation when in slots mode if (gameDeck.stopDeckAnimation) { gameDeck.stopDeckAnimation(); } // Hide Remove asset in slots mode tween(removeAsset, { alpha: 0 }, { duration: 300 }); // Hide TotalA asset in slots mode tween(totalAAsset, { alpha: 0 }, { duration: 300 }); // Hide bet value display in slots mode tween(betValueDisplay, { alpha: 0 }, { duration: 300 }); // Hide BalanceBJ asset in slots mode tween(balanceBJAsset, { alpha: 0 }, { duration: 300 }); // Hide player money display in slots mode tween(playerMoneyDisplay, { alpha: 0 }, { duration: 300 }); // Hide Apuesta asset in slots mode tween(apuestaAsset, { alpha: 0 }, { duration: 300 }); // Update ways display // Hide chips and bet display tween(chipContainer, { alpha: 0 }, { duration: 300 }); // Hide chips and bet display tween(chipContainer, { alpha: 0 }, { duration: 300 }); waysDisplay.setText(megawaysSlotMachine.getWaysText()); cascadeDisplay.setText(''); } function clearTable() { // Remove all cards for (var i = 0; i < playerCards.length; i++) { playerCards[i].destroy(); } for (var i = 0; i < dealerCards.length; i++) { dealerCards[i].destroy(); } playerCards = []; dealerCards = []; } function showBetConfirmation(callback) { var betPercentage = currentBet / playerMoney * 100; // Create confirmation overlay var confirmationOverlay = LK.getAsset('warning', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); confirmationOverlay.x = 1024; confirmationOverlay.y = 1366; confirmationOverlay.alpha = 0; game.addChild(confirmationOverlay); var warningText = new Text2('β οΈ HIGH BET WARNING β οΈ', { size: 48, fill: '#FF0000', font: "'Arial Black', Arial, sans-serif" }); warningText.anchor.set(0.5, 0.5); warningText.x = 1024; warningText.y = 1200; warningText.alpha = 0; game.addChild(warningText); var percentageText = new Text2('You are betting ' + Math.round(betPercentage) + '% of your money!', { size: 36, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); percentageText.anchor.set(0.5, 0.5); percentageText.x = 1024; percentageText.y = 1300; percentageText.alpha = 0; game.addChild(percentageText); var confirmButton = new GameButton('CONFIRM BET', 200, 80); confirmButton.x = 824; confirmButton.y = 1450; confirmButton.alpha = 0; game.addChild(confirmButton); var cancelButton = new GameButton('CANCEL', 200, 80); cancelButton.x = 1224; cancelButton.y = 1450; cancelButton.alpha = 0; game.addChild(cancelButton); // Animate in tween(confirmationOverlay, { alpha: 0.9 }, { duration: 300 }); tween(warningText, { alpha: 1 }, { duration: 300, delay: 100 }); tween(percentageText, { alpha: 1 }, { duration: 300, delay: 200 }); tween(confirmButton, { alpha: 1 }, { duration: 300, delay: 300 }); tween(cancelButton, { alpha: 1 }, { duration: 300, delay: 300 }); function cleanup() { confirmationOverlay.destroy(); warningText.destroy(); percentageText.destroy(); confirmButton.destroy(); cancelButton.destroy(); } confirmButton.up = function () { confirmedHighBet = true; cleanup(); if (callback) callback(true); }; cancelButton.up = function () { cleanup(); if (callback) callback(false); }; } function startNewBlackjackHand() { if (playerMoney < currentBet) return; // Check for high bet confirmation (50% or more of money) if (!confirmedHighBet && currentBet >= playerMoney * 0.5) { showBetConfirmation(function (confirmed) { if (confirmed) { confirmedHighBet = true; achievementSystem.checkAchievement('bigSpender', currentBet); proceedWithDeal(); } else { // Reset bet to a safer amount currentBet = Math.min(currentBet, Math.floor(playerMoney * 0.25)); updateChipSelection(); } confirmedHighBet = false; }); return; } achievementSystem.checkAchievement('bigSpender', currentBet); proceedWithDeal(); } function proceedWithDeal() { // Set hand in progress flag to prevent deal button from reappearing handInProgress = true; // Reset blackjack flag for new hand isBlackjack = false; // Track blackjack statistics totalBlackjackHands++; storage.totalBlackjackHands = totalBlackjackHands; // Hide deal button immediately when pressed tween(dealButton, { alpha: 0 }, { duration: 200 }); // Hide Remove button when cards are dealt tween(removeAsset, { alpha: 0 }, { duration: 200 }); playerMoney -= currentBet; updateMoneyDisplay(); clearTable(); createDeck(); gameDeck.updateCount(52); gamePhase = 'dealing'; // Deal initial cards with animation sequence dealCard(false, function () { dealCard(true, function () { dealCard(false, function () { dealCard(true, function () { // Dealer's first card stays face down if (dealerCards.length > 0) { dealerCards[0].faceUp = true; dealerCards[0].flip(); } updateScoreDisplays(); finishDealingPhase(); }); }); }); }); function finishDealingPhase() { var playerScore = calculateHandValue(playerCards); if (playerScore === 21) { // Player got blackjack - play random blackjack voice var playerBlackjackSounds = ['Jugador_BlackJack_1', 'Jugador_BlackJack_2', 'Jugador_BlackJack_3']; var randomBlackjackSound = playerBlackjackSounds[Math.floor(Math.random() * playerBlackjackSounds.length)]; LK.getSound(randomBlackjackSound).play(); // Set flag to indicate blackjack (perfect 21) to prevent croupier win voice isBlackjack = true; endHand(); } else { gamePhase = 'playing'; // Show action buttons tween(hitButton, { alpha: 1 }, { duration: 300 }); tween(standButton, { alpha: 1 }, { duration: 300, onFinish: function onFinish() { // Ensure stand button is interactive when shown standButton.interactive = true; standButton.buttonMode = true; } }); if (playerMoney >= currentBet) { tween(doubleButton, { alpha: 1 }, { duration: 300 }); } else { // Keep double button hidden if insufficient funds doubleButton.alpha = 0; } // Hide deal button during hand tween(dealButton, { alpha: 0 }, { duration: 300 }); } } } function playerHit() { var targetX = 850 + playerCards.length * 280; // Update to match new player card position (800 + 50) var targetY = 2100; // Play random player voice when requesting a card var playerPedirSounds = ['Jugador_Pedir_1', 'Jugador_Pedir_2', 'Jugador_Pedir_3']; var randomPedirSound = playerPedirSounds[Math.floor(Math.random() * playerPedirSounds.length)]; LK.getSound(randomPedirSound).play(); // Play card dealing sound when player requests a card LK.getSound('Carta_1').play(); // Animate table tapping gesture first tween(playerAnimatedHand, { y: playerAnimatedHand.y + 50, scaleX: 1.1, scaleY: 1.1 }, { duration: 150, onFinish: function onFinish() { tween(playerAnimatedHand, { y: playerAnimatedHand.y - 50, scaleX: 1.0, scaleY: 1.0 }, { duration: 150, onFinish: function onFinish() { // Now just deal the card without additional animation dealCard(false, function () { updateScoreDisplays(); var playerScore = calculateHandValue(playerCards); if (playerScore > 21) { endHand(); } else if (playerScore === 21) { playerStand(); } }); } }); } }); // Hide double button after hit since it's no longer available doubleButton.alpha = 0; } function playerStand() { gamePhase = 'dealer'; // Play random player voice when standing var playerPlantarseSounds = ['Jugador_Plantarse_1', 'Jugador_Plantarse_2', 'Jugador_Plantarse_3']; var randomPlantarseSound = playerPlantarseSounds[Math.floor(Math.random() * playerPlantarseSounds.length)]; LK.getSound(randomPlantarseSound).play(); // Animate negation gesture (wave hand side to side) tween(playerAnimatedHand, { x: playerAnimatedHand.x - 30, rotation: -0.2 }, { duration: 200, onFinish: function onFinish() { tween(playerAnimatedHand, { x: playerAnimatedHand.x + 60, rotation: 0.2 }, { duration: 200, onFinish: function onFinish() { tween(playerAnimatedHand, { x: playerAnimatedHand.x - 30, rotation: 0 }, { duration: 200, onFinish: function onFinish() { // Continue with original stand gesture playerAnimatedHand.standGesture(); } }); } }); } }); // Hide action buttons tween(hitButton, { alpha: 0 }, { duration: 300 }); tween(standButton, { alpha: 0 }, { duration: 300 }); tween(doubleButton, { alpha: 0 }, { duration: 300 }); // Reveal dealer's face-down card with flip animation if (dealerCards.length > 0) { dealerAnimatedHand.flipCard(dealerCards[0].x, dealerCards[0].y, function () { dealerCards[0].flip(); updateScoreDisplays(); // Dealer plays LK.setTimeout(function () { playDealerTurn(); }, 1000); }); } else { updateScoreDisplays(); // Dealer plays LK.setTimeout(function () { playDealerTurn(); }, 1000); } } function playerDouble() { if (playerMoney < currentBet) return; playerMoney -= currentBet; currentBet *= 2; updateMoneyDisplay(); var targetX = 850 + playerCards.length * 280; // Update to match new player card position (800 + 50) var targetY = 2100; // Animate two fingers gesture first tween(playerAnimatedHand, { scaleX: 1.2, scaleY: 1.2, rotation: 0.1 }, { duration: 300, onFinish: function onFinish() { tween(playerAnimatedHand, { scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 300, onFinish: function onFinish() { // Now animate double down gesture with chips and card playerAnimatedHand.doubleDownGesture(targetX, targetY, function () { dealCard(false, function () { updateScoreDisplays(); var playerScore = calculateHandValue(playerCards); if (playerScore > 21) { endHand(); } else { playerStand(); } }); }); } }); } }); } function playDealerTurn() { var dealerScore = calculateHandValue(dealerCards); if (dealerScore < 17) { dealCard(true, function () { updateScoreDisplays(); LK.setTimeout(function () { playDealerTurn(); }, 1000); }); } else { endHand(); } } function endHand() { gamePhase = 'finished'; var playerScore = calculateHandValue(playerCards); var dealerScore = calculateHandValue(dealerCards); var winnings = 0; var playerWon = false; // Arrays for random voice selection var cuprierWinSounds = ['Cuprier_Win_1', 'Cuprier_Win_2', 'Cuprier_Win_3']; if (playerScore > 21) { // Player busts - play random bust voice var playerPasaSounds = ['Jugador_Pasa_1', 'Jugador_Pasa_2', 'Jugador_Pasa_3']; var randomPasaSound = playerPasaSounds[Math.floor(Math.random() * playerPasaSounds.length)]; LK.getSound(randomPasaSound).play(); consecutiveWins = 0; } else if (dealerScore > 21) { winnings = currentBet * 2; playerWon = true; } else if (playerScore > dealerScore) { winnings = currentBet * 2; playerWon = true; } else if (playerScore < dealerScore) { // Dealer wins - play random croupier win voice (dealer wins without player bust) var randomCuprierWinSound = cuprierWinSounds[Math.floor(Math.random() * cuprierWinSounds.length)]; LK.getSound(randomCuprierWinSound).play(); consecutiveWins = 0; } else { // Tie game - play random croupier tie voice var cuprierEmpateSounds = ['Cuprier_Empate_1', 'Cuprier_Empate_2', 'Cuprier_Empate_3']; var randomEmpateSound = cuprierEmpateSounds[Math.floor(Math.random() * cuprierEmpateSounds.length)]; LK.getSound(randomEmpateSound).play(); winnings = currentBet; playerWon = true; } if (playerWon) { consecutiveWins++; totalBlackjackWins++; storage.totalBlackjackWins = totalBlackjackWins; // Track longest win streak if (consecutiveWins > longestWinStreak) { longestWinStreak = consecutiveWins; storage.longestWinStreak = longestWinStreak; } achievementSystem.checkAchievement('firstBlackjackWin', true); achievementSystem.checkAchievement('luckyStreak', consecutiveWins); storage.consecutiveWins = consecutiveWins; // Play random croupier win voice when player wins (but not on ties or blackjack) if (winnings > currentBet && !isBlackjack) { // Only play win sound if player actually won (not tie) and it's not a blackjack var cuprierGanaSounds = ['Cuprier_Gana_1', 'Cuprier_Gana_2', 'Cuprier_Gana_3']; var randomGanaSound = cuprierGanaSounds[Math.floor(Math.random() * cuprierGanaSounds.length)]; LK.getSound(randomGanaSound).play(); } } if (winnings > 0) { playerMoney += winnings; var netWin = winnings - currentBet; if (netWin > 0) { totalMoneyWon += netWin; storage.totalMoneyWon = totalMoneyWon; if (netWin > biggestWin) { biggestWin = netWin; storage.biggestWin = biggestWin; } } LK.getSound('coinWin').play(); createCoinAnimation(1024, 1366); } else { // Player lost the bet totalMoneyLost += currentBet; storage.totalMoneyLost = totalMoneyLost; } currentBet = 0; updateMoneyDisplay(); // Collect cards animation after 2 seconds LK.setTimeout(function () { var cardPositions = []; var allCards = []; // Collect player cards positions for (var i = 0; i < playerCards.length; i++) { cardPositions.push({ x: playerCards[i].x, y: playerCards[i].y }); allCards.push(playerCards[i]); } // Collect dealer cards positions for (var i = 0; i < dealerCards.length; i++) { cardPositions.push({ x: dealerCards[i].x, y: dealerCards[i].y }); allCards.push(dealerCards[i]); } // Animate collecting cards dealerAnimatedHand.collectCards(cardPositions, allCards, function () { // Clear actual cards from game after collection animation clearTable(); // Shuffle animation dealerAnimatedHand.shuffleAnimation(); }); }, 1500); // Reset game phase after dealing sequence LK.setTimeout(function () { gamePhase = 'betting'; handInProgress = false; // Reset hand in progress flag // Re-enable deal button only if still in blackjack mode and bet is greater than zero if (gameMode === 'blackjack' && currentBet > 0) { tween(dealButton, { alpha: 1 }, { duration: 300 }); } }, 2000); } function spinSlots() { // Track slots statistics totalSlotsSpins++; storage.totalSlotsSpins = totalSlotsSpins; // Debug logging to identify the exact issue console.log('spinSlots called - playerMoney:', playerMoney, 'currentBet:', currentBet, 'isSpinning:', megawaysSlotMachine.isSpinning); // Reset bet to 25 immediately if current bet exceeds player money if (currentBet > playerMoney) { currentBet = 25; totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); console.log('Bet reset to 25 - new currentBet:', currentBet); } // Check if using free spins or player money var usingFreeSpin = freeSpins > 0; if (!usingFreeSpin && playerMoney < currentBet) { console.log('Insufficient funds - playerMoney:', playerMoney, 'currentBet:', currentBet); return; } if (megawaysSlotMachine.isSpinning) { console.log('Already spinning - isSpinning:', megawaysSlotMachine.isSpinning); return; } // Set slots spin in progress flag slotsSpinInProgress = true; // Reset money difference values to 0 at start of new spin moneyAfterBet = 0; moneyAfterSpin = 0; updateMoneyDifferenceDisplay(); // Deduct cost - either free spin or player money if (usingFreeSpin) { freeSpins--; storage.freeSpins = freeSpins; moneyAfterBet = playerMoney; // No money deducted for free spins // Set effective bet to 100 for free spins calculations currentBet = 100; } else { playerMoney -= currentBet; moneyAfterBet = playerMoney; // Track money after betting } moneyAfterSpin = moneyAfterBet; // Keep at same value until spin results are processed updateMoneyDisplay(); // Update display based on remaining free spins if (freeSpins > 0) { totalBetDisplay.setText('FREE'); // Update total bet display for slots } else { totalBetDisplay.setText('$' + currentBet); // Update total bet display for slots } spinButton.setEnabled(false); messageDisplay.setText('Spinning...'); // Hide cascade display cascadeDisplay.alpha = 0; megawaysSlotMachine.totalWinAmount = 0; megawaysSlotMachine.cascadeCount = 0; lastCascadeCount = 0; // Animate spin button tween(spinButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(spinButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); LK.getSound('slotSpin').play(); // Start Megaways spin megawaysSlotMachine.spinAllReels(function () { // Show ways animation if significantly increased showWaysAnimation(megawaysSlotMachine.currentWays); // Check for wins and start cascade sequence var winningCombos = megawaysSlotMachine.checkForWins(); if (winningCombos.length > 0) { messageDisplay.setText('WINNING SPIN!'); processInitialWins(winningCombos); } else { messageDisplay.setText('No win. Try again!'); console.log('No wins - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabling button:', playerMoney >= currentBet || freeSpins > 0); spinButton.setEnabled(playerMoney >= currentBet || freeSpins > 0); // Update button text based on free spins availability if (freeSpins > 0) { totalBetDisplay.setText('FREE'); spinButton.setText('SPIN FREE'); } else { // Reset bet to 25 if current bet exceeds player money after spin if (currentBet > playerMoney) { currentBet = 25; } totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); } // Clear slots spin in progress flag when no wins slotsSpinInProgress = false; } }); } function processInitialWins(winningCombinations) { megawaysSlotMachine.processWins(winningCombinations, function (winAmount) { if (winAmount > 0) { // Show cascade animation when significantly increased showCascadeAnimation(megawaysSlotMachine.cascadeCount); // Check cascade achievement achievementSystem.checkAchievement('cascade5x', megawaysSlotMachine.cascadeCount); // Track max cascades achieved if (megawaysSlotMachine.cascadeCount > maxCascades) { maxCascades = megawaysSlotMachine.cascadeCount; storage.maxCascades = maxCascades; } // Add winnings to player money playerMoney += winAmount; moneyAfterSpin = playerMoney; // Track money after spin results // Track slots wins if (winAmount > 0) { totalMoneyWon += winAmount; storage.totalMoneyWon = totalMoneyWon; if (winAmount > biggestWin) { biggestWin = winAmount; storage.biggestWin = biggestWin; } } else { // Player lost the bet var betLost = usingFreeSpin ? 0 : currentBet; if (betLost > 0) { totalMoneyLost += betLost; storage.totalMoneyLost = totalMoneyLost; } } updateMoneyDisplay(); // Play win sound and create coin animation LK.getSound('coinWin').play(); createCoinAnimation(1024, 1366); } // Re-enable spin button after all cascades complete LK.setTimeout(function () { // Update displays based on free spins availability if (freeSpins > 0) { totalBetDisplay.setText('FREE'); spinButton.setText('SPIN FREE'); } else { // Reset bet to 25 if current bet exceeds player money after all cascades if (currentBet > playerMoney) { currentBet = 25; } totalBetDisplay.setText('$' + currentBet); spinButton.setText('SPIN $' + currentBet); } console.log('After cascades - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabling button:', playerMoney >= currentBet || freeSpins > 0); spinButton.setEnabled(playerMoney >= currentBet || freeSpins > 0); // Clear slots spin in progress flag when all cascades complete slotsSpinInProgress = false; if (megawaysSlotMachine.totalWinAmount > 0) { if (megawaysSlotMachine.totalWinAmount >= 1000) { messageDisplay.setText('π MEGA WIN! $' + megawaysSlotMachine.totalWinAmount + ' π'); } else if (megawaysSlotMachine.totalWinAmount >= 500) { messageDisplay.setText('π° BIG WIN! $' + megawaysSlotMachine.totalWinAmount + ' π°'); } else { messageDisplay.setText('β¨ WIN! $' + megawaysSlotMachine.totalWinAmount + ' β¨'); } } else { messageDisplay.setText(''); } }, 1000); }); } function checkSlotWin(s1, s2, s3) { var symbols = ['cherry', 'lemon', 'grape', 'seven', 'bell', 'diamond', 'bar', 'dollar']; var symbolNames = ['π', 'π', 'π', '7', 'π', 'π', 'BAR', '$']; var winnings = 0; var isWin = false; // Check for wins if (s1 === s2 && s2 === s3) { // Three of a kind isWin = true; if (symbols[s1] === 'seven') { winnings = 500; messageDisplay.setText('π° JACKPOT! Triple 7s! π°'); } else if (symbols[s1] === 'dollar') { winnings = 300; messageDisplay.setText('π° Big Win! Triple $$$ π°'); } else if (symbols[s1] === 'diamond') { winnings = 250; messageDisplay.setText('π Diamond Jackpot! π'); } else if (symbols[s1] === 'bell') { winnings = 200; messageDisplay.setText('π Triple Bells! π'); } else { winnings = 100; messageDisplay.setText('π Three of a kind! π'); } } else if (s1 === s2 || s2 === s3 || s1 === s3) { // Pair isWin = true; winnings = 50; messageDisplay.setText('β¨ Pair! Small win! β¨'); } else { messageDisplay.setText('No win. Try again!'); } if (isWin) { // Flash message display tween(messageDisplay, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, onFinish: function onFinish() { tween(messageDisplay, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); } if (winnings > 0) { playerMoney += winnings; LK.getSound('coinWin').play(); createCoinAnimation(1024, 1366); updateMoneyDisplay(); } } function showWaysAnimation(currentWays) { // Only show animation if ways increased significantly (by at least 10,000) if (currentWays > lastWaysCount + 10000) { // Destroy existing animation if any if (waysAnimationDisplay) { waysAnimationDisplay.destroy(); waysAnimationDisplay = null; } // Create animated ways display waysAnimationDisplay = new Text2(currentWays + ' WAYS!', { size: 72, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); waysAnimationDisplay.anchor.set(0.5, 0.5); waysAnimationDisplay.x = 1024; waysAnimationDisplay.y = 900; waysAnimationDisplay.alpha = 0; waysAnimationDisplay.scaleX = 0.5; waysAnimationDisplay.scaleY = 0.5; game.addChild(waysAnimationDisplay); // Animate popup entrance tween(waysAnimationDisplay, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { // Hold for 1 second LK.setTimeout(function () { // Animate fadeout tween(waysAnimationDisplay, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, onFinish: function onFinish() { if (waysAnimationDisplay) { waysAnimationDisplay.destroy(); waysAnimationDisplay = null; } } }); }, 1000); } }); } lastWaysCount = currentWays; } function showCascadeAnimation(currentCascadeCount) { // Only show animation if cascade count increased AND is 5 or higher if (currentCascadeCount > lastCascadeCount && currentCascadeCount >= 5) { // Play Cascada sound when cascade reaches x5 or higher LK.getSound('Cascada').play(); // Destroy existing cascade animation if any if (cascadeAnimationDisplay) { cascadeAnimationDisplay.destroy(); cascadeAnimationDisplay = null; } // Create animated cascade display cascadeAnimationDisplay = new Text2('CASCADE x' + currentCascadeCount + '!', { size: 168, fill: '#FF6347', font: "'Arial Black', Arial, sans-serif" }); cascadeAnimationDisplay.anchor.set(0.5, 0.5); cascadeAnimationDisplay.x = 1024; cascadeAnimationDisplay.y = 800; cascadeAnimationDisplay.alpha = 0; cascadeAnimationDisplay.scaleX = 0.5; cascadeAnimationDisplay.scaleY = 0.5; game.addChild(cascadeAnimationDisplay); // Animate popup entrance tween(cascadeAnimationDisplay, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { // Hold for 1 second LK.setTimeout(function () { // Animate fadeout tween(cascadeAnimationDisplay, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, onFinish: function onFinish() { if (cascadeAnimationDisplay) { cascadeAnimationDisplay.destroy(); cascadeAnimationDisplay = null; } } }); }, 1000); } }); } lastCascadeCount = currentCascadeCount; } function createCoinAnimation(x, y) { for (var i = 0; i < 5; i++) { var coin = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); coin.x = x + (Math.random() - 0.5) * 200; coin.y = y + (Math.random() - 0.5) * 200; game.addChild(coin); tween(coin, { y: coin.y - 100, alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 1000, onFinish: function onFinish() { coin.destroy(); } }); } } function createConfettiCelebration() { var confettiAssets = ['confetti1', 'confetti2', 'confetti3', 'confetti4', 'confetti5', 'confetti6']; // Create 50 confetti pieces for spectacular effect for (var i = 0; i < 50; i++) { var confettiType = confettiAssets[Math.floor(Math.random() * confettiAssets.length)]; var confetti = LK.getAsset(confettiType, { anchorX: 0.5, anchorY: 0.5 }); // Start confetti at top of screen with random horizontal positions confetti.x = Math.random() * 2048; confetti.y = -50; confetti.rotation = Math.random() * Math.PI * 2; game.addChild(confetti); // Animate confetti falling with random movement tween(confetti, { x: confetti.x + (Math.random() - 0.5) * 400, y: 2732 + 100, rotation: confetti.rotation + (Math.random() - 0.5) * Math.PI * 4, alpha: 0 }, { duration: 3000 + Math.random() * 2000, easing: tween.easeIn, onFinish: function onFinish() { confetti.destroy(); } }); } } // Card display removed from menu // Track if this is the first time entering the menu var isFirstMenuEntry = true; // Initialize game state updateMoneyDisplay(); // Add global click handler for disclaimer screen game.down = function (x, y, obj) { if (gameMode === 'disclaimer') { switchToMenu(); } }; // Initialize wheel cooldown system if (wheelLastUsed === 0) { // First time playing, allow immediate wheel use wheelLastUsed = Date.now() - WHEEL_COOLDOWN_TIME; storage.wheelLastUsed = wheelLastUsed; } // Start with disclaimer screen if (gameMode === 'disclaimer') { // Hide all menu elements initially blackjackButton.alpha = 0; slotsButton.alpha = 0; welcomeAsset.alpha = 0; fondoM.alpha = 0; logrosButton.alpha = 0; ruedaPButton.alpha = 0; spinIButton.alpha = 0; wheelTimerDisplay.alpha = 0; // Disable buttons during disclaimer screen blackjackButton.setEnabled(false); slotsButton.setEnabled(false); logrosButton.setEnabled(false); ruedaPButton.setEnabled(false); spinIButton.setEnabled(false); } else { switchToMenu(); } // Menu music will be played when entering main menu via switchToMenu function game.update = function () { updateMoneyDisplay(); }; // Wheel prize definitions var wheelPrizes = [{ type: 'credits', amount: 200, name: '+200 Credits', probability: 40, color: 0x4CAF50 }, { type: 'credits', amount: 500, name: '+500 Credits', probability: 25, color: 0x2196F3 }, { type: 'credits', amount: 1000, name: '+1,000 Credits', probability: 10, color: 0x9C27B0 }, { type: 'credits', amount: 2500, name: '+2,500 Credits', probability: 5, color: 0xFF5722 }, { type: 'freespins', amount: 3, name: '+3 Free Spins', probability: 10, color: 0xFFC107 }, { type: 'freespins', amount: 10, name: '+10 Free Spins', probability: 5, color: 0xE91E63 }, { type: 'blackjackchips', amount: 250, name: '+250 chips', probability: 4, color: 0x795548 }, { type: 'credits', amount: 10000, name: 'JACKPOT', probability: 1, color: 0xFFD700 }]; // Wheel cooldown system - 12 hours (43200000 milliseconds) var WHEEL_COOLDOWN_TIME = 43200000; // 12 hours in milliseconds var wheelLastUsed = storage.wheelLastUsed || 0; var wheelCooldownTimer = null; // Wheel spinning state variables var wheelIsSpinning = false; var preSelectedPrize = null; var wheelContainer = null; var ruedaVerificador = null; var wheelSegments = []; var targetCheckInterval = null; var wheelSpinButton = null; var giroSoundInterval = null; // Track Giro sound interval var slotsSpinInProgress = false; // Track if slots spin is active function showWheelScreen() { // Set wheel screen as open to prevent re-entry wheelScreenOpen = true; // Disable blackjack and slots buttons when wheel opens blackjackButton.setEnabled(false); slotsButton.setEnabled(false); // Create dark overlay background var wheelOverlay = LK.getAsset('warning', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95 }); wheelOverlay.x = 1024; wheelOverlay.y = 1366; wheelOverlay.alpha = 0; game.addChild(wheelOverlay); // Create title var wheelTitle = new Text2('π‘ FORTUNE WHEEL π‘', { size: 72, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); wheelTitle.anchor.set(0.5, 0.5); wheelTitle.x = 1024; wheelTitle.y = 400; wheelTitle.alpha = 0; game.addChild(wheelTitle); // Create wheel container wheelContainer = new Container(); wheelContainer.x = 1024; wheelContainer.y = 1000; wheelContainer.alpha = 0; game.addChild(wheelContainer); // Create wheel base var wheelBase = LK.getAsset('circularSpinButtonShadow', { anchorX: 0.5, anchorY: 0.5, width: 1800, height: 1836 }); wheelContainer.addChild(wheelBase); // Create wheel pointer using Flecha asset outside the wheel container so it doesn't rotate var wheelPointer = LK.getAsset('Flecha', { anchorX: 0.5, anchorY: 1.0 }); wheelPointer.x = 1024; // Position at center of screen wheelPointer.y = 250; // 750 pixels above wheel center (1000 - 750) wheelPointer.alpha = 0; game.addChild(wheelPointer); // Add to game instead of wheelContainer // Create RuedaVerificador asset at same position as Flecha ruedaVerificador = LK.getAsset('RuedaVerificador', { anchorX: 0.5, anchorY: 1.0 }); ruedaVerificador.x = 1024; // Same position as wheelPointer ruedaVerificador.y = 450; // Moved down 200 pixels from wheelPointer position ruedaVerificador.alpha = 0; game.addChild(ruedaVerificador); // Create wheel segments var segmentAngle = Math.PI * 2 / wheelPrizes.length; wheelSegments = []; for (var i = 0; i < wheelPrizes.length; i++) { var angle = i * segmentAngle; var radius = 600; // Add prize text (horizontal - make invisible) var fontSize = 60; // Adjust font size for specific prizes if (wheelPrizes[i].name === '+3 Free Spins') { fontSize = 60 * 1.03; // Make 1.03 times larger } else if (wheelPrizes[i].name === '+10 Free Spins') { fontSize = 60 / 1.05; // Make 1.05 times smaller } else if (wheelPrizes[i].name === '+1,000 Credits') { fontSize = 60 / 1.15; // Make 1.15 times smaller } else if (wheelPrizes[i].name === '+2,500 Credits') { fontSize = 60 / 1.15; // Make 1.15 times smaller } else if (wheelPrizes[i].name === '+250 chips') { fontSize = 60 * 1.2; // Make 1.2 times larger } else if (wheelPrizes[i].name === 'JACKPOT') { fontSize = 60 * 1.15; // Make 1.15 times larger } var prizeText = new Text2(wheelPrizes[i].name, { size: fontSize, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); prizeText.anchor.set(0.5, 0.5); prizeText.x = Math.cos(angle) * radius; prizeText.y = Math.sin(angle) * radius; prizeText.rotation = angle + Math.PI / 2; prizeText.alpha = 0; // Make horizontal text invisible wheelContainer.addChild(prizeText); wheelSegments.push(prizeText); // Add vertical prize text var verticalPrizeText = new Text2(wheelPrizes[i].name, { size: fontSize, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); verticalPrizeText.anchor.set(0.5, 0.5); verticalPrizeText.x = Math.cos(angle) * radius; verticalPrizeText.y = Math.sin(angle) * radius; verticalPrizeText.rotation = angle + Math.PI / 2 + Math.PI / 2; // Add 90 degrees for vertical orientation wheelContainer.addChild(verticalPrizeText); } // Create spin button wheelSpinButton = new GameButton('SPIN WHEEL', 300, 100); wheelSpinButton.x = 1024; wheelSpinButton.y = 1000; // Moved to center of wheel asset wheelSpinButton.alpha = 0; // Replace the default button background with circular assets (500x500) wheelSpinButton.removeChild(wheelSpinButton.children[0]); // Remove shadow wheelSpinButton.removeChild(wheelSpinButton.children[0]); // Remove background (index shifts after first removal) // Add circular border var circularBorder = LK.getAsset('circularSpinButtonBorder', { anchorX: 0.5, anchorY: 0.5, width: 500, height: 500 }); wheelSpinButton.addChildAt(circularBorder, 0); // Add circular button var circularButton = LK.getAsset('circularSpinButton', { anchorX: 0.5, anchorY: 0.5, width: 450, height: 295 }); wheelSpinButton.addChildAt(circularButton, 1); game.addChild(wheelSpinButton); // Move SpinI button to overlapping position above the wheel (only if it exists) if (spinIButton && spinIAsset) { tween(spinIButton, { x: wheelSpinButton.x - 400, // Position 400 pixels to the left of wheel center for overlap (320 + 80) y: wheelSpinButton.y - 100 // Position above the wheel spin button to overlay on wheel }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Ensure SpinI renders above wheel by removing and re-adding to game game.removeChild(spinIButton); game.addChild(spinIButton); } }); } // Create close button var wheelCloseButton = new GameButton('CLOSE', 200, 80); wheelCloseButton.x = 1024; wheelCloseButton.y = 2000; wheelCloseButton.alpha = 0; game.addChild(wheelCloseButton); // Animate in tween(wheelOverlay, { alpha: 0.95 }, { duration: 300 }); tween(wheelTitle, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 400, delay: 100, easing: tween.bounceOut, onFinish: function onFinish() { tween(wheelTitle, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); tween(wheelContainer, { alpha: 1 }, { duration: 400, delay: 200 }); tween(wheelPointer, { alpha: 1 }, { duration: 400, delay: 250 }); ruedaVerificador.alpha = 0; tween(wheelSpinButton, { alpha: 0 }, { duration: 300, delay: 400 }); tween(wheelCloseButton, { alpha: 1 }, { duration: 300, delay: 500 }); // Spin wheel handler wheelSpinButton.up = function () { if (!wheelSpinButton.enabled) return; if (wheelIsSpinning) return; wheelSpinButton.setEnabled(false); wheelIsSpinning = true; // Track wheel statistics totalWheelSpins++; storage.totalWheelSpins = totalWheelSpins; // Stop any currently playing music and start RuedaMusic when wheel begins spinning LK.stopMusic(); LK.playMusic('RuedaMusic'); // Hide SpinI asset when wheel is spun and stop all blinking tween.stop(spinIAsset, { alpha: true }); // Stop any ongoing alpha tween spinIAsset.alpha = 0; // Set to fully transparent tween(spinIButton, { alpha: 0 }, { duration: 300, easing: tween.easeOut }); // Clear SpinI timers when player spins wheel if (spinITimer) { LK.clearTimeout(spinITimer); spinITimer = null; } if (spinIBlinkTimer) { LK.clearInterval(spinIBlinkTimer); spinIBlinkTimer = null; } if (spinIRecurringTimer) { LK.clearInterval(spinIRecurringTimer); spinIRecurringTimer = null; } // Disable SpinI asset verificador functionality after wheel spin spinIButton.setEnabled(false); spinIAsset.interactive = false; spinIAsset.buttonMode = false; // Immediately calculate which prize to award preSelectedPrize = selectRandomPrize(); console.log('Pre-selected prize:', preSelectedPrize.prize.name, 'at index:', preSelectedPrize.index); // Start spinning the wheel immediately var continuousSpinRotation = wheelContainer.rotation + Math.PI * 2 * 10; // Spin 10 full rotations over 5 seconds // Start Giro sound interval - play every 1 second during spin var giroSoundInterval = LK.setInterval(function () { if (wheelIsSpinning) { LK.getSound('Giro').play(); } }, 1000); // Play first Giro sound immediately LK.getSound('Giro').play(); // Phase 1: Spin continuously for 5 seconds tween(wheelContainer, { rotation: continuousSpinRotation }, { duration: 5000, easing: tween.linear }); // Phase 2: After 5 seconds, start target detection and transition to target LK.setTimeout(function () { // Check if wheel is still open and spinning before proceeding if (!wheelIsSpinning || !wheelContainer) return; // Continue Giro sound interval during final phase (already playing every 1 second) // Calculate target rotation to align pre-selected prize with RuedaVerificador var segmentAngle = Math.PI * 2 / wheelPrizes.length; var targetAngle = preSelectedPrize.index * segmentAngle; // Stop current spin and calculate final rotation tween.stop(wheelContainer, { rotation: true }); // Add additional rotations to reach target smoothly var currentRotation = wheelContainer.rotation; var finalRotation = currentRotation + Math.PI * 2 * 2 + targetAngle; // Add 2 more full spins to target console.log('Transitioning to target prize. Final rotation:', finalRotation * 180 / Math.PI, 'degrees'); // Start monitoring for collision during final approach startTargetDetection(); // Animate wheel to target position with deceleration tween(wheelContainer, { rotation: finalRotation }, { duration: 3000, easing: tween.easeOut }); }, 5000); }; // Close handler function closeWheelScreen() { // Prevent closing wheel if spin is in progress if (wheelIsSpinning) return; // Make close button disappear immediately wheelCloseButton.alpha = 0; // Reset wheel screen state to allow re-entry wheelScreenOpen = false; // Re-enable blackjack and slots buttons when wheel closes blackjackButton.setEnabled(true); slotsButton.setEnabled(true); // Move SpinI button back to original position with 50px left offset and restore visibility tween(spinIButton, { x: 1488 - 50, // Original position minus 50 pixels to the left y: 2500, // Original vertical position alpha: 1 // Restore visibility when returning to original position }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Reset sound toggle when returning from wheel spinISoundToggle = false; } }); // Clear any ongoing wheel detection if (targetCheckInterval) { LK.clearInterval(targetCheckInterval); targetCheckInterval = null; } // Clear Giro sound interval when closing wheel if (giroSoundInterval) { LK.clearInterval(giroSoundInterval); giroSoundInterval = null; } // Reset wheel variables wheelIsSpinning = false; preSelectedPrize = null; // Store references before nullifying var elementsToDestroy = []; if (wheelContainer) elementsToDestroy.push(wheelContainer); if (ruedaVerificador) elementsToDestroy.push(ruedaVerificador); if (wheelSpinButton) elementsToDestroy.push(wheelSpinButton); // Find and destroy all wheel-related elements by checking all game children var gameChildren = game.children.slice(); // Create a copy to avoid modification during iteration for (var i = 0; i < gameChildren.length; i++) { var child = gameChildren[i]; // Check if this is a wheel-related element by examining its properties or position // Exclude fondoM background by checking if it's the main menu background if (child && child !== fondoM && (child.x === 1024 && child.y === 1366 && child.width && child.height || // wheelOverlay (exclude fondoM) child.x === 1024 && child.y === 400 && child.setText || // wheelTitle child.x === 1024 && child.y === 250 || // wheelPointer child.x === 1024 && child.y === 450 || // ruedaVerificador child.x === 1024 && child.y === 1600 && child.setText || // wheelSpinButton child.x === 1024 && child.y === 2000 && child.setText || // wheelCloseButton (updated position) child.x === 1024 && child.y === 1000 || // wheelContainer child.x === 1024 && child.y === 1400 && child.setText // resultText )) { elementsToDestroy.push(child); } } // Immediately hide and destroy all elements for (var i = 0; i < elementsToDestroy.length; i++) { var element = elementsToDestroy[i]; if (element) { element.alpha = 0; if (element.destroy) { element.destroy(); } } } // Reset wheel variables to null wheelContainer = null; ruedaVerificador = null; wheelSegments = []; wheelSpinButton = null; } wheelCloseButton.up = closeWheelScreen; } function selectRandomPrize() { // Select a random prize for initial spin calculation (still used for rotation) var random = Math.random() * 100; var cumulativeProbability = 0; var selectedPrizeIndex = 0; for (var i = 0; i < wheelPrizes.length; i++) { cumulativeProbability += wheelPrizes[i].probability; if (random <= cumulativeProbability) { selectedPrizeIndex = i; break; } } return { prize: wheelPrizes[selectedPrizeIndex], index: selectedPrizeIndex }; } function startTargetDetection() { // Clear any existing interval if (targetCheckInterval) { LK.clearInterval(targetCheckInterval); targetCheckInterval = null; } // Check every 50ms during spin for collision with target prize targetCheckInterval = LK.setInterval(function () { if (!wheelIsSpinning || !preSelectedPrize) return; // Check if RuedaVerificador intersects with the target prize text var targetSegment = wheelSegments[preSelectedPrize.index]; if (targetSegment && ruedaVerificador) { // Get global positions for collision detection var segmentGlobalPos = wheelContainer.toGlobal(targetSegment.position); var verificadorGlobalPos = game.toGlobal(ruedaVerificador.position); // Check distance between centers (simple collision detection) var distance = Math.sqrt(Math.pow(segmentGlobalPos.x - verificadorGlobalPos.x, 2) + Math.pow(segmentGlobalPos.y - verificadorGlobalPos.y, 2)); // If close enough (within 100 pixels), consider it a hit if (distance < 100) { console.log('Target prize detected under RuedaVerificador! Stopping wheel.'); stopWheelAtTarget(); } } }, 50); } function stopWheelAtTarget() { // Stop all wheel animations immediately tween.stop(wheelContainer, { rotation: true }); // Stop Giro sound interval when wheel stops if (giroSoundInterval) { LK.clearInterval(giroSoundInterval); giroSoundInterval = null; } // Stop RuedaMusic when wheel stops and restart menu music LK.stopMusic(); LK.setTimeout(function () { LK.playMusic('Menu'); }, 100); // Clear the detection interval if (targetCheckInterval) { LK.clearInterval(targetCheckInterval); targetCheckInterval = null; } // Award the pre-selected prize console.log('Awarding pre-selected prize:', preSelectedPrize.prize.name); awardWheelPrize(preSelectedPrize.prize); // Play premio sound when prize is won LK.getSound('premio').play(); // Create confetti celebration effect createConfettiCelebration(); // Show result with "You won:" on first line and prize on second line var youWonText = new Text2('You won:', { size: 192, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); youWonText.anchor.set(0.5, 0.5); youWonText.x = 1024; youWonText.y = 1300; youWonText.alpha = 0; game.addChild(youWonText); var prizeText = new Text2(preSelectedPrize.prize.name, { size: 192, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); prizeText.anchor.set(0.5, 0.5); prizeText.x = 1024; prizeText.y = 1500; prizeText.alpha = 0; game.addChild(prizeText); tween(youWonText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.bounceOut }); tween(prizeText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, delay: 200, easing: tween.bounceOut, onFinish: function onFinish() { LK.setTimeout(function () { tween(youWonText, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { youWonText.destroy(); } }); tween(prizeText, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { prizeText.destroy(); } }); }, 2000); } }); // Reset wheel state wheelIsSpinning = false; preSelectedPrize = null; // Re-enable spin button if it exists and wheel screen is still open if (wheelSpinButton && wheelSpinButton.setEnabled) { wheelSpinButton.setEnabled(true); } } function detectPrizeUnderVerificador(wheelContainer, ruedaVerificador, wheelSegments) { // Find which text segment intersects with RuedaVerificador using actual collision detection var closestSegment = null; var minDistance = Infinity; var winningIndex = 0; for (var i = 0; i < wheelSegments.length; i++) { var segment = wheelSegments[i]; // Check if the text segment intersects with RuedaVerificador if (segment.intersects && segment.intersects(ruedaVerificador)) { // Direct collision detected - this is our winner return { prize: wheelPrizes[i], index: i }; } // Fallback: calculate distance to RuedaVerificador as backup var segmentGlobalPos = wheelContainer.toGlobal(segment.position); var verificadorGlobalPos = ruedaVerificador.position; var distance = Math.sqrt(Math.pow(segmentGlobalPos.x - verificadorGlobalPos.x, 2) + Math.pow(segmentGlobalPos.y - verificadorGlobalPos.y, 2)); if (distance < minDistance) { minDistance = distance; closestSegment = i; winningIndex = i; } } // If no direct collision found, use closest segment return { prize: wheelPrizes[winningIndex], index: winningIndex }; } function awardWheelPrize(prize) { // Play Congratulations sound for any prize win LK.getSound('Congratulations').play(); switch (prize.type) { case 'credits': playerMoney += prize.amount; updateMoneyDisplay(); LK.getSound('coinWin').play(); createCoinAnimation(1024, 1366); break; case 'freespins': freeSpins += prize.amount; storage.freeSpins = freeSpins; console.log('Awarded ' + prize.amount + ' free spins - total:', freeSpins); break; case 'blackjackchips': playerMoney += prize.amount; updateMoneyDisplay(); LK.getSound('coinWin').play(); createCoinAnimation(1024, 1366); break; } // Set wheel last used time and save to storage wheelLastUsed = Date.now(); storage.wheelLastUsed = wheelLastUsed; } // Check if wheel is available (not on cooldown) function isWheelAvailable() { var currentTime = Date.now(); var timeSinceLastUse = currentTime - wheelLastUsed; return timeSinceLastUse >= WHEEL_COOLDOWN_TIME; } // Get remaining cooldown time in milliseconds function getRemainingCooldownTime() { var currentTime = Date.now(); var timeSinceLastUse = currentTime - wheelLastUsed; return Math.max(0, WHEEL_COOLDOWN_TIME - timeSinceLastUse); } // Format time in hours:minutes:seconds function formatTime(milliseconds) { var totalSeconds = Math.floor(milliseconds / 1000); var hours = Math.floor(totalSeconds / 3600); var minutes = Math.floor(totalSeconds % 3600 / 60); var seconds = totalSeconds % 60; return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0'); } // Update wheel timer display function updateWheelTimer() { if (!wheelTimerDisplay) return; if (isWheelAvailable()) { wheelTimerDisplay.setText('READY!'); wheelTimerDisplay.fill = '#00FF00'; // Green when ready // Remove disabled effect from wheel icon when ready if (ruedaPAsset) { tween(ruedaPAsset, { alpha: 1.0, tint: 0xFFFFFF }, { duration: 300 }); } // Reactivate SpinI when wheel is available if (spinIAsset && gameMode === 'menu') { spinIAsset.alpha = 1; } } else { var remainingTime = getRemainingCooldownTime(); wheelTimerDisplay.setText(formatTime(remainingTime)); wheelTimerDisplay.fill = '#FF6B6B'; // Red when on cooldown // Add disabled effect to wheel icon when on cooldown if (ruedaPAsset) { tween(ruedaPAsset, { alpha: 0.5, tint: 0x808080 }, { duration: 300 }); } // Deactivate SpinI when wheel is on cooldown if (spinIAsset) { spinIAsset.alpha = 0; } } } // Start wheel cooldown timer function startWheelCooldownTimer() { // Clear existing timer if any if (wheelCooldownTimer) { LK.clearInterval(wheelCooldownTimer); wheelCooldownTimer = null; } // Update timer every second wheelCooldownTimer = LK.setInterval(function () { updateWheelTimer(); }, 1000); // Initial update updateWheelTimer(); } // Statistics tracking variables var totalBlackjackHands = storage.totalBlackjackHands || 0; var totalBlackjackWins = storage.totalBlackjackWins || 0; var totalSlotsSpins = storage.totalSlotsSpins || 0; var totalMoneyWon = storage.totalMoneyWon || 0; var totalMoneyLost = storage.totalMoneyLost || 0; var maxCascades = storage.maxCascades || 0; var totalWheelSpins = storage.totalWheelSpins || 0; var biggestWin = storage.biggestWin || 0; var longestWinStreak = storage.longestWinStreak || 0; function showStatisticsScreen() { // Create dark overlay background var statsOverlay = LK.getAsset('warning', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95 }); statsOverlay.x = 1024; statsOverlay.y = 1366; statsOverlay.alpha = 0; game.addChild(statsOverlay); // Create title var statsTitle = new Text2('π PLAYER STATISTICS π', { size: 72, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); statsTitle.anchor.set(0.5, 0.5); statsTitle.x = 1024; statsTitle.y = 400; statsTitle.alpha = 0; game.addChild(statsTitle); // Create statistics displays var yPosition = 650; var statsDisplays = []; // Calculate blackjack win percentage var bjWinPercentage = totalBlackjackHands > 0 ? Math.round(totalBlackjackWins / totalBlackjackHands * 100) : 0; // Statistics to display var statistics = [{ label: 'Current Money:', value: '$' + playerMoney }, { label: 'Total Money Won:', value: '$' + totalMoneyWon }, { label: 'Total Money Lost:', value: '$' + totalMoneyLost }, { label: 'Biggest Single Win:', value: '$' + biggestWin }, { label: 'Blackjack Hands Played:', value: totalBlackjackHands.toString() }, { label: 'Blackjack Win Rate:', value: bjWinPercentage + '%' }, { label: 'Longest Win Streak:', value: longestWinStreak.toString() }, { label: 'Slots Spins:', value: totalSlotsSpins.toString() }, { label: 'Max Cascades Achieved:', value: maxCascades.toString() }, { label: 'Wheel Spins:', value: totalWheelSpins.toString() }, { label: 'Free Spins Available:', value: freeSpins.toString() }]; for (var i = 0; i < statistics.length; i++) { var stat = statistics[i]; // Stat background var statBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 1400, height: 120 }); statBg.x = 1024; statBg.y = yPosition; statBg.alpha = 0; game.addChild(statBg); statsDisplays.push(statBg); // Stat label var labelText = new Text2(stat.label, { size: 36, fill: '#FFFFFF', font: "'Arial Black', Arial, sans-serif" }); labelText.anchor.set(0, 0.5); labelText.x = 400; labelText.y = yPosition; labelText.alpha = 0; game.addChild(labelText); statsDisplays.push(labelText); // Stat value var valueText = new Text2(stat.value, { size: 36, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); valueText.anchor.set(1, 0.5); valueText.x = 1648; valueText.y = yPosition; valueText.alpha = 0; game.addChild(valueText); statsDisplays.push(valueText); yPosition += 140; } // Close button var closeStatsButton = new GameButton('CLOSE', 200, 80); closeStatsButton.x = 1024; closeStatsButton.y = 2200; closeStatsButton.alpha = 0; game.addChild(closeStatsButton); // Animate all elements in with staggered timing tween(statsOverlay, { alpha: 0.95 }, { duration: 300 }); tween(statsTitle, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 400, delay: 100, easing: tween.bounceOut, onFinish: function onFinish() { tween(statsTitle, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); // Animate statistics displays for (var i = 0; i < statsDisplays.length; i++) { (function (display, index) { tween(display, { alpha: 1 }, { duration: 300, delay: 200 + index * 30, easing: tween.easeOut }); })(statsDisplays[i], i); } tween(closeStatsButton, { alpha: 1 }, { duration: 300, delay: 600 }); // Close button handler closeStatsButton.up = function () { // Animate out var allElements = [statsOverlay, statsTitle, closeStatsButton].concat(statsDisplays); var elementsToDestroy = 0; var totalElements = allElements.length; for (var i = 0; i < allElements.length; i++) { tween(allElements[i], { alpha: 0 }, { duration: 300, delay: i * 10, onFinish: function onFinish() { elementsToDestroy++; if (elementsToDestroy === totalElements) { // Destroy all elements for (var j = 0; j < allElements.length; j++) { if (allElements[j] && allElements[j].destroy) { allElements[j].destroy(); } } } } }); } }; } function showAchievementsScreen() { // Create dark overlay background var achievementOverlay = LK.getAsset('warning', { anchorX: 0.5, anchorY: 0.5, alpha: 0.95 }); achievementOverlay.x = 1024; achievementOverlay.y = 1366; achievementOverlay.alpha = 0; game.addChild(achievementOverlay); // Create title var achievementTitle = new Text2('π ACHIEVEMENTS π', { size: 72, fill: '#FFD700', font: "'Arial Black', Arial, sans-serif" }); achievementTitle.anchor.set(0.5, 0.5); achievementTitle.x = 1024; achievementTitle.y = 500; achievementTitle.alpha = 0; game.addChild(achievementTitle); // Create achievement displays var yPosition = 750; var achievementDisplays = []; for (var key in achievementSystem.achievements) { var achievement = achievementSystem.achievements[key]; // Achievement container var achievementBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: 1400, height: 200, alpha: achievement.unlocked ? 1.0 : 0.4 }); achievementBg.x = 1024; achievementBg.y = yPosition; achievementBg.alpha = 0; game.addChild(achievementBg); achievementDisplays.push(achievementBg); // Achievement icon/status var statusIcon = new Text2(achievement.unlocked ? 'β ' : 'π', { size: 48, fill: achievement.unlocked ? '#00FF00' : '#888888', font: "'Arial Black', Arial, sans-serif" }); statusIcon.anchor.set(0.5, 0.5); statusIcon.x = 400; statusIcon.y = yPosition - 30; statusIcon.alpha = 0; game.addChild(statusIcon); achievementDisplays.push(statusIcon); // Achievement title var titleText = new Text2(achievement.title, { size: 42, fill: achievement.unlocked ? '#FFD700' : '#CCCCCC', font: "'Arial Black', Arial, sans-serif" }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = yPosition - 30; titleText.alpha = 0; game.addChild(titleText); achievementDisplays.push(titleText); // Achievement description var descText = new Text2(achievement.description, { size: 32, fill: achievement.unlocked ? '#FFFFFF' : '#999999', font: "'Arial Black', Arial, sans-serif" }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = yPosition + 20; descText.alpha = 0; game.addChild(descText); achievementDisplays.push(descText); // Achievement reward var rewardText = new Text2('Reward: +$' + achievement.reward, { size: 28, fill: achievement.unlocked ? '#00FF00' : '#666666', font: "'Arial Black', Arial, sans-serif" }); rewardText.anchor.set(0.5, 0.5); rewardText.x = 1648; rewardText.y = yPosition; rewardText.alpha = 0; game.addChild(rewardText); achievementDisplays.push(rewardText); yPosition += 250; } // Close button var closeButton = new GameButton('CLOSE', 200, 80); closeButton.x = 1024; closeButton.y = 2200; closeButton.alpha = 0; game.addChild(closeButton); // Animate all elements in with staggered timing tween(achievementOverlay, { alpha: 0.95 }, { duration: 300 }); tween(achievementTitle, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 400, delay: 100, easing: tween.bounceOut, onFinish: function onFinish() { tween(achievementTitle, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); // Animate achievement displays for (var i = 0; i < achievementDisplays.length; i++) { (function (display, index) { tween(display, { alpha: 1 }, { duration: 300, delay: 200 + index * 50, easing: tween.easeOut }); })(achievementDisplays[i], i); } tween(closeButton, { alpha: 1 }, { duration: 300, delay: 600 }); // Close button handler closeButton.up = function () { // Animate out var allElements = [achievementOverlay, achievementTitle, closeButton].concat(achievementDisplays); var elementsToDestroy = 0; var totalElements = allElements.length; for (var i = 0; i < allElements.length; i++) { tween(allElements[i], { alpha: 0 }, { duration: 300, delay: i * 20, onFinish: function onFinish() { elementsToDestroy++; if (elementsToDestroy === totalElements) { // Destroy all elements for (var j = 0; j < allElements.length; j++) { if (allElements[j] && allElements[j].destroy) { allElements[j].destroy(); } } } } }); } }; }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AchievementSystem = Container.expand(function () {
var self = Container.call(this);
// Achievement definitions
self.achievements = {
firstBlackjackWin: {
unlocked: false,
title: "First Victory",
description: "Win your first hand of Blackjack",
reward: 100
},
cascade5x: {
unlocked: false,
title: "Cascade Master",
description: "Get a 5x cascade in slots",
reward: 250
},
reach10k: {
unlocked: false,
title: "High Roller",
description: "Reach $10,000",
reward: 500
},
bigSpender: {
unlocked: false,
title: "Big Spender",
description: "Bet $500 in one hand",
reward: 200
},
luckyStreak: {
unlocked: false,
title: "Lucky Streak",
description: "Win 3 hands in a row",
reward: 300
}
};
// Load achievements from storage
var savedAchievements = storage.achievements || {};
for (var key in savedAchievements) {
if (self.achievements[key]) {
self.achievements[key].unlocked = savedAchievements[key];
}
}
self.checkAchievement = function (type, value) {
var achievement = self.achievements[type];
if (!achievement || achievement.unlocked) return;
var shouldUnlock = false;
switch (type) {
case 'firstBlackjackWin':
shouldUnlock = value === true;
break;
case 'cascade5x':
shouldUnlock = value >= 5;
break;
case 'reach10k':
shouldUnlock = value >= 10000;
break;
case 'bigSpender':
shouldUnlock = value >= 500;
break;
case 'luckyStreak':
shouldUnlock = value >= 3;
break;
}
if (shouldUnlock) {
self.unlockAchievement(type);
}
};
self.unlockAchievement = function (type) {
var achievement = self.achievements[type];
if (achievement.unlocked) return;
achievement.unlocked = true;
// Save to storage - only save the unlocked status as literals
var achievementsToSave = {};
for (var key in self.achievements) {
achievementsToSave[key] = self.achievements[key].unlocked;
}
storage.achievements = achievementsToSave;
// Show achievement notification
self.showAchievementNotification(achievement);
// Award money
playerMoney += achievement.reward;
updateMoneyDisplay();
};
self.showAchievementNotification = function (achievement) {
var notification = new Text2('π ACHIEVEMENT UNLOCKED! π', {
size: 48,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
notification.anchor.set(0.5, 0.5);
notification.x = 1024;
notification.y = 400;
notification.alpha = 0;
notification.scaleX = 0.5;
notification.scaleY = 0.5;
game.addChild(notification);
var titleText = new Text2(achievement.title, {
size: 36,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 480;
titleText.alpha = 0;
titleText.scaleX = 0.5;
titleText.scaleY = 0.5;
game.addChild(titleText);
var rewardText = new Text2('+$' + achievement.reward, {
size: 32,
fill: '#00FF00',
font: "'Arial Black', Arial, sans-serif"
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 1024;
rewardText.y = 540;
rewardText.alpha = 0;
rewardText.scaleX = 0.5;
rewardText.scaleY = 0.5;
game.addChild(rewardText);
// Animate in
tween(notification, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut
});
tween(titleText, {
alpha: 1,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
delay: 200,
easing: tween.bounceOut
});
tween(rewardText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
delay: 400,
easing: tween.bounceOut
});
// Animate out after 3 seconds
LK.setTimeout(function () {
tween(notification, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8,
y: notification.y - 100
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
notification.destroy();
}
});
tween(titleText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8,
y: titleText.y - 100
}, {
duration: 800,
delay: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
titleText.destroy();
}
});
tween(rewardText, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8,
y: rewardText.y - 100
}, {
duration: 800,
delay: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
rewardText.destroy();
}
});
}, 3000);
};
return self;
});
var AnimatedHand = Container.expand(function (isDealer) {
var self = Container.call(this);
self.isDealer = isDealer || false;
var handGraphic = self.attachAsset(isDealer ? 'dealerHand' : 'playerHand', {
anchorX: 0.5,
anchorY: 0.5,
width: isDealer ? 216 : 285.66,
height: isDealer ? 324 : 428.49,
alpha: 0.8
});
// Deal card animation (player - face up)
self.dealCardToPlayer = function (targetX, targetY, onComplete) {
var movingCard = LK.getAsset('movingCard', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
movingCard.x = self.x;
movingCard.y = self.y;
game.addChild(movingCard);
// Animate hand dealing
tween(handGraphic, {
scaleX: 1.1,
scaleY: 1.1,
rotation: 0.1
}, {
duration: 200
});
// Play card dealing sound
LK.getSound('Carta_1').play();
// Move card to target
tween(movingCard, {
x: targetX,
y: targetY,
rotation: (Math.random() - 0.5) * 0.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
movingCard.destroy();
// Reset hand
tween(handGraphic, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 200
});
if (onComplete) onComplete();
}
});
};
// Deal card face down (dealer)
self.dealCardFaceDown = function (targetX, targetY, onComplete) {
var movingCard = LK.getAsset('movingCard', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
movingCard.x = self.x;
movingCard.y = self.y;
game.addChild(movingCard);
// Animate hand dealing
tween(handGraphic, {
scaleX: 1.1,
scaleY: 1.1,
rotation: -0.1
}, {
duration: 200
});
// Play card dealing sound
LK.getSound('Carta_1').play();
// Move card to target
tween(movingCard, {
x: targetX,
y: targetY,
rotation: (Math.random() - 0.5) * 0.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
movingCard.destroy();
// Reset hand
tween(handGraphic, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 200
});
if (onComplete) onComplete();
}
});
};
// Hit gesture animation
self.hitGesture = function (targetX, targetY, onComplete) {
var movingCard = LK.getAsset('movingCard', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
movingCard.x = self.x;
movingCard.y = self.y;
game.addChild(movingCard);
// Quick dealing animation
tween(handGraphic, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 150
});
// Quick card movement
tween(movingCard, {
x: targetX,
y: targetY
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
movingCard.destroy();
tween(handGraphic, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
if (onComplete) onComplete();
}
});
};
// Stand gesture animation
self.standGesture = function () {
tween(handGraphic, {
rotation: 0.3,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
onFinish: function onFinish() {
tween(handGraphic, {
rotation: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300
});
}
});
};
// Double down gesture with chips and card
self.doubleDownGesture = function (targetX, targetY, onComplete) {
// Animate placing chips first
var chip = LK.getAsset('chipBet', {
anchorX: 0.5,
anchorY: 0.5
});
chip.x = self.x;
chip.y = self.y;
chip.alpha = 0;
game.addChild(chip);
tween(chip, {
x: targetX - 100,
y: targetY + 100,
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
// Then deal final card face down
var movingCard = LK.getAsset('movingCard', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
movingCard.x = self.x;
movingCard.y = self.y;
game.addChild(movingCard);
tween(movingCard, {
x: targetX,
y: targetY
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
movingCard.destroy();
chip.destroy();
if (onComplete) onComplete();
}
});
}
});
};
// Card flip animation
self.flipCard = function (cardX, cardY, onComplete) {
// Create card back for flip animation
var flippingCardBack = LK.getAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 300
});
flippingCardBack.x = cardX;
flippingCardBack.y = cardY;
game.addChild(flippingCardBack);
// Create card front for flip animation (hidden initially)
var flippingCardFront = LK.getAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 300,
scaleX: 0,
alpha: 0
});
flippingCardFront.x = cardX;
flippingCardFront.y = cardY;
game.addChild(flippingCardFront);
// Animate hand moving to card with dramatic gesture
tween(handGraphic, {
x: cardX - self.x,
y: cardY - self.y,
scaleX: 1.2,
scaleY: 1.2,
rotation: 0.3
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// First half of flip - shrink card back horizontally
tween(flippingCardBack, {
scaleX: 0,
rotation: 0.1
}, {
duration: 250,
easing: tween.easeIn,
onFinish: function onFinish() {
// Play card flip sound when revealing
LK.getSound('Carta_2').play();
// Hide card back, show card front
flippingCardBack.alpha = 0;
flippingCardFront.alpha = 1;
// Second half of flip - expand card front horizontally
tween(flippingCardFront, {
scaleX: 1,
rotation: 0
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
// Add subtle bounce effect
tween(flippingCardFront, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(flippingCardFront, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
// Clean up animation cards
flippingCardBack.destroy();
flippingCardFront.destroy();
// Return hand to original position with flourish
tween(handGraphic, {
x: 0,
y: 0,
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 400,
easing: tween.easeOut
});
if (onComplete) onComplete();
}
});
}
});
}
});
}
});
}
});
};
// Collect cards animation
self.collectCards = function (cardPositions, actualCards, onComplete) {
var collectCount = 0;
var totalCards = cardPositions.length;
for (var i = 0; i < cardPositions.length; i++) {
var pos = cardPositions[i];
var actualCard = actualCards ? actualCards[i] : null;
var collectingCard = LK.getAsset('movingCard', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
collectingCard.x = pos.x;
collectingCard.y = pos.y;
game.addChild(collectingCard);
// Create closure to capture current card index
(function (cardIndex, actualCardRef) {
// Play card collection sound for each card
LK.getSound('Carta_3').play();
tween(collectingCard, {
x: self.x,
y: self.y,
scaleX: 0.5,
scaleY: 0.5,
alpha: 0
}, {
duration: 400,
delay: cardIndex * 0,
easing: tween.easeIn,
onFinish: function onFinish() {
collectingCard.destroy();
// Make actual card disappear when collected
if (actualCardRef) {
actualCardRef.alpha = 0;
}
collectCount++;
if (collectCount >= totalCards && onComplete) {
onComplete();
}
}
});
})(i, actualCard);
}
// Animate hand collecting
tween(handGraphic, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(handGraphic, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
};
// Shuffle animation
self.shuffleAnimation = function () {
var shuffleDuration = 1200;
var shuffleSteps = 8;
var stepDuration = shuffleDuration / shuffleSteps;
// First, move hand to deck position
var deckPosition = {
x: 200,
y: 1366
}; // Deck position from gamecode
var handStartX = self.x;
var handStartY = self.y;
// Move hand to deck pile
tween(self, {
x: deckPosition.x,
y: deckPosition.y
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Play shuffle sound when hand reaches deck
LK.getSound('Baraja').play();
// Now perform shuffle animation at deck position
for (var i = 0; i < shuffleSteps; i++) {
LK.setTimeout(function () {
tween(handGraphic, {
rotation: (Math.random() - 0.5) * 0.4,
scaleX: 0.9 + Math.random() * 0.2,
scaleY: 0.9 + Math.random() * 0.2
}, {
duration: stepDuration / 2,
onFinish: function onFinish() {
tween(handGraphic, {
rotation: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: stepDuration / 2
});
}
});
}, i * stepDuration);
}
// After shuffle animation completes, return hand to original position
LK.setTimeout(function () {
tween(self, {
x: handStartX,
y: handStartY
}, {
duration: 300,
easing: tween.easeOut
});
}, shuffleDuration + 300);
}
});
};
return self;
});
var Card = Container.expand(function (suit, value) {
var self = Container.call(this);
self.suit = suit || 'hearts';
self.value = value || 1;
self.faceUp = false;
self.getDisplayValue = function () {
if (self.value === 1) return 'A';
if (self.value === 11) return 'J';
if (self.value === 12) return 'Q';
if (self.value === 13) return 'K';
return self.value.toString();
};
self.getSuitSymbol = function () {
switch (self.suit) {
case 'hearts':
return 'β₯';
case 'diamonds':
return 'β¦';
case 'clubs':
return 'β£';
case 'spades':
return 'β ';
default:
return 'β₯';
}
};
self.getColor = function () {
return self.suit === 'hearts' || self.suit === 'diamonds' ? '#FF0000' : '#000000';
};
var cardShadow = self.attachAsset('cardShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 380,
alpha: 0.3
});
cardShadow.x = 5;
cardShadow.y = 5;
var cardBack = self.attachAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
// Get the specific card face asset based on suit and value
var cardFaceAsset = 'card_' + self.suit + '_' + (self.value === 1 ? 'A' : self.value === 11 ? 'J' : self.value === 12 ? 'Q' : self.value === 13 ? 'K' : self.value.toString());
var cardFront = self.attachAsset(cardFaceAsset, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
width: 240,
height: 360
});
// Top left corner value
var topLeftValue = new Text2(self.getDisplayValue(), {
size: 40,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
topLeftValue.anchor.set(0, 0);
topLeftValue.x = -115;
topLeftValue.y = -170;
topLeftValue.alpha = 0;
cardFront.addChild(topLeftValue);
// Bottom right corner value (rotated 180 degrees)
var bottomRightValue = new Text2(self.getDisplayValue(), {
size: 40,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
bottomRightValue.anchor.set(1, 1);
bottomRightValue.x = 75;
bottomRightValue.y = 120;
bottomRightValue.rotation = Math.PI;
bottomRightValue.alpha = 0;
cardFront.addChild(bottomRightValue);
// Center symbols for numbered cards (2-10)
var centerSymbols = [];
if (self.value >= 2 && self.value <= 10) {
for (var i = 0; i < self.value; i++) {
var centerSymbol = new Text2(self.getSuitSymbol(), {
size: 60,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
centerSymbol.anchor.set(0.5, 0.5);
// Aesthetic positioning based on card number
var positions = [];
if (self.value === 2) {
positions = [{
x: 0,
y: -60
}, {
x: 0,
y: 60
}];
} else if (self.value === 3) {
positions = [{
x: 0,
y: -80
}, {
x: 0,
y: 0
}, {
x: 0,
y: 80
}];
} else if (self.value === 4) {
positions = [{
x: -40,
y: -60
}, {
x: 40,
y: -60
}, {
x: -40,
y: 60
}, {
x: 40,
y: 60
}];
} else if (self.value === 5) {
positions = [{
x: -40,
y: -60
}, {
x: 40,
y: -60
}, {
x: 0,
y: 0
}, {
x: -40,
y: 60
}, {
x: 40,
y: 60
}];
} else if (self.value === 6) {
positions = [{
x: -40,
y: -80
}, {
x: 40,
y: -80
}, {
x: -40,
y: 0
}, {
x: 40,
y: 0
}, {
x: -40,
y: 80
}, {
x: 40,
y: 80
}];
} else if (self.value === 7) {
positions = [{
x: -40,
y: -80
}, {
x: 40,
y: -80
}, {
x: 0,
y: -40
}, {
x: -40,
y: 0
}, {
x: 40,
y: 0
}, {
x: -40,
y: 80
}, {
x: 40,
y: 80
}];
} else if (self.value === 8) {
positions = [{
x: -40,
y: -80
}, {
x: 40,
y: -80
}, {
x: -40,
y: -30
}, {
x: 40,
y: -30
}, {
x: -40,
y: 30
}, {
x: 40,
y: 30
}, {
x: -40,
y: 80
}, {
x: 40,
y: 80
}];
} else if (self.value === 9) {
positions = [{
x: -40,
y: -80
}, {
x: 40,
y: -80
}, {
x: -40,
y: -40
}, {
x: 40,
y: -40
}, {
x: 0,
y: 0
}, {
x: -40,
y: 40
}, {
x: 40,
y: 40
}, {
x: -40,
y: 80
}, {
x: 40,
y: 80
}];
} else if (self.value === 10) {
positions = [{
x: -40,
y: -80
}, {
x: 40,
y: -80
}, {
x: -40,
y: -50
}, {
x: 40,
y: -50
}, {
x: -40,
y: -20
}, {
x: 40,
y: -20
}, {
x: -40,
y: 20
}, {
x: 40,
y: 20
}, {
x: -40,
y: 80
}, {
x: 40,
y: 80
}];
}
centerSymbol.x = positions[i].x;
centerSymbol.y = positions[i].y;
centerSymbol.alpha = 0;
cardFront.addChild(centerSymbol);
centerSymbols.push(centerSymbol);
}
}
// Main suit symbol for face cards
var suitText = new Text2(self.getSuitSymbol(), {
size: 60,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
suitText.anchor.set(0.5, 0.5);
suitText.y = 0;
suitText.alpha = 0;
// Special center symbol for Jack - create a servant/knave figure
if (self.value === 11) {
// Create a simple servant figure using text symbols
var servantFigure = new Text2('β', {
size: 180,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
servantFigure.anchor.set(0.5, 0.5);
servantFigure.y = 0;
servantFigure.alpha = 0;
cardFront.addChild(servantFigure);
// Store references for flip animation
centerSymbols.push(servantFigure);
} else if (self.value === 12) {
// Special center symbol for Queen - create a queen figure
var queenFigure = new Text2('β', {
size: 180,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
queenFigure.anchor.set(0.5, 0.5);
queenFigure.y = 0;
queenFigure.alpha = 0;
cardFront.addChild(queenFigure);
// Store references for flip animation
centerSymbols.push(queenFigure);
} else if (self.value === 13) {
// Special center symbol for King - create a king figure
var kingFigure = new Text2('β', {
size: 180,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
kingFigure.anchor.set(0.5, 0.5);
kingFigure.y = 0;
kingFigure.alpha = 0;
cardFront.addChild(kingFigure);
// Store references for flip animation
centerSymbols.push(kingFigure);
} else if (self.value < 2 || self.value > 9 && self.value !== 11 && self.value !== 12 && self.value !== 13) {
cardFront.addChild(suitText);
}
self.getBlackjackValue = function () {
if (self.value === 1) return 11; // Ace high initially
if (self.value > 10) return 10; // Face cards
return self.value;
};
self.flip = function () {
self.faceUp = !self.faceUp;
LK.getSound('cardFlip').play();
if (self.faceUp) {
tween(cardBack, {
alpha: 0
}, {
duration: 200
});
tween(cardFront, {
alpha: 1
}, {
duration: 200
});
tween(topLeftValue, {
alpha: 1
}, {
duration: 200
});
tween(bottomRightValue, {
alpha: 1
}, {
duration: 200
});
for (var i = 0; i < centerSymbols.length; i++) {
tween(centerSymbols[i], {
alpha: 1
}, {
duration: 200
});
}
if (self.value < 2 || self.value > 9) {
tween(suitText, {
alpha: 1
}, {
duration: 200
});
}
} else {
tween(cardBack, {
alpha: 1
}, {
duration: 200
});
tween(cardFront, {
alpha: 0
}, {
duration: 200
});
tween(topLeftValue, {
alpha: 0
}, {
duration: 200
});
tween(bottomRightValue, {
alpha: 0
}, {
duration: 200
});
for (var i = 0; i < centerSymbols.length; i++) {
tween(centerSymbols[i], {
alpha: 0
}, {
duration: 200
});
}
if (self.value < 2 || self.value > 9) {
tween(suitText, {
alpha: 0
}, {
duration: 200
});
}
}
};
return self;
});
var Chip = Container.expand(function (value) {
var self = Container.call(this);
self.value = value || 1;
// Get appropriate chip asset based on value
var chipAsset;
switch (self.value) {
case 1:
chipAsset = 'chip1';
break;
case 5:
chipAsset = 'chip5';
break;
case 10:
chipAsset = 'chip10';
break;
case 25:
chipAsset = 'chip25';
break;
case 100:
chipAsset = 'chip100';
break;
case 500:
chipAsset = 'chip500';
break;
default:
chipAsset = 'chip1';
}
var chipGraphic = self.attachAsset(chipAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Add value text on chip
var valueText = new Text2('$' + self.value, {
size: 18,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
valueText.anchor.set(0.5, 0.5);
chipGraphic.addChild(valueText);
self.enabled = true;
// Make chip interactive
self.interactive = true;
self.buttonMode = true;
self.setEnabled = function (enabled) {
self.enabled = enabled;
chipGraphic.alpha = enabled ? 1.0 : 0.5;
};
self.down = function (x, y, obj) {
if (!self.enabled) return;
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'betting') return;
// Check if player has enough money for this chip value when added to current bet
if (playerMoney >= currentBet + self.value) {
currentBet += self.value;
updateChipSelection();
LK.getSound('Ficha_1').play();
// Create animated chip that moves to Apuesta center
var animatedChip = LK.getAsset(chipAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Get chip's global position
var chipGlobalPos = self.parent.toGlobal(self.position);
var gameLocalPos = game.toLocal(chipGlobalPos);
animatedChip.x = gameLocalPos.x;
animatedChip.y = gameLocalPos.y;
animatedChip.alpha = 0.8;
game.addChild(animatedChip);
// Animate chip moving to center of Apuesta asset
tween(animatedChip, {
x: apuestaAsset.x,
y: apuestaAsset.y,
scaleX: 0.7,
scaleY: 0.7,
alpha: 1.0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Fade out and destroy the animated chip
tween(animatedChip, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300,
onFinish: function onFinish() {
animatedChip.destroy();
}
});
}
});
// Visual feedback on original chip
tween(chipGraphic, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(chipGraphic, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
}
};
return self;
});
var DealerCard = Container.expand(function (suit, value) {
var self = Container.call(this);
self.suit = suit || 'hearts';
self.value = value || 1;
self.faceUp = false;
self.getDisplayValue = function () {
if (self.value === 1) return 'A';
if (self.value === 11) return 'J';
if (self.value === 12) return 'Q';
if (self.value === 13) return 'K';
return self.value.toString();
};
self.getSuitSymbol = function () {
switch (self.suit) {
case 'hearts':
return 'β₯';
case 'diamonds':
return 'β¦';
case 'clubs':
return 'β£';
case 'spades':
return 'β ';
default:
return 'β₯';
}
};
self.getColor = function () {
return self.suit === 'hearts' || self.suit === 'diamonds' ? '#FF0000' : '#000000';
};
var cardShadow = self.attachAsset('dealerCardShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 320,
alpha: 0.3
});
cardShadow.x = 4;
cardShadow.y = 4;
var cardBack = self.attachAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 300
});
// Get the specific card face asset based on suit and value for dealer cards
var dealerCardFaceAsset = 'card_' + self.suit + '_' + (self.value === 1 ? 'A' : self.value === 11 ? 'J' : self.value === 12 ? 'Q' : self.value === 13 ? 'K' : self.value.toString());
var cardFront = self.attachAsset(dealerCardFaceAsset, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
width: 200,
height: 300
});
// Top left corner value
var topLeftValue = new Text2(self.getDisplayValue(), {
size: 32,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
topLeftValue.anchor.set(0, 0);
topLeftValue.x = -95;
topLeftValue.y = -140;
topLeftValue.alpha = 0;
cardFront.addChild(topLeftValue);
// Bottom right corner value (rotated 180 degrees)
var bottomRightValue = new Text2(self.getDisplayValue(), {
size: 32,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
bottomRightValue.anchor.set(1, 1);
bottomRightValue.x = 55;
bottomRightValue.y = 90;
bottomRightValue.rotation = Math.PI;
bottomRightValue.alpha = 0;
cardFront.addChild(bottomRightValue);
// Center symbols for numbered cards (2-10)
var centerSymbols = [];
if (self.value >= 2 && self.value <= 10) {
for (var i = 0; i < self.value; i++) {
var centerSymbol = new Text2(self.getSuitSymbol(), {
size: 48,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
centerSymbol.anchor.set(0.5, 0.5);
// Aesthetic positioning based on card number
var positions = [];
if (self.value === 2) {
positions = [{
x: 0,
y: -45
}, {
x: 0,
y: 45
}];
} else if (self.value === 3) {
positions = [{
x: 0,
y: -60
}, {
x: 0,
y: 0
}, {
x: 0,
y: 60
}];
} else if (self.value === 4) {
positions = [{
x: -30,
y: -45
}, {
x: 30,
y: -45
}, {
x: -30,
y: 45
}, {
x: 30,
y: 45
}];
} else if (self.value === 5) {
positions = [{
x: -30,
y: -45
}, {
x: 30,
y: -45
}, {
x: 0,
y: 0
}, {
x: -30,
y: 45
}, {
x: 30,
y: 45
}];
} else if (self.value === 6) {
positions = [{
x: -30,
y: -60
}, {
x: 30,
y: -60
}, {
x: -30,
y: 0
}, {
x: 30,
y: 0
}, {
x: -30,
y: 60
}, {
x: 30,
y: 60
}];
} else if (self.value === 7) {
positions = [{
x: -30,
y: -60
}, {
x: 30,
y: -60
}, {
x: 0,
y: -30
}, {
x: -30,
y: 0
}, {
x: 30,
y: 0
}, {
x: -30,
y: 60
}, {
x: 30,
y: 60
}];
} else if (self.value === 8) {
positions = [{
x: -30,
y: -60
}, {
x: 30,
y: -60
}, {
x: -30,
y: -20
}, {
x: 30,
y: -20
}, {
x: -30,
y: 20
}, {
x: 30,
y: 20
}, {
x: -30,
y: 60
}, {
x: 30,
y: 60
}];
} else if (self.value === 9) {
positions = [{
x: -30,
y: -60
}, {
x: 30,
y: -60
}, {
x: -30,
y: -30
}, {
x: 30,
y: -30
}, {
x: 0,
y: 0
}, {
x: -30,
y: 30
}, {
x: 30,
y: 30
}, {
x: -30,
y: 60
}, {
x: 30,
y: 60
}];
} else if (self.value === 10) {
positions = [{
x: -30,
y: -60
}, {
x: 30,
y: -60
}, {
x: -30,
y: -40
}, {
x: 30,
y: -40
}, {
x: -30,
y: -15
}, {
x: 30,
y: -15
}, {
x: -30,
y: 15
}, {
x: 30,
y: 15
}, {
x: -30,
y: 60
}, {
x: 30,
y: 60
}];
}
centerSymbol.x = positions[i].x;
centerSymbol.y = positions[i].y;
centerSymbol.alpha = 0;
cardFront.addChild(centerSymbol);
centerSymbols.push(centerSymbol);
}
}
// Main suit symbol for face cards
var suitText = new Text2(self.getSuitSymbol(), {
size: 48,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
suitText.anchor.set(0.5, 0.5);
suitText.y = 0;
suitText.alpha = 0;
// Special center symbol for Jack - create a servant/knave figure
if (self.value === 11) {
// Create a simple servant figure using text symbols
var servantFigure = new Text2('β', {
size: 144,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
servantFigure.anchor.set(0.5, 0.5);
servantFigure.y = 0;
servantFigure.alpha = 0;
cardFront.addChild(servantFigure);
// Store references for flip animation
centerSymbols.push(servantFigure);
} else if (self.value === 12) {
// Special center symbol for Queen - create a queen figure
var queenFigure = new Text2('β', {
size: 144,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
queenFigure.anchor.set(0.5, 0.5);
queenFigure.y = 0;
queenFigure.alpha = 0;
cardFront.addChild(queenFigure);
// Store references for flip animation
centerSymbols.push(queenFigure);
} else if (self.value === 13) {
// Special center symbol for King - create a king figure
var kingFigure = new Text2('β', {
size: 144,
fill: self.getColor(),
font: "'Arial Black', Arial, sans-serif"
});
kingFigure.anchor.set(0.5, 0.5);
kingFigure.y = 0;
kingFigure.alpha = 0;
cardFront.addChild(kingFigure);
// Store references for flip animation
centerSymbols.push(kingFigure);
} else if (self.value < 2 || self.value > 9 && self.value !== 11 && self.value !== 12 && self.value !== 13) {
cardFront.addChild(suitText);
}
self.getBlackjackValue = function () {
if (self.value === 1) return 11; // Ace high initially
if (self.value > 10) return 10; // Face cards
return self.value;
};
self.flip = function () {
self.faceUp = !self.faceUp;
LK.getSound('cardFlip').play();
if (self.faceUp) {
tween(cardBack, {
alpha: 0
}, {
duration: 200
});
tween(cardFront, {
alpha: 1
}, {
duration: 200
});
tween(topLeftValue, {
alpha: 1
}, {
duration: 200
});
tween(bottomRightValue, {
alpha: 1
}, {
duration: 200
});
for (var i = 0; i < centerSymbols.length; i++) {
tween(centerSymbols[i], {
alpha: 1
}, {
duration: 200
});
}
if (self.value < 2 || self.value > 9) {
tween(suitText, {
alpha: 1
}, {
duration: 200
});
}
} else {
tween(cardBack, {
alpha: 1
}, {
duration: 200
});
tween(cardFront, {
alpha: 0
}, {
duration: 200
});
tween(topLeftValue, {
alpha: 0
}, {
duration: 200
});
tween(bottomRightValue, {
alpha: 0
}, {
duration: 200
});
for (var i = 0; i < centerSymbols.length; i++) {
tween(centerSymbols[i], {
alpha: 0
}, {
duration: 200
});
}
if (self.value < 2 || self.value > 9) {
tween(suitText, {
alpha: 0
}, {
duration: 200
});
}
}
};
return self;
});
var Deck = Container.expand(function () {
var self = Container.call(this);
// Create multiple stacked cards for deck appearance
var stackedCards = [];
for (var i = 0; i < 5; i++) {
var cardLayer = self.attachAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
cardLayer.x = i * 3; // Slight offset for stacking effect
cardLayer.y = i * -2; // Vertical stacking
cardLayer.alpha = 0.9 - i * 0.1; // Fade slightly for depth
stackedCards.push(cardLayer);
}
self.cardCount = 52;
var countText = new Text2('52', {
size: 24,
fill: '#FFFFFF'
});
countText.anchor.set(0.5, 0.5);
countText.y = -200;
self.addChild(countText);
// Start deck breathing animation
self.startDeckAnimation = function () {
// Create a subtle breathing animation for the entire deck
function breatheAnimation() {
tween(self, {
scaleX: 1.02,
scaleY: 1.02,
y: self.y - 2
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
y: self.y + 2
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
breatheAnimation(); // Loop the animation
}
});
}
});
}
breatheAnimation();
// Add subtle rotation animation to individual cards for depth
for (var i = 0; i < stackedCards.length; i++) {
(function (cardLayer, index) {
function cardFloatAnimation() {
var randomOffset = (Math.random() - 0.5) * 0.02; // Small random rotation
tween(cardLayer, {
rotation: randomOffset,
y: cardLayer.y + (Math.random() - 0.5) * 1
}, {
duration: 3000 + index * 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(cardLayer, {
rotation: -randomOffset * 0.5,
y: cardLayer.y - (Math.random() - 0.5) * 1
}, {
duration: 3000 + index * 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
cardFloatAnimation(); // Loop the animation
}
});
}
});
}
cardFloatAnimation();
})(stackedCards[i], i);
}
};
// Stop deck animation
self.stopDeckAnimation = function () {
tween.stop(self, {
scaleX: true,
scaleY: true,
y: true
});
for (var i = 0; i < stackedCards.length; i++) {
tween.stop(stackedCards[i], {
rotation: true,
y: true
});
}
};
self.updateCount = function (count) {
self.cardCount = count;
countText.setText(count.toString());
if (count <= 0) {
for (var i = 0; i < stackedCards.length; i++) {
stackedCards[i].alpha = 0.1;
}
} else {
for (var i = 0; i < stackedCards.length; i++) {
stackedCards[i].alpha = 0.9 - i * 0.1;
}
}
};
self.dealAnimation = function (targetX, targetY, onComplete) {
if (self.cardCount <= 0) {
if (onComplete) onComplete();
return;
}
self.cardCount--;
self.updateCount(self.cardCount);
var dealingCard = LK.getAsset('casinoCardBack', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 360
});
dealingCard.x = self.x;
dealingCard.y = self.y;
game.addChild(dealingCard);
tween(dealingCard, {
x: targetX,
y: targetY,
rotation: (Math.random() - 0.5) * 0.2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
dealingCard.destroy();
if (onComplete) onComplete();
}
});
// Animate the entire stack slightly when dealing
for (var i = 0; i < stackedCards.length; i++) {
tween(stackedCards[i], {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(stackedCards[i], {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
}
};
return self;
});
var GameButton = Container.expand(function (text, width, height) {
var self = Container.call(this);
var buttonShadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: (width || 200) * 2 + 20,
height: (height || 80) * 2 + 20,
alpha: 0.4
});
buttonShadow.x = 6;
buttonShadow.y = 6;
var buttonBg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: (width || 200) * 2,
height: (height || 80) * 2
});
var buttonText = new Text2(text || 'Button', {
size: 48,
fill: '#000000',
font: "'Arial Black', Arial, sans-serif"
});
buttonText.anchor.set(0.5, 0.5);
buttonBg.addChild(buttonText);
self.enabled = true;
self.setText = function (newText) {
buttonText.setText(newText);
};
self.setEnabled = function (enabled) {
self.enabled = enabled;
buttonBg.alpha = enabled ? 1.0 : 0.5;
};
self.down = function (x, y, obj) {
if (!self.enabled) return;
LK.getSound('buttonClick').play();
tween(buttonBg, {
scaleX: 0.85,
scaleY: 0.85
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.enabled) return;
tween(buttonBg, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(buttonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
};
return self;
});
var MegawaysReel = Container.expand(function (reelIndex) {
var self = Container.call(this);
self.reelIndex = reelIndex || 0;
self.symbols = [];
self.symbolTypes = ['megawaysSymbolA', 'megawaysSymbolB', 'megawaysSymbolC', 'megawaysSymbolD', 'megawaysSymbolE', 'megawaysSymbolF', 'megawaysWild', 'megawaysScatter'];
self.spinning = false;
self.currentSymbolCount = 4; // Start with 4 symbols
self.maxSymbols = 4; // Maximum symbols per reel
self.minSymbols = 4; // Minimum symbols per reel
self.isSpinning = false;
self.spinEndCallback = null;
// Reel container background
var reelBorder = self.attachAsset('megawaysReelBorder', {
anchorX: 0.5,
anchorY: 0.5
});
var reelContainer = self.attachAsset('megawaysReelContainer', {
anchorX: 0.5,
anchorY: 0.5
});
// Symbol frequency weights for balanced RTP (higher weight = more frequent)
self.symbolWeights = {
'megawaysSymbolF': 35,
// Most frequent (lowest paying)
'megawaysSymbolE': 25,
// Very frequent
'megawaysSymbolD': 20,
// Frequent
'megawaysSymbolC': 12,
// Less frequent
'megawaysSymbolB': 6,
// Rare
'megawaysSymbolA': 2 // Very rare (highest paying)
};
// Get weighted random symbol based on frequency
self.getWeightedRandomSymbol = function () {
// Improved symbol distribution with more balanced frequencies
var adjustedWeights = {};
var cascadeCount = self.cascadeCount || 0; // Use cascade count from reel property
// More balanced distribution - reduce dominance of F and E symbols
if (cascadeCount >= 15) {
adjustedWeights = {
'megawaysSymbolF': 28,
// Reduced dominance from 32
'megawaysSymbolE': 22,
// Reduced from 23
'megawaysSymbolD': 22,
// Increased from 20
'megawaysSymbolC': 16,
// Increased from 14
'megawaysSymbolB': 9,
// Increased from 8
'megawaysSymbolA': 3 // Same
};
} else if (cascadeCount >= 10) {
adjustedWeights = {
'megawaysSymbolF': 30,
// Reduced from 33
'megawaysSymbolE': 22,
// Reduced from 24
'megawaysSymbolD': 22,
// Increased from 20
'megawaysSymbolC': 15,
// Increased from 13
'megawaysSymbolB': 8,
// Increased from 7
'megawaysSymbolA': 3 // Same
};
} else {
// More balanced base weights
adjustedWeights = {
'megawaysSymbolF': 30,
// Reduced from 35
'megawaysSymbolE': 22,
// Reduced from 25
'megawaysSymbolD': 22,
// Increased from 20
'megawaysSymbolC': 15,
// Increased from 12
'megawaysSymbolB': 8,
// Increased from 6
'megawaysSymbolA': 3 // Increased from 2
};
}
var totalWeight = 0;
for (var symbol in adjustedWeights) {
totalWeight += adjustedWeights[symbol];
}
var randomValue = Math.random() * totalWeight;
var currentWeight = 0;
for (var symbol in adjustedWeights) {
currentWeight += adjustedWeights[symbol];
if (randomValue <= currentWeight) {
return symbol;
}
}
// Fallback to most common symbol
return 'megawaysSymbolF';
};
// Initialize reel with random symbol count
self.generateRandomSymbolCount = function () {
self.currentSymbolCount = self.minSymbols + Math.floor(Math.random() * (self.maxSymbols - self.minSymbols + 1));
return self.currentSymbolCount;
};
// Create symbols for this reel
self.createSymbols = function () {
// Clear existing symbols
for (var i = 0; i < self.symbols.length; i++) {
if (self.symbols[i] && self.symbols[i].destroy) {
self.symbols[i].destroy();
}
}
self.symbols = [];
// Create new symbols based on current count
for (var i = 0; i < self.currentSymbolCount; i++) {
var symbolType = self.getWeightedRandomSymbol();
var symbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType));
// Position symbols vertically within reel with no spacing between them
var symbolHeight = 105; // Height of each symbol (60 * 1.4 scale + padding to fill 420px height completely)
symbol.y = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight;
// Scale symbols to fill available space better
symbol.scaleX = 1;
symbol.scaleY = 1;
self.addChild(symbol);
self.symbols.push(symbol);
}
};
// Calculate total ways to win based on symbol counts
self.calculateWays = function (reelSymbolCounts) {
var totalWays = 1;
for (var i = 0; i < reelSymbolCounts.length; i++) {
totalWays *= reelSymbolCounts[i];
}
return totalWays;
};
// Spin reel with enhanced Megaways animations
self.spin = function (duration, onComplete) {
if (self.isSpinning) return;
self.isSpinning = true;
self.spinEndCallback = onComplete;
// Generate new symbol count for this spin
self.generateRandomSymbolCount();
// Store old symbols for cascading animation
var oldSymbols = self.symbols.slice();
// Start spin animation with reel shake and blur
tween(reelContainer, {
scaleY: 0.6,
scaleX: 1.1,
alpha: 0.7
}, {
duration: 300,
easing: tween.easeOut
});
// Animate old symbols falling out
for (var i = 0; i < oldSymbols.length; i++) {
(function (symbol, index) {
tween(symbol, {
y: symbol.y + 500,
alpha: 0,
rotation: (Math.random() - 0.5) * Math.PI
}, {
duration: 400 + index * 50,
easing: tween.easeIn,
onFinish: function onFinish() {
if (symbol && symbol.destroy) {
symbol.destroy();
}
}
});
})(oldSymbols[i], i);
}
// Clear symbols array after starting fall animation
self.symbols = [];
var spinInterval;
var spinCount = 0;
var maxSpins = Math.floor(duration / 120);
var tempSymbols = [];
spinInterval = LK.setInterval(function () {
spinCount++;
// Create temporary spinning symbols for visual effect
if (spinCount % 2 === 0) {
// Clear temp symbols
for (var i = 0; i < tempSymbols.length; i++) {
if (tempSymbols[i] && tempSymbols[i].destroy) {
tempSymbols[i].destroy();
}
}
tempSymbols = [];
// Create new temp symbols
for (var i = 0; i < self.currentSymbolCount; i++) {
var symbolType = self.symbolTypes[Math.floor(Math.random() * self.symbolTypes.length)];
var tempSymbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType));
// Position temp symbols with no spacing between them
var symbolHeight = 105; // Height of each symbol with no gaps
tempSymbol.y = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight;
tempSymbol.alpha = 0.6;
// Scale temp symbols to match final ones
tempSymbol.scaleX = 1.0;
tempSymbol.scaleY = 1.0;
self.addChild(tempSymbol);
tempSymbols.push(tempSymbol);
}
}
// Add intense shake effect during spin
reelContainer.x = (Math.random() - 0.5) * 12;
reelContainer.y = (Math.random() - 0.5) * 8;
if (spinCount >= maxSpins) {
LK.clearInterval(spinInterval);
// Clear temp symbols
for (var i = 0; i < tempSymbols.length; i++) {
if (tempSymbols[i] && tempSymbols[i].destroy) {
tempSymbols[i].destroy();
}
}
tempSymbols = [];
// Create final symbols with drop-in animation
self.createFinalSymbols();
}
}, 120);
};
// Create final symbols with drop-in animation
self.createFinalSymbols = function () {
// Create new symbols above the reel
for (var i = 0; i < self.currentSymbolCount; i++) {
var symbolType = self.getWeightedRandomSymbol();
var symbol = new MegawaysSymbol(symbolType, self.symbolTypes.indexOf(symbolType));
// Position symbols with no spacing between them
var symbolHeight = 105; // Height of each symbol with no gaps
var finalY = (i - (self.currentSymbolCount - 1) / 2) * symbolHeight;
// Place symbols directly at final position instead of starting above
symbol.y = finalY;
symbol.alpha = 1;
// Scale symbols to match spinning symbols
symbol.scaleX = 1.0;
symbol.scaleY = 1.0;
self.addChild(symbol);
self.symbols.push(symbol);
}
// Wait for the same duration as the original animation to maintain timing
LK.setTimeout(function () {
self.finalizeSpin();
}, 600 + (self.currentSymbolCount - 1) * 100);
};
// Finalize spin animation
self.finalizeSpin = function () {
// Reset reel container position and scale
tween(reelContainer, {
x: 0,
y: 0,
scaleY: 1.0,
scaleX: 1.0,
alpha: 1.0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isSpinning = false;
if (self.spinEndCallback) {
self.spinEndCallback();
self.spinEndCallback = null;
}
}
});
};
// Get all symbols in this reel
self.getSymbols = function () {
return self.symbols;
};
// Get symbol count for ways calculation
self.getSymbolCount = function () {
return self.currentSymbolCount;
};
// Check for winning combinations in this reel
self.checkForWins = function (targetSymbol, position) {
var winningSymbols = [];
for (var i = 0; i < self.symbols.length; i++) {
var symbol = self.symbols[i];
if (symbol.getSymbolValue() === targetSymbol || symbol.isWild) {
winningSymbols.push(symbol);
}
}
return winningSymbols;
};
// Mark symbols for cascade removal
self.markSymbolsForRemoval = function (symbolsToRemove) {
for (var i = 0; i < symbolsToRemove.length; i++) {
var symbol = symbolsToRemove[i];
symbol.markForWin();
}
};
// Initialize with symbols
self.generateRandomSymbolCount();
self.createSymbols();
return self;
});
var MegawaysSlotMachine = Container.expand(function () {
var self = Container.call(this);
self.reels = [];
self.isSpinning = false;
self.currentWays = 0;
self.cascadeCount = 0;
self.totalWinAmount = 0;
// Create 6 reels for Megaways
self.createReels = function () {
for (var i = 0; i < 6; i++) {
var reel = new MegawaysReel(i);
// Position reels horizontally with proper spacing
reel.x = (i - 2.5) * 200; // Center 6 reels
reel.y = 0;
self.addChild(reel);
self.reels.push(reel);
}
};
// Calculate total ways to win
self.calculateTotalWays = function () {
var symbolCounts = [];
for (var i = 0; i < self.reels.length; i++) {
symbolCounts.push(self.reels[i].getSymbolCount());
}
var ways = 1;
for (var i = 0; i < symbolCounts.length; i++) {
ways *= symbolCounts[i];
}
self.currentWays = ways;
return ways;
};
// Spin all reels with staggered timing
self.spinAllReels = function (onComplete) {
if (self.isSpinning) return;
self.isSpinning = true;
self.cascadeCount = 0;
self.totalWinAmount = 0;
var completedReels = 0;
var totalReels = self.reels.length;
// Calculate when each reel will stop spinning
var reelStopTimes = [];
for (var i = 0; i < self.reels.length; i++) {
var startDelay = i * 150; // When this reel starts spinning
var spinDuration = 1200 + i * 200; // How long this reel spins
var stopTime = startDelay + spinDuration; // When this reel stops
reelStopTimes.push(stopTime);
}
// Schedule Detencion sound for each reel when it stops
for (var i = 0; i < reelStopTimes.length; i++) {
(function (reelIndex, stopTime) {
LK.setTimeout(function () {
// Play Detencion sound when this specific reel stops
LK.getSound('Detencion').play();
}, stopTime);
})(i, reelStopTimes[i]);
}
// Spin each reel with increasing delay for realistic effect
for (var i = 0; i < self.reels.length; i++) {
(function (reelIndex) {
LK.setTimeout(function () {
// Play Rodillos sound only once when first reel starts spinning
if (reelIndex === 0) {
LK.getSound('Rodillos').play();
}
self.reels[reelIndex].spin(1200 + reelIndex * 200, function () {
completedReels++;
if (completedReels === totalReels) {
self.isSpinning = false;
self.calculateTotalWays();
if (onComplete) onComplete();
}
});
}, reelIndex * 150);
})(i);
}
};
// Check for winning combinations across all reels
self.checkForWins = function () {
var winningCombinations = [];
var symbolTypes = ['megawaysSymbolA', 'megawaysSymbolB', 'megawaysSymbolC', 'megawaysSymbolD', 'megawaysSymbolE', 'megawaysSymbolF'];
// Check each symbol type for consecutive matches from left
for (var s = 0; s < symbolTypes.length; s++) {
var symbolType = symbolTypes[s];
var consecutiveReels = 0;
var winningSymbols = [];
// Check from leftmost reel
for (var r = 0; r < self.reels.length; r++) {
var reelMatches = self.reels[r].checkForWins(symbolType, r);
if (reelMatches.length > 0) {
consecutiveReels++;
winningSymbols = winningSymbols.concat(reelMatches);
} else {
break; // Must be consecutive from left
}
}
// Need at least 4 consecutive reels for a win
if (consecutiveReels >= 4) {
winningCombinations.push({
symbolType: symbolType,
reelCount: consecutiveReels,
symbols: winningSymbols,
multiplier: self.getSymbolMultiplier(symbolType, consecutiveReels)
});
}
}
return winningCombinations;
};
// Get multiplier for symbol and reel count
self.getSymbolMultiplier = function (symbolType, reelCount) {
var baseMultipliers = {
'megawaysSymbolA': 54,
// Significantly increased to make rare appearances more exciting (was 30)
'megawaysSymbolB': 39,
// Increased to provide better variety when it appears (was 24)
'megawaysSymbolC': 26,
// Slightly increased to improve mid-tier rewards (was 18)
'megawaysSymbolD': 18,
// Slightly increased (was 12)
'megawaysSymbolE': 12,
// Same - balanced for frequency
'megawaysSymbolF': 8 // Same - maintains balance as most frequent symbol
};
var reelMultiplier = Math.pow(2, reelCount - 4); // 4 reels = 1x, 5 reels = 2x, 6 reels = 4x
var betFactor = currentBet / 25; // Scale rewards based on bet amount (25 is base bet)
var cascadeBonus = 1;
if (self.cascadeCount > 1) {
if (self.cascadeCount >= 15) {
// High cascades get moderate bonus with smoother curve
cascadeBonus = Math.pow(self.cascadeCount, 1.6); // Slightly reduced growth
} else if (self.cascadeCount >= 5) {
// Improved mid-range cascades - better rewards for x5-x14
cascadeBonus = Math.pow(self.cascadeCount, 1.8); // Better progression for mid-range
} else {
// Early cascades get better bonus
cascadeBonus = self.cascadeCount * 1.5 + 1; // Better early cascade rewards
}
}
var baseWin = Math.floor((baseMultipliers[symbolType] || 1) * reelMultiplier * betFactor * cascadeBonus);
// Improved guaranteed minimums with better mid-range coverage
if (self.cascadeCount >= 20) {
var guaranteedMinimum = currentBet * 20; // Reduced from 25x to prevent excessive long spins
baseWin = Math.max(baseWin, guaranteedMinimum);
} else if (self.cascadeCount >= 15) {
var guaranteedMinimum = currentBet * 15; // New tier for x15+ cascades
baseWin = Math.max(baseWin, guaranteedMinimum);
} else if (self.cascadeCount >= 10) {
var guaranteedMinimum = currentBet * 8; // New tier for x10+ cascades
baseWin = Math.max(baseWin, guaranteedMinimum);
} else if (self.cascadeCount >= 5) {
var guaranteedMinimum = currentBet * 4; // New tier for x5+ cascades to make them more exciting
baseWin = Math.max(baseWin, guaranteedMinimum);
}
return baseWin;
};
// Process winning combinations
self.processWins = function (winningCombinations, onComplete) {
if (winningCombinations.length === 0) {
if (onComplete) onComplete(0);
return;
}
var totalWin = 0;
// Calculate total win amount
for (var i = 0; i < winningCombinations.length; i++) {
var combo = winningCombinations[i];
totalWin += combo.multiplier;
// Mark symbols for removal
for (var j = 0; j < combo.symbols.length; j++) {
combo.symbols[j].markForWin();
}
}
self.totalWinAmount += totalWin;
// Animate win highlighting
LK.setTimeout(function () {
self.cascadeWinningSymbols(winningCombinations, function () {
if (onComplete) onComplete(totalWin);
});
}, 1000);
return totalWin;
};
// Cascade (remove) winning symbols and drop remaining ones
self.cascadeWinningSymbols = function (winningCombinations, onComplete) {
self.cascadeCount++;
var symbolsToRemove = [];
// Collect all winning symbols
for (var i = 0; i < winningCombinations.length; i++) {
symbolsToRemove = symbolsToRemove.concat(winningCombinations[i].symbols);
}
// Animate symbol removal
var removedCount = 0;
for (var i = 0; i < symbolsToRemove.length; i++) {
(function (symbol) {
symbol.explode(function () {
removedCount++;
if (removedCount === symbolsToRemove.length) {
// All symbols removed, now cascade remaining symbols down
self.cascadeRemainingSymbols(function () {
// Check for new wins after cascade
LK.setTimeout(function () {
var newWins = self.checkForWins();
if (newWins.length > 0) {
// More wins found, process them
self.processWins(newWins, onComplete);
} else {
// No more wins, cascade complete
if (onComplete) onComplete();
}
}, 300);
});
}
});
})(symbolsToRemove[i]);
}
};
// Drop remaining symbols and fill gaps
self.cascadeRemainingSymbols = function (onComplete) {
var cascadeComplete = 0;
var totalReels = self.reels.length;
for (var r = 0; r < self.reels.length; r++) {
(function (reelIndex) {
var reel = self.reels[reelIndex];
var remainingSymbols = [];
// Collect non-destroyed symbols
for (var i = 0; i < reel.symbols.length; i++) {
if (reel.symbols[i] && !reel.symbols[i].marked) {
remainingSymbols.push(reel.symbols[i]);
}
}
// Fill reel back to current symbol count
var newSymbolsNeeded = reel.currentSymbolCount - remainingSymbols.length;
// Pass cascade count to reel for weighted symbol selection
reel.cascadeCount = self.cascadeCount;
for (var n = 0; n < newSymbolsNeeded; n++) {
var symbolType = reel.getWeightedRandomSymbol();
var newSymbol = new MegawaysSymbol(symbolType, reel.symbolTypes.indexOf(symbolType));
newSymbol.y = -400 - n * 70; // Start above screen
reel.addChild(newSymbol);
remainingSymbols.unshift(newSymbol); // Add to beginning
}
// Update reel's symbols array
reel.symbols = remainingSymbols;
// Animate all symbols to their final positions
var symbolHeight = 105; // Height of each symbol with no gaps
for (var i = 0; i < remainingSymbols.length; i++) {
(function (symbol, index, finalReel) {
var targetY = (index - (reel.currentSymbolCount - 1) / 2) * symbolHeight;
// Scale new symbols to match existing ones
symbol.scaleX = 1;
symbol.scaleY = 1;
symbol.startFalling(targetY, function () {
if (index === remainingSymbols.length - 1) {
cascadeComplete++;
if (cascadeComplete === totalReels) {
if (onComplete) onComplete();
}
}
});
})(remainingSymbols[i], i, reelIndex);
}
})(r);
}
};
// Get current ways display text
self.getWaysText = function () {
return self.currentWays + ' WAYS';
};
// Initialize reels
self.createReels();
return self;
});
var MegawaysSymbol = Container.expand(function (symbolType, symbolIndex) {
var self = Container.call(this);
self.symbolType = symbolType || 'megawaysSymbolA';
self.symbolIndex = symbolIndex || 0;
self.isWild = symbolType === 'megawaysWild';
self.isScatter = symbolType === 'megawaysScatter';
self.marked = false;
self.falling = false;
// Symbol graphics
var symbolGraphic = self.attachAsset(self.symbolType, {
anchorX: 0.5,
anchorY: 0.5
});
// Ensure clean state - no tinting
symbolGraphic.tint = 0xFFFFFF;
// Symbol assets for identification instead of text
var symbolAssetNames = ['A', 'B', 'C', 'D', 'E', 'F', 'Wild', 'Scatter'];
var symbolAsset = LK.getAsset(self.isWild ? 'Wild' : self.isScatter ? 'Scatter' : symbolAssetNames[self.symbolIndex], {
anchorX: 0.5,
anchorY: 0.5
});
symbolGraphic.addChild(symbolAsset);
// Mark symbol for win combination
self.markForWin = function () {
if (self.marked) return;
if (self.falling) return; // Don't mark while falling during cascade
self.marked = true;
// Play Simbolo sound when marking winning symbol
LK.getSound('Simbolo').play();
tween(symbolGraphic, {
tint: 0xffff00,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
easing: tween.bounceOut
});
};
// Start falling animation for cascade
self.startFalling = function (targetY, onComplete) {
if (self.falling) return;
self.falling = true;
// Reset any win markings and tint when falling
self.marked = false;
tween.stop(symbolGraphic, {
tint: true,
scaleX: true,
scaleY: true
});
symbolGraphic.tint = 0xFFFFFF; // Reset to white
// Keep original scale instead of forcing 1.4 to prevent growth during cascade
symbolGraphic.scaleX = 1.0;
symbolGraphic.scaleY = 1.0;
tween(self, {
y: targetY
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
self.falling = false;
if (onComplete) onComplete();
}
});
};
// Explode and remove symbol
self.explode = function (onComplete) {
// Play Explosion sound when symbol explodes
LK.getSound('Explosion').play();
tween(symbolGraphic, {
scaleX: 0,
scaleY: 0,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.destroy();
if (onComplete) onComplete();
}
});
};
// Get symbol value for matching
self.getSymbolValue = function () {
if (self.isWild) return 'WILD';
if (self.isScatter) return 'SCATTER';
return self.symbolType;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0F4C3A
});
/****
* Game Code
****/
// Hide blinking text when leaving menu
if (spinHereText) {
spinHereText.destroy();
spinHereText = null;
}
if (spinHereTextTimer) {
LK.clearTimeout(spinHereTextTimer);
spinHereTextTimer = null;
}
if (spinHereBlinkTimer) {
LK.clearInterval(spinHereBlinkTimer);
spinHereBlinkTimer = null;
}
// Card display removed from menu
// Spades (Black Suit) - 13 cards
// Clubs (Black Suit) - 13 cards
// Diamonds (Red Suit) - 13 cards
// Hearts (Red Suit) - 13 cards
// Add background
// Luxury slot machine frame assets - "La TentaciΓ³n Dorada" styling
// Dark wood main frame
// Gold inner border
// Dark inlay
// Dark blue/black reels background
// Gold border around reels
// Luxury SPIN button
// Button border
// Luxury MENU button
// Corner decorations
var fondoM = LK.getAsset('FondoM', {
anchorX: 0.5,
anchorY: 0.5
});
fondoM.x = 1024;
fondoM.y = 1366;
game.addChild(fondoM);
// Add table background
var tableBackground = LK.getAsset('fondo', {
anchorX: 0.5,
anchorY: 0.5
});
tableBackground.x = 1024;
tableBackground.y = 1366;
tableBackground.alpha = 0;
game.addChild(tableBackground);
// Add blackjack background
var blackjackBackground = LK.getAsset('fondo', {
anchorX: 0.5,
anchorY: 0.5
});
blackjackBackground.x = 1024;
blackjackBackground.y = 1366;
blackjackBackground.alpha = 0;
game.addChild(blackjackBackground);
// Add slots background
var slotsBackground = LK.getAsset('FondoS', {
anchorX: 0.5,
anchorY: 0.5
});
slotsBackground.x = 1024;
slotsBackground.y = 1366;
slotsBackground.alpha = 0;
game.addChild(slotsBackground);
// Add tragamonedas asset first (lower z-index)
var tragamonedasAsset = LK.getAsset('tragamonedas', {
anchorX: 0.5,
anchorY: 0.5
});
tragamonedasAsset.x = 1024;
tragamonedasAsset.y = 1200; // Moved higher up to overlap with slot machine
tragamonedasAsset.alpha = 0; // Start hidden
game.addChild(tragamonedasAsset);
// Add Monedero asset in bottom left corner below tragamonedas
var monederoAsset = LK.getAsset('Monedero', {
anchorX: 0.5,
anchorY: 0.5
});
monederoAsset.x = 280; // Left side position (270 + 10 pixels to the right)
monederoAsset.y = 2590; // Below tragamonedas asset (2600 - 10 pixels up)
monederoAsset.alpha = 0; // Start hidden
game.addChild(monederoAsset);
// Add Monedero2 asset in bottom right corner at same height as Monedero
var monedero2Asset = LK.getAsset('Monedero2', {
anchorX: 0.5,
anchorY: 0.5
});
monedero2Asset.x = 1648; // Right side position moved 60 pixels left (1708 - 60)
monedero2Asset.y = 2590; // Same height as Monedero
monedero2Asset.alpha = 0; // Start hidden
game.addChild(monedero2Asset);
// Add mas asset to top right of Monedero
var masAsset = LK.getAsset('mas', {
anchorX: 0.5,
anchorY: 0.5
});
masAsset.x = 570; // Right side of Monedero moved 20 pixels right (550 + 20)
masAsset.y = 2510; // Above Monedero moved 60 pixels down (2450 + 60)
masAsset.alpha = 0; // Start hidden
game.addChild(masAsset);
// Add click handler for mas asset
masAsset.down = function (x, y, obj) {
if (gameMode !== 'slots') return;
if (currentBet * 2 <= playerMoney) {
currentBet *= 2;
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
}
};
// Add menos asset to bottom right of Monedero
var menosAsset = LK.getAsset('menos', {
anchorX: 0.5,
anchorY: 0.5
});
menosAsset.x = 570; // Right side of Monedero moved 20 pixels right (550 + 20)
menosAsset.y = 2680; // Below Monedero moved 10 pixels up (2690 - 10)
menosAsset.alpha = 0; // Start hidden
game.addChild(menosAsset);
// Add click handler for menos asset
menosAsset.down = function (x, y, obj) {
if (gameMode !== 'slots') return;
if (currentBet / 2 >= 25) {
currentBet = currentBet / 2;
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
}
};
// Add Megaways slot machine above tragamonedas (higher z-index)
var megawaysSlotMachine = game.addChild(new MegawaysSlotMachine());
megawaysSlotMachine.x = 954; // Moved right by 60 pixels (894 + 60)
megawaysSlotMachine.y = 1250; // Moved down by 200 pixels total (1050 + 200)
megawaysSlotMachine.scaleX = 1.6; // Scale by 1.6 times larger
megawaysSlotMachine.scaleY = 2.73; // Scale by 2.73 times larger (2.53 + 0.20 for additional 50px stretch)
megawaysSlotMachine.alpha = 0;
// Megaways display (hidden by default)
var waysDisplay = new Text2('117,649 WAYS', {
size: 48,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
waysDisplay.anchor.set(0.5, 0.5);
waysDisplay.x = 1024;
waysDisplay.y = 900;
waysDisplay.alpha = 0;
game.addChild(waysDisplay);
// Win amount display
var winAmountDisplay = new Text2('WIN: $0', {
size: 56,
fill: '#00FF00',
font: "'Arial Black', Arial, sans-serif"
});
winAmountDisplay.anchor.set(0.5, 0.5);
winAmountDisplay.x = 1648;
winAmountDisplay.y = 2590;
winAmountDisplay.alpha = 0;
game.addChild(winAmountDisplay);
// Disclaimer UI elements
// Use black background instead of warning asset
game.setBackgroundColor(0x000000);
var disclaimerTitle = new Text2('β οΈ IMPORTANT WARNING β οΈ', {
size: 126,
fill: '#FF0000',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerTitle.anchor.set(0.5, 0.5);
disclaimerTitle.x = 1024;
disclaimerTitle.y = 650;
disclaimerTitle.alpha = 1;
game.addChild(disclaimerTitle);
var disclaimerText1 = new Text2('β’ This game features a save system', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText1.anchor.set(0.5, 0.5);
disclaimerText1.x = 1024;
disclaimerText1.y = 950;
disclaimerText1.alpha = 1;
game.addChild(disclaimerText1);
var disclaimerText2 = new Text2('β’ If you run out of virtual money,', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText2.anchor.set(0.5, 0.5);
disclaimerText2.x = 1024;
disclaimerText2.y = 1060;
disclaimerText2.alpha = 1;
game.addChild(disclaimerText2);
var disclaimerText3 = new Text2('the only way to earn more is with the wheel', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText3.anchor.set(0.5, 0.5);
disclaimerText3.x = 1024;
disclaimerText3.y = 1170;
disclaimerText3.alpha = 1;
game.addChild(disclaimerText3);
var disclaimerText4 = new Text2('β’ This game is for entertainment only', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText4.anchor.set(0.5, 0.5);
disclaimerText4.x = 1024;
disclaimerText4.y = 1280;
disclaimerText4.alpha = 1;
game.addChild(disclaimerText4);
var disclaimerText5 = new Text2('β’ NO real money is involved', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText5.anchor.set(0.5, 0.5);
disclaimerText5.x = 1024;
disclaimerText5.y = 1390;
disclaimerText5.alpha = 1;
game.addChild(disclaimerText5);
var disclaimerText6 = new Text2('β’ Gambling can be addictive', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText6.anchor.set(0.5, 0.5);
disclaimerText6.x = 1024;
disclaimerText6.y = 1500;
disclaimerText6.alpha = 1;
game.addChild(disclaimerText6);
var disclaimerText7 = new Text2('β’ Real gambling can be harmful', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText7.anchor.set(0.5, 0.5);
disclaimerText7.x = 1024;
disclaimerText7.y = 1610;
disclaimerText7.alpha = 1;
game.addChild(disclaimerText7);
var disclaimerText8 = new Text2('β’ Please seek help if needed', {
size: 62,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
disclaimerText8.anchor.set(0.5, 0.5);
disclaimerText8.x = 1024;
disclaimerText8.y = 1720;
disclaimerText8.alpha = 1;
game.addChild(disclaimerText8);
var continueButton = game.addChild(new GameButton('I UNDERSTAND - CONTINUE', 400, 100));
continueButton.x = 1024;
continueButton.y = 2140;
continueButton.alpha = 1;
// Create larger invisible hit area for better touch responsiveness
var continueButtonHitArea = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
// 50% wider than original
height: 150,
// 50% taller than original
alpha: 0 // Invisible
});
continueButtonHitArea.x = 0;
continueButtonHitArea.y = 0;
continueButton.addChild(continueButtonHitArea);
// Make the hit area interactive and forward events to the button
continueButtonHitArea.interactive = true;
continueButtonHitArea.buttonMode = true;
continueButtonHitArea.down = function (x, y, obj) {
if (continueButton.down) continueButton.down(x, y, obj);
};
continueButtonHitArea.up = function (x, y, obj) {
if (continueButton.up) continueButton.up(x, y, obj);
};
// Cascade counter (hidden by default)
var cascadeDisplay = new Text2('', {
size: 84,
fill: '#FF6347',
font: "'Arial Black', Arial, sans-serif"
});
cascadeDisplay.anchor.set(0.5, 0.5);
cascadeDisplay.x = 1024;
cascadeDisplay.y = 1366;
cascadeDisplay.alpha = 0;
game.addChild(cascadeDisplay);
// Cascade animation variables
var lastCascadeCount = 0;
var cascadeAnimationDisplay = null;
// Game state
var playerMoney = storage.playerMoney || 1000;
var currentBet = 0;
var gameMode = 'disclaimer'; // 'disclaimer', 'menu', 'blackjack', 'slots'
var wheelScreenOpen = false; // Track if wheel screen is currently open
var freeSpins = storage.freeSpins || 0; // Track free spins available
var isBlackjack = false; // Track if current hand is a blackjack
// Blinking text variables
var spinHereText = null;
var spinHereTextTimer = null;
var spinHereBlinkTimer = null;
// SpinI blinking variables
var spinITimer = null;
var spinIBlinkTimer = null;
var spinIRecurringTimer = null;
var spinISoundToggle = false; // Track when to play sound (alternating)
// Initialize achievement system
var achievementSystem = new AchievementSystem();
// Achievement tracking variables
var consecutiveWins = storage.consecutiveWins || 0;
var confirmedHighBet = false;
// Chip system
var chips = [];
var chipContainer = game.addChild(new Container());
chipContainer.x = 1004; // Move 20 pixels left (1024 - 20)
chipContainer.y = 2300; // Position below player cards
chipContainer.alpha = 0;
var moneyAfterBet = 0;
var moneyAfterSpin = 0;
var deck = [];
var playerCards = [];
var dealerCards = [];
var gamePhase = 'betting'; // 'betting', 'dealing', 'playing', 'dealer', 'finished'
var handInProgress = false; // Track if a hand is currently in progress
var lastWaysCount = 0;
var waysAnimationDisplay = null;
// Total bet display for slots (positioned in center of Monedero)
var totalBetDisplay = new Text2('$' + currentBet, {
size: 108,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
totalBetDisplay.anchor.set(0.5, 0.5);
totalBetDisplay.x = 280; // Same x position as Monedero
totalBetDisplay.y = 2590; // Same y position as Monedero
totalBetDisplay.alpha = 0; // Start hidden
game.addChild(totalBetDisplay);
// UI Elements
var moneyDisplay = new Text2('$1000', {
size: 112,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
moneyDisplay.anchor.set(0.5, 0.5);
moneyDisplay.x = 974;
moneyDisplay.y = 2596; // Position to overlap BalanceB asset (moved 30 pixels down)
moneyDisplay.alpha = 0;
game.addChild(moneyDisplay);
// Add Remove asset positioned above TotalA asset
var removeAsset = LK.getAsset('Remove', {
anchorX: 0.5,
anchorY: 0.5
});
removeAsset.x = 1724; // Same x position as totalA asset
removeAsset.y = 2375; // Positioned above totalA asset (2475 - 100)
removeAsset.alpha = 0;
game.addChild(removeAsset);
// Add click handler for Remove button
removeAsset.down = function (x, y, obj) {
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'betting') return;
// Reset bet to 0
currentBet = 0;
updateChipSelection();
LK.getSound('Ficha_2').play();
};
// Add TotalA asset at same horizontal height as chips and same vertical height as Home
var totalAAsset = LK.getAsset('TotalA', {
anchorX: 0.5,
anchorY: 0.5
});
totalAAsset.x = 1724; // Move 200 pixels right from previous position (1524 + 200)
totalAAsset.y = 2550; // Move 150 pixels down from previous position (2400 + 150)
totalAAsset.alpha = 0;
game.addChild(totalAAsset);
// Add bet value display positioned at center of TotalA asset
var betValueDisplay = new Text2('$' + currentBet, {
size: 83,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
betValueDisplay.anchor.set(0.5, 0.5);
betValueDisplay.x = 1814; // Move 10 pixels left (1824 - 10)
betValueDisplay.y = 2545; // Move 5 pixels down (2540 + 5)
betValueDisplay.alpha = 0;
game.addChild(betValueDisplay);
// Add BalanceB asset positioned in the middle of money display
var balanceBAsset = LK.getAsset('BalanceB', {
anchorX: 0.5,
anchorY: 0.5
});
balanceBAsset.x = 974; // Same x position as money display
balanceBAsset.y = 2566; // Moved 20 pixels down (2546 + 20)
balanceBAsset.alpha = 0;
game.addChild(balanceBAsset);
// Add BalanceBJ asset positioned at same height as TotalA but on left side
var balanceBJAsset = LK.getAsset('BalanceBJ', {
anchorX: 0.5,
anchorY: 0.5
});
balanceBJAsset.x = 324; // Left side position (mirroring TotalA position)
balanceBJAsset.y = 2500; // Moved 30 pixels up (2530 - 30)
balanceBJAsset.alpha = 0;
game.addChild(balanceBJAsset);
// Add Apuesta asset below deal button in blackjack mode
var apuestaAsset = LK.getAsset('Apuesta', {
anchorX: 0.5,
anchorY: 0.5
});
apuestaAsset.x = 1024; // Same x position as deal button
apuestaAsset.y = 1650; // Position below deal button (1450 + 200)
apuestaAsset.alpha = 0;
game.addChild(apuestaAsset);
// Add player money display in center of BalanceBJ asset
var playerMoneyDisplay = new Text2('$' + playerMoney, {
size: 75,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
playerMoneyDisplay.anchor.set(0.5, 0.5);
playerMoneyDisplay.x = 324; // Same x position as BalanceBJ asset
playerMoneyDisplay.y = 2530; // Moved 10 pixels up (2540 - 10)
playerMoneyDisplay.alpha = 0;
game.addChild(playerMoneyDisplay);
// Move money display after BalanceB so it renders on top
game.removeChild(moneyDisplay);
game.addChild(moneyDisplay);
// Create message display for game feedback
var messageDisplay = new Text2('', {
size: 56,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
messageDisplay.anchor.set(0.5, 0.5);
messageDisplay.x = 1024;
messageDisplay.y = 800;
messageDisplay.alpha = 0;
game.addChild(messageDisplay);
// Add welcome asset to main menu
var welcomeAsset = LK.getAsset('Welcome', {
anchorX: 0.5,
anchorY: 0.5
});
welcomeAsset.x = 1024;
welcomeAsset.y = 400; // 700 pixels above blackjack button (1100 - 700)
game.addChild(welcomeAsset);
// Menu buttons
var blackjackButton = game.addChild(new GameButton('BLACKJACK', 300, 100));
blackjackButton.x = 1024;
blackjackButton.y = 1100;
// Replace the default button background with BlackJ asset
var blackjackAsset = LK.getAsset('BlackJ', {
anchorX: 0.5,
anchorY: 0.5
});
blackjackButton.removeChild(blackjackButton.children[1]); // Remove default background
blackjackButton.addChildAt(blackjackAsset, 1); // Add new asset as background
var slotsButton = game.addChild(new GameButton('SLOT MACHINE', 300, 100));
slotsButton.x = 1004;
slotsButton.y = 1750;
// Replace the default button background with MaquinaB asset
var slotAsset = LK.getAsset('MaquinaB', {
anchorX: 0.5,
anchorY: 0.5,
width: 550,
height: 550
});
slotsButton.removeChild(slotsButton.children[1]); // Remove default background
slotsButton.addChildAt(slotAsset, 1); // Add new asset as background
// Blackjack UI
var hitButton = LK.getAsset('hit', {
anchorX: 0.5,
anchorY: 0.5
});
hitButton.x = 770; // Move 100 pixels right (670 + 100)
hitButton.y = 2400;
hitButton.alpha = 0;
game.addChild(hitButton);
var standButton = LK.getAsset('stand', {
anchorX: 0.5,
anchorY: 0.5
});
standButton.x = 1000; // Move 100 pixels right (900 + 100)
standButton.y = 2400;
standButton.alpha = 0;
standButton.interactive = true;
standButton.buttonMode = true;
game.addChild(standButton);
var doubleButton = LK.getAsset('double', {
anchorX: 0.5,
anchorY: 0.5
});
doubleButton.x = 1230; // Move 100 pixels right (1130 + 100)
doubleButton.y = 2400;
doubleButton.alpha = 0;
game.addChild(doubleButton);
// Deal button for blackjack
var dealButton = LK.getAsset('DealB', {
anchorX: 0.5,
anchorY: 0.5
});
dealButton.x = 1024; // Center of table
dealButton.y = 1300; // Move 500 pixels up from previous position (1800 - 500)
dealButton.alpha = 0;
game.addChild(dealButton);
// Slots UI (classic slots removed - using Megaways only)
var spinButton = game.addChild(new GameButton('SPIN $25', 200, 80));
spinButton.x = 974;
spinButton.y = 2230;
spinButton.alpha = 0;
// Replace the default button background with circular assets
spinButton.removeChild(spinButton.children[0]); // Remove shadow
spinButton.removeChild(spinButton.children[0]); // Remove background (index shifts after first removal)
var circularButton = LK.getAsset('circularSpinButton', {
anchorX: 0.5,
anchorY: 0.5
});
spinButton.addChildAt(circularButton, 0);
// Create money difference display in center of Monedero2 asset
var moneyDifferenceDisplay = new Text2('$0', {
size: 79,
fill: '#00FF00',
font: "'Arial Black', Arial, sans-serif"
});
moneyDifferenceDisplay.anchor.set(0.5, 0.5);
moneyDifferenceDisplay.x = 1648; // Same x position as Monedero2 asset
moneyDifferenceDisplay.y = 2590; // Same y position as Monedero2 asset
moneyDifferenceDisplay.alpha = 0;
// Add to game to position in center of Monedero2
game.addChild(moneyDifferenceDisplay);
// Create new Home button with Home asset in upper right corner
var homeButton = game.addChild(new GameButton('', 100, 100));
homeButton.x = 1850; // Upper right corner position (2048 - 198 to avoid top left menu area)
homeButton.y = 200; // Near top of screen but below status bar
homeButton.alpha = 0;
// Replace the default button background with Home asset
homeButton.removeChild(homeButton.children[0]); // Remove shadow
homeButton.removeChild(homeButton.children[0]); // Remove background (index shifts after first removal)
var homeAsset = LK.getAsset('Home', {
anchorX: 0.5,
anchorY: 0.5
});
homeButton.addChildAt(homeAsset, 0);
// Create Logros button in bottom left of main menu
var logrosButton = game.addChild(new GameButton('', 100, 100));
logrosButton.x = 200; // Bottom left corner position
logrosButton.y = 2500; // Bottom of screen
logrosButton.alpha = 0;
// Replace the default button background with Logros asset
logrosButton.removeChild(logrosButton.children[0]); // Remove shadow
logrosButton.removeChild(logrosButton.children[0]); // Remove background (index shifts after first removal)
var logrosAsset = LK.getAsset('Logros', {
anchorX: 0.5,
anchorY: 0.5
});
logrosButton.addChildAt(logrosAsset, 0);
// Create RuedaP button at Sugerencia position
var ruedaPButton = game.addChild(new GameButton('', 100, 100));
ruedaPButton.x = 1848; // Same position as Sugerencia asset
ruedaPButton.y = 2500; // Same position as Sugerencia asset
ruedaPButton.alpha = 0;
// Replace the default button background with RuedaP asset
ruedaPButton.removeChild(ruedaPButton.children[0]); // Remove shadow
ruedaPButton.removeChild(ruedaPButton.children[0]); // Remove background (index shifts after first removal)
var ruedaPAsset = LK.getAsset('RuedaP', {
anchorX: 0.5,
anchorY: 0.5
});
ruedaPButton.addChildAt(ruedaPAsset, 0);
// Declare wheelTimerDisplay variable
var wheelTimerDisplay;
// Create wheel timer display above RuedaP button
wheelTimerDisplay = new Text2('', {
size: 48,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
wheelTimerDisplay.anchor.set(0.5, 0.5);
wheelTimerDisplay.x = 1848; // Same x position as RuedaP button
wheelTimerDisplay.y = 2300; // 100 pixels above RuedaP button (moved up 100px from 2400)
wheelTimerDisplay.alpha = 0;
game.addChild(wheelTimerDisplay);
// Create Statistics button in top right corner
var statisticsButton = game.addChild(new GameButton('', 100, 100));
statisticsButton.x = 1850; // Top right position (same as home button x)
statisticsButton.y = 450; // Below home button (200 + 150 + 100)
statisticsButton.alpha = 0;
// Replace the default button background with Estadisticas asset
statisticsButton.removeChild(statisticsButton.children[0]); // Remove shadow
statisticsButton.removeChild(statisticsButton.children[0]); // Remove background (index shifts after first removal)
var estadisticasAsset = LK.getAsset('Estadisticas', {
anchorX: 0.5,
anchorY: 0.5
});
statisticsButton.addChildAt(estadisticasAsset, 0);
// Create SpinI button to the left of RuedaP
var spinIButton = game.addChild(new GameButton('', 100, 100));
spinIButton.x = 1488; // Moved 40 pixels to the right (1448 + 40)
spinIButton.y = 2500; // Same height as RuedaP
spinIButton.alpha = 0;
// Replace the default button background with SpinI asset
spinIButton.removeChild(spinIButton.children[0]); // Remove shadow
spinIButton.removeChild(spinIButton.children[0]); // Remove background (index shifts after first removal)
var spinIAsset = LK.getAsset('SpinI', {
anchorX: 0.5,
anchorY: 0.5
});
spinIButton.addChildAt(spinIAsset, 0);
// Add deck and hands
var gameDeck = game.addChild(new Deck());
gameDeck.x = 200;
gameDeck.y = 1366;
gameDeck.alpha = 0;
// Add animated hands for dealing animations
var dealerAnimatedHand = game.addChild(new AnimatedHand(true));
dealerAnimatedHand.x = 300;
dealerAnimatedHand.y = 600;
dealerAnimatedHand.alpha = 0;
var playerAnimatedHand = game.addChild(new AnimatedHand(false));
playerAnimatedHand.x = 300;
playerAnimatedHand.y = 2000;
playerAnimatedHand.alpha = 0;
// Score displays
var playerScoreText = new Text2('Player: 0', {
size: 36,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
playerScoreText.anchor.set(0.5, 0.5);
playerScoreText.x = 1024;
playerScoreText.y = 1850;
playerScoreText.alpha = 0;
game.addChild(playerScoreText);
var dealerScoreText = new Text2('Dealer: 0', {
size: 36,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
dealerScoreText.anchor.set(0.5, 0.5);
dealerScoreText.x = 1024;
dealerScoreText.y = 750;
dealerScoreText.alpha = 0;
game.addChild(dealerScoreText);
// Create betting chips
function createChips() {
// Clear existing chips
for (var i = 0; i < chips.length; i++) {
chips[i].destroy();
}
chips = [];
var chipValues = [1, 5, 10, 25, 100, 500];
for (var i = 0; i < chipValues.length; i++) {
var chip = new Chip(chipValues[i]);
chip.x = (i - 2.5) * 120; // Spread chips horizontally with 20 more pixels separation
chip.y = 300; // Move chips 300 pixels down
chipContainer.addChild(chip);
chips.push(chip);
}
updateChipSelection();
}
function updateChipSelection() {
// Update chip availability based on player money
for (var i = 0; i < chips.length; i++) {
chips[i].setEnabled(playerMoney >= chips[i].value);
}
// Update bet value display at center of TotalA asset
betValueDisplay.setText('$' + currentBet);
// Update deal button state based on bet amount - only show once per hand
if (gameMode === 'blackjack' && !handInProgress) {
if (currentBet === 0) {
// Hide deal button when bet is zero
tween(dealButton, {
alpha: 0
}, {
duration: 200
});
// Hide remove button when bet is zero
tween(removeAsset, {
alpha: 0
}, {
duration: 200
});
} else {
// Show deal button when bet is greater than zero and no hand in progress
tween(dealButton, {
alpha: 1
}, {
duration: 200
});
// Show remove button when bet is greater than zero and no hand in progress
tween(removeAsset, {
alpha: 1
}, {
duration: 200
});
}
}
}
// Button event handlers
blackjackButton.up = function () {
if (gameMode !== 'menu') return;
if (!blackjackButton.enabled) return;
switchToBlackjack();
};
slotsButton.up = function () {
if (gameMode !== 'menu') return;
if (!slotsButton.enabled) return;
switchToSlots();
};
hitButton.down = function (x, y, obj) {
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'playing') return;
playerHit();
};
standButton.down = function (x, y, obj) {
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'playing') return;
// Don't call playerStand() on down event to prevent double calls
LK.getSound('buttonClick').play();
};
standButton.up = function (x, y, obj) {
// Stand button up handler - only call playerStand here
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'playing') return;
// Only trigger if we haven't already processed this action
if (gamePhase === 'playing') {
playerStand();
}
};
doubleButton.down = function (x, y, obj) {
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'playing') return;
if (playerMoney < currentBet) return;
playerDouble();
};
homeButton.up = function () {
if (!homeButton.enabled) return;
// Prevent leaving blackjack if hand is in progress
if (gameMode === 'blackjack' && handInProgress) return;
// Prevent leaving slots if spin is in progress
if (gameMode === 'slots' && slotsSpinInProgress) return;
switchToMenu();
};
logrosButton.up = function () {
if (gameMode !== 'menu') return;
if (!logrosButton.enabled) return;
showAchievementsScreen();
};
ruedaPButton.up = function () {
if (gameMode !== 'menu') return;
if (!ruedaPButton.enabled) return;
if (wheelScreenOpen) return; // Prevent re-entry if wheel is already open
if (!isWheelAvailable()) return; // Prevent opening if wheel is on cooldown
showWheelScreen();
};
statisticsButton.up = function () {
if (gameMode !== 'menu') return;
if (!statisticsButton.enabled) return;
showStatisticsScreen();
};
// SpinI button has no functionality - purely aesthetic
continueButton.up = function () {
if (gameMode !== 'disclaimer') return;
if (!continueButton.enabled) return;
switchToMenu();
};
dealButton.down = function (x, y, obj) {
if (gameMode !== 'blackjack') return;
if (gamePhase !== 'betting') return;
if (currentBet === 0) return; // Can't deal with zero bet
// Hide deal button immediately when pressed
dealButton.alpha = 0;
startNewBlackjackHand();
};
spinButton.up = function () {
if (gameMode !== 'slots') return;
if (!spinButton.enabled) return;
spinSlots();
};
// Game functions
function updateMoneyDisplay() {
moneyDisplay.setText('$' + playerMoney);
playerMoneyDisplay.setText('$' + playerMoney);
storage.playerMoney = playerMoney;
updateMoneyDifferenceDisplay();
achievementSystem.checkAchievement('reach10k', playerMoney);
// Update chip availability if in blackjack mode
if (gameMode === 'blackjack' && chips.length > 0) {
updateChipSelection();
}
// Reset bet to 25 if current bet exceeds player money and we're in slots mode
if (gameMode === 'slots' && currentBet > playerMoney) {
currentBet = 25;
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
spinButton.setEnabled(playerMoney >= currentBet);
}
// Reset bet in blackjack if current bet exceeds player money
if (gameMode === 'blackjack' && currentBet > playerMoney) {
// Find highest affordable chip value
var affordableChips = [1, 5, 10, 25, 100, 500].filter(function (value) {
return value <= playerMoney;
});
if (affordableChips.length > 0) {
currentBet = affordableChips[affordableChips.length - 1];
} else {
currentBet = 1;
}
updateChipSelection();
}
if (playerMoney >= 1000000) {
LK.showYouWin();
}
}
function updateMoneyDifferenceDisplay() {
var difference = moneyAfterSpin - moneyAfterBet;
moneyDifferenceDisplay.setText('$' + difference);
// Clear any existing spin here text
if (spinHereText) {
spinHereText.destroy();
spinHereText = null;
}
if (spinHereTextTimer) {
LK.clearTimeout(spinHereTextTimer);
spinHereTextTimer = null;
}
if (spinHereBlinkTimer) {
LK.clearInterval(spinHereBlinkTimer);
spinHereBlinkTimer = null;
}
// Create blinking "spin here" text after 2 seconds in main menu
spinHereTextTimer = LK.setTimeout(function () {
if (gameMode !== 'menu') return; // Only show if still in menu
// Create "spin here" text
spinHereText = new Text2('SPIN HERE', {
size: 48,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
spinHereText.anchor.set(0.5, 0.5);
spinHereText.x = 1848;
spinHereText.y = 2350; // Position above RuedaP button at new location (2500 - 150)
spinHereText.alpha = 1;
game.addChild(spinHereText);
// Make it blink
var blinkVisible = true;
spinHereBlinkTimer = LK.setInterval(function () {
if (!spinHereText) return;
blinkVisible = !blinkVisible;
tween(spinHereText, {
alpha: blinkVisible ? 1 : 0.3
}, {
duration: 500,
easing: tween.easeInOut
});
}, 600);
}, 2000);
// Clear any existing SpinI timers when entering menu
if (spinITimer) {
LK.clearTimeout(spinITimer);
spinITimer = null;
}
if (spinIBlinkTimer) {
LK.clearInterval(spinIBlinkTimer);
spinIBlinkTimer = null;
}
// Card display removed from menu
}
function createDeck() {
deck = [];
var suits = ['hearts', 'diamonds', 'clubs', 'spades'];
for (var s = 0; s < suits.length; s++) {
for (var v = 1; v <= 13; v++) {
deck.push({
suit: suits[s],
value: v
});
}
}
// Shuffle deck
for (var i = deck.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
function dealCard(isDealer, callback) {
if (deck.length === 0) createDeck();
var cardData = deck.pop();
var card = isDealer ? new DealerCard(cardData.suit, cardData.value) : new Card(cardData.suit, cardData.value);
var targetX, targetY;
if (isDealer) {
dealerCards.push(card);
targetX = 930 + (dealerCards.length - 1) * 240; // Move dealer cards 20 pixels left (950 - 20)
targetY = 500;
} else {
playerCards.push(card);
targetX = 850 + (playerCards.length - 1) * 280; // Move player cards 50 pixels right (800 + 50)
targetY = 2100;
}
card.x = targetX;
card.y = targetY;
card.alpha = 0;
game.addChild(card);
// Use animated hand for dealing
var animatedHand = isDealer ? dealerAnimatedHand : playerAnimatedHand;
if (isDealer) {
animatedHand.dealCardFaceDown(targetX, targetY, function () {
tween(card, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {
card.flip();
if (callback) callback();
}
});
});
} else {
animatedHand.dealCardToPlayer(targetX, targetY, function () {
tween(card, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {
card.flip();
if (callback) callback();
}
});
});
}
return card;
}
function calculateHandValue(cards) {
var value = 0;
var aces = 0;
for (var i = 0; i < cards.length; i++) {
var cardValue = cards[i].getBlackjackValue();
if (cardValue === 11) aces++;
value += cardValue;
}
// Adjust for aces
while (value > 21 && aces > 0) {
value -= 10;
aces--;
}
return value;
}
function updateScoreDisplays() {
var playerScore = calculateHandValue(playerCards);
var dealerScore = calculateHandValue(dealerCards);
playerScoreText.setText('Player: ' + playerScore);
if (dealerCards.length > 0 && dealerCards[0].faceUp) {
dealerScoreText.setText('Dealer: ' + dealerScore);
} else if (dealerCards.length > 1) {
var visibleScore = dealerCards[1].getBlackjackValue();
dealerScoreText.setText('Dealer: ' + visibleScore + ' + ?');
}
}
function crossFadeTransition(hideElements, showElements, callback) {
var fadeOutComplete = 0;
var totalFadeOut = hideElements.length;
// Fade out old elements
for (var i = 0; i < hideElements.length; i++) {
tween(hideElements[i], {
alpha: 0
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
fadeOutComplete++;
if (fadeOutComplete === totalFadeOut) {
// Start fading in new elements
for (var j = 0; j < showElements.length; j++) {
tween(showElements[j], {
alpha: showElements[j].targetAlpha || 1
}, {
duration: 400,
delay: j * 50,
easing: tween.easeInOut
});
}
if (callback) callback();
}
}
});
}
}
function switchToMenu() {
gameMode = 'menu';
// Set background to match fondoM to prevent green strip
game.setBackgroundColor(0x000000);
// Play random crupier menu sound on first entry to menu
if (isFirstMenuEntry) {
var menuSounds = ['Cuprier_Menu_1', 'Cuprier_Menu_2', 'Cuprier_Menu_3'];
var randomSound = menuSounds[Math.floor(Math.random() * menuSounds.length)];
LK.getSound(randomSound).play();
isFirstMenuEntry = false; // Set to false after first play
}
// Re-enable buttons when entering menu (they were disabled during disclaimer)
blackjackButton.setEnabled(true);
slotsButton.setEnabled(true);
logrosButton.setEnabled(true);
ruedaPButton.setEnabled(true);
spinIButton.setEnabled(true);
statisticsButton.setEnabled(true);
// Clear SpinI timers when switching modes
if (spinITimer) {
LK.clearTimeout(spinITimer);
spinITimer = null;
}
if (spinIBlinkTimer) {
LK.clearInterval(spinIBlinkTimer);
spinIBlinkTimer = null;
}
// Start SpinI visibility timer - show SpinI after 3 seconds in menu (only if wheel timer is not running)
spinITimer = LK.setTimeout(function () {
if (gameMode !== 'menu') return; // Only show if still in menu
// Skip SpinI verification when wheel timer is active
if (wheelCooldownTimer) return; // Don't show SpinI if wheel timer is running
// Show SpinI button first
spinIButton.alpha = 1; // Make button visible immediately
// Reset sound toggle when starting new animation sequence
spinISoundToggle = false;
// Start continuous alpha alternation between 1 and 0 every second
function alternateAlpha() {
tween(spinIAsset, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
tween(spinIAsset, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// Toggle sound - play only every other time
spinISoundToggle = !spinISoundToggle;
if (spinISoundToggle && gameMode === 'menu') {
LK.getSound('SpinHere').play();
}
alternateAlpha();
}
});
}
});
}
alternateAlpha();
}, 3000);
// Add recurring check every 3 seconds to ensure SpinI is visible in menu
spinIRecurringTimer = LK.setInterval(function () {
if (gameMode !== 'menu') return; // Only check if in menu
// Skip SpinI verification when wheel timer is active
if (wheelCooldownTimer) return; // Don't restart SpinI if wheel timer is running
if (spinIButton.alpha === 0 || spinIAsset.alpha === 0) {
// Restart the blinking animation
var _alternateAlpha = function alternateAlpha() {
tween(spinIAsset, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
tween(spinIAsset, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// Toggle sound - play only every other time
spinISoundToggle = !spinISoundToggle;
if (spinISoundToggle && gameMode === 'menu') {
LK.getSound('SpinHere').play();
}
_alternateAlpha();
}
});
}
});
};
// SpinI is not visible, make it visible and restart animation
spinIButton.alpha = 1;
spinIAsset.alpha = 1;
// Reset sound toggle when restarting animation
spinISoundToggle = false;
_alternateAlpha();
} else {
// SpinI is visible, stop the recurring timer
LK.clearInterval(spinIRecurringTimer);
spinIRecurringTimer = null;
}
}, 3000);
// Disable buttons from other game modes
hitButton.interactive = false;
hitButton.buttonMode = false;
standButton.interactive = false;
standButton.buttonMode = false;
doubleButton.interactive = false;
doubleButton.buttonMode = false;
dealButton.interactive = false;
dealButton.buttonMode = false;
spinButton.setEnabled(false);
for (var i = 0; i < chips.length; i++) {
if (chips[i] && chips[i].setEnabled) {
chips[i].setEnabled(false);
}
}
masAsset.interactive = false;
masAsset.buttonMode = false;
menosAsset.interactive = false;
menosAsset.buttonMode = false;
removeAsset.interactive = false;
removeAsset.buttonMode = false;
// Stop any currently playing music and play Menu music
LK.stopMusic();
LK.playMusic('Menu');
tween(disclaimerTitle, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText1, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText2, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText3, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText4, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText5, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText6, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText7, {
alpha: 0
}, {
duration: 300
});
tween(disclaimerText8, {
alpha: 0
}, {
duration: 300
});
tween(continueButton, {
alpha: 0
}, {
duration: 300
});
// Hide all game elements
tween(hitButton, {
alpha: 0
}, {
duration: 300
});
tween(standButton, {
alpha: 0
}, {
duration: 300
});
tween(doubleButton, {
alpha: 0
}, {
duration: 300
});
tween(playerScoreText, {
alpha: 0
}, {
duration: 300
});
tween(dealerScoreText, {
alpha: 0
}, {
duration: 300
});
// Classic slot reels removed (using Megaways only)
tween(spinButton, {
alpha: 0
}, {
duration: 300
});
tween(gameDeck, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
// Stop deck animation when leaving blackjack mode
if (gameDeck.stopDeckAnimation) {
gameDeck.stopDeckAnimation();
}
}
});
tween(dealerAnimatedHand, {
alpha: 0
}, {
duration: 300
});
tween(playerAnimatedHand, {
alpha: 0
}, {
duration: 300
});
// Show main menu background
tween(fondoM, {
alpha: 1
}, {
duration: 300
});
// Show menu buttons
tween(blackjackButton, {
alpha: 1
}, {
duration: 300
});
tween(slotsButton, {
alpha: 1
}, {
duration: 300
});
tween(welcomeAsset, {
alpha: 1
}, {
duration: 300
});
// Show new menu buttons
tween(logrosButton, {
alpha: 1
}, {
duration: 300
});
tween(ruedaPButton, {
alpha: 1
}, {
duration: 300
});
tween(statisticsButton, {
alpha: 1
}, {
duration: 300
});
// Show wheel timer display
tween(wheelTimerDisplay, {
alpha: 1
}, {
duration: 300
});
// Start wheel cooldown timer when entering menu
startWheelCooldownTimer();
// SpinI button will be shown after 3 seconds via timer
spinIButton.alpha = 0; // Keep hidden initially
// Card display removed from menu
// Hide blackjack background
tween(blackjackBackground, {
alpha: 0
}, {
duration: 300
});
// Hide table background
tween(tableBackground, {
alpha: 0
}, {
duration: 300
});
// Hide slots background
tween(slotsBackground, {
alpha: 0
}, {
duration: 300
});
// Hide tragamonedas asset in menu mode
tween(tragamonedasAsset, {
alpha: 0
}, {
duration: 300
});
// Hide Monedero asset in menu mode
tween(monederoAsset, {
alpha: 0
}, {
duration: 300
});
// Hide Monedero2 asset in menu mode
tween(monedero2Asset, {
alpha: 0
}, {
duration: 300
});
// Hide total bet display in menu mode
tween(totalBetDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide mas asset in menu mode
tween(masAsset, {
alpha: 0
}, {
duration: 300
});
// Hide menos asset in menu mode
tween(menosAsset, {
alpha: 0
}, {
duration: 300
});
// Hide Megaways slot machine
// Show Home button in blackjack mode
tween(homeButton, {
alpha: 1
}, {
duration: 300
});
tween(megawaysSlotMachine, {
alpha: 0
}, {
duration: 300
});
// Hide Megaways displays
tween(waysDisplay, {
alpha: 0
}, {
duration: 300
});
tween(winAmountDisplay, {
alpha: 0
}, {
duration: 300
});
tween(cascadeDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide win amount display in menu mode
tween(winAmountDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide ways animation if showing
if (waysAnimationDisplay) {
tween(waysAnimationDisplay, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (waysAnimationDisplay) {
waysAnimationDisplay.destroy();
waysAnimationDisplay = null;
}
}
});
}
// Hide cascade animation if showing
if (cascadeAnimationDisplay) {
tween(cascadeAnimationDisplay, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
if (cascadeAnimationDisplay) {
cascadeAnimationDisplay.destroy();
cascadeAnimationDisplay = null;
}
}
});
}
// Hide money display in menu mode
tween(moneyDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide BalanceB asset in menu mode
tween(balanceBAsset, {
alpha: 0
}, {
duration: 300
});
// Clear cards
// Hide money difference display in menu mode
tween(moneyDifferenceDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide chips in menu mode
tween(chipContainer, {
alpha: 0
}, {
duration: 300
});
// Hide Home button in menu mode
tween(homeButton, {
alpha: 0
}, {
duration: 300
});
// Hide deal button in menu mode
tween(dealButton, {
alpha: 0
}, {
duration: 300
});
// Hide Remove asset in menu mode
tween(removeAsset, {
alpha: 0
}, {
duration: 300
});
// Hide TotalA asset in menu mode
tween(totalAAsset, {
alpha: 0
}, {
duration: 300
});
// Hide bet value display in menu mode
tween(betValueDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide BalanceBJ asset in menu mode
tween(balanceBJAsset, {
alpha: 0
}, {
duration: 300
});
// Hide player money display in menu mode
tween(playerMoneyDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide Apuesta asset in menu mode
tween(apuestaAsset, {
alpha: 0
}, {
duration: 300
});
clearTable();
}
function switchToBlackjack() {
gameMode = 'blackjack';
gamePhase = 'betting';
// Reset bet to 0 when switching to blackjack
currentBet = 0;
// Stop any currently playing music and play BJ music
LK.stopMusic();
LK.playMusic('BJ');
// Play random croupier BlackJack greeting sound
var bjSounds = ['Cuprier_BJ_1', 'Cuprier_BJ_2', 'Cuprier_BJ_3'];
var randomBJSound = bjSounds[Math.floor(Math.random() * bjSounds.length)];
LK.getSound(randomBJSound).play();
// Hide menu buttons
tween(blackjackButton, {
alpha: 0
}, {
duration: 300
});
tween(slotsButton, {
alpha: 0
}, {
duration: 300
});
tween(welcomeAsset, {
alpha: 0
}, {
duration: 300
});
// Hide new menu buttons
tween(logrosButton, {
alpha: 0
}, {
duration: 300
});
tween(ruedaPButton, {
alpha: 0
}, {
duration: 300
});
tween(statisticsButton, {
alpha: 0
}, {
duration: 300
});
tween(spinIButton, {
alpha: 0
}, {
duration: 300
});
// Hide wheel timer display in blackjack mode
tween(wheelTimerDisplay, {
alpha: 0
}, {
duration: 300
});
// Stop wheel cooldown timer when leaving menu
if (wheelCooldownTimer) {
LK.clearInterval(wheelCooldownTimer);
wheelCooldownTimer = null;
}
// Disable menu buttons functionality in blackjack mode
blackjackButton.setEnabled(false);
slotsButton.setEnabled(false);
logrosButton.setEnabled(false);
ruedaPButton.setEnabled(false);
spinIButton.setEnabled(false);
statisticsButton.setEnabled(false);
// Enable blackjack buttons
hitButton.interactive = true;
hitButton.buttonMode = true;
standButton.interactive = true;
standButton.buttonMode = true;
doubleButton.interactive = true;
doubleButton.buttonMode = true;
dealButton.interactive = true;
dealButton.buttonMode = true;
removeAsset.interactive = true;
removeAsset.buttonMode = true;
// Disable slots buttons functionality in blackjack mode
spinButton.setEnabled(false);
masAsset.interactive = false;
masAsset.buttonMode = false;
menosAsset.interactive = false;
menosAsset.buttonMode = false;
// Hide blinking text when leaving menu
if (spinHereText) {
spinHereText.destroy();
spinHereText = null;
}
if (spinHereTextTimer) {
LK.clearTimeout(spinHereTextTimer);
spinHereTextTimer = null;
}
if (spinHereBlinkTimer) {
LK.clearInterval(spinHereBlinkTimer);
spinHereBlinkTimer = null;
}
// Clear SpinI timers when switching modes
if (spinITimer) {
LK.clearTimeout(spinITimer);
spinITimer = null;
}
if (spinIBlinkTimer) {
LK.clearInterval(spinIBlinkTimer);
spinIBlinkTimer = null;
}
if (spinIRecurringTimer) {
LK.clearInterval(spinIRecurringTimer);
spinIRecurringTimer = null;
}
// Create blinking "spin here" text after 2 seconds in main menu
spinHereTextTimer = LK.setTimeout(function () {
if (gameMode !== 'menu') return; // Only show if still in menu
// Create "spin here" text
spinHereText = new Text2('SPIN HERE', {
size: 48,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
spinHereText.anchor.set(0.5, 0.5);
spinHereText.x = 1848;
spinHereText.y = 2350; // Position above RuedaP button at new location (2500 - 150)
spinHereText.alpha = 1;
game.addChild(spinHereText);
// Make it blink
var blinkVisible = true;
spinHereBlinkTimer = LK.setInterval(function () {
if (!spinHereText) return;
blinkVisible = !blinkVisible;
tween(spinHereText, {
alpha: blinkVisible ? 1 : 0.3
}, {
duration: 500,
easing: tween.easeInOut
});
}, 600);
}, 2000);
// Card display removed from menu
// Hide main menu background
tween(fondoM, {
alpha: 0
}, {
duration: 300
});
// Show blackjack background
tween(blackjackBackground, {
alpha: 1
}, {
duration: 300
});
// Show table background
tween(tableBackground, {
alpha: 1
}, {
duration: 300
});
// Ensure no unwanted coloring
tableBackground.tint = 0xffffff;
// Show blackjack UI
tween(playerScoreText, {
alpha: 1
}, {
duration: 300
});
tween(dealerScoreText, {
alpha: 1
}, {
duration: 300
});
// Ensure stand button is properly interactive
standButton.interactive = true;
standButton.buttonMode = true;
tween(gameDeck, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
// Start deck animation when it becomes visible
if (gameDeck.startDeckAnimation) {
gameDeck.startDeckAnimation();
}
}
});
tween(dealerAnimatedHand, {
alpha: 1
}, {
duration: 300
});
tween(playerAnimatedHand, {
alpha: 1
}, {
duration: 300
});
// Hide total bet display in blackjack mode
tween(totalBetDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide Monedero2 asset in blackjack mode
tween(monedero2Asset, {
alpha: 0
}, {
duration: 300
});
// Hide mas asset in blackjack mode
tween(masAsset, {
alpha: 0
}, {
duration: 300
});
// Hide menos asset in blackjack mode
tween(menosAsset, {
alpha: 0
}, {
duration: 300
});
// Hide money display in blackjack mode
tween(moneyDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide money difference display in blackjack mode
tween(moneyDifferenceDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide BalanceB asset in blackjack mode
tween(balanceBAsset, {
alpha: 0
}, {
duration: 300
});
// Show Home button in blackjack mode
tween(homeButton, {
alpha: 1
}, {
duration: 300
});
// Show Remove asset in blackjack mode
tween(removeAsset, {
alpha: 1
}, {
duration: 300
});
// Show TotalA asset in blackjack mode
tween(totalAAsset, {
alpha: 1
}, {
duration: 300
});
// Show bet value display in blackjack mode
tween(betValueDisplay, {
alpha: 1
}, {
duration: 300
});
// Show BalanceBJ asset in blackjack mode
tween(balanceBJAsset, {
alpha: 1
}, {
duration: 300
});
// Show player money display in blackjack mode
tween(playerMoneyDisplay, {
alpha: 1
}, {
duration: 300
});
// Show Apuesta asset in blackjack mode
tween(apuestaAsset, {
alpha: 1
}, {
duration: 300
});
// Show deal button in blackjack mode only if bet is greater than zero
if (currentBet > 0) {
tween(dealButton, {
alpha: 1
}, {
duration: 300
});
} else {
dealButton.alpha = 0; // Keep hidden if no bet
}
// Show chips and bet display
tween(chipContainer, {
alpha: 1
}, {
duration: 300
});
// Create chips if not already created
if (chips.length === 0) {
createChips();
} else {
updateChipSelection();
}
}
function switchToSlots() {
gameMode = 'slots';
// Stop any currently playing music and play SpinM music
LK.stopMusic();
LK.playMusic('SpinM');
// Hide menu buttons
tween(blackjackButton, {
alpha: 0
}, {
duration: 300
});
tween(slotsButton, {
alpha: 0
}, {
duration: 300
});
tween(welcomeAsset, {
alpha: 0
}, {
duration: 300
});
// Hide new menu buttons
tween(logrosButton, {
alpha: 0
}, {
duration: 300
});
tween(ruedaPButton, {
alpha: 0
}, {
duration: 300
});
tween(statisticsButton, {
alpha: 0
}, {
duration: 300
});
tween(spinIButton, {
alpha: 0
}, {
duration: 300
});
// Hide wheel timer display in slots mode
tween(wheelTimerDisplay, {
alpha: 0
}, {
duration: 300
});
// Stop wheel cooldown timer when leaving menu
if (wheelCooldownTimer) {
LK.clearInterval(wheelCooldownTimer);
wheelCooldownTimer = null;
}
// Disable menu buttons functionality in slots mode
blackjackButton.setEnabled(false);
slotsButton.setEnabled(false);
logrosButton.setEnabled(false);
ruedaPButton.setEnabled(false);
spinIButton.setEnabled(false);
statisticsButton.setEnabled(false);
// Disable blackjack buttons functionality in slots mode
hitButton.interactive = false;
hitButton.buttonMode = false;
standButton.interactive = false;
standButton.buttonMode = false;
doubleButton.interactive = false;
doubleButton.buttonMode = false;
dealButton.interactive = false;
dealButton.buttonMode = false;
removeAsset.interactive = false;
removeAsset.buttonMode = false;
for (var i = 0; i < chips.length; i++) {
if (chips[i] && chips[i].setEnabled) {
chips[i].setEnabled(false);
}
}
// Enable slots buttons
masAsset.interactive = true;
masAsset.buttonMode = true;
menosAsset.interactive = true;
menosAsset.buttonMode = true;
// Card display removed from menu
// Hide main menu background
tween(fondoM, {
alpha: 0
}, {
duration: 300
});
// Hide blackjack background
tween(blackjackBackground, {
alpha: 0
}, {
duration: 300
});
// Show slots background (same as main menu)
tween(fondoM, {
alpha: 1
}, {
duration: 300
});
// Show tragamonedas asset in slots mode
tween(tragamonedasAsset, {
alpha: 1
}, {
duration: 300
});
// Show Monedero asset in slots mode
tween(monederoAsset, {
alpha: 1
}, {
duration: 300
});
// Show Monedero2 asset in slots mode
tween(monedero2Asset, {
alpha: 1
}, {
duration: 300
});
// Show total bet display in slots mode
tween(totalBetDisplay, {
alpha: 1
}, {
duration: 300
});
// Show mas asset in slots mode
tween(masAsset, {
alpha: 1
}, {
duration: 300
});
// Show menos asset in slots mode
tween(menosAsset, {
alpha: 1
}, {
duration: 300
});
// Show Megaways slot machine
tween(megawaysSlotMachine, {
alpha: 1
}, {
duration: 300
});
// Hide win amount display in slots mode
tween(winAmountDisplay, {
alpha: 0
}, {
duration: 300
});
// Keep cascade display hidden (will show via animation when needed)
// Show slots UI (classic reels removed - using Megaways only)
tween(spinButton, {
alpha: 1
}, {
duration: 300
});
// Set minimum bet to 25 when switching to slots
if (currentBet < 25) {
currentBet = 25;
}
// Reset bet to 25 if current bet exceeds player money when switching to slots
if (currentBet > playerMoney) {
currentBet = 25;
}
// Set bet to 25 when entering slots, but display FREE if free spins available
currentBet = 25;
if (freeSpins > 0) {
totalBetDisplay.setText('FREE');
spinButton.setText('SPIN FREE');
} else {
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
}
console.log('Setting spin button enabled - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabled:', playerMoney >= currentBet);
spinButton.setEnabled(playerMoney >= currentBet);
// Show money difference display in slots mode
tween(moneyDifferenceDisplay, {
alpha: 1
}, {
duration: 300
});
// Show Home button in slots mode
tween(homeButton, {
alpha: 1
}, {
duration: 300
});
// Show money display in slots mode
tween(moneyDisplay, {
alpha: 1
}, {
duration: 300
});
// Show BalanceB asset in slots mode
tween(balanceBAsset, {
alpha: 1
}, {
duration: 300
});
// Hide deal button in slots mode
tween(dealButton, {
alpha: 0
}, {
duration: 300
});
// Stop deck animation when in slots mode
if (gameDeck.stopDeckAnimation) {
gameDeck.stopDeckAnimation();
}
// Hide Remove asset in slots mode
tween(removeAsset, {
alpha: 0
}, {
duration: 300
});
// Hide TotalA asset in slots mode
tween(totalAAsset, {
alpha: 0
}, {
duration: 300
});
// Hide bet value display in slots mode
tween(betValueDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide BalanceBJ asset in slots mode
tween(balanceBJAsset, {
alpha: 0
}, {
duration: 300
});
// Hide player money display in slots mode
tween(playerMoneyDisplay, {
alpha: 0
}, {
duration: 300
});
// Hide Apuesta asset in slots mode
tween(apuestaAsset, {
alpha: 0
}, {
duration: 300
});
// Update ways display
// Hide chips and bet display
tween(chipContainer, {
alpha: 0
}, {
duration: 300
});
// Hide chips and bet display
tween(chipContainer, {
alpha: 0
}, {
duration: 300
});
waysDisplay.setText(megawaysSlotMachine.getWaysText());
cascadeDisplay.setText('');
}
function clearTable() {
// Remove all cards
for (var i = 0; i < playerCards.length; i++) {
playerCards[i].destroy();
}
for (var i = 0; i < dealerCards.length; i++) {
dealerCards[i].destroy();
}
playerCards = [];
dealerCards = [];
}
function showBetConfirmation(callback) {
var betPercentage = currentBet / playerMoney * 100;
// Create confirmation overlay
var confirmationOverlay = LK.getAsset('warning', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
confirmationOverlay.x = 1024;
confirmationOverlay.y = 1366;
confirmationOverlay.alpha = 0;
game.addChild(confirmationOverlay);
var warningText = new Text2('β οΈ HIGH BET WARNING β οΈ', {
size: 48,
fill: '#FF0000',
font: "'Arial Black', Arial, sans-serif"
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 1024;
warningText.y = 1200;
warningText.alpha = 0;
game.addChild(warningText);
var percentageText = new Text2('You are betting ' + Math.round(betPercentage) + '% of your money!', {
size: 36,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
percentageText.anchor.set(0.5, 0.5);
percentageText.x = 1024;
percentageText.y = 1300;
percentageText.alpha = 0;
game.addChild(percentageText);
var confirmButton = new GameButton('CONFIRM BET', 200, 80);
confirmButton.x = 824;
confirmButton.y = 1450;
confirmButton.alpha = 0;
game.addChild(confirmButton);
var cancelButton = new GameButton('CANCEL', 200, 80);
cancelButton.x = 1224;
cancelButton.y = 1450;
cancelButton.alpha = 0;
game.addChild(cancelButton);
// Animate in
tween(confirmationOverlay, {
alpha: 0.9
}, {
duration: 300
});
tween(warningText, {
alpha: 1
}, {
duration: 300,
delay: 100
});
tween(percentageText, {
alpha: 1
}, {
duration: 300,
delay: 200
});
tween(confirmButton, {
alpha: 1
}, {
duration: 300,
delay: 300
});
tween(cancelButton, {
alpha: 1
}, {
duration: 300,
delay: 300
});
function cleanup() {
confirmationOverlay.destroy();
warningText.destroy();
percentageText.destroy();
confirmButton.destroy();
cancelButton.destroy();
}
confirmButton.up = function () {
confirmedHighBet = true;
cleanup();
if (callback) callback(true);
};
cancelButton.up = function () {
cleanup();
if (callback) callback(false);
};
}
function startNewBlackjackHand() {
if (playerMoney < currentBet) return;
// Check for high bet confirmation (50% or more of money)
if (!confirmedHighBet && currentBet >= playerMoney * 0.5) {
showBetConfirmation(function (confirmed) {
if (confirmed) {
confirmedHighBet = true;
achievementSystem.checkAchievement('bigSpender', currentBet);
proceedWithDeal();
} else {
// Reset bet to a safer amount
currentBet = Math.min(currentBet, Math.floor(playerMoney * 0.25));
updateChipSelection();
}
confirmedHighBet = false;
});
return;
}
achievementSystem.checkAchievement('bigSpender', currentBet);
proceedWithDeal();
}
function proceedWithDeal() {
// Set hand in progress flag to prevent deal button from reappearing
handInProgress = true;
// Reset blackjack flag for new hand
isBlackjack = false;
// Track blackjack statistics
totalBlackjackHands++;
storage.totalBlackjackHands = totalBlackjackHands;
// Hide deal button immediately when pressed
tween(dealButton, {
alpha: 0
}, {
duration: 200
});
// Hide Remove button when cards are dealt
tween(removeAsset, {
alpha: 0
}, {
duration: 200
});
playerMoney -= currentBet;
updateMoneyDisplay();
clearTable();
createDeck();
gameDeck.updateCount(52);
gamePhase = 'dealing';
// Deal initial cards with animation sequence
dealCard(false, function () {
dealCard(true, function () {
dealCard(false, function () {
dealCard(true, function () {
// Dealer's first card stays face down
if (dealerCards.length > 0) {
dealerCards[0].faceUp = true;
dealerCards[0].flip();
}
updateScoreDisplays();
finishDealingPhase();
});
});
});
});
function finishDealingPhase() {
var playerScore = calculateHandValue(playerCards);
if (playerScore === 21) {
// Player got blackjack - play random blackjack voice
var playerBlackjackSounds = ['Jugador_BlackJack_1', 'Jugador_BlackJack_2', 'Jugador_BlackJack_3'];
var randomBlackjackSound = playerBlackjackSounds[Math.floor(Math.random() * playerBlackjackSounds.length)];
LK.getSound(randomBlackjackSound).play();
// Set flag to indicate blackjack (perfect 21) to prevent croupier win voice
isBlackjack = true;
endHand();
} else {
gamePhase = 'playing';
// Show action buttons
tween(hitButton, {
alpha: 1
}, {
duration: 300
});
tween(standButton, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
// Ensure stand button is interactive when shown
standButton.interactive = true;
standButton.buttonMode = true;
}
});
if (playerMoney >= currentBet) {
tween(doubleButton, {
alpha: 1
}, {
duration: 300
});
} else {
// Keep double button hidden if insufficient funds
doubleButton.alpha = 0;
}
// Hide deal button during hand
tween(dealButton, {
alpha: 0
}, {
duration: 300
});
}
}
}
function playerHit() {
var targetX = 850 + playerCards.length * 280; // Update to match new player card position (800 + 50)
var targetY = 2100;
// Play random player voice when requesting a card
var playerPedirSounds = ['Jugador_Pedir_1', 'Jugador_Pedir_2', 'Jugador_Pedir_3'];
var randomPedirSound = playerPedirSounds[Math.floor(Math.random() * playerPedirSounds.length)];
LK.getSound(randomPedirSound).play();
// Play card dealing sound when player requests a card
LK.getSound('Carta_1').play();
// Animate table tapping gesture first
tween(playerAnimatedHand, {
y: playerAnimatedHand.y + 50,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
onFinish: function onFinish() {
tween(playerAnimatedHand, {
y: playerAnimatedHand.y - 50,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
onFinish: function onFinish() {
// Now just deal the card without additional animation
dealCard(false, function () {
updateScoreDisplays();
var playerScore = calculateHandValue(playerCards);
if (playerScore > 21) {
endHand();
} else if (playerScore === 21) {
playerStand();
}
});
}
});
}
});
// Hide double button after hit since it's no longer available
doubleButton.alpha = 0;
}
function playerStand() {
gamePhase = 'dealer';
// Play random player voice when standing
var playerPlantarseSounds = ['Jugador_Plantarse_1', 'Jugador_Plantarse_2', 'Jugador_Plantarse_3'];
var randomPlantarseSound = playerPlantarseSounds[Math.floor(Math.random() * playerPlantarseSounds.length)];
LK.getSound(randomPlantarseSound).play();
// Animate negation gesture (wave hand side to side)
tween(playerAnimatedHand, {
x: playerAnimatedHand.x - 30,
rotation: -0.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerAnimatedHand, {
x: playerAnimatedHand.x + 60,
rotation: 0.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerAnimatedHand, {
x: playerAnimatedHand.x - 30,
rotation: 0
}, {
duration: 200,
onFinish: function onFinish() {
// Continue with original stand gesture
playerAnimatedHand.standGesture();
}
});
}
});
}
});
// Hide action buttons
tween(hitButton, {
alpha: 0
}, {
duration: 300
});
tween(standButton, {
alpha: 0
}, {
duration: 300
});
tween(doubleButton, {
alpha: 0
}, {
duration: 300
});
// Reveal dealer's face-down card with flip animation
if (dealerCards.length > 0) {
dealerAnimatedHand.flipCard(dealerCards[0].x, dealerCards[0].y, function () {
dealerCards[0].flip();
updateScoreDisplays();
// Dealer plays
LK.setTimeout(function () {
playDealerTurn();
}, 1000);
});
} else {
updateScoreDisplays();
// Dealer plays
LK.setTimeout(function () {
playDealerTurn();
}, 1000);
}
}
function playerDouble() {
if (playerMoney < currentBet) return;
playerMoney -= currentBet;
currentBet *= 2;
updateMoneyDisplay();
var targetX = 850 + playerCards.length * 280; // Update to match new player card position (800 + 50)
var targetY = 2100;
// Animate two fingers gesture first
tween(playerAnimatedHand, {
scaleX: 1.2,
scaleY: 1.2,
rotation: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
tween(playerAnimatedHand, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 300,
onFinish: function onFinish() {
// Now animate double down gesture with chips and card
playerAnimatedHand.doubleDownGesture(targetX, targetY, function () {
dealCard(false, function () {
updateScoreDisplays();
var playerScore = calculateHandValue(playerCards);
if (playerScore > 21) {
endHand();
} else {
playerStand();
}
});
});
}
});
}
});
}
function playDealerTurn() {
var dealerScore = calculateHandValue(dealerCards);
if (dealerScore < 17) {
dealCard(true, function () {
updateScoreDisplays();
LK.setTimeout(function () {
playDealerTurn();
}, 1000);
});
} else {
endHand();
}
}
function endHand() {
gamePhase = 'finished';
var playerScore = calculateHandValue(playerCards);
var dealerScore = calculateHandValue(dealerCards);
var winnings = 0;
var playerWon = false;
// Arrays for random voice selection
var cuprierWinSounds = ['Cuprier_Win_1', 'Cuprier_Win_2', 'Cuprier_Win_3'];
if (playerScore > 21) {
// Player busts - play random bust voice
var playerPasaSounds = ['Jugador_Pasa_1', 'Jugador_Pasa_2', 'Jugador_Pasa_3'];
var randomPasaSound = playerPasaSounds[Math.floor(Math.random() * playerPasaSounds.length)];
LK.getSound(randomPasaSound).play();
consecutiveWins = 0;
} else if (dealerScore > 21) {
winnings = currentBet * 2;
playerWon = true;
} else if (playerScore > dealerScore) {
winnings = currentBet * 2;
playerWon = true;
} else if (playerScore < dealerScore) {
// Dealer wins - play random croupier win voice (dealer wins without player bust)
var randomCuprierWinSound = cuprierWinSounds[Math.floor(Math.random() * cuprierWinSounds.length)];
LK.getSound(randomCuprierWinSound).play();
consecutiveWins = 0;
} else {
// Tie game - play random croupier tie voice
var cuprierEmpateSounds = ['Cuprier_Empate_1', 'Cuprier_Empate_2', 'Cuprier_Empate_3'];
var randomEmpateSound = cuprierEmpateSounds[Math.floor(Math.random() * cuprierEmpateSounds.length)];
LK.getSound(randomEmpateSound).play();
winnings = currentBet;
playerWon = true;
}
if (playerWon) {
consecutiveWins++;
totalBlackjackWins++;
storage.totalBlackjackWins = totalBlackjackWins;
// Track longest win streak
if (consecutiveWins > longestWinStreak) {
longestWinStreak = consecutiveWins;
storage.longestWinStreak = longestWinStreak;
}
achievementSystem.checkAchievement('firstBlackjackWin', true);
achievementSystem.checkAchievement('luckyStreak', consecutiveWins);
storage.consecutiveWins = consecutiveWins;
// Play random croupier win voice when player wins (but not on ties or blackjack)
if (winnings > currentBet && !isBlackjack) {
// Only play win sound if player actually won (not tie) and it's not a blackjack
var cuprierGanaSounds = ['Cuprier_Gana_1', 'Cuprier_Gana_2', 'Cuprier_Gana_3'];
var randomGanaSound = cuprierGanaSounds[Math.floor(Math.random() * cuprierGanaSounds.length)];
LK.getSound(randomGanaSound).play();
}
}
if (winnings > 0) {
playerMoney += winnings;
var netWin = winnings - currentBet;
if (netWin > 0) {
totalMoneyWon += netWin;
storage.totalMoneyWon = totalMoneyWon;
if (netWin > biggestWin) {
biggestWin = netWin;
storage.biggestWin = biggestWin;
}
}
LK.getSound('coinWin').play();
createCoinAnimation(1024, 1366);
} else {
// Player lost the bet
totalMoneyLost += currentBet;
storage.totalMoneyLost = totalMoneyLost;
}
currentBet = 0;
updateMoneyDisplay();
// Collect cards animation after 2 seconds
LK.setTimeout(function () {
var cardPositions = [];
var allCards = [];
// Collect player cards positions
for (var i = 0; i < playerCards.length; i++) {
cardPositions.push({
x: playerCards[i].x,
y: playerCards[i].y
});
allCards.push(playerCards[i]);
}
// Collect dealer cards positions
for (var i = 0; i < dealerCards.length; i++) {
cardPositions.push({
x: dealerCards[i].x,
y: dealerCards[i].y
});
allCards.push(dealerCards[i]);
}
// Animate collecting cards
dealerAnimatedHand.collectCards(cardPositions, allCards, function () {
// Clear actual cards from game after collection animation
clearTable();
// Shuffle animation
dealerAnimatedHand.shuffleAnimation();
});
}, 1500);
// Reset game phase after dealing sequence
LK.setTimeout(function () {
gamePhase = 'betting';
handInProgress = false; // Reset hand in progress flag
// Re-enable deal button only if still in blackjack mode and bet is greater than zero
if (gameMode === 'blackjack' && currentBet > 0) {
tween(dealButton, {
alpha: 1
}, {
duration: 300
});
}
}, 2000);
}
function spinSlots() {
// Track slots statistics
totalSlotsSpins++;
storage.totalSlotsSpins = totalSlotsSpins;
// Debug logging to identify the exact issue
console.log('spinSlots called - playerMoney:', playerMoney, 'currentBet:', currentBet, 'isSpinning:', megawaysSlotMachine.isSpinning);
// Reset bet to 25 immediately if current bet exceeds player money
if (currentBet > playerMoney) {
currentBet = 25;
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
console.log('Bet reset to 25 - new currentBet:', currentBet);
}
// Check if using free spins or player money
var usingFreeSpin = freeSpins > 0;
if (!usingFreeSpin && playerMoney < currentBet) {
console.log('Insufficient funds - playerMoney:', playerMoney, 'currentBet:', currentBet);
return;
}
if (megawaysSlotMachine.isSpinning) {
console.log('Already spinning - isSpinning:', megawaysSlotMachine.isSpinning);
return;
}
// Set slots spin in progress flag
slotsSpinInProgress = true;
// Reset money difference values to 0 at start of new spin
moneyAfterBet = 0;
moneyAfterSpin = 0;
updateMoneyDifferenceDisplay();
// Deduct cost - either free spin or player money
if (usingFreeSpin) {
freeSpins--;
storage.freeSpins = freeSpins;
moneyAfterBet = playerMoney; // No money deducted for free spins
// Set effective bet to 100 for free spins calculations
currentBet = 100;
} else {
playerMoney -= currentBet;
moneyAfterBet = playerMoney; // Track money after betting
}
moneyAfterSpin = moneyAfterBet; // Keep at same value until spin results are processed
updateMoneyDisplay();
// Update display based on remaining free spins
if (freeSpins > 0) {
totalBetDisplay.setText('FREE'); // Update total bet display for slots
} else {
totalBetDisplay.setText('$' + currentBet); // Update total bet display for slots
}
spinButton.setEnabled(false);
messageDisplay.setText('Spinning...');
// Hide cascade display
cascadeDisplay.alpha = 0;
megawaysSlotMachine.totalWinAmount = 0;
megawaysSlotMachine.cascadeCount = 0;
lastCascadeCount = 0;
// Animate spin button
tween(spinButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(spinButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
LK.getSound('slotSpin').play();
// Start Megaways spin
megawaysSlotMachine.spinAllReels(function () {
// Show ways animation if significantly increased
showWaysAnimation(megawaysSlotMachine.currentWays);
// Check for wins and start cascade sequence
var winningCombos = megawaysSlotMachine.checkForWins();
if (winningCombos.length > 0) {
messageDisplay.setText('WINNING SPIN!');
processInitialWins(winningCombos);
} else {
messageDisplay.setText('No win. Try again!');
console.log('No wins - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabling button:', playerMoney >= currentBet || freeSpins > 0);
spinButton.setEnabled(playerMoney >= currentBet || freeSpins > 0);
// Update button text based on free spins availability
if (freeSpins > 0) {
totalBetDisplay.setText('FREE');
spinButton.setText('SPIN FREE');
} else {
// Reset bet to 25 if current bet exceeds player money after spin
if (currentBet > playerMoney) {
currentBet = 25;
}
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
}
// Clear slots spin in progress flag when no wins
slotsSpinInProgress = false;
}
});
}
function processInitialWins(winningCombinations) {
megawaysSlotMachine.processWins(winningCombinations, function (winAmount) {
if (winAmount > 0) {
// Show cascade animation when significantly increased
showCascadeAnimation(megawaysSlotMachine.cascadeCount);
// Check cascade achievement
achievementSystem.checkAchievement('cascade5x', megawaysSlotMachine.cascadeCount);
// Track max cascades achieved
if (megawaysSlotMachine.cascadeCount > maxCascades) {
maxCascades = megawaysSlotMachine.cascadeCount;
storage.maxCascades = maxCascades;
}
// Add winnings to player money
playerMoney += winAmount;
moneyAfterSpin = playerMoney; // Track money after spin results
// Track slots wins
if (winAmount > 0) {
totalMoneyWon += winAmount;
storage.totalMoneyWon = totalMoneyWon;
if (winAmount > biggestWin) {
biggestWin = winAmount;
storage.biggestWin = biggestWin;
}
} else {
// Player lost the bet
var betLost = usingFreeSpin ? 0 : currentBet;
if (betLost > 0) {
totalMoneyLost += betLost;
storage.totalMoneyLost = totalMoneyLost;
}
}
updateMoneyDisplay();
// Play win sound and create coin animation
LK.getSound('coinWin').play();
createCoinAnimation(1024, 1366);
}
// Re-enable spin button after all cascades complete
LK.setTimeout(function () {
// Update displays based on free spins availability
if (freeSpins > 0) {
totalBetDisplay.setText('FREE');
spinButton.setText('SPIN FREE');
} else {
// Reset bet to 25 if current bet exceeds player money after all cascades
if (currentBet > playerMoney) {
currentBet = 25;
}
totalBetDisplay.setText('$' + currentBet);
spinButton.setText('SPIN $' + currentBet);
}
console.log('After cascades - playerMoney:', playerMoney, 'currentBet:', currentBet, 'enabling button:', playerMoney >= currentBet || freeSpins > 0);
spinButton.setEnabled(playerMoney >= currentBet || freeSpins > 0);
// Clear slots spin in progress flag when all cascades complete
slotsSpinInProgress = false;
if (megawaysSlotMachine.totalWinAmount > 0) {
if (megawaysSlotMachine.totalWinAmount >= 1000) {
messageDisplay.setText('π MEGA WIN! $' + megawaysSlotMachine.totalWinAmount + ' π');
} else if (megawaysSlotMachine.totalWinAmount >= 500) {
messageDisplay.setText('π° BIG WIN! $' + megawaysSlotMachine.totalWinAmount + ' π°');
} else {
messageDisplay.setText('β¨ WIN! $' + megawaysSlotMachine.totalWinAmount + ' β¨');
}
} else {
messageDisplay.setText('');
}
}, 1000);
});
}
function checkSlotWin(s1, s2, s3) {
var symbols = ['cherry', 'lemon', 'grape', 'seven', 'bell', 'diamond', 'bar', 'dollar'];
var symbolNames = ['π', 'π', 'π', '7', 'π', 'π', 'BAR', '$'];
var winnings = 0;
var isWin = false;
// Check for wins
if (s1 === s2 && s2 === s3) {
// Three of a kind
isWin = true;
if (symbols[s1] === 'seven') {
winnings = 500;
messageDisplay.setText('π° JACKPOT! Triple 7s! π°');
} else if (symbols[s1] === 'dollar') {
winnings = 300;
messageDisplay.setText('π° Big Win! Triple $$$ π°');
} else if (symbols[s1] === 'diamond') {
winnings = 250;
messageDisplay.setText('π Diamond Jackpot! π');
} else if (symbols[s1] === 'bell') {
winnings = 200;
messageDisplay.setText('π Triple Bells! π');
} else {
winnings = 100;
messageDisplay.setText('π Three of a kind! π');
}
} else if (s1 === s2 || s2 === s3 || s1 === s3) {
// Pair
isWin = true;
winnings = 50;
messageDisplay.setText('β¨ Pair! Small win! β¨');
} else {
messageDisplay.setText('No win. Try again!');
}
if (isWin) {
// Flash message display
tween(messageDisplay, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(messageDisplay, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
}
if (winnings > 0) {
playerMoney += winnings;
LK.getSound('coinWin').play();
createCoinAnimation(1024, 1366);
updateMoneyDisplay();
}
}
function showWaysAnimation(currentWays) {
// Only show animation if ways increased significantly (by at least 10,000)
if (currentWays > lastWaysCount + 10000) {
// Destroy existing animation if any
if (waysAnimationDisplay) {
waysAnimationDisplay.destroy();
waysAnimationDisplay = null;
}
// Create animated ways display
waysAnimationDisplay = new Text2(currentWays + ' WAYS!', {
size: 72,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
waysAnimationDisplay.anchor.set(0.5, 0.5);
waysAnimationDisplay.x = 1024;
waysAnimationDisplay.y = 900;
waysAnimationDisplay.alpha = 0;
waysAnimationDisplay.scaleX = 0.5;
waysAnimationDisplay.scaleY = 0.5;
game.addChild(waysAnimationDisplay);
// Animate popup entrance
tween(waysAnimationDisplay, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Hold for 1 second
LK.setTimeout(function () {
// Animate fadeout
tween(waysAnimationDisplay, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
if (waysAnimationDisplay) {
waysAnimationDisplay.destroy();
waysAnimationDisplay = null;
}
}
});
}, 1000);
}
});
}
lastWaysCount = currentWays;
}
function showCascadeAnimation(currentCascadeCount) {
// Only show animation if cascade count increased AND is 5 or higher
if (currentCascadeCount > lastCascadeCount && currentCascadeCount >= 5) {
// Play Cascada sound when cascade reaches x5 or higher
LK.getSound('Cascada').play();
// Destroy existing cascade animation if any
if (cascadeAnimationDisplay) {
cascadeAnimationDisplay.destroy();
cascadeAnimationDisplay = null;
}
// Create animated cascade display
cascadeAnimationDisplay = new Text2('CASCADE x' + currentCascadeCount + '!', {
size: 168,
fill: '#FF6347',
font: "'Arial Black', Arial, sans-serif"
});
cascadeAnimationDisplay.anchor.set(0.5, 0.5);
cascadeAnimationDisplay.x = 1024;
cascadeAnimationDisplay.y = 800;
cascadeAnimationDisplay.alpha = 0;
cascadeAnimationDisplay.scaleX = 0.5;
cascadeAnimationDisplay.scaleY = 0.5;
game.addChild(cascadeAnimationDisplay);
// Animate popup entrance
tween(cascadeAnimationDisplay, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Hold for 1 second
LK.setTimeout(function () {
// Animate fadeout
tween(cascadeAnimationDisplay, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
if (cascadeAnimationDisplay) {
cascadeAnimationDisplay.destroy();
cascadeAnimationDisplay = null;
}
}
});
}, 1000);
}
});
}
lastCascadeCount = currentCascadeCount;
}
function createCoinAnimation(x, y) {
for (var i = 0; i < 5; i++) {
var coin = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
coin.x = x + (Math.random() - 0.5) * 200;
coin.y = y + (Math.random() - 0.5) * 200;
game.addChild(coin);
tween(coin, {
y: coin.y - 100,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 1000,
onFinish: function onFinish() {
coin.destroy();
}
});
}
}
function createConfettiCelebration() {
var confettiAssets = ['confetti1', 'confetti2', 'confetti3', 'confetti4', 'confetti5', 'confetti6'];
// Create 50 confetti pieces for spectacular effect
for (var i = 0; i < 50; i++) {
var confettiType = confettiAssets[Math.floor(Math.random() * confettiAssets.length)];
var confetti = LK.getAsset(confettiType, {
anchorX: 0.5,
anchorY: 0.5
});
// Start confetti at top of screen with random horizontal positions
confetti.x = Math.random() * 2048;
confetti.y = -50;
confetti.rotation = Math.random() * Math.PI * 2;
game.addChild(confetti);
// Animate confetti falling with random movement
tween(confetti, {
x: confetti.x + (Math.random() - 0.5) * 400,
y: 2732 + 100,
rotation: confetti.rotation + (Math.random() - 0.5) * Math.PI * 4,
alpha: 0
}, {
duration: 3000 + Math.random() * 2000,
easing: tween.easeIn,
onFinish: function onFinish() {
confetti.destroy();
}
});
}
}
// Card display removed from menu
// Track if this is the first time entering the menu
var isFirstMenuEntry = true;
// Initialize game state
updateMoneyDisplay();
// Add global click handler for disclaimer screen
game.down = function (x, y, obj) {
if (gameMode === 'disclaimer') {
switchToMenu();
}
};
// Initialize wheel cooldown system
if (wheelLastUsed === 0) {
// First time playing, allow immediate wheel use
wheelLastUsed = Date.now() - WHEEL_COOLDOWN_TIME;
storage.wheelLastUsed = wheelLastUsed;
}
// Start with disclaimer screen
if (gameMode === 'disclaimer') {
// Hide all menu elements initially
blackjackButton.alpha = 0;
slotsButton.alpha = 0;
welcomeAsset.alpha = 0;
fondoM.alpha = 0;
logrosButton.alpha = 0;
ruedaPButton.alpha = 0;
spinIButton.alpha = 0;
wheelTimerDisplay.alpha = 0;
// Disable buttons during disclaimer screen
blackjackButton.setEnabled(false);
slotsButton.setEnabled(false);
logrosButton.setEnabled(false);
ruedaPButton.setEnabled(false);
spinIButton.setEnabled(false);
} else {
switchToMenu();
}
// Menu music will be played when entering main menu via switchToMenu function
game.update = function () {
updateMoneyDisplay();
};
// Wheel prize definitions
var wheelPrizes = [{
type: 'credits',
amount: 200,
name: '+200 Credits',
probability: 40,
color: 0x4CAF50
}, {
type: 'credits',
amount: 500,
name: '+500 Credits',
probability: 25,
color: 0x2196F3
}, {
type: 'credits',
amount: 1000,
name: '+1,000 Credits',
probability: 10,
color: 0x9C27B0
}, {
type: 'credits',
amount: 2500,
name: '+2,500 Credits',
probability: 5,
color: 0xFF5722
}, {
type: 'freespins',
amount: 3,
name: '+3 Free Spins',
probability: 10,
color: 0xFFC107
}, {
type: 'freespins',
amount: 10,
name: '+10 Free Spins',
probability: 5,
color: 0xE91E63
}, {
type: 'blackjackchips',
amount: 250,
name: '+250 chips',
probability: 4,
color: 0x795548
}, {
type: 'credits',
amount: 10000,
name: 'JACKPOT',
probability: 1,
color: 0xFFD700
}];
// Wheel cooldown system - 12 hours (43200000 milliseconds)
var WHEEL_COOLDOWN_TIME = 43200000; // 12 hours in milliseconds
var wheelLastUsed = storage.wheelLastUsed || 0;
var wheelCooldownTimer = null;
// Wheel spinning state variables
var wheelIsSpinning = false;
var preSelectedPrize = null;
var wheelContainer = null;
var ruedaVerificador = null;
var wheelSegments = [];
var targetCheckInterval = null;
var wheelSpinButton = null;
var giroSoundInterval = null; // Track Giro sound interval
var slotsSpinInProgress = false; // Track if slots spin is active
function showWheelScreen() {
// Set wheel screen as open to prevent re-entry
wheelScreenOpen = true;
// Disable blackjack and slots buttons when wheel opens
blackjackButton.setEnabled(false);
slotsButton.setEnabled(false);
// Create dark overlay background
var wheelOverlay = LK.getAsset('warning', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.95
});
wheelOverlay.x = 1024;
wheelOverlay.y = 1366;
wheelOverlay.alpha = 0;
game.addChild(wheelOverlay);
// Create title
var wheelTitle = new Text2('π‘ FORTUNE WHEEL π‘', {
size: 72,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
wheelTitle.anchor.set(0.5, 0.5);
wheelTitle.x = 1024;
wheelTitle.y = 400;
wheelTitle.alpha = 0;
game.addChild(wheelTitle);
// Create wheel container
wheelContainer = new Container();
wheelContainer.x = 1024;
wheelContainer.y = 1000;
wheelContainer.alpha = 0;
game.addChild(wheelContainer);
// Create wheel base
var wheelBase = LK.getAsset('circularSpinButtonShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 1800,
height: 1836
});
wheelContainer.addChild(wheelBase);
// Create wheel pointer using Flecha asset outside the wheel container so it doesn't rotate
var wheelPointer = LK.getAsset('Flecha', {
anchorX: 0.5,
anchorY: 1.0
});
wheelPointer.x = 1024; // Position at center of screen
wheelPointer.y = 250; // 750 pixels above wheel center (1000 - 750)
wheelPointer.alpha = 0;
game.addChild(wheelPointer); // Add to game instead of wheelContainer
// Create RuedaVerificador asset at same position as Flecha
ruedaVerificador = LK.getAsset('RuedaVerificador', {
anchorX: 0.5,
anchorY: 1.0
});
ruedaVerificador.x = 1024; // Same position as wheelPointer
ruedaVerificador.y = 450; // Moved down 200 pixels from wheelPointer position
ruedaVerificador.alpha = 0;
game.addChild(ruedaVerificador);
// Create wheel segments
var segmentAngle = Math.PI * 2 / wheelPrizes.length;
wheelSegments = [];
for (var i = 0; i < wheelPrizes.length; i++) {
var angle = i * segmentAngle;
var radius = 600;
// Add prize text (horizontal - make invisible)
var fontSize = 60;
// Adjust font size for specific prizes
if (wheelPrizes[i].name === '+3 Free Spins') {
fontSize = 60 * 1.03; // Make 1.03 times larger
} else if (wheelPrizes[i].name === '+10 Free Spins') {
fontSize = 60 / 1.05; // Make 1.05 times smaller
} else if (wheelPrizes[i].name === '+1,000 Credits') {
fontSize = 60 / 1.15; // Make 1.15 times smaller
} else if (wheelPrizes[i].name === '+2,500 Credits') {
fontSize = 60 / 1.15; // Make 1.15 times smaller
} else if (wheelPrizes[i].name === '+250 chips') {
fontSize = 60 * 1.2; // Make 1.2 times larger
} else if (wheelPrizes[i].name === 'JACKPOT') {
fontSize = 60 * 1.15; // Make 1.15 times larger
}
var prizeText = new Text2(wheelPrizes[i].name, {
size: fontSize,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
prizeText.anchor.set(0.5, 0.5);
prizeText.x = Math.cos(angle) * radius;
prizeText.y = Math.sin(angle) * radius;
prizeText.rotation = angle + Math.PI / 2;
prizeText.alpha = 0; // Make horizontal text invisible
wheelContainer.addChild(prizeText);
wheelSegments.push(prizeText);
// Add vertical prize text
var verticalPrizeText = new Text2(wheelPrizes[i].name, {
size: fontSize,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
verticalPrizeText.anchor.set(0.5, 0.5);
verticalPrizeText.x = Math.cos(angle) * radius;
verticalPrizeText.y = Math.sin(angle) * radius;
verticalPrizeText.rotation = angle + Math.PI / 2 + Math.PI / 2; // Add 90 degrees for vertical orientation
wheelContainer.addChild(verticalPrizeText);
}
// Create spin button
wheelSpinButton = new GameButton('SPIN WHEEL', 300, 100);
wheelSpinButton.x = 1024;
wheelSpinButton.y = 1000; // Moved to center of wheel asset
wheelSpinButton.alpha = 0;
// Replace the default button background with circular assets (500x500)
wheelSpinButton.removeChild(wheelSpinButton.children[0]); // Remove shadow
wheelSpinButton.removeChild(wheelSpinButton.children[0]); // Remove background (index shifts after first removal)
// Add circular border
var circularBorder = LK.getAsset('circularSpinButtonBorder', {
anchorX: 0.5,
anchorY: 0.5,
width: 500,
height: 500
});
wheelSpinButton.addChildAt(circularBorder, 0);
// Add circular button
var circularButton = LK.getAsset('circularSpinButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 450,
height: 295
});
wheelSpinButton.addChildAt(circularButton, 1);
game.addChild(wheelSpinButton);
// Move SpinI button to overlapping position above the wheel (only if it exists)
if (spinIButton && spinIAsset) {
tween(spinIButton, {
x: wheelSpinButton.x - 400,
// Position 400 pixels to the left of wheel center for overlap (320 + 80)
y: wheelSpinButton.y - 100 // Position above the wheel spin button to overlay on wheel
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Ensure SpinI renders above wheel by removing and re-adding to game
game.removeChild(spinIButton);
game.addChild(spinIButton);
}
});
}
// Create close button
var wheelCloseButton = new GameButton('CLOSE', 200, 80);
wheelCloseButton.x = 1024;
wheelCloseButton.y = 2000;
wheelCloseButton.alpha = 0;
game.addChild(wheelCloseButton);
// Animate in
tween(wheelOverlay, {
alpha: 0.95
}, {
duration: 300
});
tween(wheelTitle, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
delay: 100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(wheelTitle, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
tween(wheelContainer, {
alpha: 1
}, {
duration: 400,
delay: 200
});
tween(wheelPointer, {
alpha: 1
}, {
duration: 400,
delay: 250
});
ruedaVerificador.alpha = 0;
tween(wheelSpinButton, {
alpha: 0
}, {
duration: 300,
delay: 400
});
tween(wheelCloseButton, {
alpha: 1
}, {
duration: 300,
delay: 500
});
// Spin wheel handler
wheelSpinButton.up = function () {
if (!wheelSpinButton.enabled) return;
if (wheelIsSpinning) return;
wheelSpinButton.setEnabled(false);
wheelIsSpinning = true;
// Track wheel statistics
totalWheelSpins++;
storage.totalWheelSpins = totalWheelSpins;
// Stop any currently playing music and start RuedaMusic when wheel begins spinning
LK.stopMusic();
LK.playMusic('RuedaMusic');
// Hide SpinI asset when wheel is spun and stop all blinking
tween.stop(spinIAsset, {
alpha: true
}); // Stop any ongoing alpha tween
spinIAsset.alpha = 0; // Set to fully transparent
tween(spinIButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
// Clear SpinI timers when player spins wheel
if (spinITimer) {
LK.clearTimeout(spinITimer);
spinITimer = null;
}
if (spinIBlinkTimer) {
LK.clearInterval(spinIBlinkTimer);
spinIBlinkTimer = null;
}
if (spinIRecurringTimer) {
LK.clearInterval(spinIRecurringTimer);
spinIRecurringTimer = null;
}
// Disable SpinI asset verificador functionality after wheel spin
spinIButton.setEnabled(false);
spinIAsset.interactive = false;
spinIAsset.buttonMode = false;
// Immediately calculate which prize to award
preSelectedPrize = selectRandomPrize();
console.log('Pre-selected prize:', preSelectedPrize.prize.name, 'at index:', preSelectedPrize.index);
// Start spinning the wheel immediately
var continuousSpinRotation = wheelContainer.rotation + Math.PI * 2 * 10; // Spin 10 full rotations over 5 seconds
// Start Giro sound interval - play every 1 second during spin
var giroSoundInterval = LK.setInterval(function () {
if (wheelIsSpinning) {
LK.getSound('Giro').play();
}
}, 1000);
// Play first Giro sound immediately
LK.getSound('Giro').play();
// Phase 1: Spin continuously for 5 seconds
tween(wheelContainer, {
rotation: continuousSpinRotation
}, {
duration: 5000,
easing: tween.linear
});
// Phase 2: After 5 seconds, start target detection and transition to target
LK.setTimeout(function () {
// Check if wheel is still open and spinning before proceeding
if (!wheelIsSpinning || !wheelContainer) return;
// Continue Giro sound interval during final phase (already playing every 1 second)
// Calculate target rotation to align pre-selected prize with RuedaVerificador
var segmentAngle = Math.PI * 2 / wheelPrizes.length;
var targetAngle = preSelectedPrize.index * segmentAngle;
// Stop current spin and calculate final rotation
tween.stop(wheelContainer, {
rotation: true
});
// Add additional rotations to reach target smoothly
var currentRotation = wheelContainer.rotation;
var finalRotation = currentRotation + Math.PI * 2 * 2 + targetAngle; // Add 2 more full spins to target
console.log('Transitioning to target prize. Final rotation:', finalRotation * 180 / Math.PI, 'degrees');
// Start monitoring for collision during final approach
startTargetDetection();
// Animate wheel to target position with deceleration
tween(wheelContainer, {
rotation: finalRotation
}, {
duration: 3000,
easing: tween.easeOut
});
}, 5000);
};
// Close handler
function closeWheelScreen() {
// Prevent closing wheel if spin is in progress
if (wheelIsSpinning) return;
// Make close button disappear immediately
wheelCloseButton.alpha = 0;
// Reset wheel screen state to allow re-entry
wheelScreenOpen = false;
// Re-enable blackjack and slots buttons when wheel closes
blackjackButton.setEnabled(true);
slotsButton.setEnabled(true);
// Move SpinI button back to original position with 50px left offset and restore visibility
tween(spinIButton, {
x: 1488 - 50,
// Original position minus 50 pixels to the left
y: 2500,
// Original vertical position
alpha: 1 // Restore visibility when returning to original position
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset sound toggle when returning from wheel
spinISoundToggle = false;
}
});
// Clear any ongoing wheel detection
if (targetCheckInterval) {
LK.clearInterval(targetCheckInterval);
targetCheckInterval = null;
}
// Clear Giro sound interval when closing wheel
if (giroSoundInterval) {
LK.clearInterval(giroSoundInterval);
giroSoundInterval = null;
}
// Reset wheel variables
wheelIsSpinning = false;
preSelectedPrize = null;
// Store references before nullifying
var elementsToDestroy = [];
if (wheelContainer) elementsToDestroy.push(wheelContainer);
if (ruedaVerificador) elementsToDestroy.push(ruedaVerificador);
if (wheelSpinButton) elementsToDestroy.push(wheelSpinButton);
// Find and destroy all wheel-related elements by checking all game children
var gameChildren = game.children.slice(); // Create a copy to avoid modification during iteration
for (var i = 0; i < gameChildren.length; i++) {
var child = gameChildren[i];
// Check if this is a wheel-related element by examining its properties or position
// Exclude fondoM background by checking if it's the main menu background
if (child && child !== fondoM && (child.x === 1024 && child.y === 1366 && child.width && child.height ||
// wheelOverlay (exclude fondoM)
child.x === 1024 && child.y === 400 && child.setText ||
// wheelTitle
child.x === 1024 && child.y === 250 ||
// wheelPointer
child.x === 1024 && child.y === 450 ||
// ruedaVerificador
child.x === 1024 && child.y === 1600 && child.setText ||
// wheelSpinButton
child.x === 1024 && child.y === 2000 && child.setText ||
// wheelCloseButton (updated position)
child.x === 1024 && child.y === 1000 ||
// wheelContainer
child.x === 1024 && child.y === 1400 && child.setText // resultText
)) {
elementsToDestroy.push(child);
}
}
// Immediately hide and destroy all elements
for (var i = 0; i < elementsToDestroy.length; i++) {
var element = elementsToDestroy[i];
if (element) {
element.alpha = 0;
if (element.destroy) {
element.destroy();
}
}
}
// Reset wheel variables to null
wheelContainer = null;
ruedaVerificador = null;
wheelSegments = [];
wheelSpinButton = null;
}
wheelCloseButton.up = closeWheelScreen;
}
function selectRandomPrize() {
// Select a random prize for initial spin calculation (still used for rotation)
var random = Math.random() * 100;
var cumulativeProbability = 0;
var selectedPrizeIndex = 0;
for (var i = 0; i < wheelPrizes.length; i++) {
cumulativeProbability += wheelPrizes[i].probability;
if (random <= cumulativeProbability) {
selectedPrizeIndex = i;
break;
}
}
return {
prize: wheelPrizes[selectedPrizeIndex],
index: selectedPrizeIndex
};
}
function startTargetDetection() {
// Clear any existing interval
if (targetCheckInterval) {
LK.clearInterval(targetCheckInterval);
targetCheckInterval = null;
}
// Check every 50ms during spin for collision with target prize
targetCheckInterval = LK.setInterval(function () {
if (!wheelIsSpinning || !preSelectedPrize) return;
// Check if RuedaVerificador intersects with the target prize text
var targetSegment = wheelSegments[preSelectedPrize.index];
if (targetSegment && ruedaVerificador) {
// Get global positions for collision detection
var segmentGlobalPos = wheelContainer.toGlobal(targetSegment.position);
var verificadorGlobalPos = game.toGlobal(ruedaVerificador.position);
// Check distance between centers (simple collision detection)
var distance = Math.sqrt(Math.pow(segmentGlobalPos.x - verificadorGlobalPos.x, 2) + Math.pow(segmentGlobalPos.y - verificadorGlobalPos.y, 2));
// If close enough (within 100 pixels), consider it a hit
if (distance < 100) {
console.log('Target prize detected under RuedaVerificador! Stopping wheel.');
stopWheelAtTarget();
}
}
}, 50);
}
function stopWheelAtTarget() {
// Stop all wheel animations immediately
tween.stop(wheelContainer, {
rotation: true
});
// Stop Giro sound interval when wheel stops
if (giroSoundInterval) {
LK.clearInterval(giroSoundInterval);
giroSoundInterval = null;
}
// Stop RuedaMusic when wheel stops and restart menu music
LK.stopMusic();
LK.setTimeout(function () {
LK.playMusic('Menu');
}, 100);
// Clear the detection interval
if (targetCheckInterval) {
LK.clearInterval(targetCheckInterval);
targetCheckInterval = null;
}
// Award the pre-selected prize
console.log('Awarding pre-selected prize:', preSelectedPrize.prize.name);
awardWheelPrize(preSelectedPrize.prize);
// Play premio sound when prize is won
LK.getSound('premio').play();
// Create confetti celebration effect
createConfettiCelebration();
// Show result with "You won:" on first line and prize on second line
var youWonText = new Text2('You won:', {
size: 192,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
youWonText.anchor.set(0.5, 0.5);
youWonText.x = 1024;
youWonText.y = 1300;
youWonText.alpha = 0;
game.addChild(youWonText);
var prizeText = new Text2(preSelectedPrize.prize.name, {
size: 192,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
prizeText.anchor.set(0.5, 0.5);
prizeText.x = 1024;
prizeText.y = 1500;
prizeText.alpha = 0;
game.addChild(prizeText);
tween(youWonText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut
});
tween(prizeText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
delay: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(youWonText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
youWonText.destroy();
}
});
tween(prizeText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
prizeText.destroy();
}
});
}, 2000);
}
});
// Reset wheel state
wheelIsSpinning = false;
preSelectedPrize = null;
// Re-enable spin button if it exists and wheel screen is still open
if (wheelSpinButton && wheelSpinButton.setEnabled) {
wheelSpinButton.setEnabled(true);
}
}
function detectPrizeUnderVerificador(wheelContainer, ruedaVerificador, wheelSegments) {
// Find which text segment intersects with RuedaVerificador using actual collision detection
var closestSegment = null;
var minDistance = Infinity;
var winningIndex = 0;
for (var i = 0; i < wheelSegments.length; i++) {
var segment = wheelSegments[i];
// Check if the text segment intersects with RuedaVerificador
if (segment.intersects && segment.intersects(ruedaVerificador)) {
// Direct collision detected - this is our winner
return {
prize: wheelPrizes[i],
index: i
};
}
// Fallback: calculate distance to RuedaVerificador as backup
var segmentGlobalPos = wheelContainer.toGlobal(segment.position);
var verificadorGlobalPos = ruedaVerificador.position;
var distance = Math.sqrt(Math.pow(segmentGlobalPos.x - verificadorGlobalPos.x, 2) + Math.pow(segmentGlobalPos.y - verificadorGlobalPos.y, 2));
if (distance < minDistance) {
minDistance = distance;
closestSegment = i;
winningIndex = i;
}
}
// If no direct collision found, use closest segment
return {
prize: wheelPrizes[winningIndex],
index: winningIndex
};
}
function awardWheelPrize(prize) {
// Play Congratulations sound for any prize win
LK.getSound('Congratulations').play();
switch (prize.type) {
case 'credits':
playerMoney += prize.amount;
updateMoneyDisplay();
LK.getSound('coinWin').play();
createCoinAnimation(1024, 1366);
break;
case 'freespins':
freeSpins += prize.amount;
storage.freeSpins = freeSpins;
console.log('Awarded ' + prize.amount + ' free spins - total:', freeSpins);
break;
case 'blackjackchips':
playerMoney += prize.amount;
updateMoneyDisplay();
LK.getSound('coinWin').play();
createCoinAnimation(1024, 1366);
break;
}
// Set wheel last used time and save to storage
wheelLastUsed = Date.now();
storage.wheelLastUsed = wheelLastUsed;
}
// Check if wheel is available (not on cooldown)
function isWheelAvailable() {
var currentTime = Date.now();
var timeSinceLastUse = currentTime - wheelLastUsed;
return timeSinceLastUse >= WHEEL_COOLDOWN_TIME;
}
// Get remaining cooldown time in milliseconds
function getRemainingCooldownTime() {
var currentTime = Date.now();
var timeSinceLastUse = currentTime - wheelLastUsed;
return Math.max(0, WHEEL_COOLDOWN_TIME - timeSinceLastUse);
}
// Format time in hours:minutes:seconds
function formatTime(milliseconds) {
var totalSeconds = Math.floor(milliseconds / 1000);
var hours = Math.floor(totalSeconds / 3600);
var minutes = Math.floor(totalSeconds % 3600 / 60);
var seconds = totalSeconds % 60;
return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0');
}
// Update wheel timer display
function updateWheelTimer() {
if (!wheelTimerDisplay) return;
if (isWheelAvailable()) {
wheelTimerDisplay.setText('READY!');
wheelTimerDisplay.fill = '#00FF00'; // Green when ready
// Remove disabled effect from wheel icon when ready
if (ruedaPAsset) {
tween(ruedaPAsset, {
alpha: 1.0,
tint: 0xFFFFFF
}, {
duration: 300
});
}
// Reactivate SpinI when wheel is available
if (spinIAsset && gameMode === 'menu') {
spinIAsset.alpha = 1;
}
} else {
var remainingTime = getRemainingCooldownTime();
wheelTimerDisplay.setText(formatTime(remainingTime));
wheelTimerDisplay.fill = '#FF6B6B'; // Red when on cooldown
// Add disabled effect to wheel icon when on cooldown
if (ruedaPAsset) {
tween(ruedaPAsset, {
alpha: 0.5,
tint: 0x808080
}, {
duration: 300
});
}
// Deactivate SpinI when wheel is on cooldown
if (spinIAsset) {
spinIAsset.alpha = 0;
}
}
}
// Start wheel cooldown timer
function startWheelCooldownTimer() {
// Clear existing timer if any
if (wheelCooldownTimer) {
LK.clearInterval(wheelCooldownTimer);
wheelCooldownTimer = null;
}
// Update timer every second
wheelCooldownTimer = LK.setInterval(function () {
updateWheelTimer();
}, 1000);
// Initial update
updateWheelTimer();
}
// Statistics tracking variables
var totalBlackjackHands = storage.totalBlackjackHands || 0;
var totalBlackjackWins = storage.totalBlackjackWins || 0;
var totalSlotsSpins = storage.totalSlotsSpins || 0;
var totalMoneyWon = storage.totalMoneyWon || 0;
var totalMoneyLost = storage.totalMoneyLost || 0;
var maxCascades = storage.maxCascades || 0;
var totalWheelSpins = storage.totalWheelSpins || 0;
var biggestWin = storage.biggestWin || 0;
var longestWinStreak = storage.longestWinStreak || 0;
function showStatisticsScreen() {
// Create dark overlay background
var statsOverlay = LK.getAsset('warning', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.95
});
statsOverlay.x = 1024;
statsOverlay.y = 1366;
statsOverlay.alpha = 0;
game.addChild(statsOverlay);
// Create title
var statsTitle = new Text2('π PLAYER STATISTICS π', {
size: 72,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
statsTitle.anchor.set(0.5, 0.5);
statsTitle.x = 1024;
statsTitle.y = 400;
statsTitle.alpha = 0;
game.addChild(statsTitle);
// Create statistics displays
var yPosition = 650;
var statsDisplays = [];
// Calculate blackjack win percentage
var bjWinPercentage = totalBlackjackHands > 0 ? Math.round(totalBlackjackWins / totalBlackjackHands * 100) : 0;
// Statistics to display
var statistics = [{
label: 'Current Money:',
value: '$' + playerMoney
}, {
label: 'Total Money Won:',
value: '$' + totalMoneyWon
}, {
label: 'Total Money Lost:',
value: '$' + totalMoneyLost
}, {
label: 'Biggest Single Win:',
value: '$' + biggestWin
}, {
label: 'Blackjack Hands Played:',
value: totalBlackjackHands.toString()
}, {
label: 'Blackjack Win Rate:',
value: bjWinPercentage + '%'
}, {
label: 'Longest Win Streak:',
value: longestWinStreak.toString()
}, {
label: 'Slots Spins:',
value: totalSlotsSpins.toString()
}, {
label: 'Max Cascades Achieved:',
value: maxCascades.toString()
}, {
label: 'Wheel Spins:',
value: totalWheelSpins.toString()
}, {
label: 'Free Spins Available:',
value: freeSpins.toString()
}];
for (var i = 0; i < statistics.length; i++) {
var stat = statistics[i];
// Stat background
var statBg = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 1400,
height: 120
});
statBg.x = 1024;
statBg.y = yPosition;
statBg.alpha = 0;
game.addChild(statBg);
statsDisplays.push(statBg);
// Stat label
var labelText = new Text2(stat.label, {
size: 36,
fill: '#FFFFFF',
font: "'Arial Black', Arial, sans-serif"
});
labelText.anchor.set(0, 0.5);
labelText.x = 400;
labelText.y = yPosition;
labelText.alpha = 0;
game.addChild(labelText);
statsDisplays.push(labelText);
// Stat value
var valueText = new Text2(stat.value, {
size: 36,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
valueText.anchor.set(1, 0.5);
valueText.x = 1648;
valueText.y = yPosition;
valueText.alpha = 0;
game.addChild(valueText);
statsDisplays.push(valueText);
yPosition += 140;
}
// Close button
var closeStatsButton = new GameButton('CLOSE', 200, 80);
closeStatsButton.x = 1024;
closeStatsButton.y = 2200;
closeStatsButton.alpha = 0;
game.addChild(closeStatsButton);
// Animate all elements in with staggered timing
tween(statsOverlay, {
alpha: 0.95
}, {
duration: 300
});
tween(statsTitle, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
delay: 100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(statsTitle, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Animate statistics displays
for (var i = 0; i < statsDisplays.length; i++) {
(function (display, index) {
tween(display, {
alpha: 1
}, {
duration: 300,
delay: 200 + index * 30,
easing: tween.easeOut
});
})(statsDisplays[i], i);
}
tween(closeStatsButton, {
alpha: 1
}, {
duration: 300,
delay: 600
});
// Close button handler
closeStatsButton.up = function () {
// Animate out
var allElements = [statsOverlay, statsTitle, closeStatsButton].concat(statsDisplays);
var elementsToDestroy = 0;
var totalElements = allElements.length;
for (var i = 0; i < allElements.length; i++) {
tween(allElements[i], {
alpha: 0
}, {
duration: 300,
delay: i * 10,
onFinish: function onFinish() {
elementsToDestroy++;
if (elementsToDestroy === totalElements) {
// Destroy all elements
for (var j = 0; j < allElements.length; j++) {
if (allElements[j] && allElements[j].destroy) {
allElements[j].destroy();
}
}
}
}
});
}
};
}
function showAchievementsScreen() {
// Create dark overlay background
var achievementOverlay = LK.getAsset('warning', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.95
});
achievementOverlay.x = 1024;
achievementOverlay.y = 1366;
achievementOverlay.alpha = 0;
game.addChild(achievementOverlay);
// Create title
var achievementTitle = new Text2('π ACHIEVEMENTS π', {
size: 72,
fill: '#FFD700',
font: "'Arial Black', Arial, sans-serif"
});
achievementTitle.anchor.set(0.5, 0.5);
achievementTitle.x = 1024;
achievementTitle.y = 500;
achievementTitle.alpha = 0;
game.addChild(achievementTitle);
// Create achievement displays
var yPosition = 750;
var achievementDisplays = [];
for (var key in achievementSystem.achievements) {
var achievement = achievementSystem.achievements[key];
// Achievement container
var achievementBg = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: 1400,
height: 200,
alpha: achievement.unlocked ? 1.0 : 0.4
});
achievementBg.x = 1024;
achievementBg.y = yPosition;
achievementBg.alpha = 0;
game.addChild(achievementBg);
achievementDisplays.push(achievementBg);
// Achievement icon/status
var statusIcon = new Text2(achievement.unlocked ? 'β
' : 'π', {
size: 48,
fill: achievement.unlocked ? '#00FF00' : '#888888',
font: "'Arial Black', Arial, sans-serif"
});
statusIcon.anchor.set(0.5, 0.5);
statusIcon.x = 400;
statusIcon.y = yPosition - 30;
statusIcon.alpha = 0;
game.addChild(statusIcon);
achievementDisplays.push(statusIcon);
// Achievement title
var titleText = new Text2(achievement.title, {
size: 42,
fill: achievement.unlocked ? '#FFD700' : '#CCCCCC',
font: "'Arial Black', Arial, sans-serif"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = yPosition - 30;
titleText.alpha = 0;
game.addChild(titleText);
achievementDisplays.push(titleText);
// Achievement description
var descText = new Text2(achievement.description, {
size: 32,
fill: achievement.unlocked ? '#FFFFFF' : '#999999',
font: "'Arial Black', Arial, sans-serif"
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = yPosition + 20;
descText.alpha = 0;
game.addChild(descText);
achievementDisplays.push(descText);
// Achievement reward
var rewardText = new Text2('Reward: +$' + achievement.reward, {
size: 28,
fill: achievement.unlocked ? '#00FF00' : '#666666',
font: "'Arial Black', Arial, sans-serif"
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 1648;
rewardText.y = yPosition;
rewardText.alpha = 0;
game.addChild(rewardText);
achievementDisplays.push(rewardText);
yPosition += 250;
}
// Close button
var closeButton = new GameButton('CLOSE', 200, 80);
closeButton.x = 1024;
closeButton.y = 2200;
closeButton.alpha = 0;
game.addChild(closeButton);
// Animate all elements in with staggered timing
tween(achievementOverlay, {
alpha: 0.95
}, {
duration: 300
});
tween(achievementTitle, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
delay: 100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(achievementTitle, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Animate achievement displays
for (var i = 0; i < achievementDisplays.length; i++) {
(function (display, index) {
tween(display, {
alpha: 1
}, {
duration: 300,
delay: 200 + index * 50,
easing: tween.easeOut
});
})(achievementDisplays[i], i);
}
tween(closeButton, {
alpha: 1
}, {
duration: 300,
delay: 600
});
// Close button handler
closeButton.up = function () {
// Animate out
var allElements = [achievementOverlay, achievementTitle, closeButton].concat(achievementDisplays);
var elementsToDestroy = 0;
var totalElements = allElements.length;
for (var i = 0; i < allElements.length; i++) {
tween(allElements[i], {
alpha: 0
}, {
duration: 300,
delay: i * 20,
onFinish: function onFinish() {
elementsToDestroy++;
if (elementsToDestroy === totalElements) {
// Destroy all elements
for (var j = 0; j < allElements.length; j++) {
if (allElements[j] && allElements[j].destroy) {
allElements[j].destroy();
}
}
}
}
});
}
};
}
billetes de dolar. In-Game asset. 2d. High contrast. No shadows
Pila de cartas visto desde atras. In-Game asset. 2d. High contrast. No shadows
"Crea un asset de fondo para la mesa de Blackjack de un casino virtual, disenΜada especiΜficamente para un solo jugador. CaracteriΜsticas visuales: Material: Debe ser un fieltro de casino de alta calidad. El color principal debe ser un verde esmeralda profundo y rico, con una textura sutil que simule el fieltro real (sin ser demasiado ruidosa o distractora). DisenΜo de la Mesa: Incluye las liΜneas y marcadores claΜsicos de una mesa de Blackjack, adaptada para un uΜnico jugador: Un arco o semiciΜrculo claro para la posicioΜn del crupier, ubicado en la parte superior de la mesa. Una uΜnica aΜrea claramente definida para la posicioΜn del jugador, ubicada frente a la posicioΜn del crupier. Esta posicioΜn debe tener un ciΜrculo para la apuesta. Un aΜrea designada para las cartas del crupier. Si es posible, incluye un texto sutil y elegante en dorado o blanco que indique las reglas baΜsicas del Blackjack, como "BLACKJACK PAYS 3 TO 2" y "DEALER MUST HIT ON SOFT 17" (o las reglas que prefiera. In-Game asset. 2d. High contrast. No shadows
Ambiente: Un interior de casino elegante y nocturno. Elementos: PodriΜa mostrar una vista parcial de mesas de juego (Blackjack, ruleta, tragamonedas) en el fondo, desenfocadas para no distraer. Luces ambientales caΜlidas y doradas, reflejos sutiles. Detalles arquitectoΜnicos de lujo: columnas, arcos, laΜmparas de aranΜa (parcialmente visibles). Una alfombra lujosa o suelo brillante. Paleta de Colores: Predominan los dorados, rojos profundos, negros elegantes y toques de verde esmeralda. Perspectiva: Una vista amplia y acogedora, como si el jugador estuviera entrando al casino. SensacioΜn: SofisticacioΜn, exclusividad, y la emocioΜn de lo que estaΜ por venir. Debe invitar a explorar el juego. El fondo debe ser inmersivo y coherente con la temaΜtica general del casino. In-Game asset. 2d. High contrast. No shadows
Objetivo: Crear un ambiente de casino vibrante y emocionante, enfocado en las tragamonedas, que invite a jugar. DisenΜo: Ambiente: Interior de un casino, con un enfoque en la zona de maΜquinas tragamonedas. Elementos: Filas o grupos de maΜquinas tragamonedas (parcialmente visibles, desenfocadas en el fondo para no competir con la maΜquina principal). Luces brillantes y parpadeantes tiΜpicas de las tragamonedas (efecto de neoΜn, destellos). Detalles de lujo: alfombras estampadas, iluminacioΜn ambiental dorada/roja. PodriΜa haber una pared decorativa elegante o cortinas de terciopelo. Paleta de Colores: Predominan los dorados, rojos, puΜrpuras y negros, con destellos de colores vibrantes de las luces de las maΜquinas. Perspectiva: Una vista ligeramente elevada o de frente, como si el jugador estuviera inmerso en la sala de tragamonedas. SensacioΜn: EnergiΜa, emocioΜn, oportunidad de ganar y un ambbiente de juego constante. El fondo debe ser inmersivo y complementar la maΜquina tragamonedas. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para una maΜquina tragamonedas estilo Megaways, coherente con 'La TentacioΜn Dorada'. DisenΜo Central Megaways: Rodillos DinaΜmicos: Muestra una configuracioΜn de 6 rodillos verticales, donde la altura de cada rodillo puede variar de forma dinaΜmica (mostrando entre 2 y 7 siΜmbolos por rodillo). Esto debe ser visualmente aparente, quizaΜs con indicadores de siΜmbolos en la parte superior/inferior de cada rodillo (necesito que dejes un hueco en la maquina para que yo ponga los 6 rodillos/slots). Estilo y TemaΜtica: Opulencia: Marco de la maΜquina lujoso, dorado, con detalles intrincados, similar a la tragamonedas principal. Fondo de Rodillos: Oscuro y elegante (negro, azul noche), para resaltar los siΜmbolos.
Quiero un rectangulo elegante con colores dorados en las esquinas. In-Game asset. 2d. High contrast. No shadows
Boton de signo de menos elegante de color dorado con fondo negro. In-Game asset. 2d. High contrast. No shadows
Boton de signo de mas elegante de color dorado con fondo negro. In-Game asset. 2d. High contrast. No shadows
Un diamante grande, multifacetado, con destellos luminosos y un brillo intenso. Debe parecer una joya preciosa. Colores claros y transluΜcidos (blanco, azul paΜlido) con reflejos iridiscentes. Estilo de casino de lujo. Fondo transparente. Es el siΜmbolo de mayor valor (50x), debe ser visualmente impactante y deslumbrante.. In-Game asset. 2d. High contrast. No shadows
Crea un asset de fondo para el siΜmbolo 'A' de Megaways (Diamante Brillante). Un panel cuadrado o ligeramente redondeado. Fondo de terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde elegante dorado o plateado. Puede tener un patroΜn sutil de filigrana de casino en las esquinas. Debe ser un fondo neutro pero lujoso para que el diamante resalte. Fondo transparente. In-Game asset. 2d. High contrast. No shadows
Crea un asset de fondo para el siΜmbolo 'B' de Megaways (Barra de Oro). Un panel cuadrado o ligeramente redondeado. Fondo de terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde elegante dorado o plateado. Puede tener un patroΜn sutil de filigrana de casino en las esquinas. Debe ser un fondo neutro pero lujoso para que la barra de oro resalte. Fondo transparente. In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'C' de Megaways: el NuΜmero 7 de la Suerte. El diΜgito '7' estilizado, en color dorado o rojo vibrante, con un aura brillante o un ligero efecto de fuego/energiΜa. TipografiΜa audaz y elegante. Debe transmitir suerte y la promesa de un gran premio (30x). Estilo de casino festivo. Fondo transparente. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'C' de Megaways: el NuΜmero 7 de la Suerte, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (el '7'): El diΜgito '7' estilizado, grande y centrado sobre el fondo del panel. Color del '7': Dorado brillante o rojo vibrante, con un aura sutil o un ligero efecto de fuego/energiΜa. TipografiΜa: Audaz y elegante.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'D' de Megaways: una Campana Dorada, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (la Campana): Una campana claΜsica de tragamonedas, con un acabado dorado metaΜlico y pulido, posicionada centralmente. Debe tener un brillo sutil y un disenΜo elegante. Puede tener un pequenΜo lazo o detalles decorativos.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'F' de Megaways: una Herradura Dorada, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (la Herradura): Una herradura claΜsica, de color dorado brillante y con un acabado metaΜlico, posicionada centralmente. Puede tener pequenΜos detalles grabados o incrustaciones sutiles.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'E' de Megaways: Cerezas Lujosas, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (las Cerezas): Dos cerezas rojas, estilizadas para parecer joyas o gemas, con una superficie brillante y reflejos, posicionadas centralmente. El tallo debe ser fino y elegante. Colores: Rojos intensos y brillantes. In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'B' de Megaways: una Barra de Oro. Una barra de oro soΜlida y brillante, con reflejos realistas que sugieran lujo y peso. Puede tener la palabra 'BAR' grabada sutilmente. Estilo de casino opulento. Color dorado intenso. Fondo transparente. Es un siΜmbolo de alto valor (40x), debe transmitir riqueza. In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'D' de Megaways: una Campana Dorada. Una campana claΜsica de tragamonedas, pero con un acabado dorado metaΜlico y pulido. Debe tener un brillo sutil y un disenΜo elegante. Puede tener un pequenΜo lazo o detalles decorativos. Estilo de casino tradicional y lujoso. Fondo transparente. SiΜmbolo de ganancias (25x). In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'E' de Megaways: Cerezas Lujosas. Dos cerezas rojas, estilizadas para parecer joyas o gemas, con una superficie brillante y reflejos. El tallo debe ser fino y elegante. Colores rojos intensos y brillantes. Estilo de casino sofisticado. Fondo transparente. Un giro elegante a un claΜsico (20x). In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'F' de Megaways: una Herradura Dorada. Una herradura claΜsica, pero de color dorado brillante y con un acabado metaΜlico. Puede tener pequenΜos detalles grabados o incrustaciones sutiles. Debe transmitir buena suerte y fortuna (15x). Estilo de casino elegante. Fondo transparente. Un amuleto de la suerte.. In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'S' (Scatter) de Megaways: un Cofre del Tesoro o Bolsa de Dinero. Un cofre del tesoro abierto, desbordando monedas de oro y joyas, o una bolsa de dinero con el signo '$'. Debe ser visualmente atractivo y sugerir una recompensa. Colores dorados, marrones y brillantes. Estilo de casino de aventura. Fondo transparente. SiΜmbolo de bonificacioΜn. In-Game asset. 2d. High contrast. No shadows
Crea un asset para el siΜmbolo 'W' (Wild/ComodiΜn) de Megaways: un ComodiΜn Lujoso. La palabra 'WILD' en una fuente llamativa y dinaΜmica. Colores vibrantes (ej. verde esmeralda brillante, azul eleΜctrico) con un contorno dorado o un efecto de arcoiΜris. Puede tener un pequenΜo destello o un aura de energiΜa. Debe comunicar su funcioΜn de sustitucioΜn. Fondo transparente. SiΜmbolo de sorpresa. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'W' (Wild/ComodiΜn) de Megaways, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (la palabra 'WILD'): La palabra 'WILD' en una fuente llamativa y dinaΜmica, posicionada centralmente. Colores: Vibrantes (ej. verde esmeralda brillante, azul eleΜctrico) con un contorno dorado o un efecto de arcoiΜris. Puede tener un pequenΜo destello o un aura de energiΜa.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual completo para el siΜmbolo 'S' (Scatter) de Megaways: un Cofre del Tesoro o Bolsa de Dinero, directamente sobre su panel de fondo. DisenΜo General: Forma: Un panel cuadrado o ligeramente redondeado. Fondo del Panel: Terciopelo oscuro (negro o azul noche) o un metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del panel. Detalles del Fondo: Puede tener un patroΜn sutil de filigrana de casino en las esquinas del panel. SiΜmbolo Central (Cofre/Bolsa): Un cofre del tesoro abierto desbordando monedas de oro y joyas, o una bolsa de dinero con el signo '$', posicionada centralmente. Colores: Dorados, marrones y brillantes.. In-Game asset. 2d. High contrast. No shadows
Β‘Entendido! Un botoΜn de "SPIN" ovalado con un estilo similar al de los siΜmbolos de los slots de Megaways. AquiΜ tienes el prompt ajustado: Prompt para Upit: Asset BotoΜn "SPIN" Ovalado (Estilo SiΜmbolos) "Crea un asset visual ovalado para el botoΜn 'SPIN' de la maΜquina tragamonedas de lujo, con un estilo que recuerde a los paneles de los siΜmbolos de los slots. Objetivo: Un botoΜn prominente que invite a la accioΜn, refleje la opulencia del casino y tenga una esteΜtica coherente con los siΜmbolos de los rodillos Megaways. DisenΜo: Forma: Ovalada, con proporciones que lo hagan parecer ancho y faΜcil de pulsar. Los bordes pueden ser ligeramente biselados. Material/Textura: Simula un panel similar al fondo de los siΜmbolos de los slots: terciopelo oscuro (negro o azul noche) o metal pulido muy oscuro. Borde: Un borde elegante dorado o plateado alrededor del oΜvalo, como los bordes de los siΜmbolos. Texto: La palabra 'SPIN' en el centro, en mayuΜsculas, con una tipografiΜa audaz y elegante de casin. In-Game asset. 2d. High contrast. No shadows
Β‘Entendido! Si el botoΜn "Home" se pierde en el fondo de la tragamonedas, necesitamos darle un estilo que lo haga destacar maΜs, manteniendo la coherencia con "La TentacioΜn Dorada". AquiΜ tienes un prompt con un enfoque diferente: Prompt para Upit: Asset BotoΜn "HOME" (Estilo Destacado) "Crea un asset visual para un botoΜn 'HOME' (Inicio) de casino de lujo, disenΜado para destacar claramente en la interfaz de la tragamonedas. Objetivo: Un botoΜn faΜcilmente visible y reconocible para regresar al menuΜ principal, con un estilo que contraste con el fondo de la tragamonedas pero que siga siendo elegante. DisenΜo: Forma: Un ciΜrculo o un oΜvalo con un color de base soΜlido y llamativo que contraste con los tonos oscuros y brillantes de la tragamonedas. Considera un rojo rubiΜ intenso, un verde esmeralda brillante o un dorado maΜs saturado. SiΜmbolo Central: Un icono de casa estilizado y elegante en blanco puro o dorado brillante, para que resalte sobre el color de base. TambieΜn podriΜa ser la palabra. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para un panel de visualizacioΜn del 'BALANCE' del jugador, con la palabra 'BALANCE' ubicada en la parte superior. Objetivo: Un espacio claro, elegante y prominente para mostrar el saldo monetario, coherente con la esteΜtica de lujo del casino 'La TentacioΜn Dorada', con la etiqueta 'BALANCE' en la parte superior para facilitar su identificacioΜn. DisenΜo: Forma: Un panel rectangular horizontal, con bordes suavemente redondeados o un disenΜo elegante. Material/Textura: Acabado metaΜlico pulido (dorado, plateado) o un fondo de terciopelo oscuro (negro, rojo vino, azul noche). Texto Fijo (Arriba): La palabra 'BALANCE' (o 'SALDO') debe ubicarse en la parte superior del panel, centrada o alineada a la izquierda/derecha seguΜn el disenΜo. Utiliza una tipografiΜa limpia, legible y de estilo casino, en un tamanΜo adecuado para ser una etiqueta. Espacio para el Valor (Abajo): Debe haber un espacio claro y destacado debajo de la palabra 'BALANCE' para que el valor numeΜrico del sa. In-Game asset. 2d. High contrast. No shadows
Fondo oscuro con dorado elegante. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para el botoΜn 'DEAL' (Repartir) para la mesa de Blackjack de lujo. Objetivo: Un botoΜn claro y elegante que inicie la ronda de Blackjack, coherente con la opulencia del casino. DisenΜo: Forma: Puede ser un oΜvalo o un rectaΜngulo con bordes suaves, que sea prominente y faΜcil de pulsar. Texto Central: La palabra 'DEAL' (o 'REPARTIR') en mayuΜsculas, con una tipografiΜa audaz, limpia y elegante de casino. Color: Base en un color dorado brillante o metaΜlico, que simule oro pulido. Puede tener un borde o un acento en rojo rubiΜ o verde esmeralda para complementar la paleta del casino. Efectos (si Upit lo permite): Sutil efecto de relieve o biselado para darle profundidad. Un ligero brillo o resplandor que sugiera energiΜa y anticipacioΜn. Textura que simule metal pulido o un material lujoso. Fondo: El asset debe ser independiente con fondo transparente, listo para ser superpuesto en la interfaz de la mesa de Blackjack.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para el botoΜn 'HIT' (Pedir Carta) para la mesa de Blackjack de lujo. Objetivo: Un botoΜn claro y elegante que permita al jugador pedir otra carta, coherente con la opulencia del casino. DisenΜo: Forma: OΜvalo o rectaΜngulo con bordes suaves, prominente y faΜcil de pulsar. Texto Central: La palabra 'HIT' (o 'PEDIR') en mayuΜsculas, con tipografiΜa audaz, limpia y elegante de casino. Color: Base en un color que transmita accioΜn, como un rojo rubiΜ vibrante o un naranja aΜmbar, con acabado metaΜlico o pulido. Borde: Un borde brillante en dorado o plateado. Efectos (si Upit lo permite): Sutil efecto de relieve o biselado para darle profundidad. Un ligero brillo o resplandor que lo haga destacar. Textura que simule metal pulido o un material lujoso. Fondo: Asset independiente con fondo transparente.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para el botoΜn 'STAND' (Plantarse) para la mesa de Blackjack de lujo. Objetivo: Un botoΜn claro y elegante que permita al jugador finalizar su turno, coherente con la opulencia del casino. DisenΜo: Forma: OΜvalo o rectaΜngulo con bordes suaves, prominente y faΜcil de pulsar. Texto Central: La palabra 'STAND' (o 'PLANTARSE') en mayuΜsculas, con tipografiΜa audaz, limpia y elegante de casino. Color: Base en un color que contraste con 'HIT' y 'DEAL' pero mantenga la elegancia. Considera un verde esmeralda profundo o un azul zafiro, con acabado metaΜlico o pulido. Borde: Un borde brillante en dorado o plateado. Efectos (si Upit lo permite): Sutil efecto de relieve o biselado para darle profundidad. Un ligero brillo o resplandor que lo haga destacar. Textura que simule metal pulido o un material lujoso. Fondo: Asset independiente con fondo transparente. SensacioΜn: Debe transmitir decisioΜn, control y la profesionalidad del juego.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para el botoΜn 'DOUBLE' (Doblar Apuesta) para la mesa de Blackjack de lujo. Objetivo: Un botoΜn claro y elegante que permita al jugador doblar su apuesta, coherente con la opulencia del casino. DisenΜo: Forma: OΜvalo o rectaΜngulo con bordes suaves, prominente y faΜcil de pulsar. Texto Central: La palabra 'DOUBLE' (o 'DOBLAR') en mayuΜsculas, con tipografiΜa audaz, limpia y elegante de casino. Color: Base en un color que sugiera riesgo/recompensa, como un puΜrpura real o un dorado maΜs oscuro, con acabado metaΜlico o pulido. Borde: Un borde brillante en dorado o plateado. Efectos (si Upit lo permite): Sutil efecto de relieve o biselado para darle profundidad. Un ligero brillo o resplandor que lo haga destacar. Textura que simule metal pulido o un material lujoso. Fondo: Asset independiente con fondo transparente.. In-Game asset. 2d. High contrast. No shadows
"Crea un asset visual para un panel de visualizacioΜn del 'BET' actual del jugador en la mesa de Blackjack. Objetivo: Un espacio claro y elegante para mostrar la cantidad apostada, integrado en la interfaz de la mesa de Blackjack, coherente con el lujo del casino. DisenΜo: Forma: Un panel rectangular horizontal o un oΜvalo alargado, con bordes suaves o un disenΜo elegante. Material/Textura: Acabado metaΜlico pulido (dorado, plateado) o un fondo de terciopelo oscuro (negro, rojo vino, azul noche). Texto Fijo: La palabra 'BET:' debe estar claramente visible en el panel, en una tipografiΜa limpia, legible y de estilo casino. Espacio para el Valor: Debe haber un espacio claro y destacado junto a la palabra 'BET:' para que el valor numeΜrico de la apuesta pueda ser insertado dinaΜmicamente. Color del Texto Fijo: Dorado brillante, blanco puro o un color que contraste bien con el fondo del panel. Color del Valor: Un color que destaque y sea faΜcil de leer (podriΜa ser el mismo que el texto fijo. In-Game asset. 2d. High contrast. No shadows
Crea un asset para una ficha de casino de $1 para Blackjack. Color Principal: Blanco o gris muy claro. Borde/Detalles: Dos o tres franjas finas en un color que contraste pero sea elegante, como azul zafiro o verde esmeralda. Valor: El nuΜmero '1' grande y claro en el centro, en dorado o negro, con una tipografiΜa de casino. Estilo: Lujoso, limpio, coherente con 'La TentacioΜn Dorada'.". In-Game asset. 2d. High contrast. No shadows
"Crea un asset para una ficha de casino de $10 para Blackjack. Color Principal: Azul zafiro profundo o un azul medianoche. Borde/Detalles: Dos o tres franjas finas en un color que contraste, como blanco o dorado. Valor: El nuΜmero '10' grande y claro en el centro, en dorado o blanco, con una tipografiΜa de casino. Estilo: Lujoso, elegante, coherente con 'La TentacioΜn Dorada'.". In-Game asset. 2d. High contrast. No shadows que el texto blackjack ete arriba
"Crea un asset para una ficha de casino de $25 para Blackjack. Color Principal: Verde esmeralda brillante o un verde bosque profundo. Borde/Detalles: Dos o tres franjas finas en un color que contraste, como blanco o dorado. Valor: El nuΜmero '25' grande y claro en el centro, en dorado o blanco, con una tipografiΜa de casino. Estilo: Lujoso, distintivo, coherente con 'La TentacioΜn Dorada'.". In-Game asset. 2d. High contrast. No shadows
"Crea un asset para una ficha de casino de $100 para Blackjack. Color Principal: Negro obsidiana o un puΜrpura real profundo. Borde/Detalles: Dos o tres franjas finas en un color que contraste fuertemente, como dorado brillante o blanco. Valor: El nuΜmero '100' grande y claro en el centro, en dorado o blanco, con una tipografiΜa de casino. Estilo: Lujoso, premium, coherente con 'La TentacioΜn Dorada'. Esta debe ser la maΜs impresionante visualmente.". In-Game asset. 2d. High contrast. No shadows que el texto blackjack se encuentre arriba
Crea un asset para una ficha de casino de $500 para Blackjack. Color Principal: Un color muy distintivo y premium, como un dorado soΜlido y brillante, un plateado metaΜlico o un negro azabache con un brillo iridiscente. Borde/Detalles: Un borde maΜs grueso y prominente en un color que contraste fuertemente (ej., negro sobre dorado, dorado sobre negro), y quizaΜs un patroΜn de filigrana maΜs elaborado o un disenΜo de corona/estrella discreto. Valor: El nuΜmero '500' grande y claro en el centro, en un color que destaque (ej., blanco, negro, o un color metaΜlico si el fondo es oscuro), con una tipografiΜa de casino audaz y elegante. Estilo: Extremadamente lujoso y premium, debe ser la ficha maΜs impresionante visualmente, coherente con 'La TentacioΜn Dorada'. Efectos: Un brillo intenso o reflejos que sugieran un material de altiΜsima calidad. Fondo: Transparente (solo la ficha)." que el texto de blackjack este aarriba. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para un botoΜn 'REMOVE' (Quitar Apuesta) para la mesa de Blackjack de lujo. Objetivo: Un botoΜn claro y elegante que permita al jugador quitar su apuesta actual y regresarla a cero, coherente con la opulencia del casino. DisenΜo: Forma: Puede ser un oΜvalo o un rectaΜngulo con bordes suaves, que sea prominente y faΜcil de pulsar. Texto Central: La palabra 'REMOVE' (o 'CLEAR BET') en mayuΜsculas, con una tipografiΜa audaz, limpia y elegante de casino. Color: Base en un color que sugiera "borrar" o "resetear" sin ser estridente. Considera un gris oscuro metaΜlico, un plateado pulido o un bronce oscuro, con un acabado elegante. Borde: Un borde brillante en dorado o plateado. Efectos (si Upit lo permite): Sutil efecto de relieve o biselado para darle profundidad. Un ligero brillo o resplandor que lo haga destacar. Textura que simule metal pulido o un material lujoso. Fondo: El asset debe ser independiente con fondo transparente, listo para ser superpuesto en la inter. In-Game asset. 2d. High contrast. No shadows
Β‘Claro! AquiΜ tienes el prompt para el asset del reverso de las cartas de tu casino, disenΜado para "La TentacioΜn Dorada" y ajustado al liΜmite de 1000 caracteres: Prompt para Upit: Asset Reverso de Cartas de Casino "Crea un asset visual para el reverso de una carta de casino de lujo. Objetivo: Un disenΜo elegante y distintivo que represente la marca 'La TentacioΜn Dorada' y sea visualmente atractivo en la mesa de Blackjack. DisenΜo: Forma: Rectangular, como el reverso de una carta de poΜker estaΜndar. Color Principal: Un color profundo y rico que evoque lujo, como un rojo burdeos oscuro, un verde esmeralda profundo o un azul medianoche. PatroΜn Central: Un disenΜo simeΜtrico y ornamentado en el centro. PodriΜa ser: Un patroΜn de filigrana dorada intrincada. El logo estilizado de 'La TentacioΜn Dorada' (si lo tienes definido, de lo contrario, un disenΜo abstracto de lujo). Un patroΜn geomeΜtrico elegante con toques dorados. Borde: Un borde fino y elegante en dorado o plateado alrededor de tod. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual de botoΜn ovalado/rectangular para 'BLACKJACK' en el menuΜ principal. DisenΜo: Texto 'BLACKJACK' en tipografiΜa de casino, centrado. Color base rojo rubiΜ, verde esmeralda o azul zafiro profundo (metaΜlico/pulido). Borde grueso y brillante dorado o plateado. Efecto de relieve/biselado y brillo sutil. Fondo transparente. Objetivo: BotoΜn lujoso, prominente y que invite al juego.. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para un banner de bienvenida arqueado de casino de lujo. DisenΜo: Forma de arco elegante. Texto central: 'WELCOME TO LA TENTACIOΜN DORADA' (o 'WELCOME, HIGH ROLLER'). TipografiΜa de casino elegante, mayuΜsculas. Fondo del arco: Negro, rojo burdeos o azul medianoche profundo (pulido/terciopelo). Texto y borde: Dorado o plateado brillante (metaΜlico). Detalles: Filigranas doradas sutiles, brillos. Efecto: Ligero relieve y resplandor. Fondo transparente. Objetivo: Bienvenida opulenta y exclusiva.. In-Game asset. 2d. High contrast. No shadows
quiero el reloj mas detallado y en un etilo mas realista
Mano de una persona femenina con camisa blanca vista desde arriba con un estilo realista. In-Game asset. 2d. High contrast. No shadows
Copa de logros elegante en colores dorados oscuros y brillantes. In-Game asset. 2d. High contrast. No shadows
Β‘Mil disculpas por la confusioΜn! Tienes toda la razoΜn. No es una ruleta de casino, sino una "ruleta de premios" o "rueda de la fortuna" para recompensas. AquiΜ tienes el prompt corregido para el asset del icono de la Rueda de Premios que apareceraΜ en el menuΜ principal, disenΜado para tu casino "La TentacioΜn Dorada" y con el texto en ingleΜs para Upit: Prompt for Upit: Asset 'Prize Wheel' Icon (Main Menu) "Create a visual asset for an icon representing a 'Prize Wheel' or 'Reward Wheel' for the main menu of the luxury casino 'La TentacioΜn Dorada'. Objective: A clear, attractive, and clickable icon that invites players to access the reward system, distinct from a gambling roulette. Design: Shape: Circular, mimicking a classic prize wheel. Central Element: A stylized prize wheel showing various sections, each implying a different reward (e.g., a star, a gift box silhouette, a coin symbol, a trophy, or just abstract 'prize' sections). It should have a prominent pointer at the top.. In-Game asset. 2d. High contrast. No shadows
Carta de email elegante. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para un lujoso marcador o indicador de premio para la rueda de recompensas de 'La TentacioΜn Dorada'. Objetivo: Un elemento claro y elegante que indique visualmente el premio ganador en la rueda. DisenΜo: Forma: Puede ser una flecha estilizada, un pequenΜo colgante o un puntero refinado con un elemento decorativo. Material/Color: Debe tener un aspecto premium, utilizando oro pulido o plata como color principal. Detalles: Si es una flecha, debe ser elegante y bien definida, quizaΜs con una pequenΜa joya o un detalle grabado cerca de la punta. Si es un colgante, podriΜa ser una versioΜn estilizada del logo del casino o una forma geomeΜtrica con un acabado lujoso. AseguΜrate de que tenga una direccioΜn clara de 'apuntado'. Elemento de Posicionamiento: Debe tener un punto o borde claro que se alinee con precisioΜn con las divisiones entre las secciones de premios en la rueda. IluminacioΜn/Efectos (si Upit lo permite): Un brillo sutil o destellos para llamar la atencioΜn s. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para una indicacioΜn de accioΜn que diga 'Spin Here' con una flecha decorativa senΜalando a la derecha. Objetivo: Guiar al usuario a un botoΜn de giro o a una zona interactiva, con un toque de lujo y dinamismo. DisenΜo: Texto: La frase 'Spin Here' en una tipografiΜa de casino elegante, clara y legible. El texto debe ser prominente. Color del Texto: Dorado brillante o plateado pulido, con reflejos sutiles. Flecha: Una flecha que apunte claramente hacia la derecha. Estilo de la Flecha: Debe tener un disenΜo ligeramente 'enredado' o 'enrollado', como si fuera una cinta de oro o un elemento de filigrana que se desenrolla para formar la flecha. No debe ser una flecha simple y recta. Color de la Flecha: Dorado brillante o plateado pulido, a juego con el texto. Efectos: Sutiles brillos y sombras para darle volumen y un aspecto metaΜlico. ComposicioΜn: El texto 'Spin Here' y la flecha deben estar visualmente conectados, formando un solo asset cohesivo. La flecha puede sali. In-Game asset. 2d. High contrast. No shadows
Crea un asset visual para un botoΜn de interfaz de usuario que diga 'Stats' en ingles. Objetivo: Proporcionar un botoΜn claro y atractivo para acceder a las estadiΜsticas del jugador. DisenΜo: Forma: Un botoΜn con bordes suaves o ligeramente redondeados, o una forma que sugiera una plaqueta o emblema de lujo. Texto: La palabra 'EstadiΜsticas' en una tipografiΜa elegante, clara y legible. El texto debe ser prominente y centrado en el botoΜn. Color Base: Un fondo que sea consistente con la interfaz de tu casino, como un azul profundo, puΜrpura oscuro, negro carboΜn o un color metaΜlico brunΜido. Color del Texto/Borde: Dorado brillante, plateado pulido o bronce con un acabado metaΜlico y reflejos sutiles.. In-Game asset. 2d. High contrast. No shadows
Menu
Music
BJ
Music
SpinM
Music
SpinHere
Sound effect
Giro
Sound effect
Premio
Sound effect
premio
Sound effect
RuedaMusic
Music
Rodillos
Sound effect
Detencion
Sound effect
Simbolo
Sound effect
Explosion
Sound effect
Cuprier_Menu_1
Sound effect
Cuprier_Menu_2
Sound effect
Cuprier_Menu_3
Sound effect
Ficha_1
Sound effect
Ficha_2
Sound effect
Baraja
Sound effect
Carta_1
Sound effect
Carta_2
Sound effect
Carta_3
Sound effect
Cuprier_BJ_1
Sound effect
Cuprier_BJ_2
Sound effect
Cuprier_BJ_3
Sound effect
Jugador_Hit_1
Sound effect
Jugador_Hit_2
Sound effect
Jugador_Hit_3
Sound effect
Jugador_Pedir_1
Sound effect
Jugador_Pedir_2
Sound effect
Jugador_Pedir_3
Sound effect
Jugador_Plantarse_1
Sound effect
Jugador_Plantarse_2
Sound effect
Jugador_Pasa_1
Sound effect
Jugador_Pasa_2
Sound effect
Jugador_Pasa_3
Sound effect
Cuprier_Gana_1
Sound effect
Cuprier_Gana_2
Sound effect
Cuprier_Gana_3
Sound effect
Cuprier_Empate_1
Sound effect
Cuprier_Empate_2
Sound effect
Cuprier_Empate_3
Sound effect
Jugador_BlackJack_1
Sound effect
Jugador_BlackJack_2
Sound effect
Jugador_BlackJack_3
Sound effect
Jugador_Plantarse_3
Sound effect
Cuprier_Win_1
Sound effect
Cuprier_Win_2
Sound effect
Cascada
Sound effect
Congratulations
Sound effect
Big_Win
Sound effect
Festejo
Sound effect
Mega_Win
Sound effect
Super_Mega_Win
Sound effect
Jackpot_Win
Sound effect