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.style.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: 0x0a1a2f }); /**** * 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; var DEALER_Y = 420; // 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); } // Utility: show message function showMessage(msg, color) { messageTxt.setText(msg); messageTxt.style.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(); 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); 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++; showMessage("You Win!", "#83de44"); LK.effects.flashObject(playerHand[0], 0x83de44, 600); } else if (result === 'lose') { winStreak = 0; showMessage("You Lose", "#d83318"); LK.effects.flashObject(playerHand[0], 0xd83318, 600); } else { showMessage("Push", "#b8b031"); } if (playerScore > highScore) { highScore = playerScore; storage.highScore = highScore; } 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); 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); 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 = buttonDown; standBtn.down = buttonDown; // Prevent overlap with top left menu // (All UI is centered or at bottom, so nothing in top left 100x100) // Start first round startRound(); // No need for game.update, as all logic is event-driven // End of file
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,410 @@
-/****
+/****
+* 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.style.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: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x0a1a2f
+});
+
+/****
+* 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;
+var DEALER_Y = 420;
+// 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);
+}
+// Utility: show message
+function showMessage(msg, color) {
+ messageTxt.setText(msg);
+ messageTxt.style.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();
+ 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);
+ 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++;
+ showMessage("You Win!", "#83de44");
+ LK.effects.flashObject(playerHand[0], 0x83de44, 600);
+ } else if (result === 'lose') {
+ winStreak = 0;
+ showMessage("You Lose", "#d83318");
+ LK.effects.flashObject(playerHand[0], 0xd83318, 600);
+ } else {
+ showMessage("Push", "#b8b031");
+ }
+ if (playerScore > highScore) {
+ highScore = playerScore;
+ storage.highScore = highScore;
+ }
+ 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);
+ 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);
+ 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 = buttonDown;
+standBtn.down = buttonDown;
+// Prevent overlap with top left menu
+// (All UI is centered or at bottom, so nothing in top left 100x100)
+// Start first round
+startRound();
+// No need for game.update, as all logic is event-driven
+// End of file
\ No newline at end of file