User prompt
make it so it shows how much your cards add up to, and make the dealers cards lower so you can se your streak and high score
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'txt.style.fill = self.suit === '♥' || self.suit === '♦' ? "#d83318" : "#222222";' Line Number: 79
Code edit (1 edits merged)
Please save this source code
User prompt
Blackjack Blitz
Initial prompt
a black jack game
/**** * 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; } }; self.scaleX = 1; // Ensure scaleX is initialized for flip animation return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x156c2f // green felt color }); /**** * Game Code ****/ // 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; // 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); // 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); // Start card off-screen above the table for animation card.x = x; card.y = y - 400; game.addChild(card); hand.push(card); // Animate card dropping into place tween(card, { y: y }, { duration: 320, easing: tween.cubicOut }); 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; // Animate both x and y for smooth movement tween(hand[i], { x: targetX, y: y }, { duration: 220, easing: tween.cubicOut }); } } // Start a new round function startRound() { clearTable(); hideMessage(); 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) { // Animate card flip: scaleX to 0, swap face, then scaleX to 1 tween(dealerHand[1], { scaleX: 0 }, { duration: 120, easing: tween.cubicIn, onFinish: function onFinish() { dealerHand[1].faceUp = true; dealerHand[1].updateVisual(); tween(dealerHand[1], { scaleX: 1 }, { duration: 120, easing: tween.cubicOut }); } }); } // Animate dealer hand to show all cards layoutHand(dealerHand, DEALER_Y); if (result === 'win') { playerScore++; winStreak++; if (game._justBlackjack) { // Already showed BLACKJACK, just play sound and flash LK.effects.flashObject(playerHand[0], 0xffe600, 600); LK.setTimeout(function () { LK.getSound('ding_sound_effect').play(); }, 100); // Animate BLACKJACK message: spin and hold for 3 seconds messageTxt.rotation = 0; tween(messageTxt, { rotation: Math.PI * 2 }, { duration: 900, easing: tween.cubicOut, onFinish: function onFinish() { messageTxt.rotation = 0; } }); // Reset flag for next round game._justBlackjack = false; // Delay next round for 3 seconds var nextRoundDelay = 3000; } else { showMessage("You Win!", "#83de44"); LK.effects.flashObject(playerHand[0], 0x83de44, 600); // 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); // Animate win message: spin and hold for 3 seconds messageTxt.rotation = 0; tween(messageTxt, { rotation: Math.PI * 2 }, { duration: 900, easing: tween.cubicOut, onFinish: function onFinish() { messageTxt.rotation = 0; } }); var nextRoundDelay = 3000; } } else if (result === 'lose') { winStreak = 0; showMessage("You Lose", "#d83318"); LK.effects.flashObject(playerHand[0], 0xd83318, 600); // Animate lose message: spin and hold for 3 seconds messageTxt.rotation = 0; tween(messageTxt, { rotation: Math.PI * 2 }, { duration: 900, easing: tween.cubicOut, onFinish: function onFinish() { messageTxt.rotation = 0; } }); var nextRoundDelay = 3000; } else { showMessage("Push", "#b8b031"); var nextRoundDelay = 1200; } // 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(); }, nextRoundDelay); } // Dealer's turn logic function dealerTurn() { // Reveal dealer's hidden card if (dealerHand.length > 1) { // Animate card flip: scaleX to 0, swap face, then scaleX to 1 tween(dealerHand[1], { scaleX: 0 }, { duration: 120, easing: tween.cubicIn, onFinish: function onFinish() { dealerHand[1].faceUp = true; dealerHand[1].updateVisual(); tween(dealerHand[1], { scaleX: 1 }, { duration: 120, easing: tween.cubicOut }); } }); } 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 { // Compare hands if (dealerVal > 21) { endRound('win'); } else if (dealerVal > playerVal) { endRound('lose'); } else if (dealerVal < playerVal) { endRound('win'); } else { endRound('push'); } } } 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); // 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); }; // 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;
}
};
self.scaleX = 1; // Ensure scaleX is initialized for flip animation
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x156c2f // green felt color
});
/****
* Game Code
****/
// 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;
// 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);
// 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);
// Start card off-screen above the table for animation
card.x = x;
card.y = y - 400;
game.addChild(card);
hand.push(card);
// Animate card dropping into place
tween(card, {
y: y
}, {
duration: 320,
easing: tween.cubicOut
});
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;
// Animate both x and y for smooth movement
tween(hand[i], {
x: targetX,
y: y
}, {
duration: 220,
easing: tween.cubicOut
});
}
}
// Start a new round
function startRound() {
clearTable();
hideMessage();
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) {
// Animate card flip: scaleX to 0, swap face, then scaleX to 1
tween(dealerHand[1], {
scaleX: 0
}, {
duration: 120,
easing: tween.cubicIn,
onFinish: function onFinish() {
dealerHand[1].faceUp = true;
dealerHand[1].updateVisual();
tween(dealerHand[1], {
scaleX: 1
}, {
duration: 120,
easing: tween.cubicOut
});
}
});
}
// Animate dealer hand to show all cards
layoutHand(dealerHand, DEALER_Y);
if (result === 'win') {
playerScore++;
winStreak++;
if (game._justBlackjack) {
// Already showed BLACKJACK, just play sound and flash
LK.effects.flashObject(playerHand[0], 0xffe600, 600);
LK.setTimeout(function () {
LK.getSound('ding_sound_effect').play();
}, 100);
// Animate BLACKJACK message: spin and hold for 3 seconds
messageTxt.rotation = 0;
tween(messageTxt, {
rotation: Math.PI * 2
}, {
duration: 900,
easing: tween.cubicOut,
onFinish: function onFinish() {
messageTxt.rotation = 0;
}
});
// Reset flag for next round
game._justBlackjack = false;
// Delay next round for 3 seconds
var nextRoundDelay = 3000;
} else {
showMessage("You Win!", "#83de44");
LK.effects.flashObject(playerHand[0], 0x83de44, 600);
// 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);
// Animate win message: spin and hold for 3 seconds
messageTxt.rotation = 0;
tween(messageTxt, {
rotation: Math.PI * 2
}, {
duration: 900,
easing: tween.cubicOut,
onFinish: function onFinish() {
messageTxt.rotation = 0;
}
});
var nextRoundDelay = 3000;
}
} else if (result === 'lose') {
winStreak = 0;
showMessage("You Lose", "#d83318");
LK.effects.flashObject(playerHand[0], 0xd83318, 600);
// Animate lose message: spin and hold for 3 seconds
messageTxt.rotation = 0;
tween(messageTxt, {
rotation: Math.PI * 2
}, {
duration: 900,
easing: tween.cubicOut,
onFinish: function onFinish() {
messageTxt.rotation = 0;
}
});
var nextRoundDelay = 3000;
} else {
showMessage("Push", "#b8b031");
var nextRoundDelay = 1200;
}
// 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();
}, nextRoundDelay);
}
// Dealer's turn logic
function dealerTurn() {
// Reveal dealer's hidden card
if (dealerHand.length > 1) {
// Animate card flip: scaleX to 0, swap face, then scaleX to 1
tween(dealerHand[1], {
scaleX: 0
}, {
duration: 120,
easing: tween.cubicIn,
onFinish: function onFinish() {
dealerHand[1].faceUp = true;
dealerHand[1].updateVisual();
tween(dealerHand[1], {
scaleX: 1
}, {
duration: 120,
easing: tween.cubicOut
});
}
});
}
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 {
// Compare hands
if (dealerVal > 21) {
endRound('win');
} else if (dealerVal > playerVal) {
endRound('lose');
} else if (dealerVal < playerVal) {
endRound('win');
} else {
endRound('push');
}
}
}
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);
// 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);
};
// 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