User prompt
rotate screen horizontally
User prompt
rotate game screen horizontally
User prompt
put clicked card under related card automatically
User prompt
write card numbers bigger
User prompt
remove the word stock
User prompt
cardback brighter
User prompt
move deck near word sets
User prompt
move deck little left
User prompt
move word stock near the deck
User prompt
put word stock near deck
User prompt
put word stock below adjescent to deck
User prompt
put word stock below deck
User prompt
put open cards separate from top deck
User prompt
put spider icon on background
User prompt
set background to grey
User prompt
set background to white
User prompt
numbers on two corners
Code edit (1 edits merged)
Please save this source code
User prompt
Spider Solitaire: Web of Cards
Initial prompt
solitaire game with spider theme
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Card class var Card = Container.expand(function () { var self = Container.call(this); // Card properties self.rank = 1; // 1=Ace, 13=King self.suit = 0; // 0=spades (for MVP, only one suit) self.faceUp = false; self.selected = false; // Card graphics var cardFace = self.attachAsset('cardFace', { anchorX: 0.5, anchorY: 0.5 }); var cardBack = self.attachAsset('cardBack', { anchorX: 0.5, anchorY: 0.5 }); cardBack.visible = true; cardFace.visible = false; // Card label (rank/suit) - center var label = new Text2('', { size: 60, fill: 0x222244 }); label.anchor.set(0.5, 0.5); label.x = 0; label.y = 0; self.addChild(label); // Top-left corner label var labelTL = new Text2('', { size: 38, fill: 0x222244 }); labelTL.anchor.set(0, 0); labelTL.x = -cardFace.width / 2 + 18; labelTL.y = -cardFace.height / 2 + 10; self.addChild(labelTL); // Bottom-right corner label var labelBR = new Text2('', { size: 38, fill: 0x222244 }); labelBR.anchor.set(1, 1); labelBR.x = cardFace.width / 2 - 18; labelBR.y = cardFace.height / 2 - 10; self.addChild(labelBR); // Set card data self.setCard = function (rank, suit, faceUp) { self.rank = rank; self.suit = suit; self.faceUp = faceUp; self.updateFace(); }; // Update card face/back and label self.updateFace = function () { cardFace.visible = self.faceUp; cardBack.visible = !self.faceUp; if (self.faceUp) { // Show rank and suit var rankStr = ''; if (self.rank === 1) rankStr = 'A';else if (self.rank === 11) rankStr = 'J';else if (self.rank === 12) rankStr = 'Q';else if (self.rank === 13) rankStr = 'K';else rankStr = '' + self.rank; // Only spades for MVP label.setText(rankStr + ' ♠'); label.visible = true; labelTL.setText(rankStr); labelTL.visible = true; labelBR.setText(rankStr); labelBR.visible = true; } else { label.visible = false; labelTL.visible = false; labelBR.visible = false; } self.updateSelected(); }; // Visual feedback for selection self.updateSelected = function () { if (self.selected) { cardFace.tint = 0x99ccff; cardBack.tint = 0x99ccff; } else { cardFace.tint = 0xffffff; cardBack.tint = 0xffffff; } }; // Flip card self.flip = function (faceUp) { self.faceUp = faceUp; self.updateFace(); }; // Touch events self.down = function (x, y, obj) { if (self.faceUp) { // Let game handle selection if (game) game.onCardDown(self, x, y, obj); } }; return self; }); // Stock pile class (for dealing new rows) var StockPile = Container.expand(function () { var self = Container.call(this); self.cards = []; // Add card to stock self.addCard = function (card) { self.cards.push(card); self.addChild(card); card.x = 0; card.y = 0; }; // Deal one card per tableau pile self.dealToTableau = function (tableauPiles) { if (self.cards.length < tableauPiles.length) return false; for (var i = 0; i < tableauPiles.length; i++) { var card = self.cards.shift(); card.flip(true); tableauPiles[i].addCard(card); } return true; }; // Is empty? self.isEmpty = function () { return self.cards.length === 0; }; return self; }); // Tableau pile class var TableauPile = Container.expand(function () { var self = Container.call(this); self.cards = []; // Add card to pile self.addCard = function (card) { self.cards.push(card); self.addChild(card); self.layout(); }; // Remove card(s) from pile starting at index self.removeCardsFrom = function (idx) { var removed = []; while (self.cards.length > idx) { var c = self.cards.pop(); c.parent.removeChild(c); removed.unshift(c); } self.layout(); return removed; }; // Get top card self.topCard = function () { if (self.cards.length === 0) return null; return self.cards[self.cards.length - 1]; }; // Layout cards in pile self.layout = function () { for (var i = 0; i < self.cards.length; i++) { var c = self.cards[i]; c.x = 0; c.y = i * 60; // Overlap c.zIndex = i; } }; // Reveal top card if needed self.revealTop = function () { var top = self.topCard(); if (top && !top.faceUp) { top.flip(true); } }; // Get index of card in pile self.indexOf = function (card) { for (var i = 0; i < self.cards.length; i++) { if (self.cards[i] === card) return i; } return -1; }; // Can move sequence starting at idx? self.canMoveSequence = function (idx) { // All cards from idx to end must be face up and in descending order for (var i = idx; i < self.cards.length - 1; i++) { var c1 = self.cards[i]; var c2 = self.cards[i + 1]; if (!c1.faceUp || !c2.faceUp) return false; if (c1.rank !== c2.rank + 1) return false; } return self.cards[idx].faceUp; }; // Can accept a sequence of cards (cardsArr)? self.canAccept = function (cardsArr) { if (self.cards.length === 0) { // Only King can be placed on empty pile return cardsArr[0].rank === 13; } else { var top = self.topCard(); var moving = cardsArr[0]; return top.faceUp && top.rank === moving.rank + 1; } }; // Remove completed set (K-A) self.removeCompleteSet = function () { // Check if last 13 cards are a complete set if (self.cards.length < 13) return false; for (var i = 0; i < 13; i++) { var c = self.cards[self.cards.length - 1 - i]; if (!c.faceUp || c.rank !== 13 - i) return false; } // Remove them var removed = []; for (var i = 0; i < 13; i++) { var c = self.cards.pop(); c.parent.removeChild(c); removed.unshift(c); } self.layout(); return true; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xcccccc }); /**** * Game Code ****/ // Add a large faded spider icon to the background, centered // Game constants var backgroundSpider = LK.getAsset('spider', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 8 }); // Swap width/height for landscape orientation backgroundSpider.x = 2732 / 2; backgroundSpider.y = 2048 / 2; backgroundSpider.rotation = Math.PI / 2; backgroundSpider.alpha = 0.08; game.addChildAt(backgroundSpider, 0); // Ensure it's behind all other elements // Card back (spider web themed) // Card face (white for now, will overlay suit/rank) // Spider icon for completed set // Landscape orientation: swap width/height, reposition elements var CARD_WIDTH = 180; var CARD_HEIGHT = 260; var TABLEAU_COUNT = 10; var TABLEAU_SPACING = 32; // For landscape, use 2732 as width, 2048 as height // Center tableau vertically, spread horizontally var TABLEAU_LEFT = 320; var TABLEAU_TOP = (2048 - CARD_HEIGHT) / 2 - 120; var STOCK_X = 2732 - 200; var STOCK_Y = 120; var COMPLETED_X = 200; var COMPLETED_Y = 120; // Game state var tableauPiles = []; var stockPile = null; var completedSets = 0; var draggingCards = null; var draggingFromPile = null; var dragOffsetX = 0; var dragOffsetY = 0; var dragStartX = 0; var dragStartY = 0; var dragValidTarget = null; var dragTargetPile = null; var canDeal = true; // GUI var scoreTxt = new Text2('0', { size: 90, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.x = 2732 / 2; scoreTxt.y = 30; LK.gui.top.addChild(scoreTxt); var dealBtn = new Text2('Deal', { size: 70, fill: 0xFFFFFF }); dealBtn.anchor.set(0.5, 0.5); dealBtn.x = STOCK_X + CARD_WIDTH / 2; dealBtn.y = STOCK_Y + CARD_HEIGHT + 60; LK.gui.top.addChild(dealBtn); // Completed sets display var completedSpiders = []; // Initialize tableau piles for (var i = 0; i < TABLEAU_COUNT; i++) { var pile = new TableauPile(); // In landscape, lay out piles horizontally pile.x = TABLEAU_LEFT + i * (CARD_WIDTH + TABLEAU_SPACING); pile.y = TABLEAU_TOP; game.addChild(pile); tableauPiles.push(pile); } // Initialize stock pile stockPile = new StockPile(); stockPile.x = STOCK_X; stockPile.y = STOCK_Y; game.addChild(stockPile); // (Removed stock label) // Shuffle and deal cards function shuffleDeck() { // 8 decks of spades (104 cards) var deck = []; for (var d = 0; d < 8; d++) { for (var r = 1; r <= 13; r++) { var card = new Card(); card.setCard(r, 0, false); deck.push(card); } } // Fisher-Yates shuffle for (var i = deck.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var tmp = deck[i]; deck[i] = deck[j]; deck[j] = tmp; } return deck; } function dealInitial() { var deck = shuffleDeck(); // 54 cards to tableau (first 4 piles get 6, rest get 5) for (var i = 0; i < TABLEAU_COUNT; i++) { var count = i < 4 ? 6 : 5; for (var j = 0; j < count; j++) { var card = deck.shift(); tableauPiles[i].addCard(card); } } // Flip top card of each pile for (var i = 0; i < TABLEAU_COUNT; i++) { tableauPiles[i].topCard().flip(true); } // Remaining 50 cards to stock while (deck.length > 0) { var card = deck.shift(); stockPile.addCard(card); } completedSets = 0; updateScore(); updateCompletedSpiders(); canDeal = true; } function updateScore() { scoreTxt.setText('Sets: ' + completedSets); } function updateCompletedSpiders() { // Remove old for (var i = 0; i < completedSpiders.length; i++) { if (completedSpiders[i].parent) completedSpiders[i].parent.removeChild(completedSpiders[i]); } completedSpiders = []; // Add new for (var i = 0; i < completedSets; i++) { var spider = LK.getAsset('spider', { anchorX: 0.5, anchorY: 0.5 }); // In landscape, completed spiders are horizontal at top left spider.x = COMPLETED_X + i * 110; spider.y = COMPLETED_Y; game.addChild(spider); completedSpiders.push(spider); } } // Handle card selection and drag game.onCardDown = function (card, x, y, obj) { // Find which pile this card is in var pile = null; var idx = -1; for (var i = 0; i < tableauPiles.length; i++) { var p = tableauPiles[i]; var j = p.indexOf(card); if (j !== -1) { pile = p; idx = j; break; } } if (!pile) return; // Can move sequence? if (!pile.canMoveSequence(idx)) return; // Prepare drag draggingCards = []; for (var k = idx; k < pile.cards.length; k++) { var c = pile.cards[k]; c.selected = true; c.updateSelected(); draggingCards.push(c); } draggingFromPile = pile; // Try to auto-move to a valid pile var autoMoved = false; for (var t = 0; t < tableauPiles.length; t++) { var targetPile = tableauPiles[t]; if (targetPile === pile) continue; if (targetPile.canAccept(draggingCards)) { // Remove from old pile pile.removeCardsFrom(idx); // Add to new pile for (var m = 0; m < draggingCards.length; m++) { targetPile.addCard(draggingCards[m]); } // Reveal top card in old pile pile.revealTop(); // Check for completed set if (targetPile.removeCompleteSet()) { completedSets += 1; updateScore(); updateCompletedSpiders(); // Animate spider var spider = LK.getAsset('spider', { anchorX: 0.5, anchorY: 0.5 }); spider.x = targetPile.x + CARD_WIDTH / 2; spider.y = targetPile.y + targetPile.cards.length * 60 + CARD_HEIGHT / 2; game.addChild(spider); tween(spider, { y: COMPLETED_Y, x: COMPLETED_X + (completedSets - 1) * 110 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { if (spider.parent) spider.parent.removeChild(spider); updateCompletedSpiders(); } }); } // Win condition: 8 sets if (completedSets >= 8) { LK.showYouWin(); return; } // Deselect for (var m = 0; m < draggingCards.length; m++) { draggingCards[m].selected = false; draggingCards[m].updateSelected(); } draggingCards = null; draggingFromPile = null; dragValidTarget = null; dragTargetPile = null; autoMoved = true; break; } } if (autoMoved) return; // Bring to front for manual drag for (var k = 0; k < draggingCards.length; k++) { game.addChild(draggingCards[k]); } // Offset dragOffsetX = card.x; dragOffsetY = card.y; dragStartX = card.parent.x + card.x; dragStartY = card.parent.y + card.y; }; // Handle drag move game.move = function (x, y, obj) { if (!draggingCards) return; // Move cards for (var i = 0; i < draggingCards.length; i++) { draggingCards[i].x = x - dragOffsetX; draggingCards[i].y = y - dragOffsetY + i * 60; } // Check for valid drop target dragValidTarget = null; dragTargetPile = null; for (var i = 0; i < tableauPiles.length; i++) { var pile = tableauPiles[i]; // Don't allow drop on self if (pile === draggingFromPile) continue; // Get pile bounds var px = pile.x; var py = pile.y + pile.cards.length * 60; var pw = CARD_WIDTH; var ph = CARD_HEIGHT; if (x > px && x < px + pw && y > py - 60 && y < py + ph) { // Can accept? if (pile.canAccept(draggingCards)) { dragValidTarget = pile; dragTargetPile = pile; break; } } } }; // Handle drag end game.up = function (x, y, obj) { if (!draggingCards) return; // Drop if (dragValidTarget && dragTargetPile) { // Remove from old pile var idx = draggingFromPile.indexOf(draggingCards[0]); draggingFromPile.removeCardsFrom(idx); // Add to new pile for (var i = 0; i < draggingCards.length; i++) { dragTargetPile.addCard(draggingCards[i]); } // Reveal top card in old pile draggingFromPile.revealTop(); // Check for completed set if (dragTargetPile.removeCompleteSet()) { completedSets += 1; updateScore(); updateCompletedSpiders(); // Animate spider var spider = LK.getAsset('spider', { anchorX: 0.5, anchorY: 0.5 }); spider.x = dragTargetPile.x + CARD_WIDTH / 2; spider.y = dragTargetPile.y + dragTargetPile.cards.length * 60 + CARD_HEIGHT / 2; game.addChild(spider); tween(spider, { y: COMPLETED_Y, x: COMPLETED_X + (completedSets - 1) * 110 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { if (spider.parent) spider.parent.removeChild(spider); updateCompletedSpiders(); } }); } // Win condition: 8 sets if (completedSets >= 8) { LK.showYouWin(); return; } } else { // Return to original pile for (var i = 0; i < draggingCards.length; i++) { draggingCards[i].x = dragStartX - draggingFromPile.x; draggingCards[i].y = dragStartY - draggingFromPile.y + i * 60; draggingFromPile.addChild(draggingCards[i]); } draggingFromPile.layout(); } // Deselect for (var i = 0; i < draggingCards.length; i++) { draggingCards[i].selected = false; draggingCards[i].updateSelected(); } draggingCards = null; draggingFromPile = null; dragValidTarget = null; dragTargetPile = null; }; // Deal new row dealBtn.down = function (x, y, obj) { if (!canDeal) return; // Only allow if all tableau piles have at least one card for (var i = 0; i < tableauPiles.length; i++) { if (tableauPiles[i].cards.length === 0) return; } if (stockPile.isEmpty()) return; canDeal = false; // Animate deal var dealt = stockPile.dealToTableau(tableauPiles); if (dealt) { // Flip top card of each pile for (var i = 0; i < tableauPiles.length; i++) { tableauPiles[i].topCard().flip(true); } } // Allow next deal after short delay LK.setTimeout(function () { canDeal = true; }, 400); }; // Touch on stock pile (deal) stockPile.down = function (x, y, obj) { dealBtn.down(x, y, obj); }; // Reset game function resetGame() { // Remove all cards for (var i = 0; i < tableauPiles.length; i++) { var pile = tableauPiles[i]; while (pile.cards.length > 0) { var c = pile.cards.pop(); if (c.parent) c.parent.removeChild(c); } } while (stockPile.cards.length > 0) { var c = stockPile.cards.pop(); if (c.parent) c.parent.removeChild(c); } completedSets = 0; updateScore(); updateCompletedSpiders(); canDeal = true; draggingCards = null; draggingFromPile = null; dragValidTarget = null; dragTargetPile = null; dealInitial(); } // Game over: no more moves function checkGameOver() { // If no moves and stock is empty var canMove = false; for (var i = 0; i < tableauPiles.length; i++) { var pile = tableauPiles[i]; for (var j = 0; j < pile.cards.length; j++) { if (pile.canMoveSequence(j)) { // Try to move to another pile var seq = []; for (var k = j; k < pile.cards.length; k++) seq.push(pile.cards[k]); for (var t = 0; t < tableauPiles.length; t++) { if (t === i) continue; if (tableauPiles[t].canAccept(seq)) { canMove = true; break; } } } if (canMove) break; } if (canMove) break; } if (!canMove && stockPile.isEmpty()) { LK.showGameOver(); } } // Game update game.update = function () { // Check for game over checkGameOver(); }; // Start game dealInitial();
===================================================================
--- original.js
+++ change.js
@@ -233,18 +233,20 @@
/****
* Game Code
****/
-// Game constants
// Add a large faded spider icon to the background, centered
+// Game constants
var backgroundSpider = LK.getAsset('spider', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 8
});
+// Swap width/height for landscape orientation
backgroundSpider.x = 2732 / 2;
backgroundSpider.y = 2048 / 2;
+backgroundSpider.rotation = Math.PI / 2;
backgroundSpider.alpha = 0.08;
game.addChildAt(backgroundSpider, 0); // Ensure it's behind all other elements
// Card back (spider web themed)
// Card face (white for now, will overlay suit/rank)
@@ -254,8 +256,9 @@
var CARD_HEIGHT = 260;
var TABLEAU_COUNT = 10;
var TABLEAU_SPACING = 32;
// For landscape, use 2732 as width, 2048 as height
+// Center tableau vertically, spread horizontally
var TABLEAU_LEFT = 320;
var TABLEAU_TOP = (2048 - CARD_HEIGHT) / 2 - 120;
var STOCK_X = 2732 - 200;
var STOCK_Y = 120;