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();
// Enhanced death animation with explosion effect
tween(enemyGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xff6b6b
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 400,
easing: tween.easeIn
});
}
});
}
};
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(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 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;
// Bullet spawn animation
bullet.alpha = 0;
bullet.scaleX = 0.5;
bullet.scaleY = 0.5;
bullets.push(bullet);
game.addChild(bullet);
// Animate bullet appearance
tween(bullet, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Tower fire animation
var originalScale = towerGraphics.scaleX;
tween(towerGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 100,
easing: tween.easeIn
});
}
});
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;
// Enhanced visual upgrade animation
tween(towerGraphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x00ff00
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
var finalTint = self.level === 2 ? 0x3A7BD5 : 0x2E5BBA;
tween(towerGraphics, {
scaleX: 1,
scaleY: 1,
tint: finalTint
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Upgrade sparkle effect
LK.effects.flashObject(self, 0xffd700, 800);
updateUI();
return true;
};
self.down = function (x, y, obj) {
// Always start dragging on click
draggingTower = self;
selectedTower = self;
// Use x, y parameters directly instead of trying to convert coordinates
dragOffset.x = x - self.x;
dragOffset.y = y - self.y;
originalTowerPosition.x = self.x;
originalTowerPosition.y = self.y;
// Find original grid position
var gridPos = getGridPosition(self.x, self.y);
if (gridPos) {
originalGridPosition.x = gridPos.x;
originalGridPosition.y = gridPos.y;
grid[gridPos.x][gridPos.y].occupied = false;
}
// Add drag visual effect
tween(self, {
alpha: 0.7,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
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 LightningTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with lightning tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('lightningTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 140;
self.damage = 35;
self.fireRate = 80;
self.cost = 120;
self.upgradeCost = 180;
self.towerType = 'lightning';
self.chainCount = 3;
self.chainRadius = 100;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xf1c40f;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) return;
// Lightning chain effect
var chainTargets = [target];
var currentTarget = target;
// Find chain targets
for (var c = 0; c < self.chainCount - 1; c++) {
var nextTarget = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) continue;
if (chainTargets.indexOf(enemy) !== -1) continue;
var dx = enemy.x - currentTarget.x;
var dy = enemy.y - currentTarget.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.chainRadius && distance < closestDistance) {
closestDistance = distance;
nextTarget = enemy;
}
}
if (nextTarget) {
chainTargets.push(nextTarget);
currentTarget = nextTarget;
}
}
// Apply damage to all chain targets
for (var i = 0; i < chainTargets.length; i++) {
var chainTarget = chainTargets[i];
var chainDamage = self.damage * (1 - i * 0.2); // Decreasing damage
chainTarget.takeDamage(chainDamage);
// Lightning effect animation
tween(chainTarget, {
tint: 0xf1c40f
}, {
duration: 100,
onFinish: function onFinish() {
tween(chainTarget, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
// Tower fire animation
tween(towerGraphics, {
tint: 0xf1c40f,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
self.lastFire = LK.ticks;
LK.getSound('lightning').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
currency -= self.upgradeCost;
self.level++;
self.damage += 18;
self.range += 20;
self.chainCount++;
self.chainRadius += 20;
self.fireRate = Math.max(50, 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 ? 0xd4ac0d : 0xb7950b;
updateUI();
return true;
};
return self;
});
var LaserTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with laser tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('laserTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 160;
self.damage = 8;
self.fireRate = 10;
self.cost = 110;
self.upgradeCost = 160;
self.towerType = 'laser';
self.currentTarget = null;
self.beamDuration = 0;
self.maxBeamDuration = 300;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xe74c3c;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) return;
// Continuous laser beam
if (self.currentTarget === target) {
self.beamDuration++;
// Increasing damage over time
var damageMultiplier = 1 + self.beamDuration / 100;
target.takeDamage(self.damage * damageMultiplier);
} else {
self.currentTarget = target;
self.beamDuration = 0;
target.takeDamage(self.damage);
}
// Laser beam visual effect
tween(target, {
tint: 0xe74c3c
}, {
duration: 50,
onFinish: function onFinish() {
tween(target, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
// Tower rotation towards target
var angle = Math.atan2(target.y - self.y, target.x - self.x);
tween(towerGraphics, {
rotation: angle
}, {
duration: 100,
easing: tween.easeOut
});
self.lastFire = LK.ticks;
if (self.beamDuration % 30 === 0) {
LK.getSound('laser').play();
}
};
self.findTarget = function () {
// Prefer to keep current target if still in range
if (self.currentTarget && !self.currentTarget.isDead && !self.currentTarget.reachedBase) {
var dx = self.currentTarget.x - self.x;
var dy = self.currentTarget.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
return self.currentTarget;
}
}
// Find new target if current is lost
self.currentTarget = null;
self.beamDuration = 0;
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.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
currency -= self.upgradeCost;
self.level++;
self.damage += 5;
self.range += 25;
self.maxBeamDuration += 100;
self.fireRate = Math.max(5, self.fireRate - 2);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0xc0392b : 0xa93226;
updateUI();
return true;
};
return self;
});
var FreezeTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with freeze tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('freezeTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 120;
self.damage = 10;
self.fireRate = 120;
self.cost = 90;
self.upgradeCost = 140;
self.towerType = 'freeze';
self.freezeRadius = 80;
self.freezeDuration = 180;
self.freezeEffect = 0.1;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x7fb3d3;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) return;
// Area freeze effect
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.freezeRadius) {
enemy.takeDamage(self.damage);
enemy.applySlow(self.freezeEffect, self.freezeDuration);
// Freeze effect animation
tween(enemy, {
tint: 0x7fb3d3
}, {
duration: 200,
onFinish: function onFinish() {
tween(enemy, {
tint: 0x3498db
}, {
duration: self.freezeDuration * 16
});
}
});
}
}
// Tower fire animation with pulse effect
tween(towerGraphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x3498db
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
self.lastFire = LK.ticks;
LK.getSound('freeze').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
currency -= self.upgradeCost;
self.level++;
self.damage += 8;
self.range += 15;
self.freezeRadius += 20;
self.freezeDuration += 60;
self.freezeEffect = Math.max(0.05, self.freezeEffect - 0.025);
self.fireRate = Math.max(80, 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 ? 0x5dade2 : 0x3498db;
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 = 390;
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';
var draggingTower = null;
var dragOffset = {
x: 0,
y: 0
};
var originalTowerPosition = {
x: 0,
y: 0
};
var originalGridPosition = {
x: 0,
y: 0
};
// Create UI elements
var currencyTxt = new Text2('Gold: 390', {
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 buyLightningBtn = new Text2('Lightning Tower (120g)', {
size: 60,
fill: 0xf1c40f
});
buyLightningBtn.anchor.set(0, 1);
buyLightningBtn.x = 20;
buyLightningBtn.y = -260;
LK.gui.bottomLeft.addChild(buyLightningBtn);
var buyFreezeBtn = new Text2('Freeze Tower (90g)', {
size: 60,
fill: 0x7fb3d3
});
buyFreezeBtn.anchor.set(0, 1);
buyFreezeBtn.x = 20;
buyFreezeBtn.y = -320;
LK.gui.bottomLeft.addChild(buyFreezeBtn);
var buyLaserBtn = new Text2('Laser Tower (110g)', {
size: 60,
fill: 0xe74c3c
});
buyLaserBtn.anchor.set(0, 1);
buyLaserBtn.x = 20;
buyLaserBtn.y = -380;
LK.gui.bottomLeft.addChild(buyLaserBtn);
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;
}
if (currency >= 120) {
buyLightningBtn.tint = 0xf1c40f;
} else {
buyLightningBtn.tint = 0x666666;
}
if (currency >= 90) {
buyFreezeBtn.tint = 0x7fb3d3;
} else {
buyFreezeBtn.tint = 0x666666;
}
if (currency >= 110) {
buyLaserBtn.tint = 0xe74c3c;
} else {
buyLaserBtn.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;
// Spawn animation
enemy.alpha = 0;
enemy.scaleX = 0.1;
enemy.scaleY = 0.1;
enemies.push(enemy);
game.addChild(enemy);
// Enhanced enemy entrance animation with rotation
var spawnAnimationType = Math.floor(Math.random() * 3);
if (spawnAnimationType === 0) {
// Bounce entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
} else if (spawnAnimationType === 1) {
// Spiral entrance
enemy.rotation = Math.PI * 4;
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 600,
easing: tween.easeOut
});
} else {
// Elastic entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
}
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();
} else if (selectedTowerType === 'lightning') {
cost = 120;
if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
tower = new LightningTower();
} else if (selectedTowerType === 'freeze') {
cost = 90;
if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
tower = new FreezeTower();
} else if (selectedTowerType === 'laser') {
cost = 110;
if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
tower = new LaserTower();
}
tower.x = gridX * gridSize + gridSize / 2;
tower.y = gridY * gridSize + gridSize / 2;
// Placement animation
tower.alpha = 0;
tower.scaleX = 0.1;
tower.scaleY = 0.1;
towers.push(tower);
game.addChild(tower);
// Animate tower placement
tween(tower, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(tower, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
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;
// Wave start animation
tween(startWaveBtn, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(startWaveBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Screen flash effect for wave start
LK.effects.flashScreen(0x00FF00, 300);
}
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();
}
};
buyLightningBtn.down = function () {
if (currency >= 120) {
selectedTowerType = 'lightning';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyFreezeBtn.down = function () {
if (currency >= 90) {
selectedTowerType = 'freeze';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyLaserBtn.down = function () {
if (currency >= 110) {
selectedTowerType = 'laser';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
upgradeTowerBtn.down = function () {
if (selectedTower && selectedTower.upgrade()) {
updateUI();
}
};
game.move = function (x, y, obj) {
if (draggingTower) {
draggingTower.x = x - dragOffset.x;
draggingTower.y = y - dragOffset.y;
// Visual feedback for valid/invalid placement
var gridPos = getGridPosition(draggingTower.x, draggingTower.y);
if (gridPos && canPlaceTower(gridPos.x, gridPos.y)) {
draggingTower.tint = 0x00FF00; // Green for valid
} else {
draggingTower.tint = 0xFF0000; // Red for invalid
}
}
};
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();
}
}
};
game.up = function (x, y, obj) {
if (draggingTower) {
var gridPos = getGridPosition(draggingTower.x, draggingTower.y);
var canPlace = gridPos && canPlaceTower(gridPos.x, gridPos.y);
if (canPlace) {
// Successfully place tower at new position
draggingTower.x = gridPos.x * gridSize + gridSize / 2;
draggingTower.y = gridPos.y * gridSize + gridSize / 2;
grid[gridPos.x][gridPos.y].occupied = true;
// Smooth placement animation
tween(draggingTower, {
alpha: 1,
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
} else {
// Return to original position
tween(draggingTower, {
x: originalTowerPosition.x,
y: originalTowerPosition.y,
alpha: 1,
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 400,
easing: tween.elasticOut
});
// Restore original grid position
grid[originalGridPosition.x][originalGridPosition.y].occupied = true;
}
draggingTower = null;
}
};
// 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
@@ -112,15 +112,27 @@
self.isDead = true;
LK.getSound('enemyDeath').play();
currency += self.reward;
updateUI();
- // Death animation
+ // Enhanced death animation with explosion effect
tween(enemyGraphics, {
- alpha: 0,
- scaleX: 0.1,
- scaleY: 0.1
+ scaleX: 1.5,
+ scaleY: 1.5,
+ tint: 0xff6b6b
}, {
- duration: 500
+ duration: 100,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(enemyGraphics, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1,
+ rotation: Math.PI * 2
+ }, {
+ duration: 400,
+ easing: tween.easeIn
+ });
+ }
});
}
};
self.update = function () {
@@ -323,10 +335,30 @@
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;
+ // Enhanced visual upgrade animation
+ tween(towerGraphics, {
+ scaleX: 1.4,
+ scaleY: 1.4,
+ tint: 0x00ff00
+ }, {
+ duration: 300,
+ easing: tween.bounceOut,
+ onFinish: function onFinish() {
+ var finalTint = self.level === 2 ? 0x3A7BD5 : 0x2E5BBA;
+ tween(towerGraphics, {
+ scaleX: 1,
+ scaleY: 1,
+ tint: finalTint
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ }
+ });
+ // Upgrade sparkle effect
+ LK.effects.flashObject(self, 0xffd700, 800);
updateUI();
return true;
};
self.down = function (x, y, obj) {
@@ -418,8 +450,309 @@
return true;
};
return self;
});
+var LightningTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with lightning tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('lightningTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 140;
+ self.damage = 35;
+ self.fireRate = 80;
+ self.cost = 120;
+ self.upgradeCost = 180;
+ self.towerType = 'lightning';
+ self.chainCount = 3;
+ self.chainRadius = 100;
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0xf1c40f;
+ self.fire = function (target) {
+ if (LK.ticks - self.lastFire < self.fireRate) return;
+ // Lightning chain effect
+ var chainTargets = [target];
+ var currentTarget = target;
+ // Find chain targets
+ for (var c = 0; c < self.chainCount - 1; c++) {
+ var nextTarget = null;
+ var closestDistance = Infinity;
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ if (enemy.isDead || enemy.reachedBase) continue;
+ if (chainTargets.indexOf(enemy) !== -1) continue;
+ var dx = enemy.x - currentTarget.x;
+ var dy = enemy.y - currentTarget.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.chainRadius && distance < closestDistance) {
+ closestDistance = distance;
+ nextTarget = enemy;
+ }
+ }
+ if (nextTarget) {
+ chainTargets.push(nextTarget);
+ currentTarget = nextTarget;
+ }
+ }
+ // Apply damage to all chain targets
+ for (var i = 0; i < chainTargets.length; i++) {
+ var chainTarget = chainTargets[i];
+ var chainDamage = self.damage * (1 - i * 0.2); // Decreasing damage
+ chainTarget.takeDamage(chainDamage);
+ // Lightning effect animation
+ tween(chainTarget, {
+ tint: 0xf1c40f
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(chainTarget, {
+ tint: 0xFFFFFF
+ }, {
+ duration: 200
+ });
+ }
+ });
+ }
+ // Tower fire animation
+ tween(towerGraphics, {
+ tint: 0xf1c40f,
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 150,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(towerGraphics, {
+ tint: 0xFFFFFF,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200
+ });
+ }
+ });
+ self.lastFire = LK.ticks;
+ LK.getSound('lightning').play();
+ };
+ self.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 18;
+ self.range += 20;
+ self.chainCount++;
+ self.chainRadius += 20;
+ self.fireRate = Math.max(50, 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 ? 0xd4ac0d : 0xb7950b;
+ updateUI();
+ return true;
+ };
+ return self;
+});
+var LaserTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with laser tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('laserTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 160;
+ self.damage = 8;
+ self.fireRate = 10;
+ self.cost = 110;
+ self.upgradeCost = 160;
+ self.towerType = 'laser';
+ self.currentTarget = null;
+ self.beamDuration = 0;
+ self.maxBeamDuration = 300;
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0xe74c3c;
+ self.fire = function (target) {
+ if (LK.ticks - self.lastFire < self.fireRate) return;
+ // Continuous laser beam
+ if (self.currentTarget === target) {
+ self.beamDuration++;
+ // Increasing damage over time
+ var damageMultiplier = 1 + self.beamDuration / 100;
+ target.takeDamage(self.damage * damageMultiplier);
+ } else {
+ self.currentTarget = target;
+ self.beamDuration = 0;
+ target.takeDamage(self.damage);
+ }
+ // Laser beam visual effect
+ tween(target, {
+ tint: 0xe74c3c
+ }, {
+ duration: 50,
+ onFinish: function onFinish() {
+ tween(target, {
+ tint: 0xFFFFFF
+ }, {
+ duration: 100
+ });
+ }
+ });
+ // Tower rotation towards target
+ var angle = Math.atan2(target.y - self.y, target.x - self.x);
+ tween(towerGraphics, {
+ rotation: angle
+ }, {
+ duration: 100,
+ easing: tween.easeOut
+ });
+ self.lastFire = LK.ticks;
+ if (self.beamDuration % 30 === 0) {
+ LK.getSound('laser').play();
+ }
+ };
+ self.findTarget = function () {
+ // Prefer to keep current target if still in range
+ if (self.currentTarget && !self.currentTarget.isDead && !self.currentTarget.reachedBase) {
+ var dx = self.currentTarget.x - self.x;
+ var dy = self.currentTarget.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance <= self.range) {
+ return self.currentTarget;
+ }
+ }
+ // Find new target if current is lost
+ self.currentTarget = null;
+ self.beamDuration = 0;
+ 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.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 5;
+ self.range += 25;
+ self.maxBeamDuration += 100;
+ self.fireRate = Math.max(5, self.fireRate - 2);
+ self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ towerGraphics.tint = self.level === 2 ? 0xc0392b : 0xa93226;
+ updateUI();
+ return true;
+ };
+ return self;
+});
+var FreezeTower = Tower.expand(function () {
+ var self = Tower.call(this);
+ // Replace graphics with freeze tower
+ self.removeChildAt(0);
+ var towerGraphics = self.attachAsset('freezeTower', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.range = 120;
+ self.damage = 10;
+ self.fireRate = 120;
+ self.cost = 90;
+ self.upgradeCost = 140;
+ self.towerType = 'freeze';
+ self.freezeRadius = 80;
+ self.freezeDuration = 180;
+ self.freezeEffect = 0.1;
+ // Update range indicator
+ var rangeIndicator = self.children[self.children.length - 1];
+ rangeIndicator.width = self.range * 2;
+ rangeIndicator.height = self.range * 2;
+ rangeIndicator.tint = 0x7fb3d3;
+ self.fire = function (target) {
+ if (LK.ticks - self.lastFire < self.fireRate) return;
+ // Area freeze effect
+ 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.freezeRadius) {
+ enemy.takeDamage(self.damage);
+ enemy.applySlow(self.freezeEffect, self.freezeDuration);
+ // Freeze effect animation
+ tween(enemy, {
+ tint: 0x7fb3d3
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(enemy, {
+ tint: 0x3498db
+ }, {
+ duration: self.freezeDuration * 16
+ });
+ }
+ });
+ }
+ }
+ // Tower fire animation with pulse effect
+ tween(towerGraphics, {
+ scaleX: 1.4,
+ scaleY: 1.4,
+ tint: 0x3498db
+ }, {
+ duration: 200,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(towerGraphics, {
+ scaleX: 1,
+ scaleY: 1,
+ tint: 0xFFFFFF
+ }, {
+ duration: 300,
+ easing: tween.bounceOut
+ });
+ }
+ });
+ self.lastFire = LK.ticks;
+ LK.getSound('freeze').play();
+ };
+ self.upgrade = function () {
+ if (self.level >= self.maxLevel || currency < self.upgradeCost) return false;
+ currency -= self.upgradeCost;
+ self.level++;
+ self.damage += 8;
+ self.range += 15;
+ self.freezeRadius += 20;
+ self.freezeDuration += 60;
+ self.freezeEffect = Math.max(0.05, self.freezeEffect - 0.025);
+ self.fireRate = Math.max(80, 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 ? 0x5dade2 : 0x3498db;
+ updateUI();
+ return true;
+ };
+ return self;
+});
var CannonTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with cannon tower
self.removeChildAt(0);
@@ -607,8 +940,32 @@
buyMagicBtn.anchor.set(0, 1);
buyMagicBtn.x = 20;
buyMagicBtn.y = -200;
LK.gui.bottomLeft.addChild(buyMagicBtn);
+var buyLightningBtn = new Text2('Lightning Tower (120g)', {
+ size: 60,
+ fill: 0xf1c40f
+});
+buyLightningBtn.anchor.set(0, 1);
+buyLightningBtn.x = 20;
+buyLightningBtn.y = -260;
+LK.gui.bottomLeft.addChild(buyLightningBtn);
+var buyFreezeBtn = new Text2('Freeze Tower (90g)', {
+ size: 60,
+ fill: 0x7fb3d3
+});
+buyFreezeBtn.anchor.set(0, 1);
+buyFreezeBtn.x = 20;
+buyFreezeBtn.y = -320;
+LK.gui.bottomLeft.addChild(buyFreezeBtn);
+var buyLaserBtn = new Text2('Laser Tower (110g)', {
+ size: 60,
+ fill: 0xe74c3c
+});
+buyLaserBtn.anchor.set(0, 1);
+buyLaserBtn.x = 20;
+buyLaserBtn.y = -380;
+LK.gui.bottomLeft.addChild(buyLaserBtn);
var upgradeTowerBtn = new Text2('Upgrade Tower', {
size: 70,
fill: 0xFF6B35
});
@@ -640,8 +997,23 @@
buyMagicBtn.tint = 0xe67e22;
} else {
buyMagicBtn.tint = 0x666666;
}
+ if (currency >= 120) {
+ buyLightningBtn.tint = 0xf1c40f;
+ } else {
+ buyLightningBtn.tint = 0x666666;
+ }
+ if (currency >= 90) {
+ buyFreezeBtn.tint = 0x7fb3d3;
+ } else {
+ buyFreezeBtn.tint = 0x666666;
+ }
+ if (currency >= 110) {
+ buyLaserBtn.tint = 0xe74c3c;
+ } else {
+ buyLaserBtn.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)');
@@ -824,17 +1196,43 @@
enemy.scaleX = 0.1;
enemy.scaleY = 0.1;
enemies.push(enemy);
game.addChild(enemy);
- // Animate enemy entrance
- tween(enemy, {
- alpha: 1,
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 500,
- easing: tween.bounceOut
- });
+ // Enhanced enemy entrance animation with rotation
+ var spawnAnimationType = Math.floor(Math.random() * 3);
+ if (spawnAnimationType === 0) {
+ // Bounce entrance
+ tween(enemy, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.bounceOut
+ });
+ } else if (spawnAnimationType === 1) {
+ // Spiral entrance
+ enemy.rotation = Math.PI * 4;
+ tween(enemy, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1,
+ rotation: 0
+ }, {
+ duration: 600,
+ easing: tween.easeOut
+ });
+ } else {
+ // Elastic entrance
+ tween(enemy, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 700,
+ easing: tween.elasticOut
+ });
+ }
enemiesSpawned++;
}
function getGridPosition(x, y) {
var gridX = Math.floor(x / gridSize);
@@ -868,8 +1266,20 @@
} else if (selectedTowerType === 'magic') {
cost = 80;
if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
tower = new MagicTower();
+ } else if (selectedTowerType === 'lightning') {
+ cost = 120;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new LightningTower();
+ } else if (selectedTowerType === 'freeze') {
+ cost = 90;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new FreezeTower();
+ } else if (selectedTowerType === 'laser') {
+ cost = 110;
+ if (!canPlaceTower(gridX, gridY) || currency < cost) return false;
+ tower = new LaserTower();
}
tower.x = gridX * gridSize + gridSize / 2;
tower.y = gridY * gridSize + gridSize / 2;
// Placement animation
@@ -999,8 +1409,35 @@
hideAllRanges();
updateUI();
}
};
+buyLightningBtn.down = function () {
+ if (currency >= 120) {
+ selectedTowerType = 'lightning';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
+buyFreezeBtn.down = function () {
+ if (currency >= 90) {
+ selectedTowerType = 'freeze';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
+buyLaserBtn.down = function () {
+ if (currency >= 110) {
+ selectedTowerType = 'laser';
+ placingTower = true;
+ selectedTower = null;
+ hideAllRanges();
+ updateUI();
+ }
+};
upgradeTowerBtn.down = function () {
if (selectedTower && selectedTower.upgrade()) {
updateUI();
}