User prompt
gold should be automatically transferred to our account. A new soldier can be bought with every 10 gold.
User prompt
Add zoom in and zoom out.
User prompt
Gold should be collectable. And we can buy new soldiers with each 5 gold. Slow down bullets by 50%.
User prompt
make the gate in the middle of the towers
User prompt
Decrease zombies spead. Gate shouldbe middle of castle
Code edit (1 edits merged)
Please save this source code
User prompt
Last Gate: Castle Defense
Initial prompt
Game Prompt Title: “Last Gate: Castle Defense” Prompt: You have one castle. Watchtowers stand on its walls. Every 3 seconds, waves of zombies approach from all directions. Your soldiers on the towers fight them off automatically. Each defeated zombie drops gold. Use the gold to recruit new soldiers and upgrade existing ones. Your goal: protect the castle gate at all costs.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet fired by soldiers var Bullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 32; self.target = null; // Zombie instance self.damage = 1; self.update = function () { if (!self.target || self.target.isDead) { self.destroy(); return; } // Move towards target var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 32) { // Hit! self.target.takeDamage(self.damage); self.destroy(); return; } var step = self.speed; self.x += dx / dist * step; self.y += dy / dist * step; }; return self; }); // Gold coin dropped by zombies var Gold = Container.expand(function () { var self = Container.call(this); var goldAsset = self.attachAsset('gold', { anchorX: 0.5, anchorY: 0.5 }); self.value = 1; self.life = 180; // 3 seconds self.update = function () { self.life--; if (self.life <= 0) { self.destroy(); } }; return self; }); // Soldier on a watchtower var Soldier = Container.expand(function () { var self = Container.call(this); var soldierAsset = self.attachAsset('soldier', { anchorX: 0.5, anchorY: 0.5 }); self.level = 1; self.fireRate = 60; // frames between shots self.fireTimer = 0; self.range = 600; self.upgradeCost = 5; self.parentTower = null; self.update = function () { if (!self.parentTower) return; self.fireTimer--; if (self.fireTimer <= 0) { // Find nearest zombie in range var nearest = null; var minDist = self.range; for (var i = 0; i < zombies.length; i++) { var z = zombies[i]; if (z.isDead) continue; var dx = z.x - self.x; var dy = z.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minDist) { minDist = dist; nearest = z; } } if (nearest) { // Fire! var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = nearest; bullet.damage = self.level; bullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); self.fireTimer = Math.max(20, self.fireRate - self.level * 8); } } }; self.upgrade = function () { self.level++; self.fireRate = Math.max(20, self.fireRate - 8); self.upgradeCost += 5; // Animate upgrade tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120 }); } }); }; return self; }); // Watchtower (can have a soldier) var Watchtower = Container.expand(function () { var self = Container.call(this); var towerAsset = self.attachAsset('watchtower', { anchorX: 0.5, anchorY: 1 }); self.soldier = null; self.index = 0; // For tap detection self.down = function (x, y, obj) { if (!self.soldier) { // Recruit soldier if (game.gold >= 5) { game.gold -= 5; var s = new Soldier(); s.x = self.x; s.y = self.y - 80; s.parentTower = self; self.soldier = s; soldiers.push(s); game.addChild(s); updateGoldText(); // Animate tween(s, { alpha: 0 }, { duration: 0, onFinish: function onFinish() { tween(s, { alpha: 1 }, { duration: 200 }); } }); } } else { // Upgrade soldier if (game.gold >= self.soldier.upgradeCost) { game.gold -= self.soldier.upgradeCost; self.soldier.upgrade(); updateGoldText(); } } }; return self; }); // Zombie enemy var Zombie = Container.expand(function () { var self = Container.call(this); var zombieAsset = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.maxHp = 2; self.hp = self.maxHp; self.speed = 2 + Math.random() * 1.5; self.isDead = false; self.targetX = 0; self.targetY = 0; self.takeDamage = function (dmg) { if (self.isDead) return; self.hp -= dmg; if (self.hp <= 0) { self.die(); } else { // Flash red tween(self, { tint: 0xFF0000 }, { duration: 80, onFinish: function onFinish() { tween(self, { tint: 0x4CAF50 }, { duration: 120 }); } }); } }; self.die = function () { if (self.isDead) return; self.isDead = true; LK.getSound('zombieDie').play(); // Drop gold var gold = new Gold(); gold.x = self.x; gold.y = self.y; golds.push(gold); game.addChild(gold); // Animate fade out tween(self, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); } }); }; self.update = function () { if (self.isDead) return; var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 30) { // Reached gate self.isDead = true; self.destroy(); // Damage gate game.gateHp--; LK.effects.flashObject(game.castleGate, 0xFF0000, 400); if (game.gateHp <= 0) { LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } return; } var step = self.speed; self.x += dx / dist * step; self.y += dy / dist * step; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222233 }); /**** * Game Code ****/ // Music // Sound for zombie death // Sound for collecting gold // Sound for shooting // Gold coin // Bullet // Zombie // Soldier // Watchtower base // Castle gate (center bottom) // Play music LK.playMusic('castleTheme'); // Game variables var zombies = []; var bullets = []; var golds = []; var soldiers = []; var towers = []; game.gateHp = 5; game.gold = 10; game.wave = 1; game.waveTimer = 0; // Castle gate game.castleGate = LK.getAsset('castleGate', { anchorX: 0.5, anchorY: 1, x: 1024, y: 2732 - 40 }); game.addChild(game.castleGate); // Watchtower positions (left, center, right, top-left, top-right) var towerPositions = [{ x: 400, y: 1800 }, { x: 1024, y: 1700 }, { x: 1648, y: 1800 }, { x: 700, y: 1200 }, { x: 1348, y: 1200 }]; for (var i = 0; i < towerPositions.length; i++) { var pos = towerPositions[i]; var tower = new Watchtower(); tower.x = pos.x; tower.y = pos.y; tower.index = i; towers.push(tower); game.addChild(tower); } // GUI: Gold display var goldTxt = new Text2('Gold: 10', { size: 90, fill: 0xFFD700 }); goldTxt.anchor.set(0.5, 0); LK.gui.top.addChild(goldTxt); // GUI: Gate HP display var hpTxt = new Text2('Gate: 5', { size: 90, fill: 0xFFFFFF }); hpTxt.anchor.set(0.5, 0); LK.gui.topRight.addChild(hpTxt); // GUI: Wave display var waveTxt = new Text2('Wave: 1', { size: 80, fill: 0x00BFFF }); waveTxt.anchor.set(0.5, 0); LK.gui.bottom.addChild(waveTxt); function updateGoldText() { goldTxt.setText('Gold: ' + game.gold); } function updateHpText() { hpTxt.setText('Gate: ' + game.gateHp); } function updateWaveText() { waveTxt.setText('Wave: ' + game.wave); } // Handle collecting gold game.down = function (x, y, obj) { // Check if gold was tapped for (var i = golds.length - 1; i >= 0; i--) { var g = golds[i]; var dx = g.x - x; var dy = g.y - y; if (dx * dx + dy * dy < 900) { // Collect LK.getSound('coin').play(); game.gold += g.value; updateGoldText(); g.destroy(); golds.splice(i, 1); return; } } // Check if a tower was tapped for (var j = 0; j < towers.length; j++) { var t = towers[j]; var tx = t.x, ty = t.y; if (x > tx - 60 && x < tx + 60 && y > ty - 220 && y < ty) { t.down(x, y, obj); return; } } }; // Main update loop game.update = function () { // Update gate HP and gold updateHpText(); // Update all zombies for (var i = zombies.length - 1; i >= 0; i--) { var z = zombies[i]; z.update(); if (z.isDead && z.alpha === 0) { z.destroy(); zombies.splice(i, 1); } } // Update all bullets for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); if (b.destroyed) { bullets.splice(i, 1); } } // Update all golds for (var i = golds.length - 1; i >= 0; i--) { var g = golds[i]; g.update(); if (g.life <= 0 || g.destroyed) { g.destroy(); golds.splice(i, 1); } } // Update all soldiers for (var i = 0; i < soldiers.length; i++) { soldiers[i].update(); } // Spawn new wave every 180 ticks (3 seconds) game.waveTimer++; if (game.waveTimer >= 180) { game.waveTimer = 0; spawnWave(); } }; function spawnWave() { var n = 2 + Math.floor(game.wave * 0.7); for (var i = 0; i < n; i++) { var z = new Zombie(); // Spawn from random edge var edge = Math.floor(Math.random() * 4); var zx, zy; if (edge === 0) { // left zx = -60; zy = 1000 + Math.random() * 1200; } else if (edge === 1) { // right zx = 2048 + 60; zy = 1000 + Math.random() * 1200; } else if (edge === 2) { // top zx = 400 + Math.random() * 1200; zy = -80; } else { // bottom (rare) zx = 400 + Math.random() * 1200; zy = 2732 + 80; } z.x = zx; z.y = zy; z.targetX = 1024; z.targetY = 2732 - 100; // Increase HP and speed with wave z.maxHp = 2 + Math.floor(game.wave / 2); z.hp = z.maxHp; z.speed = 2 + Math.random() * 1.5 + game.wave * 0.15; zombies.push(z); game.addChild(z); } game.wave++; updateWaveText(); }
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,453 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Bullet fired by soldiers
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletAsset = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 32;
+ self.target = null; // Zombie instance
+ self.damage = 1;
+ self.update = function () {
+ if (!self.target || self.target.isDead) {
+ self.destroy();
+ return;
+ }
+ // Move towards target
+ var dx = self.target.x - self.x;
+ var dy = self.target.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 32) {
+ // Hit!
+ self.target.takeDamage(self.damage);
+ self.destroy();
+ return;
+ }
+ var step = self.speed;
+ self.x += dx / dist * step;
+ self.y += dy / dist * step;
+ };
+ return self;
+});
+// Gold coin dropped by zombies
+var Gold = Container.expand(function () {
+ var self = Container.call(this);
+ var goldAsset = self.attachAsset('gold', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.value = 1;
+ self.life = 180; // 3 seconds
+ self.update = function () {
+ self.life--;
+ if (self.life <= 0) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+// Soldier on a watchtower
+var Soldier = Container.expand(function () {
+ var self = Container.call(this);
+ var soldierAsset = self.attachAsset('soldier', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.level = 1;
+ self.fireRate = 60; // frames between shots
+ self.fireTimer = 0;
+ self.range = 600;
+ self.upgradeCost = 5;
+ self.parentTower = null;
+ self.update = function () {
+ if (!self.parentTower) return;
+ self.fireTimer--;
+ if (self.fireTimer <= 0) {
+ // Find nearest zombie in range
+ var nearest = null;
+ var minDist = self.range;
+ for (var i = 0; i < zombies.length; i++) {
+ var z = zombies[i];
+ if (z.isDead) continue;
+ var dx = z.x - self.x;
+ var dy = z.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < minDist) {
+ minDist = dist;
+ nearest = z;
+ }
+ }
+ if (nearest) {
+ // Fire!
+ var bullet = new Bullet();
+ bullet.x = self.x;
+ bullet.y = self.y;
+ bullet.target = nearest;
+ bullet.damage = self.level;
+ bullets.push(bullet);
+ game.addChild(bullet);
+ LK.getSound('shoot').play();
+ self.fireTimer = Math.max(20, self.fireRate - self.level * 8);
+ }
+ }
+ };
+ self.upgrade = function () {
+ self.level++;
+ self.fireRate = Math.max(20, self.fireRate - 8);
+ self.upgradeCost += 5;
+ // Animate upgrade
+ tween(self, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 120,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 120
+ });
+ }
+ });
+ };
+ return self;
+});
+// Watchtower (can have a soldier)
+var Watchtower = Container.expand(function () {
+ var self = Container.call(this);
+ var towerAsset = self.attachAsset('watchtower', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ self.soldier = null;
+ self.index = 0;
+ // For tap detection
+ self.down = function (x, y, obj) {
+ if (!self.soldier) {
+ // Recruit soldier
+ if (game.gold >= 5) {
+ game.gold -= 5;
+ var s = new Soldier();
+ s.x = self.x;
+ s.y = self.y - 80;
+ s.parentTower = self;
+ self.soldier = s;
+ soldiers.push(s);
+ game.addChild(s);
+ updateGoldText();
+ // Animate
+ tween(s, {
+ alpha: 0
+ }, {
+ duration: 0,
+ onFinish: function onFinish() {
+ tween(s, {
+ alpha: 1
+ }, {
+ duration: 200
+ });
+ }
+ });
+ }
+ } else {
+ // Upgrade soldier
+ if (game.gold >= self.soldier.upgradeCost) {
+ game.gold -= self.soldier.upgradeCost;
+ self.soldier.upgrade();
+ updateGoldText();
+ }
+ }
+ };
+ return self;
+});
+// Zombie enemy
+var Zombie = Container.expand(function () {
+ var self = Container.call(this);
+ var zombieAsset = self.attachAsset('zombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.maxHp = 2;
+ self.hp = self.maxHp;
+ self.speed = 2 + Math.random() * 1.5;
+ self.isDead = false;
+ self.targetX = 0;
+ self.targetY = 0;
+ self.takeDamage = function (dmg) {
+ if (self.isDead) return;
+ self.hp -= dmg;
+ if (self.hp <= 0) {
+ self.die();
+ } else {
+ // Flash red
+ tween(self, {
+ tint: 0xFF0000
+ }, {
+ duration: 80,
+ onFinish: function onFinish() {
+ tween(self, {
+ tint: 0x4CAF50
+ }, {
+ duration: 120
+ });
+ }
+ });
+ }
+ };
+ self.die = function () {
+ if (self.isDead) return;
+ self.isDead = true;
+ LK.getSound('zombieDie').play();
+ // Drop gold
+ var gold = new Gold();
+ gold.x = self.x;
+ gold.y = self.y;
+ golds.push(gold);
+ game.addChild(gold);
+ // Animate fade out
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ };
+ self.update = function () {
+ if (self.isDead) return;
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 30) {
+ // Reached gate
+ self.isDead = true;
+ self.destroy();
+ // Damage gate
+ game.gateHp--;
+ LK.effects.flashObject(game.castleGate, 0xFF0000, 400);
+ if (game.gateHp <= 0) {
+ LK.effects.flashScreen(0xFF0000, 1000);
+ LK.showGameOver();
+ }
+ return;
+ }
+ var step = self.speed;
+ self.x += dx / dist * step;
+ self.y += dy / dist * step;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222233
+});
+
+/****
+* Game Code
+****/
+// Music
+// Sound for zombie death
+// Sound for collecting gold
+// Sound for shooting
+// Gold coin
+// Bullet
+// Zombie
+// Soldier
+// Watchtower base
+// Castle gate (center bottom)
+// Play music
+LK.playMusic('castleTheme');
+// Game variables
+var zombies = [];
+var bullets = [];
+var golds = [];
+var soldiers = [];
+var towers = [];
+game.gateHp = 5;
+game.gold = 10;
+game.wave = 1;
+game.waveTimer = 0;
+// Castle gate
+game.castleGate = LK.getAsset('castleGate', {
+ anchorX: 0.5,
+ anchorY: 1,
+ x: 1024,
+ y: 2732 - 40
+});
+game.addChild(game.castleGate);
+// Watchtower positions (left, center, right, top-left, top-right)
+var towerPositions = [{
+ x: 400,
+ y: 1800
+}, {
+ x: 1024,
+ y: 1700
+}, {
+ x: 1648,
+ y: 1800
+}, {
+ x: 700,
+ y: 1200
+}, {
+ x: 1348,
+ y: 1200
+}];
+for (var i = 0; i < towerPositions.length; i++) {
+ var pos = towerPositions[i];
+ var tower = new Watchtower();
+ tower.x = pos.x;
+ tower.y = pos.y;
+ tower.index = i;
+ towers.push(tower);
+ game.addChild(tower);
+}
+// GUI: Gold display
+var goldTxt = new Text2('Gold: 10', {
+ size: 90,
+ fill: 0xFFD700
+});
+goldTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(goldTxt);
+// GUI: Gate HP display
+var hpTxt = new Text2('Gate: 5', {
+ size: 90,
+ fill: 0xFFFFFF
+});
+hpTxt.anchor.set(0.5, 0);
+LK.gui.topRight.addChild(hpTxt);
+// GUI: Wave display
+var waveTxt = new Text2('Wave: 1', {
+ size: 80,
+ fill: 0x00BFFF
+});
+waveTxt.anchor.set(0.5, 0);
+LK.gui.bottom.addChild(waveTxt);
+function updateGoldText() {
+ goldTxt.setText('Gold: ' + game.gold);
+}
+function updateHpText() {
+ hpTxt.setText('Gate: ' + game.gateHp);
+}
+function updateWaveText() {
+ waveTxt.setText('Wave: ' + game.wave);
+}
+// Handle collecting gold
+game.down = function (x, y, obj) {
+ // Check if gold was tapped
+ for (var i = golds.length - 1; i >= 0; i--) {
+ var g = golds[i];
+ var dx = g.x - x;
+ var dy = g.y - y;
+ if (dx * dx + dy * dy < 900) {
+ // Collect
+ LK.getSound('coin').play();
+ game.gold += g.value;
+ updateGoldText();
+ g.destroy();
+ golds.splice(i, 1);
+ return;
+ }
+ }
+ // Check if a tower was tapped
+ for (var j = 0; j < towers.length; j++) {
+ var t = towers[j];
+ var tx = t.x,
+ ty = t.y;
+ if (x > tx - 60 && x < tx + 60 && y > ty - 220 && y < ty) {
+ t.down(x, y, obj);
+ return;
+ }
+ }
+};
+// Main update loop
+game.update = function () {
+ // Update gate HP and gold
+ updateHpText();
+ // Update all zombies
+ for (var i = zombies.length - 1; i >= 0; i--) {
+ var z = zombies[i];
+ z.update();
+ if (z.isDead && z.alpha === 0) {
+ z.destroy();
+ zombies.splice(i, 1);
+ }
+ }
+ // Update all bullets
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var b = bullets[i];
+ b.update();
+ if (b.destroyed) {
+ bullets.splice(i, 1);
+ }
+ }
+ // Update all golds
+ for (var i = golds.length - 1; i >= 0; i--) {
+ var g = golds[i];
+ g.update();
+ if (g.life <= 0 || g.destroyed) {
+ g.destroy();
+ golds.splice(i, 1);
+ }
+ }
+ // Update all soldiers
+ for (var i = 0; i < soldiers.length; i++) {
+ soldiers[i].update();
+ }
+ // Spawn new wave every 180 ticks (3 seconds)
+ game.waveTimer++;
+ if (game.waveTimer >= 180) {
+ game.waveTimer = 0;
+ spawnWave();
+ }
+};
+function spawnWave() {
+ var n = 2 + Math.floor(game.wave * 0.7);
+ for (var i = 0; i < n; i++) {
+ var z = new Zombie();
+ // Spawn from random edge
+ var edge = Math.floor(Math.random() * 4);
+ var zx, zy;
+ if (edge === 0) {
+ // left
+ zx = -60;
+ zy = 1000 + Math.random() * 1200;
+ } else if (edge === 1) {
+ // right
+ zx = 2048 + 60;
+ zy = 1000 + Math.random() * 1200;
+ } else if (edge === 2) {
+ // top
+ zx = 400 + Math.random() * 1200;
+ zy = -80;
+ } else {
+ // bottom (rare)
+ zx = 400 + Math.random() * 1200;
+ zy = 2732 + 80;
+ }
+ z.x = zx;
+ z.y = zy;
+ z.targetX = 1024;
+ z.targetY = 2732 - 100;
+ // Increase HP and speed with wave
+ z.maxHp = 2 + Math.floor(game.wave / 2);
+ z.hp = z.maxHp;
+ z.speed = 2 + Math.random() * 1.5 + game.wave * 0.15;
+ zombies.push(z);
+ game.addChild(z);
+ }
+ game.wave++;
+ updateWaveText();
+}
\ No newline at end of file
Green zombie. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Gold coin with dollar icon. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Arrow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Add fingers to left hand. Make the bow and arrow wooden color.
Make it a rectangle.
Castle wall. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Smurf home. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
zombie with fire in hand. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat