User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded.' in or related to this line: 'localOriginalUpdate.call(p.target);' Line Number: 1282
User prompt
Make it so the megalodon can make you unable to spawn towers if it chooses to.
User prompt
Make it so the megalodon can stun the player, making you unable to put down any towers on the megalodon wave, if the megalodon chooses to stun you.
User prompt
Finish it please
User prompt
Make it so the Plastic Bag enemy spawns at the start of the track(the opposite side of the coral)
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded.' in or related to this line: 'originalUpdate.call(p.target);' Line Number: 1110
User prompt
Do it.
User prompt
Get rid of the code that allows you to upgrade your towers
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded.' in or related to this line: 'originalUpdate.call(p.target);' Line Number: 1089
User prompt
Make it so you can upgrade your towers by simply tapping on them
User prompt
I just added a new tower called the Jelly Stinger, i want you to make it produce electricity that stuns the enemies for 30 seconds. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make it so there are 100 waves and not just 10.
User prompt
Make it so the megalodon spawns at wave 20
User prompt
I said to start with 100 pearls.
User prompt
Make it so you start with 100 pearls
User prompt
Make it so the enemies spawn near your towers.
User prompt
Finish the code please
User prompt
Add the code please
User prompt
Now the sharks won’t spawn.
User prompt
Make them appear on every wave right after you place a tower or 2
User prompt
Make the enemies able to appear from somewhere on the track
User prompt
Make the seaweed trap stare at the enemies, stunning them for a minute ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Floppy Fish Fortress: Reef Defender
Initial prompt
A tower defense game with the player as Floppy Fish from my game named Floppy Fish.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, pearls: 0, currentLevel: 1 }); /**** * Classes ****/ var BuildSpot = Container.expand(function () { var self = Container.call(this); var buildGraphics = self.attachAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.occupied = false; self.tower = null; self.down = function (x, y, obj) { if (!self.occupied && gameState.pearls >= 10 && !gameState.playerStunned) { openBuildMenu(self); } else if (gameState.playerStunned) { // Show visual feedback that player is stunned LK.effects.flashScreen(0x0000ff, 300); } }; return self; }); var CoralReef = Container.expand(function () { var self = Container.call(this); var coralGraphics = self.attachAsset('coral', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 500); if (self.health <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.speed = 1.5; self.damage = 10; self.pathIndex = 0; self.pearls = 5; self.boss = false; // Default enemies are not bosses // Health bar var healthBar = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, width: 60, height: 10, scaleX: 1, scaleY: 0.2, y: -40, tint: 0x00ff00 }); self.addChild(healthBar); self.update = function () { // Initialize stunned property if not set if (self.stunned === undefined) { self.stunned = false; } if (self.pathIndex < gamePath.length && !self.stunned) { var targetPos = gamePath[self.pathIndex]; var dx = targetPos.x - self.x; var dy = targetPos.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; // Face the direction of movement if (dx < 0) { enemyGraphics.scaleX = -1; } else { enemyGraphics.scaleX = 1; } } else { self.pathIndex++; } } else if (self.pathIndex >= gamePath.length) { // Reached the end, damage coral coralReef.takeDamage(self.damage); self.destroy(); var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } } healthBar.scaleX = self.health / self.maxHealth; // Visual indicator for stunned state if (self.stunned) { // Pulsate alpha when stunned if (LK.ticks % 15 === 0) { enemyGraphics.alpha = enemyGraphics.alpha === 1 ? 0.5 : 1; } } else { enemyGraphics.alpha = 1; } }; self.takeDamage = function (damage) { self.health -= damage; LK.getSound('enemyHit').play(); if (self.health <= 0) { gameState.pearls += self.pearls; pearlText.setText("Pearls: " + gameState.pearls); LK.getSound('enemyDefeat').play(); // Add to score LK.setScore(LK.getScore() + 10); scoreText.setText("Score: " + LK.getScore()); self.destroy(); var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } } }; return self; }); var PlasticBag = Enemy.expand(function () { var self = Enemy.call(this); // Replace with plastic bag graphic self.removeChild(self.children[1]); // Remove regular enemy graphic var plasticBagGraphics = self.attachAsset('PlasticBag', { anchorX: 0.5, anchorY: 0.5 }); // Plastic bag properties self.health = 80; self.maxHealth = 80; self.speed = 2.0; // Faster than regular enemies self.damage = 5; // Less damage self.pearls = 3; // Special ability: Sometimes changes direction randomly self.update = function () { // Call parent's update logic Enemy.prototype.update.call(self); // 2% chance per frame to temporarily speed up if (Math.random() < 0.02 && !self.speedBoost) { self.speedBoost = true; self.originalSpeed = self.speed; self.speed *= 1.5; // Reset speed after a short duration LK.setTimeout(function () { if (self && self.parent) { self.speed = self.originalSpeed; self.speedBoost = false; } }, 1000); } }; return self; }); var Megalodon = Enemy.expand(function () { var self = Enemy.call(this); // Replace with megalodon graphic self.removeChild(self.children[1]); // Remove regular enemy graphic var megalGraphics = self.attachAsset('Megalodon', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); // Megalodon properties self.health = 500; self.maxHealth = 500; self.speed = 1.0; self.damage = 30; self.pearls = 25; self.boss = true; // Special abilities: regenerate health and stun player self.lastRegenTick = 0; self.lastStunTick = 0; self.hasStunned = false; // Track if this megalodon has already stunned // Override update method to add regeneration and stunning ability var parentUpdate = self.update; self.update = function () { // Call parent update first parentUpdate.call(self); // Regenerate health every 3 seconds (180 frames) if (LK.ticks - self.lastRegenTick > 180) { self.lastRegenTick = LK.ticks; if (self.health < self.maxHealth) { self.health = Math.min(self.health + 20, self.maxHealth); // Show healing effect LK.effects.flashObject(self, 0x00ff00, 500); } } // 25% chance to stun player when megalodon first appears // Only try to stun once per megalodon if (!self.hasStunned && Math.random() < 0.25) { self.hasStunned = true; // Stun the player gameState.playerStunned = true; gameState.stunDuration = 600; // 10 seconds at 60fps // Show stun effect LK.effects.flashScreen(0x0000ff, 500); // Display warning message var stunText = new Text2("MEGALODON STUN ATTACK!\nCan't build towers!", { size: 60, fill: 0x0000FF }); stunText.anchor.set(0.5, 0.5); LK.gui.center.addChild(stunText); // Remove text after 3 seconds LK.setTimeout(function () { if (stunText && stunText.parent) { stunText.destroy(); } }, 3000); } }; return self; }); var FloppyFish = Container.expand(function () { var self = Container.call(this); var fishGraphics = self.attachAsset('floppyFish', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.targetX = null; self.targetY = null; self.update = function () { if (self.targetX !== null && self.targetY !== null) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; // Face the direction of movement if (dx < 0) { fishGraphics.scaleX = -1; } else { fishGraphics.scaleX = 1; } } else { self.x = self.targetX; self.y = self.targetY; self.targetX = null; self.targetY = null; } } }; return self; }); var PathTile = Container.expand(function () { var self = Container.call(this); var pathGraphics = self.attachAsset('path', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.buildable = false; return self; }); var Tower = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'bubbleCannon'; self.level = 1; self.range = 250; self.damage = 25; self.fireRate = 60; // frames between shots self.fireCounter = 0; self.cost = 10; self.upgradesCost = 15; var towerGraphics = self.attachAsset(self.type, { anchorX: 0.5, anchorY: 0.5 }); // Range indicator (only shown when selected) var rangeIndicator = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, alpha: 0.2, tint: 0x3498db }); // Scale the range indicator to match the tower's range rangeIndicator.scaleX = self.range / 40; rangeIndicator.scaleY = self.range / 40; rangeIndicator.visible = false; self.addChild(rangeIndicator); self.down = function (x, y, obj) { // Deselect previous tower if (selectedTower && selectedTower !== self) { selectedTower.deselect(); } selectedTower = self; self.select(); // Show upgrade UI with cost upgradeButton.visible = true; stopUpgradeButton.visible = true; upgradeText.setText("Upgrade: " + self.upgradesCost + " pearls"); }; self.select = function () { rangeIndicator.visible = true; towerGraphics.tint = 0xffff00; }; self.deselect = function () { rangeIndicator.visible = false; towerGraphics.tint = 0xffffff; }; self.upgrade = function () { if (gameState.pearls >= self.upgradesCost) { gameState.pearls -= self.upgradesCost; pearlText.setText("Pearls: " + gameState.pearls); self.level++; self.damage += 15; self.range += 50; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradesCost = Math.floor(self.upgradesCost * 1.5); // Update range indicator rangeIndicator.scaleX = self.range / 40; rangeIndicator.scaleY = self.range / 40; // Update upgrade button text upgradeText.setText("Upgrade: " + self.upgradesCost + " pearls"); // Scale up tower slightly to show upgrade tween(towerGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1, scaleY: 1 }, { duration: 300 }); } }); } }; self.findTarget = function () { var closestEnemy = null; var closestDistance = self.range; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestEnemy = enemy; closestDistance = distance; } } return closestEnemy; }; self.shoot = function (target) { var bubble = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(bubble); projectiles.push({ sprite: bubble, target: target, damage: self.damage, speed: 7 }); LK.getSound('bubble').play(); }; self.update = function () { self.fireCounter++; if (self.fireCounter >= self.fireRate) { var target = self.findTarget(); if (target) { self.shoot(target); self.fireCounter = 0; } } }; return self; }); var TurtleShell = Tower.expand(function () { var self = Tower.call(this, 'TurtleShell'); // Override properties for turtle shell self.range = 300; self.damage = 30; self.fireRate = 60; // Override shoot method for attack self.shoot = function (target) { // Create turtle shell projectile var shell = LK.getAsset('TurtleShellAttack', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(shell); // Create special projectile that will do damage projectiles.push({ sprite: shell, target: target, damage: self.damage, speed: 8 }); // Play sound (using bubble sound for now) LK.getSound('bubble').play(); }; return self; }); var SharkTower = Tower.expand(function () { var self = Tower.call(this, 'Sharky'); // Override properties for shark tower self.range = 250; self.damage = 100; self.fireRate = 90; // Slower than bubble cannon but high damage // Override shoot method for instant kill functionality self.shoot = function (target) { // Create bite effect (using the bubble as a placeholder for the bite animation) var bite = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(bite); // Move bite effect to target projectiles.push({ sprite: bite, target: target, damage: target.boss ? self.damage : target.health, // Instant kill for non-boss enemies speed: 10 // Faster projectile to simulate bite }); // Flash target red to indicate it's being bitten LK.effects.flashObject(target, 0xff0000, 200); // Play bite sound (using bubble sound for now) LK.getSound('bubble').play(); }; return self; }); var SeaweedTrap = Tower.expand(function () { var self = Tower.call(this, 'seaweedTrap'); // Override properties for seaweed trap self.range = 200; self.damage = 5; self.fireRate = 60; self.stunDuration = 60; // 1 second stun (60 frames) // Override shoot method for stun functionality self.shoot = function (target) { // Apply stun effect to the target if (!target.stunned) { target.stunned = true; target.originalSpeed = target.speed; target.speed = 0; // Make the seaweed trap "stare" at the enemy by rotating to face it var dx = target.x - self.x; var dy = target.y - self.y; var angle = Math.atan2(dy, dx); // Use tween to rotate the tower to face the enemy tween(self.children[0], { rotation: angle }, { duration: 300, easing: tween.easeOut }); // Flash the target to indicate stun LK.effects.flashObject(target, 0x00ff00, 300); // Set a timer to remove the stun after duration LK.setTimeout(function () { if (target && target.parent) { target.speed = target.originalSpeed; target.stunned = false; } }, self.stunDuration * 16.67); // Convert frames to milliseconds (60fps ≈ 16.67ms per frame) } target.takeDamage(self.damage); LK.getSound('bubble').play(); }; return self; }); var JellyStinger = Tower.expand(function () { var self = Tower.call(this, 'JellyStinger'); // Override properties for jelly stinger self.range = 230; self.damage = 15; self.fireRate = 90; self.stunDuration = 1800; // 30 seconds (60fps * 30) // Override shoot method for electricity stunning self.shoot = function (target) { // Create electricity effect var electricity = LK.getAsset('Electricity', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 0.8 }); game.addChild(electricity); // Create special projectile that will apply electricity stun projectiles.push({ sprite: electricity, target: target, damage: self.damage, speed: 8, isElectric: true, stunDuration: self.stunDuration }); // Play sound (using bubble sound for now) LK.getSound('bubble').play(); }; return self; }); var ClamMine = Tower.expand(function () { var self = Tower.call(this, 'clamMine'); // Override properties for clam mine self.range = 200; self.damage = 40; self.fireRate = 120; // Slower fire rate but area damage self.areaRadius = 150; // Radius of explosion // Override shoot method for area damage self.shoot = function (target) { // Create pearl projectile var pearl = LK.getAsset('pearl', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(pearl); // Create special projectile that will explode projectiles.push({ sprite: pearl, target: target, damage: self.damage, speed: 5, isAreaDamage: true, areaRadius: self.areaRadius }); LK.getSound('bubble').play(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a5276 }); /**** * Game Code ****/ // Play music // Base characters // Towers and defenses // Items and effects // Sounds // Music LK.playMusic('underwaterTheme'); // Game variables var gameState = { pearls: 100, currentWave: 1, maxWaves: 100, waveInProgress: false, enemiesLeft: 0, playerStunned: false, // Track if player is stunned by megalodon stunDuration: 0 // Track remaining frames of stun }; var selectedTower = null; var buildMenuOpen = false; var gamePath = []; var buildSpots = []; var enemies = []; var towers = []; var projectiles = []; var coralReef; var floppyFish; // UI Elements var scoreText = new Text2("Score: 0", { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topRight.addChild(scoreText); scoreText.x = -scoreText.width - 20; scoreText.y = 20; var pearlText = new Text2("Pearls: " + gameState.pearls, { size: 50, fill: 0xFFFFFF }); pearlText.anchor.set(0, 0); LK.gui.topRight.addChild(pearlText); pearlText.x = -pearlText.width - 20; pearlText.y = 80; var waveText = new Text2("Wave: " + gameState.currentWave + "/" + gameState.maxWaves, { size: 50, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); waveText.y = 20; // Upgrade button (hidden initially) var upgradeButton = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 80, tint: 0x2ecc71 }); upgradeButton.visible = false; LK.gui.bottom.addChild(upgradeButton); upgradeButton.y = -100; var upgradeText = new Text2("Upgrade: 15 pearls", { size: 40, fill: 0xFFFFFF }); upgradeText.anchor.set(0.5, 0.5); upgradeButton.addChild(upgradeText); // Stop upgrading button (hidden initially) var stopUpgradeButton = LK.getAsset('Stopupgrade', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80, tint: 0xff0000 }); stopUpgradeButton.visible = false; LK.gui.bottom.addChild(stopUpgradeButton); stopUpgradeButton.x = 200; stopUpgradeButton.y = -100; // Start wave button var startWaveButton = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, width: 300, height: 80, tint: 0x3498db }); LK.gui.bottom.addChild(startWaveButton); startWaveButton.y = -200; var startWaveText = new Text2("Start Wave", { size: 40, fill: 0xFFFFFF }); startWaveText.anchor.set(0.5, 0.5); startWaveButton.addChild(startWaveText); // Build menu (hidden initially) var buildMenu = new Container(); buildMenu.visible = false; LK.gui.center.addChild(buildMenu); var buildMenuBackground = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 500, tint: 0x34495e, alpha: 0.9 }); buildMenu.addChild(buildMenuBackground); var buildMenuTitle = new Text2("Build Tower", { size: 50, fill: 0xFFFFFF }); buildMenuTitle.anchor.set(0.5, 0); buildMenuTitle.y = -200; buildMenu.addChild(buildMenuTitle); // Tower options in build menu var bubbleOption = LK.getAsset('bubbleCannon', { anchorX: 0.5, anchorY: 0.5, x: -100, y: -100 }); buildMenu.addChild(bubbleOption); var bubbleText = new Text2("Bubble\nCannon\n10 pearls", { size: 30, fill: 0xFFFFFF }); bubbleText.anchor.set(0.5, 0); bubbleText.y = 50; bubbleOption.addChild(bubbleText); var seaweedOption = LK.getAsset('seaweedTrap', { anchorX: 0.5, anchorY: 0.5, x: 100, y: -100 }); buildMenu.addChild(seaweedOption); var seaweedText = new Text2("Seaweed\nTrap\n10 pearls", { size: 30, fill: 0xFFFFFF }); seaweedText.anchor.set(0.5, 0); seaweedText.y = 50; seaweedOption.addChild(seaweedText); var clamOption = LK.getAsset('clamMine', { anchorX: 0.5, anchorY: 0.5, x: -100, y: 50 }); buildMenu.addChild(clamOption); var clamText = new Text2("Clam\nMine\n10 pearls", { size: 30, fill: 0xFFFFFF }); clamText.anchor.set(0.5, 0); clamText.y = 50; clamOption.addChild(clamText); var sharkyOption = LK.getAsset('Sharky', { anchorX: 0.5, anchorY: 0.5, x: 100, y: 50 }); buildMenu.addChild(sharkyOption); var sharkyText = new Text2("Sharky\nBiter\n10 pearls", { size: 30, fill: 0xFFFFFF }); sharkyText.anchor.set(0.5, 0); sharkyText.y = 50; sharkyOption.addChild(sharkyText); var jellyStingerOption = LK.getAsset('JellyStinger', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 150 }); buildMenu.addChild(jellyStingerOption); var jellyStingerText = new Text2("Jelly\nStinger\n10 pearls", { size: 30, fill: 0xFFFFFF }); jellyStingerText.anchor.set(0.5, 0); jellyStingerText.y = 50; jellyStingerOption.addChild(jellyStingerText); var cancelBuildButton = LK.getAsset('buildPlaceholder', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 60, y: 150, tint: 0xe74c3c }); buildMenu.addChild(cancelBuildButton); var cancelText = new Text2("Cancel", { size: 40, fill: 0xFFFFFF }); cancelText.anchor.set(0.5, 0.5); cancelBuildButton.addChild(cancelText); // Initialize the map function initializeMap() { // Create path var pathPoints = [{ x: 0, y: 600 }, { x: 400, y: 600 }, { x: 400, y: 1000 }, { x: 800, y: 1000 }, { x: 800, y: 500 }, { x: 1200, y: 500 }, { x: 1200, y: 1200 }, { x: 1600, y: 1200 }, { x: 1600, y: 800 }, { x: 2000, y: 800 }]; // Create path tiles for (var i = 0; i < pathPoints.length; i++) { gamePath.push(pathPoints[i]); var pathTile = new PathTile(); pathTile.x = pathPoints[i].x; pathTile.y = pathPoints[i].y; game.addChild(pathTile); // Create build spots along the path (offset from path) if (i < pathPoints.length - 1) { var dx = pathPoints[i + 1].x - pathPoints[i].x; var dy = pathPoints[i + 1].y - pathPoints[i].y; var len = Math.sqrt(dx * dx + dy * dy); // Normalize and rotate 90 degrees for perpendicular var perpX = -dy / len; var perpY = dx / len; // Create build spots along segments var segments = Math.floor(len / 200); for (var j = 0; j <= segments; j++) { var segX = pathPoints[i].x + dx * j / segments; var segY = pathPoints[i].y + dy * j / segments; // Create build spots on both sides of path var buildSpot1 = new BuildSpot(); buildSpot1.x = segX + perpX * 120; buildSpot1.y = segY + perpY * 120; game.addChild(buildSpot1); buildSpots.push(buildSpot1); var buildSpot2 = new BuildSpot(); buildSpot2.x = segX - perpX * 120; buildSpot2.y = segY - perpY * 120; game.addChild(buildSpot2); buildSpots.push(buildSpot2); } } } // Add coral reef at the end of the path coralReef = new CoralReef(); coralReef.x = 2048 - 100; coralReef.y = 800; game.addChild(coralReef); // Add floppy fish floppyFish = new FloppyFish(); floppyFish.x = 1024; floppyFish.y = 1366; game.addChild(floppyFish); } // Initialize the game initializeMap(); // Functions function openBuildMenu(buildSpot) { buildMenuOpen = true; buildMenu.visible = true; buildMenu.currentBuildSpot = buildSpot; // If the player has insufficient pearls, disable options bubbleOption.alpha = gameState.pearls >= 10 ? 1 : 0.5; seaweedOption.alpha = gameState.pearls >= 10 ? 1 : 0.5; clamOption.alpha = gameState.pearls >= 10 ? 1 : 0.5; sharkyOption.alpha = gameState.pearls >= 10 ? 1 : 0.5; jellyStingerOption.alpha = gameState.pearls >= 10 ? 1 : 0.5; } function closeBuildMenu() { buildMenuOpen = false; buildMenu.visible = false; buildMenu.currentBuildSpot = null; } function buildTower(type) { if (gameState.pearls < 10) { return; } var buildSpot = buildMenu.currentBuildSpot; if (!buildSpot || buildSpot.occupied) { return; } gameState.pearls -= 10; pearlText.setText("Pearls: " + gameState.pearls); var tower; if (type === 'seaweedTrap') { tower = new SeaweedTrap(); } else if (type === 'Sharky') { tower = new SharkTower(); } else if (type === 'clamMine') { tower = new ClamMine(); } else if (type === 'JellyStinger') { tower = new JellyStinger(); } else { tower = new Tower(type); } tower.x = buildSpot.x; tower.y = buildSpot.y; game.addChild(tower); buildSpot.occupied = true; buildSpot.tower = tower; towers.push(tower); LK.getSound('buildTower').play(); // Spawn an enemy if a wave is in progress if (gameState.waveInProgress) { // Immediate spawn of enemy after tower placement spawnEnemy(); } closeBuildMenu(); } function spawnEnemy() { if (gameState.enemiesLeft <= 0) { return; } // Determine if this should be a Megalodon boss (at wave 20 or every 3rd wave, and last enemy of the wave) var isMegalodon = (gameState.currentWave === 20 || gameState.currentWave % 3 === 0) && gameState.enemiesLeft === 1 && enemies.length === 0; var enemy; if (isMegalodon) { // Create Megalodon enemy = new Megalodon(); // Announce Megalodon arrival var bossText = new Text2("MEGALODON INCOMING!", { size: 80, fill: 0xFF0000 }); bossText.anchor.set(0.5, 0.5); LK.gui.center.addChild(bossText); // Flash screen and remove announcement after delay LK.effects.flashScreen(0xFF0000, 500); LK.setTimeout(function () { bossText.destroy(); }, 2000); } else { // Create regular enemy // 25% chance to create a plastic bag instead of regular enemy if (Math.random() < 0.25) { enemy = new Enemy(); // Override with plastic bag graphics enemy.removeChild(enemy.children[1]); // Remove regular enemy graphic var plasticBagGraphics = enemy.attachAsset('PlasticBag', { anchorX: 0.5, anchorY: 0.5 }); } else { enemy = new Enemy(); } // Randomly make some regular enemies bosses var isBoss = Math.random() < 0.2; // 20% chance for boss enemy.boss = isBoss; // Increase enemy stats based on wave enemy.health = 100 + (gameState.currentWave - 1) * 20; // Boss enemies have double health if (enemy.boss) { enemy.health *= 2; enemy.scaleX = 1.5; enemy.scaleY = 1.5; enemy.pearls *= 2; } } // Check if this is a plastic bag (has PlasticBag as child) var isPlasticBag = enemy.children.some(function (child) { return child.assetId === 'PlasticBag'; }); var spawnX, spawnY, pathIndex; // Always spawn at start of track (first path point) spawnX = gamePath[0].x; spawnY = gamePath[0].y; pathIndex = 0; // If not a plastic bag, we can spawn at different locations if (!isPlasticBag) { // Spawn near a tower if there are towers (for non-plastic bag enemies) var spawnNearTower = towers.length > 0; if (spawnNearTower) { // Choose a random tower to spawn near var randomTower = towers[Math.floor(Math.random() * towers.length)]; // Find the closest path segment to this tower var minDistance = Infinity; var closestSegment = 0; for (var i = 0; i < gamePath.length - 1; i++) { var dx = gamePath[i].x - randomTower.x; var dy = gamePath[i].y - randomTower.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < minDistance) { minDistance = distance; closestSegment = i; } } // Use the closest path segment spawnX = gamePath[closestSegment].x; spawnY = gamePath[closestSegment].y; pathIndex = closestSegment; } else { // No towers, use random path segment as before var randomPathSegment = Math.floor(Math.random() * (gamePath.length - 1)); spawnX = gamePath[randomPathSegment].x; spawnY = gamePath[randomPathSegment].y; pathIndex = randomPathSegment; } } enemy.x = spawnX; enemy.y = spawnY; enemy.pathIndex = pathIndex; // Set the path index to start from the chosen segment // Adjust regular enemy stats based on wave if (!isMegalodon) { enemy.maxHealth = enemy.health; enemy.speed = 1.5 + (gameState.currentWave - 1) * 0.1; enemy.pearls = 5 + Math.floor((gameState.currentWave - 1) / 2); } game.addChild(enemy); enemies.push(enemy); gameState.enemiesLeft--; // Schedule next enemy if (gameState.enemiesLeft > 0) { LK.setTimeout(spawnEnemy, 1000); } } function startWave() { if (gameState.waveInProgress) { return; } gameState.waveInProgress = true; gameState.enemiesLeft = 5 + gameState.currentWave * 2; startWaveButton.tint = 0x95a5a6; // Gray out button // Update wave text waveText.setText("Wave: " + gameState.currentWave + "/" + gameState.maxWaves); // Start spawning enemies spawnEnemy(); } function endWave() { gameState.waveInProgress = false; gameState.currentWave++; if (gameState.currentWave > gameState.maxWaves) { // Game won LK.showYouWin(); return; } // Update wave text waveText.setText("Wave: " + gameState.currentWave + "/" + gameState.maxWaves); startWaveButton.tint = 0x3498db; // Blue button } // Event handlers startWaveButton.down = function () { if (!gameState.waveInProgress) { startWave(); } }; upgradeButton.down = function () { if (selectedTower) { selectedTower.upgrade(); } }; stopUpgradeButton.down = function () { if (selectedTower) { selectedTower.deselect(); selectedTower = null; upgradeButton.visible = false; stopUpgradeButton.visible = false; } }; cancelBuildButton.down = function () { closeBuildMenu(); }; bubbleOption.down = function () { buildTower('bubbleCannon'); }; seaweedOption.down = function () { buildTower('seaweedTrap'); }; clamOption.down = function () { buildTower('clamMine'); }; sharkyOption.down = function () { buildTower('Sharky'); }; jellyStingerOption.down = function () { buildTower('JellyStinger'); }; game.down = function (x, y, obj) { // Deselect tower when clicking elsewhere if (selectedTower && !upgradeButton.visible) { selectedTower.deselect(); selectedTower = null; upgradeButton.visible = false; stopUpgradeButton.visible = false; } if (!buildMenuOpen) { floppyFish.targetX = x; floppyFish.targetY = y; } }; game.up = function (x, y, obj) { // Nothing specific needed for up events }; // Update logic game.update = function () { // Handle player stun effect if (gameState.playerStunned) { gameState.stunDuration--; // Visual indicator for stunned state - pulse the screen slightly if (gameState.stunDuration % 60 === 0) { LK.effects.flashScreen(0x0000ff, 200); } // End stun when duration expires if (gameState.stunDuration <= 0) { gameState.playerStunned = false; // Show recovery notification var recoveryText = new Text2("Stun effect worn off!", { size: 60, fill: 0x00FF00 }); recoveryText.anchor.set(0.5, 0.5); LK.gui.center.addChild(recoveryText); // Remove text after 2 seconds LK.setTimeout(function () { if (recoveryText && recoveryText.parent) { recoveryText.destroy(); } }, 2000); } } // Update floppy fish if (floppyFish) { // Check if floppy fish is colliding with any enemies for (var i = 0; i < enemies.length; i++) { if (floppyFish.intersects(enemies[i])) { enemies[i].takeDamage(5); LK.effects.flashObject(floppyFish, 0xff0000, 200); break; } } } // Update towers for (var i = 0; i < towers.length; i++) { towers[i].update(); } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].update(); } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var p = projectiles[i]; // Check if target still exists if (!p.target || !p.target.parent) { p.sprite.destroy(); projectiles.splice(i, 1); continue; } // Move towards target var dx = p.target.x - p.sprite.x; var dy = p.target.y - p.sprite.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > p.speed) { p.sprite.x += dx / distance * p.speed; p.sprite.y += dy / distance * p.speed; } else { // Hit target if (p.isAreaDamage) { // Create explosion effect var explosion = LK.getAsset('pearl', { anchorX: 0.5, anchorY: 0.5, x: p.target.x, y: p.target.y, scaleX: 0.5, scaleY: 0.5 }); game.addChild(explosion); // Scale up and fade out for explosion effect tween(explosion, { scaleX: 5, scaleY: 5, alpha: 0 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Deal damage to all enemies in area for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; var dxe = enemy.x - p.target.x; var dye = enemy.y - p.target.y; var dist = Math.sqrt(dxe * dxe + dye * dye); if (dist <= p.areaRadius) { // Deal damage based on distance (more damage closer to center) var damageFactor = 1 - dist / p.areaRadius; var actualDamage = Math.floor(p.damage * damageFactor); enemy.takeDamage(actualDamage); } } } else if (p.isElectric) { // Apply electricity stun effect to the target p.target.takeDamage(p.damage); // Apply stunning effect p.target.stunned = true; p.target.originalSpeed = p.target.speed; p.target.speed = 0; // Create electricity visual effect around the target var electricEffect = LK.getAsset('Electricity', { anchorX: 0.5, anchorY: 0.5, x: p.target.x, y: p.target.y, scaleX: 0.8, scaleY: 0.8, alpha: 0.7 }); game.addChild(electricEffect); p.target.electricEffect = electricEffect; // Make the electricity follow the target var updateElectricity = function updateElectricity() { if (p.target && p.target.parent && electricEffect && electricEffect.parent) { electricEffect.x = p.target.x; electricEffect.y = p.target.y; // Pulsate the effect if (LK.ticks % 10 === 0) { tween(electricEffect, { alpha: electricEffect.alpha > 0.4 ? 0.4 : 0.7 }, { duration: 300 }); } } }; // Store the original update function safely - capture it in a closure to avoid recursion var originalUpdate = p.target.update; // Create a new update function that doesn't cause recursion p.target.update = function () { // Create a local reference to avoid recursion var localOriginalUpdate = originalUpdate; // Only call the original update if it exists and is a function if (typeof localOriginalUpdate === 'function' && localOriginalUpdate !== p.target.update) { // Use call instead of apply with the proper context localOriginalUpdate.call(p.target); } updateElectricity(); }; // Apply a tint to show the enemy is electrified tween(p.target, { tint: 0x00ffff }, { duration: 300 }); // Set a timer to remove the stun after duration LK.setTimeout(function () { if (p.target && p.target.parent) { p.target.speed = p.target.originalSpeed; p.target.stunned = false; // Remove the electricity effect if (electricEffect && electricEffect.parent) { electricEffect.destroy(); } // Reset the tint tween(p.target, { tint: 0xffffff }, { duration: 300 }); // Safely restore original update function if (typeof originalUpdate === 'function') { p.target.update = originalUpdate; } else { // Create a fallback update if original was not available p.target.update = function () { // Basic enemy update logic if (p.target.pathIndex < gamePath.length && !p.target.stunned) { var targetPos = gamePath[p.target.pathIndex]; var dx = targetPos.x - p.target.x; var dy = targetPos.y - p.target.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > p.target.speed) { p.target.x += dx / distance * p.target.speed; p.target.y += dy / distance * p.target.speed; } else { p.target.pathIndex++; } } }; } } }, p.stunDuration * 16.67); // Convert frames to milliseconds } else { // Regular projectile just hits target p.target.takeDamage(p.damage); } p.sprite.destroy(); projectiles.splice(i, 1); } } // Check if wave is over if (gameState.waveInProgress && gameState.enemiesLeft <= 0 && enemies.length === 0) { endWave(); } // Update UI based on player stun status if (gameState.playerStunned) { // Visual indicator that building is disabled for (var i = 0; i < buildSpots.length; i++) { if (!buildSpots[i].occupied) { buildSpots[i].alpha = 0.3; } } } else { // Restore normal appearance for (var i = 0; i < buildSpots.length; i++) { if (!buildSpots[i].occupied) { buildSpots[i].alpha = 0.5; } } } // Update storage data storage.pearls = gameState.pearls; if (gameState.currentWave > storage.currentLevel) { storage.currentLevel = gameState.currentWave; } if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); } };
===================================================================
--- original.js
+++ change.js
@@ -20,10 +20,13 @@
});
self.occupied = false;
self.tower = null;
self.down = function (x, y, obj) {
- if (!self.occupied && gameState.pearls >= 10) {
+ if (!self.occupied && gameState.pearls >= 10 && !gameState.playerStunned) {
openBuildMenu(self);
+ } else if (gameState.playerStunned) {
+ // Show visual feedback that player is stunned
+ LK.effects.flashScreen(0x0000ff, 300);
}
};
return self;
});
@@ -180,11 +183,13 @@
self.speed = 1.0;
self.damage = 30;
self.pearls = 25;
self.boss = true;
- // Special ability: regenerate health
+ // Special abilities: regenerate health and stun player
self.lastRegenTick = 0;
- // Override update method to add regeneration
+ self.lastStunTick = 0;
+ self.hasStunned = false; // Track if this megalodon has already stunned
+ // Override update method to add regeneration and stunning ability
var parentUpdate = self.update;
self.update = function () {
// Call parent update first
parentUpdate.call(self);
@@ -196,8 +201,31 @@
// Show healing effect
LK.effects.flashObject(self, 0x00ff00, 500);
}
}
+ // 25% chance to stun player when megalodon first appears
+ // Only try to stun once per megalodon
+ if (!self.hasStunned && Math.random() < 0.25) {
+ self.hasStunned = true;
+ // Stun the player
+ gameState.playerStunned = true;
+ gameState.stunDuration = 600; // 10 seconds at 60fps
+ // Show stun effect
+ LK.effects.flashScreen(0x0000ff, 500);
+ // Display warning message
+ var stunText = new Text2("MEGALODON STUN ATTACK!\nCan't build towers!", {
+ size: 60,
+ fill: 0x0000FF
+ });
+ stunText.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(stunText);
+ // Remove text after 3 seconds
+ LK.setTimeout(function () {
+ if (stunText && stunText.parent) {
+ stunText.destroy();
+ }
+ }, 3000);
+ }
};
return self;
});
var FloppyFish = Container.expand(function () {
@@ -547,9 +575,12 @@
pearls: 100,
currentWave: 1,
maxWaves: 100,
waveInProgress: false,
- enemiesLeft: 0
+ enemiesLeft: 0,
+ playerStunned: false,
+ // Track if player is stunned by megalodon
+ stunDuration: 0 // Track remaining frames of stun
};
var selectedTower = null;
var buildMenuOpen = false;
var gamePath = [];
@@ -1052,8 +1083,33 @@
// Nothing specific needed for up events
};
// Update logic
game.update = function () {
+ // Handle player stun effect
+ if (gameState.playerStunned) {
+ gameState.stunDuration--;
+ // Visual indicator for stunned state - pulse the screen slightly
+ if (gameState.stunDuration % 60 === 0) {
+ LK.effects.flashScreen(0x0000ff, 200);
+ }
+ // End stun when duration expires
+ if (gameState.stunDuration <= 0) {
+ gameState.playerStunned = false;
+ // Show recovery notification
+ var recoveryText = new Text2("Stun effect worn off!", {
+ size: 60,
+ fill: 0x00FF00
+ });
+ recoveryText.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(recoveryText);
+ // Remove text after 2 seconds
+ LK.setTimeout(function () {
+ if (recoveryText && recoveryText.parent) {
+ recoveryText.destroy();
+ }
+ }, 2000);
+ }
+ }
// Update floppy fish
if (floppyFish) {
// Check if floppy fish is colliding with any enemies
for (var i = 0; i < enemies.length; i++) {
@@ -1227,8 +1283,24 @@
// Check if wave is over
if (gameState.waveInProgress && gameState.enemiesLeft <= 0 && enemies.length === 0) {
endWave();
}
+ // Update UI based on player stun status
+ if (gameState.playerStunned) {
+ // Visual indicator that building is disabled
+ for (var i = 0; i < buildSpots.length; i++) {
+ if (!buildSpots[i].occupied) {
+ buildSpots[i].alpha = 0.3;
+ }
+ }
+ } else {
+ // Restore normal appearance
+ for (var i = 0; i < buildSpots.length; i++) {
+ if (!buildSpots[i].occupied) {
+ buildSpots[i].alpha = 0.5;
+ }
+ }
+ }
// Update storage data
storage.pearls = gameState.pearls;
if (gameState.currentWave > storage.currentLevel) {
storage.currentLevel = gameState.currentWave;
Floppy Fish the fish. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. Floppy Fish
Coral with seeweed inside of it. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Seeweed with eyes. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Bubbles. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A cannon made out of a bubble. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A clam. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A shark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A pearl. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A sleeping fish. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Friendly shark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Megalodon shark. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Jellyfish. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Electricity. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Button that says, stop upgrading. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Plastic bag. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Turtle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Turtle shell. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows