User prompt
enemies spawn at the beginning and move towards the end of the path, so fix the progress of the enemies
User prompt
Aliens spawn at the beginning and move towards the end of the path, so fix the progress of the aliens
User prompt
Let the enemies spawn at the beginning of the brown road
Code edit (1 edits merged)
Please save this source code
User prompt
Fortress Guardian
Initial prompt
make a tower defense game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Enemy = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'basicEnemy'; self.enemyGraphic = self.attachAsset(self.type, { anchorX: 0.5, anchorY: 0.5 }); switch (self.type) { case 'basicEnemy': self.maxHealth = 100; self.speed = 1.5; self.goldValue = 10; break; case 'fastEnemy': self.maxHealth = 75; self.speed = 2.5; self.goldValue = 15; break; case 'tankEnemy': self.maxHealth = 250; self.speed = 0.8; self.goldValue = 25; break; case 'bossEnemy': self.maxHealth = 500; self.speed = 1.0; self.goldValue = 100; break; default: self.maxHealth = 100; self.speed = 1.5; self.goldValue = 10; } self.health = self.maxHealth; self.currentPathIndex = 0; self.reachedEnd = false; // Health bar self.healthBarBackground = new Container(); self.healthBarBackground.width = self.enemyGraphic.width * 1.2; self.healthBarBackground.height = 10; self.healthBarBackground.x = -self.healthBarBackground.width / 2; self.healthBarBackground.y = -self.enemyGraphic.height / 2 - 15; self.addChild(self.healthBarBackground); self.healthBar = new Container(); self.healthBar.width = self.healthBarBackground.width; self.healthBar.height = self.healthBarBackground.height; self.healthBar.x = self.healthBarBackground.x; self.healthBar.y = self.healthBarBackground.y; self.addChild(self.healthBar); self.updateHealthBar = function () { var healthPercentage = self.health / self.maxHealth; self.healthBar.width = self.healthBarBackground.width * healthPercentage; // Change color based on health percentage if (healthPercentage > 0.6) { self.healthBar.tint = 0x00FF00; // Green } else if (healthPercentage > 0.3) { self.healthBar.tint = 0xFFFF00; // Yellow } else { self.healthBar.tint = 0xFF0000; // Red } }; self.takeDamage = function (amount) { self.health -= amount; self.updateHealthBar(); // Briefly flash the enemy when taking damage tween(self.enemyGraphic, { alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(self.enemyGraphic, { alpha: 1 }, { duration: 100 }); } }); if (self.health <= 0) { return true; // Enemy is dead } return false; // Enemy is still alive }; self.moveAlongPath = function (path) { if (self.currentPathIndex >= path.length) { self.reachedEnd = true; return true; } var targetX = path[self.currentPathIndex].x; var targetY = path[self.currentPathIndex].y; var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 5) { self.currentPathIndex++; return false; } var normalizedX = dx / distance; var normalizedY = dy / distance; self.x += normalizedX * self.speed; self.y += normalizedY * self.speed; return false; }; self.updateHealthBar(); return self; }); var MapTile = Container.expand(function (tileType) { var self = Container.call(this); self.tileType = tileType || 'grass'; self.canPlaceTower = self.tileType === 'grass'; var tileGraphic = self.attachAsset(self.tileType, { anchorX: 0.5, anchorY: 0.5 }); self.setHighlight = function (highlight) { if (highlight && self.canPlaceTower) { tileGraphic.alpha = 0.8; } else { tileGraphic.alpha = 1.0; } }; return self; }); var Projectile = Container.expand(function (targetEnemy, damage, speed, type) { var self = Container.call(this); self.targetEnemy = targetEnemy; self.damage = damage || 25; self.speed = speed || 10; self.projectileType = type || 'projectile'; var projectileGraphic = self.attachAsset(self.projectileType, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (!self.targetEnemy || !self.targetEnemy.parent) { self.destroy(); return; } var dx = self.targetEnemy.x - self.x; var dy = self.targetEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 15) { // Hit enemy if (self.targetEnemy.takeDamage(self.damage)) { // Enemy is dead gameState.gold += self.targetEnemy.goldValue; gameState.score += self.targetEnemy.goldValue; updateGoldText(); updateScoreText(); LK.getSound('enemyDeath').play(); var enemyIndex = gameState.enemies.indexOf(self.targetEnemy); if (enemyIndex !== -1) { self.targetEnemy.destroy(); gameState.enemies.splice(enemyIndex, 1); } } self.destroy(); return; } // Move toward enemy var normalizedX = dx / distance; var normalizedY = dy / distance; self.x += normalizedX * self.speed; self.y += normalizedY * self.speed; // Rotate projectile to face direction of travel self.rotation = Math.atan2(dy, dx) + Math.PI / 2; }; return self; }); var Tower = Container.expand(function (type) { var self = Container.call(this); self.towerType = type || 'baseTower'; self.baseTower = self.attachAsset('baseTower', { anchorX: 0.5, anchorY: 0.5 }); self.towerGraphic = self.attachAsset(self.towerType, { anchorX: 0.5, anchorY: 0.5, y: -10 }); // Tower properties based on type switch (self.towerType) { case 'cannonTower': self.damage = 40; self.range = 200; self.attackSpeed = 1.5; // Attacks per second self.cost = 100; self.projectileSpeed = 8; self.targetingStrategy = 'first'; // Target first enemy in path break; case 'archerTower': self.damage = 20; self.range = 300; self.attackSpeed = 3; // Attacks per second self.cost = 150; self.projectileSpeed = 15; self.targetingStrategy = 'first'; break; case 'magicTower': self.damage = 30; self.range = 250; self.attackSpeed = 2; // Attacks per second self.cost = 200; self.projectileSpeed = 10; self.targetingStrategy = 'strongest'; // Target enemy with most health break; default: self.damage = 25; self.range = 200; self.attackSpeed = 1; // Attacks per second self.cost = 50; self.projectileSpeed = 8; self.targetingStrategy = 'first'; } self.level = 1; self.attackCooldown = 0; self.rangeIndicator = null; self.selected = false; // Show range indicator when tower is selected self.showRange = function (show) { if (show && !self.rangeIndicator) { self.rangeIndicator = self.attachAsset('rangeIndicator', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3, scaleX: self.range / 300, // Scale to match tower's range scaleY: self.range / 300 }); self.rangeIndicator.zIndex = -1; } else if (!show && self.rangeIndicator) { self.removeChild(self.rangeIndicator); self.rangeIndicator = null; } }; self.upgrade = function () { if (self.level >= 3) return false; // Max level reached var upgradeCost = self.cost * self.level; if (gameState.gold < upgradeCost) return false; // Not enough gold gameState.gold -= upgradeCost; self.level++; // Upgrade stats self.damage *= 1.5; self.range *= 1.2; self.attackSpeed *= 1.2; // Update visuals for upgraded tower self.towerGraphic.scale.set(1 + (self.level - 1) * 0.2); // Update range indicator if visible if (self.rangeIndicator) { self.removeChild(self.rangeIndicator); self.showRange(true); } updateGoldText(); return true; }; self.findTarget = function (enemies) { var target = null; var maxPriority = -1; var minDistance = Infinity; 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 <= self.range) { var priority = 0; switch (self.targetingStrategy) { case 'first': priority = enemy.currentPathIndex + (1 - distance / self.range); break; case 'strongest': priority = enemy.health; break; case 'closest': priority = self.range - distance; break; } if (priority > maxPriority || priority === maxPriority && distance < minDistance) { maxPriority = priority; minDistance = distance; target = enemy; } } } return target; }; self.attackEnemy = function (enemy) { if (!enemy) return; // Create projectile var projectile = new Projectile(enemy, self.damage, self.projectileSpeed); projectile.x = self.x; projectile.y = self.y; game.addChild(projectile); gameState.projectiles.push(projectile); LK.getSound('projectileShot').play(); // Reset cooldown self.attackCooldown = 60 / self.attackSpeed; // Tower attack animation tween(self.towerGraphic, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(self.towerGraphic, { scaleX: 1 + (self.level - 1) * 0.2, scaleY: 1 + (self.level - 1) * 0.2 }, { duration: 100 }); } }); }; self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } else { var target = self.findTarget(gameState.enemies); if (target) { self.attackEnemy(target); } } }; self.down = function (x, y, obj) { // Select this tower, deselect others selectTower(self); }; return self; }); var TowerButton = Container.expand(function (towerType, cost) { var self = Container.call(this); self.towerType = towerType; self.cost = cost; var button = self.attachAsset('uiButton', { anchorX: 0.5, anchorY: 0.5 }); var towerPreview = self.attachAsset(towerType, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var costText = new Text2(cost.toString(), { size: 24, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0.5); costText.y = 30; self.addChild(costText); self.setEnabled = function (enabled) { button.alpha = enabled ? 1.0 : 0.5; towerPreview.alpha = enabled ? 1.0 : 0.5; self.enabled = enabled; }; self.down = function (x, y, obj) { if (!self.enabled) return; // Set the selected tower type for placement gameState.selectedTowerType = self.towerType; gameState.placingTower = true; // Deselect any selected tower if (gameState.selectedTower) { gameState.selectedTower.showRange(false); gameState.selectedTower = null; } // Show tower placeholders for (var i = 0; i < gameState.map.length; i++) { for (var j = 0; j < gameState.map[i].length; j++) { var tile = gameState.map[i][j]; if (tile.canPlaceTower && !tile.tower) { tile.setHighlight(true); } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2B5329 // Green background for the game }); /**** * Game Code ****/ // Music // Sounds // Map and UI assets // Enemy assets // Tower assets // Game state variables var gameState = { gold: 200, lives: 10, score: 0, wave: 0, enemyCount: 0, waveInProgress: false, selectedTower: null, selectedTowerType: null, placingTower: false, map: [], towers: [], enemies: [], projectiles: [], path: [], tileSize: 100, mapWidth: 10, mapHeight: 10 }; // Create UI elements var scoreText = new Text2('Score: 0', { size: 36, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var goldText = new Text2('Gold: ' + gameState.gold, { size: 36, fill: 0xFFD700 }); goldText.anchor.set(0, 0); goldText.x = 150; LK.gui.topLeft.addChild(goldText); var livesText = new Text2('Lives: ' + gameState.lives, { size: 36, fill: 0xFF0000 }); livesText.anchor.set(1, 0); livesText.x = -150; LK.gui.topRight.addChild(livesText); var waveText = new Text2('Wave: ' + gameState.wave, { size: 36, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); waveText.y = 50; LK.gui.top.addChild(waveText); var nextWaveButton = new Container(); var nextWaveButtonGraphic = nextWaveButton.attachAsset('uiButton', { anchorX: 0.5, anchorY: 0.5 }); var nextWaveButtonText = new Text2('Next Wave', { size: 30, fill: 0xFFFFFF }); nextWaveButtonText.anchor.set(0.5, 0.5); nextWaveButton.addChild(nextWaveButtonText); nextWaveButton.x = 0; nextWaveButton.y = -100; LK.gui.bottom.addChild(nextWaveButton); // Create tower buttons UI var towerButtonsContainer = new Container(); towerButtonsContainer.y = -200; LK.gui.bottom.addChild(towerButtonsContainer); var towerButtons = [{ type: 'cannonTower', cost: 100 }, { type: 'archerTower', cost: 150 }, { type: 'magicTower', cost: 200 }]; var buttonSpacing = 220; for (var i = 0; i < towerButtons.length; i++) { var button = new TowerButton(towerButtons[i].type, towerButtons[i].cost); button.x = (i - (towerButtons.length - 1) / 2) * buttonSpacing; towerButtonsContainer.addChild(button); } // Tower upgrade button and sell button var upgradeButton = new Container(); var upgradeButtonGraphic = upgradeButton.attachAsset('uiButton', { anchorX: 0.5, anchorY: 0.5 }); var upgradeButtonText = new Text2('Upgrade', { size: 30, fill: 0xFFFFFF }); upgradeButtonText.anchor.set(0.5, 0.5); upgradeButton.addChild(upgradeButtonText); upgradeButton.visible = false; upgradeButton.x = -120; upgradeButton.y = -300; LK.gui.bottom.addChild(upgradeButton); var sellButton = new Container(); var sellButtonGraphic = sellButton.attachAsset('uiButton', { anchorX: 0.5, anchorY: 0.5 }); var sellButtonText = new Text2('Sell', { size: 30, fill: 0xFFFFFF }); sellButtonText.anchor.set(0.5, 0.5); sellButton.addChild(sellButtonText); sellButton.visible = false; sellButton.x = 120; sellButton.y = -300; LK.gui.bottom.addChild(sellButton); // Update functions for UI elements function updateScoreText() { scoreText.setText('Score: ' + gameState.score); } function updateGoldText() { goldText.setText('Gold: ' + gameState.gold); // Update tower buttons enabled/disabled state based on gold for (var i = 0; i < towerButtonsContainer.children.length; i++) { var button = towerButtonsContainer.children[i]; button.setEnabled(gameState.gold >= button.cost); } } function updateLivesText() { livesText.setText('Lives: ' + gameState.lives); } function updateWaveText() { waveText.setText('Wave: ' + gameState.wave); } // Generate the game map with path function generateMap() { // Define map layout var layout = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 1, 1, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 1, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 2]]; var startX = 0; var startY = 0; var endX = 0; var endY = 0; // X offset to center map on screen var offsetX = (2048 - gameState.mapWidth * gameState.tileSize) / 2; var offsetY = (2732 - gameState.mapHeight * gameState.tileSize) / 2 - 150; // Offset to account for UI // Create map tiles based on layout for (var i = 0; i < gameState.mapHeight; i++) { gameState.map[i] = []; for (var j = 0; j < gameState.mapWidth; j++) { var tileType = layout[i][j] === 1 ? 'path' : 'grass'; // Handle start point (entry point) if (layout[i][j] === 1 && (i === 0 || j === 0 || i === gameState.mapHeight - 1 || j === gameState.mapWidth - 1)) { if (gameState.path.length === 0) { startX = j * gameState.tileSize + offsetX + gameState.tileSize / 2; startY = i * gameState.tileSize + offsetY + gameState.tileSize / 2; } } // Handle end point (base) if (layout[i][j] === 2) { tileType = 'baseStructure'; endX = j * gameState.tileSize + offsetX + gameState.tileSize / 2; endY = i * gameState.tileSize + offsetY + gameState.tileSize / 2; } var tile = new MapTile(tileType); tile.x = j * gameState.tileSize + offsetX + gameState.tileSize / 2; tile.y = i * gameState.tileSize + offsetY + gameState.tileSize / 2; tile.gridX = j; tile.gridY = i; tile.tower = null; gameState.map[i][j] = tile; game.addChild(tile); // Add to path if it's a path tile if (tileType === 'path') { gameState.path.push({ x: tile.x, y: tile.y, tile: tile }); } } } // Sort path from start to end (using a simplified approach for this straight path) // This is a simplification - a real game would need a proper path finding algorithm gameState.path.sort(function (a, b) { var distA = Math.sqrt(Math.pow(a.x - startX, 2) + Math.pow(a.y - startY, 2)); var distB = Math.sqrt(Math.pow(b.x - startX, 2) + Math.pow(b.y - startY, 2)); return distA - distB; }); // The first point should be off-screen for enemy spawn gameState.path.unshift({ x: startX - gameState.tileSize, y: startY, offScreen: true }); // The last point is the base gameState.path.push({ x: endX, y: endY, isBase: true }); } // Start a new wave of enemies function startWave() { if (gameState.waveInProgress) return; gameState.wave++; updateWaveText(); gameState.waveInProgress = true; gameState.enemyCount = 5 + gameState.wave * 2; // More enemies per wave LK.getSound('waveStart').play(); var spawnInterval = LK.setInterval(function () { spawnEnemy(); gameState.enemyCount--; if (gameState.enemyCount <= 0) { LK.clearInterval(spawnInterval); // Wave is considered over when all enemies are spawned // The actual check for wave completion is in the update function } }, 1500 - gameState.wave * 100); // Spawn faster in later waves } // Spawn an enemy function spawnEnemy() { var enemyTypes = ['basicEnemy']; // Add more enemy types as waves progress if (gameState.wave >= 3) enemyTypes.push('fastEnemy'); if (gameState.wave >= 5) enemyTypes.push('tankEnemy'); if (gameState.wave >= 10 && gameState.wave % 5 === 0) enemyTypes.push('bossEnemy'); var randomType = enemyTypes[Math.floor(Math.random() * enemyTypes.length)]; // Always spawn a boss on wave 5, 10, 15, etc. if (gameState.wave % 5 === 0 && gameState.enemyCount === 0) { randomType = 'bossEnemy'; } var enemy = new Enemy(randomType); // Spawn at the start of the path // Use the first path point (index 0), which is off-screen var startPoint = gameState.path[0]; enemy.x = startPoint.x; enemy.y = startPoint.y; // Set the initial path index to 0 so enemies start from beginning enemy.currentPathIndex = 0; gameState.enemies.push(enemy); game.addChild(enemy); } // Check if wave is complete function checkWaveComplete() { if (gameState.waveInProgress && gameState.enemyCount <= 0 && gameState.enemies.length === 0) { gameState.waveInProgress = false; gameState.gold += 50 + gameState.wave * 10; // Bonus gold for completing wave updateGoldText(); } } // Place a tower on the map function placeTower(gridX, gridY) { var tile = gameState.map[gridY][gridX]; if (!tile.canPlaceTower || tile.tower) return false; var towerCost = 0; switch (gameState.selectedTowerType) { case 'cannonTower': towerCost = 100; break; case 'archerTower': towerCost = 150; break; case 'magicTower': towerCost = 200; break; default: towerCost = 100; } if (gameState.gold < towerCost) return false; var tower = new Tower(gameState.selectedTowerType); tower.x = tile.x; tower.y = tile.y; tower.gridX = gridX; tower.gridY = gridY; tile.tower = tower; gameState.towers.push(tower); game.addChild(tower); gameState.gold -= towerCost; updateGoldText(); LK.getSound('buildTower').play(); // Clear tower placement mode clearTowerPlacement(); return true; } // Select a tower function selectTower(tower) { // Deselect previously selected tower if (gameState.selectedTower) { gameState.selectedTower.showRange(false); } // Clear tower placement mode clearTowerPlacement(); // Select new tower gameState.selectedTower = tower; tower.showRange(true); // Show upgrade and sell buttons upgradeButton.visible = true; sellButton.visible = true; } // Clear tower placement mode function clearTowerPlacement() { gameState.placingTower = false; gameState.selectedTowerType = null; // Remove highlights from all tiles for (var i = 0; i < gameState.map.length; i++) { for (var j = 0; j < gameState.map[i].length; j++) { gameState.map[i][j].setHighlight(false); } } } // Handle game over function checkGameOver() { if (gameState.lives <= 0) { // Update high score if (gameState.score > storage.highScore) { storage.highScore = gameState.score; } // Game over LK.getSound('gameOver').play(); LK.showGameOver(); } } // Event handlers nextWaveButton.down = function () { if (!gameState.waveInProgress) { startWave(); } }; upgradeButton.down = function () { if (gameState.selectedTower) { if (gameState.selectedTower.upgrade()) { // Success - tower was upgraded } else { // Failed to upgrade (either max level or not enough gold) } } }; sellButton.down = function () { if (gameState.selectedTower) { // Refund 70% of tower cost var refundAmount = Math.floor(gameState.selectedTower.cost * 0.7); gameState.gold += refundAmount; updateGoldText(); // Remove tower from map and arrays var tile = gameState.map[gameState.selectedTower.gridY][gameState.selectedTower.gridX]; tile.tower = null; var towerIndex = gameState.towers.indexOf(gameState.selectedTower); if (towerIndex !== -1) { gameState.towers.splice(towerIndex, 1); } gameState.selectedTower.destroy(); gameState.selectedTower = null; // Hide buttons upgradeButton.visible = false; sellButton.visible = false; } }; game.down = function (x, y, obj) { if (gameState.placingTower) { // Find which tile was clicked for (var i = 0; i < gameState.map.length; i++) { for (var j = 0; j < gameState.map[i].length; j++) { var tile = gameState.map[i][j]; var dx = tile.x - x; var dy = tile.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < gameState.tileSize / 2) { if (placeTower(j, i)) { return; // Tower placed successfully } } } } // Clicked outside valid tile, cancel placement clearTowerPlacement(); } else { // Check if clicked on a tower var towerClicked = false; for (var i = 0; i < gameState.towers.length; i++) { var tower = gameState.towers[i]; var dx = tower.x - x; var dy = tower.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < gameState.tileSize / 2) { selectTower(tower); towerClicked = true; break; } } // If clicked outside tower, deselect current tower if (!towerClicked && gameState.selectedTower) { gameState.selectedTower.showRange(false); gameState.selectedTower = null; upgradeButton.visible = false; sellButton.visible = false; } } }; // Main update function game.update = function () { // Update all towers for (var i = 0; i < gameState.towers.length; i++) { gameState.towers[i].update(); } // Update all projectiles for (var i = gameState.projectiles.length - 1; i >= 0; i--) { gameState.projectiles[i].update(); // Check if projectile needs to be removed if (!gameState.projectiles[i].parent) { gameState.projectiles.splice(i, 1); } } // Update all enemies for (var i = gameState.enemies.length - 1; i >= 0; i--) { var enemy = gameState.enemies[i]; var reachedEnd = enemy.moveAlongPath(gameState.path); if (reachedEnd) { // Enemy reached the base, player loses a life gameState.lives--; updateLivesText(); LK.getSound('playerDamage').play(); // Remove enemy enemy.destroy(); gameState.enemies.splice(i, 1); // Flash screen LK.effects.flashScreen(0xFF0000, 500); // Check for game over checkGameOver(); } } // Check if wave is complete checkWaveComplete(); // Update UI button states nextWaveButton.alpha = gameState.waveInProgress ? 0.5 : 1.0; }; // Initialize game function initGame() { // Reset game state gameState.gold = 200; gameState.lives = 10; gameState.score = 0; gameState.wave = 0; gameState.waveInProgress = false; gameState.selectedTower = null; gameState.selectedTowerType = null; gameState.placingTower = false; gameState.map = []; gameState.towers = []; gameState.enemies = []; gameState.projectiles = []; gameState.path = []; // Update UI updateScoreText(); updateGoldText(); updateLivesText(); updateWaveText(); // Generate map generateMap(); // Hide upgrade and sell buttons upgradeButton.visible = false; sellButton.visible = false; // Play background music LK.playMusic('bgMusic'); } // Start the game initGame();
===================================================================
--- original.js
+++ change.js
@@ -631,12 +631,14 @@
randomType = 'bossEnemy';
}
var enemy = new Enemy(randomType);
// Spawn at the start of the path
- // Find the first actual path tile (index 1), as index 0 is off-screen
- var startPoint = gameState.path[1];
+ // Use the first path point (index 0), which is off-screen
+ var startPoint = gameState.path[0];
enemy.x = startPoint.x;
enemy.y = startPoint.y;
+ // Set the initial path index to 0 so enemies start from beginning
+ enemy.currentPathIndex = 0;
gameState.enemies.push(enemy);
game.addChild(enemy);
}
// Check if wave is complete
a archer robot. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a robotic heart. In-Game asset. 2d. High contrast. No shadows
a alien with space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a king alien with space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a cannon robot. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a fast alien with space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a magic wizard robot. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a tank alien with space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat