User prompt
if enemy on the left of tower_2 flip the arrow asset
User prompt
change tower_1 shot by star, tower_2 shot by arrow, tower_3 with both star and arrow at the same time.
User prompt
change tower_1 shot by star, tower_2 shot by arrow, tower_3 with both star and arrow at the same time.
User prompt
center the enemies on the center of the road they are moving on the edges! ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the map bigger and with one line of cells on the left side and the right side no double cells of towers beside each others!
Code edit (12 edits merged)
Please save this source code
User prompt
Please fix the bug: 'towertext1 is not defined' in or related to this line: 'towertext1.x = 50;' Line Number: 273
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
reduce the distance between cursor and the dragged tower!
User prompt
when i buy tower drag it with same position of the cursor
User prompt
Create healthbar for the enemy red color
User prompt
Fix double buildable tiles by ensuring each tile is only marked once
User prompt
Do one line on each side of the roads with the buildabletile
User prompt
make the dragging towers distance closer to the cursor its far from it.
User prompt
the tower clicking detection is not working!
User prompt
add drag to the 3 towers icons to be dragged after buying
User prompt
Buy tower directly when i click on it duplicate the same image of it with the cursor to be placed.
User prompt
make the buying directly by clicking on the towers assets.
User prompt
center the tower_1 in its Uibutton.
User prompt
the towers assets are not in the middle of their UIbuttons!
User prompt
the towers assets are not in the middle of their buttons!
User prompt
If i click on any tower to buy it duplicate it to the cursor to be placed to the grid cell
User prompt
if i click on a tower stop the dragging of the gamebackground to place a tower
User prompt
Make the towers in the middle of their grids cells buttons
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Enemy = Container.expand(function (path) { var self = Container.call(this); self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.speed = 3; self.path = path; self.currentWaypointIndex = 1; self.value = 10; // Score awarded on defeat self.update = function () { if (self.currentWaypointIndex >= self.path.length) { // Reached the end LK.showGameOver(); self.destroy(); // Self-destruct to avoid multiple game overs return; } var targetWaypoint = self.path[self.currentWaypointIndex]; var dx = targetWaypoint.x - self.x; var dy = targetWaypoint.y - self.y; var angle = Math.atan2(dy, dx); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.speed) { self.currentWaypointIndex++; } }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { return true; // Is dead } LK.effects.flashObject(self, 0xffffff, 100); return false; // Is alive }; return self; }); var Projectile = Container.expand(function (start, target, damage) { var self = Container.call(this); self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.x = start.x; self.y = start.y; self.target = target; self.damage = damage; self.speed = 20; self.update = function () { if (!self.target || self.target.health <= 0) { // Target is gone projectiles.splice(projectiles.indexOf(self), 1); self.destroy(); 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 < self.speed) { // Hit target if (self.target.takeDamage(self.damage)) { // Enemy died LK.getSound('enemy_die').play(); LK.setScore(LK.getScore() + self.target.value); scoreTxt.setText('SCORE: ' + LK.getScore()); enemies.splice(enemies.indexOf(self.target), 1); self.target.destroy(); } projectiles.splice(projectiles.indexOf(self), 1); self.destroy(); } else { // Move towards target var angle = Math.atan2(dy, dx); self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } }; return self; }); var Tower = Container.expand(function (config) { var self = Container.call(this); self.config = config; self.attachAsset(config.asset, { anchorX: 0.5, anchorY: 0.5 }); self.cost = config.cost; self.damage = config.damage; self.range = 400; // All towers have same range for now self.fireRate = config.fireRate; // shots per second self.cooldown = 0; self.isTower = true; self.down = function (x, y, obj) { // This makes the tower a "button" console.log("Tower clicked! Damage: " + self.damage); LK.effects.flashObject(self, 0xffffff, 200); }; self.update = function () { if (self.cooldown > 0) { self.cooldown--; return; } var target = findClosestEnemy(self.x, self.y, self.range); if (target) { fireProjectile(self, target); self.cooldown = 60 / self.fireRate; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1e272e }); /**** * Game Code ****/ // The engine will automatically create these assets based on their usage below. // --- Constants & Game State --- var MAP_WIDTH = 3000; var MAP_HEIGHT = 4000; var CELL_SIZE = 200; var GRID_WIDTH = MAP_WIDTH / CELL_SIZE; var GRID_HEIGHT = MAP_HEIGHT / CELL_SIZE; // Grid states: 0=empty, 1=path, 2=buildable, 3=occupied var grid = []; var pathWaypoints = [{ x: 1500, y: -100 }, { x: 1500, y: 800 }, { x: 600, y: 800 }, { x: 600, y: 1600 }, { x: 2400, y: 1600 }, { x: 2400, y: 2400 }, { x: 1000, y: 2400 }, { x: 1000, y: 3200 }, { x: 2000, y: 3200 }, { x: 2000, y: 4100 }]; var enemies = []; var towers = []; var projectiles = []; var mapContainer = game.addChild(new Container()); mapContainer.width = MAP_WIDTH; mapContainer.height = MAP_HEIGHT; var placingTowerConfig = null; var ghostTower = null; var isDraggingMap = false; var dragStart = { x: 0, y: 0 }; var mapStart = { x: 0, y: 0 }; // --- Tower Configurations --- var towerTypes = { '1': { asset: 'tower_1', cost: 50, damage: 25, fireRate: 1.5 }, '2': { asset: 'tower_2', cost: 100, damage: 60, fireRate: 1 }, '3': { asset: 'tower_3', cost: 150, damage: 100, fireRate: 0.75 } }; // --- UI --- LK.setScore(80); // Starting cash var scoreTxt = new Text2('SCORE: ' + LK.getScore(), { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 20; LK.gui.top.addChild(scoreTxt); var uiContainer = LK.gui.bottom.addChild(new Container()); uiContainer.y = -20; // Move it up slightly from the absolute bottom var towerButton1 = uiContainer.addChild(LK.getAsset('uiButton', { anchorX: 0.5, anchorY: 1 })); towerButton1.x = -300; var towerIcon1 = towerButton1.addChild(LK.getAsset('tower_1', { scaleX: 0.8, scaleY: 0.8, anchorX: 0.5, anchorY: 0.5 })); towerIcon1.x = 110; towerIcon1.y = 110; var towerText1 = towerButton1.addChild(new Text2('50', { size: 50, fill: '#fff', anchorX: 0.5, anchorY: 0.5 })); towerText1.x = 110; towerText1.y = 195; var towerButton2 = uiContainer.addChild(LK.getAsset('uiButton', { anchorX: 0.5, anchorY: 1 })); var towerIcon2 = towerButton2.addChild(LK.getAsset('tower_2', { scaleX: 0.8, scaleY: 0.8, anchorX: 0.5, anchorY: 0.5 })); towerIcon2.x = 110; towerIcon2.y = 80; var towerText2 = towerButton2.addChild(new Text2('100', { size: 50, fill: '#fff', anchorX: 0.5, anchorY: 0.5 })); towerText2.x = 110; towerText2.y = 175; var towerButton3 = uiContainer.addChild(LK.getAsset('uiButton', { anchorX: 0.5, anchorY: 1 })); towerButton3.x = 300; var towerIcon3 = towerButton3.addChild(LK.getAsset('tower_3', { scaleX: 0.8, scaleY: 0.8, anchorX: 0.5, anchorY: 0.5 })); towerIcon3.x = 110; towerIcon3.y = 80; var towerText3 = towerButton3.addChild(new Text2('150', { size: 50, fill: '#fff', anchorX: 0.5, anchorY: 0.5 })); towerText3.x = 110; towerText3.y = 175; // --- Initialization Functions --- function initializeGrid() { for (var i = 0; i < GRID_WIDTH; i++) { grid[i] = []; for (var j = 0; j < GRID_HEIGHT; j++) { grid[i][j] = 0; // Empty } } // Mark path tiles for (var k = 0; k < pathWaypoints.length - 1; k++) { var start = pathWaypoints[k]; var end = pathWaypoints[k + 1]; var p1 = { x: Math.floor(start.x / CELL_SIZE), y: Math.floor(start.y / CELL_SIZE) }; var p2 = { x: Math.floor(end.x / CELL_SIZE), y: Math.floor(end.y / CELL_SIZE) }; var x = p1.x; var y = p1.y; var dx = Math.abs(p2.x - x); var dy = Math.abs(p2.y - y); var sx = x < p2.x ? 1 : -1; var sy = y < p2.y ? 1 : -1; var err = dx - dy; while (true) { if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) { grid[x][y] = 1; } if (x === p2.x && y === p2.y) break; var e2 = 2 * err; if (e2 > -dy) { err -= dy; x += sx; } if (e2 < dx) { err += dx; y += sy; } } } // Mark buildable tiles for (var i = 0; i < GRID_WIDTH; i++) { for (var j = 0; j < GRID_HEIGHT; j++) { if (grid[i][j] === 1) { // is a path tile for (var dx = -1; dx <= 1; dx++) { for (var dy = -1; dy <= 1; dy++) { if (dx === 0 && dy === 0) continue; var nx = i + dx; var ny = j + dy; if (nx >= 0 && nx < GRID_WIDTH && ny >= 0 && ny < GRID_HEIGHT && grid[nx][ny] === 0) { grid[nx][ny] = 2; // buildable } } } } } } // Draw visual grid for (var i = 0; i < GRID_WIDTH; i++) { for (var j = 0; j < GRID_HEIGHT; j++) { var tile; if (grid[i][j] === 1) { tile = mapContainer.addChild(LK.getAsset('pathTile', {})); } else if (grid[i][j] === 2) { tile = mapContainer.addChild(LK.getAsset('buildableTile', {})); tile.alpha = 0.5; } if (tile) { tile.x = i * CELL_SIZE; tile.y = j * CELL_SIZE; } } } } initializeGrid(); function startPlacingTower(type) { var config = towerTypes[type]; if (LK.getScore() >= config.cost) { placingTowerConfig = config; ghostTower = mapContainer.addChild(LK.getAsset(config.asset, { anchorX: 0.5, anchorY: 0.5 })); ghostTower.alpha = 0.7; } } // --- Event Handlers --- game.down = function (x, y, obj) { var localPoint = uiContainer.toLocal({ x: x, y: y }); // Tower Button 1 Check var b1_topLeft_x = towerButton1.x - towerButton1.width * 0.5; var b1_topLeft_y = towerButton1.y - towerButton1.height * 1; if (localPoint.x >= b1_topLeft_x && localPoint.x <= b1_topLeft_x + towerButton1.width && localPoint.y >= b1_topLeft_y && localPoint.y <= b1_topLeft_y + towerButton1.height) { startPlacingTower('1'); if (placingTowerConfig) game.move(x, y, obj); return; } // Tower Button 2 Check var b2_topLeft_x = towerButton2.x - towerButton2.width * 0.5; var b2_topLeft_y = towerButton2.y - towerButton2.height * 1; if (localPoint.x >= b2_topLeft_x && localPoint.x <= b2_topLeft_x + towerButton2.width && localPoint.y >= b2_topLeft_y && localPoint.y <= b2_topLeft_y + towerButton2.height) { startPlacingTower('2'); if (placingTowerConfig) game.move(x, y, obj); return; } // Tower Button 3 Check var b3_topLeft_x = towerButton3.x - towerButton3.width * 0.5; var b3_topLeft_y = towerButton3.y - towerButton3.height * 1; if (localPoint.x >= b3_topLeft_x && localPoint.x <= b3_topLeft_x + towerButton3.width && localPoint.y >= b3_topLeft_y && localPoint.y <= b3_topLeft_y + towerButton3.height) { startPlacingTower('3'); if (placingTowerConfig) game.move(x, y, obj); return; } // If the clicked object is a tower, treat it as a purchase click for that tower type if (obj && obj.target && (obj.target.isTower || obj.target.parent && obj.target.parent.isTower)) { var clickedTower = obj.target.isTower ? obj.target : obj.target.parent; // Find tower type from its config var myType = null; if (clickedTower.config) { for (var key in towerTypes) { if (towerTypes[key].asset === clickedTower.config.asset) { myType = key; break; } } } if (myType) { startPlacingTower(myType); if (placingTowerConfig) { game.move(x, y, obj); } } return; // Stop further processing (like map dragging) } if (!placingTowerConfig) { isDraggingMap = true; dragStart.x = x; dragStart.y = y; mapStart.x = mapContainer.x; mapStart.y = mapContainer.y; } }; game.move = function (x, y, obj) { if (placingTowerConfig) { var mapPos = mapContainer.toLocal({ x: x, y: y }); ghostTower.x = mapPos.x; ghostTower.y = mapPos.y; var gridX = Math.floor(mapPos.x / CELL_SIZE); var gridY = Math.floor(mapPos.y / CELL_SIZE); if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT && grid[gridX][gridY] === 2) { ghostTower.tint = 0x00ff00; // Green for valid } else { ghostTower.tint = 0xff0000; // Red for invalid } } else if (isDraggingMap) { var dx = x - dragStart.x; var dy = y - dragStart.y; // Clamp map position var newX = mapStart.x + dx; var newY = mapStart.y + dy; var gameWidth = 2048; var gameHeight = 2732; if (newX > 0) newX = 0; if (newY > 0) newY = 0; if (newX < gameWidth - MAP_WIDTH) newX = gameWidth - MAP_WIDTH; if (newY < gameHeight - MAP_HEIGHT) newY = gameHeight - MAP_HEIGHT; mapContainer.x = newX; mapContainer.y = newY; } }; game.up = function (x, y, obj) { if (placingTowerConfig) { var mapPos = mapContainer.toLocal({ x: x, y: y }); var gridX = Math.floor(mapPos.x / CELL_SIZE); var gridY = Math.floor(mapPos.y / CELL_SIZE); if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT && grid[gridX][gridY] === 2) { if (LK.getScore() >= placingTowerConfig.cost) { var newTower = new Tower(placingTowerConfig); newTower.x = gridX * CELL_SIZE + CELL_SIZE / 2; newTower.y = gridY * CELL_SIZE + CELL_SIZE / 2; mapContainer.addChild(newTower); towers.push(newTower); grid[gridX][gridY] = 3; // Mark as occupied LK.setScore(LK.getScore() - placingTowerConfig.cost); scoreTxt.setText('SCORE: ' + LK.getScore()); LK.getSound('place_tower').play(); } } ghostTower.destroy(); ghostTower = null; placingTowerConfig = null; } isDraggingMap = false; }; // --- Game Logic Functions --- function findClosestEnemy(x, y, range) { var closestEnemy = null; var minDistanceSq = range * range; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - x; var dy = enemy.y - y; var distanceSq = dx * dx + dy * dy; if (distanceSq < minDistanceSq) { minDistanceSq = distanceSq; closestEnemy = enemy; } } return closestEnemy; } function fireProjectile(tower, target) { var projectile = new Projectile({ x: tower.x, y: tower.y }, target, tower.damage); projectiles.push(projectile); mapContainer.addChild(projectile); LK.getSound('shoot').play(); } LK.setInterval(function () { var enemy = new Enemy(pathWaypoints); enemy.x = pathWaypoints[0].x; enemy.y = pathWaypoints[0].y; enemy.health += LK.getScore() / 10; // Scale health with score enemies.push(enemy); mapContainer.addChild(enemy); }, 2000); game.update = function () { for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].update(); } for (var i = towers.length - 1; i >= 0; i--) { towers[i].update(); } for (var i = projectiles.length - 1; i >= 0; i--) { projectiles[i].update(); } };
===================================================================
--- original.js
+++ change.js
@@ -226,36 +226,40 @@
var towerIcon1 = towerButton1.addChild(LK.getAsset('tower_1', {
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
- anchorY: 0.5,
- y: -140
+ anchorY: 0.5
}));
+towerIcon1.x = 110;
+towerIcon1.y = 110;
var towerText1 = towerButton1.addChild(new Text2('50', {
size: 50,
fill: '#fff',
anchorX: 0.5,
anchorY: 0.5
}));
-towerText1.y = -50;
+towerText1.x = 110;
+towerText1.y = 195;
var towerButton2 = uiContainer.addChild(LK.getAsset('uiButton', {
anchorX: 0.5,
anchorY: 1
}));
var towerIcon2 = towerButton2.addChild(LK.getAsset('tower_2', {
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
- anchorY: 0.5,
- y: -140
+ anchorY: 0.5
}));
+towerIcon2.x = 110;
+towerIcon2.y = 80;
var towerText2 = towerButton2.addChild(new Text2('100', {
size: 50,
fill: '#fff',
anchorX: 0.5,
anchorY: 0.5
}));
-towerText2.y = -50;
+towerText2.x = 110;
+towerText2.y = 175;
var towerButton3 = uiContainer.addChild(LK.getAsset('uiButton', {
anchorX: 0.5,
anchorY: 1
}));
@@ -263,18 +267,20 @@
var towerIcon3 = towerButton3.addChild(LK.getAsset('tower_3', {
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
- anchorY: 0.5,
- y: -140
+ anchorY: 0.5
}));
+towerIcon3.x = 110;
+towerIcon3.y = 80;
var towerText3 = towerButton3.addChild(new Text2('150', {
size: 50,
fill: '#fff',
anchorX: 0.5,
anchorY: 0.5
}));
-towerText3.y = -50;
+towerText3.x = 110;
+towerText3.y = 175;
// --- Initialization Functions ---
function initializeGrid() {
for (var i = 0; i < GRID_WIDTH; i++) {
grid[i] = [];