User prompt
7th to south by 15 pixels 8th to south by 100 pixels 9th north by 50 pixels
User prompt
5th tower to left a little bit more 7th tower to south significantly 8th tower to north by half of its size
User prompt
move 4th and 5th towers from start slightly to left
User prompt
ensure all towers will allow a level 1 wizard to shoot to the enemy path. top 3 towers seems to be misplaced.
User prompt
avoid putting tower on enemy path. all towers shall be outside of enemy path to home base
User prompt
place all towers again so all towers will be able to let a level 1 wizard to hit an enemy
User prompt
towers shall not intersect with enemy path assets. no tower asset shall be touching enemy path asset
User prompt
revert all tower placements
User prompt
tower assets shall not intersect with enemy path assets
User prompt
place towers just near the enemy path but not intersecting with the path
User prompt
place each tower apart from the enemy path asset with an exact distance of half of the width of path asset
User prompt
place towers completely out of enemy path assets. however each tower shall allow a level 1 wizard to be able to shoot to the path.
User prompt
towers placement shall not interfere with enemy path. they can be close but not intersecting with enemy path.
User prompt
tunnels are not like i want. i want the path that enemies travel a continious route like a road.
User prompt
show enemy path as a open top tunnel
User prompt
make maze more complex so it is not a simple zigzag pattern
User prompt
decrease enemy kill gold bonus by dividing it to 10. make background an cobblestone road asset. make enemy path a dark colored road instead of lines.
User prompt
border maze with lines so it will be more visible
User prompt
arrange placement of each tower so even a level 1 wizard can shoot in the maze
User prompt
decrease the number of towers increase home base hp to 1000 increase enemy HP remove main menu, tutorial and select level buttons and make wave start button to start the game allow player to place wizards on towers before starting the wave have only one type of enemy for each wave
User prompt
waves shall follow each other automatically with 5 second difference. which means 5 seconds after last enemy of wave 1 enters, first enemy of wave 2 shall enter without clicking start wave button.
User prompt
wave system is completely broken. only two wave enters and at the same time interval. also you may remove below wizard selecting menu as now we are clicking on tower to select wizard type. also show wizards' shooting range.
User prompt
second wave still enters while first wave is entering. do not send any enemy from following wave until first wave's last enemy enters the maze and 5 second passes. let's forget about drag and drop of wizards. when i click a wizard, pause the game, show me a pop-up menu so i can select type and level of wizard and then unpause the game when i select the tower to place the wizard.
User prompt
thing to modify: 1. level shall start when player clicks start 2. there shall be a main menu to let player to start game, to read tutorial or to select level. 3. wizards cannot be dragged into towers 4. each wave shall enter the maze 5 seconds after the last character of previous wave enters the maze 5. maze shall be more visible by line borders 6. number of enemies in each wave is wrong. each wave also have 10-20 random number of enemies from level 1 to 5, 15-25 random number of enemies for level 6-10, 20-35 for levels 11-15 and 35-50 for levels 16-20.
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Enemy = Container.expand(function (enemyType, level) { var self = Container.call(this); self.enemyType = enemyType || 'basic'; self.level = level || 1; self.pathIndex = 0; self.pathProgress = 0; self.speed = 2; switch (self.enemyType) { case 'basic': self.maxHP = 100 + level * 50; self.speed = 2; break; case 'fast': self.maxHP = 50 + level * 25; self.speed = 4; break; case 'tank': self.maxHP = 300 + level * 100; self.speed = 1; break; } self.hp = self.maxHP; self.goldValue = self.maxHP; var enemyGraphics = self.attachAsset('enemy_' + self.enemyType, { anchorX: 0.5, anchorY: 0.5 }); var hpBar = new Container(); var hpBackground = LK.getAsset('ui_background', { width: 60, height: 8, anchorX: 0.5, anchorY: 0.5 }); hpBackground.tint = 0x000000; hpBar.addChild(hpBackground); var hpFill = LK.getAsset('ui_background', { width: 60, height: 8, anchorX: 0, anchorY: 0.5 }); hpFill.tint = 0x00ff00; hpFill.x = -30; hpBar.addChild(hpFill); hpBar.y = -40; self.addChild(hpBar); self.update = function () { if (currentPath && currentPath.length > 0) { self.followPath(); } // Update HP bar var hpPercent = self.hp / self.maxHP; hpFill.width = 60 * hpPercent; hpFill.tint = hpPercent > 0.5 ? 0x00ff00 : hpPercent > 0.25 ? 0xffff00 : 0xff0000; }; self.followPath = function () { if (self.pathIndex >= currentPath.length) { self.reachBase(); return; } var targetPoint = currentPath[self.pathIndex]; var dx = targetPoint.x - self.x; var dy = targetPoint.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 5) { self.pathIndex++; return; } self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; }; self.takeDamage = function (damage) { self.hp -= damage; LK.getSound('enemyHit').play(); if (self.hp <= 0) { self.die(); } }; self.die = function () { gold += self.goldValue; updateGoldDisplay(); LK.getSound('enemyDeath').play(); for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); }; self.reachBase = function () { baseHP -= 10; updateBaseHPDisplay(); if (baseHP <= 0) { LK.showGameOver(); } for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); }; return self; }); var Projectile = Container.expand(function (startX, startY, target, damage) { var self = Container.call(this); self.x = startX; self.y = startY; self.target = target; self.damage = damage; self.speed = 8; var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (!self.target || self.target.destroyed) { 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 < 10) { self.target.takeDamage(self.damage); self.destroy(); return; } self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; }; return self; }); var TowerSlot = Container.expand(function (x, y) { var self = Container.call(this); self.x = x; self.y = y; self.isEmpty = true; self.wizard = null; var slotGraphics = self.attachAsset('tower_slot', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { if (draggedWizard && self.isEmpty) { self.placeWizard(draggedWizard); } }; self.placeWizard = function (wizardType) { var cost = 500; if (gold >= cost) { gold -= cost; updateGoldDisplay(); self.wizard = new Wizard(wizardType, 1); self.wizard.x = self.x; self.wizard.y = self.y; self.isEmpty = false; game.addChild(self.wizard); wizards.push(self.wizard); draggedWizard = null; } }; return self; }); var Wizard = Container.expand(function (elementType, level) { var self = Container.call(this); self.elementType = elementType || 'fire'; self.level = level || 1; self.elementalDamage = 100 * self.level; self.magicDamage = 100 * self.level; self.range = 150 + self.level * 20; self.attackSpeed = 1000 - self.level * 50; // ms between attacks self.lastAttackTime = 0; self.cost = 500 * Math.pow(1.8, self.level - 1); var wizardGraphics = self.attachAsset('wizard_' + self.elementType, { anchorX: 0.5, anchorY: 0.5 }); var levelText = new Text2(self.level.toString(), { size: 24, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0.5); levelText.y = -10; self.addChild(levelText); self.update = function () { if (LK.ticks - self.lastAttackTime > self.attackSpeed / 16.67) { var target = self.findTarget(); if (target) { self.attack(target); self.lastAttackTime = LK.ticks; } } }; self.findTarget = function () { var closestEnemy = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2)); if (distance <= self.range && distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } return closestEnemy; }; self.attack = function (target) { var projectile = new Projectile(self.x, self.y, target, self.elementalDamage + self.magicDamage); projectiles.push(projectile); game.addChild(projectile); LK.getSound('shoot').play(); }; return self; }); var WizardIcon = Container.expand(function (elementType) { var self = Container.call(this); self.elementType = elementType; var iconGraphics = self.attachAsset('wizard_' + elementType, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var costText = new Text2('500', { size: 20, fill: 0xFFFFFF }); costText.anchor.set(0.5, 0); costText.y = 45; self.addChild(costText); self.down = function (x, y, obj) { if (gold >= 500) { draggedWizard = self.elementType; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x228B22 }); /**** * Game Code ****/ // Game state variables var currentLevel = 1; var currentWave = 1; var maxWaves = 10; var gold = 1000; var baseHP = 100; var gameState = 'playing'; // 'playing', 'paused', 'between_waves' var waveSpawnTimer = 0; var enemiesSpawnedThisWave = 0; var enemiesPerWave = 10; var draggedWizard = null; // Game object arrays var enemies = []; var wizards = []; var projectiles = []; var towerSlots = []; var wizardIcons = []; // Path system var currentPath = []; var pathPoints = [{ x: 50, y: 400 }, { x: 200, y: 400 }, { x: 200, y: 600 }, { x: 400, y: 600 }, { x: 400, y: 800 }, { x: 600, y: 800 }, { x: 600, y: 1000 }, { x: 800, y: 1000 }, { x: 800, y: 1200 }, { x: 1000, y: 1200 }, { x: 1000, y: 1400 }, { x: 1200, y: 1400 }, { x: 1200, y: 1600 }, { x: 1400, y: 1600 }, { x: 1400, y: 1800 }, { x: 1600, y: 1800 }]; // UI elements var goldText = new Text2('Gold: ' + gold, { size: 40, fill: 0xFFFFFF }); goldText.anchor.set(0, 0); goldText.x = 100; goldText.y = 50; game.addChild(goldText); var baseHPText = new Text2('Base HP: ' + baseHP, { size: 40, fill: 0xFFFFFF }); baseHPText.anchor.set(0, 0); baseHPText.x = 100; baseHPText.y = 100; game.addChild(baseHPText); var waveText = new Text2('Wave: ' + currentWave + '/' + maxWaves, { size: 40, fill: 0xFFFFFF }); waveText.anchor.set(0, 0); waveText.x = 100; waveText.y = 150; game.addChild(waveText); // Initialize path currentPath = pathPoints; // Create path visualization for (var i = 0; i < currentPath.length; i++) { var pathTile = game.addChild(LK.getAsset('path_tile', { anchorX: 0.5, anchorY: 0.5 })); pathTile.x = currentPath[i].x; pathTile.y = currentPath[i].y; } // Create home base var homeBase = game.addChild(LK.getAsset('home_base', { anchorX: 0.5, anchorY: 0.5 })); homeBase.x = currentPath[currentPath.length - 1].x; homeBase.y = currentPath[currentPath.length - 1].y; // Create tower slots var towerPositions = [{ x: 300, y: 300 }, { x: 500, y: 300 }, { x: 700, y: 300 }, { x: 300, y: 500 }, { x: 500, y: 500 }, { x: 700, y: 500 }, { x: 300, y: 700 }, { x: 500, y: 700 }, { x: 700, y: 700 }, { x: 900, y: 700 }, { x: 1100, y: 700 }, { x: 1300, y: 700 }, { x: 900, y: 900 }, { x: 1100, y: 900 }, { x: 1300, y: 900 }, { x: 900, y: 1100 }, { x: 1100, y: 1100 }, { x: 1300, y: 1100 }, { x: 1500, y: 1100 }, { x: 1700, y: 1100 }, { x: 1500, y: 1300 }, { x: 1700, y: 1300 }, { x: 1500, y: 1500 }, { x: 1700, y: 1500 }]; for (var i = 0; i < towerPositions.length; i++) { var slot = new TowerSlot(towerPositions[i].x, towerPositions[i].y); towerSlots.push(slot); game.addChild(slot); } // Create UI bottom panel var uiPanel = game.addChild(LK.getAsset('ui_background', { anchorX: 0, anchorY: 1 })); uiPanel.x = 0; uiPanel.y = 2732; // Create wizard icons var wizardTypes = ['fire', 'ice', 'nature', 'dark', 'light']; for (var i = 0; i < wizardTypes.length; i++) { var icon = new WizardIcon(wizardTypes[i]); icon.x = 150 + i * 150; icon.y = 2632; wizardIcons.push(icon); game.addChild(icon); } // Helper functions function updateGoldDisplay() { goldText.setText('Gold: ' + gold); } function updateBaseHPDisplay() { baseHPText.setText('Base HP: ' + baseHP); } function updateWaveDisplay() { waveText.setText('Wave: ' + currentWave + '/' + maxWaves); } function spawnEnemy() { var enemyType = 'basic'; if (Math.random() < 0.3) enemyType = 'fast'; if (Math.random() < 0.1) enemyType = 'tank'; var enemy = new Enemy(enemyType, currentLevel); enemy.x = currentPath[0].x; enemy.y = currentPath[0].y; enemies.push(enemy); game.addChild(enemy); } function startNextWave() { if (currentWave < maxWaves) { currentWave++; enemiesSpawnedThisWave = 0; gameState = 'playing'; updateWaveDisplay(); } else { // Level complete currentLevel++; currentWave = 1; maxWaves += 2; enemiesPerWave += 5; updateWaveDisplay(); if (currentLevel > 20) { LK.showYouWin(); } } } // Game update loop game.update = function () { // Spawn enemies if (gameState === 'playing' && enemiesSpawnedThisWave < enemiesPerWave) { if (LK.ticks % 60 === 0) { // Spawn every second spawnEnemy(); enemiesSpawnedThisWave++; } } // Check if wave is complete if (enemiesSpawnedThisWave >= enemiesPerWave && enemies.length === 0) { gameState = 'between_waves'; setTimeout(function () { startNextWave(); }, 2000); } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; if (projectile.destroyed) { projectiles.splice(i, 1); } } // Clean up destroyed enemies for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].destroyed) { enemies.splice(i, 1); } } // Clean up destroyed wizards for (var i = wizards.length - 1; i >= 0; i--) { if (wizards[i].destroyed) { wizards.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function (enemyType, level) {
var self = Container.call(this);
self.enemyType = enemyType || 'basic';
self.level = level || 1;
self.pathIndex = 0;
self.pathProgress = 0;
self.speed = 2;
switch (self.enemyType) {
case 'basic':
self.maxHP = 100 + level * 50;
self.speed = 2;
break;
case 'fast':
self.maxHP = 50 + level * 25;
self.speed = 4;
break;
case 'tank':
self.maxHP = 300 + level * 100;
self.speed = 1;
break;
}
self.hp = self.maxHP;
self.goldValue = self.maxHP;
var enemyGraphics = self.attachAsset('enemy_' + self.enemyType, {
anchorX: 0.5,
anchorY: 0.5
});
var hpBar = new Container();
var hpBackground = LK.getAsset('ui_background', {
width: 60,
height: 8,
anchorX: 0.5,
anchorY: 0.5
});
hpBackground.tint = 0x000000;
hpBar.addChild(hpBackground);
var hpFill = LK.getAsset('ui_background', {
width: 60,
height: 8,
anchorX: 0,
anchorY: 0.5
});
hpFill.tint = 0x00ff00;
hpFill.x = -30;
hpBar.addChild(hpFill);
hpBar.y = -40;
self.addChild(hpBar);
self.update = function () {
if (currentPath && currentPath.length > 0) {
self.followPath();
}
// Update HP bar
var hpPercent = self.hp / self.maxHP;
hpFill.width = 60 * hpPercent;
hpFill.tint = hpPercent > 0.5 ? 0x00ff00 : hpPercent > 0.25 ? 0xffff00 : 0xff0000;
};
self.followPath = function () {
if (self.pathIndex >= currentPath.length) {
self.reachBase();
return;
}
var targetPoint = currentPath[self.pathIndex];
var dx = targetPoint.x - self.x;
var dy = targetPoint.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 5) {
self.pathIndex++;
return;
}
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
};
self.takeDamage = function (damage) {
self.hp -= damage;
LK.getSound('enemyHit').play();
if (self.hp <= 0) {
self.die();
}
};
self.die = function () {
gold += self.goldValue;
updateGoldDisplay();
LK.getSound('enemyDeath').play();
for (var i = 0; i < enemies.length; i++) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
self.reachBase = function () {
baseHP -= 10;
updateBaseHPDisplay();
if (baseHP <= 0) {
LK.showGameOver();
}
for (var i = 0; i < enemies.length; i++) {
if (enemies[i] === self) {
enemies.splice(i, 1);
break;
}
}
self.destroy();
};
return self;
});
var Projectile = Container.expand(function (startX, startY, target, damage) {
var self = Container.call(this);
self.x = startX;
self.y = startY;
self.target = target;
self.damage = damage;
self.speed = 8;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.target || self.target.destroyed) {
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 < 10) {
self.target.takeDamage(self.damage);
self.destroy();
return;
}
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
};
return self;
});
var TowerSlot = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.isEmpty = true;
self.wizard = null;
var slotGraphics = self.attachAsset('tower_slot', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
if (draggedWizard && self.isEmpty) {
self.placeWizard(draggedWizard);
}
};
self.placeWizard = function (wizardType) {
var cost = 500;
if (gold >= cost) {
gold -= cost;
updateGoldDisplay();
self.wizard = new Wizard(wizardType, 1);
self.wizard.x = self.x;
self.wizard.y = self.y;
self.isEmpty = false;
game.addChild(self.wizard);
wizards.push(self.wizard);
draggedWizard = null;
}
};
return self;
});
var Wizard = Container.expand(function (elementType, level) {
var self = Container.call(this);
self.elementType = elementType || 'fire';
self.level = level || 1;
self.elementalDamage = 100 * self.level;
self.magicDamage = 100 * self.level;
self.range = 150 + self.level * 20;
self.attackSpeed = 1000 - self.level * 50; // ms between attacks
self.lastAttackTime = 0;
self.cost = 500 * Math.pow(1.8, self.level - 1);
var wizardGraphics = self.attachAsset('wizard_' + self.elementType, {
anchorX: 0.5,
anchorY: 0.5
});
var levelText = new Text2(self.level.toString(), {
size: 24,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0.5);
levelText.y = -10;
self.addChild(levelText);
self.update = function () {
if (LK.ticks - self.lastAttackTime > self.attackSpeed / 16.67) {
var target = self.findTarget();
if (target) {
self.attack(target);
self.lastAttackTime = LK.ticks;
}
}
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.attack = function (target) {
var projectile = new Projectile(self.x, self.y, target, self.elementalDamage + self.magicDamage);
projectiles.push(projectile);
game.addChild(projectile);
LK.getSound('shoot').play();
};
return self;
});
var WizardIcon = Container.expand(function (elementType) {
var self = Container.call(this);
self.elementType = elementType;
var iconGraphics = self.attachAsset('wizard_' + elementType, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
var costText = new Text2('500', {
size: 20,
fill: 0xFFFFFF
});
costText.anchor.set(0.5, 0);
costText.y = 45;
self.addChild(costText);
self.down = function (x, y, obj) {
if (gold >= 500) {
draggedWizard = self.elementType;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Game state variables
var currentLevel = 1;
var currentWave = 1;
var maxWaves = 10;
var gold = 1000;
var baseHP = 100;
var gameState = 'playing'; // 'playing', 'paused', 'between_waves'
var waveSpawnTimer = 0;
var enemiesSpawnedThisWave = 0;
var enemiesPerWave = 10;
var draggedWizard = null;
// Game object arrays
var enemies = [];
var wizards = [];
var projectiles = [];
var towerSlots = [];
var wizardIcons = [];
// Path system
var currentPath = [];
var pathPoints = [{
x: 50,
y: 400
}, {
x: 200,
y: 400
}, {
x: 200,
y: 600
}, {
x: 400,
y: 600
}, {
x: 400,
y: 800
}, {
x: 600,
y: 800
}, {
x: 600,
y: 1000
}, {
x: 800,
y: 1000
}, {
x: 800,
y: 1200
}, {
x: 1000,
y: 1200
}, {
x: 1000,
y: 1400
}, {
x: 1200,
y: 1400
}, {
x: 1200,
y: 1600
}, {
x: 1400,
y: 1600
}, {
x: 1400,
y: 1800
}, {
x: 1600,
y: 1800
}];
// UI elements
var goldText = new Text2('Gold: ' + gold, {
size: 40,
fill: 0xFFFFFF
});
goldText.anchor.set(0, 0);
goldText.x = 100;
goldText.y = 50;
game.addChild(goldText);
var baseHPText = new Text2('Base HP: ' + baseHP, {
size: 40,
fill: 0xFFFFFF
});
baseHPText.anchor.set(0, 0);
baseHPText.x = 100;
baseHPText.y = 100;
game.addChild(baseHPText);
var waveText = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0, 0);
waveText.x = 100;
waveText.y = 150;
game.addChild(waveText);
// Initialize path
currentPath = pathPoints;
// Create path visualization
for (var i = 0; i < currentPath.length; i++) {
var pathTile = game.addChild(LK.getAsset('path_tile', {
anchorX: 0.5,
anchorY: 0.5
}));
pathTile.x = currentPath[i].x;
pathTile.y = currentPath[i].y;
}
// Create home base
var homeBase = game.addChild(LK.getAsset('home_base', {
anchorX: 0.5,
anchorY: 0.5
}));
homeBase.x = currentPath[currentPath.length - 1].x;
homeBase.y = currentPath[currentPath.length - 1].y;
// Create tower slots
var towerPositions = [{
x: 300,
y: 300
}, {
x: 500,
y: 300
}, {
x: 700,
y: 300
}, {
x: 300,
y: 500
}, {
x: 500,
y: 500
}, {
x: 700,
y: 500
}, {
x: 300,
y: 700
}, {
x: 500,
y: 700
}, {
x: 700,
y: 700
}, {
x: 900,
y: 700
}, {
x: 1100,
y: 700
}, {
x: 1300,
y: 700
}, {
x: 900,
y: 900
}, {
x: 1100,
y: 900
}, {
x: 1300,
y: 900
}, {
x: 900,
y: 1100
}, {
x: 1100,
y: 1100
}, {
x: 1300,
y: 1100
}, {
x: 1500,
y: 1100
}, {
x: 1700,
y: 1100
}, {
x: 1500,
y: 1300
}, {
x: 1700,
y: 1300
}, {
x: 1500,
y: 1500
}, {
x: 1700,
y: 1500
}];
for (var i = 0; i < towerPositions.length; i++) {
var slot = new TowerSlot(towerPositions[i].x, towerPositions[i].y);
towerSlots.push(slot);
game.addChild(slot);
}
// Create UI bottom panel
var uiPanel = game.addChild(LK.getAsset('ui_background', {
anchorX: 0,
anchorY: 1
}));
uiPanel.x = 0;
uiPanel.y = 2732;
// Create wizard icons
var wizardTypes = ['fire', 'ice', 'nature', 'dark', 'light'];
for (var i = 0; i < wizardTypes.length; i++) {
var icon = new WizardIcon(wizardTypes[i]);
icon.x = 150 + i * 150;
icon.y = 2632;
wizardIcons.push(icon);
game.addChild(icon);
}
// Helper functions
function updateGoldDisplay() {
goldText.setText('Gold: ' + gold);
}
function updateBaseHPDisplay() {
baseHPText.setText('Base HP: ' + baseHP);
}
function updateWaveDisplay() {
waveText.setText('Wave: ' + currentWave + '/' + maxWaves);
}
function spawnEnemy() {
var enemyType = 'basic';
if (Math.random() < 0.3) enemyType = 'fast';
if (Math.random() < 0.1) enemyType = 'tank';
var enemy = new Enemy(enemyType, currentLevel);
enemy.x = currentPath[0].x;
enemy.y = currentPath[0].y;
enemies.push(enemy);
game.addChild(enemy);
}
function startNextWave() {
if (currentWave < maxWaves) {
currentWave++;
enemiesSpawnedThisWave = 0;
gameState = 'playing';
updateWaveDisplay();
} else {
// Level complete
currentLevel++;
currentWave = 1;
maxWaves += 2;
enemiesPerWave += 5;
updateWaveDisplay();
if (currentLevel > 20) {
LK.showYouWin();
}
}
}
// Game update loop
game.update = function () {
// Spawn enemies
if (gameState === 'playing' && enemiesSpawnedThisWave < enemiesPerWave) {
if (LK.ticks % 60 === 0) {
// Spawn every second
spawnEnemy();
enemiesSpawnedThisWave++;
}
}
// Check if wave is complete
if (enemiesSpawnedThisWave >= enemiesPerWave && enemies.length === 0) {
gameState = 'between_waves';
setTimeout(function () {
startNextWave();
}, 2000);
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
if (projectile.destroyed) {
projectiles.splice(i, 1);
}
}
// Clean up destroyed enemies
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].destroyed) {
enemies.splice(i, 1);
}
}
// Clean up destroyed wizards
for (var i = wizards.length - 1; i >= 0; i--) {
if (wizards[i].destroyed) {
wizards.splice(i, 1);
}
}
};
Fort to defend. In-Game asset. 2d. High contrast. No shadows
bulky warrior like a tank. In-Game asset. 2d. High contrast. No shadows
fast and slim warrior to represent speed. In-Game asset. 2d. High contrast. No shadows
in game asset, colored, 2d warrior, face covered with helmet
dark wizard 2d in game asset. In-Game asset. 2d. High contrast. No shadows
mostly transparent grey circle. In-Game asset. 2d. High contrast. No shadows
top view, stone high tower.. In-Game asset. 2d. High contrast. No shadows
a fire wizard. In-Game asset. 2d. High contrast. No shadows
cornerstone 2d in game asset from top view
2d in game asset ice wizard. In-Game asset. 2d. High contrast. No shadows
2d in game asset nature (green) wizard.
2d in game asset light (yellow) wizard.
magic bolt traveling in air
2d, top view, very light grey, very very very small tiled (at least 1000 tiles), cobblestone road texture