User prompt
Reduce the unit price to 35 gold
User prompt
Make units a little cheaper
User prompt
You know that 0/1000 waves thingy? Well, remove the /1000 thing
User prompt
Remove the wave limit
User prompt
The game now has INFINITE WAVES!
User prompt
Make goblins drop more gold
User prompt
Make goblins a little weaker
User prompt
Make waves a little easier by making goblins be slower and have less health, but they will get 2% more health and speed every wave
User prompt
Put the unit's name below the level of the tower
Code edit (1 edits merged)
Please save this source code
User prompt
Merge Defenders: Evolution
Initial prompt
Merging defense: a game where you merge units to make strongher units (example: rock thrower + rock thrower = slinger)to kill the goblins from reaching your base! You have 3 lives. (Units (from weakest to stronghest): rock thrower, slinger, spear thrower, archer, Fire archer, crossbowman, Mosquettere, cannoneer, rifleman, grenadier, tank); make sure to use ALL of the units i said and make them cost gold that is obtained through killing enemies or making in-app purchases with real money
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Goblin = Container.expand(function (pathPoints, health, speed, value) { var self = Container.call(this); self.pathPoints = pathPoints; self.maxHealth = health; self.health = health; self.speed = speed; self.value = value; self.active = true; self.currentPathIndex = 0; self.pathProgress = 0; var goblinGraphics = self.attachAsset('goblin', { anchorX: 0.5, anchorY: 0.5 }); var healthBar = LK.getAsset('tile', { width: 60, height: 10, color: 0x00FF00, anchorX: 0.5, anchorY: 0.5 }); healthBar.y = -40; self.addChild(healthBar); self.x = pathPoints[0].x; self.y = pathPoints[0].y; self.takeDamage = function (damage) { self.health -= damage; // Update health bar var healthPercent = Math.max(0, self.health / self.maxHealth); healthBar.width = 60 * healthPercent; healthBar.tint = healthPercent > 0.5 ? 0x00FF00 : healthPercent > 0.25 ? 0xFFFF00 : 0xFF0000; if (self.health <= 0) { self.die(); } }; self.die = function () { self.active = false; gold += self.value; goldText.setText("Gold: " + gold); score += self.value; scoreText.setText("Score: " + score); LK.setScore(score); LK.getSound('goblin_death').play(); // Create coin effect var coinText = new Text2("+" + self.value, { size: 40, fill: 0xFFD700 }); coinText.x = self.x; coinText.y = self.y; coinText.anchor.set(0.5, 0.5); game.addChild(coinText); tween(coinText, { y: coinText.y - 100, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { coinText.destroy(); } }); self.destroy(); }; self.reachedBase = function () { self.active = false; lives--; livesText.setText("Lives: " + lives); if (lives <= 0) { endGame(); } self.destroy(); }; self.update = function () { if (!self.active) { return; } if (self.currentPathIndex >= self.pathPoints.length - 1) { self.reachedBase(); return; } var currentPoint = self.pathPoints[self.currentPathIndex]; var nextPoint = self.pathPoints[self.currentPathIndex + 1]; var dx = nextPoint.x - currentPoint.x; var dy = nextPoint.y - currentPoint.y; var dist = Math.sqrt(dx * dx + dy * dy); self.pathProgress = self.currentPathIndex / (self.pathPoints.length - 1); // Calculate how far along this segment we are var currentX = self.x - currentPoint.x; var currentY = self.y - currentPoint.y; var segmentProgress = Math.sqrt(currentX * currentX + currentY * currentY) / dist; // Add segment progress to overall progress self.pathProgress += segmentProgress / (self.pathPoints.length - 1); // Move towards next point var dx = nextPoint.x - self.x; var dy = nextPoint.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.speed) { // Reached the next point self.currentPathIndex++; } else { // Move along the path self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); var Projectile = Container.expand(function (source, target, damage) { var self = Container.call(this); self.source = source; self.target = target; self.damage = damage; self.speed = 15; self.active = true; var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.x = source.x; self.y = source.y; self.update = function () { if (!self.active || !self.target || !self.target.active) { self.destroy(); return; } // Calculate direction vector var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 20) { // Hit target self.target.takeDamage(self.damage); LK.getSound('hit').play(); self.active = false; self.destroy(); return; } // Normalize and scale by speed self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; }; return self; }); var Unit = Container.expand(function (tier) { var self = Container.call(this); self.tier = tier || 1; self.damage = Math.pow(2, self.tier - 1); self.range = 300 + self.tier * 50; self.fireRate = 1000 - self.tier * 50; // ms between shots self.lastShot = 0; self.targets = []; self.isDragging = false; self.merging = false; var unitGraphics = self.attachAsset('unit' + self.tier, { anchorX: 0.5, anchorY: 0.5 }); var tierText = new Text2(self.tier.toString(), { size: 40, fill: 0x000000 }); tierText.anchor.set(0.5, 0.5); self.addChild(tierText); // Add unit name text below the level of the tower var unitNames = ["Rock Thrower", "Slinger", "Spear Thrower", "Archer", "Fire Archer", "Crossbowman", "Musketeer", "Cannoneer", "Rifleman", "Grenadier", "Tank"]; var unitNameText = new Text2(unitNames[self.tier - 1], { size: 30, fill: 0x000000 }); unitNameText.anchor.set(0.5, 0); unitNameText.y = 50; // Position below the tier text self.addChild(unitNameText); self.findTarget = function () { if (self.targets.length === 0) { return null; } // Sort targets by progress self.targets.sort(function (a, b) { return b.pathProgress - a.pathProgress; }); // Return the most progressed goblin return self.targets[0]; }; self.shoot = function (target) { if (!target || !target.active) { return; } var now = Date.now(); if (now - self.lastShot < self.fireRate) { return; } self.lastShot = now; var projectile = new Projectile(self, target, self.damage); projectiles.push(projectile); game.addChild(projectile); LK.getSound('shoot').play(); }; self.update = function () { if (self.merging) { return; } // Clean up destroyed targets self.targets = self.targets.filter(function (target) { return target.active; }); var target = self.findTarget(); if (target) { self.shoot(target); } }; self.down = function (x, y, obj) { if (!placingUnit && !gameOver) { self.isDragging = true; selectedUnit = self; if (self.gridPosition) { // Remove from grid grid[self.gridPosition.y][self.gridPosition.x].unit = null; self.gridPosition = null; } } }; self.checkForMerge = function (gridCell) { if (!gridCell || !gridCell.unit || gridCell.unit === self) { return false; } if (gridCell.unit.tier === self.tier && self.tier < 10) { // Merge units mergeUnits(self, gridCell.unit); return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x558855 }); /**** * Game Code ****/ // Game configuration var gridWidth = 7; var gridHeight = 6; var tileSize = 120; var grid = []; var pathPoints = []; var goblins = []; var projectiles = []; var units = []; var waves = []; var currentWave = 0; var waveInProgress = false; var selectedUnit = null; var placingUnit = null; var gold = 100; var lives = 3; var score = 0; var gameOver = false; var gridOffsetX = (2048 - gridWidth * tileSize) / 2; var gridOffsetY = 400; var highlight = null; var unitCost = 50; // UI elements var waveText; var goldText; var livesText; var scoreText; var nextWaveButton; var unitBuyButton; function initializeGrid() { for (var y = 0; y < gridHeight; y++) { grid[y] = []; for (var x = 0; x < gridWidth; x++) { grid[y][x] = { x: gridOffsetX + x * tileSize + tileSize / 2, y: gridOffsetY + y * tileSize + tileSize / 2, unit: null, isPath: false }; var tile = LK.getAsset('tile', { anchorX: 0.5, anchorY: 0.5 }); tile.x = grid[y][x].x; tile.y = grid[y][x].y; tile.alpha = 0.5; game.addChild(tile); } } } function createPath() { // Define a simple path through the grid var pathCoordinates = [{ x: 0, y: 2 }, { x: 1, y: 2 }, { x: 2, y: 2 }, { x: 3, y: 2 }, { x: 3, y: 3 }, { x: 3, y: 4 }, { x: 4, y: 4 }, { x: 5, y: 4 }, { x: 6, y: 4 }]; for (var i = 0; i < pathCoordinates.length; i++) { var coord = pathCoordinates[i]; var cell = grid[coord.y][coord.x]; cell.isPath = true; var pathTile = LK.getAsset('path', { anchorX: 0.5, anchorY: 0.5 }); pathTile.x = cell.x; pathTile.y = cell.y; pathTile.alpha = 0.7; game.addChild(pathTile); pathPoints.push({ x: cell.x, y: cell.y }); } // Add the base at the end of the path var lastCoord = pathCoordinates[pathCoordinates.length - 1]; var baseCell = grid[lastCoord.y][lastCoord.x]; var base = LK.getAsset('base', { anchorX: 0.5, anchorY: 0.5 }); base.x = baseCell.x + tileSize; base.y = baseCell.y; game.addChild(base); } function initializeWaves() { // Define waves of increasing difficulty waves = [{ count: 5, health: 8, speed: 1.5, value: 5, delay: 1000 }]; // Adjust health and speed for each subsequent wave for (var i = 1; i < 1000; i++) { // Generate a large number of waves waves.push({ count: 5 + i * 3, health: Math.round(waves[i - 1].health * 1.02), speed: parseFloat((waves[i - 1].speed * 1.02).toFixed(2)), value: 10 + i, delay: Math.max(200, 1000 - i * 50) // Ensure delay doesn't go below 200ms }); } } function startWave() { if (waveInProgress || gameOver) { return; } waveInProgress = true; currentWave++; // Removed wave limit check to make waves infinite waveText.setText("Wave: " + currentWave + " (Infinite)"); nextWaveButton.visible = false; var wave = waves[currentWave - 1]; var goblinsReleased = 0; var spawnInterval = LK.setInterval(function () { spawnGoblin(wave); goblinsReleased++; if (goblinsReleased >= wave.count) { LK.clearInterval(spawnInterval); // Check every second if wave is complete var checkInterval = LK.setInterval(function () { if (goblins.length === 0) { waveInProgress = false; nextWaveButton.visible = true; LK.clearInterval(checkInterval); } }, 1000); } }, wave.delay); } function spawnGoblin(wave) { var goblin = new Goblin(pathPoints, wave.health, wave.speed, wave.value); goblins.push(goblin); game.addChild(goblin); // Add this goblin as a target for all units in range units.forEach(function (unit) { var dx = unit.x - goblin.x; var dy = unit.y - goblin.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= unit.range) { unit.targets.push(goblin); } }); } function createUnit(tier) { var unit = new Unit(tier); units.push(unit); return unit; } function placeUnit(unit, gridX, gridY) { if (gridX < 0 || gridX >= gridWidth || gridY < 0 || gridY >= gridHeight) { return false; } var gridCell = grid[gridY][gridX]; if (gridCell.isPath || gridCell.unit) { return false; } // Place the unit unit.x = gridCell.x; unit.y = gridCell.y; unit.gridPosition = { x: gridX, y: gridY }; gridCell.unit = unit; // Find nearby targets goblins.forEach(function (goblin) { if (goblin.active) { var dx = unit.x - goblin.x; var dy = unit.y - goblin.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= unit.range) { unit.targets.push(goblin); } } }); LK.getSound('place').play(); return true; } function mergeUnits(unit1, unit2) { // Create a new unit of the next tier var newUnit = createUnit(unit1.tier + 1); game.addChild(newUnit); // Place at the position of the second unit newUnit.gridPosition = unit2.gridPosition; grid[unit2.gridPosition.y][unit2.gridPosition.x].unit = newUnit; newUnit.x = unit2.x; newUnit.y = unit2.y; // Remove the merged units unit1.merging = true; unit2.merging = true; // Effect tween(unit1, { x: unit2.x, y: unit2.y, alpha: 0 }, { duration: 300, onFinish: function onFinish() { unit1.destroy(); removeFromArray(units, unit1); } }); tween(unit2, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { unit2.destroy(); removeFromArray(units, unit2); } }); // Scale up effect for new unit newUnit.scale.x = 0.5; newUnit.scale.y = 0.5; tween(newUnit.scale, { x: 1, y: 1 }, { duration: 300, easing: tween.elasticOut }); LK.getSound('merge').play(); return newUnit; } function buyUnit() { if (gold < unitCost || placingUnit || gameOver) { return; } gold -= unitCost; goldText.setText("Gold: " + gold); placingUnit = createUnit(1); game.addChild(placingUnit); // Create highlight if it doesn't exist if (!highlight) { highlight = LK.getAsset('highlight', { anchorX: 0.5, anchorY: 0.5 }); highlight.alpha = 0.3; game.addChild(highlight); } highlight.visible = true; } function createUI() { // Wave text waveText = new Text2("Wave: 0/" + waves.length, { size: 50, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); // Gold text goldText = new Text2("Gold: " + gold, { size: 50, fill: 0xFFD700 }); goldText.anchor.set(0, 0); LK.gui.topLeft.addChild(goldText); goldText.x = 120; // Move away from the top left corner // Lives text livesText = new Text2("Lives: " + lives, { size: 50, fill: 0xFF0000 }); livesText.anchor.set(1, 0); LK.gui.topRight.addChild(livesText); // Score text scoreText = new Text2("Score: " + score, { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 80; // Next wave button nextWaveButton = new Container(); var nextWaveButtonBg = LK.getAsset('tile', { width: 300, height: 100, color: 0x336699, anchorX: 0.5, anchorY: 0.5 }); nextWaveButton.addChild(nextWaveButtonBg); var nextWaveButtonText = new Text2("Next Wave", { size: 50, fill: 0xFFFFFF }); nextWaveButtonText.anchor.set(0.5, 0.5); nextWaveButton.addChild(nextWaveButtonText); nextWaveButton.down = function () { startWave(); }; LK.gui.bottom.addChild(nextWaveButton); nextWaveButton.y = -150; // Buy unit button unitBuyButton = new Container(); var unitBuyButtonBg = LK.getAsset('tile', { width: 300, height: 100, color: 0x669933, anchorX: 0.5, anchorY: 0.5 }); unitBuyButton.addChild(unitBuyButtonBg); var unitBuyButtonText = new Text2("Buy Unit: " + unitCost + "g", { size: 40, fill: 0xFFFFFF }); unitBuyButtonText.anchor.set(0.5, 0.5); unitBuyButton.addChild(unitBuyButtonText); unitBuyButton.down = function () { buyUnit(); }; LK.gui.bottomLeft.addChild(unitBuyButton); unitBuyButton.y = -150; unitBuyButton.x = 170; } function endGame() { if (gameOver) { return; } gameOver = true; if (score > storage.highScore) { storage.highScore = score; } LK.getSound('game_over').play(); LK.showGameOver(); } function removeFromArray(array, item) { var index = array.indexOf(item); if (index !== -1) { array.splice(index, 1); } } function initialize() { initializeGrid(); createPath(); initializeWaves(); createUI(); // Play background music LK.playMusic('bg_music'); // Create highlight for placing units (initially hidden) highlight = LK.getAsset('highlight', { anchorX: 0.5, anchorY: 0.5 }); highlight.alpha = 0.3; highlight.visible = false; game.addChild(highlight); // Start with wave 0 waveText.setText("Wave: 0/" + waves.length); } initialize(); game.move = function (x, y) { if (gameOver) { return; } if (selectedUnit) { selectedUnit.x = x; selectedUnit.y = y; } else if (placingUnit) { // Find the closest grid cell var gridX = Math.floor((x - gridOffsetX) / tileSize); var gridY = Math.floor((y - gridOffsetY) / tileSize); if (gridX >= 0 && gridX < gridWidth && gridY >= 0 && gridY < gridHeight) { var cell = grid[gridY][gridX]; placingUnit.x = x; placingUnit.y = y; highlight.x = cell.x; highlight.y = cell.y; highlight.visible = true; // Change highlight color based on valid placement if (cell.isPath || cell.unit) { highlight.tint = 0xFF0000; } else { highlight.tint = 0x00FF00; } } else { highlight.visible = false; } } }; game.down = function (x, y) { if (gameOver) { return; } // If we're placing a new unit if (placingUnit) { var gridX = Math.floor((x - gridOffsetX) / tileSize); var gridY = Math.floor((y - gridOffsetY) / tileSize); if (gridX >= 0 && gridX < gridWidth && gridY >= 0 && gridY < gridHeight) { if (placeUnit(placingUnit, gridX, gridY)) { placingUnit = null; highlight.visible = false; } } } }; game.up = function (x, y) { if (gameOver) { return; } if (selectedUnit && selectedUnit.isDragging) { var gridX = Math.floor((x - gridOffsetX) / tileSize); var gridY = Math.floor((y - gridOffsetY) / tileSize); if (gridX >= 0 && gridX < gridWidth && gridY >= 0 && gridY < gridHeight) { var gridCell = grid[gridY][gridX]; if (selectedUnit.checkForMerge(gridCell)) { // Merged successfully } else if (!gridCell.isPath && !gridCell.unit) { // Place on empty cell placeUnit(selectedUnit, gridX, gridY); } else { // Invalid placement, return to original position if any if (selectedUnit.gridPosition) { selectedUnit.x = grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].x; selectedUnit.y = grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].y; grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].unit = selectedUnit; } else { // If it didn't have a grid position, destroy it selectedUnit.destroy(); removeFromArray(units, selectedUnit); } } } else { // Dragged off grid, return to original position if any if (selectedUnit.gridPosition) { selectedUnit.x = grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].x; selectedUnit.y = grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].y; grid[selectedUnit.gridPosition.y][selectedUnit.gridPosition.x].unit = selectedUnit; } else { // If it didn't have a grid position, destroy it selectedUnit.destroy(); removeFromArray(units, selectedUnit); } } selectedUnit.isDragging = false; selectedUnit = null; } }; game.update = function () { // Update all active goblins for (var i = goblins.length - 1; i >= 0; i--) { if (goblins[i].active) { goblins[i].update(); } else { removeFromArray(goblins, goblins[i]); } } // Update all active projectiles for (var i = projectiles.length - 1; i >= 0; i--) { if (projectiles[i].active) { projectiles[i].update(); } else { removeFromArray(projectiles, projectiles[i]); } } // Update all units for (var i = 0; i < units.length; i++) { if (!units[i].merging) { units[i].update(); } } // Check if units in range of goblins units.forEach(function (unit) { if (unit.merging) { return; } // Reset targets and find new ones unit.targets = []; goblins.forEach(function (goblin) { if (goblin.active) { var dx = unit.x - goblin.x; var dy = unit.y - goblin.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= unit.range) { unit.targets.push(goblin); } } }); }); };
===================================================================
--- original.js
+++ change.js
@@ -371,15 +371,16 @@
value: 5,
delay: 1000
}];
// Adjust health and speed for each subsequent wave
- for (var i = 1; i < 10; i++) {
+ for (var i = 1; i < 1000; i++) {
+ // Generate a large number of waves
waves.push({
count: 5 + i * 3,
health: Math.round(waves[i - 1].health * 1.02),
speed: parseFloat((waves[i - 1].speed * 1.02).toFixed(2)),
value: 10 + i,
- delay: 1000 - i * 50
+ delay: Math.max(200, 1000 - i * 50) // Ensure delay doesn't go below 200ms
});
}
}
function startWave() {
@@ -387,14 +388,10 @@
return;
}
waveInProgress = true;
currentWave++;
- if (currentWave > waves.length) {
- // Player has completed all waves!
- LK.showYouWin();
- return;
- }
- waveText.setText("Wave: " + currentWave + "/" + waves.length);
+ // Removed wave limit check to make waves infinite
+ waveText.setText("Wave: " + currentWave + " (Infinite)");
nextWaveButton.visible = false;
var wave = waves[currentWave - 1];
var goblinsReleased = 0;
var spawnInterval = LK.setInterval(function () {