User prompt
her wavede 5 elmas kazanalım
User prompt
oyuna boss ekle wave 10 da boss gelsin ve yeni para birimi elmas gelsin elmas sayesinde bütün towerleri güçlendirebilelim ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yeni kaleler ekle ve daha çok animasyon ve güçlendirme ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(enemyGraphics, {' Line Number: 207 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var globalPos = obj.parent.toGlobal(obj.position);' Line Number: 364
User prompt
başta 390 altın ile başlayalım ve kuleleri tıklama ile taşıma ekle
User prompt
kule taşıma ve daha animasyon ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yeni kaleler ekle şavasçılar
User prompt
geliştir fuc king
Code edit (1 edits merged)
Please save this source code
User prompt
Tower Defense 3D
Initial prompt
tower defense 3d
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 25; self.target = null; self.hasHit = false; self.update = function () { if (!self.target || self.hasHit) return; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { if (self.isSplash) { // Splash damage to all enemies in radius for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) continue; var splashDx = enemy.x - self.x; var splashDy = enemy.y - self.y; var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy); if (splashDistance <= self.splashRadius) { enemy.takeDamage(self.damage); } } } else if (self.isMagic) { // Magic damage with slow effect self.target.takeDamage(self.damage); self.target.applySlow(self.slowEffect, self.slowDuration); } else { // Regular damage self.target.takeDamage(self.damage); } self.hasHit = true; LK.getSound('enemyHit').play(); return; } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 100; self.health = self.maxHealth; self.speed = 2; self.reward = 10; self.pathIndex = 0; self.isDead = false; self.reachedBase = false; self.originalSpeed = self.speed; self.slowEndTime = 0; self.isSlowed = false; // Add health bar var healthBarBg = LK.getAsset('pathTile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.1 }); healthBarBg.y = -40; healthBarBg.tint = 0x333333; self.addChild(healthBarBg); var healthBar = LK.getAsset('grassTile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.1 }); healthBar.y = -40; healthBar.tint = 0x00FF00; self.addChild(healthBar); self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; healthBar.scaleX = 0.6 * healthPercent; if (healthPercent > 0.6) { healthBar.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { healthBar.tint = 0xFFFF00; // Yellow } else { healthBar.tint = 0xFF0000; // Red } }; self.applySlow = function (slowFactor, duration) { self.speed = self.originalSpeed * slowFactor; self.slowEndTime = LK.ticks + duration; self.isSlowed = true; enemyGraphics.tint = 0x3498db; // Blue tint for slowed enemies }; self.takeDamage = function (damage) { self.health -= damage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; updateUI(); // Death animation tween.to(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, 500); } }; self.update = function () { if (self.isDead || self.reachedBase) return; // Check if slow effect should end if (self.isSlowed && LK.ticks >= self.slowEndTime) { self.speed = self.originalSpeed; self.isSlowed = false; enemyGraphics.tint = 0xFFFFFF; // Reset tint } if (self.pathIndex < enemyPath.length) { var target = enemyPath[self.pathIndex]; var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { self.pathIndex++; if (self.pathIndex >= enemyPath.length) { self.reachedBase = true; lives--; updateUI(); return; } } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; } }; return self; }); var MagicWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with magic warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('magicWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 120; self.health = self.maxHealth; self.speed = 2.2; self.originalSpeed = self.speed; self.reward = 20; self.enemyType = 'magic'; self.magicResistance = 0.5; // Takes 50% less damage from magic towers self.takeDamage = function (damage, damageType) { var actualDamage = damage; if (damageType === 'magic') { actualDamage = damage * self.magicResistance; } self.health -= actualDamage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; updateUI(); tween.to(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, 500); } }; return self; }); var HeavyWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with heavy warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('heavyWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 200; self.health = self.maxHealth; self.speed = 1.0; self.originalSpeed = self.speed; self.reward = 25; self.enemyType = 'heavy'; return self; }); var FastWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with fast warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('fastWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 60; self.health = self.maxHealth; self.speed = 3.5; self.originalSpeed = self.speed; self.reward = 15; self.enemyType = 'fast'; return self; }); var Tower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('tower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 150; self.damage = 25; self.fireRate = 60; self.lastFire = 0; self.cost = 50; self.level = 1; self.maxLevel = 3; self.showingRange = false; self.upgradeCost = 75; var rangeIndicator = self.attachAsset('towerRange', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.visible = false; self.showRange = function () { rangeIndicator.visible = true; self.showingRange = true; }; self.hideRange = function () { rangeIndicator.visible = false; self.showingRange = false; }; self.findTarget = function () { var closestEnemy = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) continue; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range && distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } return closestEnemy; }; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) return; var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; bullets.push(bullet); game.addChild(bullet); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) return false; currency -= self.upgradeCost; self.level++; self.damage += 15; self.range += 25; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); // Update range indicator rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; // Visual upgrade indicator towerGraphics.tint = self.level === 2 ? 0x3A7BD5 : 0x2E5BBA; updateUI(); return true; }; self.down = function (x, y, obj) { if (selectedTower === self) { // Try to upgrade if tower is selected if (self.level < self.maxLevel && currency >= self.upgradeCost) { self.upgrade(); } selectedTower = null; hideAllRanges(); } else { // Select this tower selectedTower = self; hideAllRanges(); self.showRange(); } }; self.update = function () { var target = self.findTarget(); if (target) { self.fire(target); } }; return self; }); var MagicTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with magic tower self.removeChildAt(0); var towerGraphics = self.attachAsset('magicTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 130; self.damage = 20; self.fireRate = 50; self.cost = 80; self.upgradeCost = 120; self.towerType = 'magic'; self.slowEffect = 0.5; self.slowDuration = 120; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xe67e22; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) return; // Create slowing bullet var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; bullet.slowEffect = self.slowEffect; bullet.slowDuration = self.slowDuration; bullet.isMagic = true; bullets.push(bullet); game.addChild(bullet); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) return false; currency -= self.upgradeCost; self.level++; self.damage += 12; self.range += 25; self.slowEffect = Math.max(0.2, self.slowEffect - 0.1); self.slowDuration += 30; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0xD35400 : 0xA04000; updateUI(); return true; }; return self; }); var CannonTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with cannon tower self.removeChildAt(0); var towerGraphics = self.attachAsset('cannonTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 120; self.damage = 40; self.fireRate = 90; self.cost = 100; self.upgradeCost = 150; self.towerType = 'cannon'; self.splashRadius = 80; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x34495e; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) return; // Create splash damage bullet var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; bullet.splashRadius = self.splashRadius; bullet.isSplash = true; bullets.push(bullet); game.addChild(bullet); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) return false; currency -= self.upgradeCost; self.level++; self.damage += 20; self.range += 20; self.splashRadius += 20; self.fireRate = Math.max(60, self.fireRate - 15); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0x2C3E50 : 0x1B2631; updateUI(); return true; }; return self; }); var ArcherTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with archer tower self.removeChildAt(0); var towerGraphics = self.attachAsset('archerTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 200; self.damage = 15; self.fireRate = 40; self.cost = 75; self.upgradeCost = 100; self.towerType = 'archer'; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x8e44ad; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) return false; currency -= self.upgradeCost; self.level++; self.damage += 10; self.range += 30; self.fireRate = Math.max(25, self.fireRate - 5); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0x7D3C98 : 0x6C3483; updateUI(); return true; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var gridSize = 100; var mapWidth = 20; var mapHeight = 25; var currency = 100; var lives = 20; var wave = 1; var enemiesInWave = 5; var enemiesSpawned = 0; var waveActive = false; var gameOver = false; var towers = []; var enemies = []; var bullets = []; var grid = []; var enemyPath = []; var selectedTower = null; var placingTower = false; var selectedTowerType = 'basic'; // Create UI elements var currencyTxt = new Text2('Gold: 100', { size: 60, fill: 0xFFD700 }); currencyTxt.anchor.set(0, 0); currencyTxt.x = 120; currencyTxt.y = 20; LK.gui.topLeft.addChild(currencyTxt); var livesTxt = new Text2('Lives: 20', { size: 60, fill: 0xFF0000 }); livesTxt.anchor.set(0.5, 0); LK.gui.top.addChild(livesTxt); var waveTxt = new Text2('Wave: 1', { size: 60, fill: 0xFFFFFF }); waveTxt.anchor.set(1, 0); LK.gui.topRight.addChild(waveTxt); var startWaveBtn = new Text2('Start Wave', { size: 80, fill: 0x00FF00 }); startWaveBtn.anchor.set(0.5, 1); startWaveBtn.y = -20; LK.gui.bottom.addChild(startWaveBtn); var buyTowerBtn = new Text2('Basic Tower (50g)', { size: 60, fill: 0x4A90E2 }); buyTowerBtn.anchor.set(0, 1); buyTowerBtn.x = 20; buyTowerBtn.y = -20; LK.gui.bottomLeft.addChild(buyTowerBtn); var buyArcherBtn = new Text2('Archer Tower (75g)', { size: 60, fill: 0x8e44ad }); buyArcherBtn.anchor.set(0, 1); buyArcherBtn.x = 20; buyArcherBtn.y = -80; LK.gui.bottomLeft.addChild(buyArcherBtn); var buyCannonBtn = new Text2('Cannon Tower (100g)', { size: 60, fill: 0x34495e }); buyCannonBtn.anchor.set(0, 1); buyCannonBtn.x = 20; buyCannonBtn.y = -140; LK.gui.bottomLeft.addChild(buyCannonBtn); var buyMagicBtn = new Text2('Magic Tower (80g)', { size: 60, fill: 0xe67e22 }); buyMagicBtn.anchor.set(0, 1); buyMagicBtn.x = 20; buyMagicBtn.y = -200; LK.gui.bottomLeft.addChild(buyMagicBtn); var upgradeTowerBtn = new Text2('Upgrade Tower', { size: 70, fill: 0xFF6B35 }); upgradeTowerBtn.anchor.set(0, 1); upgradeTowerBtn.x = 20; upgradeTowerBtn.y = -100; upgradeTowerBtn.visible = false; LK.gui.bottomLeft.addChild(upgradeTowerBtn); function updateUI() { currencyTxt.setText('Gold: ' + currency); livesTxt.setText('Lives: ' + lives); waveTxt.setText('Wave: ' + wave); if (currency >= 50) { buyTowerBtn.tint = 0x4A90E2; } else { buyTowerBtn.tint = 0x666666; } if (currency >= 75) { buyArcherBtn.tint = 0x8e44ad; } else { buyArcherBtn.tint = 0x666666; } if (currency >= 100) { buyCannonBtn.tint = 0x34495e; } else { buyCannonBtn.tint = 0x666666; } if (currency >= 80) { buyMagicBtn.tint = 0xe67e22; } else { buyMagicBtn.tint = 0x666666; } // Update upgrade button visibility and state if (selectedTower && selectedTower.level < selectedTower.maxLevel) { upgradeTowerBtn.visible = true; upgradeTowerBtn.setText('Upgrade Lv' + selectedTower.level + ' (' + selectedTower.upgradeCost + 'g)'); if (currency >= selectedTower.upgradeCost) { upgradeTowerBtn.tint = 0xFF6B35; } else { upgradeTowerBtn.tint = 0x666666; } } else { upgradeTowerBtn.visible = false; } } function hideAllRanges() { for (var i = 0; i < towers.length; i++) { towers[i].hideRange(); } } function initializeGrid() { for (var x = 0; x < mapWidth; x++) { grid[x] = []; for (var y = 0; y < mapHeight; y++) { grid[x][y] = { x: x * gridSize + gridSize / 2, y: y * gridSize + gridSize / 2, occupied: false, isPath: false }; } } } function createPath() { enemyPath = []; var pathCoords = [{ x: 0, y: 12 }, { x: 1, y: 12 }, { x: 2, y: 12 }, { x: 3, y: 12 }, { x: 4, y: 12 }, { x: 5, y: 12 }, { x: 6, y: 12 }, { x: 7, y: 12 }, { x: 8, y: 12 }, { x: 8, y: 11 }, { x: 8, y: 10 }, { x: 8, y: 9 }, { x: 8, y: 8 }, { x: 9, y: 8 }, { x: 10, y: 8 }, { x: 11, y: 8 }, { x: 12, y: 8 }, { x: 12, y: 9 }, { x: 12, y: 10 }, { x: 12, y: 11 }, { x: 12, y: 12 }, { x: 13, y: 12 }, { x: 14, y: 12 }, { x: 15, y: 12 }, { x: 16, y: 12 }, { x: 17, y: 12 }, { x: 18, y: 12 }, { x: 19, y: 12 }]; for (var i = 0; i < pathCoords.length; i++) { var coord = pathCoords[i]; if (coord.x < mapWidth && coord.y < mapHeight) { grid[coord.x][coord.y].isPath = true; enemyPath.push({ x: coord.x * gridSize + gridSize / 2, y: coord.y * gridSize + gridSize / 2 }); } } } function drawMap() { for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { var tile; if (grid[x][y].isPath) { tile = LK.getAsset('pathTile', { x: x * gridSize, y: y * gridSize }); } else { tile = LK.getAsset('grassTile', { x: x * gridSize, y: y * gridSize }); } game.addChild(tile); } } } function drawBase() { var base = LK.getAsset('base', { anchorX: 0.5, anchorY: 0.5, x: (mapWidth - 1) * gridSize + gridSize / 2, y: 12 * gridSize + gridSize / 2 }); game.addChild(base); } function spawnEnemy() { if (enemiesSpawned >= enemiesInWave) return; var enemy; var enemyType = Math.floor(Math.random() * 4); if (enemyType === 0) { enemy = new Enemy(); } else if (enemyType === 1) { enemy = new FastWarrior(); } else if (enemyType === 2) { enemy = new HeavyWarrior(); } else { enemy = new MagicWarrior(); } enemy.x = gridSize / 2; enemy.y = 12 * gridSize + gridSize / 2; // Scale stats with wave enemy.health = enemy.maxHealth + (wave - 1) * 20; enemy.maxHealth = enemy.health; enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2; enemy.originalSpeed = enemy.speed; enemy.reward = enemy.reward + (wave - 1) * 2; enemies.push(enemy); game.addChild(enemy); enemiesSpawned++; } function getGridPosition(x, y) { var gridX = Math.floor(x / gridSize); var gridY = Math.floor(y / gridSize); if (gridX >= 0 && gridX < mapWidth && gridY >= 0 && gridY < mapHeight) { return { x: gridX, y: gridY }; } return null; } function canPlaceTower(gridX, gridY) { return !grid[gridX][gridY].occupied && !grid[gridX][gridY].isPath; } function placeTower(gridX, gridY) { var tower; var cost; if (selectedTowerType === 'basic') { cost = 50; if (!canPlaceTower(gridX, gridY) || currency < cost) return false; tower = new Tower(); } else if (selectedTowerType === 'archer') { cost = 75; if (!canPlaceTower(gridX, gridY) || currency < cost) return false; tower = new ArcherTower(); } else if (selectedTowerType === 'cannon') { cost = 100; if (!canPlaceTower(gridX, gridY) || currency < cost) return false; tower = new CannonTower(); } else if (selectedTowerType === 'magic') { cost = 80; if (!canPlaceTower(gridX, gridY) || currency < cost) return false; tower = new MagicTower(); } tower.x = gridX * gridSize + gridSize / 2; tower.y = gridY * gridSize + gridSize / 2; towers.push(tower); game.addChild(tower); grid[gridX][gridY].occupied = true; currency -= cost; placingTower = false; updateUI(); return true; } function startWave() { if (waveActive) return; waveActive = true; enemiesSpawned = 0; enemiesInWave = 5 + wave * 2; startWaveBtn.setText('Wave Active'); startWaveBtn.tint = 0x666666; } function checkWaveComplete() { if (!waveActive) return; var allEnemiesGone = true; for (var i = 0; i < enemies.length; i++) { if (!enemies[i].isDead && !enemies[i].reachedBase) { allEnemiesGone = false; break; } } if (enemiesSpawned >= enemiesInWave && allEnemiesGone) { waveActive = false; wave++; currency += 25; startWaveBtn.setText('Start Wave'); startWaveBtn.tint = 0x00FF00; updateUI(); // Clean up dead enemies for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].isDead || enemies[i].reachedBase) { enemies[i].destroy(); enemies.splice(i, 1); } } } } // Initialize game initializeGrid(); createPath(); drawMap(); drawBase(); updateUI(); // Event handlers startWaveBtn.down = function () { startWave(); }; buyTowerBtn.down = function () { if (currency >= 50) { selectedTowerType = 'basic'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyArcherBtn.down = function () { if (currency >= 75) { selectedTowerType = 'archer'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyCannonBtn.down = function () { if (currency >= 100) { selectedTowerType = 'cannon'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyMagicBtn.down = function () { if (currency >= 80) { selectedTowerType = 'magic'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; upgradeTowerBtn.down = function () { if (selectedTower && selectedTower.upgrade()) { updateUI(); } }; game.down = function (x, y, obj) { if (placingTower) { var gridPos = getGridPosition(x, y); if (gridPos) { placeTower(gridPos.x, gridPos.y); } } else { // Clear tower selection if clicking on empty space var gridPos = getGridPosition(x, y); if (gridPos && !grid[gridPos.x][gridPos.y].occupied) { selectedTower = null; hideAllRanges(); updateUI(); } } }; // Main game loop game.update = function () { if (lives <= 0 && !gameOver) { gameOver = true; LK.showGameOver(); return; } if (wave > 20) { LK.showYouWin(); return; } // Spawn enemies during wave with decreasing interval var spawnInterval = Math.max(45, 90 - wave * 2); if (waveActive && LK.ticks % spawnInterval === 0) { spawnEnemy(); } // Clean up bullets that hit targets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.hasHit || !bullet.target || bullet.target.isDead) { bullet.destroy(); bullets.splice(i, 1); } } checkWaveComplete(); };
===================================================================
--- original.js
+++ change.js
@@ -21,9 +21,28 @@
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
- self.target.takeDamage(self.damage);
+ if (self.isSplash) {
+ // Splash damage to all enemies in radius
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ if (enemy.isDead || enemy.reachedBase) continue;
+ var splashDx = enemy.x - self.x;
+ var splashDy = enemy.y - self.y;
+ var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy);
+ if (splashDistance <= self.splashRadius) {
+ enemy.takeDamage(self.damage);
+ }
+ }
+ } else if (self.isMagic) {
+ // Magic damage with slow effect
+ self.target.takeDamage(self.damage);
+ self.target.applySlow(self.slowEffect, self.slowDuration);
+ } else {
+ // Regular damage
+ self.target.takeDamage(self.damage);
+ }
self.hasHit = true;
LK.getSound('enemyHit').play();
return;
}
@@ -46,8 +65,11 @@
self.reward = 10;
self.pathIndex = 0;
self.isDead = false;
self.reachedBase = false;
+ self.originalSpeed = self.speed;
+ self.slowEndTime = 0;
+ self.isSlowed = false;
// Add health bar
var healthBarBg = LK.getAsset('pathTile', {
anchorX: 0.5,
anchorY: 0.5,
@@ -76,8 +98,14 @@
} else {
healthBar.tint = 0xFF0000; // Red
}
};
+ self.applySlow = function (slowFactor, duration) {
+ self.speed = self.originalSpeed * slowFactor;
+ self.slowEndTime = LK.ticks + duration;
+ self.isSlowed = true;
+ enemyGraphics.tint = 0x3498db; // Blue tint for slowed enemies
+ };
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0 && !self.isDead) {
@@ -94,8 +122,14 @@
}
};
self.update = function () {
if (self.isDead || self.reachedBase) return;
+ // Check if slow effect should end
+ if (self.isSlowed && LK.ticks >= self.slowEndTime) {
+ self.speed = self.originalSpeed;
+ self.isSlowed = false;
+ enemyGraphics.tint = 0xFFFFFF; // Reset tint
+ }
if (self.pathIndex < enemyPath.length) {
var target = enemyPath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
@@ -116,8 +150,76 @@
}
};
return self;
});
+var MagicWarrior = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace graphics with magic warrior
+ self.removeChildAt(0);
+ var enemyGraphics = self.attachAsset('magicWarrior', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.maxHealth = 120;
+ self.health = self.maxHealth;
+ self.speed = 2.2;
+ self.originalSpeed = self.speed;
+ self.reward = 20;
+ self.enemyType = 'magic';
+ self.magicResistance = 0.5; // Takes 50% less damage from magic towers
+ self.takeDamage = function (damage, damageType) {
+ var actualDamage = damage;
+ if (damageType === 'magic') {
+ actualDamage = damage * self.magicResistance;
+ }
+ self.health -= actualDamage;
+ self.updateHealthBar();
+ if (self.health <= 0 && !self.isDead) {
+ self.isDead = true;
+ LK.getSound('enemyDeath').play();
+ currency += self.reward;
+ updateUI();
+ tween.to(enemyGraphics, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ }, 500);
+ }
+ };
+ return self;
+});
+var HeavyWarrior = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace graphics with heavy warrior
+ self.removeChildAt(0);
+ var enemyGraphics = self.attachAsset('heavyWarrior', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.maxHealth = 200;
+ self.health = self.maxHealth;
+ self.speed = 1.0;
+ self.originalSpeed = self.speed;
+ self.reward = 25;
+ self.enemyType = 'heavy';
+ return self;
+});
+var FastWarrior = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace graphics with fast warrior
+ self.removeChildAt(0);
+ var enemyGraphics = self.attachAsset('fastWarrior', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.maxHealth = 60;
+ self.health = self.maxHealth;
+ self.speed = 3.5;
+ self.originalSpeed = self.speed;
+ self.reward = 15;
+ self.enemyType = 'fast';
+ return self;
+});
var Tower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
@@ -214,8 +316,150 @@
}
};
return self;
});
+var MagicTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with magic tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('magicTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 130;
+ self.damage = 20;
+ self.fireRate = 50;
+ self.cost = 80;
+ self.upgradeCost = 120;
+ self.towerType = 'magic';
+ self.slowEffect = 0.5;
+ self.slowDuration = 120;
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0xe67e22;
+ self.fire = function (target) {
+ if (LK.ticks - self.lastFire < self.fireRate) return;
+ // Create slowing bullet
+ var bullet = new Bullet();
+ bullet.x = self.x;
+ bullet.y = self.y;
+ bullet.target = target;
+ bullet.damage = self.damage;
+ bullet.slowEffect = self.slowEffect;
+ bullet.slowDuration = self.slowDuration;
+ bullet.isMagic = true;
+ bullets.push(bullet);
+ game.addChild(bullet);
+ self.lastFire = LK.ticks;
+ LK.getSound('shoot').play();
+ };
+ self.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 12;
+ self.range += 25;
+ self.slowEffect = Math.max(0.2, self.slowEffect - 0.1);
+ self.slowDuration += 30;
+ self.fireRate = Math.max(30, self.fireRate - 10);
+ self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ towerGraphics.tint = self.level === 2 ? 0xD35400 : 0xA04000;
+ updateUI();
+ return true;
+ };
+ return self;
+});
+var CannonTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with cannon tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('cannonTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 120;
+ self.damage = 40;
+ self.fireRate = 90;
+ self.cost = 100;
+ self.upgradeCost = 150;
+ self.towerType = 'cannon';
+ self.splashRadius = 80;
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0x34495e;
+ self.fire = function (target) {
+ if (LK.ticks - self.lastFire < self.fireRate) return;
+ // Create splash damage bullet
+ var bullet = new Bullet();
+ bullet.x = self.x;
+ bullet.y = self.y;
+ bullet.target = target;
+ bullet.damage = self.damage;
+ bullet.splashRadius = self.splashRadius;
+ bullet.isSplash = true;
+ bullets.push(bullet);
+ game.addChild(bullet);
+ self.lastFire = LK.ticks;
+ LK.getSound('shoot').play();
+ };
+ self.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 20;
+ self.range += 20;
+ self.splashRadius += 20;
+ self.fireRate = Math.max(60, self.fireRate - 15);
+ self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ towerGraphics.tint = self.level === 2 ? 0x2C3E50 : 0x1B2631;
+ updateUI();
+ return true;
+ };
+ return self;
+});
+var ArcherTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with archer tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('archerTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 200;
+ self.damage = 15;
+ self.fireRate = 40;
+ self.cost = 75;
+ self.upgradeCost = 100;
+ self.towerType = 'archer';
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0x8e44ad;
+ self.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 10;
+ self.range += 30;
+ self.fireRate = Math.max(25, self.fireRate - 5);
+ self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ towerGraphics.tint = self.level === 2 ? 0x7D3C98 : 0x6C3483;
+ updateUI();
+ return true;
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -242,8 +486,9 @@
var grid = [];
var enemyPath = [];
var selectedTower = null;
var placingTower = false;
+var selectedTowerType = 'basic';
// Create UI elements
var currencyTxt = new Text2('Gold: 100', {
size: 60,
fill: 0xFFD700
@@ -270,16 +515,40 @@
});
startWaveBtn.anchor.set(0.5, 1);
startWaveBtn.y = -20;
LK.gui.bottom.addChild(startWaveBtn);
-var buyTowerBtn = new Text2('Buy Tower (50g)', {
- size: 70,
+var buyTowerBtn = new Text2('Basic Tower (50g)', {
+ size: 60,
fill: 0x4A90E2
});
buyTowerBtn.anchor.set(0, 1);
buyTowerBtn.x = 20;
buyTowerBtn.y = -20;
LK.gui.bottomLeft.addChild(buyTowerBtn);
+var buyArcherBtn = new Text2('Archer Tower (75g)', {
+ size: 60,
+ fill: 0x8e44ad
+});
+buyArcherBtn.anchor.set(0, 1);
+buyArcherBtn.x = 20;
+buyArcherBtn.y = -80;
+LK.gui.bottomLeft.addChild(buyArcherBtn);
+var buyCannonBtn = new Text2('Cannon Tower (100g)', {
+ size: 60,
+ fill: 0x34495e
+});
+buyCannonBtn.anchor.set(0, 1);
+buyCannonBtn.x = 20;
+buyCannonBtn.y = -140;
+LK.gui.bottomLeft.addChild(buyCannonBtn);
+var buyMagicBtn = new Text2('Magic Tower (80g)', {
+ size: 60,
+ fill: 0xe67e22
+});
+buyMagicBtn.anchor.set(0, 1);
+buyMagicBtn.x = 20;
+buyMagicBtn.y = -200;
+LK.gui.bottomLeft.addChild(buyMagicBtn);
var upgradeTowerBtn = new Text2('Upgrade Tower', {
size: 70,
fill: 0xFF6B35
});
@@ -296,8 +565,23 @@
buyTowerBtn.tint = 0x4A90E2;
} else {
buyTowerBtn.tint = 0x666666;
}
+ if (currency >= 75) {
+ buyArcherBtn.tint = 0x8e44ad;
+ } else {
+ buyArcherBtn.tint = 0x666666;
+ }
+ if (currency >= 100) {
+ buyCannonBtn.tint = 0x34495e;
+ } else {
+ buyCannonBtn.tint = 0x666666;
+ }
+ if (currency >= 80) {
+ buyMagicBtn.tint = 0xe67e22;
+ } else {
+ buyMagicBtn.tint = 0x666666;
+ }
// Update upgrade button visibility and state
if (selectedTower && selectedTower.level < selectedTower.maxLevel) {
upgradeTowerBtn.visible = true;
upgradeTowerBtn.setText('Upgrade Lv' + selectedTower.level + ' (' + selectedTower.upgradeCost + 'g)');
@@ -455,15 +739,27 @@
game.addChild(base);
}
function spawnEnemy() {
if (enemiesSpawned >= enemiesInWave) return;
- var enemy = new Enemy();
+ var enemy;
+ var enemyType = Math.floor(Math.random() * 4);
+ if (enemyType === 0) {
+ enemy = new Enemy();
+ } else if (enemyType === 1) {
+ enemy = new FastWarrior();
+ } else if (enemyType === 2) {
+ enemy = new HeavyWarrior();
+ } else {
+ enemy = new MagicWarrior();
+ }
enemy.x = gridSize / 2;
enemy.y = 12 * gridSize + gridSize / 2;
- enemy.health = 100 + (wave - 1) * 20;
+ // Scale stats with wave
+ enemy.health = enemy.maxHealth + (wave - 1) * 20;
enemy.maxHealth = enemy.health;
- enemy.speed = 1.5 + (wave - 1) * 0.2;
- enemy.reward = 10 + (wave - 1) * 2;
+ enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2;
+ enemy.originalSpeed = enemy.speed;
+ enemy.reward = enemy.reward + (wave - 1) * 2;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
}
@@ -481,16 +777,33 @@
function canPlaceTower(gridX, gridY) {
return !grid[gridX][gridY].occupied && !grid[gridX][gridY].isPath;
}
function placeTower(gridX, gridY) {
- if (!canPlaceTower(gridX, gridY) || currency < 50) return false;
- var tower = new Tower();
+ var tower;
+ var cost;
+ if (selectedTowerType === 'basic') {
+ cost = 50;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new Tower();
+ } else if (selectedTowerType === 'archer') {
+ cost = 75;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new ArcherTower();
+ } else if (selectedTowerType === 'cannon') {
+ cost = 100;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new CannonTower();
+ } else if (selectedTowerType === 'magic') {
+ cost = 80;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new MagicTower();
+ }
tower.x = gridX * gridSize + gridSize / 2;
tower.y = gridY * gridSize + gridSize / 2;
towers.push(tower);
game.addChild(tower);
grid[gridX][gridY].occupied = true;
- currency -= tower.cost;
+ currency -= cost;
placingTower = false;
updateUI();
return true;
}
@@ -538,14 +851,42 @@
startWave();
};
buyTowerBtn.down = function () {
if (currency >= 50) {
+ selectedTowerType = 'basic';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
+buyArcherBtn.down = function () {
+ if (currency >= 75) {
+ selectedTowerType = 'archer';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
+buyCannonBtn.down = function () {
+ if (currency >= 100) {
+ selectedTowerType = 'cannon';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
+buyMagicBtn.down = function () {
+ if (currency >= 80) {
+ selectedTowerType = 'magic';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
upgradeTowerBtn.down = function () {
if (selectedTower && selectedTower.upgrade()) {
updateUI();
}