User prompt
Update as needed with: var SCREEN_WIDTH = 2048; var SCREEN_HEIGHT = 2732; var PLAY_AREA_COLS = 5; var PLAY_AREA_ROWS = 2; var SLOT_WIDTH = 200; var SLOT_HEIGHT = 280; var DEAL_SLOT_WIDTH = 160; var DEAL_SLOT_HEIGHT = 220; // AI area positioning (top) var AI_AREA_X = (SCREEN_WIDTH - (PLAY_AREA_COLS * SLOT_WIDTH)) / 2; var AI_AREA_Y = 150; // Player area positioning (middle, with plenty of room below) var PLAYER_AREA_X = (SCREEN_WIDTH - (PLAY_AREA_COLS * SLOT_WIDTH)) / 2; var PLAYER_AREA_Y = SCREEN_HEIGHT - 1200; // Much higher up // Player deal area (hand slots) - below play area var PLAYER_DEAL_AREA_Y = PLAYER_AREA_Y + (PLAY_AREA_ROWS * SLOT_HEIGHT) + 40; // Deal button position - below hand slots with plenty of room var DEAL_BUTTON_Y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT + 60; /**** * Updated Path System with Rectangular Paths ****/ var PathSystem = { playerPath: [], aiPath: [], init: function() { // Create player path - rectangular loop around the play area var padding = 80; // Distance from play area var leftX = PLAYER_AREA_X - padding; var rightX = PLAYER_AREA_X + (PLAY_AREA_COLS * SLOT_WIDTH) + padding; var topY = PLAYER_AREA_Y - padding; var bottomY = PLAYER_AREA_Y + (PLAY_AREA_ROWS * SLOT_HEIGHT) + padding; this.playerPath = [ // Start at bottom left {x: leftX, y: bottomY}, // Go up the left side {x: leftX, y: topY}, // Go across the top {x: rightX, y: topY}, // Go down the right side {x: rightX, y: bottomY} ]; // Create AI path - rectangular loop around the AI play area var aiLeftX = AI_AREA_X - padding; var aiRightX = AI_AREA_X + (PLAY_AREA_COLS * SLOT_WIDTH) + padding; var aiTopY = AI_AREA_Y - padding; var aiBottomY = AI_AREA_Y + (PLAY_AREA_ROWS * SLOT_HEIGHT) + padding; this.aiPath = [ // Start at bottom left {x: aiLeftX, y: aiBottomY}, // Go up the left side {x: aiLeftX, y: aiTopY}, // Go across the top {x: aiRightX, y: aiTopY}, // Go down the right side {x: aiRightX, y: aiBottomY} ]; }, getPathStart: function(isPlayerSide) { return isPlayerSide ? this.playerPath[0] : this.aiPath[0]; }, getPositionAlongPath: function(progress, isPlayerSide) { var path = isPlayerSide ? this.playerPath : this.aiPath; var pathLength = this.calculatePathLength(path); var targetDistance = (progress / 100) * pathLength; if (targetDistance >= pathLength) { return {x: path[path.length - 1].x, y: path[path.length - 1].y, completed: true}; } var currentDistance = 0; for (var i = 0; i < path.length - 1; i++) { var segmentLength = this.getDistance(path[i], path[i + 1]); if (currentDistance + segmentLength >= targetDistance) { var segmentProgress = (targetDistance - currentDistance) / segmentLength; return { x: path[i].x + (path[i + 1].x - path[i].x) * segmentProgress, y: path[i].y + (path[i + 1].y - path[i].y) * segmentProgress, completed: false }; } currentDistance += segmentLength; } return {x: path[path.length - 1].x, y: path[path.length - 1].y, completed: true}; }, calculatePathLength: function(path) { var total = 0; for (var i = 0; i < path.length - 1; i++) { total += this.getDistance(path[i], path[i + 1]); } return total; }, getDistance: function(p1, p2) { var dx = p2.x - p1.x; var dy = p2.y - p1.y; return Math.sqrt(dx * dx + dy * dy); } }; /**** * Updated UI Elements Positioning ****/ var playerGoldText = new Text2('Gold: 100', { size: 50, fill: 0xffd700, weight: 800 }); playerGoldText.x = 50; playerGoldText.y = SCREEN_HEIGHT - 120; uiLayer.addChild(playerGoldText); var playerLivesText = new Text2('Lives: 3', { size: 50, fill: 0xff0000, weight: 800 }); playerLivesText.x = 50; playerLivesText.y = SCREEN_HEIGHT - 180; uiLayer.addChild(playerLivesText); // Add AI stats too for clarity var aiGoldText = new Text2('AI Gold: 100', { size: 40, fill: 0xffd700, weight: 800 }); aiGoldText.x = 50; aiGoldText.y = 50; uiLayer.addChild(aiGoldText); var aiLivesText = new Text2('AI Lives: 3', { size: 40, fill: 0xff0000, weight: 800 }); aiLivesText.x = 50; aiLivesText.y = 100; uiLayer.addChild(aiLivesText); var dealButton = new Container(); var dealButtonGraphics = dealButton.attachAsset('dealButton', { anchorX: 0.5, anchorY: 0.5 }); var dealButtonText = new Text2('Deal (50)', { size: 40, fill: 0xffffff, weight: 800 }); dealButtonText.anchor.set(0.5, 0.5); dealButton.addChild(dealButtonText); dealButton.x = SCREEN_WIDTH / 2; dealButton.y = DEAL_BUTTON_Y; uiLayer.addChild(dealButton); /**** * Update the updateUI function to include AI stats ****/ function updateUI() { playerGoldText.setText('Gold: ' + gameState.playerGold); playerLivesText.setText('Lives: ' + gameState.playerLives); aiGoldText.setText('AI Gold: ' + gameState.aiGold); aiLivesText.setText('AI Lives: ' + gameState.aiLives); dealButtonText.setText('Deal (' + gameState.dealCost + ')'); // Update button color based on affordability if (gameState.playerGold >= gameState.dealCost) { dealButtonGraphics.tint = 0x00aa00; } else { dealButtonGraphics.tint = 0x666666; } }
User prompt
Update as needed with: var SCREEN_WIDTH = 2048; var SCREEN_HEIGHT = 2732; var PLAY_AREA_COLS = 5; var PLAY_AREA_ROWS = 2; var SLOT_WIDTH = 200; var SLOT_HEIGHT = 280; var DEAL_SLOT_WIDTH = 160; var DEAL_SLOT_HEIGHT = 220; // AI area positioning (top) var AI_AREA_X = (SCREEN_WIDTH - (PLAY_AREA_COLS * SLOT_WIDTH)) / 2; var AI_AREA_Y = 100; // Moved up a bit // Player area positioning (middle-bottom, with room for hand below) var PLAYER_AREA_X = (SCREEN_WIDTH - (PLAY_AREA_COLS * SLOT_WIDTH)) / 2; var PLAYER_AREA_Y = SCREEN_HEIGHT - 800; // Much higher up to leave room // Player deal area (hand slots) - below play area var PLAYER_DEAL_AREA_Y = PLAYER_AREA_Y + (PLAY_AREA_ROWS * SLOT_HEIGHT) + 20; // 20px gap // Deal button position - below hand slots var DEAL_BUTTON_Y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT + 30; // 30px gap below hand ``` And update the UI elements positioning: ```javascript /**** * Updated UI Elements Positioning ****/ var playerGoldText = new Text2('Gold: 100', { size: 50, fill: 0xffd700, weight: 800 }); playerGoldText.x = 50; playerGoldText.y = SCREEN_HEIGHT - 80; // Moved up from bottom uiLayer.addChild(playerGoldText); var playerLivesText = new Text2('Lives: 3', { size: 50, fill: 0xff0000, weight: 800 }); playerLivesText.x = 50; playerLivesText.y = SCREEN_HEIGHT - 140; // Moved up from bottom uiLayer.addChild(playerLivesText); var dealButton = new Container(); var dealButtonGraphics = dealButton.attachAsset('dealButton', { anchorX: 0.5, anchorY: 0.5 }); var dealButtonText = new Text2('Deal (50)', { size: 40, fill: 0xffffff, weight: 800 }); dealButtonText.anchor.set(0.5, 0.5); dealButton.addChild(dealButtonText); dealButton.x = SCREEN_WIDTH / 2; dealButton.y = DEAL_BUTTON_Y; // Use the new constant uiLayer.addChild(dealButton); ``` And update the `drawPlayAreas` function to use the correct AI positioning: ```javascript function drawPlayAreas() { // Draw player play area slots for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { var slot = new Container(); var slotGraphics = slot.attachAsset('playSlot', { anchorX: 0.5, anchorY: 0.5 }); slotGraphics.alpha = 0.3; slot.x = PLAYER_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH/2; slot.y = PLAYER_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT/2; gameLayer.addChild(slot); } } // Draw AI play area slots for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { var slot = new Container(); var slotGraphics = slot.attachAsset('playSlot', { anchorX: 0.5, anchorY: 0.5 }); slotGraphics.alpha = 0.3; slotGraphics.tint = 0x440000; // Red tint for AI area slot.x = AI_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH/2; slot.y = AI_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT/2; gameLayer.addChild(slot); } } // Draw player deal area slots (hand) for (var i = 0; i < 5; i++) { var dealSlot = new Container(); var dealSlotGraphics = dealSlot.attachAsset('dealSlot', { anchorX: 0.5, anchorY: 0.5 }); dealSlotGraphics.alpha = 0.2; dealSlot.x = PLAYER_AREA_X + i * DEAL_SLOT_WIDTH + (i * 20) + DEAL_SLOT_WIDTH/2; dealSlot.y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT/2; gameLayer.addChild(dealSlot); } }
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 929
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'self.getSuitSymbol is not a function' in or related to this line: 'valueText.anchor.set(0, 0);' Line Number: 89
Code edit (2 edits merged)
Please save this source code
User prompt
Move the bottom build area left 1% and up 1%
User prompt
Move the bottom build area left 2% and up 2%
Code edit (2 edits merged)
Please save this source code
User prompt
Shrink the build area by 10% but leave the battlements exactly where they are.
Code edit (1 edits merged)
Please save this source code
User prompt
Size and place a battlement asset as the background for each build area.
User prompt
Size and place a battlement asset underneath each build area.
User prompt
Fix the wave incoming text so it’s not so dark and blurred out. Something is wrong with the outlining or something. Analyze.
User prompt
When a dice is dragged it should be moved to a layer above the other dice so it doesn’t appear underneath the other dice.
User prompt
Remove the magnetic effect for same dice
User prompt
As soon as I combine the first dice, new dice that spawn do not have visible numbers on them. Analyze and fix.
User prompt
Instead of using pips on the dice. Display their level as a number on the bottom center of each die.
User prompt
Decrease the gold increase for generating dice by 30%
User prompt
Compress the top and bottom lanes towards the center by 10% and adjust the building areas to match
User prompt
Compress the lanes in toward the center by 10% and move the building areas to match.
User prompt
All merged dice are becoming Warrior dice. They need to retain their class
User prompt
The merged dice still needs to be the same class as the combined dice and it needs to gain a level.
User prompt
When dice are combined, instead of spawning the new dice in another area, the new dice should be spawned in the cell where the dice where combined.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ /**** * Bullet Class ****/ var Bullet = Container.expand(function () { var self = Container.call(this); self.active = false; self.target = null; self.damage = 10; self.speed = 8; var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.activate = function (startX, startY, target, damage) { self.active = true; self.visible = true; self.x = startX; self.y = startY; self.target = target; self.damage = damage; }; self.update = function () { if (!self.active || !self.target || !self.target.active) { PoolManager.returnBullet(self); return; } var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.speed) { // Hit target self.target.takeDamage(self.damage); PoolManager.returnBullet(self); } else { var angle = Math.atan2(dy, dx); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } }; return self; }); /**** * Object Pool Manager ****/ /**** * Card Class ****/ var Card = Container.expand(function (cardData) { var self = Container.call(this); self.cardData = cardData; self.level = 1; // All cards start at level 1 self.isInPlay = false; self.playSlotX = 0; self.playSlotY = 0; self.lastFired = 0; self.fireRate = 60; // Base fire rate self.damage = 10; // Base damage self.range = 200; // Can hit anywhere on path self.handBonus = 1; // Multiplier from poker hand var cardGraphics = self.attachAsset('card', { anchorX: 0.5, anchorY: 0.5 }); // Define getSuitSymbol method before using it self.getSuitSymbol = function (suit) { switch (suit) { case 'hearts': return '♥'; case 'diamonds': return '♦'; case 'clubs': return '♣'; case 'spades': return '♠'; case 'joker': return '🃏'; default: return '?'; } }; // Card value in top left corner var valueText = new Text2(cardData.value, { size: 30, fill: CardSystem.suitColors[cardData.suit] || 0x000000, weight: 800 }); valueText.anchor.set(0, 0); valueText.x = -60; // Top left valueText.y = -85; self.addChild(valueText); // Large suit symbol in center var suitText = new Text2(self.getSuitSymbol(cardData.suit), { size: 80, fill: CardSystem.suitColors[cardData.suit] || 0x000000, weight: 800 }); suitText.anchor.set(0.5, 0.5); suitText.y = -10; // Slightly above center self.addChild(suitText); // Level text at bottom var levelText = new Text2('Lvl 1', { size: 25, fill: 0x000000, weight: 800 }); levelText.anchor.set(0.5, 1); levelText.y = 85; // Bottom of card self.addChild(levelText); self.activate = function (x, y, inPlay) { self.x = x; self.y = y; self.isInPlay = inPlay || false; self.visible = true; if (inPlay) { self.calculateStats(); } }; self.calculateStats = function () { // Stats based on level only, not card face value var baseDamage = 10; var baseFireRate = 60; // Level scaling self.damage = Math.floor(baseDamage * Math.pow(1.5, self.level - 1)); self.fireRate = Math.max(10, Math.floor(baseFireRate / Math.pow(1.2, self.level - 1))); // Apply poker hand bonus self.damage = Math.floor(self.damage * self.handBonus); self.fireRate = Math.max(5, Math.floor(self.fireRate / self.handBonus)); }; self.setLevel = function (newLevel) { self.level = newLevel; levelText.setText('Lvl ' + self.level); self.calculateStats(); // Visual feedback for higher levels if (self.level > 1) { var glowIntensity = Math.min(0.3, self.level * 0.05); cardGraphics.alpha = 1 + glowIntensity; } }; self.canMergeWith = function (otherCard) { if (!otherCard || otherCard === self) return false; // Must be same level AND (same suit OR same value) var sameLevel = self.level === otherCard.level; var sameSuit = self.cardData.suit === otherCard.cardData.suit; var sameValue = self.cardData.value === otherCard.cardData.value; return sameLevel && (sameSuit || sameValue); }; self.mergeWith = function (otherCard) { if (!self.canMergeWith(otherCard)) return null; var newCardData; var newLevel = self.level + 1; // Increase level by 1 if (self.cardData.suit === otherCard.cardData.suit) { // Same suit: random value, keep suit var randomValue = CardSystem.values[Math.floor(Math.random() * CardSystem.values.length)]; newCardData = { suit: self.cardData.suit, value: randomValue, id: self.cardData.suit + '_' + randomValue }; } else { // Same value: increase value by 1, random suit var currentValueIndex = CardSystem.values.indexOf(self.cardData.value); var nextValueIndex = (currentValueIndex + 1) % CardSystem.values.length; var randomSuit = CardSystem.suits[Math.floor(Math.random() * CardSystem.suits.length)]; newCardData = { suit: randomSuit, value: CardSystem.values[nextValueIndex], id: randomSuit + '_' + CardSystem.values[nextValueIndex] }; } var mergedCard = new Card(newCardData); mergedCard.setLevel(newLevel); return mergedCard; }; self.findTarget = function () { var targets = gameState.isPlayerTurn ? activeAIChips : activePlayerChips; for (var i = 0; i < targets.length; i++) { if (targets[i].active) { return targets[i]; // For now, just target first available } } return null; }; self.fire = function () { var target = self.findTarget(); if (!target) return; var bullet = PoolManager.getBullet(); if (bullet) { bullet.activate(self.x, self.y, target, self.damage); gameLayer.addChild(bullet); activeBullets.push(bullet); self.lastFired = LK.ticks; // Visual feedback for firing tween.stop(self, { scaleX: true, scaleY: true }); tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.quadOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.elasticOut }); } }); } }; self.update = function () { if (!self.isInPlay) return; if (LK.ticks - self.lastFired >= self.fireRate) { self.fire(); } }; // Initialize with level 1 self.setLevel(1); return self; }); /**** * Poker Chip Enemy Class ****/ var PokerChip = Container.expand(function () { var self = Container.call(this); self.active = false; self.health = 10; self.maxHealth = 10; self.value = 1; // Chip value (1, 5, 10, 25, 100) self.speed = 2; self.pathProgress = 0; self.isPlayerSide = true; // true for player side, false for AI side var chipGraphics = self.attachAsset('pokerChip', { anchorX: 0.5, anchorY: 0.5 }); var valueText = new Text2('1', { size: 30, fill: 0xffffff, weight: 800 }); valueText.anchor.set(0.5, 0.5); self.addChild(valueText); self.activate = function (value, isPlayerSide) { self.active = true; self.visible = true; self.value = value; self.isPlayerSide = isPlayerSide; self.health = self.maxHealth = value; self.pathProgress = 0; // Set chip color based on value self.setChipAppearance(); // Position at start of path var startPos = PathSystem.getPathStart(isPlayerSide); self.x = startPos.x; self.y = startPos.y; }; self.setChipAppearance = function () { var colors = { 1: 0xffffff, // White 5: 0xff0000, // Red 10: 0x00ff00, // Green 25: 0x000000, // Black 100: 0x800080 // Purple }; chipGraphics.tint = colors[self.value] || 0xffffff; valueText.setText(self.value.toString()); }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.die(); } }; self.die = function () { // Award money based on chip value var goldEarned = self.value; if (self.isPlayerSide) { gameState.playerGold += goldEarned; } else { gameState.aiGold += goldEarned; } // Spawn new chips on opposite side self.spawnCounterChips(); PoolManager.returnChip(self); }; self.spawnCounterChips = function () { // When player defeats AI chip, spawn chips on AI side // When AI defeats player chip, spawn chips on player side var targetSide = !self.isPlayerSide; var spawnCount = Math.max(1, Math.floor(self.value / 5)); for (var i = 0; i < spawnCount; i++) { setTimeout(function () { ChipSpawner.spawnChip(1, targetSide); // Spawn basic chips }, i * 500); } }; self.update = function () { if (!self.active) { return; } self.pathProgress += self.speed; var pathPos = PathSystem.getPositionAlongPath(self.pathProgress, self.isPlayerSide); if (pathPos.completed) { // Chip reached the end if (self.isPlayerSide) { gameState.playerLives--; } else { gameState.aiLives--; } PoolManager.returnChip(self); return; } self.x = pathPos.x; self.y = pathPos.y; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0f3d0f }); /**** * Game Code ****/ /**** * Poker Tower Defense - Complete Refactor ****/ /**** * Game Constants ****/ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) { throw o; } } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } var SCREEN_WIDTH = 2048; var SCREEN_HEIGHT = 2732; var PLAY_AREA_COLS = 5; var PLAY_AREA_ROWS = 2; var SLOT_WIDTH = 200; var SLOT_HEIGHT = 280; var DEAL_SLOT_WIDTH = 160; var DEAL_SLOT_HEIGHT = 220; // Player area positioning (bottom) var PLAYER_AREA_X = (SCREEN_WIDTH - PLAY_AREA_COLS * SLOT_WIDTH) / 2; var PLAYER_AREA_Y = SCREEN_HEIGHT - 400; var PLAYER_DEAL_AREA_Y = PLAYER_AREA_Y + PLAY_AREA_ROWS * SLOT_HEIGHT + 40; // AI area positioning (top) - mirrored var AI_AREA_X = PLAYER_AREA_X; var AI_AREA_Y = 200; /**** * Card System ****/ var CardSystem = { suits: ['hearts', 'diamonds', 'clubs', 'spades'], values: ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'], suitColors: { 'hearts': 0xff0000, 'diamonds': 0xff0000, 'clubs': 0x000000, 'spades': 0x000000 }, createDeck: function createDeck() { var deck = []; var _iterator = _createForOfIteratorHelper(this.suits), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var suit = _step.value; var _iterator2 = _createForOfIteratorHelper(this.values), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var value = _step2.value; deck.push({ suit: suit, value: value, id: suit + '_' + value }); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } // Add jokers } catch (err) { _iterator.e(err); } finally { _iterator.f(); } deck.push({ suit: 'joker', value: 'red', id: 'joker_red' }); deck.push({ suit: 'joker', value: 'black', id: 'joker_black' }); return this.shuffleDeck(deck); }, shuffleDeck: 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; } return deck; }, getCardValue: function getCardValue(card) { if (card.suit === 'joker') { return 14; } // Jokers are highest if (card.value === 'A') { return 14; } // Aces high if (card.value === 'K') { return 13; } if (card.value === 'Q') { return 12; } if (card.value === 'J') { return 11; } return parseInt(card.value); }, evaluatePokerHand: function evaluatePokerHand(cards) { var _this = this; if (!cards || cards.length !== 5) { return { type: 'none', strength: 0 }; } // Sort cards by value for easier analysis var sortedCards = cards.slice().sort(function (a, b) { return _this.getCardValue(b) - _this.getCardValue(a); }); var values = sortedCards.map(function (card) { return _this.getCardValue(card); }); var suits = sortedCards.map(function (card) { return card.suit; }); // Count values and suits var valueCounts = {}; var suitCounts = {}; values.forEach(function (value) { return valueCounts[value] = (valueCounts[value] || 0) + 1; }); suits.forEach(function (suit) { return suitCounts[suit] = (suitCounts[suit] || 0) + 1; }); var counts = Object.values(valueCounts).sort(function (a, b) { return b - a; }); var isFlush = Object.keys(suitCounts).length === 1; var isStraight = this.checkStraight(values); // Royal Flush if (isFlush && isStraight && values[0] === 14 && values[4] === 10) { return { type: 'royal_flush', strength: 10, multiplier: 50 }; } // Straight Flush if (isFlush && isStraight) { return { type: 'straight_flush', strength: 9, multiplier: 25 }; } // Four of a Kind if (counts[0] === 4) { return { type: 'four_of_a_kind', strength: 8, multiplier: 15 }; } // Full House if (counts[0] === 3 && counts[1] === 2) { return { type: 'full_house', strength: 7, multiplier: 8 }; } // Flush if (isFlush) { return { type: 'flush', strength: 6, multiplier: 5 }; } // Straight if (isStraight) { return { type: 'straight', strength: 5, multiplier: 4 }; } // Three of a Kind if (counts[0] === 3) { return { type: 'three_of_a_kind', strength: 4, multiplier: 3 }; } // Two Pair if (counts[0] === 2 && counts[1] === 2) { return { type: 'two_pair', strength: 3, multiplier: 2.5 }; } // One Pair if (counts[0] === 2) { return { type: 'one_pair', strength: 2, multiplier: 1.5 }; } // High Card return { type: 'high_card', strength: 1, multiplier: 1 }; }, checkStraight: function checkStraight(values) { if (values.length !== 5) { return false; } // Check for ace-low straight (A, 2, 3, 4, 5) if (values[0] === 14 && values[1] === 5 && values[2] === 4 && values[3] === 3 && values[4] === 2) { return true; } // Check normal straight for (var i = 0; i < 4; i++) { if (values[i] - values[i + 1] !== 1) { return false; } } return true; } }; /**** * Object Pool Manager ****/ var PoolManager = { chipPool: [], bulletPool: [], cardPool: [], CHIP_POOL_SIZE: 50, BULLET_POOL_SIZE: 100, CARD_POOL_SIZE: 60, init: function init() { // Initialize pools for (var i = 0; i < this.CHIP_POOL_SIZE; i++) { var chip = new PokerChip(); chip.active = false; chip.visible = false; this.chipPool.push(chip); } for (var i = 0; i < this.BULLET_POOL_SIZE; i++) { var bullet = new Bullet(); bullet.active = false; bullet.visible = false; this.bulletPool.push(bullet); } }, getChip: function getChip() { for (var i = 0; i < this.chipPool.length; i++) { if (!this.chipPool[i].active) { return this.chipPool[i]; } } return null; }, getBullet: function getBullet() { for (var i = 0; i < this.bulletPool.length; i++) { if (!this.bulletPool[i].active) { return this.bulletPool[i]; } } return null; }, returnChip: function returnChip(chip) { chip.active = false; chip.visible = false; // Remove from active arrays var playerIndex = activePlayerChips.indexOf(chip); if (playerIndex !== -1) { activePlayerChips.splice(playerIndex, 1); } var aiIndex = activeAIChips.indexOf(chip); if (aiIndex !== -1) { activeAIChips.splice(aiIndex, 1); } gameLayer.removeChild(chip); }, returnBullet: function returnBullet(bullet) { bullet.active = false; bullet.visible = false; var index = activeBullets.indexOf(bullet); if (index !== -1) { activeBullets.splice(index, 1); } gameLayer.removeChild(bullet); } }; /**** * Path System ****/ var PathSystem = { playerPath: [], aiPath: [], init: function init() { // Create player path (bottom area) var playerStartX = PLAYER_AREA_X - 100; var playerStartY = PLAYER_AREA_Y + SLOT_HEIGHT; var playerEndX = PLAYER_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH + 100; var playerEndY = playerStartY; this.playerPath = [{ x: playerStartX, y: playerStartY }, { x: playerStartX + 50, y: playerStartY - 100 }, { x: playerEndX - 50, y: playerStartY - 100 }, { x: playerEndX, y: playerStartY }]; // Create AI path (top area) - mirrored var aiStartX = AI_AREA_X - 100; var aiStartY = AI_AREA_Y + SLOT_HEIGHT; var aiEndX = AI_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH + 100; var aiEndY = aiStartY; this.aiPath = [{ x: aiStartX, y: aiStartY }, { x: aiStartX + 50, y: aiStartY - 100 }, { x: aiEndX - 50, y: aiStartY - 100 }, { x: aiEndX, y: aiEndY }]; }, getPathStart: function getPathStart(isPlayerSide) { return isPlayerSide ? this.playerPath[0] : this.aiPath[0]; }, getPositionAlongPath: function getPositionAlongPath(progress, isPlayerSide) { var path = isPlayerSide ? this.playerPath : this.aiPath; var pathLength = this.calculatePathLength(path); var targetDistance = progress / 100 * pathLength; if (targetDistance >= pathLength) { return { x: path[path.length - 1].x, y: path[path.length - 1].y, completed: true }; } var currentDistance = 0; for (var i = 0; i < path.length - 1; i++) { var segmentLength = this.getDistance(path[i], path[i + 1]); if (currentDistance + segmentLength >= targetDistance) { var segmentProgress = (targetDistance - currentDistance) / segmentLength; return { x: path[i].x + (path[i + 1].x - path[i].x) * segmentProgress, y: path[i].y + (path[i + 1].y - path[i].y) * segmentProgress, completed: false }; } currentDistance += segmentLength; } return { x: path[path.length - 1].x, y: path[path.length - 1].y, completed: true }; }, calculatePathLength: function calculatePathLength(path) { var total = 0; for (var i = 0; i < path.length - 1; i++) { total += this.getDistance(path[i], path[i + 1]); } return total; }, getDistance: function getDistance(p1, p2) { var dx = p2.x - p1.x; var dy = p2.y - p1.y; return Math.sqrt(dx * dx + dy * dy); } }; /**** * Chip Spawner ****/ var ChipSpawner = { spawnChip: function spawnChip(value, isPlayerSide) { var chip = PoolManager.getChip(); if (!chip) { return; } chip.activate(value, isPlayerSide); gameLayer.addChild(chip); if (isPlayerSide) { activePlayerChips.push(chip); } else { activeAIChips.push(chip); } } }; /**** * Game State ****/ var gameState = { playerGold: 100, aiGold: 100, playerLives: 3, aiLives: 3, isPlayerTurn: true, dealCost: 50, dealCount: 0, playerDeck: [], playerHand: [], playerPlayArea: [], // 2D array [row][col] aiDeck: [], aiPlayArea: [] }; /**** * Game Variables ****/ var activePlayerChips = []; var activeAIChips = []; var activeBullets = []; var selectedCard = null; var isDragging = false; var gameLayer = new Container(); var uiLayer = new Container(); game.addChild(gameLayer); game.addChild(uiLayer); /**** * UI Elements ****/ var playerGoldText = new Text2('Gold: 100', { size: 50, fill: 0xffd700, weight: 800 }); playerGoldText.x = 50; playerGoldText.y = SCREEN_HEIGHT - 100; uiLayer.addChild(playerGoldText); var playerLivesText = new Text2('Lives: 3', { size: 50, fill: 0xff0000, weight: 800 }); playerLivesText.x = 50; playerLivesText.y = SCREEN_HEIGHT - 150; uiLayer.addChild(playerLivesText); var dealButton = new Container(); var dealButtonGraphics = dealButton.attachAsset('dealButton', { anchorX: 0.5, anchorY: 0.5 }); var dealButtonText = new Text2('Deal (50)', { size: 40, fill: 0xffffff, weight: 800 }); dealButtonText.anchor.set(0.5, 0.5); dealButton.addChild(dealButtonText); dealButton.x = SCREEN_WIDTH / 2; dealButton.y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT + 50; uiLayer.addChild(dealButton); dealButton.down = function () { if (gameState.playerGold >= gameState.dealCost) { dealNewHand(); } }; /**** * Game Functions ****/ function initializeGame() { PoolManager.init(); PathSystem.init(); // Initialize play areas gameState.playerPlayArea = []; gameState.aiPlayArea = []; for (var row = 0; row < PLAY_AREA_ROWS; row++) { gameState.playerPlayArea[row] = []; gameState.aiPlayArea[row] = []; for (var col = 0; col < PLAY_AREA_COLS; col++) { gameState.playerPlayArea[row][col] = null; gameState.aiPlayArea[row][col] = null; } } // Create initial decks gameState.playerDeck = CardSystem.createDeck(); gameState.aiDeck = CardSystem.createDeck(); // Draw grid lines drawPlayAreas(); drawPaths(); // Deal initial hand dealNewHand(); // Start spawning chips setTimeout(function () { ChipSpawner.spawnChip(5, false); // Spawn on AI side }, 2000); } function dealNewHand() { if (gameState.playerGold < gameState.dealCost) { return; } gameState.playerGold -= gameState.dealCost; gameState.dealCount++; gameState.dealCost = Math.floor(50 * Math.pow(1.2, gameState.dealCount)); // Clear current hand gameState.playerHand.forEach(function (card) { if (card) { uiLayer.removeChild(card); } }); gameState.playerHand = []; // Deal 5 new cards for (var i = 0; i < 5; i++) { if (gameState.playerDeck.length === 0) { gameState.playerDeck = CardSystem.createDeck(); } var cardData = gameState.playerDeck.pop(); var card = new Card(cardData); var slotX = PLAYER_AREA_X + i * DEAL_SLOT_WIDTH + i * 20 + DEAL_SLOT_WIDTH / 2; var slotY = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2; card.activate(slotX, slotY, false); uiLayer.addChild(card); gameState.playerHand[i] = card; } updateUI(); } function updateUI() { playerGoldText.setText('Gold: ' + gameState.playerGold); playerLivesText.setText('Lives: ' + gameState.playerLives); dealButtonText.setText('Deal (' + gameState.dealCost + ')'); // Update button color based on affordability if (gameState.playerGold >= gameState.dealCost) { dealButtonGraphics.tint = 0x00aa00; } else { dealButtonGraphics.tint = 0x666666; } } function drawPlayAreas() { // Draw player play area slots for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { var slot = new Container(); var slotGraphics = slot.attachAsset('playSlot', { anchorX: 0.5, anchorY: 0.5 }); slotGraphics.alpha = 0.3; slot.x = PLAYER_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH / 2; slot.y = PLAYER_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT / 2; gameLayer.addChild(slot); } } // Draw AI play area slots for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { var slot = new Container(); var slotGraphics = slot.attachAsset('playSlot', { anchorX: 0.5, anchorY: 0.5 }); slotGraphics.alpha = 0.3; slotGraphics.tint = 0x440000; // Red tint for AI area slot.x = AI_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH / 2; slot.y = AI_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT / 2; gameLayer.addChild(slot); } } // Draw player deal area slots for (var i = 0; i < 5; i++) { var dealSlot = new Container(); var dealSlotGraphics = dealSlot.attachAsset('dealSlot', { anchorX: 0.5, anchorY: 0.5 }); dealSlotGraphics.alpha = 0.2; dealSlot.x = PLAYER_AREA_X + i * DEAL_SLOT_WIDTH + i * 20 + DEAL_SLOT_WIDTH / 2; dealSlot.y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2; gameLayer.addChild(dealSlot); } } function drawPaths() { // Draw player path for (var i = 0; i < PathSystem.playerPath.length - 1; i++) { var start = PathSystem.playerPath[i]; var end = PathSystem.playerPath[i + 1]; drawPathSegment(start, end, 0x666666); } // Draw AI path for (var i = 0; i < PathSystem.aiPath.length - 1; i++) { var start = PathSystem.aiPath[i]; var end = PathSystem.aiPath[i + 1]; drawPathSegment(start, end, 0x664444); } } function drawPathSegment(start, end, color) { var dx = end.x - start.x; var dy = end.y - start.y; var distance = Math.sqrt(dx * dx + dy * dy); var segments = Math.floor(distance / 20); for (var i = 0; i <= segments; i++) { var progress = i / segments; var x = start.x + dx * progress; var y = start.y + dy * progress; var pathDot = new Container(); var dotGraphics = pathDot.attachAsset('pathSegment', { anchorX: 0.5, anchorY: 0.5 }); dotGraphics.width = dotGraphics.height = 8; dotGraphics.tint = color; dotGraphics.alpha = 0.6; pathDot.x = x; pathDot.y = y; gameLayer.addChild(pathDot); } } function getSlotPosition(row, col, isPlayerArea) { var baseX = isPlayerArea ? PLAYER_AREA_X : AI_AREA_X; var baseY = isPlayerArea ? PLAYER_AREA_Y : AI_AREA_Y; return { x: baseX + col * SLOT_WIDTH + SLOT_WIDTH / 2, y: baseY + row * SLOT_HEIGHT + SLOT_HEIGHT / 2 }; } function getSlotFromPosition(x, y) { // Check player play area if (x >= PLAYER_AREA_X && x <= PLAYER_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH && y >= PLAYER_AREA_Y && y <= PLAYER_AREA_Y + PLAY_AREA_ROWS * SLOT_HEIGHT) { var col = Math.floor((x - PLAYER_AREA_X) / SLOT_WIDTH); var row = Math.floor((y - PLAYER_AREA_Y) / SLOT_HEIGHT); if (col >= 0 && col < PLAY_AREA_COLS && row >= 0 && row < PLAY_AREA_ROWS) { return { area: 'player', row: row, col: col }; } } return null; } function evaluateRowHand(row, isPlayerArea) { var playArea = isPlayerArea ? gameState.playerPlayArea : gameState.aiPlayArea; var cards = []; for (var col = 0; col < PLAY_AREA_COLS; col++) { if (playArea[row][col]) { cards.push(playArea[row][col].cardData); } } if (cards.length === 5) { return CardSystem.evaluatePokerHand(cards); } return { type: 'none', strength: 0, multiplier: 1 }; } function applyHandBonuses() { // Apply bonuses to player cards for (var row = 0; row < PLAY_AREA_ROWS; row++) { var handEval = evaluateRowHand(row, true); for (var col = 0; col < PLAY_AREA_COLS; col++) { var card = gameState.playerPlayArea[row][col]; if (card) { card.handBonus = handEval.multiplier; card.calculateStats(); } } } // Apply bonuses to AI cards for (var row = 0; row < PLAY_AREA_ROWS; row++) { var handEval = evaluateRowHand(row, false); for (var col = 0; col < PLAY_AREA_COLS; col++) { var card = gameState.aiPlayArea[row][col]; if (card) { card.handBonus = handEval.multiplier; card.calculateStats(); } } } } /**** * AI System ****/ var AISystem = { thinkTimer: 0, thinkDelay: 120, // 2 seconds update: function update() { if (gameState.isPlayerTurn) { return; } this.thinkTimer++; if (this.thinkTimer >= this.thinkDelay) { this.thinkTimer = 0; this.makeMove(); } }, makeMove: function makeMove() { // Simple AI: deal new hand if can afford it if (gameState.aiGold >= gameState.dealCost) { this.dealAIHand(); } // Try to place cards from AI hand to play area this.tryPlaceCards(); // Spawn some chips on player side if (Math.random() < 0.3) { ChipSpawner.spawnChip(Math.floor(Math.random() * 3) + 1, true); } gameState.isPlayerTurn = true; }, dealAIHand: function dealAIHand() { gameState.aiGold -= gameState.dealCost; // Deal cards directly to AI play area for (var attempt = 0; attempt < 5; attempt++) { if (gameState.aiDeck.length === 0) { gameState.aiDeck = CardSystem.createDeck(); } var cardData = gameState.aiDeck.pop(); var card = new Card(cardData); // Find empty slot var placed = false; for (var row = 0; row < PLAY_AREA_ROWS && !placed; row++) { for (var col = 0; col < PLAY_AREA_COLS && !placed; col++) { if (!gameState.aiPlayArea[row][col]) { var pos = getSlotPosition(row, col, false); card.activate(pos.x, pos.y, true); gameLayer.addChild(card); gameState.aiPlayArea[row][col] = card; placed = true; } } } if (!placed) { break; } // No more space } }, tryPlaceCards: function tryPlaceCards() { // AI logic for placing cards (simplified) // In a full implementation, this would be more sophisticated } }; /**** * Input Handling ****/ game.down = function (x, y, obj) { // Check if clicking on a card in hand for (var i = 0; i < gameState.playerHand.length; i++) { var card = gameState.playerHand[i]; if (card && Math.abs(x - card.x) < DEAL_SLOT_WIDTH / 2 && Math.abs(y - card.y) < DEAL_SLOT_HEIGHT / 2) { selectedCard = card; isDragging = true; return; } } // Check if clicking on a card in play area for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { var card = gameState.playerPlayArea[row][col]; if (card && Math.abs(x - card.x) < SLOT_WIDTH / 2 && Math.abs(y - card.y) < SLOT_HEIGHT / 2) { selectedCard = card; isDragging = true; // Remove from current position gameState.playerPlayArea[row][col] = null; return; } } } }; game.move = function (x, y, obj) { if (isDragging && selectedCard) { selectedCard.x = x; selectedCard.y = y; } }; game.up = function (x, y, obj) { if (isDragging && selectedCard) { isDragging = false; var targetSlot = getSlotFromPosition(x, y); if (targetSlot && targetSlot.area === 'player') { var existingCard = gameState.playerPlayArea[targetSlot.row][targetSlot.col]; if (existingCard && selectedCard.canMergeWith(existingCard)) { // Merge cards var mergedCard = selectedCard.mergeWith(existingCard); if (mergedCard) { // Remove old cards gameLayer.removeChild(existingCard); var handIndex = gameState.playerHand.indexOf(selectedCard); if (handIndex !== -1) { uiLayer.removeChild(selectedCard); gameState.playerHand[handIndex] = null; } // Place merged card var pos = getSlotPosition(targetSlot.row, targetSlot.col, true); mergedCard.activate(pos.x, pos.y, true); gameLayer.addChild(mergedCard); gameState.playerPlayArea[targetSlot.row][targetSlot.col] = mergedCard; } } else if (!existingCard) { // Place card in empty slot var pos = getSlotPosition(targetSlot.row, targetSlot.col, true); selectedCard.activate(pos.x, pos.y, true); // Remove from hand if it was in hand var handIndex = gameState.playerHand.indexOf(selectedCard); if (handIndex !== -1) { uiLayer.removeChild(selectedCard); gameLayer.addChild(selectedCard); gameState.playerHand[handIndex] = null; } gameState.playerPlayArea[targetSlot.row][targetSlot.col] = selectedCard; } else { // Return to original position returnCardToOriginalPosition(); } } else { // Return to original position returnCardToOriginalPosition(); } selectedCard = null; applyHandBonuses(); } }; function returnCardToOriginalPosition() { var handIndex = gameState.playerHand.indexOf(selectedCard); if (handIndex !== -1) { // Return to hand var slotX = PLAYER_AREA_X + handIndex * DEAL_SLOT_WIDTH + handIndex * 20 + DEAL_SLOT_WIDTH / 2; var slotY = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2; selectedCard.x = slotX; selectedCard.y = slotY; } } /**** * Main Game Loop ****/ game.update = function () { // Update active chips for (var i = activePlayerChips.length - 1; i >= 0; i--) { activePlayerChips[i].update(); } for (var i = activeAIChips.length - 1; i >= 0; i--) { activeAIChips[i].update(); } // Update active bullets for (var i = activeBullets.length - 1; i >= 0; i--) { activeBullets[i].update(); } // Update cards in play for (var row = 0; row < PLAY_AREA_ROWS; row++) { for (var col = 0; col < PLAY_AREA_COLS; col++) { if (gameState.playerPlayArea[row][col]) { gameState.playerPlayArea[row][col].update(); } if (gameState.aiPlayArea[row][col]) { gameState.aiPlayArea[row][col].update(); } } } // Update AI AISystem.update(); // Check win/lose conditions if (gameState.playerLives <= 0) { showGameOver(false); } else if (gameState.aiLives <= 0) { showGameOver(true); } updateUI(); }; /**** * Game Over ****/ function showGameOver(playerWon) { var overlay = new Container(); var bg = overlay.attachAsset('playSlot', { anchorX: 0.5, anchorY: 0.5 }); bg.width = SCREEN_WIDTH; bg.height = SCREEN_HEIGHT; bg.tint = 0x000000; bg.alpha = 0.8; var resultText = new Text2(playerWon ? 'YOU WIN!' : 'YOU LOSE!', { size: 100, fill: playerWon ? 0x00ff00 : 0xff0000, weight: 800 }); resultText.anchor.set(0.5, 0.5); overlay.addChild(resultText); var restartText = new Text2('Tap to Restart', { size: 60, fill: 0xffffff, weight: 600 }); restartText.anchor.set(0.5, 0.5); restartText.y = 100; overlay.addChild(restartText); overlay.x = SCREEN_WIDTH / 2; overlay.y = SCREEN_HEIGHT / 2; game.addChild(overlay); overlay.down = function () { location.reload(); }; } /**** * Utility Functions ****/ function displayHandInfo() { // Show current poker hand evaluations for debugging for (var row = 0; row < PLAY_AREA_ROWS; row++) { var handEval = evaluateRowHand(row, true); console.log('Player Row ' + row + ':', handEval.type, 'Multiplier:', handEval.multiplier); } } initializeGame();
===================================================================
--- original.js
+++ change.js
@@ -5,1184 +5,672 @@
/****
* Classes
****/
-var BlobEnemy = Container.expand(function () {
- var self = Container.call(this);
- self.active = false;
- self.material = 'slime';
- self.health = 40;
- self.maxHealth = 40;
- self.speed = 1.2;
- self.pathProgress = 0;
- self.pathIndex = 0;
- self.waveNumber = 1;
- // Jump states
- self.jumpState = 'paused';
- self.jumpTimer = 0;
- self.pauseDuration = 30;
- self.jumpDuration = 30;
- self.startPosition = {
- x: 0,
- y: 0
- };
- self.targetPosition = {
- x: 0,
- y: 0
- };
- self.jumpDistance = 80;
- self.jumpHeight = 40;
- self.baseY = 0;
- // Status effects
- self.slowed = false;
- self.poisoned = false;
- self.slowDuration = 0;
- self.poisonDuration = 0;
- self.poisonDamage = 0;
- self.originalSpeed = self.speed;
- var blobGraphics = self.attachAsset('blob', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- var healthBarOutline = self.attachAsset('healthBarOutline', {
- anchorX: 0,
- anchorY: 0.5
- });
- var healthBar = self.attachAsset('healthBar', {
- anchorX: 0,
- anchorY: 0.5
- });
- // Position health bars
- healthBarOutline.y = healthBar.y = -30;
- healthBarOutline.x = -36;
- healthBar.x = -35;
- healthBar.tint = 0x00ff00;
- self.activate = function (material, waveNumber, pathIndex) {
- self.active = true;
- self.visible = true;
- self.material = material || 'slime';
- self.waveNumber = waveNumber || 1;
- self.pathIndex = pathIndex || 0;
- self.pathProgress = 0;
- self.jumpState = 'paused';
- self.jumpTimer = self.pauseDuration;
- // Reset status effects
- self.slowed = false;
- self.poisoned = false;
- self.slowDuration = 0;
- self.poisonDuration = 0;
- // Set material properties
- self.setMaterial(self.material);
- // Scale health with wave number
- var healthMultiplier = Math.pow(1.15, self.waveNumber);
- self.maxHealth = Math.round(self.maxHealth * healthMultiplier);
- self.health = self.maxHealth;
- // Start at beginning of path
- var startPos = PathSystem.getPositionAlongPath(0, self.pathIndex);
- self.x = startPos.x;
- self.y = startPos.y;
- self.baseY = self.y;
- // Reset blob scale
- blobGraphics.scaleX = 1;
- blobGraphics.scaleY = 1;
- };
- self.setMaterial = function (material) {
- switch (material) {
- case 'slime':
- blobGraphics.tint = 0x00FF00;
- self.speed = 0.8;
- self.pauseDuration = 30;
- self.jumpDistance = 80;
- self.jumpHeight = 40;
- self.maxHealth = 40;
- break;
- case 'metal':
- blobGraphics.tint = 0xC0C0C0;
- self.speed = 0.6;
- self.pauseDuration = 40;
- self.jumpDistance = 60;
- self.jumpHeight = 25;
- self.maxHealth = 60;
- break;
- case 'lava':
- blobGraphics.tint = 0xFF4500;
- self.speed = 1.0;
- self.pauseDuration = 22;
- self.jumpDistance = 90;
- self.jumpHeight = 50;
- self.maxHealth = 48;
- break;
- case 'ice':
- blobGraphics.tint = 0x87CEEB;
- self.speed = 0.5;
- self.pauseDuration = 45;
- self.jumpDistance = 50;
- self.jumpHeight = 30;
- self.maxHealth = 32;
- break;
- case 'shadow':
- blobGraphics.tint = 0x4B0082;
- self.speed = 1.2;
- self.pauseDuration = 15;
- self.jumpDistance = 100;
- self.jumpHeight = 60;
- self.maxHealth = 80;
- break;
- }
- self.originalSpeed = self.speed;
- };
- self.takeDamage = function (damage, damageType, towerLevel) {
- self.health -= damage;
- healthBar.width = Math.max(0, self.health / self.maxHealth * 70);
- // Apply special effects
- if (damageType === 'splash') {
- var effect = PoolManager.getEffect();
- if (effect) {
- effect.activate(self.x, self.y, 'splash');
- gameLayer.addChild(effect);
- }
- } else if (damageType === 'slow' && self.material !== 'ice') {
- // Ice is immune to slow
- if (!self.slowed) {
- var slowPct = 0.5 + (towerLevel - 1) * 0.05; // 50% to 75% slow
- self.speed = self.originalSpeed * (1 - slowPct);
- self.slowed = true;
- self.slowDuration = 180;
- var effect = PoolManager.getEffect();
- if (effect) {
- effect.activate(self.x, self.y, 'slow');
- gameLayer.addChild(effect);
- }
- } else {
- self.slowDuration = 180; // Reset duration
- }
- } else if (damageType === 'poison' && self.material !== 'metal') {
- // Metal is immune to poison
- if (!self.poisoned) {
- self.poisoned = true;
- self.poisonDamage = damage * 0.2;
- self.poisonDuration = 300;
- var effect = PoolManager.getEffect();
- if (effect) {
- effect.activate(self.x, self.y, 'poison');
- gameLayer.addChild(effect);
- }
- }
- } else if (damageType === 'sniper') {
- var effect = PoolManager.getEffect();
- if (effect) {
- effect.activate(self.x, self.y, 'sniper');
- gameLayer.addChild(effect);
- }
- }
- if (self.health <= 0) {
- self.die();
- }
- };
- self.die = function () {
- // Create death particles
- for (var i = 0; i < 8; i++) {
- var particle = PoolManager.getParticle();
- if (particle) {
- particle.activate(self.x, self.y, self.material);
- gameLayer.addChild(particle);
- }
- }
- // Give gold based on enemy type and wave
- var goldEarned = Math.floor(5 + self.waveNumber * 0.5);
- if (self.material === 'shadow') {
- goldEarned *= 2;
- } // Shadow enemies give double gold
- goldEarned = Math.floor(goldEarned * 1.25); // Increase gold by 25%
- setGold(gold + goldEarned);
- score += 10 + self.waveNumber;
- PoolManager.returnBlob(self);
- };
- self.startJumpPreparation = function () {
- self.jumpState = 'preparing';
- // Calculate next position along path with consistent progress regardless of direction
- var pathLength = PathSystem.getPathLength(self.pathIndex);
- var progressIncrement = self.jumpDistance / pathLength;
- var nextProgress = Math.min(1, self.pathProgress + progressIncrement);
- var nextPos = PathSystem.getPositionAlongPath(nextProgress, self.pathIndex);
- self.startPosition.x = self.x;
- self.startPosition.y = self.baseY;
- self.targetPosition.x = nextPos.x;
- self.targetPosition.y = nextPos.y;
- // Pre-jump squish (getting ready)
- tween.stop(blobGraphics, {
- scaleX: true,
- scaleY: true
- });
- tween(blobGraphics, {
- scaleX: 1.2,
- scaleY: 0.8
- }, {
- duration: 150,
- easing: tween.quadOut,
- onFinish: function onFinish() {
- self.executeJump();
- }
- });
- };
- self.executeJump = function () {
- self.jumpState = 'jumping';
- self.jumpTimer = self.jumpDuration;
- // Stretch animation for jump take-off
- tween.stop(blobGraphics, {
- scaleX: true,
- scaleY: true
- });
- tween(blobGraphics, {
- scaleX: 0.8,
- scaleY: 1.2
- }, {
- duration: 200,
- easing: tween.quadOut
- });
- };
- self.landJump = function () {
- self.jumpState = 'landing';
- self.baseY = self.targetPosition.y;
- // Update path progress using the same increment
- var pathLength = PathSystem.getPathLength(self.pathIndex);
- var progressIncrement = self.jumpDistance / pathLength;
- self.pathProgress = Math.min(1, self.pathProgress + progressIncrement);
- // Landing squish
- tween.stop(blobGraphics, {
- scaleX: true,
- scaleY: true
- });
- tween(blobGraphics, {
- scaleX: 1.3,
- scaleY: 0.7
- }, {
- duration: 120,
- easing: tween.quadOut,
- onFinish: function onFinish() {
- // Return to normal
- tween(blobGraphics, {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 300,
- easing: tween.elasticOut,
- onFinish: function onFinish() {
- self.jumpState = 'paused';
- self.jumpTimer = self.pauseDuration;
- }
- });
- }
- });
- };
- self.getArcPosition = function (progress) {
- var x = self.startPosition.x + (self.targetPosition.x - self.startPosition.x) * progress;
- var y_base = self.startPosition.y + (self.targetPosition.y - self.startPosition.y) * progress;
- // The arc is a parabola on top of the base Y, peaking at progress = 0.5
- var arc_y = self.jumpHeight * 4 * progress * (1 - progress);
- var y = y_base - arc_y; // Subtract because Y is inverted (0 is top)
- return {
- x: x,
- y: y
- };
- };
- self.update = function () {
- if (!self.active) {
- return;
- }
- // Handle status effects
- if (self.slowed) {
- self.slowDuration--;
- if (self.slowDuration <= 0) {
- self.speed = self.originalSpeed;
- self.slowed = false;
- }
- }
- if (self.poisoned) {
- if (LK.ticks % 30 === 0) {
- // Poison damage every 30 frames
- self.health -= self.poisonDamage;
- healthBar.width = Math.max(0, self.health / self.maxHealth * 70);
- if (self.health <= 0) {
- self.die();
- return;
- }
- }
- self.poisonDuration--;
- if (self.poisonDuration <= 0) {
- self.poisoned = false;
- }
- }
- // Check if reached end of path
- if (self.pathProgress >= 1) {
- lives--;
- updateUI();
- PoolManager.returnBlob(self);
- if (lives <= 0) {
- LK.showGameOver();
- }
- return;
- }
- // Jump state machine
- switch (self.jumpState) {
- case 'paused':
- self.jumpTimer--;
- if (self.jumpTimer <= 0) {
- self.startJumpPreparation();
- }
- break;
- case 'preparing':
- // Animation handles this
- break;
- case 'jumping':
- self.jumpTimer--;
- var progress = (self.jumpDuration - self.jumpTimer) / self.jumpDuration;
- var arcPos = self.getArcPosition(progress);
- self.x = arcPos.x;
- self.y = arcPos.y;
- if (self.jumpTimer <= 0) {
- self.x = self.targetPosition.x;
- self.y = self.targetPosition.y;
- self.landJump();
- }
- break;
- case 'landing':
- // Animation handles this
- break;
- }
- };
- self.reset = function () {
- self.material = 'slime';
- self.health = 40;
- self.maxHealth = 40;
- self.speed = 1.2;
- self.pathProgress = 0;
- self.pathIndex = 0;
- self.waveNumber = 1;
- self.jumpState = 'paused';
- self.jumpTimer = 0;
- self.pauseDuration = 30;
- self.slowed = false;
- self.poisoned = false;
- self.slowDuration = 0;
- self.poisonDuration = 0;
- tween.stop(blobGraphics);
- blobGraphics.scaleX = 1;
- blobGraphics.scaleY = 1;
- blobGraphics.tint = 0x00FF00;
- };
- return self;
-});
+/****
+* Bullet Class
+****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
self.active = false;
- self.targetEnemy = null;
+ self.target = null;
self.damage = 10;
- self.speed = 5;
- self.type = 'default';
- self.sourceTowerLevel = 1;
- var bulletGraphics = self.attachAsset('particle', {
+ self.speed = 8;
+ var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
- bulletGraphics.width = 15;
- bulletGraphics.height = 15;
- self.activate = function (startX, startY, targetEnemy, damage, speed, type, sourceTowerLevel) {
+ self.activate = function (startX, startY, target, damage) {
self.active = true;
self.visible = true;
self.x = startX;
self.y = startY;
- self.targetEnemy = targetEnemy;
- self.damage = damage || 10;
- self.speed = speed || 5;
- self.type = type || 'default';
- self.sourceTowerLevel = sourceTowerLevel || 1;
- // Customize appearance based on type
- switch (self.type) {
- case 'rapid':
- bulletGraphics.tint = 0x00AAFF;
- bulletGraphics.width = bulletGraphics.height = 12;
- break;
- case 'sniper':
- bulletGraphics.tint = 0xFF5500;
- bulletGraphics.width = bulletGraphics.height = 8;
- break;
- case 'splash':
- bulletGraphics.tint = 0x33CC00;
- bulletGraphics.width = bulletGraphics.height = 20;
- break;
- case 'slow':
- bulletGraphics.tint = 0x9900FF;
- bulletGraphics.width = bulletGraphics.height = 18;
- break;
- case 'poison':
- bulletGraphics.tint = 0x00FFAA;
- bulletGraphics.width = bulletGraphics.height = 18;
- break;
- default:
- bulletGraphics.tint = 0xFFFFFF;
- bulletGraphics.width = bulletGraphics.height = 15;
- }
+ self.target = target;
+ self.damage = damage;
};
self.update = function () {
- if (!self.active || !self.targetEnemy || !self.targetEnemy.active) {
+ if (!self.active || !self.target || !self.target.active) {
PoolManager.returnBullet(self);
return;
}
- var dx = self.targetEnemy.x - self.x;
- var dy = self.targetEnemy.y - self.y;
+ var dx = self.target.x - self.x;
+ var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < self.speed) {
// Hit target
- self.targetEnemy.takeDamage(self.damage, self.type, self.sourceTowerLevel);
+ self.target.takeDamage(self.damage);
PoolManager.returnBullet(self);
} else {
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
}
};
- self.reset = function () {
- self.targetEnemy = null;
- self.damage = 10;
- self.speed = 5;
- self.type = 'default';
- self.sourceTowerLevel = 1;
- };
return self;
});
-var ClassDice = Container.expand(function () {
+/****
+* Object Pool Manager
+****/
+/****
+* Card Class
+****/
+var Card = Container.expand(function (cardData) {
var self = Container.call(this);
- self.active = false;
- self.diceType = 'warrior';
- self.level = 1;
- self.maxLevel = 6;
- self.gridX = 0;
- self.gridY = 0;
- self.area = 0;
- self.range = 3 * CELL_SIZE;
- self.damage = 10;
- self.fireRate = 60;
- self.bulletSpeed = 5;
+ self.cardData = cardData;
+ self.level = 1; // All cards start at level 1
+ self.isInPlay = false;
+ self.playSlotX = 0;
+ self.playSlotY = 0;
self.lastFired = 0;
- self.targetEnemy = null;
- self.isDragging = false;
- self.magneticTarget = null;
- var diceGraphics = self.attachAsset('warriorDice', {
+ self.fireRate = 60; // Base fire rate
+ self.damage = 10; // Base damage
+ self.range = 200; // Can hit anywhere on path
+ self.handBonus = 1; // Multiplier from poker hand
+ var cardGraphics = self.attachAsset('card', {
anchorX: 0.5,
anchorY: 0.5
});
- var pips = [];
- self.activate = function (diceType, gridX, gridY, area, level) {
- self.active = true;
- self.visible = true;
- self.diceType = diceType || 'warrior';
- self.level = level || 1;
- self.gridX = gridX;
- self.gridY = gridY;
- self.area = area;
- self.lastFired = 0;
- self.targetEnemy = null;
- self.setDiceType(self.diceType);
- self.updateVisuals();
- self.updatePosition();
- };
- self.setDiceType = function (type) {
- self.diceType = type;
- if (diceGraphics) {
- self.removeChild(diceGraphics);
- }
- switch (type) {
- case 'knifethrower':
- self.fireRate = 30;
- self.damage = 5;
- self.range = 2.5 * CELL_SIZE;
- self.bulletSpeed = 7;
- diceGraphics = self.attachAsset('knifethrowerDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- break;
- case 'archer':
- self.fireRate = 90;
- self.damage = 25;
- self.range = 5 * CELL_SIZE;
- self.bulletSpeed = 25;
- diceGraphics = self.attachAsset('archerDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- break;
- case 'engineer':
- self.fireRate = 75;
- self.damage = 15;
- self.range = 2 * CELL_SIZE;
- self.bulletSpeed = 4;
- diceGraphics = self.attachAsset('engineerDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- break;
- case 'icemage':
- self.fireRate = 50;
- self.damage = 8;
- self.range = 3.5 * CELL_SIZE;
- self.bulletSpeed = 5;
- diceGraphics = self.attachAsset('iceMageDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- break;
- case 'assassin':
- self.fireRate = 70;
- self.damage = 12;
- self.range = 3.2 * CELL_SIZE;
- self.bulletSpeed = 5;
- diceGraphics = self.attachAsset('assassinDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- break;
+ // Define getSuitSymbol method before using it
+ self.getSuitSymbol = function (suit) {
+ switch (suit) {
+ case 'hearts':
+ return '♥';
+ case 'diamonds':
+ return '♦';
+ case 'clubs':
+ return '♣';
+ case 'spades':
+ return '♠';
+ case 'joker':
+ return '🃏';
default:
- self.fireRate = 60;
- self.damage = 10;
- self.range = 3 * CELL_SIZE;
- self.bulletSpeed = 5;
- diceGraphics = self.attachAsset('warriorDice', {
- anchorX: 0.5,
- anchorY: 0.5
- });
+ return '?';
}
};
- self.updateVisuals = function () {
- var baseSize = 270; // Fixed size, no longer increases with level
- diceGraphics.width = diceGraphics.height = baseSize;
- for (var i = 0; i < pips.length; i++) {
- self.removeChild(pips[i]);
+ // Card value in top left corner
+ var valueText = new Text2(cardData.value, {
+ size: 30,
+ fill: CardSystem.suitColors[cardData.suit] || 0x000000,
+ weight: 800
+ });
+ valueText.anchor.set(0, 0);
+ valueText.x = -60; // Top left
+ valueText.y = -85;
+ self.addChild(valueText);
+ // Large suit symbol in center
+ var suitText = new Text2(self.getSuitSymbol(cardData.suit), {
+ size: 80,
+ fill: CardSystem.suitColors[cardData.suit] || 0x000000,
+ weight: 800
+ });
+ suitText.anchor.set(0.5, 0.5);
+ suitText.y = -10; // Slightly above center
+ self.addChild(suitText);
+ // Level text at bottom
+ var levelText = new Text2('Lvl 1', {
+ size: 25,
+ fill: 0x000000,
+ weight: 800
+ });
+ levelText.anchor.set(0.5, 1);
+ levelText.y = 85; // Bottom of card
+ self.addChild(levelText);
+ self.activate = function (x, y, inPlay) {
+ self.x = x;
+ self.y = y;
+ self.isInPlay = inPlay || false;
+ self.visible = true;
+ if (inPlay) {
+ self.calculateStats();
}
- pips = [];
- self.createPips(self.level);
- var pulseScale = 1.02; // Fixed pulse scale, no longer increases with level
- tween.stop(diceGraphics, {
- scaleX: true,
- scaleY: true
- });
- tween(diceGraphics, {
- scaleX: pulseScale,
- scaleY: pulseScale
- }, {
- duration: 1000,
- easing: tween.sineInOut,
- repeat: -1,
- yoyo: true
- });
};
- self.createPips = function (level) {
- // This function now creates a level number text instead of pips.
- if (!self.levelText) {
- self.levelText = new Text2('', {
- size: 100,
- fill: '#FFFFFF',
- weight: 'bolder',
- stroke: '#000000',
- strokeThickness: 12
- });
- self.levelText.anchor.set(0.5, 1);
- self.levelText.y = 140; // Position at bottom center of dice graphic
- self.addChild(self.levelText);
- } else {
- // Ensure text is on top by re-adding it to the container
- self.removeChild(self.levelText);
- self.addChild(self.levelText);
+ self.calculateStats = function () {
+ // Stats based on level only, not card face value
+ var baseDamage = 10;
+ var baseFireRate = 60;
+ // Level scaling
+ self.damage = Math.floor(baseDamage * Math.pow(1.5, self.level - 1));
+ self.fireRate = Math.max(10, Math.floor(baseFireRate / Math.pow(1.2, self.level - 1)));
+ // Apply poker hand bonus
+ self.damage = Math.floor(self.damage * self.handBonus);
+ self.fireRate = Math.max(5, Math.floor(self.fireRate / self.handBonus));
+ };
+ self.setLevel = function (newLevel) {
+ self.level = newLevel;
+ levelText.setText('Lvl ' + self.level);
+ self.calculateStats();
+ // Visual feedback for higher levels
+ if (self.level > 1) {
+ var glowIntensity = Math.min(0.3, self.level * 0.05);
+ cardGraphics.alpha = 1 + glowIntensity;
}
- self.levelText.setText(level);
};
- self.updatePosition = function () {
- var startX = self.area === 0 ? TOP_AREA_X : BOTTOM_AREA_X;
- var startY = self.area === 0 ? TOP_AREA_Y : BOTTOM_AREA_Y;
- self.x = startX + self.gridX * CELL_SIZE + CELL_SIZE / 2;
- self.y = startY + self.gridY * CELL_SIZE + CELL_SIZE / 2;
+ self.canMergeWith = function (otherCard) {
+ if (!otherCard || otherCard === self) return false;
+ // Must be same level AND (same suit OR same value)
+ var sameLevel = self.level === otherCard.level;
+ var sameSuit = self.cardData.suit === otherCard.cardData.suit;
+ var sameValue = self.cardData.value === otherCard.cardData.value;
+ return sameLevel && (sameSuit || sameValue);
};
- self.getRange = function () {
- var baseRange = self.range;
- var rangeMultiplier = 1 + (self.level - 1) * 0.15;
- if (self.diceType === 'archer' && self.level === self.maxLevel) {
- rangeMultiplier *= 2;
+ self.mergeWith = function (otherCard) {
+ if (!self.canMergeWith(otherCard)) return null;
+ var newCardData;
+ var newLevel = self.level + 1; // Increase level by 1
+ if (self.cardData.suit === otherCard.cardData.suit) {
+ // Same suit: random value, keep suit
+ var randomValue = CardSystem.values[Math.floor(Math.random() * CardSystem.values.length)];
+ newCardData = {
+ suit: self.cardData.suit,
+ value: randomValue,
+ id: self.cardData.suit + '_' + randomValue
+ };
+ } else {
+ // Same value: increase value by 1, random suit
+ var currentValueIndex = CardSystem.values.indexOf(self.cardData.value);
+ var nextValueIndex = (currentValueIndex + 1) % CardSystem.values.length;
+ var randomSuit = CardSystem.suits[Math.floor(Math.random() * CardSystem.suits.length)];
+ newCardData = {
+ suit: randomSuit,
+ value: CardSystem.values[nextValueIndex],
+ id: randomSuit + '_' + CardSystem.values[nextValueIndex]
+ };
}
- return baseRange * rangeMultiplier;
+ var mergedCard = new Card(newCardData);
+ mergedCard.setLevel(newLevel);
+ return mergedCard;
};
- self.getCurrentDamage = function () {
- var damageMultiplier = 1 + (self.level - 1) * 0.5;
- if (self.level === self.maxLevel) {
- damageMultiplier *= 2;
- }
- return Math.floor(self.damage * damageMultiplier);
- };
- self.getCurrentFireRate = function () {
- var rateMultiplier = 1 + (self.level - 1) * 0.3;
- return Math.max(10, Math.floor(self.fireRate / rateMultiplier));
- };
self.findTarget = function () {
- var closestEnemy = null;
- var closestDistance = Infinity;
- var diceRange = self.getRange();
- for (var i = 0; i < activeBlobs.length; i++) {
- var blob = activeBlobs[i];
- if (!blob.active) {
- continue;
+ var targets = gameState.isPlayerTurn ? activeAIChips : activePlayerChips;
+ for (var i = 0; i < targets.length; i++) {
+ if (targets[i].active) {
+ return targets[i]; // For now, just target first available
}
- var dx = blob.x - self.x;
- var dy = blob.y - self.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance <= diceRange && distance < closestDistance) {
- closestDistance = distance;
- closestEnemy = blob;
- }
}
- return closestEnemy;
+ return null;
};
- self.getBulletType = function () {
- switch (self.diceType) {
- case 'knifethrower':
- return 'rapid';
- case 'archer':
- return 'sniper';
- case 'engineer':
- return 'splash';
- case 'icemage':
- return 'slow';
- case 'assassin':
- return 'poison';
- case 'warrior':
- default:
- return 'default';
- }
- };
self.fire = function () {
- if (!self.targetEnemy) {
- return;
- }
+ var target = self.findTarget();
+ if (!target) return;
var bullet = PoolManager.getBullet();
if (bullet) {
- var bulletStartX = self.x;
- var bulletStartY = self.y;
- bullet.activate(bulletStartX, bulletStartY, self.targetEnemy, self.getCurrentDamage(), self.bulletSpeed + self.level, self.getBulletType(), self.level);
+ bullet.activate(self.x, self.y, target, self.damage);
gameLayer.addChild(bullet);
activeBullets.push(bullet);
- tween.stop(diceGraphics, {
+ self.lastFired = LK.ticks;
+ // Visual feedback for firing
+ tween.stop(self, {
scaleX: true,
scaleY: true
});
- tween(diceGraphics, {
+ tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
- duration: 50,
+ duration: 100,
easing: tween.quadOut,
onFinish: function onFinish() {
- tween(diceGraphics, {
+ tween(self, {
scaleX: 1,
scaleY: 1
}, {
- duration: 100,
+ duration: 150,
easing: tween.elasticOut
});
}
});
}
};
- self.canMergeWith = function (otherDice) {
- return otherDice && otherDice !== self && otherDice.active && otherDice.diceType === self.diceType && otherDice.level === self.level && self.level < self.maxLevel;
- };
- self.checkMagneticAttraction = function (otherDice) {
- // Magnetic effect removed by design.
- };
- self.mergeWith = function (otherDice) {
- if (!self.canMergeWith(otherDice)) {
- return false;
- }
- // Check for an available dice in the pool before removing the existing ones.
- var newDice = PoolManager.getClassDice();
- if (!newDice) {
- return false;
- }
- var newDiceGridX = otherDice.gridX;
- var newDiceGridY = otherDice.gridY;
- var newDiceArea = otherDice.area;
- var newDiceType = self.diceType;
- var newLevel = self.level + 1;
- // Remove old dice first to free up the grid spot.
- GameManager.removeDice(self);
- GameManager.removeDice(otherDice);
- // Activate and place the new dice.
- newDice.activate(newDiceType, newDiceGridX, newDiceGridY, newDiceArea, newLevel);
- if (newDiceArea === 0) {
- topAreaLayer.addChild(newDice);
- topAreaDice[newDiceGridX][newDiceGridY] = newDice;
- } else {
- bottomAreaLayer.addChild(newDice);
- bottomAreaDice[newDiceGridX][newDiceGridY] = newDice;
- }
- tween(newDice, {
- scaleX: 1.5,
- scaleY: 1.5
- }, {
- duration: 200,
- easing: tween.elasticOut,
- onFinish: function onFinish() {
- tween(newDice, {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 300,
- easing: tween.elasticOut
- });
- }
- });
- return true;
- };
self.update = function () {
- if (!self.active || self.isDragging) {
- return;
+ if (!self.isInPlay) return;
+ if (LK.ticks - self.lastFired >= self.fireRate) {
+ self.fire();
}
- self.targetEnemy = self.findTarget();
- if (self.targetEnemy) {
- if (LK.ticks - self.lastFired >= self.getCurrentFireRate()) {
- self.fire();
- self.lastFired = LK.ticks;
- }
- }
};
- self.reset = function () {
- self.diceType = 'warrior';
- self.level = 1;
- self.gridX = 0;
- self.gridY = 0;
- self.area = 0;
- self.lastFired = 0;
- self.targetEnemy = null;
- self.isDragging = false;
- self.magneticTarget = null;
- tween.stop(self);
- tween.stop(diceGraphics);
- if (self.levelText) {
- self.levelText.setText('');
- }
- pips = [];
- diceGraphics.scaleX = diceGraphics.scaleY = 1;
- };
+ // Initialize with level 1
+ self.setLevel(1);
return self;
});
-var DeathParticle = Container.expand(function () {
+/****
+* Poker Chip Enemy Class
+****/
+var PokerChip = Container.expand(function () {
var self = Container.call(this);
self.active = false;
- self.velocity = {
- x: 0,
- y: 0
- };
- self.life = 0;
- self.maxLife = 60;
- var particleGraphics = self.attachAsset('particle', {
+ self.health = 10;
+ self.maxHealth = 10;
+ self.value = 1; // Chip value (1, 5, 10, 25, 100)
+ self.speed = 2;
+ self.pathProgress = 0;
+ self.isPlayerSide = true; // true for player side, false for AI side
+ var chipGraphics = self.attachAsset('pokerChip', {
anchorX: 0.5,
anchorY: 0.5
});
- self.activate = function (x, y, material) {
- self.active = true;
- self.visible = true;
- self.x = x;
- self.y = y;
- self.life = self.maxLife;
- // Random velocity
- var angle = Math.random() * Math.PI * 2;
- var speed = 2 + Math.random() * 4;
- self.velocity.x = Math.cos(angle) * speed;
- self.velocity.y = Math.sin(angle) * speed;
- // Set color based on material
- switch (material) {
- case 'slime':
- particleGraphics.tint = 0x00FF00;
- break;
- case 'metal':
- particleGraphics.tint = 0xC0C0C0;
- break;
- case 'lava':
- particleGraphics.tint = 0xFF4500;
- break;
- case 'ice':
- particleGraphics.tint = 0x87CEEB;
- break;
- case 'shadow':
- particleGraphics.tint = 0x4B0082;
- break;
- default:
- particleGraphics.tint = 0xFFFFFF;
- }
- particleGraphics.width = particleGraphics.height = 4 + Math.random() * 8;
- self.alpha = 1;
- };
- self.update = function () {
- if (!self.active) {
- return;
- }
- self.x += self.velocity.x;
- self.y += self.velocity.y;
- self.velocity.y += 0.2; // Gravity
- self.life--;
- self.alpha = self.life / self.maxLife;
- if (self.life <= 0) {
- PoolManager.returnParticle(self);
- }
- };
- self.reset = function () {
- self.velocity.x = 0;
- self.velocity.y = 0;
- self.life = 0;
- };
- return self;
-});
-var EffectIndicator = Container.expand(function () {
- var self = Container.call(this);
- self.active = false;
- self.effectType = 'splash';
- var effectGraphics = self.attachAsset('rangeCircle', {
- anchorX: 0.5,
- anchorY: 0.5
+ var valueText = new Text2('1', {
+ size: 30,
+ fill: 0xffffff,
+ weight: 800
});
- effectGraphics.blendMode = 1;
- self.activate = function (x, y, type) {
+ valueText.anchor.set(0.5, 0.5);
+ self.addChild(valueText);
+ self.activate = function (value, isPlayerSide) {
self.active = true;
self.visible = true;
- self.x = x;
- self.y = y;
- self.effectType = type;
- switch (type) {
- case 'splash':
- effectGraphics.tint = 0x33CC00;
- effectGraphics.width = effectGraphics.height = CELL_SIZE * 1.5;
- break;
- case 'slow':
- effectGraphics.tint = 0x9900FF;
- effectGraphics.width = effectGraphics.height = CELL_SIZE;
- break;
- case 'poison':
- effectGraphics.tint = 0x00FFAA;
- effectGraphics.width = effectGraphics.height = CELL_SIZE;
- break;
- case 'sniper':
- effectGraphics.tint = 0xFF5500;
- effectGraphics.width = effectGraphics.height = CELL_SIZE;
- break;
- }
- effectGraphics.alpha = 0.7;
- self.alpha = 0;
- self.scaleX = 0.5;
- self.scaleY = 0.5;
- // Animate effect
- tween(self, {
- alpha: 0.8,
- scaleX: 1.5,
- scaleY: 1.5
- }, {
- duration: 200,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- tween(self, {
- alpha: 0,
- scaleX: 2,
- scaleY: 2
- }, {
- duration: 300,
- easing: tween.easeIn,
- onFinish: function onFinish() {
- PoolManager.returnEffect(self);
- }
- });
- }
- });
+ self.value = value;
+ self.isPlayerSide = isPlayerSide;
+ self.health = self.maxHealth = value;
+ self.pathProgress = 0;
+ // Set chip color based on value
+ self.setChipAppearance();
+ // Position at start of path
+ var startPos = PathSystem.getPathStart(isPlayerSide);
+ self.x = startPos.x;
+ self.y = startPos.y;
};
- self.reset = function () {
- self.effectType = 'splash';
- tween.stop(self);
+ self.setChipAppearance = function () {
+ var colors = {
+ 1: 0xffffff,
+ // White
+ 5: 0xff0000,
+ // Red
+ 10: 0x00ff00,
+ // Green
+ 25: 0x000000,
+ // Black
+ 100: 0x800080 // Purple
+ };
+ chipGraphics.tint = colors[self.value] || 0xffffff;
+ valueText.setText(self.value.toString());
};
- return self;
-});
-var GenerateButton = Container.expand(function (area) {
- var self = Container.call(this);
- self.area = area; // 0 for top, 1 for bottom
- self.cost = 10;
- var buttonGraphics = self.attachAsset('generateButton', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- var costText = new Text2('Generate: ' + self.cost, {
- size: 30,
- fill: 0xFFFFFF,
- weight: 800
- });
- costText.anchor.set(0.5, 0.5);
- self.addChild(costText);
- self.updateCost = function () {
- // Fibonacci-like progression
- var newCost = Math.floor(10 * Math.pow(1.315, GameManager.getGenerateCount(self.area)));
- self.cost = newCost;
- costText.setText('Generate: ' + self.cost);
- // Update button color based on affordability
- if (gold >= self.cost) {
- buttonGraphics.tint = 0x00AA00;
- } else {
- buttonGraphics.tint = 0x888888;
+ self.takeDamage = function (damage) {
+ self.health -= damage;
+ if (self.health <= 0) {
+ self.die();
}
};
- self.generate = function () {
- if (gold < self.cost) {
- return false;
- }
- var emptySpot = GameManager.findEmptySpot(self.area);
- if (!emptySpot) {
- return false;
- }
- // Random dice type
- var types = ['warrior', 'knifethrower', 'archer', 'engineer', 'icemage', 'assassin'];
- var randomType = types[Math.floor(Math.random() * types.length)];
- var newDice = PoolManager.getClassDice();
- if (newDice) {
- newDice.activate(randomType, emptySpot.x, emptySpot.y, self.area);
- if (self.area === 0) {
- topAreaLayer.addChild(newDice);
- topAreaDice[emptySpot.x][emptySpot.y] = newDice;
- } else {
- bottomAreaLayer.addChild(newDice);
- bottomAreaDice[emptySpot.x][emptySpot.y] = newDice;
- }
- setGold(gold - self.cost);
- GameManager.incrementGenerateCount(self.area);
- self.updateCost();
- // Spawn animation
- newDice.alpha = 0;
- newDice.scaleX = newDice.scaleY = 0.5;
- tween(newDice, {
- alpha: 1,
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 300,
- easing: tween.elasticOut
- });
- return true;
- }
- return false;
- };
- self.down = function () {
- self.generate();
- };
- self.update = function () {
- self.updateCost();
- };
- return self;
-});
-var Notification = Container.expand(function (message) {
- var self = Container.call(this);
- var notificationText = new Text2(message, {
- size: 80,
- fill: '#FFFFFF',
- weight: 'bolder',
- stroke: '#000000',
- strokeThickness: 12
- });
- notificationText.anchor.set(0.5, 0.5);
- self.addChild(notificationText);
- self.alpha = 1;
- var fadeOutTime = 180; // 3 seconds
- self.update = function () {
- if (fadeOutTime > 0) {
- fadeOutTime--;
- self.alpha = Math.min(fadeOutTime / 60, 1);
+ self.die = function () {
+ // Award money based on chip value
+ var goldEarned = self.value;
+ if (self.isPlayerSide) {
+ gameState.playerGold += goldEarned;
} else {
- self.destroy();
+ gameState.aiGold += goldEarned;
}
+ // Spawn new chips on opposite side
+ self.spawnCounterChips();
+ PoolManager.returnChip(self);
};
- return self;
-});
-/****
-* Game Manager
-****/
-var WaveManager = Container.expand(function () {
- var self = Container.call(this);
- self.currentWave = 0;
- self.maxWaves = 50;
- self.waveTimer = 0;
- self.waveDelay = 300; // 5 seconds at 60fps
- self.waveActive = false;
- self.enemiesSpawned = 0;
- self.enemiesToSpawn = 0;
- self.spawnTimer = 0;
- self.spawnDelay = 30; // 0.5 seconds between spawns
- var waveText = new Text2('Wave: 1', {
- size: 60,
- fill: 0xFFFF00,
- weight: 800
- });
- waveText.anchor.set(0.5, 0.5);
- self.addChild(waveText);
- self.startNextWave = function () {
- self.currentWave++;
- self.waveActive = true;
- self.enemiesSpawned = 0;
- self.spawnTimer = 0;
- // Determine wave composition
- self.enemiesToSpawn = 10 + Math.floor(self.currentWave * 1.5);
- waveText.setText('Wave: ' + self.currentWave);
- // Show wave start notification
- var notification = new Notification('Wave ' + self.currentWave + ' incoming!');
- notification.x = SCREEN_WIDTH / 2;
- notification.y = SCREEN_HEIGHT / 2;
- gameLayer.addChild(notification);
- };
- self.getWaveMaterial = function () {
- // Introduce new materials over time
- if (self.currentWave <= 5) {
- return 'slime';
+ self.spawnCounterChips = function () {
+ // When player defeats AI chip, spawn chips on AI side
+ // When AI defeats player chip, spawn chips on player side
+ var targetSide = !self.isPlayerSide;
+ var spawnCount = Math.max(1, Math.floor(self.value / 5));
+ for (var i = 0; i < spawnCount; i++) {
+ setTimeout(function () {
+ ChipSpawner.spawnChip(1, targetSide); // Spawn basic chips
+ }, i * 500);
}
- if (self.currentWave <= 10) {
- return Math.random() < 0.7 ? 'slime' : 'metal';
- }
- if (self.currentWave <= 15) {
- var materials = ['slime', 'metal', 'ice'];
- return materials[Math.floor(Math.random() * materials.length)];
- }
- if (self.currentWave <= 25) {
- var materials = ['slime', 'metal', 'ice', 'lava'];
- return materials[Math.floor(Math.random() * materials.length)];
- }
- // All materials available
- var materials = ['slime', 'metal', 'ice', 'lava', 'shadow'];
- return materials[Math.floor(Math.random() * materials.length)];
};
- self.spawnEnemy = function () {
- var blob = PoolManager.getBlob();
- if (blob) {
- var material = self.getWaveMaterial();
- var pathIndex = self.enemiesSpawned % 2;
- blob.activate(material, self.currentWave, pathIndex);
- gameLayer.addChild(blob);
- activeBlobs.push(blob);
- self.enemiesSpawned++;
- }
- };
self.update = function () {
- if (!self.waveActive) {
- self.waveTimer++;
- if (self.waveTimer >= self.waveDelay) {
- self.waveTimer = 0;
- self.startNextWave();
- }
- } else {
- // Spawn enemies
- if (self.enemiesSpawned < self.enemiesToSpawn) {
- self.spawnTimer++;
- if (self.spawnTimer >= self.spawnDelay) {
- self.spawnTimer = 0;
- self.spawnEnemy();
- }
+ if (!self.active) {
+ return;
+ }
+ self.pathProgress += self.speed;
+ var pathPos = PathSystem.getPositionAlongPath(self.pathProgress, self.isPlayerSide);
+ if (pathPos.completed) {
+ // Chip reached the end
+ if (self.isPlayerSide) {
+ gameState.playerLives--;
} else {
- // Check if wave is complete
- var activeEnemies = 0;
- for (var i = 0; i < activeBlobs.length; i++) {
- if (activeBlobs[i].active) {
- activeEnemies++;
- }
- }
- if (activeEnemies === 0) {
- self.waveActive = false;
- if (self.currentWave >= self.maxWaves) {
- LK.showYouWin();
- }
- }
+ gameState.aiLives--;
}
+ PoolManager.returnChip(self);
+ return;
}
+ self.x = pathPos.x;
+ self.y = pathPos.y;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
- backgroundColor: 0x1a1a2e
+ backgroundColor: 0x0f3d0f
});
/****
* Game Code
****/
/****
-* Object Pools
+* Poker Tower Defense - Complete Refactor
****/
/****
* Game Constants
****/
+function _createForOfIteratorHelper(r, e) {
+ var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
+ if (!t) {
+ if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
+ t && (r = t);
+ var _n = 0,
+ F = function F() {};
+ return {
+ s: F,
+ n: function n() {
+ return _n >= r.length ? {
+ done: !0
+ } : {
+ done: !1,
+ value: r[_n++]
+ };
+ },
+ e: function e(r) {
+ throw r;
+ },
+ f: F
+ };
+ }
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
+ var o,
+ a = !0,
+ u = !1;
+ return {
+ s: function s() {
+ t = t.call(r);
+ },
+ n: function n() {
+ var r = t.next();
+ return a = r.done, r;
+ },
+ e: function e(r) {
+ u = !0, o = r;
+ },
+ f: function f() {
+ try {
+ a || null == t["return"] || t["return"]();
+ } finally {
+ if (u) {
+ throw o;
+ }
+ }
+ }
+ };
+}
+function _unsupportedIterableToArray(r, a) {
+ if (r) {
+ if ("string" == typeof r) {
+ return _arrayLikeToArray(r, a);
+ }
+ var t = {}.toString.call(r).slice(8, -1);
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
+ }
+}
+function _arrayLikeToArray(r, a) {
+ (null == a || a > r.length) && (a = r.length);
+ for (var e = 0, n = Array(a); e < a; e++) {
+ n[e] = r[e];
+ }
+ return n;
+}
+var SCREEN_WIDTH = 2048;
+var SCREEN_HEIGHT = 2732;
+var PLAY_AREA_COLS = 5;
+var PLAY_AREA_ROWS = 2;
+var SLOT_WIDTH = 200;
+var SLOT_HEIGHT = 280;
+var DEAL_SLOT_WIDTH = 160;
+var DEAL_SLOT_HEIGHT = 220;
+// Player area positioning (bottom)
+var PLAYER_AREA_X = (SCREEN_WIDTH - PLAY_AREA_COLS * SLOT_WIDTH) / 2;
+var PLAYER_AREA_Y = SCREEN_HEIGHT - 400;
+var PLAYER_DEAL_AREA_Y = PLAYER_AREA_Y + PLAY_AREA_ROWS * SLOT_HEIGHT + 40;
+// AI area positioning (top) - mirrored
+var AI_AREA_X = PLAYER_AREA_X;
+var AI_AREA_Y = 200;
+/****
+* Card System
+****/
+var CardSystem = {
+ suits: ['hearts', 'diamonds', 'clubs', 'spades'],
+ values: ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'],
+ suitColors: {
+ 'hearts': 0xff0000,
+ 'diamonds': 0xff0000,
+ 'clubs': 0x000000,
+ 'spades': 0x000000
+ },
+ createDeck: function createDeck() {
+ var deck = [];
+ var _iterator = _createForOfIteratorHelper(this.suits),
+ _step;
+ try {
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
+ var suit = _step.value;
+ var _iterator2 = _createForOfIteratorHelper(this.values),
+ _step2;
+ try {
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
+ var value = _step2.value;
+ deck.push({
+ suit: suit,
+ value: value,
+ id: suit + '_' + value
+ });
+ }
+ } catch (err) {
+ _iterator2.e(err);
+ } finally {
+ _iterator2.f();
+ }
+ }
+ // Add jokers
+ } catch (err) {
+ _iterator.e(err);
+ } finally {
+ _iterator.f();
+ }
+ deck.push({
+ suit: 'joker',
+ value: 'red',
+ id: 'joker_red'
+ });
+ deck.push({
+ suit: 'joker',
+ value: 'black',
+ id: 'joker_black'
+ });
+ return this.shuffleDeck(deck);
+ },
+ shuffleDeck: 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;
+ }
+ return deck;
+ },
+ getCardValue: function getCardValue(card) {
+ if (card.suit === 'joker') {
+ return 14;
+ } // Jokers are highest
+ if (card.value === 'A') {
+ return 14;
+ } // Aces high
+ if (card.value === 'K') {
+ return 13;
+ }
+ if (card.value === 'Q') {
+ return 12;
+ }
+ if (card.value === 'J') {
+ return 11;
+ }
+ return parseInt(card.value);
+ },
+ evaluatePokerHand: function evaluatePokerHand(cards) {
+ var _this = this;
+ if (!cards || cards.length !== 5) {
+ return {
+ type: 'none',
+ strength: 0
+ };
+ }
+ // Sort cards by value for easier analysis
+ var sortedCards = cards.slice().sort(function (a, b) {
+ return _this.getCardValue(b) - _this.getCardValue(a);
+ });
+ var values = sortedCards.map(function (card) {
+ return _this.getCardValue(card);
+ });
+ var suits = sortedCards.map(function (card) {
+ return card.suit;
+ });
+ // Count values and suits
+ var valueCounts = {};
+ var suitCounts = {};
+ values.forEach(function (value) {
+ return valueCounts[value] = (valueCounts[value] || 0) + 1;
+ });
+ suits.forEach(function (suit) {
+ return suitCounts[suit] = (suitCounts[suit] || 0) + 1;
+ });
+ var counts = Object.values(valueCounts).sort(function (a, b) {
+ return b - a;
+ });
+ var isFlush = Object.keys(suitCounts).length === 1;
+ var isStraight = this.checkStraight(values);
+ // Royal Flush
+ if (isFlush && isStraight && values[0] === 14 && values[4] === 10) {
+ return {
+ type: 'royal_flush',
+ strength: 10,
+ multiplier: 50
+ };
+ }
+ // Straight Flush
+ if (isFlush && isStraight) {
+ return {
+ type: 'straight_flush',
+ strength: 9,
+ multiplier: 25
+ };
+ }
+ // Four of a Kind
+ if (counts[0] === 4) {
+ return {
+ type: 'four_of_a_kind',
+ strength: 8,
+ multiplier: 15
+ };
+ }
+ // Full House
+ if (counts[0] === 3 && counts[1] === 2) {
+ return {
+ type: 'full_house',
+ strength: 7,
+ multiplier: 8
+ };
+ }
+ // Flush
+ if (isFlush) {
+ return {
+ type: 'flush',
+ strength: 6,
+ multiplier: 5
+ };
+ }
+ // Straight
+ if (isStraight) {
+ return {
+ type: 'straight',
+ strength: 5,
+ multiplier: 4
+ };
+ }
+ // Three of a Kind
+ if (counts[0] === 3) {
+ return {
+ type: 'three_of_a_kind',
+ strength: 4,
+ multiplier: 3
+ };
+ }
+ // Two Pair
+ if (counts[0] === 2 && counts[1] === 2) {
+ return {
+ type: 'two_pair',
+ strength: 3,
+ multiplier: 2.5
+ };
+ }
+ // One Pair
+ if (counts[0] === 2) {
+ return {
+ type: 'one_pair',
+ strength: 2,
+ multiplier: 1.5
+ };
+ }
+ // High Card
+ return {
+ type: 'high_card',
+ strength: 1,
+ multiplier: 1
+ };
+ },
+ checkStraight: function checkStraight(values) {
+ if (values.length !== 5) {
+ return false;
+ }
+ // Check for ace-low straight (A, 2, 3, 4, 5)
+ if (values[0] === 14 && values[1] === 5 && values[2] === 4 && values[3] === 3 && values[4] === 2) {
+ return true;
+ }
+ // Check normal straight
+ for (var i = 0; i < 4; i++) {
+ if (values[i] - values[i + 1] !== 1) {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+/****
+* Object Pool Manager
+****/
var PoolManager = {
- classDicePool: [],
- blobPool: [],
+ chipPool: [],
bulletPool: [],
- particlePool: [],
- effectPool: [],
- // Pool sizes
- CLASS_DICE_POOL_SIZE: 30,
- BLOB_POOL_SIZE: 100,
- BULLET_POOL_SIZE: 200,
- PARTICLE_POOL_SIZE: 500,
- EFFECT_POOL_SIZE: 100,
+ cardPool: [],
+ CHIP_POOL_SIZE: 50,
+ BULLET_POOL_SIZE: 100,
+ CARD_POOL_SIZE: 60,
init: function init() {
- // Initialize dice pool
- for (var i = 0; i < this.CLASS_DICE_POOL_SIZE; i++) {
- var dice = new ClassDice();
- dice.active = false;
- dice.visible = false;
- this.classDicePool.push(dice);
+ // Initialize pools
+ for (var i = 0; i < this.CHIP_POOL_SIZE; i++) {
+ var chip = new PokerChip();
+ chip.active = false;
+ chip.visible = false;
+ this.chipPool.push(chip);
}
- // Initialize blob pool
- for (var i = 0; i < this.BLOB_POOL_SIZE; i++) {
- var blob = new BlobEnemy();
- blob.active = false;
- blob.visible = false;
- this.blobPool.push(blob);
- }
- // Initialize bullet pool
for (var i = 0; i < this.BULLET_POOL_SIZE; i++) {
var bullet = new Bullet();
bullet.active = false;
bullet.visible = false;
this.bulletPool.push(bullet);
}
- // Initialize particle pool
- for (var i = 0; i < this.PARTICLE_POOL_SIZE; i++) {
- var particle = new DeathParticle();
- particle.active = false;
- particle.visible = false;
- this.particlePool.push(particle);
- }
- // Initialize effect pool
- for (var i = 0; i < this.EFFECT_POOL_SIZE; i++) {
- var effect = new EffectIndicator();
- effect.active = false;
- effect.visible = false;
- this.effectPool.push(effect);
- }
},
- getClassDice: function getClassDice() {
- for (var i = 0; i < this.classDicePool.length; i++) {
- if (!this.classDicePool[i].active) {
- return this.classDicePool[i];
+ getChip: function getChip() {
+ for (var i = 0; i < this.chipPool.length; i++) {
+ if (!this.chipPool[i].active) {
+ return this.chipPool[i];
}
}
- return null; // Pool exhausted
- },
- getBlob: function getBlob() {
- for (var i = 0; i < this.blobPool.length; i++) {
- if (!this.blobPool[i].active) {
- return this.blobPool[i];
- }
- }
return null;
},
getBullet: function getBullet() {
for (var i = 0; i < this.bulletPool.length; i++) {
@@ -1191,834 +679,652 @@
}
}
return null;
},
- getParticle: function getParticle() {
- for (var i = 0; i < this.particlePool.length; i++) {
- if (!this.particlePool[i].active) {
- return this.particlePool[i];
- }
+ returnChip: function returnChip(chip) {
+ chip.active = false;
+ chip.visible = false;
+ // Remove from active arrays
+ var playerIndex = activePlayerChips.indexOf(chip);
+ if (playerIndex !== -1) {
+ activePlayerChips.splice(playerIndex, 1);
}
- return null;
- },
- getEffect: function getEffect() {
- for (var i = 0; i < this.effectPool.length; i++) {
- if (!this.effectPool[i].active) {
- return this.effectPool[i];
- }
+ var aiIndex = activeAIChips.indexOf(chip);
+ if (aiIndex !== -1) {
+ activeAIChips.splice(aiIndex, 1);
}
- return null;
+ gameLayer.removeChild(chip);
},
- returnClassDice: function returnClassDice(dice) {
- dice.active = false;
- dice.visible = false;
- dice.reset();
- },
- returnBlob: function returnBlob(blob) {
- blob.active = false;
- blob.visible = false;
- blob.reset();
- if (blob.shadow) {
- blob.shadow.visible = false;
- }
- },
returnBullet: function returnBullet(bullet) {
bullet.active = false;
bullet.visible = false;
- bullet.reset();
- },
- returnParticle: function returnParticle(particle) {
- particle.active = false;
- particle.visible = false;
- particle.reset();
- },
- returnEffect: function returnEffect(effect) {
- effect.active = false;
- effect.visible = false;
- effect.reset();
+ var index = activeBullets.indexOf(bullet);
+ if (index !== -1) {
+ activeBullets.splice(index, 1);
+ }
+ gameLayer.removeChild(bullet);
}
};
/****
-* Path System - WRAPPED AROUND BUILDING AREAS
+* Path System
****/
var PathSystem = {
- pathPoints: [],
+ playerPath: [],
+ aiPath: [],
init: function init() {
- // Define centerline for path
- var pathLeft = 150; // Start near left edge of screen
- var pathRight = SCREEN_WIDTH - 150; // Go to near right edge of screen
- var pathTop = 274; // Compressed towards center
- var pathMiddle = TOP_AREA_Y + BUILDING_AREA_HEIGHT + 77; // Center path in the new ~153px gap
- var pathBottom = BOTTOM_AREA_Y + BUILDING_AREA_HEIGHT + 100; // Position path 100px below the build area
- var laneWidth = 40; // Half the distance between the two lanes
- var L = pathLeft,
- R = pathRight,
- T = pathTop,
- M = pathMiddle,
- B = pathBottom;
- var d = laneWidth;
- // Paths for top and bottom spawns, meeting in the middle.
- // Top path
- this.pathPoints = [{
- x: L,
- y: T
- },
- // Start top-left
- {
- x: R,
- y: T
- },
- // Top-right
- {
- x: R,
- y: M - d
- },
- // Mid-right (top part)
- {
- x: L,
- y: M - d
- } // End in middle (top part)
- ];
- // Bottom path
- this.pathPoints2 = [{
- x: L,
- y: B
- },
- // Start bottom-left
- {
- x: R,
- y: B
- },
- // Bottom-right
- {
- x: R,
- y: M + d
- },
- // Mid-right (bottom part)
- {
- x: L,
- y: M + d
- } // End in middle (bottom part)
- ];
+ // Create player path (bottom area)
+ var playerStartX = PLAYER_AREA_X - 100;
+ var playerStartY = PLAYER_AREA_Y + SLOT_HEIGHT;
+ var playerEndX = PLAYER_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH + 100;
+ var playerEndY = playerStartY;
+ this.playerPath = [{
+ x: playerStartX,
+ y: playerStartY
+ }, {
+ x: playerStartX + 50,
+ y: playerStartY - 100
+ }, {
+ x: playerEndX - 50,
+ y: playerStartY - 100
+ }, {
+ x: playerEndX,
+ y: playerStartY
+ }];
+ // Create AI path (top area) - mirrored
+ var aiStartX = AI_AREA_X - 100;
+ var aiStartY = AI_AREA_Y + SLOT_HEIGHT;
+ var aiEndX = AI_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH + 100;
+ var aiEndY = aiStartY;
+ this.aiPath = [{
+ x: aiStartX,
+ y: aiStartY
+ }, {
+ x: aiStartX + 50,
+ y: aiStartY - 100
+ }, {
+ x: aiEndX - 50,
+ y: aiStartY - 100
+ }, {
+ x: aiEndX,
+ y: aiEndY
+ }];
},
- getPositionAlongPath: function getPositionAlongPath(progress, pathIndex) {
- var points = pathIndex === 1 ? this.pathPoints2 : this.pathPoints;
- if (!points) {
- points = this.pathPoints; // Fallback
- }
- if (progress <= 0) {
+ getPathStart: function getPathStart(isPlayerSide) {
+ return isPlayerSide ? this.playerPath[0] : this.aiPath[0];
+ },
+ getPositionAlongPath: function getPositionAlongPath(progress, isPlayerSide) {
+ var path = isPlayerSide ? this.playerPath : this.aiPath;
+ var pathLength = this.calculatePathLength(path);
+ var targetDistance = progress / 100 * pathLength;
+ if (targetDistance >= pathLength) {
return {
- x: points[0].x,
- y: points[0].y
+ x: path[path.length - 1].x,
+ y: path[path.length - 1].y,
+ completed: true
};
}
- if (progress >= 1) {
- return {
- x: points[points.length - 1].x,
- y: points[points.length - 1].y
- };
+ var currentDistance = 0;
+ for (var i = 0; i < path.length - 1; i++) {
+ var segmentLength = this.getDistance(path[i], path[i + 1]);
+ if (currentDistance + segmentLength >= targetDistance) {
+ var segmentProgress = (targetDistance - currentDistance) / segmentLength;
+ return {
+ x: path[i].x + (path[i + 1].x - path[i].x) * segmentProgress,
+ y: path[i].y + (path[i + 1].y - path[i].y) * segmentProgress,
+ completed: false
+ };
+ }
+ currentDistance += segmentLength;
}
- var totalSegments = points.length - 1;
- var segmentProgress = progress * totalSegments;
- var currentSegment = Math.floor(segmentProgress);
- var segmentRatio = segmentProgress - currentSegment;
- if (currentSegment >= totalSegments) {
- return {
- x: points[points.length - 1].x,
- y: points[points.length - 1].y
- };
- }
- var start = points[currentSegment];
- var end = points[currentSegment + 1];
return {
- x: start.x + (end.x - start.x) * segmentRatio,
- y: start.y + (end.y - start.y) * segmentRatio
+ x: path[path.length - 1].x,
+ y: path[path.length - 1].y,
+ completed: true
};
},
- getPathLength: function getPathLength(pathIndex) {
- var points = pathIndex === 1 ? this.pathPoints2 : this.pathPoints;
- if (!points) {
- points = this.pathPoints; // Fallback
+ calculatePathLength: function calculatePathLength(path) {
+ var total = 0;
+ for (var i = 0; i < path.length - 1; i++) {
+ total += this.getDistance(path[i], path[i + 1]);
}
- var totalLength = 0;
- for (var i = 0; i < points.length - 1; i++) {
- var dx = points[i + 1].x - points[i].x;
- var dy = points[i + 1].y - points[i].y;
- totalLength += Math.sqrt(dx * dx + dy * dy);
- }
- return totalLength;
+ return total;
+ },
+ getDistance: function getDistance(p1, p2) {
+ var dx = p2.x - p1.x;
+ var dy = p2.y - p1.y;
+ return Math.sqrt(dx * dx + dy * dy);
}
};
/****
-* Game Manager
+* Chip Spawner
****/
-var GameManager = {
- topAreaGenerateCount: 0,
- bottomAreaGenerateCount: 0,
- findEmptySpot: function findEmptySpot(area) {
- var diceArray = area === 0 ? topAreaDice : bottomAreaDice;
- if (area === 0) {
- // Top area: spawn from top-left
- for (var y = 0; y < GRID_ROWS; y++) {
- for (var x = 0; x < GRID_COLS; x++) {
- if (!diceArray[x][y]) {
- return {
- x: x,
- y: y
- };
- }
- }
- }
- } else {
- // Bottom area: spawn from bottom-left
- for (var y = GRID_ROWS - 1; y >= 0; y--) {
- for (var x = 0; x < GRID_COLS; x++) {
- if (!diceArray[x][y]) {
- return {
- x: x,
- y: y
- };
- }
- }
- }
+var ChipSpawner = {
+ spawnChip: function spawnChip(value, isPlayerSide) {
+ var chip = PoolManager.getChip();
+ if (!chip) {
+ return;
}
- return null; // No empty spot
- },
- removeDice: function removeDice(dice) {
- var diceArray = dice.area === 0 ? topAreaDice : bottomAreaDice;
- var layer = dice.area === 0 ? topAreaLayer : bottomAreaLayer;
- diceArray[dice.gridX][dice.gridY] = null;
- layer.removeChild(dice);
- PoolManager.returnClassDice(dice);
- },
- getDiceAt: function getDiceAt(area, gridX, gridY) {
- var diceArray = area === 0 ? topAreaDice : bottomAreaDice;
- return diceArray[gridX] && diceArray[gridX][gridY];
- },
- getGenerateCount: function getGenerateCount(area) {
- return area === 0 ? this.topAreaGenerateCount : this.bottomAreaGenerateCount;
- },
- incrementGenerateCount: function incrementGenerateCount(area) {
- if (area === 0) {
- this.topAreaGenerateCount++;
+ chip.activate(value, isPlayerSide);
+ gameLayer.addChild(chip);
+ if (isPlayerSide) {
+ activePlayerChips.push(chip);
} else {
- this.bottomAreaGenerateCount++;
+ activeAIChips.push(chip);
}
}
};
/****
-* Game Constants - ACTUALLY USE THE FULL SCREEN
+* Game State
****/
-var CELL_SIZE = 288; // Shrunk 10% from 320
-var GRID_COLS = 5;
-var GRID_ROWS = 3;
-var SCREEN_WIDTH = 2048;
-var SCREEN_HEIGHT = 2732;
-// Actually use the full screen dimensions
-var BUILDING_AREA_WIDTH = GRID_COLS * CELL_SIZE; // 1440px wide
-var BUILDING_AREA_HEIGHT = GRID_ROWS * CELL_SIZE; // 864px tall
-// Center the building areas in the screen with proper spacing
-var TOP_AREA_X = (SCREEN_WIDTH - BUILDING_AREA_WIDTH) / 2; // ~304px from left
-var TOP_AREA_Y = 372; // Repositioned to center in battlement
-var BOTTOM_AREA_X = TOP_AREA_X - SCREEN_WIDTH * 0.01; // Move left 1% of screen width
-var BOTTOM_AREA_Y = TOP_AREA_Y + BUILDING_AREA_HEIGHT + 249 - SCREEN_HEIGHT * 0.01; // Move up 1% of screen height
-// Path uses much more of the screen
-var PATH_MARGIN = 200; // Bigger margins for wider paths
+var gameState = {
+ playerGold: 100,
+ aiGold: 100,
+ playerLives: 3,
+ aiLives: 3,
+ isPlayerTurn: true,
+ dealCost: 50,
+ dealCount: 0,
+ playerDeck: [],
+ playerHand: [],
+ playerPlayArea: [],
+ // 2D array [row][col]
+ aiDeck: [],
+ aiPlayArea: []
+};
/****
* Game Variables
****/
-var gold = 100;
-var lives = 20;
-var score = 0;
-var activeBlobs = [];
+var activePlayerChips = [];
+var activeAIChips = [];
var activeBullets = [];
-var topAreaDice = [];
-var bottomAreaDice = [];
-var selectedDice = null;
+var selectedCard = null;
var isDragging = false;
-var dragStartPos = {
- x: 0,
- y: 0
-};
+var gameLayer = new Container();
+var uiLayer = new Container();
+game.addChild(gameLayer);
+game.addChild(uiLayer);
/****
-* Initialize Arrays
-****/
-for (var x = 0; x < GRID_COLS; x++) {
- topAreaDice[x] = [];
- bottomAreaDice[x] = [];
- for (var y = 0; y < GRID_ROWS; y++) {
- topAreaDice[x][y] = null;
- bottomAreaDice[x][y] = null;
- }
-}
-/****
* UI Elements
****/
-var goldText = new Text2('Gold: ' + gold, {
- size: 60,
- fill: 0xFFD700,
+var playerGoldText = new Text2('Gold: 100', {
+ size: 50,
+ fill: 0xffd700,
weight: 800
});
-goldText.anchor.set(0.5, 0.5);
-var livesText = new Text2('Lives: ' + lives, {
- size: 60,
- fill: 0x00FF00,
+playerGoldText.x = 50;
+playerGoldText.y = SCREEN_HEIGHT - 100;
+uiLayer.addChild(playerGoldText);
+var playerLivesText = new Text2('Lives: 3', {
+ size: 50,
+ fill: 0xff0000,
weight: 800
});
-livesText.anchor.set(0.5, 0.5);
-var scoreText = new Text2('Score: ' + score, {
- size: 60,
- fill: 0xFF0000,
+playerLivesText.x = 50;
+playerLivesText.y = SCREEN_HEIGHT - 150;
+uiLayer.addChild(playerLivesText);
+var dealButton = new Container();
+var dealButtonGraphics = dealButton.attachAsset('dealButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+var dealButtonText = new Text2('Deal (50)', {
+ size: 40,
+ fill: 0xffffff,
weight: 800
});
-scoreText.anchor.set(0.5, 0.5);
-LK.gui.top.addChild(goldText);
-LK.gui.top.addChild(livesText);
-LK.gui.top.addChild(scoreText);
-goldText.x = -400;
-goldText.y = 50;
-livesText.x = 0;
-livesText.y = 50;
-scoreText.x = 400;
-scoreText.y = 50;
-function updateUI() {
- goldText.setText('Gold: ' + gold);
- livesText.setText('Lives: ' + lives);
- scoreText.setText('Score: ' + score);
-}
-function setGold(value) {
- gold = value;
- updateUI();
-}
+dealButtonText.anchor.set(0.5, 0.5);
+dealButton.addChild(dealButtonText);
+dealButton.x = SCREEN_WIDTH / 2;
+dealButton.y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT + 50;
+uiLayer.addChild(dealButton);
+dealButton.down = function () {
+ if (gameState.playerGold >= gameState.dealCost) {
+ dealNewHand();
+ }
+};
/****
-* Layer Setup
+* Game Functions
****/
-var gameLayer = new Container();
-var topAreaLayer = new Container();
-var bottomAreaLayer = new Container();
-var effectLayer = new Container();
-game.addChild(gameLayer);
-game.addChild(topAreaLayer);
-game.addChild(bottomAreaLayer);
-game.addChild(effectLayer);
-/****
-* Generate Buttons - PROPERLY POSITIONED
-****/
-var topGenerateButton = new GenerateButton(0);
-topGenerateButton.x = TOP_AREA_X + BUILDING_AREA_WIDTH + 100;
-topGenerateButton.y = TOP_AREA_Y + BUILDING_AREA_HEIGHT / 2;
-game.addChild(topGenerateButton);
-var bottomGenerateButton = new GenerateButton(1);
-bottomGenerateButton.x = BOTTOM_AREA_X + BUILDING_AREA_WIDTH + 100;
-bottomGenerateButton.y = BOTTOM_AREA_Y + BUILDING_AREA_HEIGHT / 2;
-game.addChild(bottomGenerateButton);
-/****
-* Wave Manager - BOTTOM OF SCREEN
-****/
-var waveManager = new WaveManager();
-waveManager.x = SCREEN_WIDTH / 2;
-waveManager.y = SCREEN_HEIGHT - 200; // Actually near bottom of screen
-game.addChild(waveManager);
-/****
-* Input Handling
-****/
-game.down = function (x, y, obj) {
- // Check if clicking on a dice
- var clickedDice = null;
- var clickedArea = -1;
- // Check top area
- if (x >= TOP_AREA_X && x <= TOP_AREA_X + GRID_COLS * CELL_SIZE && y >= TOP_AREA_Y && y <= TOP_AREA_Y + GRID_ROWS * CELL_SIZE) {
- var gridX = Math.floor((x - TOP_AREA_X) / CELL_SIZE);
- var gridY = Math.floor((y - TOP_AREA_Y) / CELL_SIZE);
- clickedDice = GameManager.getDiceAt(0, gridX, gridY);
- clickedArea = 0;
+function initializeGame() {
+ PoolManager.init();
+ PathSystem.init();
+ // Initialize play areas
+ gameState.playerPlayArea = [];
+ gameState.aiPlayArea = [];
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ gameState.playerPlayArea[row] = [];
+ gameState.aiPlayArea[row] = [];
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ gameState.playerPlayArea[row][col] = null;
+ gameState.aiPlayArea[row][col] = null;
+ }
}
- // Check bottom area
- if (!clickedDice && x >= BOTTOM_AREA_X && x <= BOTTOM_AREA_X + GRID_COLS * CELL_SIZE && y >= BOTTOM_AREA_Y && y <= BOTTOM_AREA_Y + GRID_ROWS * CELL_SIZE) {
- var gridX = Math.floor((x - BOTTOM_AREA_X) / CELL_SIZE);
- var gridY = Math.floor((y - BOTTOM_AREA_Y) / CELL_SIZE);
- clickedDice = GameManager.getDiceAt(1, gridX, gridY);
- clickedArea = 1;
+ // Create initial decks
+ gameState.playerDeck = CardSystem.createDeck();
+ gameState.aiDeck = CardSystem.createDeck();
+ // Draw grid lines
+ drawPlayAreas();
+ drawPaths();
+ // Deal initial hand
+ dealNewHand();
+ // Start spawning chips
+ setTimeout(function () {
+ ChipSpawner.spawnChip(5, false); // Spawn on AI side
+ }, 2000);
+}
+function dealNewHand() {
+ if (gameState.playerGold < gameState.dealCost) {
+ return;
}
- if (clickedDice) {
- selectedDice = clickedDice;
- isDragging = true;
- dragStartPos.x = x;
- dragStartPos.y = y;
- selectedDice.isDragging = true;
- // Bring to front by moving to the main game container
- var layer = selectedDice.area === 0 ? topAreaLayer : bottomAreaLayer;
- layer.removeChild(selectedDice);
- game.addChild(selectedDice);
- }
-};
-game.move = function (x, y, obj) {
- if (isDragging && selectedDice) {
- selectedDice.x = selectedDice.x + (x - dragStartPos.x);
- selectedDice.y = selectedDice.y + (y - dragStartPos.y);
- dragStartPos.x = x;
- dragStartPos.y = y;
- // Check for magnetic attraction
- var diceArray = selectedDice.area === 0 ? topAreaDice : bottomAreaDice;
- for (var gx = 0; gx < GRID_COLS; gx++) {
- for (var gy = 0; gy < GRID_ROWS; gy++) {
- var otherDice = diceArray[gx][gy];
- if (otherDice && otherDice !== selectedDice) {
- selectedDice.checkMagneticAttraction(otherDice);
- }
- }
+ gameState.playerGold -= gameState.dealCost;
+ gameState.dealCount++;
+ gameState.dealCost = Math.floor(50 * Math.pow(1.2, gameState.dealCount));
+ // Clear current hand
+ gameState.playerHand.forEach(function (card) {
+ if (card) {
+ uiLayer.removeChild(card);
}
+ });
+ gameState.playerHand = [];
+ // Deal 5 new cards
+ for (var i = 0; i < 5; i++) {
+ if (gameState.playerDeck.length === 0) {
+ gameState.playerDeck = CardSystem.createDeck();
+ }
+ var cardData = gameState.playerDeck.pop();
+ var card = new Card(cardData);
+ var slotX = PLAYER_AREA_X + i * DEAL_SLOT_WIDTH + i * 20 + DEAL_SLOT_WIDTH / 2;
+ var slotY = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2;
+ card.activate(slotX, slotY, false);
+ uiLayer.addChild(card);
+ gameState.playerHand[i] = card;
}
-};
-game.up = function (x, y, obj) {
- if (isDragging && selectedDice) {
- isDragging = false;
- selectedDice.isDragging = false;
- // Check for merge
- var mergeHappened = false;
- var targetArea = -1;
- // Determine which area we're over
- if (x >= TOP_AREA_X && x <= TOP_AREA_X + GRID_COLS * CELL_SIZE && y >= TOP_AREA_Y && y <= TOP_AREA_Y + GRID_ROWS * CELL_SIZE) {
- targetArea = 0;
- } else if (x >= BOTTOM_AREA_X && x <= BOTTOM_AREA_X + GRID_COLS * CELL_SIZE && y >= BOTTOM_AREA_Y && y <= BOTTOM_AREA_Y + GRID_ROWS * CELL_SIZE) {
- targetArea = 1;
+ updateUI();
+}
+function updateUI() {
+ playerGoldText.setText('Gold: ' + gameState.playerGold);
+ playerLivesText.setText('Lives: ' + gameState.playerLives);
+ dealButtonText.setText('Deal (' + gameState.dealCost + ')');
+ // Update button color based on affordability
+ if (gameState.playerGold >= gameState.dealCost) {
+ dealButtonGraphics.tint = 0x00aa00;
+ } else {
+ dealButtonGraphics.tint = 0x666666;
+ }
+}
+function drawPlayAreas() {
+ // Draw player play area slots
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ var slot = new Container();
+ var slotGraphics = slot.attachAsset('playSlot', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ slotGraphics.alpha = 0.3;
+ slot.x = PLAYER_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH / 2;
+ slot.y = PLAYER_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT / 2;
+ gameLayer.addChild(slot);
}
- if (targetArea !== -1) {
- var gridX = Math.floor((x - (targetArea === 0 ? TOP_AREA_X : BOTTOM_AREA_X)) / CELL_SIZE);
- var gridY = Math.floor((y - (targetArea === 0 ? TOP_AREA_Y : BOTTOM_AREA_Y)) / CELL_SIZE);
- if (gridX >= 0 && gridX < GRID_COLS && gridY >= 0 && gridY < GRID_ROWS) {
- var targetDice = GameManager.getDiceAt(targetArea, gridX, gridY);
- if (targetDice && selectedDice.canMergeWith(targetDice)) {
- // Merge the dice
- mergeHappened = selectedDice.mergeWith(targetDice);
- }
- }
- }
- game.removeChild(selectedDice);
- if (!mergeHappened) {
- // Return dice to original layer and position
- var layer = selectedDice.area === 0 ? topAreaLayer : bottomAreaLayer;
- layer.addChild(selectedDice);
- selectedDice.updatePosition();
- // Smooth return animation
- tween(selectedDice, {
- x: selectedDice.area === 0 ? TOP_AREA_X + selectedDice.gridX * CELL_SIZE + CELL_SIZE / 2 : BOTTOM_AREA_X + selectedDice.gridX * CELL_SIZE + CELL_SIZE / 2,
- y: selectedDice.area === 0 ? TOP_AREA_Y + selectedDice.gridY * CELL_SIZE + CELL_SIZE / 2 : BOTTOM_AREA_Y + selectedDice.gridY * CELL_SIZE + CELL_SIZE / 2
- }, {
- duration: 300,
- easing: tween.elasticOut
+ }
+ // Draw AI play area slots
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ var slot = new Container();
+ var slotGraphics = slot.attachAsset('playSlot', {
+ anchorX: 0.5,
+ anchorY: 0.5
});
+ slotGraphics.alpha = 0.3;
+ slotGraphics.tint = 0x440000; // Red tint for AI area
+ slot.x = AI_AREA_X + col * SLOT_WIDTH + SLOT_WIDTH / 2;
+ slot.y = AI_AREA_Y + row * SLOT_HEIGHT + SLOT_HEIGHT / 2;
+ gameLayer.addChild(slot);
}
- selectedDice.magneticTarget = null;
- selectedDice = null;
}
-};
-/****
-* Grid Visual Indicators
-****/
-function drawGridLines() {
- // Add battlement backgrounds
- var topBattlement = gameLayer.attachAsset('battlements', {
- anchorX: 0,
- anchorY: 0
- });
- topBattlement.width = 1600;
- topBattlement.height = 960;
- topBattlement.x = 224;
- topBattlement.y = 324;
- var bottomBattlement = gameLayer.attachAsset('battlements', {
- anchorX: 0,
- anchorY: 0
- });
- bottomBattlement.width = 1600;
- bottomBattlement.height = 970;
- bottomBattlement.x = 224;
- bottomBattlement.y = 1437;
- // Top area grid
- for (var x = 0; x <= GRID_COLS; x++) {
- var line = new Container();
- var lineGraphics = line.attachAsset('cell', {
- anchorX: 0,
- anchorY: 0
+ // Draw player deal area slots
+ for (var i = 0; i < 5; i++) {
+ var dealSlot = new Container();
+ var dealSlotGraphics = dealSlot.attachAsset('dealSlot', {
+ anchorX: 0.5,
+ anchorY: 0.5
});
- lineGraphics.width = 2;
- lineGraphics.height = GRID_ROWS * CELL_SIZE;
- lineGraphics.tint = 0x444444;
- lineGraphics.alpha = 0.3;
- line.x = TOP_AREA_X + x * CELL_SIZE;
- line.y = TOP_AREA_Y;
- gameLayer.addChild(line);
+ dealSlotGraphics.alpha = 0.2;
+ dealSlot.x = PLAYER_AREA_X + i * DEAL_SLOT_WIDTH + i * 20 + DEAL_SLOT_WIDTH / 2;
+ dealSlot.y = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2;
+ gameLayer.addChild(dealSlot);
}
- for (var y = 0; y <= GRID_ROWS; y++) {
- var line = new Container();
- var lineGraphics = line.attachAsset('cell', {
- anchorX: 0,
- anchorY: 0
- });
- lineGraphics.width = GRID_COLS * CELL_SIZE;
- lineGraphics.height = 2;
- lineGraphics.tint = 0x444444;
- lineGraphics.alpha = 0.3;
- line.x = TOP_AREA_X;
- line.y = TOP_AREA_Y + y * CELL_SIZE;
- gameLayer.addChild(line);
+}
+function drawPaths() {
+ // Draw player path
+ for (var i = 0; i < PathSystem.playerPath.length - 1; i++) {
+ var start = PathSystem.playerPath[i];
+ var end = PathSystem.playerPath[i + 1];
+ drawPathSegment(start, end, 0x666666);
}
- // Bottom area grid
- for (var x = 0; x <= GRID_COLS; x++) {
- var line = new Container();
- var lineGraphics = line.attachAsset('cell', {
- anchorX: 0,
- anchorY: 0
- });
- lineGraphics.width = 2;
- lineGraphics.height = GRID_ROWS * CELL_SIZE;
- lineGraphics.tint = 0x444444;
- lineGraphics.alpha = 0.3;
- line.x = BOTTOM_AREA_X + x * CELL_SIZE;
- line.y = BOTTOM_AREA_Y;
- gameLayer.addChild(line);
+ // Draw AI path
+ for (var i = 0; i < PathSystem.aiPath.length - 1; i++) {
+ var start = PathSystem.aiPath[i];
+ var end = PathSystem.aiPath[i + 1];
+ drawPathSegment(start, end, 0x664444);
}
- for (var y = 0; y <= GRID_ROWS; y++) {
- var line = new Container();
- var lineGraphics = line.attachAsset('cell', {
- anchorX: 0,
- anchorY: 0
+}
+function drawPathSegment(start, end, color) {
+ var dx = end.x - start.x;
+ var dy = end.y - start.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ var segments = Math.floor(distance / 20);
+ for (var i = 0; i <= segments; i++) {
+ var progress = i / segments;
+ var x = start.x + dx * progress;
+ var y = start.y + dy * progress;
+ var pathDot = new Container();
+ var dotGraphics = pathDot.attachAsset('pathSegment', {
+ anchorX: 0.5,
+ anchorY: 0.5
});
- lineGraphics.width = GRID_COLS * CELL_SIZE;
- lineGraphics.height = 2;
- lineGraphics.tint = 0x444444;
- lineGraphics.alpha = 0.3;
- line.x = BOTTOM_AREA_X;
- line.y = BOTTOM_AREA_Y + y * CELL_SIZE;
- gameLayer.addChild(line);
+ dotGraphics.width = dotGraphics.height = 8;
+ dotGraphics.tint = color;
+ dotGraphics.alpha = 0.6;
+ pathDot.x = x;
+ pathDot.y = y;
+ gameLayer.addChild(pathDot);
}
}
-/****
-* Path Visualization
-****/
-function drawPath() {
- var paths = [PathSystem.pathPoints, PathSystem.pathPoints2];
- for (var p = 0; p < paths.length; p++) {
- var currentPath = paths[p];
- for (var i = 0; i < currentPath.length - 1; i++) {
- var start = currentPath[i];
- var end = currentPath[i + 1];
- var dx = end.x - start.x;
- var dy = end.y - start.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- var segments = Math.floor(distance / 20);
- for (var j = 0; j < segments; j++) {
- var progress = j / segments;
- var x = start.x + dx * progress;
- var y = start.y + dy * progress;
- var pathDot = new Container();
- var dotGraphics = pathDot.attachAsset('particle', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- dotGraphics.width = dotGraphics.height = 8;
- dotGraphics.tint = 0x666666;
- dotGraphics.alpha = 0.6;
- pathDot.x = x;
- pathDot.y = y;
- gameLayer.addChild(pathDot);
- }
+function getSlotPosition(row, col, isPlayerArea) {
+ var baseX = isPlayerArea ? PLAYER_AREA_X : AI_AREA_X;
+ var baseY = isPlayerArea ? PLAYER_AREA_Y : AI_AREA_Y;
+ return {
+ x: baseX + col * SLOT_WIDTH + SLOT_WIDTH / 2,
+ y: baseY + row * SLOT_HEIGHT + SLOT_HEIGHT / 2
+ };
+}
+function getSlotFromPosition(x, y) {
+ // Check player play area
+ if (x >= PLAYER_AREA_X && x <= PLAYER_AREA_X + PLAY_AREA_COLS * SLOT_WIDTH && y >= PLAYER_AREA_Y && y <= PLAYER_AREA_Y + PLAY_AREA_ROWS * SLOT_HEIGHT) {
+ var col = Math.floor((x - PLAYER_AREA_X) / SLOT_WIDTH);
+ var row = Math.floor((y - PLAYER_AREA_Y) / SLOT_HEIGHT);
+ if (col >= 0 && col < PLAY_AREA_COLS && row >= 0 && row < PLAY_AREA_ROWS) {
+ return {
+ area: 'player',
+ row: row,
+ col: col
+ };
}
}
+ return null;
}
-/****
-* Initialization
-****/
-PoolManager.init();
-PathSystem.init();
-drawGridLines();
-drawPath();
-// Start first wave after a delay
-waveManager.waveTimer = 240; // 4 second delay before first wave
-/****
-* Main Game Loop
-****/
-game.update = function () {
- // Update active blobs
- for (var i = activeBlobs.length - 1; i >= 0; i--) {
- var blob = activeBlobs[i];
- if (blob.active) {
- blob.update();
- } else {
- activeBlobs.splice(i, 1);
- gameLayer.removeChild(blob);
+function evaluateRowHand(row, isPlayerArea) {
+ var playArea = isPlayerArea ? gameState.playerPlayArea : gameState.aiPlayArea;
+ var cards = [];
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ if (playArea[row][col]) {
+ cards.push(playArea[row][col].cardData);
}
}
- // Update active bullets
- for (var i = activeBullets.length - 1; i >= 0; i--) {
- var bullet = activeBullets[i];
- if (bullet.active) {
- bullet.update();
- } else {
- activeBullets.splice(i, 1);
- gameLayer.removeChild(bullet);
- }
+ if (cards.length === 5) {
+ return CardSystem.evaluatePokerHand(cards);
}
- // Update all dice
- for (var x = 0; x < GRID_COLS; x++) {
- for (var y = 0; y < GRID_ROWS; y++) {
- if (topAreaDice[x][y]) {
- topAreaDice[x][y].update();
+ return {
+ type: 'none',
+ strength: 0,
+ multiplier: 1
+ };
+}
+function applyHandBonuses() {
+ // Apply bonuses to player cards
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ var handEval = evaluateRowHand(row, true);
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ var card = gameState.playerPlayArea[row][col];
+ if (card) {
+ card.handBonus = handEval.multiplier;
+ card.calculateStats();
}
- if (bottomAreaDice[x][y]) {
- bottomAreaDice[x][y].update();
- }
}
}
- // Update active particles
- var allParticles = gameLayer.children.filter(function (child) {
- return child instanceof DeathParticle;
- });
- for (var i = 0; i < allParticles.length; i++) {
- allParticles[i].update();
- }
- // Update active effects
- var allEffects = gameLayer.children.filter(function (child) {
- return child instanceof EffectIndicator;
- });
- for (var i = 0; i < allEffects.length; i++) {
- if (allEffects[i] && typeof allEffects[i].update === 'function') {
- allEffects[i].update();
+ // Apply bonuses to AI cards
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ var handEval = evaluateRowHand(row, false);
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ var card = gameState.aiPlayArea[row][col];
+ if (card) {
+ card.handBonus = handEval.multiplier;
+ card.calculateStats();
+ }
}
}
- // Update notifications
- var allNotifications = gameLayer.children.filter(function (child) {
- return child instanceof Notification;
- });
- for (var i = 0; i < allNotifications.length; i++) {
- allNotifications[i].update();
- }
- // Update wave manager
- waveManager.update();
- // Update generate buttons
- topGenerateButton.update();
- bottomGenerateButton.update();
- // Check win condition
- if (waveManager.currentWave >= waveManager.maxWaves && activeBlobs.length === 0) {
- LK.showYouWin();
- }
- // Check lose condition
- if (lives <= 0) {
- LK.showGameOver();
- }
- updateUI();
-};
-/****
-* Debug Features (Remove in production)
-****/
-if (LK.debug) {
- // Add some starting dice for testing
- setTimeout(function () {
- var testDice1 = PoolManager.getClassDice();
- if (testDice1) {
- testDice1.activate('knifethrower', 1, 1, 0);
- topAreaLayer.addChild(testDice1);
- topAreaDice[1][1] = testDice1;
- }
- var testDice2 = PoolManager.getClassDice();
- if (testDice2) {
- testDice2.activate('archer', 3, 1, 1);
- bottomAreaLayer.addChild(testDice2);
- bottomAreaDice[3][1] = testDice2;
- }
- }, 1000);
}
/****
-* Performance Monitoring (Optional)
+* AI System
****/
-var PerformanceMonitor = {
- frameCount: 0,
- lastTime: Date.now(),
- fps: 60,
+var AISystem = {
+ thinkTimer: 0,
+ thinkDelay: 120,
+ // 2 seconds
update: function update() {
- this.frameCount++;
- var currentTime = Date.now();
- if (currentTime - this.lastTime >= 1000) {
- this.fps = this.frameCount;
- this.frameCount = 0;
- this.lastTime = currentTime;
- // Log performance warnings
- if (this.fps < 30) {
- console.warn('Low FPS detected:', this.fps);
- console.log('Active objects - Blobs:', activeBlobs.length, 'Bullets:', activeBullets.length);
+ if (gameState.isPlayerTurn) {
+ return;
+ }
+ this.thinkTimer++;
+ if (this.thinkTimer >= this.thinkDelay) {
+ this.thinkTimer = 0;
+ this.makeMove();
+ }
+ },
+ makeMove: function makeMove() {
+ // Simple AI: deal new hand if can afford it
+ if (gameState.aiGold >= gameState.dealCost) {
+ this.dealAIHand();
+ }
+ // Try to place cards from AI hand to play area
+ this.tryPlaceCards();
+ // Spawn some chips on player side
+ if (Math.random() < 0.3) {
+ ChipSpawner.spawnChip(Math.floor(Math.random() * 3) + 1, true);
+ }
+ gameState.isPlayerTurn = true;
+ },
+ dealAIHand: function dealAIHand() {
+ gameState.aiGold -= gameState.dealCost;
+ // Deal cards directly to AI play area
+ for (var attempt = 0; attempt < 5; attempt++) {
+ if (gameState.aiDeck.length === 0) {
+ gameState.aiDeck = CardSystem.createDeck();
}
+ var cardData = gameState.aiDeck.pop();
+ var card = new Card(cardData);
+ // Find empty slot
+ var placed = false;
+ for (var row = 0; row < PLAY_AREA_ROWS && !placed; row++) {
+ for (var col = 0; col < PLAY_AREA_COLS && !placed; col++) {
+ if (!gameState.aiPlayArea[row][col]) {
+ var pos = getSlotPosition(row, col, false);
+ card.activate(pos.x, pos.y, true);
+ gameLayer.addChild(card);
+ gameState.aiPlayArea[row][col] = card;
+ placed = true;
+ }
+ }
+ }
+ if (!placed) {
+ break;
+ } // No more space
}
+ },
+ tryPlaceCards: function tryPlaceCards() {
+ // AI logic for placing cards (simplified)
+ // In a full implementation, this would be more sophisticated
}
};
-// Add performance monitoring to game loop if in debug mode
-if (LK.debug) {
- var originalUpdate = game.update;
- game.update = function () {
- PerformanceMonitor.update();
- originalUpdate.call(this);
- };
-}
/****
-* Utility Functions
+* Input Handling
****/
-function getDistanceBetweenPoints(p1, p2) {
- var dx = p2.x - p1.x;
- var dy = p2.y - p1.y;
- return Math.sqrt(dx * dx + dy * dy);
-}
-function clamp(value, min, max) {
- return Math.max(min, Math.min(max, value));
-}
-function lerp(start, end, factor) {
- return start + (end - start) * factor;
-}
-// Fibonacci sequence for costs
-function fibonacci(n) {
- if (n <= 1) {
- return 1;
+game.down = function (x, y, obj) {
+ // Check if clicking on a card in hand
+ for (var i = 0; i < gameState.playerHand.length; i++) {
+ var card = gameState.playerHand[i];
+ if (card && Math.abs(x - card.x) < DEAL_SLOT_WIDTH / 2 && Math.abs(y - card.y) < DEAL_SLOT_HEIGHT / 2) {
+ selectedCard = card;
+ isDragging = true;
+ return;
+ }
}
- var a = 1,
- b = 1;
- for (var i = 2; i <= n; i++) {
- var temp = a + b;
- a = b;
- b = temp;
+ // Check if clicking on a card in play area
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ var card = gameState.playerPlayArea[row][col];
+ if (card && Math.abs(x - card.x) < SLOT_WIDTH / 2 && Math.abs(y - card.y) < SLOT_HEIGHT / 2) {
+ selectedCard = card;
+ isDragging = true;
+ // Remove from current position
+ gameState.playerPlayArea[row][col] = null;
+ return;
+ }
+ }
}
- return b;
+};
+game.move = function (x, y, obj) {
+ if (isDragging && selectedCard) {
+ selectedCard.x = x;
+ selectedCard.y = y;
+ }
+};
+game.up = function (x, y, obj) {
+ if (isDragging && selectedCard) {
+ isDragging = false;
+ var targetSlot = getSlotFromPosition(x, y);
+ if (targetSlot && targetSlot.area === 'player') {
+ var existingCard = gameState.playerPlayArea[targetSlot.row][targetSlot.col];
+ if (existingCard && selectedCard.canMergeWith(existingCard)) {
+ // Merge cards
+ var mergedCard = selectedCard.mergeWith(existingCard);
+ if (mergedCard) {
+ // Remove old cards
+ gameLayer.removeChild(existingCard);
+ var handIndex = gameState.playerHand.indexOf(selectedCard);
+ if (handIndex !== -1) {
+ uiLayer.removeChild(selectedCard);
+ gameState.playerHand[handIndex] = null;
+ }
+ // Place merged card
+ var pos = getSlotPosition(targetSlot.row, targetSlot.col, true);
+ mergedCard.activate(pos.x, pos.y, true);
+ gameLayer.addChild(mergedCard);
+ gameState.playerPlayArea[targetSlot.row][targetSlot.col] = mergedCard;
+ }
+ } else if (!existingCard) {
+ // Place card in empty slot
+ var pos = getSlotPosition(targetSlot.row, targetSlot.col, true);
+ selectedCard.activate(pos.x, pos.y, true);
+ // Remove from hand if it was in hand
+ var handIndex = gameState.playerHand.indexOf(selectedCard);
+ if (handIndex !== -1) {
+ uiLayer.removeChild(selectedCard);
+ gameLayer.addChild(selectedCard);
+ gameState.playerHand[handIndex] = null;
+ }
+ gameState.playerPlayArea[targetSlot.row][targetSlot.col] = selectedCard;
+ } else {
+ // Return to original position
+ returnCardToOriginalPosition();
+ }
+ } else {
+ // Return to original position
+ returnCardToOriginalPosition();
+ }
+ selectedCard = null;
+ applyHandBonuses();
+ }
+};
+function returnCardToOriginalPosition() {
+ var handIndex = gameState.playerHand.indexOf(selectedCard);
+ if (handIndex !== -1) {
+ // Return to hand
+ var slotX = PLAYER_AREA_X + handIndex * DEAL_SLOT_WIDTH + handIndex * 20 + DEAL_SLOT_WIDTH / 2;
+ var slotY = PLAYER_DEAL_AREA_Y + DEAL_SLOT_HEIGHT / 2;
+ selectedCard.x = slotX;
+ selectedCard.y = slotY;
+ }
}
/****
-* Effects and Polish
+* Main Game Loop
****/
-function createScreenShake(intensity, duration) {
- var originalX = game.x;
- var originalY = game.y;
- var shakeTimer = duration;
- var _shakeUpdate = function shakeUpdate() {
- if (shakeTimer > 0) {
- game.x = originalX + (Math.random() - 0.5) * intensity;
- game.y = originalY + (Math.random() - 0.5) * intensity;
- shakeTimer--;
- requestAnimationFrame(_shakeUpdate);
- } else {
- game.x = originalX;
- game.y = originalY;
+game.update = function () {
+ // Update active chips
+ for (var i = activePlayerChips.length - 1; i >= 0; i--) {
+ activePlayerChips[i].update();
+ }
+ for (var i = activeAIChips.length - 1; i >= 0; i--) {
+ activeAIChips[i].update();
+ }
+ // Update active bullets
+ for (var i = activeBullets.length - 1; i >= 0; i--) {
+ activeBullets[i].update();
+ }
+ // Update cards in play
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ for (var col = 0; col < PLAY_AREA_COLS; col++) {
+ if (gameState.playerPlayArea[row][col]) {
+ gameState.playerPlayArea[row][col].update();
+ }
+ if (gameState.aiPlayArea[row][col]) {
+ gameState.aiPlayArea[row][col].update();
+ }
}
- };
- _shakeUpdate();
-}
-function createFloatingText(text, x, y, color) {
- var floatingText = new Text2(text, {
- size: 40,
- fill: color || 0xFFFFFF,
- weight: 800
- });
- floatingText.anchor.set(0.5, 0.5);
- floatingText.x = x;
- floatingText.y = y;
- floatingText.alpha = 1;
- gameLayer.addChild(floatingText);
- tween(floatingText, {
- y: y - 50,
- alpha: 0
- }, {
- duration: 1000,
- easing: tween.quadOut,
- onFinish: function onFinish() {
- gameLayer.removeChild(floatingText);
- }
- });
-}
+ }
+ // Update AI
+ AISystem.update();
+ // Check win/lose conditions
+ if (gameState.playerLives <= 0) {
+ showGameOver(false);
+ } else if (gameState.aiLives <= 0) {
+ showGameOver(true);
+ }
+ updateUI();
+};
/****
-* Game Over and Victory Screens
+* Game Over
****/
-LK.showGameOver = function () {
+function showGameOver(playerWon) {
var overlay = new Container();
- var bg = overlay.attachAsset('notification', {
+ var bg = overlay.attachAsset('playSlot', {
anchorX: 0.5,
anchorY: 0.5
});
bg.width = SCREEN_WIDTH;
bg.height = SCREEN_HEIGHT;
bg.tint = 0x000000;
bg.alpha = 0.8;
- var gameOverText = new Text2('GAME OVER', {
+ var resultText = new Text2(playerWon ? 'YOU WIN!' : 'YOU LOSE!', {
size: 100,
- fill: 0xFF0000,
+ fill: playerWon ? 0x00ff00 : 0xff0000,
weight: 800
});
- gameOverText.anchor.set(0.5, 0.5);
- gameOverText.y = -100;
- overlay.addChild(gameOverText);
- var finalScoreText = new Text2('Final Score: ' + score, {
- size: 60,
- fill: 0xFFFFFF,
- weight: 600
- });
- finalScoreText.anchor.set(0.5, 0.5);
- finalScoreText.y = 0;
- overlay.addChild(finalScoreText);
+ resultText.anchor.set(0.5, 0.5);
+ overlay.addChild(resultText);
var restartText = new Text2('Tap to Restart', {
- size: 50,
- fill: 0x00FF00,
- weight: 600
- });
- restartText.anchor.set(0.5, 0.5);
- restartText.y = 100;
- overlay.addChild(restartText);
- overlay.x = SCREEN_WIDTH / 2;
- overlay.y = SCREEN_HEIGHT / 2;
- game.addChild(overlay);
- overlay.down = function () {
- location.reload(); // Simple restart
- };
-};
-LK.showYouWin = function () {
- var overlay = new Container();
- var bg = overlay.attachAsset('notification', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- bg.width = SCREEN_WIDTH;
- bg.height = SCREEN_HEIGHT;
- bg.tint = 0x000000;
- bg.alpha = 0.8;
- var victoryText = new Text2('VICTORY!', {
- size: 100,
- fill: 0x00FF00,
- weight: 800
- });
- victoryText.anchor.set(0.5, 0.5);
- victoryText.y = -100;
- overlay.addChild(victoryText);
- var finalScoreText = new Text2('Final Score: ' + score, {
size: 60,
- fill: 0xFFFFFF,
+ fill: 0xffffff,
weight: 600
});
- finalScoreText.anchor.set(0.5, 0.5);
- finalScoreText.y = 0;
- overlay.addChild(finalScoreText);
- var restartText = new Text2('Tap to Play Again', {
- size: 50,
- fill: 0x00FF00,
- weight: 600
- });
restartText.anchor.set(0.5, 0.5);
restartText.y = 100;
overlay.addChild(restartText);
overlay.x = SCREEN_WIDTH / 2;
overlay.y = SCREEN_HEIGHT / 2;
game.addChild(overlay);
overlay.down = function () {
- location.reload(); // Simple restart
+ location.reload();
};
- // Victory animation
- tween(victoryText, {
- scaleX: 1.2,
- scaleY: 1.2
- }, {
- duration: 500,
- easing: tween.elasticOut,
- repeat: -1,
- yoyo: true
- });
-};
\ No newline at end of file
+}
+/****
+* Utility Functions
+****/
+function displayHandInfo() {
+ // Show current poker hand evaluations for debugging
+ for (var row = 0; row < PLAY_AREA_ROWS; row++) {
+ var handEval = evaluateRowHand(row, true);
+ console.log('Player Row ' + row + ':', handEval.type, 'Multiplier:', handEval.multiplier);
+ }
+}
+initializeGame();
\ No newline at end of file
A long rack of different colored poker chips seen from above. Anime style.. In-Game asset. 2d. High contrast. No shadows
A graphic for the center of a joker card.
a 2:3 format thin black border with nothing in the center. In-Game asset. 2d. High contrast. No shadows
A small white explosion particle.. In-Game asset. 2d. High contrast. No shadows
Make the blue a lighter blue.
Make this in a white instead of blue. Keep everything else the same.
A couple different sized stacks of these chips beside each other.
Just the spade from this picture with a blue snowflake in the middle of it.
Just the heart from this picture with a flame in the cent t of it.
Just the club from this picture with 1. **Fan/Spray Symbol** - Three or more lines radiating outward from a central point, yellow in color, in the center of the club.
Just the diamond from this picture with a dollar sign in the center
A white circle with a lightening gradient towards the edge.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A simple golden line break.. In-Game asset. 2d. High contrast. No shadows
A fanned card hand that shows a royal flush in spades. Anime style. In-Game asset. 2d. High contrast. No shadows
An SVG of the word 'Battle'. text in yellow with a black outline. In-Game asset. 2d. High contrast. No shadows
change the text to say "Mods"
The four card suits arranged in 2x2 grid layout, no lines. Anime style. In-Game asset. 2d. High contrast. No shadows
A single ice crystal. anime style. In-Game asset. 2d. High contrast. No shadows
Change the text to say ‘Refund’. Change the cards to a trash can.
A completely blank playing card with textured surface. Slightly used edges with a couple nicks out of it. Black background. In-Game asset. 2d. High contrast. No shadows
A 3:2 ratio rectangular green button that says “PvP” using this yellow font.
Change the text to say ‘Co-op’
Change the font to say ‘Victory!’
Change the text to say ‘Defeat!’
A 2:3 ratio rectangular picture that shows two card playing cats in a casino very close face to face with teeth bared and fists clenched as if they’re about to fight. Each cat has a different card suit pattern on the fur of their forehead. One is wearing a suit and the other is wearing tan leather jacket with a striped tank top underneath. Anime style.. In-Game asset. 2d. High contrast. No shadows
Show these same cats smiling and instead of clenched fists they’re grasping hands because they’re friends.
Incorporate these two cats heads into a game logo for a poker based tower defense that includes the name “Double Down Defense”. Put their heads offset on either side with eyes open and looking at the logo.
A small treasure chest with poker themed graphics on it. Anime style. In-Game asset. 2d. High contrast. No shadows
The hearts card suit symbol with two linked hearts in the center of it. Anime style.. In-Game asset. 2d. High contrast. No shadows
The diamond card suit with a coin in the center. The coin has a ‘2X’ in the center. Anime style.. In-Game asset. 2d. High contrast. No shadows
Just the club from this picture with a clock in the center.
Just the spade from this image with a land mine in the center of it.
Just the mine from this image.
Just the heart from this image with a piggy bank in the center.
Just the diamond from this picture with a sword with a small arrow pointing up in the center of the diamond.
Just the club from this picture with an icon in the center of it that represents a projectile bouncing at an angle off of a surface.
Just the spade with a skull in the center of it. Anime style.
This chest with the top open and nothing inside.
Change the text to say Shop
An old style cash register. The numeric read out says 7.77. Anime style.. In-Game asset. 2d. High contrast. No shadows
A giant question mark. Anime style.. In-Game asset. 2d. High contrast. No shadows
A shield with a spade and heart card suit coat of arms on it with a sword crossed downwards, behind it. icon. Anime style.. In-Game asset. 2d. High contrast. No shadows
Change the text to say ‘Draw’
The back of a playing card. Blue pattern. Anime style.. In-Game asset. 2d. High contrast. No shadows
The back of a playing card. Red pattern with a heart in the center. Anime style.. In-Game asset. 2d. High contrast. No shadows