/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Button = Container.expand(function (text, color) { var self = Container.call(this); var buttonShape = color; var buttonGraphics = self.attachAsset(buttonShape, { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(text, { size: 56, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function (x, y, obj) { tween(self, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); }; self.up = function (x, y, obj) { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; return self; }); var Card = Container.expand(function (suit, rank) { var self = Container.call(this); self.suit = suit; self.rank = rank; self.faceUp = false; var cardBackGraphics = self.attachAsset('cardBack', { anchorX: 0.5, anchorY: 0.5 }); var cardAssetId = suit + '_' + rank; var cardFrontGraphics = self.attachAsset(cardAssetId, { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); var cardText = new Text2('', { size: 32, fill: 0x000000 }); cardText.anchor.set(0.5, 0.5); cardText.alpha = 0; self.addChild(cardText); self.getValue = function () { if (self.rank === 'A') return 11; if (self.rank === 'K' || self.rank === 'Q' || self.rank === 'J') return 10; return parseInt(self.rank); }; self.flip = function () { if (self.faceUp) return; self.faceUp = true; LK.getSound('cardFlip').play(); tween(cardBackGraphics, { alpha: 0 }, { duration: 300 }); tween(cardFrontGraphics, { alpha: 1 }, { duration: 300 }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0F4C0F }); /**** * Game Code ****/ // Add background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0 })); background.x = 0; background.y = 0; // Spades cards (black) // Clubs cards (black) // Diamonds cards (red) // Hearts cards (red) var suits = ['hearts', 'diamonds', 'clubs', 'spades']; var ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; var deck = []; var playerCards = []; var dealerCards = []; var playerTotal = 0; var dealerTotal = 0; var gameState = 'waiting'; // 'waiting', 'playing', 'dealerTurn', 'gameOver' var wins = 0; var losses = 0; // Visual deck in center var deckDisplay = game.addChild(LK.getAsset('cardBack', { anchorX: 0.5, anchorY: 0.5 })); deckDisplay.x = 1024; deckDisplay.y = 1366; // UI Elements var playerTotalText = new Text2('Player: 0', { size: 48, fill: 0xFFFFFF }); playerTotalText.anchor.set(0.5, 0); playerTotalText.x = 1024; playerTotalText.y = 1700; game.addChild(playerTotalText); var dealerTotalText = new Text2('Dealer: ?', { size: 48, fill: 0xFFFFFF }); dealerTotalText.anchor.set(0.5, 0); dealerTotalText.x = 1024; dealerTotalText.y = 850; game.addChild(dealerTotalText); var scoreText = new Text2('Wins: 0 | Losses: 0', { size: 36, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 1024; scoreText.y = 100; game.addChild(scoreText); var messageText = new Text2('Tap Deal to start!', { size: 42, fill: 0xFFFF00 }); messageText.anchor.set(0.5, 0.5); messageText.x = 1024; messageText.y = 1000; game.addChild(messageText); // Buttons var hitButton = game.addChild(new Button('HIT', 'hitButton')); hitButton.x = 650; hitButton.y = 2200; hitButton.alpha = 0; var standButton = game.addChild(new Button('STAND', 'standButton')); standButton.x = 1398; standButton.y = 2200; standButton.alpha = 0; var dealButton = game.addChild(new Button('DEAL', 'dealButton')); dealButton.x = 1024; dealButton.y = 2200; function createDeck() { deck = []; for (var s = 0; s < suits.length; s++) { for (var r = 0; r < ranks.length; r++) { deck.push(new Card(suits[s], ranks[r])); } } // Shuffle deck for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } function dealCard(toPlayer) { if (deck.length === 0) return null; var card = deck.pop(); game.addChild(card); // Start card at deck position card.x = 1024; card.y = 1366; if (toPlayer) { playerCards.push(card); var totalWidth = playerCards.length * 260; var startX = 1024 - (totalWidth - 260) / 2; var finalX = startX + (playerCards.length - 1) * 260; var finalY = 2000; // Animate card to player position with slight leftward movement tween(card, { x: finalX - 50, y: finalY }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { tween(card, { x: finalX }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { LK.getSound('cardFlip').play(); card.flip(); } }); } }); } else { dealerCards.push(card); var totalWidth = dealerCards.length * 260; var startX = 1024 - (totalWidth - 260) / 2; var finalX = startX + (dealerCards.length - 1) * 260; var finalY = 600; // Animate card to dealer position with slight leftward movement tween(card, { x: finalX - 50, y: finalY }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { tween(card, { x: finalX }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { if (dealerCards.length === 1) { LK.getSound('cardFlip').play(); card.flip(); } } }); } }); } return card; } function calculateTotal(cards, showAll) { var total = 0; var aces = 0; for (var i = 0; i < cards.length; i++) { if (!showAll && cards === dealerCards && i === 1 && !cards[i].faceUp) { continue; } var value = cards[i].getValue(); if (value === 11) { aces++; } total += value; } while (total > 21 && aces > 0) { total -= 10; aces--; } return total; } function updateTotals() { playerTotal = calculateTotal(playerCards, true); dealerTotal = calculateTotal(dealerCards, gameState !== 'playing'); playerTotalText.setText('Player: ' + playerTotal); if (gameState === 'playing') { dealerTotalText.setText('Dealer: ?'); } else { dealerTotalText.setText('Dealer: ' + dealerTotal); } } function startNewHand() { // Clear previous cards for (var i = 0; i < playerCards.length; i++) { playerCards[i].destroy(); } for (var i = 0; i < dealerCards.length; i++) { dealerCards[i].destroy(); } playerCards = []; dealerCards = []; createDeck(); gameState = 'playing'; // Deal initial cards dealCard(true); // Player dealCard(false); // Dealer (face up) dealCard(true); // Player dealCard(false); // Dealer (face down) updateTotals(); if (playerTotal === 21) { messageText.setText('Blackjack!'); LK.getSound('win').play(); LK.setTimeout(function () { endHand(); }, 1000); } else { messageText.setText('Hit or Stand?'); } hitButton.alpha = 1; standButton.alpha = 1; dealButton.alpha = 0; } function playerHit() { if (gameState !== 'playing') return; dealCard(true); updateTotals(); if (playerTotal > 21) { messageText.setText('Bust! You lose!'); hitButton.alpha = 0; standButton.alpha = 0; dealButton.alpha = 1; gameState = 'gameOver'; losses++; updateScore(); LK.getSound('lose').play(); } else if (playerTotal === 21) { playerStand(); } } function playerStand() { if (gameState !== 'playing') return; gameState = 'dealerTurn'; hitButton.alpha = 0; standButton.alpha = 0; // Reveal dealer's face-down card if (dealerCards.length > 1) { LK.getSound('cardFlip').play(); dealerCards[1].flip(); } updateTotals(); dealerPlay(); } function dealerPlay() { LK.setTimeout(function () { dealerTotal = calculateTotal(dealerCards, true); if (dealerTotal < 17) { dealCard(false); if (dealerCards[dealerCards.length - 1]) { LK.getSound('cardFlip').play(); dealerCards[dealerCards.length - 1].flip(); } updateTotals(); dealerPlay(); } else { endHand(); } }, 1000); } function endHand() { gameState = 'gameOver'; dealButton.alpha = 1; var playerFinalTotal = calculateTotal(playerCards, true); var dealerFinalTotal = calculateTotal(dealerCards, true); if (playerFinalTotal > 21) { messageText.setText('You bust! Dealer wins!'); losses++; LK.getSound('lose').play(); } else if (dealerFinalTotal > 21) { messageText.setText('Dealer busts! You win!'); wins++; LK.getSound('win').play(); } else if (playerFinalTotal > dealerFinalTotal) { messageText.setText('You win!'); wins++; LK.getSound('win').play(); } else if (dealerFinalTotal > playerFinalTotal) { messageText.setText('Dealer wins!'); losses++; LK.getSound('lose').play(); } else { messageText.setText('Push! It\'s a tie!'); } updateScore(); } function updateScore() { scoreText.setText('Wins: ' + wins + ' | Losses: ' + losses); } // Button event handlers hitButton.down = function (x, y, obj) { tween(hitButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); if (gameState === 'playing') { playerHit(); } }; hitButton.up = function (x, y, obj) { tween(hitButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; standButton.down = function (x, y, obj) { tween(standButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); if (gameState === 'playing') { playerStand(); } }; standButton.up = function (x, y, obj) { tween(standButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; dealButton.down = function (x, y, obj) { tween(dealButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); if (gameState === 'waiting' || gameState === 'gameOver') { startNewHand(); } }; dealButton.up = function (x, y, obj) { tween(dealButton, { scaleX: 1, scaleY: 1 }, { duration: 100 }); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Button = Container.expand(function (text, color) {
var self = Container.call(this);
var buttonShape = color;
var buttonGraphics = self.attachAsset(buttonShape, {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 56,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
return self;
});
var Card = Container.expand(function (suit, rank) {
var self = Container.call(this);
self.suit = suit;
self.rank = rank;
self.faceUp = false;
var cardBackGraphics = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
var cardAssetId = suit + '_' + rank;
var cardFrontGraphics = self.attachAsset(cardAssetId, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
var cardText = new Text2('', {
size: 32,
fill: 0x000000
});
cardText.anchor.set(0.5, 0.5);
cardText.alpha = 0;
self.addChild(cardText);
self.getValue = function () {
if (self.rank === 'A') return 11;
if (self.rank === 'K' || self.rank === 'Q' || self.rank === 'J') return 10;
return parseInt(self.rank);
};
self.flip = function () {
if (self.faceUp) return;
self.faceUp = true;
LK.getSound('cardFlip').play();
tween(cardBackGraphics, {
alpha: 0
}, {
duration: 300
});
tween(cardFrontGraphics, {
alpha: 1
}, {
duration: 300
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0F4C0F
});
/****
* Game Code
****/
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
// Spades cards (black)
// Clubs cards (black)
// Diamonds cards (red)
// Hearts cards (red)
var suits = ['hearts', 'diamonds', 'clubs', 'spades'];
var ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
var deck = [];
var playerCards = [];
var dealerCards = [];
var playerTotal = 0;
var dealerTotal = 0;
var gameState = 'waiting'; // 'waiting', 'playing', 'dealerTurn', 'gameOver'
var wins = 0;
var losses = 0;
// Visual deck in center
var deckDisplay = game.addChild(LK.getAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
}));
deckDisplay.x = 1024;
deckDisplay.y = 1366;
// UI Elements
var playerTotalText = new Text2('Player: 0', {
size: 48,
fill: 0xFFFFFF
});
playerTotalText.anchor.set(0.5, 0);
playerTotalText.x = 1024;
playerTotalText.y = 1700;
game.addChild(playerTotalText);
var dealerTotalText = new Text2('Dealer: ?', {
size: 48,
fill: 0xFFFFFF
});
dealerTotalText.anchor.set(0.5, 0);
dealerTotalText.x = 1024;
dealerTotalText.y = 850;
game.addChild(dealerTotalText);
var scoreText = new Text2('Wins: 0 | Losses: 0', {
size: 36,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1024;
scoreText.y = 100;
game.addChild(scoreText);
var messageText = new Text2('Tap Deal to start!', {
size: 42,
fill: 0xFFFF00
});
messageText.anchor.set(0.5, 0.5);
messageText.x = 1024;
messageText.y = 1000;
game.addChild(messageText);
// Buttons
var hitButton = game.addChild(new Button('HIT', 'hitButton'));
hitButton.x = 650;
hitButton.y = 2200;
hitButton.alpha = 0;
var standButton = game.addChild(new Button('STAND', 'standButton'));
standButton.x = 1398;
standButton.y = 2200;
standButton.alpha = 0;
var dealButton = game.addChild(new Button('DEAL', 'dealButton'));
dealButton.x = 1024;
dealButton.y = 2200;
function createDeck() {
deck = [];
for (var s = 0; s < suits.length; s++) {
for (var r = 0; r < ranks.length; r++) {
deck.push(new Card(suits[s], ranks[r]));
}
}
// Shuffle deck
for (var i = deck.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
function dealCard(toPlayer) {
if (deck.length === 0) return null;
var card = deck.pop();
game.addChild(card);
// Start card at deck position
card.x = 1024;
card.y = 1366;
if (toPlayer) {
playerCards.push(card);
var totalWidth = playerCards.length * 260;
var startX = 1024 - (totalWidth - 260) / 2;
var finalX = startX + (playerCards.length - 1) * 260;
var finalY = 2000;
// Animate card to player position with slight leftward movement
tween(card, {
x: finalX - 50,
y: finalY
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(card, {
x: finalX
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.getSound('cardFlip').play();
card.flip();
}
});
}
});
} else {
dealerCards.push(card);
var totalWidth = dealerCards.length * 260;
var startX = 1024 - (totalWidth - 260) / 2;
var finalX = startX + (dealerCards.length - 1) * 260;
var finalY = 600;
// Animate card to dealer position with slight leftward movement
tween(card, {
x: finalX - 50,
y: finalY
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(card, {
x: finalX
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
if (dealerCards.length === 1) {
LK.getSound('cardFlip').play();
card.flip();
}
}
});
}
});
}
return card;
}
function calculateTotal(cards, showAll) {
var total = 0;
var aces = 0;
for (var i = 0; i < cards.length; i++) {
if (!showAll && cards === dealerCards && i === 1 && !cards[i].faceUp) {
continue;
}
var value = cards[i].getValue();
if (value === 11) {
aces++;
}
total += value;
}
while (total > 21 && aces > 0) {
total -= 10;
aces--;
}
return total;
}
function updateTotals() {
playerTotal = calculateTotal(playerCards, true);
dealerTotal = calculateTotal(dealerCards, gameState !== 'playing');
playerTotalText.setText('Player: ' + playerTotal);
if (gameState === 'playing') {
dealerTotalText.setText('Dealer: ?');
} else {
dealerTotalText.setText('Dealer: ' + dealerTotal);
}
}
function startNewHand() {
// Clear previous cards
for (var i = 0; i < playerCards.length; i++) {
playerCards[i].destroy();
}
for (var i = 0; i < dealerCards.length; i++) {
dealerCards[i].destroy();
}
playerCards = [];
dealerCards = [];
createDeck();
gameState = 'playing';
// Deal initial cards
dealCard(true); // Player
dealCard(false); // Dealer (face up)
dealCard(true); // Player
dealCard(false); // Dealer (face down)
updateTotals();
if (playerTotal === 21) {
messageText.setText('Blackjack!');
LK.getSound('win').play();
LK.setTimeout(function () {
endHand();
}, 1000);
} else {
messageText.setText('Hit or Stand?');
}
hitButton.alpha = 1;
standButton.alpha = 1;
dealButton.alpha = 0;
}
function playerHit() {
if (gameState !== 'playing') return;
dealCard(true);
updateTotals();
if (playerTotal > 21) {
messageText.setText('Bust! You lose!');
hitButton.alpha = 0;
standButton.alpha = 0;
dealButton.alpha = 1;
gameState = 'gameOver';
losses++;
updateScore();
LK.getSound('lose').play();
} else if (playerTotal === 21) {
playerStand();
}
}
function playerStand() {
if (gameState !== 'playing') return;
gameState = 'dealerTurn';
hitButton.alpha = 0;
standButton.alpha = 0;
// Reveal dealer's face-down card
if (dealerCards.length > 1) {
LK.getSound('cardFlip').play();
dealerCards[1].flip();
}
updateTotals();
dealerPlay();
}
function dealerPlay() {
LK.setTimeout(function () {
dealerTotal = calculateTotal(dealerCards, true);
if (dealerTotal < 17) {
dealCard(false);
if (dealerCards[dealerCards.length - 1]) {
LK.getSound('cardFlip').play();
dealerCards[dealerCards.length - 1].flip();
}
updateTotals();
dealerPlay();
} else {
endHand();
}
}, 1000);
}
function endHand() {
gameState = 'gameOver';
dealButton.alpha = 1;
var playerFinalTotal = calculateTotal(playerCards, true);
var dealerFinalTotal = calculateTotal(dealerCards, true);
if (playerFinalTotal > 21) {
messageText.setText('You bust! Dealer wins!');
losses++;
LK.getSound('lose').play();
} else if (dealerFinalTotal > 21) {
messageText.setText('Dealer busts! You win!');
wins++;
LK.getSound('win').play();
} else if (playerFinalTotal > dealerFinalTotal) {
messageText.setText('You win!');
wins++;
LK.getSound('win').play();
} else if (dealerFinalTotal > playerFinalTotal) {
messageText.setText('Dealer wins!');
losses++;
LK.getSound('lose').play();
} else {
messageText.setText('Push! It\'s a tie!');
}
updateScore();
}
function updateScore() {
scoreText.setText('Wins: ' + wins + ' | Losses: ' + losses);
}
// Button event handlers
hitButton.down = function (x, y, obj) {
tween(hitButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
if (gameState === 'playing') {
playerHit();
}
};
hitButton.up = function (x, y, obj) {
tween(hitButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
standButton.down = function (x, y, obj) {
tween(standButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
if (gameState === 'playing') {
playerStand();
}
};
standButton.up = function (x, y, obj) {
tween(standButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
dealButton.down = function (x, y, obj) {
tween(dealButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
if (gameState === 'waiting' || gameState === 'gameOver') {
startNewHand();
}
};
dealButton.up = function (x, y, obj) {
tween(dealButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};