/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Card class: represents a single card in the game 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 size var CARD_WIDTH = 220; var CARD_HEIGHT = 320; // Card background var bg = self.attachAsset('cardBg', { width: CARD_WIDTH, height: CARD_HEIGHT, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Card border var border = self.attachAsset('cardBorder', { width: CARD_WIDTH, height: CARD_HEIGHT, color: 0x222222, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); border.alpha = 0.12; // Card text (rank and suit) var txt = new Text2('', { size: 90, fill: 0x222222 }); txt.anchor.set(0.5, 0.5); txt.x = 0; txt.y = 0; self.addChild(txt); // Face down overlay var back = self.attachAsset('cardBack', { width: CARD_WIDTH, height: CARD_HEIGHT, color: 0x3a3a3a, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); back.visible = false; // Set card data self.setCard = function (rank, suit, faceUp) { self.rank = rank; self.suit = suit; self.faceUp = faceUp !== false; self.updateVisual(); }; // Update card visuals self.updateVisual = function () { if (self.faceUp) { txt.visible = true; txt.setText(self.rank + self.suit); txt.setStyle({ fill: self.suit === '♥' || self.suit === '♦' ? "#d83318" : "#222222" }); back.visible = false; } else { txt.visible = false; back.visible = true; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x156c2f // green felt color }); /**** * Game Code ****/ // Add a centered, semi-transparent 'wallpaper' image as a background visual area var wallpaper = LK.getAsset('cardBack', { width: 1200, height: 1800, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); wallpaper.alpha = 0.25; game.addChild(wallpaper); // Card deck setup var SUITS = ['♠', '♥', '♦', '♣']; var RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; // Game state var playerHand = []; var dealerHand = []; var deck = []; var inPlay = false; var playerStands = false; var revealDealer = false; var messageTxt = null; var scoreTxt = null; var streakTxt = null; var highScoreTxt = null; var hitBtn = null; var standBtn = null; var playerScore = 0; var winStreak = 0; var highScore = storage.highScore || 0; // --- Money System --- var minBet = 100; var betAmount = minBet; var maxBet = 1000000; var money = typeof storage.money === "number" ? storage.money : 1000; var moneyTxt = null; var betTxt = null; var betIncBtn = null; var betDecBtn = null; // Card layout var CARD_SPACING = 160; var PLAYER_Y = 2732 - 420; // Move dealer cards lower to make room for streak/high score var DEALER_Y = 420 + 120; // 120px lower // UI: Player hand value var playerValueTxt = new Text2("", { size: 70, fill: 0xffffff }); playerValueTxt.anchor.set(0.5, 1); playerValueTxt.x = 2048 / 2; playerValueTxt.y = PLAYER_Y - 180; game.addChild(playerValueTxt); // UI: Dealer hand value var dealerValueTxt = new Text2("", { size: 70, fill: 0xffffff }); dealerValueTxt.anchor.set(0.5, 0); dealerValueTxt.x = 2048 / 2; dealerValueTxt.y = DEALER_Y + 220; game.addChild(dealerValueTxt); // Utility: shuffle array function shuffle(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = array[i]; array[i] = array[j]; array[j] = t; } return array; } // Utility: create a new deck function createDeck() { var d = []; for (var s = 0; s < SUITS.length; s++) { for (var r = 0; r < RANKS.length; r++) { d.push({ rank: RANKS[r], suit: SUITS[s] }); } } return shuffle(d); } // Utility: get hand value function handValue(hand) { var total = 0; var aces = 0; for (var i = 0; i < hand.length; i++) { var r = hand[i].rank; if (r === 'A') { total += 11; aces++; } else if (r === 'K' || r === 'Q' || r === 'J') { total += 10; } else { total += parseInt(r); } } while (total > 21 && aces > 0) { total -= 10; aces--; } return total; } // Utility: clear all cards from the table function clearTable() { for (var i = 0; i < playerHand.length; i++) { playerHand[i].destroy(); } for (var i = 0; i < dealerHand.length; i++) { dealerHand[i].destroy(); } playerHand = []; dealerHand = []; } // Utility: update all UI text function updateUI() { scoreTxt.setText(playerScore + ""); streakTxt.setText("Streak: " + winStreak); highScoreTxt.setText("High: " + highScore); // Update money and bet UI moneyTxt.setText("Para: " + money + " TL"); betTxt.setText("Bahis: " + betAmount + " TL"); // Enable/disable bet buttons based on bet/money if (betIncBtn && betDecBtn) { betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5; betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5; } // Disable hit/stand if not enough money if (money < minBet) { hitBtn.visible = false; standBtn.visible = false; showMessage("Yetersiz bakiye!", "#d83318"); } // Show player hand value if (playerHand.length > 0) { var playerVal = handValue(playerHand); playerValueTxt.setText("Your total: " + playerVal); playerValueTxt.visible = true; // Check for blackjack (21) and auto-win if in play, but only if it's the initial deal (2 cards) if (playerVal === 21 && inPlay && playerHand.length === 2) { // Show BLACKJACK message in the center of the screen, yellow color messageTxt.setText("BLACKJACK"); messageTxt.setStyle({ fill: 0xFFE600 }); messageTxt.visible = true; // End round as blackjack after a short delay to show the message inPlay = false; hitBtn.visible = false; standBtn.visible = false; // Set a flag so endRound knows this was a blackjack game._justBlackjack = true; LK.setTimeout(function () { endRound('win'); }, 900); } } else { playerValueTxt.visible = false; } // Show dealer hand value (only reveal if dealer's hidden card is up) if (dealerHand.length > 0) { var showDealer = false; if (dealerHand.length > 1 && dealerHand[1].faceUp) showDealer = true; if (dealerHand.length === 1) showDealer = true; if (showDealer) { dealerValueTxt.setText("Dealer: " + handValue(dealerHand)); dealerValueTxt.visible = true; } else { // Show only the visible card's value dealerValueTxt.setText("Dealer: " + handValue([dealerHand[0]])); dealerValueTxt.visible = true; } } else { dealerValueTxt.visible = false; } } // Utility: show message function showMessage(msg, color) { messageTxt.setText(msg); messageTxt.setStyle({ fill: color || "#ffffff" }); messageTxt.visible = true; } // Utility: hide message function hideMessage() { messageTxt.visible = false; } // Deal a card to a hand function dealCard(hand, faceUp, x, y) { if (deck.length === 0) { deck = createDeck(); } var cardData = deck.pop(); var card = new Card(); card.setCard(cardData.rank, cardData.suit, faceUp); card.x = x; card.y = y; game.addChild(card); hand.push(card); return card; } // Layout cards in a hand function layoutHand(hand, y) { var totalWidth = (hand.length - 1) * CARD_SPACING; var startX = 2048 / 2 - totalWidth / 2; for (var i = 0; i < hand.length; i++) { var targetX = startX + i * CARD_SPACING; tween(hand[i], { x: targetX, y: y }, { duration: 200, easing: tween.cubicOut }); } } // Start a new round function startRound() { clearTable(); hideMessage(); // Block round if not enough money if (money < betAmount) { showMessage("Yetersiz bakiye!", "#d83318"); hitBtn.visible = false; standBtn.visible = false; inPlay = false; updateUI(); return; } // Deduct bet at round start money -= betAmount; storage.money = money; inPlay = true; playerStands = false; revealDealer = false; // Shuffle deck if low if (deck.length < 10) { deck = createDeck(); } // Deal initial cards dealCard(playerHand, true, 2048 / 2 - CARD_SPACING / 2, PLAYER_Y); dealCard(dealerHand, true, 2048 / 2 - CARD_SPACING / 2, DEALER_Y); dealCard(playerHand, true, 2048 / 2 + CARD_SPACING / 2, PLAYER_Y); dealCard(dealerHand, false, 2048 / 2 + CARD_SPACING / 2, DEALER_Y); layoutHand(playerHand, PLAYER_Y); layoutHand(dealerHand, DEALER_Y); updateUI(); hitBtn.visible = true; standBtn.visible = true; } // End round and show result function endRound(result) { inPlay = false; revealDealer = true; // Reveal dealer's hidden card if (dealerHand.length > 1) { dealerHand[1].faceUp = true; dealerHand[1].updateVisual(); } // Animate dealer hand to show all cards layoutHand(dealerHand, DEALER_Y); if (result === 'win') { playerScore++; winStreak++; // Award 300x bet on win var winAmount = betAmount * 300; money += winAmount; storage.money = money; if (game._justBlackjack) { // Already showed BLACKJACK, just play sound and flash LK.effects.flashObject(playerHand[0], 0xffe600, 600); // Show win amount in center var winAmountTxt = new Text2("+" + winAmount + " TL", { size: 120, fill: 0xFFE600 }); winAmountTxt.anchor.set(0.5, 0.5); winAmountTxt.x = 2048 / 2; winAmountTxt.y = 2732 / 2 + 120; game.addChild(winAmountTxt); LK.setTimeout(function () { winAmountTxt.visible = false; winAmountTxt.destroy && winAmountTxt.destroy(); }, 900); LK.setTimeout(function () { LK.getSound('ding_sound_effect').play(); }, 100); // Reset flag for next round game._justBlackjack = false; } else { showMessage("You Win!\n+" + winAmount + " TL", "#83de44"); LK.effects.flashObject(playerHand[0], 0x83de44, 600); // Show win amount in center var winAmountTxt = new Text2("+" + winAmount + " TL", { size: 120, fill: 0x83de44 }); winAmountTxt.anchor.set(0.5, 0.5); winAmountTxt.x = 2048 / 2; winAmountTxt.y = 2732 / 2 + 120; game.addChild(winAmountTxt); LK.setTimeout(function () { winAmountTxt.visible = false; winAmountTxt.destroy && winAmountTxt.destroy(); }, 900); // Play win sound effect after a short delay to ensure message is visible and not interrupted LK.setTimeout(function () { LK.getSound('ding_sound_effect').play(); }, 100); } } else if (result === 'lose') { winStreak = 0; showMessage("You Lose", "#d83318"); LK.effects.flashObject(playerHand[0], 0xd83318, 600); } else { // Push: return bet money += betAmount; storage.money = money; showMessage("Push", "#b8b031"); } // Only allow high score to increase if playerScore exceeds it, and only after surpassing it with a win streak if (playerScore > highScore && winStreak > 1) { highScore = playerScore; storage.highScore = highScore; } // If player loses, do not reset highScore, just reset winStreak (already handled above) updateUI(); // Hide buttons hitBtn.visible = false; standBtn.visible = false; // Start next round after delay LK.setTimeout(function () { startRound(); }, 1200); } // Dealer's turn logic function dealerTurn() { // Reveal dealer's hidden card if (dealerHand.length > 1) { dealerHand[1].faceUp = true; dealerHand[1].updateVisual(); } layoutHand(dealerHand, DEALER_Y); // Dealer draws to 17 or higher var dealerVal = handValue(dealerHand); var playerVal = handValue(playerHand); function dealerDraw() { dealerVal = handValue(dealerHand); updateUI(); if (dealerVal < 17) { var card = dealCard(dealerHand, true, 2048 / 2 + (dealerHand.length - 1) * CARD_SPACING / 2, DEALER_Y); layoutHand(dealerHand, DEALER_Y); LK.setTimeout(dealerDraw, 500); } else { // --- Manipulate outcome: 20% win, 80% lose if possible --- var winChance = Math.random(); var canDealerWin = dealerVal > playerVal && dealerVal <= 21; var canDealerPush = dealerVal === playerVal && dealerVal <= 21; var canDealerBust = dealerVal > 21; var canPlayerWin = playerVal > dealerVal && playerVal <= 21; // If player busts, always lose if (playerVal > 21) { endRound('lose'); return; } // If dealer busts, always win if (dealerVal > 21) { endRound('win'); return; } // 20% chance to win, 80% to lose (if possible) if (winChance < 0.2) { // Try to let player win or push, else lose if (canPlayerWin) { endRound('win'); } else if (canDealerPush) { endRound('push'); } else { endRound('lose'); } } else { // Try to let dealer win, else push, else player win if (canDealerWin) { endRound('lose'); } else if (canDealerPush) { endRound('push'); } else { endRound('win'); } } } } LK.setTimeout(dealerDraw, 600); } // Handle player "Hit" function onHit() { if (!inPlay) return; var card = dealCard(playerHand, true, 2048 / 2 + (playerHand.length - 1) * CARD_SPACING / 2, PLAYER_Y); layoutHand(playerHand, PLAYER_Y); var val = handValue(playerHand); updateUI(); if (val > 21) { endRound('lose'); } } // Handle player "Stand" function onStand() { if (!inPlay) return; playerStands = true; hitBtn.visible = false; standBtn.visible = false; dealerTurn(); } // Handle touch on hit/stand buttons function buttonDown(x, y, obj) { if (!inPlay) return; if (obj === hitBtn) { onHit(); } else if (obj === standBtn) { onStand(); } } // UI: Score scoreTxt = new Text2("0", { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // UI: Streak streakTxt = new Text2("Streak: 0", { size: 60, fill: 0xB8B031 }); streakTxt.anchor.set(0.5, 0); streakTxt.y = 120; LK.gui.top.addChild(streakTxt); // UI: High Score highScoreTxt = new Text2("High: " + highScore, { size: 60, fill: 0x83DE44 }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = 200; LK.gui.top.addChild(highScoreTxt); // UI: Message messageTxt = new Text2("", { size: 120, fill: 0xFFFFFF }); messageTxt.anchor.set(0.5, 0.5); messageTxt.x = 2048 / 2; messageTxt.y = 2732 / 2 - 100; messageTxt.visible = false; game.addChild(messageTxt); // --- Money UI --- moneyTxt = new Text2("Para: " + money + " TL", { size: 70, fill: 0xFFE600 }); moneyTxt.anchor.set(0.5, 1); moneyTxt.x = 2048 / 2; moneyTxt.y = playerValueTxt.y - 90; // 90px above 'Your total' (moved higher) game.addChild(moneyTxt); betTxt = new Text2("Bahis: " + betAmount + " TL", { size: 70, fill: 0xB8B031 }); // Move betTxt to bottom left, just above the bet buttons, left-aligned betTxt.anchor.set(0, 1); betTxt.x = 100; // 100px from left edge betTxt.y = 2732 - 120 - 20; // 20px above the top bet button game.addChild(betTxt); // --- Bet Buttons --- // Move bet buttons to bottom left, stacked vertically, with padding from edge betIncBtn = LK.getAsset('hitBtn', { width: 120, height: 120, color: 0x83de44, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 100 + 60, // 60 is half width, 100px padding from left y: 2732 - 100 - 120 // 100px padding from bottom, 120px up for stacking }); game.addChild(betIncBtn); var betIncTxt = new Text2("+", { size: 90, fill: 0xffffff }); betIncTxt.anchor.set(0.5, 0.5); betIncBtn.addChild(betIncTxt); betDecBtn = LK.getAsset('standBtn', { width: 120, height: 120, color: 0xd83318, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 100 + 60, // 60 is half width, 100px padding from left y: 2732 - 100 // 100px padding from bottom }); game.addChild(betDecBtn); var betDecTxt = new Text2("-", { size: 90, fill: 0xffffff }); betDecTxt.anchor.set(0.5, 0.5); betDecBtn.addChild(betDecTxt); // UI: Hit Button hitBtn = LK.getAsset('hitBtn', { width: 420, height: 160, color: 0x83de44, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 260, y: 2732 - 180 }); game.addChild(hitBtn); var hitTxt = new Text2("HIT", { size: 80, fill: 0xFFFFFF }); hitTxt.anchor.set(0.5, 0.5); hitTxt.x = 0; hitTxt.y = 0; hitBtn.addChild(hitTxt); // UI: Stand Button standBtn = LK.getAsset('standBtn', { width: 420, height: 160, color: 0xd83318, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 260, y: 2732 - 180 }); game.addChild(standBtn); var standTxt = new Text2("STAND", { size: 80, fill: 0xFFFFFF }); standTxt.anchor.set(0.5, 0.5); standTxt.x = 0; standTxt.y = 0; standBtn.addChild(standTxt); // Button event handlers hitBtn.down = function (x, y, obj) { buttonDown(x, y, hitBtn); }; standBtn.down = function (x, y, obj) { buttonDown(x, y, standBtn); }; // Bet increase button betIncBtn.down = function (x, y, obj) { if (inPlay) return; if (betAmount + minBet <= money && betAmount + minBet <= maxBet) { betAmount += minBet; updateUI(); } // Enable/disable buttons based on new bet betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5; betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5; }; // Bet decrease button betDecBtn.down = function (x, y, obj) { if (inPlay) return; if (betAmount - minBet >= minBet) { betAmount -= minBet; updateUI(); } // Enable/disable buttons based on new bet betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5; betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5; }; // Prevent overlap with top left menu // (All UI is centered or at bottom, so nothing in top left 100x100) // Play music at game start LK.playMusic('blackjackmusic'); // Start first round startRound(); // No need for game.update, as all logic is event-driven // End of file
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Card class: represents a single card in the game
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 size
var CARD_WIDTH = 220;
var CARD_HEIGHT = 320;
// Card background
var bg = self.attachAsset('cardBg', {
width: CARD_WIDTH,
height: CARD_HEIGHT,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Card border
var border = self.attachAsset('cardBorder', {
width: CARD_WIDTH,
height: CARD_HEIGHT,
color: 0x222222,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
border.alpha = 0.12;
// Card text (rank and suit)
var txt = new Text2('', {
size: 90,
fill: 0x222222
});
txt.anchor.set(0.5, 0.5);
txt.x = 0;
txt.y = 0;
self.addChild(txt);
// Face down overlay
var back = self.attachAsset('cardBack', {
width: CARD_WIDTH,
height: CARD_HEIGHT,
color: 0x3a3a3a,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
back.visible = false;
// Set card data
self.setCard = function (rank, suit, faceUp) {
self.rank = rank;
self.suit = suit;
self.faceUp = faceUp !== false;
self.updateVisual();
};
// Update card visuals
self.updateVisual = function () {
if (self.faceUp) {
txt.visible = true;
txt.setText(self.rank + self.suit);
txt.setStyle({
fill: self.suit === '♥' || self.suit === '♦' ? "#d83318" : "#222222"
});
back.visible = false;
} else {
txt.visible = false;
back.visible = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x156c2f // green felt color
});
/****
* Game Code
****/
// Add a centered, semi-transparent 'wallpaper' image as a background visual area
var wallpaper = LK.getAsset('cardBack', {
width: 1200,
height: 1800,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
wallpaper.alpha = 0.25;
game.addChild(wallpaper);
// Card deck setup
var SUITS = ['♠', '♥', '♦', '♣'];
var RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
// Game state
var playerHand = [];
var dealerHand = [];
var deck = [];
var inPlay = false;
var playerStands = false;
var revealDealer = false;
var messageTxt = null;
var scoreTxt = null;
var streakTxt = null;
var highScoreTxt = null;
var hitBtn = null;
var standBtn = null;
var playerScore = 0;
var winStreak = 0;
var highScore = storage.highScore || 0;
// --- Money System ---
var minBet = 100;
var betAmount = minBet;
var maxBet = 1000000;
var money = typeof storage.money === "number" ? storage.money : 1000;
var moneyTxt = null;
var betTxt = null;
var betIncBtn = null;
var betDecBtn = null;
// Card layout
var CARD_SPACING = 160;
var PLAYER_Y = 2732 - 420;
// Move dealer cards lower to make room for streak/high score
var DEALER_Y = 420 + 120; // 120px lower
// UI: Player hand value
var playerValueTxt = new Text2("", {
size: 70,
fill: 0xffffff
});
playerValueTxt.anchor.set(0.5, 1);
playerValueTxt.x = 2048 / 2;
playerValueTxt.y = PLAYER_Y - 180;
game.addChild(playerValueTxt);
// UI: Dealer hand value
var dealerValueTxt = new Text2("", {
size: 70,
fill: 0xffffff
});
dealerValueTxt.anchor.set(0.5, 0);
dealerValueTxt.x = 2048 / 2;
dealerValueTxt.y = DEALER_Y + 220;
game.addChild(dealerValueTxt);
// Utility: shuffle array
function shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = array[i];
array[i] = array[j];
array[j] = t;
}
return array;
}
// Utility: create a new deck
function createDeck() {
var d = [];
for (var s = 0; s < SUITS.length; s++) {
for (var r = 0; r < RANKS.length; r++) {
d.push({
rank: RANKS[r],
suit: SUITS[s]
});
}
}
return shuffle(d);
}
// Utility: get hand value
function handValue(hand) {
var total = 0;
var aces = 0;
for (var i = 0; i < hand.length; i++) {
var r = hand[i].rank;
if (r === 'A') {
total += 11;
aces++;
} else if (r === 'K' || r === 'Q' || r === 'J') {
total += 10;
} else {
total += parseInt(r);
}
}
while (total > 21 && aces > 0) {
total -= 10;
aces--;
}
return total;
}
// Utility: clear all cards from the table
function clearTable() {
for (var i = 0; i < playerHand.length; i++) {
playerHand[i].destroy();
}
for (var i = 0; i < dealerHand.length; i++) {
dealerHand[i].destroy();
}
playerHand = [];
dealerHand = [];
}
// Utility: update all UI text
function updateUI() {
scoreTxt.setText(playerScore + "");
streakTxt.setText("Streak: " + winStreak);
highScoreTxt.setText("High: " + highScore);
// Update money and bet UI
moneyTxt.setText("Para: " + money + " TL");
betTxt.setText("Bahis: " + betAmount + " TL");
// Enable/disable bet buttons based on bet/money
if (betIncBtn && betDecBtn) {
betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5;
betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5;
}
// Disable hit/stand if not enough money
if (money < minBet) {
hitBtn.visible = false;
standBtn.visible = false;
showMessage("Yetersiz bakiye!", "#d83318");
}
// Show player hand value
if (playerHand.length > 0) {
var playerVal = handValue(playerHand);
playerValueTxt.setText("Your total: " + playerVal);
playerValueTxt.visible = true;
// Check for blackjack (21) and auto-win if in play, but only if it's the initial deal (2 cards)
if (playerVal === 21 && inPlay && playerHand.length === 2) {
// Show BLACKJACK message in the center of the screen, yellow color
messageTxt.setText("BLACKJACK");
messageTxt.setStyle({
fill: 0xFFE600
});
messageTxt.visible = true;
// End round as blackjack after a short delay to show the message
inPlay = false;
hitBtn.visible = false;
standBtn.visible = false;
// Set a flag so endRound knows this was a blackjack
game._justBlackjack = true;
LK.setTimeout(function () {
endRound('win');
}, 900);
}
} else {
playerValueTxt.visible = false;
}
// Show dealer hand value (only reveal if dealer's hidden card is up)
if (dealerHand.length > 0) {
var showDealer = false;
if (dealerHand.length > 1 && dealerHand[1].faceUp) showDealer = true;
if (dealerHand.length === 1) showDealer = true;
if (showDealer) {
dealerValueTxt.setText("Dealer: " + handValue(dealerHand));
dealerValueTxt.visible = true;
} else {
// Show only the visible card's value
dealerValueTxt.setText("Dealer: " + handValue([dealerHand[0]]));
dealerValueTxt.visible = true;
}
} else {
dealerValueTxt.visible = false;
}
}
// Utility: show message
function showMessage(msg, color) {
messageTxt.setText(msg);
messageTxt.setStyle({
fill: color || "#ffffff"
});
messageTxt.visible = true;
}
// Utility: hide message
function hideMessage() {
messageTxt.visible = false;
}
// Deal a card to a hand
function dealCard(hand, faceUp, x, y) {
if (deck.length === 0) {
deck = createDeck();
}
var cardData = deck.pop();
var card = new Card();
card.setCard(cardData.rank, cardData.suit, faceUp);
card.x = x;
card.y = y;
game.addChild(card);
hand.push(card);
return card;
}
// Layout cards in a hand
function layoutHand(hand, y) {
var totalWidth = (hand.length - 1) * CARD_SPACING;
var startX = 2048 / 2 - totalWidth / 2;
for (var i = 0; i < hand.length; i++) {
var targetX = startX + i * CARD_SPACING;
tween(hand[i], {
x: targetX,
y: y
}, {
duration: 200,
easing: tween.cubicOut
});
}
}
// Start a new round
function startRound() {
clearTable();
hideMessage();
// Block round if not enough money
if (money < betAmount) {
showMessage("Yetersiz bakiye!", "#d83318");
hitBtn.visible = false;
standBtn.visible = false;
inPlay = false;
updateUI();
return;
}
// Deduct bet at round start
money -= betAmount;
storage.money = money;
inPlay = true;
playerStands = false;
revealDealer = false;
// Shuffle deck if low
if (deck.length < 10) {
deck = createDeck();
}
// Deal initial cards
dealCard(playerHand, true, 2048 / 2 - CARD_SPACING / 2, PLAYER_Y);
dealCard(dealerHand, true, 2048 / 2 - CARD_SPACING / 2, DEALER_Y);
dealCard(playerHand, true, 2048 / 2 + CARD_SPACING / 2, PLAYER_Y);
dealCard(dealerHand, false, 2048 / 2 + CARD_SPACING / 2, DEALER_Y);
layoutHand(playerHand, PLAYER_Y);
layoutHand(dealerHand, DEALER_Y);
updateUI();
hitBtn.visible = true;
standBtn.visible = true;
}
// End round and show result
function endRound(result) {
inPlay = false;
revealDealer = true;
// Reveal dealer's hidden card
if (dealerHand.length > 1) {
dealerHand[1].faceUp = true;
dealerHand[1].updateVisual();
}
// Animate dealer hand to show all cards
layoutHand(dealerHand, DEALER_Y);
if (result === 'win') {
playerScore++;
winStreak++;
// Award 300x bet on win
var winAmount = betAmount * 300;
money += winAmount;
storage.money = money;
if (game._justBlackjack) {
// Already showed BLACKJACK, just play sound and flash
LK.effects.flashObject(playerHand[0], 0xffe600, 600);
// Show win amount in center
var winAmountTxt = new Text2("+" + winAmount + " TL", {
size: 120,
fill: 0xFFE600
});
winAmountTxt.anchor.set(0.5, 0.5);
winAmountTxt.x = 2048 / 2;
winAmountTxt.y = 2732 / 2 + 120;
game.addChild(winAmountTxt);
LK.setTimeout(function () {
winAmountTxt.visible = false;
winAmountTxt.destroy && winAmountTxt.destroy();
}, 900);
LK.setTimeout(function () {
LK.getSound('ding_sound_effect').play();
}, 100);
// Reset flag for next round
game._justBlackjack = false;
} else {
showMessage("You Win!\n+" + winAmount + " TL", "#83de44");
LK.effects.flashObject(playerHand[0], 0x83de44, 600);
// Show win amount in center
var winAmountTxt = new Text2("+" + winAmount + " TL", {
size: 120,
fill: 0x83de44
});
winAmountTxt.anchor.set(0.5, 0.5);
winAmountTxt.x = 2048 / 2;
winAmountTxt.y = 2732 / 2 + 120;
game.addChild(winAmountTxt);
LK.setTimeout(function () {
winAmountTxt.visible = false;
winAmountTxt.destroy && winAmountTxt.destroy();
}, 900);
// Play win sound effect after a short delay to ensure message is visible and not interrupted
LK.setTimeout(function () {
LK.getSound('ding_sound_effect').play();
}, 100);
}
} else if (result === 'lose') {
winStreak = 0;
showMessage("You Lose", "#d83318");
LK.effects.flashObject(playerHand[0], 0xd83318, 600);
} else {
// Push: return bet
money += betAmount;
storage.money = money;
showMessage("Push", "#b8b031");
}
// Only allow high score to increase if playerScore exceeds it, and only after surpassing it with a win streak
if (playerScore > highScore && winStreak > 1) {
highScore = playerScore;
storage.highScore = highScore;
}
// If player loses, do not reset highScore, just reset winStreak (already handled above)
updateUI();
// Hide buttons
hitBtn.visible = false;
standBtn.visible = false;
// Start next round after delay
LK.setTimeout(function () {
startRound();
}, 1200);
}
// Dealer's turn logic
function dealerTurn() {
// Reveal dealer's hidden card
if (dealerHand.length > 1) {
dealerHand[1].faceUp = true;
dealerHand[1].updateVisual();
}
layoutHand(dealerHand, DEALER_Y);
// Dealer draws to 17 or higher
var dealerVal = handValue(dealerHand);
var playerVal = handValue(playerHand);
function dealerDraw() {
dealerVal = handValue(dealerHand);
updateUI();
if (dealerVal < 17) {
var card = dealCard(dealerHand, true, 2048 / 2 + (dealerHand.length - 1) * CARD_SPACING / 2, DEALER_Y);
layoutHand(dealerHand, DEALER_Y);
LK.setTimeout(dealerDraw, 500);
} else {
// --- Manipulate outcome: 20% win, 80% lose if possible ---
var winChance = Math.random();
var canDealerWin = dealerVal > playerVal && dealerVal <= 21;
var canDealerPush = dealerVal === playerVal && dealerVal <= 21;
var canDealerBust = dealerVal > 21;
var canPlayerWin = playerVal > dealerVal && playerVal <= 21;
// If player busts, always lose
if (playerVal > 21) {
endRound('lose');
return;
}
// If dealer busts, always win
if (dealerVal > 21) {
endRound('win');
return;
}
// 20% chance to win, 80% to lose (if possible)
if (winChance < 0.2) {
// Try to let player win or push, else lose
if (canPlayerWin) {
endRound('win');
} else if (canDealerPush) {
endRound('push');
} else {
endRound('lose');
}
} else {
// Try to let dealer win, else push, else player win
if (canDealerWin) {
endRound('lose');
} else if (canDealerPush) {
endRound('push');
} else {
endRound('win');
}
}
}
}
LK.setTimeout(dealerDraw, 600);
}
// Handle player "Hit"
function onHit() {
if (!inPlay) return;
var card = dealCard(playerHand, true, 2048 / 2 + (playerHand.length - 1) * CARD_SPACING / 2, PLAYER_Y);
layoutHand(playerHand, PLAYER_Y);
var val = handValue(playerHand);
updateUI();
if (val > 21) {
endRound('lose');
}
}
// Handle player "Stand"
function onStand() {
if (!inPlay) return;
playerStands = true;
hitBtn.visible = false;
standBtn.visible = false;
dealerTurn();
}
// Handle touch on hit/stand buttons
function buttonDown(x, y, obj) {
if (!inPlay) return;
if (obj === hitBtn) {
onHit();
} else if (obj === standBtn) {
onStand();
}
}
// UI: Score
scoreTxt = new Text2("0", {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// UI: Streak
streakTxt = new Text2("Streak: 0", {
size: 60,
fill: 0xB8B031
});
streakTxt.anchor.set(0.5, 0);
streakTxt.y = 120;
LK.gui.top.addChild(streakTxt);
// UI: High Score
highScoreTxt = new Text2("High: " + highScore, {
size: 60,
fill: 0x83DE44
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.y = 200;
LK.gui.top.addChild(highScoreTxt);
// UI: Message
messageTxt = new Text2("", {
size: 120,
fill: 0xFFFFFF
});
messageTxt.anchor.set(0.5, 0.5);
messageTxt.x = 2048 / 2;
messageTxt.y = 2732 / 2 - 100;
messageTxt.visible = false;
game.addChild(messageTxt);
// --- Money UI ---
moneyTxt = new Text2("Para: " + money + " TL", {
size: 70,
fill: 0xFFE600
});
moneyTxt.anchor.set(0.5, 1);
moneyTxt.x = 2048 / 2;
moneyTxt.y = playerValueTxt.y - 90; // 90px above 'Your total' (moved higher)
game.addChild(moneyTxt);
betTxt = new Text2("Bahis: " + betAmount + " TL", {
size: 70,
fill: 0xB8B031
});
// Move betTxt to bottom left, just above the bet buttons, left-aligned
betTxt.anchor.set(0, 1);
betTxt.x = 100; // 100px from left edge
betTxt.y = 2732 - 120 - 20; // 20px above the top bet button
game.addChild(betTxt);
// --- Bet Buttons ---
// Move bet buttons to bottom left, stacked vertically, with padding from edge
betIncBtn = LK.getAsset('hitBtn', {
width: 120,
height: 120,
color: 0x83de44,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 100 + 60,
// 60 is half width, 100px padding from left
y: 2732 - 100 - 120 // 100px padding from bottom, 120px up for stacking
});
game.addChild(betIncBtn);
var betIncTxt = new Text2("+", {
size: 90,
fill: 0xffffff
});
betIncTxt.anchor.set(0.5, 0.5);
betIncBtn.addChild(betIncTxt);
betDecBtn = LK.getAsset('standBtn', {
width: 120,
height: 120,
color: 0xd83318,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 100 + 60,
// 60 is half width, 100px padding from left
y: 2732 - 100 // 100px padding from bottom
});
game.addChild(betDecBtn);
var betDecTxt = new Text2("-", {
size: 90,
fill: 0xffffff
});
betDecTxt.anchor.set(0.5, 0.5);
betDecBtn.addChild(betDecTxt);
// UI: Hit Button
hitBtn = LK.getAsset('hitBtn', {
width: 420,
height: 160,
color: 0x83de44,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 260,
y: 2732 - 180
});
game.addChild(hitBtn);
var hitTxt = new Text2("HIT", {
size: 80,
fill: 0xFFFFFF
});
hitTxt.anchor.set(0.5, 0.5);
hitTxt.x = 0;
hitTxt.y = 0;
hitBtn.addChild(hitTxt);
// UI: Stand Button
standBtn = LK.getAsset('standBtn', {
width: 420,
height: 160,
color: 0xd83318,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 260,
y: 2732 - 180
});
game.addChild(standBtn);
var standTxt = new Text2("STAND", {
size: 80,
fill: 0xFFFFFF
});
standTxt.anchor.set(0.5, 0.5);
standTxt.x = 0;
standTxt.y = 0;
standBtn.addChild(standTxt);
// Button event handlers
hitBtn.down = function (x, y, obj) {
buttonDown(x, y, hitBtn);
};
standBtn.down = function (x, y, obj) {
buttonDown(x, y, standBtn);
};
// Bet increase button
betIncBtn.down = function (x, y, obj) {
if (inPlay) return;
if (betAmount + minBet <= money && betAmount + minBet <= maxBet) {
betAmount += minBet;
updateUI();
}
// Enable/disable buttons based on new bet
betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5;
betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5;
};
// Bet decrease button
betDecBtn.down = function (x, y, obj) {
if (inPlay) return;
if (betAmount - minBet >= minBet) {
betAmount -= minBet;
updateUI();
}
// Enable/disable buttons based on new bet
betIncBtn.alpha = betAmount + minBet <= money && betAmount + minBet <= maxBet ? 1 : 0.5;
betDecBtn.alpha = betAmount - minBet >= minBet ? 1 : 0.5;
};
// Prevent overlap with top left menu
// (All UI is centered or at bottom, so nothing in top left 100x100)
// Play music at game start
LK.playMusic('blackjackmusic');
// Start first round
startRound();
// No need for game.update, as all logic is event-driven
// End of file