User prompt
towers yazısı ve start wave yazısı birbirine değmesin
User prompt
geri al
User prompt
biraz daha
User prompt
towers yazısını biraz yukarı al
User prompt
towers ve start wave butonlarını 2 kat büyük
User prompt
kulenin üstündeki sağlık çubuğunu büyüt
User prompt
harita yolunu gri karelerle değiştir
User prompt
kuleler yazsını geri getir
User prompt
towers yazısını kaldır
User prompt
biraz daha bekleyerek ateş etsin mesela 1.5 saniyede bir
User prompt
okçu kulesi düşmanları 5 vuruşta öldürebilsin
User prompt
gold ve score yazılarını üst üste koyma yan yana koy
Code edit (1 edits merged)
Please save this source code
User prompt
Medieval Tower Defense
Initial prompt
etkileyici bir orta çağ arka planının üstünde bir kule ve ona giden zikzaklı bir yol olsun ve burdan düşmanlar gelsin biz ise tıkladığımız yere silahlar koyarak onların kaleye gitmesini engelleyelim
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
lastWave: 0
});
/****
* Classes
****/
var Castle = Container.expand(function () {
var self = Container.call(this);
var castleGraphic = self.attachAsset('castle', {
anchorX: 0.5,
anchorY: 0.5
});
// Properties
self.health = 10;
self.maxHealth = 10;
// Health bar
self.healthBar = new Container();
self.healthBar.y = -castleGraphic.height / 2 - 20;
self.healthBackground = LK.getAsset('map-path', {
anchorX: 0,
anchorY: 0.5,
width: 200,
height: 15,
tint: 0x444444
});
self.healthFill = LK.getAsset('map-path', {
anchorX: 0,
anchorY: 0.5,
width: 200,
height: 15,
tint: 0x00FF00
});
self.healthBar.addChild(self.healthBackground);
self.healthBar.addChild(self.healthFill);
self.healthBar.x = -100;
self.addChild(self.healthBar);
self.takeDamage = function (amount) {
self.health -= amount;
self.updateHealthBar();
if (self.health <= 0) {
LK.showGameOver();
} else {
LK.getSound('castle-hit').play();
// Flash the castle red when damaged
LK.effects.flashObject(castleGraphic, 0xFF0000, 500);
}
};
self.updateHealthBar = function () {
var healthPercent = Math.max(0, self.health / self.maxHealth);
self.healthFill.width = 200 * healthPercent;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Properties
self.health = 100;
self.maxHealth = 100;
self.speed = 2;
self.damage = 1;
self.currentPathIndex = 0;
self.reward = 10;
self.type = 'normal';
// Health bar
self.healthBar = new Container();
self.healthBar.y = -enemyGraphic.height / 2 - 10;
self.healthBackground = LK.getAsset('map-path', {
anchorX: 0,
anchorY: 0.5,
width: 70,
height: 5,
tint: 0x444444
});
self.healthFill = LK.getAsset('map-path', {
anchorX: 0,
anchorY: 0.5,
width: 70,
height: 5,
tint: 0x00FF00
});
self.healthBar.addChild(self.healthBackground);
self.healthBar.addChild(self.healthFill);
self.healthBar.x = -35;
self.addChild(self.healthBar);
self.update = function () {
if (self.currentPathIndex >= pathTiles.length) {
// Reached the castle
self.reachedCastle();
return;
}
var targetTile = pathTiles[self.currentPathIndex];
var dx = targetTile.x - self.x;
var dy = targetTile.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 5) {
// Reached this tile, move to next tile
self.currentPathIndex++;
} else {
// Move towards the current tile
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Rotate enemy to face movement direction
self.rotation = Math.atan2(moveY, moveX);
}
};
self.takeDamage = function (amount) {
self.health -= amount;
self.updateHealthBar();
LK.getSound('enemy-hit').play();
if (self.health <= 0) {
// Enemy died
LK.getSound('enemy-death').play();
gold += self.reward;
goldText.setText("Gold: " + gold);
self.destroy();
enemies.splice(enemies.indexOf(self), 1);
// Update score
LK.setScore(LK.getScore() + 10);
scoreText.setText("Score: " + LK.getScore());
} else {
// Flash the enemy red when hit
LK.effects.flashObject(enemyGraphic, 0xFF0000, 200);
}
};
self.updateHealthBar = function () {
var healthPercent = Math.max(0, self.health / self.maxHealth);
self.healthFill.width = 70 * healthPercent;
};
self.reachedCastle = function () {
castle.takeDamage(self.damage);
self.destroy();
enemies.splice(enemies.indexOf(self), 1);
};
return self;
});
var PathTile = Container.expand(function () {
var self = Container.call(this);
var pathGraphic = self.attachAsset('map-path', {
anchorX: 0.5,
anchorY: 0.5
});
// Properties
self.tileIndex = 0;
self.nextTile = null;
self.canPlaceTower = true;
return self;
});
var Projectile = Container.expand(function (type, source, target) {
var self = Container.call(this);
// Set properties based on type
var assetId;
var speed;
switch (type) {
case 'arrow':
assetId = 'arrow';
speed = 10;
break;
case 'cannonball':
assetId = 'cannonball';
speed = 7;
break;
case 'magic':
assetId = 'magic';
speed = 8;
break;
default:
assetId = 'arrow';
speed = 10;
}
var projectileGraphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Properties
self.source = source;
self.target = target;
self.damage = source.damage;
self.speed = speed;
self.type = type;
self.hasSplashDamage = false;
self.splashRadius = 0;
self.hasSlowEffect = false;
self.slowAmount = 0;
self.slowDuration = 0;
// Set initial position to tower
self.x = source.x;
self.y = source.y;
self.update = function () {
if (!self.target || !self.target.parent) {
// Target is dead, remove projectile
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
return;
}
// Move towards target
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Rotate projectile to face target
self.rotation = Math.atan2(dy, dx);
if (distance < 20) {
// Hit target
self.hit();
} else {
// Move towards target
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
self.hit = function () {
if (self.hasSplashDamage) {
// Deal splash damage to nearby enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.target.x;
var dy = enemy.y - self.target.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.splashRadius) {
// Calculate damage falloff based on distance
var damageMultiplier = 1 - distance / self.splashRadius;
var damage = Math.floor(self.damage * damageMultiplier);
enemy.takeDamage(damage);
}
}
} else {
// Deal direct damage to target
self.target.takeDamage(self.damage);
// Apply slow effect if applicable
if (self.hasSlowEffect && self.target.speed) {
var originalSpeed = self.target.speed;
self.target.speed *= 1 - self.slowAmount;
// Reset speed after duration
LK.setTimeout(function () {
if (self.target && self.target.parent) {
self.target.speed = originalSpeed;
}
}, self.slowDuration * (1000 / 60)); // Convert frames to milliseconds
// Visual indication of slow effect
tween(self.target, {
alpha: 0.7
}, {
duration: 200,
onFinish: function onFinish() {
if (self.target && self.target.parent) {
tween(self.target, {
alpha: 1
}, {
duration: 200
});
}
}
});
}
}
// Remove projectile
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
// Common tower properties
self.range = 250;
self.damage = 25;
self.attackSpeed = 1; // Attacks per second
self.attackCooldown = 0;
self.cost = 100;
self.level = 1;
self.upgradeCost = 50;
self.type = 'basic';
// Range indicator (initially invisible)
self.rangeIndicator = LK.getAsset('tower-range', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
visible: false
});
self.rangeIndicator.width = self.range * 2;
self.rangeIndicator.height = self.range * 2;
self.addChild(self.rangeIndicator);
self.findTarget = function () {
var nearestEnemy = null;
var nearestDistance = self.range;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestEnemy = enemy;
nearestDistance = distance;
}
}
return nearestEnemy;
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
} else {
var target = self.findTarget();
if (target) {
self.attack(target);
self.attackCooldown = Math.floor(60 / self.attackSpeed); // 60 is FPS
}
}
};
self.attack = function (target) {
// To be overridden by specific tower types
};
self.showRange = function () {
self.rangeIndicator.visible = true;
};
self.hideRange = function () {
self.rangeIndicator.visible = false;
};
self.down = function (x, y, obj) {
// Show range and tower info when clicked
self.showRange();
// Set as selected tower
if (selectedTower && selectedTower !== self) {
selectedTower.hideRange();
}
selectedTower = self;
// Show upgrade button if applicable
if (gold >= self.upgradeCost) {
upgradeButton.visible = true;
upgradeText.setText("Upgrade: " + self.upgradeCost + "g");
} else {
upgradeButton.visible = false;
}
// Show tower stats
var towerInfo = "Level: " + self.level + "\n";
towerInfo += "Damage: " + self.damage + "\n";
towerInfo += "Range: " + self.range + "\n";
towerInfo += "Speed: " + self.attackSpeed.toFixed(1);
towerInfoText.setText(towerInfo);
towerInfoText.visible = true;
// Position the upgrade UI near the tower
var gamePosition = game.toLocal({
x: self.x,
y: self.y
});
upgradeUI.x = Math.min(Math.max(gamePosition.x, 300), 2048 - 300);
upgradeUI.y = Math.min(Math.max(gamePosition.y + 150, 200), 2732 - 200);
upgradeUI.visible = true;
};
self.upgrade = function () {
if (gold >= self.upgradeCost) {
gold -= self.upgradeCost;
goldText.setText("Gold: " + gold);
// Increase tower stats
self.level++;
self.damage = Math.floor(self.damage * 1.3);
self.range = Math.floor(self.range * 1.1);
self.attackSpeed *= 1.1;
// Update range indicator
self.rangeIndicator.width = self.range * 2;
self.rangeIndicator.height = self.range * 2;
// Update upgrade cost
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
// Update UI
upgradeText.setText("Upgrade: " + self.upgradeCost + "g");
// Update tower info
var towerInfo = "Level: " + self.level + "\n";
towerInfo += "Damage: " + self.damage + "\n";
towerInfo += "Range: " + self.range + "\n";
towerInfo += "Speed: " + self.attackSpeed.toFixed(1);
towerInfoText.setText(towerInfo);
// Show upgrade button only if player has enough gold
if (gold < self.upgradeCost) {
upgradeButton.visible = false;
}
LK.getSound('build').play();
}
};
return self;
});
var WizardTower = Tower.expand(function () {
var self = Tower.call(this);
var towerGraphic = self.attachAsset('wizard-tower', {
anchorX: 0.5,
anchorY: 0.5
});
// Wizard tower specific properties
self.range = 250;
self.damage = 15;
self.attackSpeed = 1.2;
self.cost = 200;
self.slowEffect = 0.5; // Slow enemies to 50% speed
self.slowDuration = 120; // 2 seconds (60 frames per second)
self.type = 'wizard';
// Update range indicator
self.rangeIndicator.width = self.range * 2;
self.rangeIndicator.height = self.range * 2;
self.attack = function (target) {
// Create a magic projectile that slows enemies
var magic = new Projectile('magic', self, target);
magic.hasSlowEffect = true;
magic.slowAmount = self.slowEffect;
magic.slowDuration = self.slowDuration;
projectiles.push(magic);
game.addChild(magic);
};
return self;
});
var CannonTower = Tower.expand(function () {
var self = Tower.call(this);
var towerGraphic = self.attachAsset('cannon-tower', {
anchorX: 0.5,
anchorY: 0.5
});
// Cannon tower specific properties
self.range = 200;
self.damage = 50;
self.attackSpeed = 0.8;
self.cost = 150;
self.splashRadius = 100;
self.type = 'cannon';
// Update range indicator
self.rangeIndicator.width = self.range * 2;
self.rangeIndicator.height = self.range * 2;
self.attack = function (target) {
// Create a cannonball with splash damage
var cannonball = new Projectile('cannonball', self, target);
cannonball.hasSplashDamage = true;
cannonball.splashRadius = self.splashRadius;
projectiles.push(cannonball);
game.addChild(cannonball);
};
return self;
});
var ArcherTower = Tower.expand(function () {
var self = Tower.call(this);
var towerGraphic = self.attachAsset('archer-tower', {
anchorX: 0.5,
anchorY: 0.5
});
// Archer tower specific properties
self.range = 300;
self.damage = 20;
self.attackSpeed = 1.5;
self.cost = 100;
self.type = 'archer';
// Update range indicator
self.rangeIndicator.width = self.range * 2;
self.rangeIndicator.height = self.range * 2;
self.attack = function (target) {
// Create an arrow
var arrow = new Projectile('arrow', self, target);
projectiles.push(arrow);
game.addChild(arrow);
};
return self;
});
var TowerButton = Container.expand(function (towerType) {
var self = Container.call(this);
// Button background
var buttonGraphic = self.attachAsset('tower-button', {
anchorX: 0.5,
anchorY: 0.5
});
// Tower preview
var towerPreview;
var cost;
if (towerType === 'archer') {
towerPreview = self.attachAsset('archer-tower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
cost = 100;
} else if (towerType === 'cannon') {
towerPreview = self.attachAsset('cannon-tower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
cost = 150;
} else if (towerType === 'wizard') {
towerPreview = self.attachAsset('wizard-tower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
cost = 200;
}
// Cost text
var costText = new Text2(cost + "g", {
size: 30,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0.5);
costText.y = 50;
self.addChild(costText);
// Properties
self.towerType = towerType;
self.cost = cost;
self.down = function (x, y, obj) {
// Initiate tower placement
if (gold >= self.cost) {
// Create ghost tower for placement preview
placingTowerType = self.towerType;
createTowerPlacementPreview();
closeMenu();
} else {
// Not enough gold - flash the gold text
tween(goldText, {
alpha: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(goldText, {
alpha: 1
}, {
duration: 200
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x548147 // Green background for grass
});
/****
* Game Code
****/
// Game state variables
var gold = 200;
var wave = 1;
var waveSize = 5;
var waveActive = false;
var enemySpawnInterval = 1000; // ms between enemy spawns
var enemySpawnTimer = 0;
var enemiesSpawned = 0;
var enemiesToSpawn = 0;
var selectedTower = null;
var placingTowerType = null;
var towerPlacementPreview = null;
var pathTiles = [];
var enemies = [];
var towers = [];
var projectiles = [];
var castle;
// UI Elements
var scoreText;
var goldText;
var waveText;
var nextWaveButton;
var towerMenu;
var upgradeUI;
var upgradeButton;
var upgradeText;
var towerInfoText;
// Initialize UI
function initUI() {
// Score text
scoreText = new Text2("Score: 0", {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -50;
scoreText.y = 50;
// Gold text
goldText = new Text2("Gold: " + gold, {
size: 50,
fill: 0xFFD700
});
goldText.anchor.set(1, 0);
LK.gui.topRight.addChild(goldText);
goldText.x = -250;
goldText.y = 50;
// Wave text
waveText = new Text2("Wave: " + wave, {
size: 50,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
waveText.y = 50;
// Next wave button
nextWaveButton = new Container();
var nextWaveButtonBg = LK.getAsset('tower-button', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 80,
tint: 0x5588FF
});
nextWaveButton.addChild(nextWaveButtonBg);
var nextWaveButtonText = new Text2("Start Wave", {
size: 40,
fill: 0xFFFFFF
});
nextWaveButtonText.anchor.set(0.5, 0.5);
nextWaveButton.addChild(nextWaveButtonText);
LK.gui.bottomRight.addChild(nextWaveButton);
nextWaveButton.x = -150;
nextWaveButton.y = -100;
nextWaveButton.interactive = true;
nextWaveButton.down = function () {
if (!waveActive) {
startWave();
}
};
// Tower menu button
var towerMenuButton = new Container();
var towerMenuButtonBg = LK.getAsset('tower-button', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 80,
tint: 0x55AA55
});
towerMenuButton.addChild(towerMenuButtonBg);
var towerMenuButtonText = new Text2("Towers", {
size: 40,
fill: 0xFFFFFF
});
towerMenuButtonText.anchor.set(0.5, 0.5);
towerMenuButton.addChild(towerMenuButtonText);
LK.gui.bottomRight.addChild(towerMenuButton);
towerMenuButton.x = -150;
towerMenuButton.y = -200;
towerMenuButton.interactive = true;
towerMenuButton.down = function () {
if (towerMenu.visible) {
closeMenu();
} else {
openMenu();
}
};
// Tower selection menu
towerMenu = new Container();
var towerMenuBg = LK.getAsset('tower-menu', {
anchorX: 0.5,
anchorY: 0.5
});
towerMenu.addChild(towerMenuBg);
// Add tower buttons
var archerButton = new TowerButton('archer');
archerButton.x = -150;
towerMenu.addChild(archerButton);
var cannonButton = new TowerButton('cannon');
cannonButton.x = 0;
towerMenu.addChild(cannonButton);
var wizardButton = new TowerButton('wizard');
wizardButton.x = 150;
towerMenu.addChild(wizardButton);
// Add title
var menuTitle = new Text2("Select Tower", {
size: 40,
fill: 0x000000
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.y = -80;
towerMenu.addChild(menuTitle);
LK.gui.center.addChild(towerMenu);
towerMenu.visible = false;
// Tower upgrade UI
upgradeUI = new Container();
var upgradeUIBg = LK.getAsset('tower-menu', {
anchorX: 0.5,
anchorY: 0.5,
width: 300,
height: 200
});
upgradeUI.addChild(upgradeUIBg);
towerInfoText = new Text2("", {
size: 30,
fill: 0x000000
});
towerInfoText.anchor.set(0.5, 0);
towerInfoText.y = -80;
upgradeUI.addChild(towerInfoText);
upgradeButton = LK.getAsset('tower-button', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 60,
tint: 0x55AA55
});
upgradeButton.y = 60;
upgradeUI.addChild(upgradeButton);
upgradeText = new Text2("Upgrade: 50g", {
size: 30,
fill: 0xFFFFFF
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.y = 60;
upgradeUI.addChild(upgradeText);
// Close button for upgrade UI
var closeButton = new Text2("X", {
size: 40,
fill: 0xFF0000
});
closeButton.anchor.set(0.5, 0.5);
closeButton.x = upgradeUIBg.width / 2 - 20;
closeButton.y = -upgradeUIBg.height / 2 + 20;
closeButton.interactive = true;
closeButton.down = function () {
if (selectedTower) {
selectedTower.hideRange();
selectedTower = null;
}
upgradeUI.visible = false;
};
upgradeUI.addChild(closeButton);
upgradeButton.interactive = true;
upgradeButton.down = function () {
if (selectedTower) {
selectedTower.upgrade();
}
};
game.addChild(upgradeUI);
upgradeUI.visible = false;
}
function openMenu() {
// Show tower menu
towerMenu.visible = true;
// Hide upgrade UI
if (selectedTower) {
selectedTower.hideRange();
selectedTower = null;
}
upgradeUI.visible = false;
}
function closeMenu() {
towerMenu.visible = false;
}
// Create map path
function createMap() {
// Create a zigzag path from start to the castle
var path = [];
var startX = 150;
var startY = 150;
var tileSize = 120;
var mapWidth = Math.floor(2048 / tileSize) - 1;
var mapHeight = Math.floor(2732 / tileSize) - 5;
// Start point
path.push({
x: startX,
y: startY
});
// Generate zigzag path
var currentX = startX;
var currentY = startY;
var direction = 1; // 1 = right, -1 = left
for (var row = 0; row < 10; row++) {
// Move across
for (var i = 0; i < mapWidth - 1; i++) {
currentX += tileSize * direction;
path.push({
x: currentX,
y: currentY
});
}
// Move down
currentY += tileSize;
path.push({
x: currentX,
y: currentY
});
// Reverse direction
direction *= -1;
}
// Create path tiles
for (var i = 0; i < path.length; i++) {
var tile = new PathTile();
tile.x = path[i].x;
tile.y = path[i].y;
tile.tileIndex = i;
// Connect to next tile
if (i < path.length - 1) {
tile.nextTile = path[i + 1];
}
pathTiles.push(tile);
game.addChild(tile);
}
// Create castle at the end of the path
castle = new Castle();
castle.x = path[path.length - 1].x;
castle.y = path[path.length - 1].y + 150;
game.addChild(castle);
}
// Start a new wave
function startWave() {
waveActive = true;
enemiesToSpawn = waveSize;
enemiesSpawned = 0;
waveText.setText("Wave: " + wave + " - " + enemiesSpawned + "/" + enemiesToSpawn);
// Play wave start sound
LK.getSound('wave-start').play();
}
// Spawn a new enemy
function spawnEnemy() {
var enemy = new Enemy();
// Set enemy position at the start of the path
enemy.x = pathTiles[0].x;
enemy.y = pathTiles[0].y;
// Adjust enemy stats based on wave
enemy.health = 100 + (wave - 1) * 20;
enemy.maxHealth = enemy.health;
enemy.speed = 2 + wave * 0.1;
// Special enemy types for later waves
if (wave > 3 && Math.random() < 0.3) {
// Fast enemy
enemy.health = Math.floor(enemy.health * 0.7);
enemy.maxHealth = enemy.health;
enemy.speed = enemy.speed * 1.5;
enemy.reward = 15;
enemy.type = 'fast';
// Visually distinguish fast enemies
enemy.children[0].tint = 0x00FFFF;
}
if (wave > 5 && Math.random() < 0.2) {
// Tank enemy
enemy.health = Math.floor(enemy.health * 2);
enemy.maxHealth = enemy.health;
enemy.speed = enemy.speed * 0.7;
enemy.reward = 20;
enemy.type = 'tank';
// Visually distinguish tank enemies
enemy.children[0].tint = 0x8800FF;
}
// Update health bar
enemy.updateHealthBar();
// Add to game
enemies.push(enemy);
game.addChild(enemy);
// Update counter
enemiesSpawned++;
waveText.setText("Wave: " + wave + " - " + enemiesSpawned + "/" + enemiesToSpawn);
}
// Create tower placement preview
function createTowerPlacementPreview() {
// Remove existing preview if any
if (towerPlacementPreview) {
towerPlacementPreview.destroy();
towerPlacementPreview = null;
}
// Create appropriate tower preview based on type
if (placingTowerType === 'archer') {
towerPlacementPreview = new ArcherTower();
} else if (placingTowerType === 'cannon') {
towerPlacementPreview = new CannonTower();
} else if (placingTowerType === 'wizard') {
towerPlacementPreview = new WizardTower();
}
// Make preview semi-transparent
towerPlacementPreview.alpha = 0.6;
// Show range
towerPlacementPreview.showRange();
// Add to game
game.addChild(towerPlacementPreview);
}
// Check if position is valid for tower placement
function isValidTowerPosition(x, y) {
// Don't place towers on the path
for (var i = 0; i < pathTiles.length; i++) {
var tile = pathTiles[i];
var dx = tile.x - x;
var dy = tile.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
return false;
}
}
// Don't place towers on the castle
var dx = castle.x - x;
var dy = castle.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
return false;
}
// Don't place towers on other towers
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - x;
var dy = tower.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
return false;
}
}
// Check if in bounds
if (x < 50 || x > 2048 - 50 || y < 50 || y > 2732 - 50) {
return false;
}
return true;
}
// Place tower at position
function placeTower(x, y) {
var tower;
if (placingTowerType === 'archer') {
tower = new ArcherTower();
gold -= tower.cost;
} else if (placingTowerType === 'cannon') {
tower = new CannonTower();
gold -= tower.cost;
} else if (placingTowerType === 'wizard') {
tower = new WizardTower();
gold -= tower.cost;
}
tower.x = x;
tower.y = y;
// Add to game
towers.push(tower);
game.addChild(tower);
// Play build sound
LK.getSound('build').play();
// Update gold text
goldText.setText("Gold: " + gold);
// Clear placement mode
placingTowerType = null;
if (towerPlacementPreview) {
towerPlacementPreview.destroy();
towerPlacementPreview = null;
}
}
// Game down event (mouse/touch down)
game.down = function (x, y, obj) {
// If in tower placement mode
if (placingTowerType && towerPlacementPreview) {
if (isValidTowerPosition(x, y)) {
placeTower(x, y);
}
} else {
// If upgrade UI is visible and clicked outside, hide it
if (upgradeUI.visible) {
var upgradeUIBounds = upgradeUI.getBounds();
if (x < upgradeUI.x - upgradeUIBounds.width / 2 || x > upgradeUI.x + upgradeUIBounds.width / 2 || y < upgradeUI.y - upgradeUIBounds.height / 2 || y > upgradeUI.y + upgradeUIBounds.height / 2) {
if (selectedTower) {
selectedTower.hideRange();
selectedTower = null;
}
upgradeUI.visible = false;
}
}
// If tower menu is visible and clicked outside, hide it
if (towerMenu.visible) {
var menuBounds = towerMenu.getBounds();
if (x < towerMenu.x - menuBounds.width / 2 || x > towerMenu.x + menuBounds.width / 2 || y < towerMenu.y - menuBounds.height / 2 || y > towerMenu.y + menuBounds.height / 2) {
closeMenu();
}
}
}
};
// Game move event
game.move = function (x, y, obj) {
// If in tower placement mode, update preview position
if (placingTowerType && towerPlacementPreview) {
towerPlacementPreview.x = x;
towerPlacementPreview.y = y;
// Change color based on placement validity
if (isValidTowerPosition(x, y)) {
towerPlacementPreview.alpha = 0.6;
towerPlacementPreview.rangeIndicator.tint = 0xFFFFFF;
} else {
towerPlacementPreview.alpha = 0.4;
towerPlacementPreview.rangeIndicator.tint = 0xFF0000;
}
}
};
// Game up event
game.up = function (x, y, obj) {
// We handle most interactions in the down event
};
// Main game update
game.update = function () {
// Spawn enemies during active wave
if (waveActive) {
enemySpawnTimer++;
if (enemySpawnTimer >= 60 && enemiesSpawned < enemiesToSpawn) {
spawnEnemy();
enemySpawnTimer = 0;
}
// Check if wave is complete
if (enemiesSpawned >= enemiesToSpawn && enemies.length === 0) {
// Wave completed
waveActive = false;
wave++;
waveSize = Math.floor(waveSize * 1.3);
waveText.setText("Wave: " + wave);
// Award gold for completing wave
var waveReward = 50 + wave * 10;
gold += waveReward;
goldText.setText("Gold: " + gold);
// Display wave completion message
var waveCompleteText = new Text2("Wave Complete!\n+" + waveReward + " gold", {
size: 70,
fill: 0xFFFFFF
});
waveCompleteText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(waveCompleteText);
// Remove message after delay
LK.setTimeout(function () {
LK.gui.center.removeChild(waveCompleteText);
}, 2000);
// Update high score if needed
if (wave > storage.lastWave) {
storage.lastWave = wave;
}
}
}
// Update all enemies
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
// Update all towers
for (var i = 0; i < towers.length; i++) {
towers[i].update();
}
// Update all projectiles
for (var i = 0; i < projectiles.length; i++) {
projectiles[i].update();
}
};
// Initialize game
function initGame() {
// Reset variables
gold = 200;
wave = 1;
waveSize = 5;
waveActive = false;
enemySpawnTimer = 0;
enemiesSpawned = 0;
enemiesToSpawn = 0;
selectedTower = null;
placingTowerType = null;
// Clear arrays
while (enemies.length > 0) {
enemies[0].destroy();
enemies.splice(0, 1);
}
while (towers.length > 0) {
towers[0].destroy();
towers.splice(0, 1);
}
while (projectiles.length > 0) {
projectiles[0].destroy();
projectiles.splice(0, 1);
}
while (pathTiles.length > 0) {
pathTiles[0].destroy();
pathTiles.splice(0, 1);
}
if (castle) {
castle.destroy();
castle = null;
}
if (towerPlacementPreview) {
towerPlacementPreview.destroy();
towerPlacementPreview = null;
}
// Reset score
LK.setScore(0);
// Set up UI
initUI();
// Create map
createMap();
// Start background music
LK.playMusic('background-music');
}
// Initialize game on startup
initGame(); ===================================================================
--- original.js
+++ change.js
@@ -580,20 +580,20 @@
scoreText = new Text2("Score: 0", {
size: 50,
fill: 0xFFFFFF
});
- scoreText.anchor.set(0, 0);
+ scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
- scoreText.x = -250;
+ scoreText.x = -50;
scoreText.y = 50;
// Gold text
goldText = new Text2("Gold: " + gold, {
size: 50,
fill: 0xFFD700
});
goldText.anchor.set(1, 0);
LK.gui.topRight.addChild(goldText);
- goldText.x = -50;
+ goldText.x = -250;
goldText.y = 50;
// Wave text
waveText = new Text2("Wave: " + wave, {
size: 50,