User prompt
separate images for left-spawned and right-spawned enemies
Code edit (7 edits merged)
Please save this source code
User prompt
enemies should be visible
User prompt
ADD A SPAWNER TO THE LEFT AND RIGHT, SEPARATE THEM, MAKE LEFT-SPAWNED ENEMIES FACE RIGHT, RIGHT-SPAWNED ENEMIES LEFT
User prompt
left enemies should face right.
Code edit (1 edits merged)
Please save this source code
User prompt
separate the enemies from left-spawning and right-spawning, reverse the image for ONLY the ones spawning from left
User prompt
reverse the image for left-spawned enemies
User prompt
reverse the image for the left-spawned enemies
User prompt
left-spawned enemies should face right
User prompt
enemies coming from right should face left, enemies coming from left should face right, set it up
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Base class var Base = Container.expand(function () { var self = Container.call(this); // Attach base asset (ellipse, blue) var baseGraphics = self.attachAsset('base', { anchorX: 0.5, anchorY: 0.5 }); baseGraphics.width = 180; baseGraphics.height = 180; baseGraphics.color = 0x3399ff; self.maxHp = 20; self.hp = self.maxHp; // Flash on hit self.hit = function () { LK.effects.flashObject(self, 0xff0000, 400); }; // Repair self.repair = function () { self.hp = Math.min(self.maxHp, self.hp + 5); }; // Upgrade self.upgrade = function () { self.maxHp += 10; self.hp = self.maxHp; baseGraphics.scaleX += 0.1; baseGraphics.scaleY += 0.1; }; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); // Attach bullet asset (box, yellow) var bulletGraphics = self.attachAsset('bullet', { anchorX: -2, anchorY: 2 }); bulletGraphics.width = 20; bulletGraphics.height = 20; bulletGraphics.color = 0xb8b031; self.speed = 24; self.target = null; self.side = 1; self.damage = 1; 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 dist = Math.sqrt(dx * dx + dy * dy); if (dist < 40) { // Hit! self.target.hp -= self.damage; LK.effects.flashObject(self.target, 0xffff00, 200); self.destroy(); return; } var step = self.speed; self.x += dx / dist * step; self.y += dy / dist * step; }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); // Attach enemy asset (ellipse, red) // Use separate images for left- and right-spawned enemies var assetId = self.direction === -1 ? 'enemyLeft' : 'enemyRight'; var enemyGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Set size and color enemyGraphics.width = 90; enemyGraphics.height = 90; enemyGraphics.color = 0xd83318; // Enemy properties self.speed = 3 + Math.random() * 1.5; // Will be set per wave self.hp = 1; // Will be set per wave self.direction = 1; // 1 for right-to-left, -1 for left-to-right // Update method self.update = function () { self.x += self.speed * self.direction; }; return self; }); // Turret class var Turret = Container.expand(function () { var self = Container.call(this); // Attach turret asset (box, green) var turretGraphics = self.attachAsset('turret', { anchorX: 0.5, anchorY: 0.5 }); turretGraphics.width = 100; turretGraphics.height = 100; turretGraphics.color = 0x83de44; // Turret properties self.range = 500; self.fireRate = 60; // frames between shots self.cooldown = 0; self.level = 1; self.side = 1; // 1 = right, -1 = left // Upgrade method self.upgrade = function () { if (self.level < 3) { self.level += 1; self.range += 100; self.fireRate = Math.max(30, self.fireRate - 10); turretGraphics.scaleX += 0.1; turretGraphics.scaleY += 0.1; } }; // Update method self.update = function () { if (self.cooldown > 0) { self.cooldown--; return; } // Find closest enemy in range on this side var closest = null; var minDist = self.range + 1; for (var i = 0; i < enemies.length; i++) { var e = enemies[i]; if (self.side === 1 && e.x > base.x || self.side === -1 && e.x < base.x) { var dx = e.x - self.x; var dy = e.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minDist && dist <= self.range) { minDist = dist; closest = e; } } } if (closest) { // Fire at enemy var b = new Bullet(); b.x = self.x; b.y = self.y; b.target = closest; b.side = self.side; b.damage = self.level; // Reverse bullet image for left turrets if (self.side === -1 && b.children && b.children.length > 0) { if (typeof b.children[0].scaleX !== "undefined") { b.children[0].scaleX = -1 * Math.abs(b.children[0].scaleX); } } bullets.push(b); game.addChild(b); self.cooldown = self.fireRate; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Add background image to the game scene var backgroundImg = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, width: 2048, height: 2732 }); game.addChild(backgroundImg); // Game state variables var base = new Base(); base.x = 2048 / 2; base.y = 2732 / 2; game.addChild(base); var turrets = []; var enemies = []; var bullets = []; var gold = 50; var wave = 1; var enemiesToSpawn = 0; var enemiesSpawned = 0; var enemiesPerWave = 6; var waveInProgress = false; var spawnTimer = 0; var nextWaveTimer = 0; var baseHealthTxt, goldTxt, waveTxt; var selectedTurret = null; // HP Bar for base (black outline, gray background, green foreground) // Use shape assets for outline, background, and foreground bar var baseHpBarOutline = LK.getAsset('baseHpBarOutline', { anchorX: 0.5, anchorY: 0.5, x: base.x, y: base.y - 190, width: 208, height: 40 }); var baseHpBarBg = LK.getAsset('baseHpBarBg', { anchorX: 0.5, anchorY: 0.5, x: base.x, y: base.y - 190, width: 200, height: 32 }); var baseHpBar = LK.getAsset('baseHpBar', { anchorX: 0, anchorY: 0.5, x: base.x - 100, y: base.y - 190, width: 200, height: 32 }); game.addChild(baseHpBarOutline); game.addChild(baseHpBarBg); game.addChild(baseHpBar); // (ground platform removed) // GUI // HP text removed goldTxt = new Text2("Gold: " + gold, { size: 80, fill: 0xFFD700 }); goldTxt.anchor.set(1, 0); LK.gui.topRight.addChild(goldTxt); waveTxt = new Text2("Wave: " + wave, { size: 80, fill: "#fff" }); waveTxt.anchor.set(0.5, 0); LK.gui.top.addChild(waveTxt); // Turret placement buttons (left and right) // Space out the buttons and texts at the bottom of the screen for better separation var bottomY = 2732 - 180; var leftTurretBtn = LK.getAsset('turret', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 700, y: bottomY, scaleX: 1.2, scaleY: 1.2 }); var rightTurretBtn = LK.getAsset('turret', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 700, y: bottomY, scaleX: 1.2, scaleY: 1.2 }); game.addChild(leftTurretBtn); game.addChild(rightTurretBtn); var leftTurretCostTxt = new Text2("Buy: 30", { size: 60, fill: "#fff" }); leftTurretCostTxt.anchor.set(0.5, 0); leftTurretCostTxt.x = leftTurretBtn.x; leftTurretCostTxt.y = leftTurretBtn.y + 100; game.addChild(leftTurretCostTxt); var rightTurretCostTxt = new Text2("Buy: 30", { size: 60, fill: "#fff" }); rightTurretCostTxt.anchor.set(0.5, 0); rightTurretCostTxt.x = rightTurretBtn.x; rightTurretCostTxt.y = rightTurretBtn.y + 100; game.addChild(rightTurretCostTxt); // Base repair and upgrade buttons var repairBtn = LK.getAsset('repair', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 350, y: bottomY, scaleX: 0.7, scaleY: 0.7 }); var upgradeBtn = LK.getAsset('upgrade', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 350, y: bottomY, scaleX: 0.7, scaleY: 0.7 }); game.addChild(repairBtn); game.addChild(upgradeBtn); var repairCostTxt = new Text2("Repair: 15", { size: 60, fill: "#fff" }); repairCostTxt.anchor.set(0.5, 0); repairCostTxt.x = repairBtn.x; repairCostTxt.y = repairBtn.y + 100; game.addChild(repairCostTxt); var upgradeCostTxt = new Text2("Upgrade: 40", { size: 60, fill: "#fff" }); upgradeCostTxt.anchor.set(0.5, 0); upgradeCostTxt.x = upgradeBtn.x; upgradeCostTxt.y = upgradeBtn.y + 100; game.addChild(upgradeCostTxt); // Turret upgrade buttons (appear above turrets) function showTurretUpgradeBtn(turret) { if (turret.upgradeBtn) { return; } var btn = LK.getAsset('turret', { anchorX: 0.5, anchorY: 0.5, x: turret.x, y: turret.y - 120, scaleX: 0.6, scaleY: 0.6 }); var txt = new Text2("Upgrade: 25", { size: 50, fill: "#fff" }); txt.anchor.set(0.5, 0); txt.x = btn.x; txt.y = btn.y + 50; btn._upgradeTxt = txt; game.addChild(btn); game.addChild(txt); turret.upgradeBtn = btn; turret.upgradeTxt = txt; } // Remove upgrade button function hideTurretUpgradeBtn(turret) { if (turret.upgradeBtn) { turret.upgradeBtn.destroy(); turret.upgradeTxt.destroy(); turret.upgradeBtn = null; turret.upgradeTxt = null; } } // Place initial turrets function placeTurret(side) { // Count how many turrets already exist on this side var count = 0; for (var i = 0; i < turrets.length; i++) { if (turrets[i].side === side) { count++; } } // Place the first turret at center, then alternate above/below var x = base.x + (side === 1 ? 300 : -300); var y = base.y; if (count > 0) { // Alternate above and below, spacing by 180px var offset = 180 * Math.ceil(count / 2); if (count % 2 === 1) { y = base.y - offset; // above } else { y = base.y + offset; // below } } var t = new Turret(); t.x = x; t.y = y; t.side = side; // Reverse the image for the left turret if (side === -1 && t.children && t.children.length > 0) { // Assume the first child is the turret graphics if (typeof t.children[0].scaleX !== "undefined") { t.children[0].scaleX = -1 * Math.abs(t.children[0].scaleX); } } turrets.push(t); game.addChild(t); return t; } // Initial turrets placeTurret(-1); placeTurret(1); // Handle turret placement leftTurretBtn.down = function (x, y, obj) { if (gold >= 30) { var t = placeTurret(-1); gold -= 30; goldTxt.setText("Gold: " + gold); } }; rightTurretBtn.down = function (x, y, obj) { if (gold >= 30) { var t = placeTurret(1); gold -= 30; goldTxt.setText("Gold: " + gold); } }; // Handle base repair/upgrade repairBtn.down = function (x, y, obj) { if (gold >= 15 && base.hp < base.maxHp) { base.repair(); gold -= 15; goldTxt.setText("Gold: " + gold); // HP text removed, no update needed here } }; upgradeBtn.down = function (x, y, obj) { if (gold >= 40) { base.upgrade(); gold -= 40; goldTxt.setText("Gold: " + gold); // HP text removed, no update needed here } }; // Handle turret upgrade game.down = function (x, y, obj) { // Check if a turret was tapped for (var i = 0; i < turrets.length; i++) { var t = turrets[i]; if (t && LK.util && typeof LK.util.containsPoint === "function" && LK.util.containsPoint(t, { x: x, y: y })) { selectedTurret = t; showTurretUpgradeBtn(t); return; } } // Check if upgrade button was tapped for (var i = 0; i < turrets.length; i++) { var t = turrets[i]; if (t && t.upgradeBtn && LK.util && typeof LK.util.containsPoint === "function" && LK.util.containsPoint(t.upgradeBtn, { x: x, y: y })) { if (gold >= 25 && t.level < 3) { t.upgrade(); gold -= 25; goldTxt.setText("Gold: " + gold); if (t.level >= 3) { hideTurretUpgradeBtn(t); } } return; } } // Deselect turret if tap elsewhere for (var i = 0; i < turrets.length; i++) { hideTurretUpgradeBtn(turrets[i]); } selectedTurret = null; }; // Enemy spawn logic function startWave() { waveInProgress = true; enemiesToSpawn = Math.floor(enemiesPerWave + (wave - 1) * 4.5); // more enemies per wave, longer waves enemiesSpawned = 0; spawnTimer = 0; waveTxt.setText("Wave: " + wave); } function endWave() { waveInProgress = false; nextWaveTimer = 120; // 2 seconds gold += 20 + wave * 5; goldTxt.setText("Gold: " + gold); enemiesPerWave += 4; // increase more per wave, longer waves wave += 1; } // Main update loop game.update = function () { // Update HP bar position and width baseHpBarOutline.x = base.x; baseHpBarOutline.y = base.y - 190; baseHpBarBg.x = base.x; baseHpBarBg.y = base.y - 190; // Health bar shrinks left-to-right as base takes damage var hpRatio = Math.max(0, base.hp) / base.maxHp; baseHpBar.width = 200 * hpRatio; baseHpBar.x = base.x - 100; // left edge stays fixed baseHpBar.y = base.y - 190; // Update turrets for (var i = 0; i < turrets.length; i++) { turrets[i].update(); } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Check if reached base if (e.direction === 1 && e.x >= base.x - 90 || e.direction === -1 && e.x <= base.x + 90) { base.hp -= 1; base.hit(); e.destroy(); enemies.splice(i, 1); if (base.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } continue; } // Check if dead if (e.hp <= 0) { e.destroy(); enemies.splice(i, 1); if (Math.random() < 0.4) { // 40% chance to get gold per enemy gold += 5; goldTxt.setText("Gold: " + gold); } continue; } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); if (b.destroyed) { b.destroy(); bullets.splice(i, 1); } } // Wave logic if (waveInProgress) { if (enemiesSpawned < enemiesToSpawn) { if (spawnTimer <= 0) { // Spawn enemy from left or right var side = Math.random() < 0.5 ? -1 : 1; var EnemyClass = Enemy; EnemyClass.prototype.direction = side; // Set direction before instantiation for asset selection var e = new EnemyClass(); e.direction = side; e.x = side === 1 ? 0 : 2048; e.y = base.y - 200 + Math.random() * 400; // Make enemies slower and waves harder: lower base speed, increase HP and spawn more per wave e.speed = 1.5 + wave * 0.15 + Math.random() * 0.5; // slower base, less scaling e.hp = 2 + Math.floor(wave * 1.2); // more HP per wave enemies.push(e); game.addChild(e); enemiesSpawned++; spawnTimer = 36 + Math.floor(Math.random() * 24); // slightly slower spawn rate } else { spawnTimer--; } } else if (enemies.length === 0) { endWave(); } } else { if (nextWaveTimer > 0) { nextWaveTimer--; if (nextWaveTimer === 0) { startWave(); } } } }; // Start first wave startWave();
===================================================================
--- original.js
+++ change.js
@@ -40,13 +40,13 @@
var Bullet = Container.expand(function () {
var self = Container.call(this);
// Attach bullet asset (box, yellow)
var bulletGraphics = self.attachAsset('bullet', {
- anchorX: 0.5,
- anchorY: 0.5
+ anchorX: -2,
+ anchorY: 2
});
- bulletGraphics.width = 40;
- bulletGraphics.height = 40;
+ bulletGraphics.width = 20;
+ bulletGraphics.height = 20;
bulletGraphics.color = 0xb8b031;
self.speed = 24;
self.target = null;
self.side = 1;
@@ -75,20 +75,14 @@
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Attach enemy asset (ellipse, red)
- var enemyGraphics = self.attachAsset('enemy', {
+ // Use separate images for left- and right-spawned enemies
+ var assetId = self.direction === -1 ? 'enemyLeft' : 'enemyRight';
+ var enemyGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
- // Reverse the image ONLY for left-spawned enemies
- if (typeof enemyGraphics.scaleX !== "undefined") {
- if (self.direction === -1) {
- enemyGraphics.scaleX = -1 * Math.abs(enemyGraphics.scaleX); // Reverse for left-spawned
- } else {
- enemyGraphics.scaleX = Math.abs(enemyGraphics.scaleX); // Normal for right-spawned
- }
- }
// Set size and color
enemyGraphics.width = 90;
enemyGraphics.height = 90;
enemyGraphics.color = 0xd83318;
@@ -545,9 +539,11 @@
if (enemiesSpawned < enemiesToSpawn) {
if (spawnTimer <= 0) {
// Spawn enemy from left or right
var side = Math.random() < 0.5 ? -1 : 1;
- var e = new Enemy();
+ var EnemyClass = Enemy;
+ EnemyClass.prototype.direction = side; // Set direction before instantiation for asset selection
+ var e = new EnemyClass();
e.direction = side;
e.x = side === 1 ? 0 : 2048;
e.y = base.y - 200 + Math.random() * 400;
// Make enemies slower and waves harder: lower base speed, increase HP and spawn more per wave
2d turret. In-Game asset. 2d. High contrast. No shadows
a 2d turret base. In-Game asset. 2d. High contrast. No shadows
a 2d upgrade button png. In-Game asset. 2d. High contrast. No shadows
purple zombie 2d. In-Game asset. 2d. High contrast. No shadows
add a grass background, empty middle, grass and trees around. In-Game asset. 2d. High contrast. No shadows