/****
* 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