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) { openBuildMenu(self); } }; 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; // Flash red when damaged 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; // 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 () { if (self.pathIndex < gamePath.length) { 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 { // Reached the end, damage coral coralReef.takeDamage(self.damage); self.destroy(); var index = enemies.indexOf(self); if (index !== -1) { enemies.splice(index, 1); } } // Update health bar healthBar.scaleX = self.health / self.maxHealth; }; 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 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 upgradeButton.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; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a5276 }); /**** * Game Code ****/ // Music // Sounds // Items and effects // Towers and defenses // Base characters // Play music LK.playMusic('underwaterTheme'); // Game variables var gameState = { pearls: storage.pearls || 50, currentWave: 1, maxWaves: 10, waveInProgress: false, enemiesLeft: 0 }; 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); // 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: 0, 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 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; } 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 = 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(); closeBuildMenu(); } function spawnEnemy() { if (gameState.enemiesLeft <= 0) { return; } var enemy = new Enemy(); enemy.x = gamePath[0].x; enemy.y = gamePath[0].y; // Increase enemy stats based on wave enemy.health = 100 + (gameState.currentWave - 1) * 20; 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(); } }; cancelBuildButton.down = function () { closeBuildMenu(); }; bubbleOption.down = function () { buildTower('bubbleCannon'); }; seaweedOption.down = function () { buildTower('seaweedTrap'); }; clamOption.down = function () { buildTower('clamMine'); }; game.down = function (x, y, obj) { // Deselect tower when clicking elsewhere if (selectedTower && !upgradeButton.visible) { selectedTower.deselect(); selectedTower = null; upgradeButton.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 () { // 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 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 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
@@ -1,6 +1,707 @@
-/****
+/****
+* 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) {
+ openBuildMenu(self);
+ }
+ };
+ 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;
+ // Flash red when damaged
+ 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;
+ // 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 () {
+ if (self.pathIndex < gamePath.length) {
+ 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 {
+ // Reached the end, damage coral
+ coralReef.takeDamage(self.damage);
+ self.destroy();
+ var index = enemies.indexOf(self);
+ if (index !== -1) {
+ enemies.splice(index, 1);
+ }
+ }
+ // Update health bar
+ healthBar.scaleX = self.health / self.maxHealth;
+ };
+ 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 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
+ upgradeButton.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;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1a5276
+});
+
+/****
+* Game Code
+****/
+// Music
+// Sounds
+// Items and effects
+// Towers and defenses
+// Base characters
+// Play music
+LK.playMusic('underwaterTheme');
+// Game variables
+var gameState = {
+ pearls: storage.pearls || 50,
+ currentWave: 1,
+ maxWaves: 10,
+ waveInProgress: false,
+ enemiesLeft: 0
+};
+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);
+// 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: 0,
+ 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 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;
+}
+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 = 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();
+ closeBuildMenu();
+}
+function spawnEnemy() {
+ if (gameState.enemiesLeft <= 0) {
+ return;
+ }
+ var enemy = new Enemy();
+ enemy.x = gamePath[0].x;
+ enemy.y = gamePath[0].y;
+ // Increase enemy stats based on wave
+ enemy.health = 100 + (gameState.currentWave - 1) * 20;
+ 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();
+ }
+};
+cancelBuildButton.down = function () {
+ closeBuildMenu();
+};
+bubbleOption.down = function () {
+ buildTower('bubbleCannon');
+};
+seaweedOption.down = function () {
+ buildTower('seaweedTrap');
+};
+clamOption.down = function () {
+ buildTower('clamMine');
+};
+game.down = function (x, y, obj) {
+ // Deselect tower when clicking elsewhere
+ if (selectedTower && !upgradeButton.visible) {
+ selectedTower.deselect();
+ selectedTower = null;
+ upgradeButton.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 () {
+ // 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
+ 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 storage data
+ storage.pearls = gameState.pearls;
+ if (gameState.currentWave > storage.currentLevel) {
+ storage.currentLevel = gameState.currentWave;
+ }
+ if (LK.getScore() > storage.highScore) {
+ storage.highScore = LK.getScore();
+ }
+};
\ No newline at end of file
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