User prompt
In the bet increase section, put a section where we can increase it by writing it ourselves.
User prompt
When increasing the bet, the bets after 1000 should be increased by 100, those after 5000 by 500, those after 10000 by 1000, and those after 20000 by 2000.
User prompt
change the max bet is 500000
User prompt
add ablack jack a table and make it "bjtable" from the images
User prompt
remove all bg's from blackjack
User prompt
change background and add a fullscreen bg (make it bj table)
User prompt
make croupier bigger (fit with the table)
User prompt
change croupier image to "croupier" image
User prompt
add a croupier
User prompt
fix the croupier bug when player hit the card the croupier card are gone
User prompt
add card deal effects ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
leave space between the bj cards
User prompt
make roulet background blood red and pitch black
User prompt
chane roulette ball with image rouletteball
User prompt
change roulette wheel and make the numbers visible on it
User prompt
change roulette background with RouletteBG image
User prompt
add a roulette table background
User prompt
more down
User prompt
more down
User prompt
move down the red and black bet sign
User prompt
move roulet wheel to the more up
User prompt
more space
User prompt
leave space between split bet keyboard and make them a little bigger
User prompt
leave space between red and black bet buttons
User prompt
more down
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // --- Blackjack Game Logic --- var BlackjackGame = Container.expand(function () { var self = Container.call(this); // State self.currentSeat = 0; // Track which seat is currently active self.deck = []; self.playerHand = []; self.dealerHand = []; self.playerCards = []; self.dealerCards = []; self.state = 'bet'; // 'bet', 'player', 'dealer', 'result', 'betBehind' self.resultText = null; self.buttons = []; self.bet = betAmount; self.betBehind = 0; // Amount bet behind self.betBehindWin = 0; // Track bet behind win for this round // Add Blackjack table background image (bjTable) as the table background var bjTableBg = self.attachAsset('bjTable', { width: 1800, height: 900, anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 700 // position to fit under croupier and cards }); self.addChild(bjTableBg); // Add croupier image above the dealer cards, make it bigger to fit with the table var croupier = self.attachAsset('croupier', { width: 320, height: 320, anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 900 - 80 // slightly above dealer cards }); self.addChild(croupier); // Deal new deck self.newDeck = function () { var suits = ['♠', '♥', '♦', '♣']; var ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; var deck = []; for (var s = 0; s < 4; s++) { for (var r = 0; r < 13; r++) { deck.push({ rank: ranks[r], suit: suits[s] }); } } // Shuffle for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = deck[i]; deck[i] = deck[j]; deck[j] = t; } self.deck = deck; }; // Draw a card self.drawCard = function () { if (self.deck.length === 0) self.newDeck(); return self.deck.pop(); }; // Calculate hand value self.handValue = function (hand) { var value = 0; var aces = 0; for (var i = 0; i < hand.length; i++) { var r = hand[i].rank; if (r === 'A') { value += 11; aces++; } else if (r === 'K' || r === 'Q' || r === 'J') { value += 10; } else { value += parseInt(r); } } while (value > 21 && aces > 0) { value -= 10; aces--; } return value; }; // Start a new round self.startRound = function () { self.state = 'player'; self.playerHand = []; self.dealerHand = []; self.clearCards(); self.resultText && self.resultText.destroy(); self.resultText = null; // Bet self.bet = betAmount; self.betBehindWin = 0; self.perfectPairWin = false; // Track perfect pair win for this round if (playerBalance < self.bet) { self.showResult('Not enough balance!', true); return; } playerBalance -= self.bet; updateBalance(); // Deal // Deal cards with animation self.playerHand.push(self.drawCard()); self.dealerHand.push(self.drawCard()); self.playerHand.push(self.drawCard()); self.dealerHand.push(self.drawCard()); self.clearCards(); // --- Perfect Pair Side Bet Logic --- // If first two player cards are same rank and same suit, pay 25:1 self.perfectPairWin = false; self.perfectPairPayout = 0; if (self.playerHand.length === 2 && self.playerHand[0].rank === self.playerHand[1].rank && self.playerHand[0].suit === self.playerHand[1].suit) { self.perfectPairWin = true; self.perfectPairPayout = self.bet * 25; playerBalance += self.perfectPairPayout; updateBalance(); // Show a quick popup for perfect pair win var pairText = new Text2('Perfect Pair! +$' + self.perfectPairPayout, { size: 80, fill: 0xFFE066 }); pairText.anchor.set(0.5, 0.5); pairText.x = 2048 / 2; pairText.y = 1550; self.addChild(pairText); tween(pairText, { y: pairText.y - 120, alpha: 0 }, { duration: 1200, onFinish: function onFinish() { pairText.destroy(); } }); } // Card distribution animation var px = 2048 / 2 - 200; var py = 1700; var dx = 2048 / 2 - 200; var dy = 900; var dealDelay = 200; var dealDuration = 350; var dealStartX = 2048 / 2; var dealStartY = 1200; self.playerCards = []; self.dealerCards = []; // Helper to animate a card to its position with deal effect function animateCard(card, toX, toY, delay, isPlayer) { card.x = dealStartX; card.y = dealStartY; card.scaleX = 0.2; card.scaleY = 0.2; card.alpha = 0; card.visible = true; self.addChild(card); tween(card, { x: toX, y: toY, scaleX: 1, scaleY: 1, alpha: 1 }, { duration: dealDuration, easing: tween.cubicOut, delay: delay }); if (isPlayer) { self.playerCards.push(card); } else { self.dealerCards.push(card); } } // Create and animate cards in order: player1, dealer1, player2, dealer2 var playerCard1 = new Card(); playerCard1.setCard(self.playerHand[0].rank, self.playerHand[0].suit, true); playerCard1.visible = false; var dealerCard1 = new Card(); dealerCard1.setCard(self.dealerHand[0].rank, self.dealerHand[0].suit, true); dealerCard1.visible = false; var playerCard2 = new Card(); playerCard2.setCard(self.playerHand[1].rank, self.playerHand[1].suit, true); playerCard2.visible = false; var dealerCard2 = new Card(); dealerCard2.setCard(self.dealerHand[1].rank, self.dealerHand[1].suit, false); dealerCard2.visible = false; LK.setTimeout(function () { animateCard(playerCard1, px, py, 0, true); playerCard1.visible = true; LK.setTimeout(function () { animateCard(dealerCard1, dx, dy, 0, false); dealerCard1.visible = true; LK.setTimeout(function () { animateCard(playerCard2, px + 180, py, 0, true); // Increased spacing from 120 to 180 playerCard2.visible = true; LK.setTimeout(function () { animateCard(dealerCard2, dx + 180, dy, 0, false); // Increased spacing from 120 to 180 dealerCard2.visible = true; // After all cards are dealt, show buttons LK.setTimeout(function () { self.showButtons(['Hit', 'Stand']); }, dealDuration); }, dealDelay); }, dealDelay); }, dealDelay); }, 0); }; // Show cards on table self.showHands = function (revealDealer) { if (typeof revealDealer === "undefined") revealDealer = false; self.clearCards(); // Player var px = 2048 / 2 - 200; var py = 1700; for (var i = 0; i < self.playerHand.length; i++) { var c = new Card(); c.setCard(self.playerHand[i].rank, self.playerHand[i].suit, true); c.x = px + i * 180; // Increased spacing from 120 to 180 c.y = py; c.visible = true; // Player cards are visible self.addChild(c); self.playerCards.push(c); } // Dealer var dx = 2048 / 2 - 200; var dy = 900; for (var i = 0; i < self.dealerHand.length; i++) { var c = new Card(); var faceUp = i === 0 || revealDealer; c.setCard(self.dealerHand[i].rank, self.dealerHand[i].suit, faceUp); c.x = dx + i * 180; // Increased spacing from 120 to 180 c.y = dy; c.visible = revealDealer ? true : false; // Show dealer cards only if revealDealer is true self.addChild(c); self.dealerCards.push(c); } }; // Remove card objects self.clearCards = function () { for (var i = 0; i < self.playerCards.length; i++) { self.playerCards[i].destroy(); } for (var i = 0; i < self.dealerCards.length; i++) { self.dealerCards[i].destroy(); } self.playerCards = []; self.dealerCards = []; }; // Show action buttons self.showButtons = function (labels) { for (var i = 0; i < self.buttons.length; i++) { self.buttons[i].destroy(); } self.buttons = []; // If in player state, add Double if allowed (first move, enough balance, only 2 cards) var showDouble = false; if (self.state === 'player' && self.playerHand.length === 2 && playerBalance >= self.bet) { showDouble = true; if (labels.indexOf('Double') === -1) labels.push('Double'); } // Add Bet Behind button if in 'bet' state and player has enough balance if (self.state === 'bet' && playerBalance >= betAmount) { labels.push('Bet Behind'); } var startX = 2048 / 2 - (labels.length - 1) * 220; for (var i = 0; i < labels.length; i++) { var btn = new GameButton(); btn.setText(labels[i]); btn.x = startX + i * 440; btn.y = 2100; btn.action = labels[i]; btn.down = function () { this.flash(); if (this.action === 'Bet Behind') { // Place bet behind if (playerBalance >= betAmount) { self.betBehind += betAmount; playerBalance -= betAmount; updateBalance(); // Show quick popup for bet behind placed var bbText = new Text2('Bet Behind: $' + self.betBehind, { size: 70, fill: 0x66ffcc }); bbText.anchor.set(0.5, 0.5); bbText.x = 2048 / 2; bbText.y = 2000; self.addChild(bbText); tween(bbText, { y: bbText.y - 80, alpha: 0 }, { duration: 900, onFinish: function onFinish() { bbText.destroy(); } }); } } else { self.handleAction(this.action); } }; self.addChild(btn); self.buttons.push(btn); } }; // Handle player actions self.handleAction = function (action) { if (self.state !== 'player') return; if (action === 'Hit') { self.playerHand.push(self.drawCard()); self.showHands(false); //{21} // Always show dealer's first card only until round ends var val = self.handValue(self.playerHand); if (val > 21) { self.state = 'result'; self.showHands(true); self.showResult('Bust! You lose.'); } } else if (action === 'Stand') { self.state = 'dealer'; self.showHands(true); self.showButtons([]); self.dealerTurn(); } else if (action === 'Double') { // Double the bet, draw one card, then stand if (playerBalance >= self.bet && self.playerHand.length === 2) { playerBalance -= self.bet; self.bet *= 2; updateBalance(); self.playerHand.push(self.drawCard()); self.showHands(false); //{2f} // Always show dealer's first card only until round ends var val = self.handValue(self.playerHand); if (val > 21) { self.state = 'result'; self.showHands(true); self.showResult('Bust! You lose.'); } else { self.state = 'dealer'; self.showHands(true); self.showButtons([]); self.dealerTurn(); } } } }; // Dealer logic self.dealerTurn = function () { var self_ = self; var dealerVal = self.handValue(self.dealerHand); var playerVal = self.handValue(self.playerHand); function dealerStep() { dealerVal = self_.handValue(self_.dealerHand); if (dealerVal < 17) { self_.dealerHand.push(self_.drawCard()); self_.showHands(true); LK.setTimeout(dealerStep, 700); } else { self_.state = 'result'; self_.showHands(true); self_.showResult(self_.getResultText()); } } LK.setTimeout(dealerStep, 700); }; // Determine result self.getResultText = function () { var playerVal = self.handValue(self.playerHand); var dealerVal = self.handValue(self.dealerHand); if (playerVal > 21) return 'Bust! You lose.'; // Dealer busts if (dealerVal > 21) { playerBalance += self.bet * 2; // Bet behind wins if player hand not bust if (self.betBehind > 0 && playerVal <= 21) { self.betBehindWin = self.betBehind * 2; playerBalance += self.betBehindWin; } updateBalance(); return 'Dealer busts! You win!' + (self.betBehindWin > 0 ? '\nBet Behind Win: $' + self.betBehindWin : ''); } // Player wins if (playerVal > dealerVal) { // Check for natural 21 (Blackjack) on initial deal, no hit, and win var isNatural21 = self.playerHand.length === 2 && self.handValue(self.playerHand) === 21 && typeof self.lastAction !== "string" // No action taken (no hit/double) ; var winAmount = self.bet * 2; if (isNatural21) { // Award 50% more for natural 21 win without hit var bonus = Math.floor(self.bet * 0.5); winAmount += bonus; } playerBalance += winAmount; // Bet behind wins if player hand not bust if (self.betBehind > 0 && playerVal <= 21) { self.betBehindWin = self.betBehind * 2; playerBalance += self.betBehindWin; } updateBalance(); var winMsg = 'You win!' + (self.betBehindWin > 0 ? '\nBet Behind Win: $' + self.betBehindWin : ''); if (isNatural21) { winMsg = 'Blackjack! +50% bonus\n' + winMsg; } return winMsg; } // Player loses if (playerVal < dealerVal) { // Bet behind lost return 'You lose.' + (self.betBehind > 0 ? '\nBet Behind Lost: $' + self.betBehind : ''); } // Push playerBalance += self.bet; if (self.betBehind > 0) { playerBalance += self.betBehind; // Return bet behind on push self.betBehindWin = self.betBehind; } updateBalance(); return 'Push!' + (self.betBehind > 0 ? '\nBet Behind Push: $' + self.betBehind : ''); }; // Show result and next round self.showResult = function (txt, noNext) { self.resultText && self.resultText.destroy(); // If perfect pair win, append to result text if (self.perfectPairWin && txt && txt.indexOf('Perfect Pair!') === -1) { txt = 'Perfect Pair! +$' + self.perfectPairPayout + '\n' + txt; } // --- Quest: Play 3 Blackjack rounds --- if (typeof questEvent === "function") questEvent('blackjack_round'); // --- Quest: Win 2 Blackjack rounds --- if (typeof questEvent === "function" && txt && txt.indexOf('win') !== -1 && txt.toLowerCase().indexOf('you win') !== -1) questEvent('blackjack_win'); // --- Quest: Double Down in Blackjack --- if (typeof questEvent === "function" && self.lastAction === 'Double') questEvent('blackjack_double'); // --- Quest: Get Perfect Pair in Blackjack --- if (typeof questEvent === "function" && self.perfectPairWin) questEvent('blackjack_perfect_pair'); self.resultText = new Text2(txt, { size: 90, fill: "#fff" }); self.resultText.anchor.set(0.5, 0.5); self.resultText.x = 2048 / 2; self.resultText.y = 1450; self.addChild(self.resultText); self.showButtons(['New Round', 'Back']); self.buttons[0].down = function () { this.flash(); self.startRound(); }; self.buttons[1].down = function () { this.flash(); self.destroy(); blackjack = null; showModeSelect(); }; if (noNext) { self.buttons[0].visible = false; } }; // Destroy self.destroy = function () { self.clearCards(); for (var i = 0; i < self.buttons.length; i++) { self.buttons[i].destroy(); } self.buttons = []; self.resultText && self.resultText.destroy(); self.resultText = null; self.perfectPairWin = false; self.perfectPairPayout = 0; self.betBehind = 0; self.betBehindWin = 0; if (self.parent) self.parent.removeChild(self); }; // Start self.newDeck(); self.startRound(); return self; }); // Card class for Blackjack var Card = Container.expand(function () { var self = Container.call(this); // Card properties self.rank = null; // 2-10, J, Q, K, A self.suit = null; // '♠', '♥', '♦', '♣' self.faceUp = true; // Card background var cardBg = self.attachAsset('cardBg', { width: 180, height: 260, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Card text var cardText = new Text2('', { size: 80, fill: 0x222222 }); cardText.anchor.set(0.5, 0.5); self.addChild(cardText); // Set card value self.setCard = function (rank, suit, faceUp) { self.rank = rank; self.suit = suit; self.faceUp = faceUp !== false; if (self.faceUp) { cardText.setText(rank + suit); cardText.visible = true; cardBg.color = suit === '♥' || suit === '♦' ? 0xffeaea : 0xffffff; } else { cardText.setText(''); cardText.visible = false; cardBg.color = 0x8888aa; } }; // Flip card self.flip = function (up) { self.faceUp = up; self.setCard(self.rank, self.suit, up); }; return self; }); // Simple Button class var GameButton = Container.expand(function () { var self = Container.call(this); var btnBg = self.attachAsset('btnBg', { width: 420, height: 120, color: 0x333366, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.btnBg = btnBg; // <-- Fix: assign btnBg as a property for external access var btnText = new Text2('', { size: 60, fill: 0xFFFFFF }); btnText.anchor.set(0.5, 0.5); self.addChild(btnText); self.setText = function (txt) { btnText.setText(txt); }; // For touch feedback self.flash = function () { tween(btnBg, { color: 0x6666cc }, { duration: 100, onFinish: function onFinish() { tween(btnBg, { color: 0x333366 }, { duration: 200 }); } }); }; return self; }); // --- Roulette Game Logic --- var RouletteGame = Container.expand(function () { var self = Container.call(this); // State self.state = 'bet'; // 'bet', 'spin', 'result' self.betType = null; // 'red', 'black', 'even', 'odd', 'number' self.betValue = null; // For number bet self.resultText = null; self.buttons = []; self.rouletteWheel = null; self.ball = null; self.spinBtn = null; self.backBtn = null; self.betOptions = []; self.selectedBetBtn = null; // Table background (roulette table image) var rouletteTableBg = self.attachAsset('RouletteBG', { width: 1400, height: 700, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 800 }); // Draw roulette wheel using a realistic image and overlay visible numbers var wheelRadius = 320; var wheelCenterX = 2048 / 2; var wheelCenterY = 800; // Move wheel further up var numbers = []; for (var i = 0; i < 37; i++) numbers.push(i); // Red/Black numbers (European roulette) var reds = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36]; var blacks = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35]; // Draw wheel container self.rouletteWheel = new Container(); self.rouletteWheel.x = wheelCenterX; self.rouletteWheel.y = wheelCenterY; self.addChild(self.rouletteWheel); // Add roulette wheel image (should be a top-down wheel with visible slots) var wheelImg = self.rouletteWheel.attachAsset('rouletteWheelImg', { width: wheelRadius * 2, height: wheelRadius * 2, anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Overlay numbers on the wheel image for visibility for (var i = 0; i < 37; i++) { var angle = i / 37 * Math.PI * 2 - Math.PI / 2; var num = numbers[i]; // European roulette: 0 is green, reds as defined, rest are black var color = "#fff"; var bgColor = 0x222222; if (num === 0) { bgColor = 0x1abc2c; // vivid green for 0 color = "#fff"; } else if (reds.indexOf(num) !== -1) { bgColor = 0xff0000; color = "#fff"; } else if (blacks.indexOf(num) !== -1) { bgColor = 0x222222; color = "#fff"; } // Draw number text with a subtle shadow for visibility var txt = new Text2(num + '', { size: 38, fill: color, stroke: "#000", strokeThickness: 6 }); txt.anchor.set(0.5, 0.5); txt.x = Math.cos(angle) * (wheelRadius - 38); txt.y = Math.sin(angle) * (wheelRadius - 38); self.rouletteWheel.addChild(txt); // Add invisible hit area for number bets (for touch/click) var hitSlot = self.rouletteWheel.attachAsset('cardBg', { width: 60, height: 60, color: 0x000000, alpha: 0, // invisible shape: 'box', anchorX: 0.5, anchorY: 0.5, x: Math.cos(angle) * (wheelRadius - 38), y: Math.sin(angle) * (wheelRadius - 38) }); hitSlot.hitArea = new Rectangle(-30, -30, 60, 60); hitSlot.down = function (betValue) { return function () { // Provide visual feedback by flashing the number text var txtNode = txt; if (typeof tween === "function" && txtNode && typeof txtNode.alpha !== "undefined") { var originalAlpha = txtNode.alpha; tween(txtNode, { alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(txtNode, { alpha: originalAlpha }, { duration: 200 }); } }); } // Unhighlight all bet buttons for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366; if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366; self.betType = 'number'; self.betValue = betValue; self.selectedBetBtn = this; self.showResult('Number bet: ' + self.betValue + ' ($' + Math.max(betAmount, 50) + ')', true); // Highlight selected number text txtNode.style = txtNode.style || {}; txtNode.style.fill = "#ffe066"; if (self.state === 'bet') { self.spinBtn.visible = true; } }; }(num); } // Ball self.ball = self.rouletteWheel.attachAsset('rouletteball', { width: 38, height: 38, anchorX: 0.5, anchorY: 0.5, x: Math.cos(-Math.PI / 2) * (wheelRadius - 40), y: Math.sin(-Math.PI / 2) * (wheelRadius - 40) }); // Bet options // Allow number bets (0-36) and split bets (adjacent numbers) in a compact grid below the wheel // Arrange numbers 0-36 in a 4-row grid: 0 on its own, then 1-12 in second, 13-24 in third, 25-36 in fourth var betGridCols = 12; var betGridRows = 4; // 0 in first row, 1-12 in second, 13-24 in third, 25-36 in fourth var betBtnW = 70; var betBtnH = 70; var betGridStartX = 2048 / 2 - betGridCols * betBtnW / 2 + betBtnW / 2; var betGridStartY = 1150; // Move up to match new wheel position self.betOptions = []; self.splitBetOptions = []; // Store split bet buttons // --- Number Bet Keyboard (below bet sign) --- // Move number bet keyboard to the left of the roulette wheel var numberKeyboardStartY = wheelCenterY - wheelRadius + 40; // Align top with wheel, with a little padding var numberKeyboardStartX = wheelCenterX - wheelRadius - 420; // Place to the left of the wheel, with some gap var numberKeyboardLabels = [['1', '2', '3', '4'], ['5', '6', '7', '8'], ['9', '10', '11', '12'], ['13', '14', '15', '16'], ['17', '18', '19', '20'], ['21', '22', '23', '24'], ['25', '26', '27', '28'], ['29', '30', '31', '32'], ['33', '34', '35', '36'], ['0']]; self.numberBetButtons = []; for (var row = 0; row < numberKeyboardLabels.length; row++) { for (var col = 0; col < numberKeyboardLabels[row].length; col++) { var label = numberKeyboardLabels[row][col]; var btn = new GameButton(); btn.setText(label); btn.btnBg.width = 80; btn.btnBg.height = 80; btn.x = numberKeyboardStartX + col * 90; btn.y = numberKeyboardStartY + row * 90; btn.betType = 'number'; btn.betValue = parseInt(label); btn.down = function (btnRef, value) { return function () { this.flash(); // Unhighlight all bet buttons for (var j = 0; j < self.betOptions.length; j++) { if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.numberBetButtons.length; j++) { if (self.numberBetButtons[j].btnBg) self.numberBetButtons[j].btnBg.color = 0x333366; } if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366; if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366; self.betType = 'number'; self.betValue = value; self.selectedBetBtn = this; self.showResult('Number bet: ' + value + ' ($' + Math.max(betAmount, 50) + ')', true); if (this.btnBg) this.btnBg.color = 0x6666cc; if (self.state === 'bet') { self.spinBtn.visible = true; } }; }(btn, parseInt(label)); self.addChild(btn); self.numberBetButtons.push(btn); } } // Helper to get grid position for a number function getGridPos(num) { if (num === 0) { return { col: 5.5, row: 0 }; // Center 0 above the grid } var idx = num - 1; return { col: idx % betGridCols, row: 1 + Math.floor(idx / betGridCols) }; } // --- Add Red/Black bet buttons --- // Move the red/black bet buttons even further down below the roulette wheel var colorBetY = numberKeyboardStartY + numberKeyboardLabels.length * 90 + 520; // Move even further down var colorBetXOffset = 200; // Increase horizontal offset for more space between buttons var redBtn = new GameButton(); redBtn.setText('Red'); redBtn.x = wheelCenterX - colorBetXOffset; redBtn.y = colorBetY; redBtn.betType = 'red'; redBtn.down = function () { this.flash(); // Unhighlight all bet buttons for (var j = 0; j < self.betOptions.length; j++) { if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366; if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366; self.betType = 'red'; self.betValue = null; self.selectedBetBtn = this; self.showResult('Red bet ($' + Math.max(betAmount, 50) + ')', true); if (this.btnBg) this.btnBg.color = 0xff0000; if (self.state === 'bet') { self.spinBtn.visible = true; } }; self.addChild(redBtn); self.betOptions.push(redBtn); self.redBtn = redBtn; var blackBtn = new GameButton(); blackBtn.setText('Black'); blackBtn.x = wheelCenterX + colorBetXOffset; blackBtn.y = colorBetY; blackBtn.betType = 'black'; blackBtn.down = function () { this.flash(); // Unhighlight all bet buttons for (var j = 0; j < self.betOptions.length; j++) { if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366; if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366; self.betType = 'black'; self.betValue = null; self.selectedBetBtn = this; self.showResult('Black bet ($' + Math.max(betAmount, 50) + ')', true); if (this.btnBg) this.btnBg.color = 0x222222; if (self.state === 'bet') { self.spinBtn.visible = true; } }; self.addChild(blackBtn); self.betOptions.push(blackBtn); self.blackBtn = blackBtn; // Create split bet buttons (between adjacent numbers: right and below) for (var i = 0; i < 37; i++) { var pos = getGridPos(i); // Split right (horizontal) if (pos.col < betGridCols - 1 && i + 1 < 37) { var splitBtn = new GameButton(); splitBtn.setText(i + '|' + (i + 1)); splitBtn.x = betGridStartX + pos.col * betBtnW + betBtnW / 2; splitBtn.y = betGridStartY + pos.row * (betBtnH + 10) + 200; // Moved down splitBtn.btnBg.width = 90; splitBtn.btnBg.height = 90; // Add even more space between split bet buttons horizontally splitBtn.x = betGridStartX + pos.col * (betBtnW + 50) + betBtnW / 2; splitBtn.y = betGridStartY + pos.row * (betBtnH + 50) + 200; // Moved down and spaced further splitBtn.betType = 'split'; splitBtn.betValue = [i, i + 1]; splitBtn.down = function (splitBtn) { return function () { this.flash(); // Unhighlight all bet buttons for (var j = 0; j < self.betOptions.length; j++) { if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } self.betType = 'split'; self.betValue = splitBtn.betValue; self.selectedBetBtn = this; self.showResult('Split bet: ' + splitBtn.betValue[0] + ' & ' + splitBtn.betValue[1] + ' ($' + Math.max(betAmount, 50) + ')', true); if (this.btnBg) this.btnBg.color = 0x6666cc; if (self.state === 'bet') { self.spinBtn.visible = true; } }; }(splitBtn); self.addChild(splitBtn); self.splitBetOptions.push(splitBtn); } // Split below (vertical) if (pos.row < betGridRows - 1 && i + betGridCols < 37) { var splitBtn2 = new GameButton(); splitBtn2.setText(i + '\\' + (i + betGridCols)); splitBtn2.x = betGridStartX + pos.col * (betBtnW + 10); splitBtn2.y = betGridStartY + pos.row * (betBtnH + 10) + (betBtnH + 10) / 2 + 100; // Moved down splitBtn2.btnBg.width = 90; splitBtn2.btnBg.height = 90; // Add even more space between split bet buttons vertically splitBtn2.x = betGridStartX + pos.col * (betBtnW + 50); splitBtn2.y = betGridStartY + pos.row * (betBtnH + 50) + (betBtnH + 50) / 2 + 100; // Moved down and spaced further splitBtn2.betType = 'split'; splitBtn2.betValue = [i, i + betGridCols]; splitBtn2.down = function (splitBtn2) { return function () { this.flash(); // Unhighlight all bet buttons for (var j = 0; j < self.betOptions.length; j++) { if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366; } for (var j = 0; j < self.splitBetOptions.length; j++) { if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366; } self.betType = 'split'; self.betValue = splitBtn2.betValue; self.selectedBetBtn = this; self.showResult('Split bet: ' + splitBtn2.betValue[0] + ' & ' + splitBtn2.betValue[1] + ' ($' + Math.max(betAmount, 50) + ')', true); if (this.btnBg) this.btnBg.color = 0x6666cc; if (self.state === 'bet') { self.spinBtn.visible = true; } }; }(splitBtn2); self.addChild(splitBtn2); self.splitBetOptions.push(splitBtn2); } } // Spin button // Calculate betY for button positioning var betY = betGridStartY + betGridRows * betBtnH + 40; self.spinBtn = new GameButton(); self.spinBtn.setText('Spin'); // Make Spin button visually and structurally match the Back button self.spinBtn.x = 2048 / 2 - 600; self.spinBtn.y = betY + 300; self.spinBtn.btnBg.width = 420; self.spinBtn.btnBg.height = 120; self.spinBtn.visible = false; // Only show after bet selected self.spinBtn.down = function () { this.flash(); self.handleSpin(); }; self.addChild(self.spinBtn); // Back button self.backBtn = new GameButton(); self.backBtn.setText('Back'); // Move Back button further left of Spin self.backBtn.x = 2048 / 2 - 600; self.backBtn.y = betY + 450; self.backBtn.down = function () { self.destroy(); roulette = null; showModeSelect(); }; self.addChild(self.backBtn); // Show result text self.showResult = function (txt, noNext) { self.resultText && self.resultText.destroy(); self.resultText = new Text2(txt, { size: 90, fill: "#fff" }); self.resultText.anchor.set(0.5, 0.5); self.resultText.x = 2048 / 2; self.resultText.y = 1550; self.addChild(self.resultText); if (!noNext) { // Show "New Round" button var nextBtn = new GameButton(); nextBtn.setText('New Round'); nextBtn.x = 2048 / 2; nextBtn.y = betY + 600; nextBtn.down = function () { this.flash(); self.reset(); }; self.addChild(nextBtn); self.buttons.push(nextBtn); } }; // Handle spin self.handleSpin = function () { // Only allow spin if a bet is selected if (!self.betType || self.betType === 'number' && (typeof self.betValue !== "number" || self.betValue < 0 || self.betValue > 36)) { self.showResult('Select a bet first!', true); return; } if (betAmount < 50) { self.showResult('Minimum bet is $50!', true); return; } if (self.state !== 'bet') { self.showResult('You can only place one bet per round!', true); return; } self.state = 'spin'; if (playerBalance < betAmount) { self.showResult('Not enough balance!', true); return; } playerBalance -= betAmount; updateBalance(); self.state = 'spin'; self.spinBtn.visible = false; for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].visible = false; self.resultText && self.resultText.destroy(); // Animate ball spin var winningNumber = Math.floor(Math.random() * 37); var totalSpins = 3 + Math.floor(Math.random() * 2); var frames = 60 * totalSpins; var startAngle = -Math.PI / 2; var endAngle = winningNumber / 37 * Math.PI * 2 - Math.PI / 2; var currentFrame = 0; function animateBall() { var t = currentFrame / frames; var angle = startAngle + (endAngle - startAngle) * t + Math.PI * 2 * (1 - t) * totalSpins; self.ball.x = Math.cos(angle) * (wheelRadius - 40); self.ball.y = Math.sin(angle) * (wheelRadius - 40); currentFrame++; if (currentFrame <= frames) { LK.setTimeout(animateBall, 1000 / 60); } else { self.showSpinResult(winningNumber); // After result, allow new bet self.betType = null; self.betValue = null; if (self.selectedBetBtn && self.selectedBetBtn.btnBg) { self.selectedBetBtn.btnBg.color = 0x333366; } self.selectedBetBtn = null; // Show bet options for next round, but keep spin button hidden until bet is selected self.spinBtn.visible = false; for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].visible = true; } } animateBall(); }; // Show spin result and payout self.showSpinResult = function (winningNumber) { var win = false; var payout = 0; var msg = ''; if (self.betType === 'red' && reds.indexOf(winningNumber) !== -1) { win = true; payout = betAmount * 2; msg = 'Red wins!'; } else if (self.betType === 'black' && blacks.indexOf(winningNumber) !== -1) { win = true; payout = betAmount * 2; msg = 'Black wins!'; } else if (self.betType === 'even' && winningNumber !== 0 && winningNumber % 2 === 0) { win = true; payout = betAmount * 2; msg = 'Even wins!'; } else if (self.betType === 'odd' && winningNumber % 2 === 1) { win = true; payout = betAmount * 2; msg = 'Odd wins!'; } else if (self.betType === 'number' && self.betValue === winningNumber) { win = true; payout = betAmount * 36; msg = 'Number ' + winningNumber + ' wins!'; } else if (self.betType === 'split' && self.betValue && self.betValue.indexOf(winningNumber) !== -1) { win = true; payout = betAmount * 18; // Standard split bet payout is 17:1, so bet*18 msg = 'Split bet wins! Number ' + winningNumber + '!'; } else { msg = 'Number ' + winningNumber + '. You lose.'; } if (win) { playerBalance += payout; updateBalance(); msg += ' You win $' + payout + '!'; // --- Quest: Win $500 in Roulette --- if (typeof questEvent === "function") questEvent('roulette_win', payout); // --- Quest: Place 5 Roulette bets --- if (typeof questEvent === "function") questEvent('roulette_bet'); // --- Quest: Win on a number bet in Roulette --- if (typeof questEvent === "function" && self.betType === 'number' && self.betValue === winningNumber) questEvent('roulette_number_win'); // --- Quest: Win on Red/Black in Roulette --- if (typeof questEvent === "function" && (self.betType === 'red' || self.betType === 'black')) questEvent('roulette_red_black_win'); } else { // Even if lose, count bet for "Place 5 Roulette bets" if (typeof questEvent === "function") questEvent('roulette_bet'); } self.state = 'result'; self.showResult(msg); }; // Reset for new round self.reset = function () { self.betType = null; self.betValue = null; self.state = 'bet'; self.resultText && self.resultText.destroy(); for (var i = 0; i < self.buttons.length; i++) self.buttons[i].destroy(); self.buttons = []; self.spinBtn.visible = false; for (var i = 0; i < self.betOptions.length; i++) { self.betOptions[i].visible = true; if (self.betOptions[i].btnBg) self.betOptions[i].btnBg.color = 0x333366; } for (var i = 0; i < (self.splitBetOptions ? self.splitBetOptions.length : 0); i++) { self.splitBetOptions[i].visible = true; if (self.splitBetOptions[i].btnBg) self.splitBetOptions[i].btnBg.color = 0x333366; } self.selectedBetBtn = null; }; // Destroy self.destroy = function () { self.resultText && self.resultText.destroy(); for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].destroy(); self.betOptions = []; if (self.splitBetOptions) { for (var i = 0; i < self.splitBetOptions.length; i++) self.splitBetOptions[i].destroy(); self.splitBetOptions = []; } self.spinBtn && self.spinBtn.destroy(); self.backBtn && self.backBtn.destroy(); for (var i = 0; i < self.buttons.length; i++) self.buttons[i].destroy(); self.buttons = []; self.rouletteWheel && self.rouletteWheel.destroy(); self.state = 'bet'; if (self.parent) self.parent.removeChild(self); }; return self; }); // --- Sweet Bonanza Game Logic --- var SweetBonanzaGame = Container.expand(function () { var self = Container.call(this); // Slot config var ROWS = 5; var COLS = 6; var SYMBOLS = [{ id: 'red', color: 0xff4b5c, payout: 10 }, { id: 'blue', color: 0x4b7bff, payout: 8 }, { id: 'green', color: 0x4bff7b, payout: 6 }, { id: 'yellow', color: 0xffe066, payout: 4 }, { id: 'purple', color: 0xb266ff, payout: 12 }, { id: 'bomb', color: 0xffffff, payout: 0, isBomb: true }]; var symbolSize = 180; var gridOffsetX = 2048 / 2 - COLS * symbolSize / 2; var gridOffsetY = 900; var grid = []; var symbolNodes = []; var spinBtn = null; var resultText = null; var canSpin = true; // (Removed slot background) // Draw grid function drawGrid() { // Remove old for (var i = 0; i < symbolNodes.length; i++) { for (var j = 0; j < symbolNodes[i].length; j++) { symbolNodes[i][j].destroy(); } } symbolNodes = []; for (var row = 0; row < ROWS; row++) { symbolNodes[row] = []; for (var col = 0; col < COLS; col++) { var sym = grid[row][col]; var node = self.attachAsset('cardBg', { width: symbolSize - 10, height: symbolSize - 10, color: sym.color, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: gridOffsetX + col * symbolSize + symbolSize / 2, y: gridOffsetY + row * symbolSize + symbolSize / 2 }); // Add symbol text var txt = new Text2(sym.isBomb ? '💣' : '', { size: 80, fill: "#222" }); txt.anchor.set(0.5, 0.5); node.addChild(txt); symbolNodes[row][col] = node; } } } // Generate random grid function randomGrid() { grid = []; for (var row = 0; row < ROWS; row++) { grid[row] = []; for (var col = 0; col < COLS; col++) { var sym = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)]; grid[row][col] = sym; } } } // Find clusters of 8+ matching symbols (Sweet Bonanza style) function findClusters() { var visited = []; for (var i = 0; i < ROWS; i++) visited[i] = []; var clusters = []; function dfs(r, c, id, cluster) { if (r < 0 || r >= ROWS || c < 0 || c >= COLS) return; if (visited[r][c]) return; if (grid[r][c].id !== id) return; visited[r][c] = true; cluster.push({ row: r, col: c }); dfs(r - 1, c, id, cluster); dfs(r + 1, c, id, cluster); dfs(r, c - 1, id, cluster); dfs(r, c + 1, id, cluster); } for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { if (!visited[row][col] && !grid[row][col].isBomb) { var cluster = []; dfs(row, col, grid[row][col].id, cluster); if (cluster.length >= 8) { clusters.push({ id: grid[row][col].id, cells: cluster, payout: grid[row][col].payout }); } } } } return clusters; } // Remove clusters and drop new symbols function removeClusters(clusters) { for (var i = 0; i < clusters.length; i++) { var cells = clusters[i].cells; for (var j = 0; j < cells.length; j++) { var r = cells[j].row; var c = cells[j].col; grid[r][c] = null; } } // Drop down for (var col = 0; col < COLS; col++) { var empty = []; for (var row = ROWS - 1; row >= 0; row--) { if (grid[row][col] === null) { empty.push(row); } else if (empty.length > 0) { var target = empty.shift(); grid[target][col] = grid[row][col]; grid[row][col] = null; empty.push(row); } } // Fill empty with new for (var k = 0; k < empty.length; k++) { var r = empty[k]; var sym = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)]; grid[r][col] = sym; } } } // Check for bombs function hasBomb() { for (var row = 0; row < ROWS; row++) { for (var col = 0; col < COLS; col++) { if (grid[row][col].isBomb) return true; } } return false; } // Spin logic function spin() { if (!canSpin) return; if (playerBalance < betAmount) { showResult('Not enough balance!'); return; } // --- Quest: Spin Sweet Bonanza 5 times --- if (typeof questEvent === "function") questEvent('sweet_spin'); canSpin = false; playerBalance -= betAmount; updateBalance(); resultText && resultText.destroy(); resultText = null; randomGrid(); drawGrid(); // Animate spin (simple delay) LK.setTimeout(function () { var clusters = findClusters(); var win = 0; for (var i = 0; i < clusters.length; i++) { win += clusters[i].payout * betAmount; } if (win > 0) { playerBalance += win; updateBalance(); showResult('Win! $' + win); } else if (hasBomb()) { showResult('💣 Bomb! Lose!'); } else { showResult('No win'); } // Remove clusters and drop new if (clusters.length > 0) { removeClusters(clusters); drawGrid(); } canSpin = true; }, 700); } // Show result text function showResult(txt) { resultText && resultText.destroy(); resultText = new Text2(txt, { size: 90, fill: "#fff" }); resultText.anchor.set(0.5, 0.5); resultText.x = 2048 / 2; resultText.y = gridOffsetY + ROWS * symbolSize + 120; self.addChild(resultText); } // Spin button spinBtn = new GameButton(); spinBtn.setText('Spin'); spinBtn.x = 2048 / 2; spinBtn.y = gridOffsetY + ROWS * symbolSize + 250; spinBtn.down = function () { this.flash(); spin(); }; self.addChild(spinBtn); // Back button var backBtn = new GameButton(); backBtn.setText('Back'); backBtn.x = 2048 / 2; backBtn.y = gridOffsetY + ROWS * symbolSize + 400; backBtn.down = function () { self.destroy(); sweetBonanza = null; showModeSelect(); }; self.addChild(backBtn); // Destroy self.destroy = function () { for (var i = 0; i < symbolNodes.length; i++) { for (var j = 0; j < symbolNodes[i].length; j++) { symbolNodes[i][j].destroy(); } } symbolNodes = []; spinBtn && spinBtn.destroy(); backBtn && backBtn.destroy(); resultText && resultText.destroy(); if (self.parent) self.parent.removeChild(self); }; // Init randomGrid(); drawGrid(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2e8b57 // deep green, matches Blackjack table }); /**** * Game Code ****/ // Blood red background (deep red) // --- Account System State --- // --- Global State --- // (Removed fullscreen Blackjack table background image) function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var accountState = { loggedIn: false, username: null }; var accountPrompt = null; var accountErrorText = null; var accountNameInput = null; var accountPasswordInput = null; var accountNameValue = ''; var accountPasswordValue = ''; var accountMode = 'login'; // 'login' or 'register' // Helper: get all accounts from storage function getAllAccounts() { // Use storage.getItem to retrieve accounts, fallback to empty object if not found var accounts = storage.getItem && typeof storage.getItem === "function" ? storage.getItem("accounts") : storage.accounts; if (!accounts || _typeof(accounts) !== "object") accounts = {}; return accounts; } // Helper: save all accounts to storage function saveAllAccounts(accounts) { // Use storage.setItem to persist accounts if available if (storage.setItem && typeof storage.setItem === "function") { storage.setItem("accounts", accounts); } storage.accounts = accounts; } // Helper: hash password (simple, not secure, but for demo) function hashPassword(pw) { // Ensure pw is a string to avoid errors on charCodeAt if (pw === undefined || pw === null) pw = ''; pw = String(pw); var h = 0; for (var i = 0; i < pw.length; i++) { // Defensive: check that pw is a string and pw[i] exists var ch = typeof pw === "string" && pw.length > i ? pw.charAt(i) : ''; if (typeof ch === "string" && ch.length === 1) { h += ch.charCodeAt(0) * (i + 17); } } // Defensive: ensure h is a number before converting to string if (typeof h !== "number" || isNaN(h)) h = 0; // Always return as string, and never undefined/null try { // Defensive: if h is not a string or number, return empty string if (typeof h === "string") return h; if (typeof h === "number") return String(h); // If h is not string or number, fallback to empty string return ''; } catch (e) { // In case of any error, always return empty string return ''; } // Final fallback: always return a string if (typeof h === "undefined" || h === null) return ''; // Defensive: ensure return is always a string try { // Fix: Always return a string, never throw if (typeof h === "string") return h; if (typeof h === "number") return String(h); return ''; } catch (e) { return ''; } // Absolute fallback return ''; } // Show account setup/login UI function showAccountPrompt() { // Remove old prompt if present if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } accountPrompt = new Container(); game.addChild(accountPrompt); // Background overlay var overlay = accountPrompt.attachAsset('cardBg', { width: 900, height: 600, color: 0x222244, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1200 }); // Title var title = new Text2(accountMode === 'register' ? 'Create Account' : 'Login', { size: 80, fill: "#fff" }); title.anchor.set(0.5, 0.5); title.x = 2048 / 2; title.y = 950; accountPrompt.addChild(title); // Username input accountNameInput = new Text2('Name: ' + accountNameValue, { size: 60, fill: "#fff" }); accountNameInput.anchor.set(0.5, 0.5); accountNameInput.x = 2048 / 2; accountNameInput.y = 1100; accountPrompt.addChild(accountNameInput); // Password input (show as ****) var stars = ''; for (var i = 0; i < accountPasswordValue.length; i++) stars += '*'; accountPasswordInput = new Text2('Password: ' + stars, { size: 60, fill: "#fff" }); accountPasswordInput.anchor.set(0.5, 0.5); accountPasswordInput.x = 2048 / 2; accountPasswordInput.y = 1200; accountPrompt.addChild(accountPasswordInput); function updateNameInputDisplay() { accountNameInput.setText('Name: ' + accountNameValue); if (accountErrorText) accountErrorText.setText(''); } function updatePasswordInputDisplay() { var stars = ''; for (var i = 0; i < accountPasswordValue.length; i++) stars += '*'; accountPasswordInput.setText('Password: ' + stars); if (accountErrorText) accountErrorText.setText(''); } function clearAccountInputs() { accountNameValue = ''; accountPasswordValue = ''; updateNameInputDisplay(); updatePasswordInputDisplay(); } // Error text accountErrorText = new Text2('', { size: 48, fill: 0xFF4444 }); accountErrorText.anchor.set(0.5, 0.5); accountErrorText.x = 2048 / 2; accountErrorText.y = 1270; accountPrompt.addChild(accountErrorText); // Name pad (A-Z, backspace, next) - split left var namePadStartX = 2048 / 2 - 500; var namePadStartY = 1350; var namePadLabels = [['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'W', 'X', 'Y', 'Z', '/', '_', '<-', 'OK']]; function updateNameInputDisplay() { accountNameInput.setText('Name: ' + accountNameValue); if (accountErrorText) accountErrorText.setText(''); } function updatePasswordInputDisplay() { var stars = ''; for (var i = 0; i < accountPasswordValue.length; i++) stars += '*'; accountPasswordInput.setText('Password: ' + stars); if (accountErrorText) accountErrorText.setText(''); } function clearAccountInputs() { accountNameValue = ''; accountPasswordValue = ''; updateNameInputDisplay(); updatePasswordInputDisplay(); } function tryAccountSubmit() { var name = accountNameValue.trim(); var pw = accountPasswordValue; if (name.length < 3) { accountErrorText.setText('Name must be at least 3 characters.'); return; } if (pw.length < 6) { accountErrorText.setText('Password must be at least 6 digits.'); return; } var accounts = getAllAccounts(); if (accountMode === 'register') { if (accounts[name]) { accountErrorText.setText('Name already taken!'); return; } // Only allow digits in password if (!/^\d+$/.test(pw)) { accountErrorText.setText('Password must be digits only.'); return; } // Register accounts[name] = { password: hashPassword(pw), created: Date.now() }; saveAllAccounts(accounts); accountState.loggedIn = true; accountState.username = name; accountPasswordValue = ''; // Clear password after success if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } showModeSelect(); } else { // Login if (!accounts[name]) { accountErrorText.setText('Account not found.'); return; } if (accounts[name].password !== hashPassword(pw)) { accountErrorText.setText('Incorrect password.'); return; } accountState.loggedIn = true; accountState.username = name; accountPasswordValue = ''; // Clear password after success if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } showModeSelect(); } } function clearAccountInputs() { accountNameValue = ''; accountPasswordValue = ''; updateNameInputDisplay(); updatePasswordInputDisplay(); } var namePadStartY = 1350; var namePadLabels = [['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'W', 'X', 'Y', 'Z', '/', '_', '<-', 'OK']]; function updateNameInputDisplay() { accountNameInput.setText('Name: ' + accountNameValue); if (accountErrorText) accountErrorText.setText(''); } function updatePasswordInputDisplay() { var stars = ''; for (var i = 0; i < accountPasswordValue.length; i++) stars += '*'; accountPasswordInput.setText('Password: ' + stars); if (accountErrorText) accountErrorText.setText(''); } function tryAccountSubmit() { var name = accountNameValue.trim(); var pw = accountPasswordValue; if (name.length < 3) { accountErrorText.setText('Name must be at least 3 characters.'); return; } if (pw.length < 6) { accountErrorText.setText('Password must be at least 6 digits.'); return; } var accounts = getAllAccounts(); if (accountMode === 'register') { if (accounts[name]) { accountErrorText.setText('Name already taken!'); return; } // Only allow digits in password if (!/^\d+$/.test(pw)) { accountErrorText.setText('Password must be digits only.'); return; } // Register accounts[name] = { password: hashPassword(pw), created: Date.now() }; saveAllAccounts(accounts); accountState.loggedIn = true; accountState.username = name; accountPasswordValue = ''; // Clear password after success if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } showModeSelect(); } else { // Login if (!accounts[name]) { accountErrorText.setText('Account not found.'); return; } if (accounts[name].password !== hashPassword(pw)) { accountErrorText.setText('Incorrect password.'); return; } accountState.loggedIn = true; accountState.username = name; accountPasswordValue = ''; // Clear password after success if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } showModeSelect(); } } function clearAccountInputs() { accountNameValue = ''; accountPasswordValue = ''; updateNameInputDisplay(); updatePasswordInputDisplay(); } // Draw name pad (letters only, left side) for (var row = 0; row < namePadLabels.length; row++) { for (var col = 0; col < namePadLabels[row].length; col++) { var label = namePadLabels[row][col]; var btn = new GameButton(); btn.setText(label); // Make buttons smaller and add more space between them btn.btnBg.width = 54; btn.btnBg.height = 54; btn.x = namePadStartX + col * 74; // 54px button + 20px gap btn.y = namePadStartY + row * 80; // 54px button + 26px gap // Make text a bit larger for visibility for (var t = 0; t < btn.children.length; t++) { if (btn.children[t] && typeof btn.children[t].setText === "function") { btn.children[t].style = btn.children[t].style || {}; btn.children[t].style.size = 36; btn.children[t].setText(label); } } if (label === '<-') btn.btnBg.color = 0xffcccc; if (label === 'OK') btn.btnBg.color = 0xccffcc; btn.down = function (lbl) { return function () { this.flash(); if (lbl === '<-') { if (accountNameValue.length > 0) { accountNameValue = accountNameValue.slice(0, -1); updateNameInputDisplay(); } } else if (lbl === 'OK') { // Move to password input // If already on password, try submit if (accountPasswordValue.length < 6) { accountErrorText.setText('Password must be at least 6 digits.'); return; } tryAccountSubmit(); } else { if (accountNameValue.length < 12 && /^[A-Z_\/]$/.test(lbl)) { accountNameValue += lbl; updateNameInputDisplay(); } } }; }(label); accountPrompt.addChild(btn); } } // Number pad (digits 0-9, C, OK) - right side var pwPadStartX = 2048 / 2 + 400; var pwPadStartY = 1350; var pwPadLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']]; for (var prow = 0; prow < 4; prow++) { for (var pcol = 0; pcol < 3; pcol++) { var plabel = pwPadLabels[prow][pcol]; var pbtn = new GameButton(); pbtn.setText(plabel); // Make buttons smaller and add more space between them pbtn.btnBg.width = 54; pbtn.btnBg.height = 54; pbtn.x = pwPadStartX + pcol * 74; // 54px button + 20px gap pbtn.y = pwPadStartY + prow * 80; // 54px button + 26px gap // Make text a bit larger for visibility for (var t = 0; t < pbtn.children.length; t++) { if (pbtn.children[t] && typeof pbtn.children[t].setText === "function") { pbtn.children[t].style = pbtn.children[t].style || {}; pbtn.children[t].style.size = 36; pbtn.children[t].setText(plabel); } } if (plabel === 'C') pbtn.btnBg.color = 0xffcccc; if (plabel === 'OK') pbtn.btnBg.color = 0xccffcc; pbtn.down = function (lbl) { return function () { this.flash(); if (lbl === 'C') { accountPasswordValue = ''; updatePasswordInputDisplay(); } else if (lbl === 'OK') { tryAccountSubmit(); } else if (lbl.length === 1 && accountPasswordValue.length < 12 && /^\d$/.test(lbl)) { accountPasswordValue += lbl; updatePasswordInputDisplay(); } }; }(plabel); accountPrompt.addChild(pbtn); } } // Switch mode button var switchBtn = new GameButton(); switchBtn.setText(accountMode === 'register' ? 'Have account? Login' : 'No account? Register'); switchBtn.x = 2048 / 2; switchBtn.y = 1800; // moved even further down switchBtn.btnBg.width = 400; switchBtn.btnBg.height = 70; switchBtn.down = function () { this.flash(); accountMode = accountMode === 'register' ? 'login' : 'register'; accountNameValue = ''; accountPasswordValue = ''; if (accountPrompt) { accountPrompt.destroy(); accountPrompt = null; } showAccountPrompt(); }; accountPrompt.addChild(switchBtn); } // On game start, allow guest play by default // Optionally, user can open account prompt from a button in the mode select screen // --- Top Left Back Button --- var topLeftBackBtn = null; function showTopLeftBackBtn(onBack) { // Remove if already present if (topLeftBackBtn && topLeftBackBtn.parent) { topLeftBackBtn.parent.removeChild(topLeftBackBtn); topLeftBackBtn.destroy(); topLeftBackBtn = null; } topLeftBackBtn = new GameButton(); topLeftBackBtn.setText('Back'); // Place at (100,220) to avoid the reserved 100x100px area and move a little further down topLeftBackBtn.x = 100 + 80; // 80px right of reserved area topLeftBackBtn.y = 100 + 160; // 160px below reserved area (moved a little further down) topLeftBackBtn.btnBg.width = 180; topLeftBackBtn.btnBg.height = 80; topLeftBackBtn.down = function () { this.flash(); if (typeof onBack === "function") onBack(); }; game.addChild(topLeftBackBtn); } function hideTopLeftBackBtn() { if (topLeftBackBtn && topLeftBackBtn.parent) { topLeftBackBtn.parent.removeChild(topLeftBackBtn); topLeftBackBtn.destroy(); topLeftBackBtn = null; } } /**** * Casino Carnival - MVP * Four-in-one casino game: Blackjack, Sweet Bonanza, Gates of Olympus, Sugar Rush * MVP: Game selection, basic betting, and one playable mode (Blackjack) ****/ var MODES = [{ id: 'blackjack', name: 'Blackjack' }, { id: 'roulette', name: 'Roulette' }]; var currentMode = null; // 'blackjack', etc. var playerBalance = storage.balance || 1000; var betAmount = 100; var minBet = 50; var maxBet = 500000; // --- Single Seat State --- var blackjack = null; // UI elements var modeButtons = []; var betText = null; var balanceText = null; var playArea = null; var blackjack = null; // --- GUI: Balance and Bet --- balanceText = new Text2('Balance: $' + playerBalance, { size: 60, fill: "#fff" }); balanceText.anchor.set(0.5, 0); LK.gui.top.addChild(balanceText); betText = new Text2('Bet: $' + betAmount, { size: 50, fill: "#fff" }); betText.anchor.set(0.5, 0); LK.gui.top.addChild(betText); // Position GUI elements balanceText.y = 10; betText.y = 80; // --- Game Selection Screen --- function showModeSelect() { hideTopLeftBackBtn(); // Clear play area if (playArea) { playArea.destroy(); playArea = null; } if (blackjack) { blackjack.destroy(); blackjack = null; } // Destroy blackjack instance if present if (blackjack && blackjack.destroy) { blackjack.destroy(); blackjack = null; } // Remove old mode buttons for (var i = 0; i < modeButtons.length; i++) { if (modeButtons[i].parent) modeButtons[i].parent.removeChild(modeButtons[i]); } modeButtons = []; // Title var title = new Text2('Casino Carnival', { size: 120, fill: 0xFFE066 }); title.anchor.set(0.5, 0.5); title.x = 2048 / 2; title.y = 350; game.addChild(title); // Mode buttons var startY = 700; var gapY = 200; for (var i = 0; i < MODES.length; i++) { var btn = new GameButton(); btn.setText(MODES[i].name); // Adjust font size to fit the button for 'Blackjack' and 'Roulette' if (MODES[i].name === 'Blackjack' || MODES[i].name === 'Roulette') { // Find the Text2 child and set its size smaller to fit the red area for (var j = 0; j < btn.children.length; j++) { if (btn.children[j] && typeof btn.children[j].setText === "function") { btn.children[j].style = btn.children[j].style || {}; btn.children[j].style.size = 48; // Reduce font size to fit btn.children[j].setText(MODES[i].name); } } } btn.x = 2048 / 2; btn.y = startY + i * gapY; btn.modeId = MODES[i].id; btn.down = function (x, y, obj) { this.flash(); selectMode(this.modeId); }; game.addChild(btn); modeButtons.push(btn); } // Bet controls var betMinus = new GameButton(); betMinus.setText('-'); betMinus.x = 2048 / 2 - 350; betMinus.y = startY + MODES.length * gapY + 60; betMinus.down = function () { var step = 50; if (betAmount > 20000) { step = 2000; } else if (betAmount > 10000) { step = 1000; } else if (betAmount > 5000) { step = 500; } else if (betAmount > 1000) { step = 100; } if (betAmount - step >= minBet) { betAmount -= step; } else if (betAmount > minBet) { betAmount = minBet; } betText.setText('Bet: $' + betAmount); }; game.addChild(betMinus); var betCustomBtn = new GameButton(); betCustomBtn.setText('✎'); betCustomBtn.x = 2048 / 2; betCustomBtn.y = startY + MODES.length * gapY + 60; betCustomBtn.btnBg.width = 100; betCustomBtn.btnBg.height = 100; betCustomBtn.down = function () { this.flash(); showCustomBetInput(); }; game.addChild(betCustomBtn); var betPlus = new GameButton(); betPlus.setText('+'); betPlus.x = 2048 / 2 + 350; betPlus.y = startY + MODES.length * gapY + 60; betPlus.down = function () { var step = 50; if (betAmount >= 20000) { step = 2000; } else if (betAmount >= 10000) { step = 1000; } else if (betAmount >= 5000) { step = 500; } else if (betAmount >= 1000) { step = 100; } if (betAmount + step <= maxBet) { betAmount += step; } else if (betAmount < maxBet) { betAmount = maxBet; } betText.setText('Bet: $' + betAmount); }; game.addChild(betPlus); // Store for later removal // Store for later removal modeButtons.push(title, betMinus, betCustomBtn, betPlus); // --- Custom Bet Input UI --- var customBetPrompt = null; function showCustomBetInput() { if (customBetPrompt) { customBetPrompt.destroy(); customBetPrompt = null; } customBetPrompt = new Container(); game.addChild(customBetPrompt); var overlay = customBetPrompt.attachAsset('cardBg', { width: 600, height: 400, color: 0x222244, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1200 }); var title = new Text2('Enter Bet Amount', { size: 70, fill: "#fff" }); title.anchor.set(0.5, 0.5); title.x = 2048 / 2; title.y = 1050; customBetPrompt.addChild(title); var inputValue = ''; var inputText = new Text2('Bet: ', { size: 60, fill: "#fff" }); inputText.anchor.set(0.5, 0.5); inputText.x = 2048 / 2; inputText.y = 1200; customBetPrompt.addChild(inputText); var errorText = new Text2('', { size: 40, fill: 0xFF4444 }); errorText.anchor.set(0.5, 0.5); errorText.x = 2048 / 2; errorText.y = 1270; customBetPrompt.addChild(errorText); function updateInputDisplay() { inputText.setText('Bet: ' + inputValue); errorText.setText(''); } // Number pad (digits 0-9, C, OK) var padStartX = 2048 / 2 - 120; var padStartY = 1350; var padLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']]; for (var prow = 0; prow < 4; prow++) { for (var pcol = 0; pcol < 3; pcol++) { var plabel = padLabels[prow][pcol]; var pbtn = new GameButton(); pbtn.setText(plabel); pbtn.btnBg.width = 80; pbtn.btnBg.height = 80; pbtn.x = padStartX + pcol * 100; pbtn.y = padStartY + prow * 100; for (var t = 0; t < pbtn.children.length; t++) { if (pbtn.children[t] && typeof pbtn.children[t].setText === "function") { pbtn.children[t].style = pbtn.children[t].style || {}; pbtn.children[t].style.size = 36; pbtn.children[t].setText(plabel); } } if (plabel === 'C') pbtn.btnBg.color = 0xffcccc; if (plabel === 'OK') pbtn.btnBg.color = 0xccffcc; pbtn.down = function (lbl) { return function () { this.flash(); if (lbl === 'C') { inputValue = ''; updateInputDisplay(); } else if (lbl === 'OK') { var val = parseInt(inputValue, 10); if (isNaN(val) || val < minBet || val > maxBet) { errorText.setText('Enter $' + minBet + ' - $' + maxBet); return; } betAmount = val; betText.setText('Bet: $' + betAmount); if (customBetPrompt) { customBetPrompt.destroy(); customBetPrompt = null; } } else if (lbl.length === 1 && inputValue.length < 9 && /^\d$/.test(lbl)) { if (inputValue === '0') inputValue = ''; inputValue += lbl; updateInputDisplay(); } }; }(plabel); customBetPrompt.addChild(pbtn); } } // Cancel button var cancelBtn = new GameButton(); cancelBtn.setText('Cancel'); cancelBtn.x = 2048 / 2; cancelBtn.y = padStartY + 450; cancelBtn.btnBg.width = 200; cancelBtn.btnBg.height = 70; cancelBtn.down = function () { this.flash(); if (customBetPrompt) { customBetPrompt.destroy(); customBetPrompt = null; } }; customBetPrompt.addChild(cancelBtn); updateInputDisplay(); } // Add Instagram handle var instaHandle = new Text2('@ahmet_db', { size: 40, fill: 0xffffff }); instaHandle.anchor.set(0, 0.5); // Align to the left middle instaHandle.x = 2048 - 250; // Position slightly more left instaHandle.y = 130; // Position slightly more up game.addChild(instaHandle); // Add Instagram logo var instaLogo = LK.getAsset('instagramLogo', { width: 50, height: 50, anchorX: 1, // Align to the right anchorY: 0.5, // Align to the middle x: instaHandle.x - 10, // Position 10px to the left of the text y: instaHandle.y }); game.addChild(instaLogo); // Add "Open Account" button var openAccountBtn = new GameButton(); openAccountBtn.setText('Open Account'); openAccountBtn.x = 2048 / 2 + 750; // Position further to the right openAccountBtn.y = 200; // Position further upwards openAccountBtn.btnBg.width = 400; openAccountBtn.btnBg.height = 80; openAccountBtn.down = function () { this.flash(); accountMode = 'register'; // Set mode to register clearAccountInputs(); // Clear any previous input showAccountPrompt(); }; } // --- Mode Selection Handler --- // Password UI state var roulettePasswordPrompt = null; var roulettePasswordInput = null; var roulettePasswordError = null; function showRoulettePasswordPrompt() { showTopLeftBackBtn(function () { if (roulettePasswordPrompt) { roulettePasswordPrompt.destroy(); roulettePasswordPrompt = null; } showModeSelect(); }); // Remove any previous prompt if (roulettePasswordPrompt) { roulettePasswordPrompt.destroy(); roulettePasswordPrompt = null; } roulettePasswordPrompt = new Container(); game.addChild(roulettePasswordPrompt); // Background overlay var overlay = roulettePasswordPrompt.attachAsset('cardBg', { width: 900, height: 500, color: 0x222244, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1200 }); // Title var promptTitle = new Text2('Enter Roulette Password', { size: 80, fill: "#fff" }); promptTitle.anchor.set(0.5, 0.5); promptTitle.x = 2048 / 2; promptTitle.y = 1050; roulettePasswordPrompt.addChild(promptTitle); // Password input (show as ****) var passwordValue = ''; roulettePasswordInput = new Text2('Password: ', { size: 60, fill: "#fff" }); roulettePasswordInput.anchor.set(0.5, 0.5); roulettePasswordInput.x = 2048 / 2; roulettePasswordInput.y = 1200; roulettePasswordPrompt.addChild(roulettePasswordInput); // Error text roulettePasswordError = new Text2('', { size: 48, fill: 0xFF4444 }); roulettePasswordError.anchor.set(0.5, 0.5); roulettePasswordError.x = 2048 / 2; roulettePasswordError.y = 1270; roulettePasswordPrompt.addChild(roulettePasswordError); // Number pad var padStartX = 2048 / 2 + 400; // moved even further right var padStartY = 1320; var padBtns = []; function updateInputDisplay() { var stars = ''; for (var i = 0; i < passwordValue.length; i++) stars += '*'; roulettePasswordInput.setText('Password: ' + stars); if (roulettePasswordError) roulettePasswordError.setText(''); } function clearInput() { passwordValue = ''; updateInputDisplay(); } function trySubmit() { if (passwordValue === '1334') { // Success if (roulettePasswordPrompt) { roulettePasswordPrompt.destroy(); roulettePasswordPrompt = null; } startRoulette(); } else { // Error if (roulettePasswordError) roulettePasswordError.setText('Incorrect password!'); clearInput(); } } // Password keypad layout: numbers in phone order var keypadLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']]; for (var row = 0; row < 4; row++) { for (var col = 0; col < 3; col++) { var label = keypadLabels[row][col]; var btn = new GameButton(); btn.setText(label); // Make buttons smaller and add more space between them btn.btnBg.width = 80; btn.btnBg.height = 80; btn.x = padStartX + col * 94; // 54px button + 40px gap btn.y = padStartY + row * 100; // 54px button + 46px gap // Make the button text larger for visibility for (var t = 0; t < btn.children.length; t++) { if (btn.children[t] && typeof btn.children[t].setText === "function") { btn.children[t].style = btn.children[t].style || {}; btn.children[t].style.size = 36; btn.children[t].setText(label); } } // Make the button background lighter for better contrast if (!isNaN(parseInt(label))) { if (label === '0') { btn.btnBg.color = 0xeeeeee; btn.setText(label); } else { btn.btnBg.color = 0xffffff; btn.setText(label); } } else if (label === 'C') { btn.btnBg.color = 0xffcccc; } else if (label === 'OK') { btn.btnBg.color = 0xccffcc; } btn.down = function (lbl) { return function () { this.flash(); if (lbl === 'C') { clearInput(); } else if (lbl === 'OK') { trySubmit(); } else if (lbl.length === 1 && passwordValue.length < 8) { passwordValue += lbl; updateInputDisplay(); } }; }(label); roulettePasswordPrompt.addChild(btn); padBtns.push(btn); } } updateInputDisplay(); } function selectMode(modeId) { currentMode = modeId; // Remove mode select UI for (var i = 0; i < modeButtons.length; i++) { if (modeButtons[i].parent) modeButtons[i].parent.removeChild(modeButtons[i]); } modeButtons = []; // Start selected mode if (modeId === 'blackjack') { startBlackjack(); } else if (modeId === 'roulette') { showRoulettePasswordPrompt(); } else { showComingSoon(modeId); } } // --- Coming Soon Placeholder --- function showComingSoon(modeId) { showTopLeftBackBtn(function () { if (playArea) playArea.destroy(); playArea = null; showModeSelect(); }); if (playArea) playArea.destroy(); playArea = new Container(); game.addChild(playArea); var txt = new Text2(MODES.filter(function (m) { return m.id === modeId; })[0].name + '\nComing Soon!', { size: 100, fill: "#fff" }); txt.anchor.set(0.5, 0.5); txt.x = 2048 / 2; txt.y = 1200; playArea.addChild(txt); // Back button var backBtn = new GameButton(); backBtn.setText('Back'); backBtn.x = 2048 / 2; backBtn.y = 1800; backBtn.down = function () { playArea.destroy(); playArea = null; showModeSelect(); }; playArea.addChild(backBtn); } // --- Start Blackjack --- function startBlackjack() { showTopLeftBackBtn(function () { if (playArea) playArea.destroy(); playArea = null; if (blackjack) { blackjack.destroy(); blackjack = null; } showModeSelect(); }); if (playArea) playArea.destroy(); playArea = new Container(); game.addChild(playArea); // Destroy old blackjack if any if (blackjack && blackjack.destroy) { blackjack.destroy(); blackjack = null; } blackjack = new BlackjackGame(); playArea.addChild(blackjack); } // (removed selectBlackjackSeat, not needed for single seat) // --- Start Sweet Bonanza --- function startSweetBonanza() { if (playArea) playArea.destroy(); playArea = new Container(); game.addChild(playArea); if (typeof sweetBonanza !== "undefined" && sweetBonanza && sweetBonanza.destroy) { sweetBonanza.destroy(); } sweetBonanza = new SweetBonanzaGame(); playArea.addChild(sweetBonanza); } // --- Start Roulette --- function startRoulette() { showTopLeftBackBtn(function () { if (playArea) playArea.destroy(); playArea = null; if (roulette) { roulette.destroy(); roulette = null; } showModeSelect(); }); if (playArea) playArea.destroy(); playArea = new Container(); game.addChild(playArea); if (typeof roulette !== "undefined" && roulette && roulette.destroy) { roulette.destroy(); } roulette = new RouletteGame(); playArea.addChild(roulette); } // --- Update Balance --- function updateBalance() { balanceText.setText('Balance: $' + playerBalance); storage.balance = playerBalance; } // --- Auto Reward System --- // Give +2000 every 10 minutes (600,000 ms) var AUTO_REWARD_AMOUNT = 2000; var AUTO_REWARD_INTERVAL = 600000; // 10 minutes in ms var lastRewardTime = storage.lastRewardTime || Date.now(); // --- Auto Reward Counter UI --- var autoRewardCounterText = new Text2('', { size: 40, fill: 0x66FFCC }); autoRewardCounterText.anchor.set(0.5, 0); // Place original counter in the center top (for legacy/compat) autoRewardCounterText.x = 2048 / 2; autoRewardCounterText.y = 160; LK.gui.top.addChild(autoRewardCounterText); // Add countdown timer to the top left var autoRewardCounterTextLeft = new Text2('', { size: 40, fill: 0x66FFCC }); autoRewardCounterTextLeft.anchor.set(0, 0); // left aligned, top autoRewardCounterTextLeft.x = 120; // 20px right of reserved area (100px reserved) autoRewardCounterTextLeft.y = 20; // 20px from top LK.gui.topLeft.addChild(autoRewardCounterTextLeft); // --- Quest System --- // Daily quest pool (at least 8, so 5 can be picked randomly each day) var QUEST_POOL = [{ id: 'bj_3rounds', desc: 'Play 3 Blackjack rounds', goal: 3, reward: 500 }, { id: 'roulette_win500', desc: 'Win $500 in Roulette', goal: 500, reward: 1000 }, { id: 'bj_blackjack_win2', desc: 'Win 2 Blackjack rounds', goal: 2, reward: 600 }, { id: 'roulette_bet5', desc: 'Place 5 Roulette bets', goal: 5, reward: 400 }, { id: 'bj_perfect_pair', desc: 'Get 1 Perfect Pair in Blackjack', goal: 1, reward: 1200 }, { id: 'roulette_number_win', desc: 'Win on a number bet in Roulette', goal: 1, reward: 900 }, { id: 'bj_double_down', desc: 'Double Down 2 times in Blackjack', goal: 2, reward: 700 }, { id: 'roulette_red_black', desc: 'Win 3 times on Red or Black in Roulette', goal: 3, reward: 500 }]; // Helper to get a deterministic "random" set of 5 quests per day function getDailyQuestIds() { var now = new Date(); var daySeed = now.getFullYear() * 10000 + (now.getMonth() + 1) * 100 + now.getDate(); var ids = []; var used = []; for (var i = 0; i < QUEST_POOL.length; i++) used[i] = false; var count = 0; var poolLen = QUEST_POOL.length; var seed = daySeed; while (ids.length < 5 && count < 20) { // Simple LCG for deterministic shuffle seed = (seed * 9301 + 49297) % 233280; var idx = Math.floor(seed / 233280 * poolLen); if (!used[idx]) { ids.push(QUEST_POOL[idx].id); used[idx] = true; } count++; } return ids; } // Build today's QUESTS array var QUESTS = []; var dailyIds = getDailyQuestIds(); for (var i = 0; i < dailyIds.length; i++) { for (var j = 0; j < QUEST_POOL.length; j++) { if (QUEST_POOL[j].id === dailyIds[i]) { // Clone quest object and add progress/complete QUESTS.push({ id: QUEST_POOL[j].id, desc: QUEST_POOL[j].desc, goal: QUEST_POOL[j].goal, reward: QUEST_POOL[j].reward, progress: 0, complete: false }); break; } } } // Load quest progress from storage if available and if for today if (storage.quests && storage.questsDay === new Date().toDateString()) { for (var i = 0; i < QUESTS.length; i++) { var q = QUESTS[i]; // Load from flat keys, e.g. quests.key_progress and quests.key_complete var progressKey = q.id + '_progress'; var completeKey = q.id + '_complete'; if (typeof storage.quests[progressKey] !== "undefined") { q.progress = storage.quests[progressKey]; } if (typeof storage.quests[completeKey] !== "undefined") { q.complete = storage.quests[completeKey]; } } } else { // New day, reset quest progress and save today's date // Initialize storage.quests as a flat object with only 1-level deep properties storage.quests = {}; storage.questsDay = new Date().toDateString(); } function saveQuests() { var save = {}; for (var i = 0; i < QUESTS.length; i++) { var q = QUESTS[i]; if (!storage.quests) storage.quests = {}; // Store as flat keys, e.g. quests.key_progress and quests.key_complete storage.quests[q.id + '_progress'] = q.progress; storage.quests[q.id + '_complete'] = q.complete; } storage.questsDay = new Date().toDateString(); } // Quest UI (bottom left, separate area) var questTextNodes = []; function updateQuestUI() { // Remove old for (var i = 0; i < questTextNodes.length; i++) { if (questTextNodes[i].parent) questTextNodes[i].parent.removeChild(questTextNodes[i]); questTextNodes[i].destroy(); } questTextNodes = []; // Place quests in bottom left, avoid left 100px reserved area var y = 40; // Padding from bottom for (var i = 0; i < QUESTS.length; i++) { var q = QUESTS[i]; var txt = new Text2((q.complete ? '✅ ' : '') + q.desc + ' [' + q.progress + '/' + q.goal + ']' + (q.complete ? ' (Claimed)' : ' Prize: $' + q.reward), { size: 32, fill: q.complete ? "#aaffaa" : "#fff" }); txt.anchor.set(0, 1); // left aligned, bottom txt.x = 120; // 20px right of reserved area txt.y = -y; // negative y for bottom alignment in LK.gui.bottomLeft LK.gui.bottomLeft.addChild(txt); questTextNodes.push(txt); y += 38; } } updateQuestUI(); // --- Daily Quest Timer UI (bottom right) --- var questTimerText = new Text2('', { size: 38, fill: 0xFFD700 }); questTimerText.anchor.set(1, 1); // right aligned, bottom questTimerText.x = -40; // 40px from right edge in LK.gui.bottomRight questTimerText.y = -40; // 40px from bottom LK.gui.bottomRight.addChild(questTimerText); function updateQuestTimer() { // Calculate time left until midnight var now = new Date(); var tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0, 0); var msLeft = tomorrow - now; if (msLeft < 0) msLeft = 0; var sec = Math.floor(msLeft / 1000) % 60; var min = Math.floor(msLeft / 60000) % 60; var hr = Math.floor(msLeft / 3600000); var timeStr = (hr < 10 ? '0' : '') + hr + ':' + (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec; questTimerText.setText('Daily quests reset in: ' + timeStr); } LK.setInterval(updateQuestTimer, 1000); updateQuestTimer(); // Quest logic: call these when player does actions function questEvent(event, value) { var updated = false; for (var i = 0; i < QUESTS.length; i++) { var q = QUESTS[i]; if (q.complete) continue; // Blackjack round played if (event === 'blackjack_round' && q.id === 'bj_3rounds') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Win 2 Blackjack rounds if (event === 'blackjack_win' && q.id === 'bj_blackjack_win2') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Double Down in Blackjack if (event === 'blackjack_double' && q.id === 'bj_double_down') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Get Perfect Pair in Blackjack if (event === 'blackjack_perfect_pair' && q.id === 'bj_perfect_pair') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Roulette win $500 if (event === 'roulette_win' && q.id === 'roulette_win500') { q.progress += value; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Place 5 Roulette bets if (event === 'roulette_bet' && q.id === 'roulette_bet5') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Win on a number bet in Roulette if (event === 'roulette_number_win' && q.id === 'roulette_number_win') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } // Win on Red/Black in Roulette if (event === 'roulette_red_black_win' && q.id === 'roulette_red_black') { q.progress++; if (q.progress >= q.goal) { q.progress = q.goal; q.complete = true; playerBalance += q.reward; updateBalance(); showQuestRewardPopup(q.reward, q.desc); } updated = true; } } if (updated) { saveQuests(); updateQuestUI(); } } function showQuestRewardPopup(amount, desc) { var popup = new Text2('Quest Complete!\n' + desc + '\n+$' + amount, { size: 70, fill: 0xFFD700 }); popup.anchor.set(0.5, 0.5); popup.x = 2048 / 2; popup.y = 600; game.addChild(popup); tween(popup, { y: popup.y - 80, alpha: 0 }, { duration: 1400, onFinish: function onFinish() { popup.destroy(); } }); } // Update auto reward counter as before function updateAutoRewardCounter() { var now = Date.now(); var msLeft = AUTO_REWARD_INTERVAL - (now - lastRewardTime) % AUTO_REWARD_INTERVAL; if (msLeft < 0) msLeft = 0; var sec = Math.floor(msLeft / 1000) % 60; var min = Math.floor(msLeft / 60000); var timeStr = (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec; autoRewardCounterText.setText('Next Reward: +' + AUTO_REWARD_AMOUNT + ' in ' + timeStr); autoRewardCounterTextLeft.setText('Next reward: ' + timeStr); } function checkAutoReward() { var now = Date.now(); // If more than interval has passed, give reward (handle multiple missed intervals) var intervals = Math.floor((now - lastRewardTime) / AUTO_REWARD_INTERVAL); if (intervals > 0) { var totalReward = intervals * AUTO_REWARD_AMOUNT; playerBalance += totalReward; updateBalance(); lastRewardTime += intervals * AUTO_REWARD_INTERVAL; storage.lastRewardTime = lastRewardTime; // Optionally show a quick popup for reward var rewardText = new Text2('Auto Reward: +$' + totalReward, { size: 70, fill: 0x66ffcc }); rewardText.anchor.set(0.5, 0.5); rewardText.x = 2048 / 2; rewardText.y = 400; game.addChild(rewardText); tween(rewardText, { y: rewardText.y - 80, alpha: 0 }, { duration: 1200, onFinish: function onFinish() { rewardText.destroy(); } }); } updateAutoRewardCounter(); } // Check auto reward every 10 seconds, and update counter every second LK.setInterval(checkAutoReward, 10000); LK.setInterval(updateAutoRewardCounter, 1000); updateAutoRewardCounter(); // Check for new day and reset quests if needed function checkQuestDay() { var today = new Date().toDateString(); if (storage.questsDay !== today) { // Force reload of page to reset quests (or you can re-run quest init logic here) location.reload(); } } LK.setInterval(checkQuestDay, 60000); // check every minute // --- Start Game --- showModeSelect(); updateBalance(); // --- Touch Handling (for mobile) --- game.move = function (x, y, obj) { // No drag in this game }; game.down = function (x, y, obj) { // No drag in this game }; game.up = function (x, y, obj) { // No drag in this game }; // --- Game Tick --- game.update = function () { // No per-frame logic needed for MVP // Win/Lose system for all casino modes (except Blackjack, which already has it) // Placeholder for future slot/other games: if (currentMode === 'sweet') { // Example: If playerBalance <= 0, show lose popup if (playerBalance <= 0) { LK.showGameOver(); } // Example: If playerBalance >= 10000, show win popup if (playerBalance >= 10000) { LK.showYouWin(); } } };
===================================================================
--- original.js
+++ change.js
@@ -1922,9 +1922,9 @@
}
// Bet controls
var betMinus = new GameButton();
betMinus.setText('-');
- betMinus.x = 2048 / 2 - 250;
+ betMinus.x = 2048 / 2 - 350;
betMinus.y = startY + MODES.length * gapY + 60;
betMinus.down = function () {
var step = 50;
if (betAmount > 20000) {
@@ -1943,11 +1943,22 @@
}
betText.setText('Bet: $' + betAmount);
};
game.addChild(betMinus);
+ var betCustomBtn = new GameButton();
+ betCustomBtn.setText('✎');
+ betCustomBtn.x = 2048 / 2;
+ betCustomBtn.y = startY + MODES.length * gapY + 60;
+ betCustomBtn.btnBg.width = 100;
+ betCustomBtn.btnBg.height = 100;
+ betCustomBtn.down = function () {
+ this.flash();
+ showCustomBetInput();
+ };
+ game.addChild(betCustomBtn);
var betPlus = new GameButton();
betPlus.setText('+');
- betPlus.x = 2048 / 2 + 250;
+ betPlus.x = 2048 / 2 + 350;
betPlus.y = startY + MODES.length * gapY + 60;
betPlus.down = function () {
var step = 50;
if (betAmount >= 20000) {
@@ -1968,9 +1979,124 @@
};
game.addChild(betPlus);
// Store for later removal
// Store for later removal
- modeButtons.push(title, betMinus, betPlus);
+ modeButtons.push(title, betMinus, betCustomBtn, betPlus);
+ // --- Custom Bet Input UI ---
+ var customBetPrompt = null;
+ function showCustomBetInput() {
+ if (customBetPrompt) {
+ customBetPrompt.destroy();
+ customBetPrompt = null;
+ }
+ customBetPrompt = new Container();
+ game.addChild(customBetPrompt);
+ var overlay = customBetPrompt.attachAsset('cardBg', {
+ width: 600,
+ height: 400,
+ color: 0x222244,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 1200
+ });
+ var title = new Text2('Enter Bet Amount', {
+ size: 70,
+ fill: "#fff"
+ });
+ title.anchor.set(0.5, 0.5);
+ title.x = 2048 / 2;
+ title.y = 1050;
+ customBetPrompt.addChild(title);
+ var inputValue = '';
+ var inputText = new Text2('Bet: ', {
+ size: 60,
+ fill: "#fff"
+ });
+ inputText.anchor.set(0.5, 0.5);
+ inputText.x = 2048 / 2;
+ inputText.y = 1200;
+ customBetPrompt.addChild(inputText);
+ var errorText = new Text2('', {
+ size: 40,
+ fill: 0xFF4444
+ });
+ errorText.anchor.set(0.5, 0.5);
+ errorText.x = 2048 / 2;
+ errorText.y = 1270;
+ customBetPrompt.addChild(errorText);
+ function updateInputDisplay() {
+ inputText.setText('Bet: ' + inputValue);
+ errorText.setText('');
+ }
+ // Number pad (digits 0-9, C, OK)
+ var padStartX = 2048 / 2 - 120;
+ var padStartY = 1350;
+ var padLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']];
+ for (var prow = 0; prow < 4; prow++) {
+ for (var pcol = 0; pcol < 3; pcol++) {
+ var plabel = padLabels[prow][pcol];
+ var pbtn = new GameButton();
+ pbtn.setText(plabel);
+ pbtn.btnBg.width = 80;
+ pbtn.btnBg.height = 80;
+ pbtn.x = padStartX + pcol * 100;
+ pbtn.y = padStartY + prow * 100;
+ for (var t = 0; t < pbtn.children.length; t++) {
+ if (pbtn.children[t] && typeof pbtn.children[t].setText === "function") {
+ pbtn.children[t].style = pbtn.children[t].style || {};
+ pbtn.children[t].style.size = 36;
+ pbtn.children[t].setText(plabel);
+ }
+ }
+ if (plabel === 'C') pbtn.btnBg.color = 0xffcccc;
+ if (plabel === 'OK') pbtn.btnBg.color = 0xccffcc;
+ pbtn.down = function (lbl) {
+ return function () {
+ this.flash();
+ if (lbl === 'C') {
+ inputValue = '';
+ updateInputDisplay();
+ } else if (lbl === 'OK') {
+ var val = parseInt(inputValue, 10);
+ if (isNaN(val) || val < minBet || val > maxBet) {
+ errorText.setText('Enter $' + minBet + ' - $' + maxBet);
+ return;
+ }
+ betAmount = val;
+ betText.setText('Bet: $' + betAmount);
+ if (customBetPrompt) {
+ customBetPrompt.destroy();
+ customBetPrompt = null;
+ }
+ } else if (lbl.length === 1 && inputValue.length < 9 && /^\d$/.test(lbl)) {
+ if (inputValue === '0') inputValue = '';
+ inputValue += lbl;
+ updateInputDisplay();
+ }
+ };
+ }(plabel);
+ customBetPrompt.addChild(pbtn);
+ }
+ }
+ // Cancel button
+ var cancelBtn = new GameButton();
+ cancelBtn.setText('Cancel');
+ cancelBtn.x = 2048 / 2;
+ cancelBtn.y = padStartY + 450;
+ cancelBtn.btnBg.width = 200;
+ cancelBtn.btnBg.height = 70;
+ cancelBtn.down = function () {
+ this.flash();
+ if (customBetPrompt) {
+ customBetPrompt.destroy();
+ customBetPrompt = null;
+ }
+ };
+ customBetPrompt.addChild(cancelBtn);
+ updateInputDisplay();
+ }
// Add Instagram handle
var instaHandle = new Text2('@ahmet_db', {
size: 40,
fill: 0xffffff
empty card. In-Game asset. 2d. High contrast. No shadows
Metallic button frame, black snake patterns around, red middle of the button, metal gray frame. In-Game asset. 2d. High contrast. No shadows
instagram logo. In-Game asset. No shadows
more shiney , black areas are like night dark and lines are blood red
remove the cards and the other things make left just croupier
make it a blackjack table and make it fit with the fullscreen. In-Game asset. 2d. High contrast. No shadows