User prompt
Please fix the bug: 'Uncaught TypeError: slot.containsPoint is not a function' in or related to this line: 'if (!slot.occupied && slot.containsPoint({' Line Number: 485
Code edit (1 edits merged)
Please save this source code
User prompt
Cardbound: The Inscription Trials
Initial prompt
I want a game like inscription from you
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Card class: represents a single card (creature or resource) var Card = Container.expand(function () { var self = Container.call(this); // Card properties (to be set on creation) self.cardData = null; // {name, attack, health, cost, type, id} self.isPlayerCard = true; // true if belongs to player, false if opponent // Card visual var cardBox = self.attachAsset('cardBox', { width: 260, height: 360, color: 0x222222, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Card name var nameTxt = new Text2('', { size: 48, fill: "#fff" }); nameTxt.anchor.set(0.5, 0); nameTxt.x = 0; nameTxt.y = -150; self.addChild(nameTxt); // Attack/Health var statsTxt = new Text2('', { size: 48, fill: 0xFFEC70 }); statsTxt.anchor.set(0.5, 0.5); statsTxt.x = -70; statsTxt.y = 120; self.addChild(statsTxt); // Cost var costTxt = new Text2('', { size: 40, fill: 0xB8B031 }); costTxt.anchor.set(0.5, 0.5); costTxt.x = 70; costTxt.y = 120; self.addChild(costTxt); // Set card data and visuals self.setCard = function (cardData, isPlayerCard) { self.cardData = cardData; self.isPlayerCard = isPlayerCard; nameTxt.setText(cardData.name); statsTxt.setText(cardData.attack + "/" + cardData.health); costTxt.setText(cardData.cost); // Tint for opponent cards cardBox.tint = isPlayerCard ? 0x222222 : 0x2a1a2a; }; // Update stats display self.updateStats = function () { if (self.cardData) { statsTxt.setText(self.cardData.attack + "/" + self.cardData.health); } }; // Flash effect for damage self.flash = function (color) { LK.effects.flashObject(self, color, 300); }; // Dragging self.isDraggable = false; self.isDragging = false; // Touch events self.down = function (x, y, obj) { if (self.isDraggable && !self.isDragging) { self.isDragging = true; dragCard = self; dragOrigin = { x: self.x, y: self.y }; // Bring to front if (self.parent) { self.parent.removeChild(self); game.addChild(self); } } }; self.up = function (x, y, obj) { if (self.isDragging) { self.isDragging = false; dragCard = null; // Snap back if not played if (!self.justPlayed) { tween(self, { x: dragOrigin.x, y: dragOrigin.y }, { duration: 200, easing: tween.easeOut }); } self.justPlayed = false; } }; return self; }); // Slot class: represents a board slot (for creatures) var Slot = Container.expand(function () { var self = Container.call(this); self.isPlayerSlot = true; self.slotIndex = 0; self.occupied = false; self.card = null; var slotBox = self.attachAsset('slotBox', { width: 270, height: 380, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Highlight for valid drop self.setHighlight = function (on) { slotBox.tint = on ? 0x83de44 : 0x444444; }; // Place card in slot self.placeCard = function (card) { self.card = card; self.occupied = true; card.x = self.x; card.y = self.y; card.isDraggable = false; card.isDragging = false; card.justPlayed = true; game.addChild(card); }; // Remove card from slot self.removeCard = function () { self.card = null; self.occupied = false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x18181a }); /**** * Game Code ****/ // --- Game Constants --- var BOARD_COLS = 4; var PLAYER_Y = 2100; var OPPONENT_Y = 700; var HAND_Y = 2500; var SLOT_SPACING = 340; var HAND_SPACING = 320; var MAX_HAND = 5; var MAX_HEALTH = 10; // --- Card Pool --- var CARD_POOL = [{ id: 1, name: "Stoat", attack: 1, health: 2, cost: 1, type: "creature" }, { id: 2, name: "Wolf", attack: 3, health: 2, cost: 2, type: "creature" }, { id: 3, name: "Bullfrog", attack: 1, health: 3, cost: 1, type: "creature" }, { id: 4, name: "Adder", attack: 1, health: 1, cost: 2, type: "creature" }, { id: 5, name: "Squirrel", attack: 0, health: 1, cost: 0, type: "resource" }]; // --- Game State --- var playerDeck = []; var opponentDeck = []; var playerHand = []; var opponentHand = []; var playerSlots = []; var opponentSlots = []; var playerHealth = MAX_HEALTH; var opponentHealth = MAX_HEALTH; var turn = "player"; // "player" or "opponent" var dragCard = null; var dragOrigin = null; var validDropSlot = null; var canPlay = true; var playerResources = 0; var turnTxt, healthTxt, oppHealthTxt, resourceTxt, messageTxt; // --- UI Setup --- // Health display healthTxt = new Text2("You: " + playerHealth, { size: 80, fill: "#fff" }); healthTxt.anchor.set(0, 0.5); LK.gui.top.addChild(healthTxt); oppHealthTxt = new Text2("Opponent: " + opponentHealth, { size: 80, fill: "#fff" }); oppHealthTxt.anchor.set(1, 0.5); LK.gui.topRight.addChild(oppHealthTxt); // Turn display turnTxt = new Text2("Your Turn", { size: 70, fill: 0xFFEC70 }); turnTxt.anchor.set(0.5, 0.5); LK.gui.top.addChild(turnTxt); // Resource display resourceTxt = new Text2("Blood: " + playerResources, { size: 60, fill: 0xB8B031 }); resourceTxt.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(resourceTxt); // Message display messageTxt = new Text2("", { size: 60, fill: 0xFFEC70 }); messageTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(messageTxt); // --- Board Setup --- // Player slots for (var i = 0; i < BOARD_COLS; i++) { var slot = new Slot(); slot.isPlayerSlot = true; slot.slotIndex = i; slot.x = 400 + i * SLOT_SPACING; slot.y = PLAYER_Y; playerSlots.push(slot); game.addChild(slot); } // Opponent slots for (var i = 0; i < BOARD_COLS; i++) { var slot = new Slot(); slot.isPlayerSlot = false; slot.slotIndex = i; slot.x = 400 + i * SLOT_SPACING; slot.y = OPPONENT_Y; opponentSlots.push(slot); game.addChild(slot); } // --- Deck/Hand Setup --- function shuffleDeck(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 createDeck() { // Player: 2 Stoat, 2 Wolf, 2 Bullfrog, 1 Adder, 3 Squirrel var deck = []; for (var i = 0; i < 2; i++) deck.push(CARD_POOL[0]); for (var i = 0; i < 2; i++) deck.push(CARD_POOL[1]); for (var i = 0; i < 2; i++) deck.push(CARD_POOL[2]); deck.push(CARD_POOL[3]); for (var i = 0; i < 3; i++) deck.push(CARD_POOL[4]); shuffleDeck(deck); return deck.slice(); } function createOpponentDeck() { // Opponent: 2 Wolf, 2 Bullfrog, 2 Adder, 2 Squirrel var deck = []; for (var i = 0; i < 2; i++) deck.push(CARD_POOL[1]); for (var i = 0; i < 2; i++) deck.push(CARD_POOL[2]); for (var i = 0; i < 2; i++) deck.push(CARD_POOL[3]); for (var i = 0; i < 2; i++) deck.push(CARD_POOL[4]); shuffleDeck(deck); return deck.slice(); } // --- Hand Display --- function updateHandDisplay() { // Remove all player hand cards from game for (var i = 0; i < playerHand.length; i++) { if (playerHand[i].parent) playerHand[i].parent.removeChild(playerHand[i]); } // Layout hand for (var i = 0; i < playerHand.length; i++) { var card = playerHand[i]; card.x = 400 + i * HAND_SPACING; card.y = HAND_Y; card.isDraggable = canPlay && turn === "player"; card.isPlayerCard = true; game.addChild(card); } } function updateOpponentHandDisplay() { // Remove all opponent hand cards from game for (var i = 0; i < opponentHand.length; i++) { if (opponentHand[i].parent) opponentHand[i].parent.removeChild(opponentHand[i]); } // Layout hand (hidden) for (var i = 0; i < opponentHand.length; i++) { var card = opponentHand[i]; card.x = 400 + i * HAND_SPACING; card.y = OPPONENT_Y - 250; card.isDraggable = false; card.isPlayerCard = false; game.addChild(card); } } // --- Draw Card --- function drawCard(deck, hand, isPlayer) { if (deck.length === 0 || hand.length >= MAX_HAND) return; var cardData = deck.shift(); var card = new Card(); card.setCard(cardData, isPlayer); hand.push(card); } // --- Start Game --- function startGame() { playerDeck = createDeck(); opponentDeck = createOpponentDeck(); playerHand = []; opponentHand = []; playerHealth = MAX_HEALTH; opponentHealth = MAX_HEALTH; playerResources = 0; turn = "player"; canPlay = true; messageTxt.setText(""); // Remove all cards from slots for (var i = 0; i < BOARD_COLS; i++) { if (playerSlots[i].card) { playerSlots[i].card.destroy(); playerSlots[i].removeCard(); } if (opponentSlots[i].card) { opponentSlots[i].card.destroy(); opponentSlots[i].removeCard(); } } // Draw initial hands for (var i = 0; i < 4; i++) drawCard(playerDeck, playerHand, true); for (var i = 0; i < 4; i++) drawCard(opponentDeck, opponentHand, false); updateHandDisplay(); updateOpponentHandDisplay(); updateUI(); } function updateUI() { healthTxt.setText("You: " + playerHealth); oppHealthTxt.setText("Opponent: " + opponentHealth); resourceTxt.setText("Blood: " + playerResources); turnTxt.setText(turn === "player" ? "Your Turn" : "Opponent Turn"); } // --- Turn Logic --- function startPlayerTurn() { turn = "player"; canPlay = true; playerResources += 1; drawCard(playerDeck, playerHand, true); updateHandDisplay(); updateUI(); messageTxt.setText("Your turn. Drag a card to a slot."); } function startOpponentTurn() { turn = "opponent"; canPlay = false; updateUI(); messageTxt.setText("Opponent's turn..."); LK.setTimeout(opponentPlay, 900); } // --- Play Card --- function canPlayCard(card, slot) { if (!card || !slot) return false; if (!slot.isPlayerSlot) return false; if (slot.occupied) return false; if (card.cardData.type === "resource") return true; if (playerResources >= card.cardData.cost) return true; return false; } function playCard(card, slot) { if (!canPlayCard(card, slot)) return false; // Remove from hand var idx = playerHand.indexOf(card); if (idx !== -1) playerHand.splice(idx, 1); // Place in slot slot.placeCard(card); // Pay cost if (card.cardData.type === "creature") { playerResources -= card.cardData.cost; } // Squirrel: resource, gives +1 blood, then disappears if (card.cardData.type === "resource") { playerResources += 1; card.flash(0xb8b031); LK.setTimeout(function () { slot.removeCard(); card.destroy(); }, 400); } updateHandDisplay(); updateUI(); return true; } // --- Drag & Drop --- game.move = function (x, y, obj) { if (dragCard && dragCard.isDragging) { dragCard.x = x; dragCard.y = y; // Highlight valid slot var found = null; for (var i = 0; i < playerSlots.length; i++) { var slot = playerSlots[i]; if (!slot.occupied && slot.containsPoint({ x: x, y: y })) { found = slot; slot.setHighlight(true); } else { slot.setHighlight(false); } } validDropSlot = found; } }; game.down = function (x, y, obj) { // No-op: handled by Card.down }; game.up = function (x, y, obj) { if (dragCard && dragCard.isDragging) { // Try to play card if (validDropSlot && canPlayCard(dragCard, validDropSlot)) { playCard(dragCard, validDropSlot); dragCard.justPlayed = true; validDropSlot.setHighlight(false); } else { // Snap back dragCard.justPlayed = false; } dragCard.isDragging = false; dragCard = null; validDropSlot = null; for (var i = 0; i < playerSlots.length; i++) playerSlots[i].setHighlight(false); } }; // --- Combat Phase --- function combatPhase() { // Player creatures attack for (var i = 0; i < BOARD_COLS; i++) { var pSlot = playerSlots[i]; if (pSlot.card && pSlot.card.cardData.type === "creature") { var oppSlot = opponentSlots[i]; if (oppSlot.card && oppSlot.card.cardData.type === "creature") { // Attack opposing creature oppSlot.card.cardData.health -= pSlot.card.cardData.attack; pSlot.card.flash(0xffec70); oppSlot.card.flash(0xd83318); oppSlot.card.updateStats(); if (oppSlot.card.cardData.health <= 0) { oppSlot.card.flash(0xd83318); LK.setTimeout(function (slot, card) { return function () { slot.removeCard(); card.destroy(); }; }(oppSlot, oppSlot.card), 300); } } else { // Attack opponent directly opponentHealth -= pSlot.card.cardData.attack; if (opponentHealth < 0) opponentHealth = 0; } } } // Opponent creatures attack for (var i = 0; i < BOARD_COLS; i++) { var oSlot = opponentSlots[i]; if (oSlot.card && oSlot.card.cardData.type === "creature") { var pSlot = playerSlots[i]; if (pSlot.card && pSlot.card.cardData.type === "creature") { // Attack opposing creature pSlot.card.cardData.health -= oSlot.card.cardData.attack; oSlot.card.flash(0xffec70); pSlot.card.flash(0xd83318); pSlot.card.updateStats(); if (pSlot.card.cardData.health <= 0) { pSlot.card.flash(0xd83318); LK.setTimeout(function (slot, card) { return function () { slot.removeCard(); card.destroy(); }; }(pSlot, pSlot.card), 300); } } else { // Attack player directly playerHealth -= oSlot.card.cardData.attack; if (playerHealth < 0) playerHealth = 0; } } } updateUI(); // Check win/lose if (playerHealth <= 0) { LK.effects.flashScreen(0xd83318, 1000); LK.showGameOver(); return; } if (opponentHealth <= 0) { LK.effects.flashScreen(0x83de44, 1000); LK.showYouWin(); return; } // Next turn if (turn === "player") { LK.setTimeout(startOpponentTurn, 900); } else { LK.setTimeout(startPlayerTurn, 900); } } // --- Opponent AI --- function opponentPlay() { // Play first playable creature to empty slot var played = false; for (var i = 0; i < opponentHand.length; i++) { var card = opponentHand[i]; if (card.cardData.type === "creature") { for (var j = 0; j < BOARD_COLS; j++) { var slot = opponentSlots[j]; if (!slot.occupied) { // Play card opponentHand.splice(i, 1); slot.placeCard(card); played = true; break; } } if (played) break; } } // Draw a card drawCard(opponentDeck, opponentHand, false); updateOpponentHandDisplay(); LK.setTimeout(combatPhase, 900); } // --- Game Update --- game.update = function () { // No per-frame logic needed for MVP }; // --- Start the game --- startGame();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,577 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Card class: represents a single card (creature or resource)
+var Card = Container.expand(function () {
+ var self = Container.call(this);
+ // Card properties (to be set on creation)
+ self.cardData = null; // {name, attack, health, cost, type, id}
+ self.isPlayerCard = true; // true if belongs to player, false if opponent
+ // Card visual
+ var cardBox = self.attachAsset('cardBox', {
+ width: 260,
+ height: 360,
+ color: 0x222222,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Card name
+ var nameTxt = new Text2('', {
+ size: 48,
+ fill: "#fff"
+ });
+ nameTxt.anchor.set(0.5, 0);
+ nameTxt.x = 0;
+ nameTxt.y = -150;
+ self.addChild(nameTxt);
+ // Attack/Health
+ var statsTxt = new Text2('', {
+ size: 48,
+ fill: 0xFFEC70
+ });
+ statsTxt.anchor.set(0.5, 0.5);
+ statsTxt.x = -70;
+ statsTxt.y = 120;
+ self.addChild(statsTxt);
+ // Cost
+ var costTxt = new Text2('', {
+ size: 40,
+ fill: 0xB8B031
+ });
+ costTxt.anchor.set(0.5, 0.5);
+ costTxt.x = 70;
+ costTxt.y = 120;
+ self.addChild(costTxt);
+ // Set card data and visuals
+ self.setCard = function (cardData, isPlayerCard) {
+ self.cardData = cardData;
+ self.isPlayerCard = isPlayerCard;
+ nameTxt.setText(cardData.name);
+ statsTxt.setText(cardData.attack + "/" + cardData.health);
+ costTxt.setText(cardData.cost);
+ // Tint for opponent cards
+ cardBox.tint = isPlayerCard ? 0x222222 : 0x2a1a2a;
+ };
+ // Update stats display
+ self.updateStats = function () {
+ if (self.cardData) {
+ statsTxt.setText(self.cardData.attack + "/" + self.cardData.health);
+ }
+ };
+ // Flash effect for damage
+ self.flash = function (color) {
+ LK.effects.flashObject(self, color, 300);
+ };
+ // Dragging
+ self.isDraggable = false;
+ self.isDragging = false;
+ // Touch events
+ self.down = function (x, y, obj) {
+ if (self.isDraggable && !self.isDragging) {
+ self.isDragging = true;
+ dragCard = self;
+ dragOrigin = {
+ x: self.x,
+ y: self.y
+ };
+ // Bring to front
+ if (self.parent) {
+ self.parent.removeChild(self);
+ game.addChild(self);
+ }
+ }
+ };
+ self.up = function (x, y, obj) {
+ if (self.isDragging) {
+ self.isDragging = false;
+ dragCard = null;
+ // Snap back if not played
+ if (!self.justPlayed) {
+ tween(self, {
+ x: dragOrigin.x,
+ y: dragOrigin.y
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ }
+ self.justPlayed = false;
+ }
+ };
+ return self;
+});
+// Slot class: represents a board slot (for creatures)
+var Slot = Container.expand(function () {
+ var self = Container.call(this);
+ self.isPlayerSlot = true;
+ self.slotIndex = 0;
+ self.occupied = false;
+ self.card = null;
+ var slotBox = self.attachAsset('slotBox', {
+ width: 270,
+ height: 380,
+ color: 0x444444,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Highlight for valid drop
+ self.setHighlight = function (on) {
+ slotBox.tint = on ? 0x83de44 : 0x444444;
+ };
+ // Place card in slot
+ self.placeCard = function (card) {
+ self.card = card;
+ self.occupied = true;
+ card.x = self.x;
+ card.y = self.y;
+ card.isDraggable = false;
+ card.isDragging = false;
+ card.justPlayed = true;
+ game.addChild(card);
+ };
+ // Remove card from slot
+ self.removeCard = function () {
+ self.card = null;
+ self.occupied = false;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x18181a
+});
+
+/****
+* Game Code
+****/
+// --- Game Constants ---
+var BOARD_COLS = 4;
+var PLAYER_Y = 2100;
+var OPPONENT_Y = 700;
+var HAND_Y = 2500;
+var SLOT_SPACING = 340;
+var HAND_SPACING = 320;
+var MAX_HAND = 5;
+var MAX_HEALTH = 10;
+// --- Card Pool ---
+var CARD_POOL = [{
+ id: 1,
+ name: "Stoat",
+ attack: 1,
+ health: 2,
+ cost: 1,
+ type: "creature"
+}, {
+ id: 2,
+ name: "Wolf",
+ attack: 3,
+ health: 2,
+ cost: 2,
+ type: "creature"
+}, {
+ id: 3,
+ name: "Bullfrog",
+ attack: 1,
+ health: 3,
+ cost: 1,
+ type: "creature"
+}, {
+ id: 4,
+ name: "Adder",
+ attack: 1,
+ health: 1,
+ cost: 2,
+ type: "creature"
+}, {
+ id: 5,
+ name: "Squirrel",
+ attack: 0,
+ health: 1,
+ cost: 0,
+ type: "resource"
+}];
+// --- Game State ---
+var playerDeck = [];
+var opponentDeck = [];
+var playerHand = [];
+var opponentHand = [];
+var playerSlots = [];
+var opponentSlots = [];
+var playerHealth = MAX_HEALTH;
+var opponentHealth = MAX_HEALTH;
+var turn = "player"; // "player" or "opponent"
+var dragCard = null;
+var dragOrigin = null;
+var validDropSlot = null;
+var canPlay = true;
+var playerResources = 0;
+var turnTxt, healthTxt, oppHealthTxt, resourceTxt, messageTxt;
+// --- UI Setup ---
+// Health display
+healthTxt = new Text2("You: " + playerHealth, {
+ size: 80,
+ fill: "#fff"
+});
+healthTxt.anchor.set(0, 0.5);
+LK.gui.top.addChild(healthTxt);
+oppHealthTxt = new Text2("Opponent: " + opponentHealth, {
+ size: 80,
+ fill: "#fff"
+});
+oppHealthTxt.anchor.set(1, 0.5);
+LK.gui.topRight.addChild(oppHealthTxt);
+// Turn display
+turnTxt = new Text2("Your Turn", {
+ size: 70,
+ fill: 0xFFEC70
+});
+turnTxt.anchor.set(0.5, 0.5);
+LK.gui.top.addChild(turnTxt);
+// Resource display
+resourceTxt = new Text2("Blood: " + playerResources, {
+ size: 60,
+ fill: 0xB8B031
+});
+resourceTxt.anchor.set(0.5, 0.5);
+LK.gui.bottom.addChild(resourceTxt);
+// Message display
+messageTxt = new Text2("", {
+ size: 60,
+ fill: 0xFFEC70
+});
+messageTxt.anchor.set(0.5, 0.5);
+LK.gui.center.addChild(messageTxt);
+// --- Board Setup ---
+// Player slots
+for (var i = 0; i < BOARD_COLS; i++) {
+ var slot = new Slot();
+ slot.isPlayerSlot = true;
+ slot.slotIndex = i;
+ slot.x = 400 + i * SLOT_SPACING;
+ slot.y = PLAYER_Y;
+ playerSlots.push(slot);
+ game.addChild(slot);
+}
+// Opponent slots
+for (var i = 0; i < BOARD_COLS; i++) {
+ var slot = new Slot();
+ slot.isPlayerSlot = false;
+ slot.slotIndex = i;
+ slot.x = 400 + i * SLOT_SPACING;
+ slot.y = OPPONENT_Y;
+ opponentSlots.push(slot);
+ game.addChild(slot);
+}
+// --- Deck/Hand Setup ---
+function shuffleDeck(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 createDeck() {
+ // Player: 2 Stoat, 2 Wolf, 2 Bullfrog, 1 Adder, 3 Squirrel
+ var deck = [];
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[0]);
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[1]);
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[2]);
+ deck.push(CARD_POOL[3]);
+ for (var i = 0; i < 3; i++) deck.push(CARD_POOL[4]);
+ shuffleDeck(deck);
+ return deck.slice();
+}
+function createOpponentDeck() {
+ // Opponent: 2 Wolf, 2 Bullfrog, 2 Adder, 2 Squirrel
+ var deck = [];
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[1]);
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[2]);
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[3]);
+ for (var i = 0; i < 2; i++) deck.push(CARD_POOL[4]);
+ shuffleDeck(deck);
+ return deck.slice();
+}
+// --- Hand Display ---
+function updateHandDisplay() {
+ // Remove all player hand cards from game
+ for (var i = 0; i < playerHand.length; i++) {
+ if (playerHand[i].parent) playerHand[i].parent.removeChild(playerHand[i]);
+ }
+ // Layout hand
+ for (var i = 0; i < playerHand.length; i++) {
+ var card = playerHand[i];
+ card.x = 400 + i * HAND_SPACING;
+ card.y = HAND_Y;
+ card.isDraggable = canPlay && turn === "player";
+ card.isPlayerCard = true;
+ game.addChild(card);
+ }
+}
+function updateOpponentHandDisplay() {
+ // Remove all opponent hand cards from game
+ for (var i = 0; i < opponentHand.length; i++) {
+ if (opponentHand[i].parent) opponentHand[i].parent.removeChild(opponentHand[i]);
+ }
+ // Layout hand (hidden)
+ for (var i = 0; i < opponentHand.length; i++) {
+ var card = opponentHand[i];
+ card.x = 400 + i * HAND_SPACING;
+ card.y = OPPONENT_Y - 250;
+ card.isDraggable = false;
+ card.isPlayerCard = false;
+ game.addChild(card);
+ }
+}
+// --- Draw Card ---
+function drawCard(deck, hand, isPlayer) {
+ if (deck.length === 0 || hand.length >= MAX_HAND) return;
+ var cardData = deck.shift();
+ var card = new Card();
+ card.setCard(cardData, isPlayer);
+ hand.push(card);
+}
+// --- Start Game ---
+function startGame() {
+ playerDeck = createDeck();
+ opponentDeck = createOpponentDeck();
+ playerHand = [];
+ opponentHand = [];
+ playerHealth = MAX_HEALTH;
+ opponentHealth = MAX_HEALTH;
+ playerResources = 0;
+ turn = "player";
+ canPlay = true;
+ messageTxt.setText("");
+ // Remove all cards from slots
+ for (var i = 0; i < BOARD_COLS; i++) {
+ if (playerSlots[i].card) {
+ playerSlots[i].card.destroy();
+ playerSlots[i].removeCard();
+ }
+ if (opponentSlots[i].card) {
+ opponentSlots[i].card.destroy();
+ opponentSlots[i].removeCard();
+ }
+ }
+ // Draw initial hands
+ for (var i = 0; i < 4; i++) drawCard(playerDeck, playerHand, true);
+ for (var i = 0; i < 4; i++) drawCard(opponentDeck, opponentHand, false);
+ updateHandDisplay();
+ updateOpponentHandDisplay();
+ updateUI();
+}
+function updateUI() {
+ healthTxt.setText("You: " + playerHealth);
+ oppHealthTxt.setText("Opponent: " + opponentHealth);
+ resourceTxt.setText("Blood: " + playerResources);
+ turnTxt.setText(turn === "player" ? "Your Turn" : "Opponent Turn");
+}
+// --- Turn Logic ---
+function startPlayerTurn() {
+ turn = "player";
+ canPlay = true;
+ playerResources += 1;
+ drawCard(playerDeck, playerHand, true);
+ updateHandDisplay();
+ updateUI();
+ messageTxt.setText("Your turn. Drag a card to a slot.");
+}
+function startOpponentTurn() {
+ turn = "opponent";
+ canPlay = false;
+ updateUI();
+ messageTxt.setText("Opponent's turn...");
+ LK.setTimeout(opponentPlay, 900);
+}
+// --- Play Card ---
+function canPlayCard(card, slot) {
+ if (!card || !slot) return false;
+ if (!slot.isPlayerSlot) return false;
+ if (slot.occupied) return false;
+ if (card.cardData.type === "resource") return true;
+ if (playerResources >= card.cardData.cost) return true;
+ return false;
+}
+function playCard(card, slot) {
+ if (!canPlayCard(card, slot)) return false;
+ // Remove from hand
+ var idx = playerHand.indexOf(card);
+ if (idx !== -1) playerHand.splice(idx, 1);
+ // Place in slot
+ slot.placeCard(card);
+ // Pay cost
+ if (card.cardData.type === "creature") {
+ playerResources -= card.cardData.cost;
+ }
+ // Squirrel: resource, gives +1 blood, then disappears
+ if (card.cardData.type === "resource") {
+ playerResources += 1;
+ card.flash(0xb8b031);
+ LK.setTimeout(function () {
+ slot.removeCard();
+ card.destroy();
+ }, 400);
+ }
+ updateHandDisplay();
+ updateUI();
+ return true;
+}
+// --- Drag & Drop ---
+game.move = function (x, y, obj) {
+ if (dragCard && dragCard.isDragging) {
+ dragCard.x = x;
+ dragCard.y = y;
+ // Highlight valid slot
+ var found = null;
+ for (var i = 0; i < playerSlots.length; i++) {
+ var slot = playerSlots[i];
+ if (!slot.occupied && slot.containsPoint({
+ x: x,
+ y: y
+ })) {
+ found = slot;
+ slot.setHighlight(true);
+ } else {
+ slot.setHighlight(false);
+ }
+ }
+ validDropSlot = found;
+ }
+};
+game.down = function (x, y, obj) {
+ // No-op: handled by Card.down
+};
+game.up = function (x, y, obj) {
+ if (dragCard && dragCard.isDragging) {
+ // Try to play card
+ if (validDropSlot && canPlayCard(dragCard, validDropSlot)) {
+ playCard(dragCard, validDropSlot);
+ dragCard.justPlayed = true;
+ validDropSlot.setHighlight(false);
+ } else {
+ // Snap back
+ dragCard.justPlayed = false;
+ }
+ dragCard.isDragging = false;
+ dragCard = null;
+ validDropSlot = null;
+ for (var i = 0; i < playerSlots.length; i++) playerSlots[i].setHighlight(false);
+ }
+};
+// --- Combat Phase ---
+function combatPhase() {
+ // Player creatures attack
+ for (var i = 0; i < BOARD_COLS; i++) {
+ var pSlot = playerSlots[i];
+ if (pSlot.card && pSlot.card.cardData.type === "creature") {
+ var oppSlot = opponentSlots[i];
+ if (oppSlot.card && oppSlot.card.cardData.type === "creature") {
+ // Attack opposing creature
+ oppSlot.card.cardData.health -= pSlot.card.cardData.attack;
+ pSlot.card.flash(0xffec70);
+ oppSlot.card.flash(0xd83318);
+ oppSlot.card.updateStats();
+ if (oppSlot.card.cardData.health <= 0) {
+ oppSlot.card.flash(0xd83318);
+ LK.setTimeout(function (slot, card) {
+ return function () {
+ slot.removeCard();
+ card.destroy();
+ };
+ }(oppSlot, oppSlot.card), 300);
+ }
+ } else {
+ // Attack opponent directly
+ opponentHealth -= pSlot.card.cardData.attack;
+ if (opponentHealth < 0) opponentHealth = 0;
+ }
+ }
+ }
+ // Opponent creatures attack
+ for (var i = 0; i < BOARD_COLS; i++) {
+ var oSlot = opponentSlots[i];
+ if (oSlot.card && oSlot.card.cardData.type === "creature") {
+ var pSlot = playerSlots[i];
+ if (pSlot.card && pSlot.card.cardData.type === "creature") {
+ // Attack opposing creature
+ pSlot.card.cardData.health -= oSlot.card.cardData.attack;
+ oSlot.card.flash(0xffec70);
+ pSlot.card.flash(0xd83318);
+ pSlot.card.updateStats();
+ if (pSlot.card.cardData.health <= 0) {
+ pSlot.card.flash(0xd83318);
+ LK.setTimeout(function (slot, card) {
+ return function () {
+ slot.removeCard();
+ card.destroy();
+ };
+ }(pSlot, pSlot.card), 300);
+ }
+ } else {
+ // Attack player directly
+ playerHealth -= oSlot.card.cardData.attack;
+ if (playerHealth < 0) playerHealth = 0;
+ }
+ }
+ }
+ updateUI();
+ // Check win/lose
+ if (playerHealth <= 0) {
+ LK.effects.flashScreen(0xd83318, 1000);
+ LK.showGameOver();
+ return;
+ }
+ if (opponentHealth <= 0) {
+ LK.effects.flashScreen(0x83de44, 1000);
+ LK.showYouWin();
+ return;
+ }
+ // Next turn
+ if (turn === "player") {
+ LK.setTimeout(startOpponentTurn, 900);
+ } else {
+ LK.setTimeout(startPlayerTurn, 900);
+ }
+}
+// --- Opponent AI ---
+function opponentPlay() {
+ // Play first playable creature to empty slot
+ var played = false;
+ for (var i = 0; i < opponentHand.length; i++) {
+ var card = opponentHand[i];
+ if (card.cardData.type === "creature") {
+ for (var j = 0; j < BOARD_COLS; j++) {
+ var slot = opponentSlots[j];
+ if (!slot.occupied) {
+ // Play card
+ opponentHand.splice(i, 1);
+ slot.placeCard(card);
+ played = true;
+ break;
+ }
+ }
+ if (played) break;
+ }
+ }
+ // Draw a card
+ drawCard(opponentDeck, opponentHand, false);
+ updateOpponentHandDisplay();
+ LK.setTimeout(combatPhase, 900);
+}
+// --- Game Update ---
+game.update = function () {
+ // No per-frame logic needed for MVP
+};
+// --- Start the game ---
+startGame();
\ No newline at end of file