User prompt
make the background changeable in the assets section
User prompt
can we make the background a dungeon background... skulls, prisoners inside the dungeon, cobwebs, etc.
User prompt
I want to change my background
User prompt
Please fix the bug: 'areaBtn is not defined' in or related to this line: 'areaBtn.down = function (x, y, obj) {' Line Number: 504
User prompt
I will remove the Area, Shield and Trap writings above and add small icons below, when we use it, the icons will darken and gradually lighten and load and be ready to use again.
User prompt
let the other characters come at us one by one, one by one, one by one.
User prompt
remove the round center in the middle, add a life bar to the boss and make the other characters come one by one, but every time the other characters develop, they get a little stronger. Finally, provide computer control of this game, so we can play both on the computer and on the phone.
Code edit (1 edits merged)
Please save this source code
User prompt
Boss Master: Final Stand
Initial prompt
Make me a game where we manage a final boss and destroy the incoming character with our special abilities
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // AreaAttack class (visual only, handles hit in game code) var AreaAttack = Container.expand(function () { var self = Container.call(this); var areaGfx = self.attachAsset('areaAttack', { anchorX: 0.5, anchorY: 0.5 }); areaGfx.alpha = 0.4; self.update = function () {}; return self; }); // Boss class (player) var Boss = Container.expand(function () { var self = Container.call(this); var bossGfx = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bossGfx.width * 0.5; self.cooldowns = { area: 0, shield: 0, trap: 0 }; self.shieldActive = false; self.shieldTimer = 0; self.update = function () { // Cooldown timers if (self.cooldowns.area > 0) self.cooldowns.area--; if (self.cooldowns.shield > 0) self.cooldowns.shield--; if (self.cooldowns.trap > 0) self.cooldowns.trap--; if (self.shieldActive) { self.shieldTimer--; if (self.shieldTimer <= 0) { self.shieldActive = false; if (self.shieldObj) { self.shieldObj.destroy(); self.shieldObj = null; } } } }; return self; }); // Hero class (basic, blue, straight movement) var Hero = Container.expand(function () { var self = Container.call(this); var heroGfx = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6 + Math.random() * 2; self.hp = 1; self.type = 1; self.update = function () { // Move toward core var dx = core.x - self.x; var dy = core.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Hero2 class (green, zigzag movement) var Hero2 = Container.expand(function () { var self = Container.call(this); var heroGfx = self.attachAsset('hero2', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5 + Math.random() * 2; self.hp = 2; self.type = 2; self.zigzagAngle = Math.random() * Math.PI * 2; self.update = function () { // Zigzag toward core var dx = core.x - self.x; var dy = core.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var angle = Math.atan2(dy, dx); // Add zigzag self.zigzagAngle += 0.15; var zigzag = Math.sin(self.zigzagAngle) * 0.5; angle += zigzag; self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; } }; return self; }); // Hero3 class (red, fast, pauses randomly) var Hero3 = Container.expand(function () { var self = Container.call(this); var heroGfx = self.attachAsset('hero3', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8 + Math.random() * 2; self.hp = 1; self.type = 3; self.pauseTimer = 0; self.update = function () { if (self.pauseTimer > 0) { self.pauseTimer--; return; } // Randomly pause if (Math.random() < 0.01) { self.pauseTimer = 30 + Math.floor(Math.random() * 30); return; } // Move toward core var dx = core.x - self.x; var dy = core.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Shield class (visual only) var Shield = Container.expand(function () { var self = Container.call(this); var shieldGfx = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5 }); shieldGfx.alpha = 0.25; self.update = function () {}; return self; }); // Trap class (placed by boss, destroys hero on contact) var Trap = Container.expand(function () { var self = Container.call(this); var trapGfx = self.attachAsset('trap', { anchorX: 0.5, anchorY: 0.5 }); self.timer = 240; // 4 seconds self.update = function () { self.timer--; if (self.timer <= 0) { self.destroy(); for (var i = 0; i < traps.length; ++i) { if (traps[i] === self) { traps.splice(i, 1); break; } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x18181b }); /**** * Game Code ****/ // Sound for area attack // Trap asset: small ellipse, dark gray // Shield asset: large semi-transparent ellipse, cyan // Area attack asset: large semi-transparent ellipse, orange // Hero3 asset: rectangle, red (for variety) // Hero2 asset: rectangle, green (for variety) // Hero asset: rectangle, blue // Core asset: smaller ellipse, gold // Boss (player) asset: large ellipse, purple // Center positions var centerX = 2048 / 2; var centerY = 2732 / 2; // Core (defense point) var core = LK.getAsset('core', { anchorX: 0.5, anchorY: 0.5 }); core.x = centerX; core.y = centerY + 500; game.addChild(core); // Boss (player) var boss = new Boss(); boss.x = centerX; boss.y = centerY + 900; game.addChild(boss); // Score display var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Ability cooldown display (simple text) var abilityTxt = new Text2('', { size: 60, fill: "#fff" }); abilityTxt.anchor.set(0.5, 0); LK.gui.top.addChild(abilityTxt); abilityTxt.y = 130; // Arrays for game objects var heroes = []; var traps = []; var areaAttacks = []; // Dragging boss var dragNode = null; // Ability state var abilityMode = null; // null, 'area', 'shield', 'trap' var areaAttackObj = null; // Ability cooldowns (frames) var AREA_COOLDOWN = 360; // 6s var SHIELD_COOLDOWN = 540; // 9s var TRAP_COOLDOWN = 180; // 3s // Ability durations var SHIELD_DURATION = 180; // 3s // Area attack radius var AREA_RADIUS = 300; // Shield radius var SHIELD_RADIUS = 200; // Trap radius var TRAP_RADIUS = 60; // Touch UI: Ability buttons (simple text buttons) var areaBtn = new Text2('Area', { size: 80, fill: 0xFF9800 }); areaBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(areaBtn); areaBtn.x = -400; areaBtn.y = -100; var shieldBtn = new Text2('Shield', { size: 80, fill: 0x00E5FF }); shieldBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(shieldBtn); shieldBtn.x = 0; shieldBtn.y = -100; var trapBtn = new Text2('Trap', { size: 80, fill: 0xBDBDBD }); trapBtn.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(trapBtn); trapBtn.x = 400; trapBtn.y = -100; // Helper: check if two objects intersect (circle-based) function circlesIntersect(a, rA, b, rB) { var dx = a.x - b.x; var dy = a.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); return dist < rA + rB; } // Helper: spawn a hero at random edge function spawnHero() { var edge = Math.floor(Math.random() * 4); var x, y; if (edge === 0) { // Top x = 200 + Math.random() * (2048 - 400); y = -100; } else if (edge === 1) { // Bottom x = 200 + Math.random() * (2048 - 400); y = 2732 + 100; } else if (edge === 2) { // Left x = -100; y = 400 + Math.random() * (2732 - 800); } else { // Right x = 2048 + 100; y = 400 + Math.random() * (2732 - 800); } // Random hero type var t = Math.random(); var hero; if (t < 0.5) { hero = new Hero(); } else if (t < 0.8) { hero = new Hero2(); } else { hero = new Hero3(); } hero.x = x; hero.y = y; hero.lastIntersectingCore = false; hero.lastIntersectingBoss = false; hero.lastIntersectingTrap = false; heroes.push(hero); game.addChild(hero); } // Ability: Area attack function useAreaAttack() { if (boss.cooldowns.area > 0) return; boss.cooldowns.area = AREA_COOLDOWN; // Visual areaAttackObj = new AreaAttack(); areaAttackObj.x = boss.x; areaAttackObj.y = boss.y; areaAttackObj.scaleX = 0.1; areaAttackObj.scaleY = 0.1; areaAttackObj.alpha = 0.5; game.addChild(areaAttackObj); areaAttacks.push(areaAttackObj); // Animate tween(areaAttackObj, { scaleX: 1, scaleY: 1, alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { if (areaAttackObj) { areaAttackObj.destroy(); var idx = areaAttacks.indexOf(areaAttackObj); if (idx !== -1) areaAttacks.splice(idx, 1); areaAttackObj = null; } } }); // Hit all heroes in radius for (var i = heroes.length - 1; i >= 0; --i) { var h = heroes[i]; if (circlesIntersect(boss, AREA_RADIUS, h, 60)) { h.hp -= 1; LK.getSound('area').play(); LK.effects.flashObject(h, 0xff9800, 300); if (h.hp <= 0) { LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); LK.getSound('heroHit').play(); h.destroy(); heroes.splice(i, 1); } } } } // Ability: Shield function useShield() { if (boss.cooldowns.shield > 0) return; boss.cooldowns.shield = SHIELD_COOLDOWN; boss.shieldActive = true; boss.shieldTimer = SHIELD_DURATION; if (boss.shieldObj) boss.shieldObj.destroy(); boss.shieldObj = new Shield(); boss.shieldObj.x = boss.x; boss.shieldObj.y = boss.y; game.addChild(boss.shieldObj); LK.getSound('shield').play(); } // Ability: Trap function useTrap() { if (boss.cooldowns.trap > 0) return; boss.cooldowns.trap = TRAP_COOLDOWN; // Place trap at boss position var trap = new Trap(); trap.x = boss.x; trap.y = boss.y; traps.push(trap); game.addChild(trap); LK.getSound('trap').play(); } // Ability button handlers areaBtn.down = function (x, y, obj) { useAreaAttack(); }; shieldBtn.down = function (x, y, obj) { useShield(); }; trapBtn.down = function (x, y, obj) { useTrap(); }; // Dragging boss function handleMove(x, y, obj) { if (dragNode) { // Clamp boss inside game area var minX = boss.radius + 40; var maxX = 2048 - boss.radius - 40; var minY = boss.radius + 200; var maxY = 2732 - boss.radius - 40; boss.x = Math.max(minX, Math.min(maxX, x)); boss.y = Math.max(minY, Math.min(maxY, y)); if (boss.shieldObj) { boss.shieldObj.x = boss.x; boss.shieldObj.y = boss.y; } } } game.move = handleMove; game.down = function (x, y, obj) { // Only drag if touch is on boss var dx = x - boss.x; var dy = y - boss.y; if (dx * dx + dy * dy < boss.radius * boss.radius) { dragNode = boss; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { dragNode = null; }; // Main game update game.update = function () { // Update boss boss.update(); // Update ability cooldown text var areaCd = boss.cooldowns.area > 0 ? Math.ceil(boss.cooldowns.area / 60) + 's' : 'Ready'; var shieldCd = boss.cooldowns.shield > 0 ? Math.ceil(boss.cooldowns.shield / 60) + 's' : 'Ready'; var trapCd = boss.cooldowns.trap > 0 ? Math.ceil(boss.cooldowns.trap / 60) + 's' : 'Ready'; abilityTxt.setText('Area: ' + areaCd + ' Shield: ' + shieldCd + ' Trap: ' + trapCd); // Update heroes for (var i = heroes.length - 1; i >= 0; --i) { var h = heroes[i]; h.update(); // Check collision with shield if (boss.shieldActive && boss.shieldObj && circlesIntersect(boss, SHIELD_RADIUS, h, 60)) { // Repel hero var dx = h.x - boss.x; var dy = h.y - boss.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { h.x += dx / dist * 40; h.y += dy / dist * 40; } LK.effects.flashObject(h, 0x00e5ff, 200); } // Check collision with traps for (var t = traps.length - 1; t >= 0; --t) { var trap = traps[t]; if (circlesIntersect(h, 60, trap, TRAP_RADIUS)) { LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); LK.getSound('heroHit').play(); h.destroy(); heroes.splice(i, 1); trap.destroy(); traps.splice(t, 1); break; } } // Check collision with core var nowIntersectingCore = circlesIntersect(h, 60, core, 80); if (!h.lastIntersectingCore && nowIntersectingCore) { // Game over LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } h.lastIntersectingCore = nowIntersectingCore; } // Update traps for (var i = traps.length - 1; i >= 0; --i) { traps[i].update(); } // Remove area attack visuals if needed for (var i = areaAttacks.length - 1; i >= 0; --i) { // No update needed, handled by tween } // Spawn heroes if (LK.ticks % 45 === 0) { spawnHero(); } // Win condition: survive 60 heroes if (LK.getScore() >= 60) { LK.showYouWin(); } };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,487 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// AreaAttack class (visual only, handles hit in game code)
+var AreaAttack = Container.expand(function () {
+ var self = Container.call(this);
+ var areaGfx = self.attachAsset('areaAttack', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ areaGfx.alpha = 0.4;
+ self.update = function () {};
+ return self;
+});
+// Boss class (player)
+var Boss = Container.expand(function () {
+ var self = Container.call(this);
+ var bossGfx = self.attachAsset('boss', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = bossGfx.width * 0.5;
+ self.cooldowns = {
+ area: 0,
+ shield: 0,
+ trap: 0
+ };
+ self.shieldActive = false;
+ self.shieldTimer = 0;
+ self.update = function () {
+ // Cooldown timers
+ if (self.cooldowns.area > 0) self.cooldowns.area--;
+ if (self.cooldowns.shield > 0) self.cooldowns.shield--;
+ if (self.cooldowns.trap > 0) self.cooldowns.trap--;
+ if (self.shieldActive) {
+ self.shieldTimer--;
+ if (self.shieldTimer <= 0) {
+ self.shieldActive = false;
+ if (self.shieldObj) {
+ self.shieldObj.destroy();
+ self.shieldObj = null;
+ }
+ }
+ }
+ };
+ return self;
+});
+// Hero class (basic, blue, straight movement)
+var Hero = Container.expand(function () {
+ var self = Container.call(this);
+ var heroGfx = self.attachAsset('hero', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 6 + Math.random() * 2;
+ self.hp = 1;
+ self.type = 1;
+ self.update = function () {
+ // Move toward core
+ var dx = core.x - self.x;
+ var dy = core.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ }
+ };
+ return self;
+});
+// Hero2 class (green, zigzag movement)
+var Hero2 = Container.expand(function () {
+ var self = Container.call(this);
+ var heroGfx = self.attachAsset('hero2', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 5 + Math.random() * 2;
+ self.hp = 2;
+ self.type = 2;
+ self.zigzagAngle = Math.random() * Math.PI * 2;
+ self.update = function () {
+ // Zigzag toward core
+ var dx = core.x - self.x;
+ var dy = core.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ var angle = Math.atan2(dy, dx);
+ // Add zigzag
+ self.zigzagAngle += 0.15;
+ var zigzag = Math.sin(self.zigzagAngle) * 0.5;
+ angle += zigzag;
+ self.x += Math.cos(angle) * self.speed;
+ self.y += Math.sin(angle) * self.speed;
+ }
+ };
+ return self;
+});
+// Hero3 class (red, fast, pauses randomly)
+var Hero3 = Container.expand(function () {
+ var self = Container.call(this);
+ var heroGfx = self.attachAsset('hero3', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 8 + Math.random() * 2;
+ self.hp = 1;
+ self.type = 3;
+ self.pauseTimer = 0;
+ self.update = function () {
+ if (self.pauseTimer > 0) {
+ self.pauseTimer--;
+ return;
+ }
+ // Randomly pause
+ if (Math.random() < 0.01) {
+ self.pauseTimer = 30 + Math.floor(Math.random() * 30);
+ return;
+ }
+ // Move toward core
+ var dx = core.x - self.x;
+ var dy = core.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ }
+ };
+ return self;
+});
+// Shield class (visual only)
+var Shield = Container.expand(function () {
+ var self = Container.call(this);
+ var shieldGfx = self.attachAsset('shield', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ shieldGfx.alpha = 0.25;
+ self.update = function () {};
+ return self;
+});
+// Trap class (placed by boss, destroys hero on contact)
+var Trap = Container.expand(function () {
+ var self = Container.call(this);
+ var trapGfx = self.attachAsset('trap', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.timer = 240; // 4 seconds
+ self.update = function () {
+ self.timer--;
+ if (self.timer <= 0) {
+ self.destroy();
+ for (var i = 0; i < traps.length; ++i) {
+ if (traps[i] === self) {
+ traps.splice(i, 1);
+ break;
+ }
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x18181b
+});
+
+/****
+* Game Code
+****/
+// Sound for area attack
+// Trap asset: small ellipse, dark gray
+// Shield asset: large semi-transparent ellipse, cyan
+// Area attack asset: large semi-transparent ellipse, orange
+// Hero3 asset: rectangle, red (for variety)
+// Hero2 asset: rectangle, green (for variety)
+// Hero asset: rectangle, blue
+// Core asset: smaller ellipse, gold
+// Boss (player) asset: large ellipse, purple
+// Center positions
+var centerX = 2048 / 2;
+var centerY = 2732 / 2;
+// Core (defense point)
+var core = LK.getAsset('core', {
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+core.x = centerX;
+core.y = centerY + 500;
+game.addChild(core);
+// Boss (player)
+var boss = new Boss();
+boss.x = centerX;
+boss.y = centerY + 900;
+game.addChild(boss);
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Ability cooldown display (simple text)
+var abilityTxt = new Text2('', {
+ size: 60,
+ fill: "#fff"
+});
+abilityTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(abilityTxt);
+abilityTxt.y = 130;
+// Arrays for game objects
+var heroes = [];
+var traps = [];
+var areaAttacks = [];
+// Dragging boss
+var dragNode = null;
+// Ability state
+var abilityMode = null; // null, 'area', 'shield', 'trap'
+var areaAttackObj = null;
+// Ability cooldowns (frames)
+var AREA_COOLDOWN = 360; // 6s
+var SHIELD_COOLDOWN = 540; // 9s
+var TRAP_COOLDOWN = 180; // 3s
+// Ability durations
+var SHIELD_DURATION = 180; // 3s
+// Area attack radius
+var AREA_RADIUS = 300;
+// Shield radius
+var SHIELD_RADIUS = 200;
+// Trap radius
+var TRAP_RADIUS = 60;
+// Touch UI: Ability buttons (simple text buttons)
+var areaBtn = new Text2('Area', {
+ size: 80,
+ fill: 0xFF9800
+});
+areaBtn.anchor.set(0.5, 0.5);
+LK.gui.bottom.addChild(areaBtn);
+areaBtn.x = -400;
+areaBtn.y = -100;
+var shieldBtn = new Text2('Shield', {
+ size: 80,
+ fill: 0x00E5FF
+});
+shieldBtn.anchor.set(0.5, 0.5);
+LK.gui.bottom.addChild(shieldBtn);
+shieldBtn.x = 0;
+shieldBtn.y = -100;
+var trapBtn = new Text2('Trap', {
+ size: 80,
+ fill: 0xBDBDBD
+});
+trapBtn.anchor.set(0.5, 0.5);
+LK.gui.bottom.addChild(trapBtn);
+trapBtn.x = 400;
+trapBtn.y = -100;
+// Helper: check if two objects intersect (circle-based)
+function circlesIntersect(a, rA, b, rB) {
+ var dx = a.x - b.x;
+ var dy = a.y - b.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ return dist < rA + rB;
+}
+// Helper: spawn a hero at random edge
+function spawnHero() {
+ var edge = Math.floor(Math.random() * 4);
+ var x, y;
+ if (edge === 0) {
+ // Top
+ x = 200 + Math.random() * (2048 - 400);
+ y = -100;
+ } else if (edge === 1) {
+ // Bottom
+ x = 200 + Math.random() * (2048 - 400);
+ y = 2732 + 100;
+ } else if (edge === 2) {
+ // Left
+ x = -100;
+ y = 400 + Math.random() * (2732 - 800);
+ } else {
+ // Right
+ x = 2048 + 100;
+ y = 400 + Math.random() * (2732 - 800);
+ }
+ // Random hero type
+ var t = Math.random();
+ var hero;
+ if (t < 0.5) {
+ hero = new Hero();
+ } else if (t < 0.8) {
+ hero = new Hero2();
+ } else {
+ hero = new Hero3();
+ }
+ hero.x = x;
+ hero.y = y;
+ hero.lastIntersectingCore = false;
+ hero.lastIntersectingBoss = false;
+ hero.lastIntersectingTrap = false;
+ heroes.push(hero);
+ game.addChild(hero);
+}
+// Ability: Area attack
+function useAreaAttack() {
+ if (boss.cooldowns.area > 0) return;
+ boss.cooldowns.area = AREA_COOLDOWN;
+ // Visual
+ areaAttackObj = new AreaAttack();
+ areaAttackObj.x = boss.x;
+ areaAttackObj.y = boss.y;
+ areaAttackObj.scaleX = 0.1;
+ areaAttackObj.scaleY = 0.1;
+ areaAttackObj.alpha = 0.5;
+ game.addChild(areaAttackObj);
+ areaAttacks.push(areaAttackObj);
+ // Animate
+ tween(areaAttackObj, {
+ scaleX: 1,
+ scaleY: 1,
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (areaAttackObj) {
+ areaAttackObj.destroy();
+ var idx = areaAttacks.indexOf(areaAttackObj);
+ if (idx !== -1) areaAttacks.splice(idx, 1);
+ areaAttackObj = null;
+ }
+ }
+ });
+ // Hit all heroes in radius
+ for (var i = heroes.length - 1; i >= 0; --i) {
+ var h = heroes[i];
+ if (circlesIntersect(boss, AREA_RADIUS, h, 60)) {
+ h.hp -= 1;
+ LK.getSound('area').play();
+ LK.effects.flashObject(h, 0xff9800, 300);
+ if (h.hp <= 0) {
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ LK.getSound('heroHit').play();
+ h.destroy();
+ heroes.splice(i, 1);
+ }
+ }
+ }
+}
+// Ability: Shield
+function useShield() {
+ if (boss.cooldowns.shield > 0) return;
+ boss.cooldowns.shield = SHIELD_COOLDOWN;
+ boss.shieldActive = true;
+ boss.shieldTimer = SHIELD_DURATION;
+ if (boss.shieldObj) boss.shieldObj.destroy();
+ boss.shieldObj = new Shield();
+ boss.shieldObj.x = boss.x;
+ boss.shieldObj.y = boss.y;
+ game.addChild(boss.shieldObj);
+ LK.getSound('shield').play();
+}
+// Ability: Trap
+function useTrap() {
+ if (boss.cooldowns.trap > 0) return;
+ boss.cooldowns.trap = TRAP_COOLDOWN;
+ // Place trap at boss position
+ var trap = new Trap();
+ trap.x = boss.x;
+ trap.y = boss.y;
+ traps.push(trap);
+ game.addChild(trap);
+ LK.getSound('trap').play();
+}
+// Ability button handlers
+areaBtn.down = function (x, y, obj) {
+ useAreaAttack();
+};
+shieldBtn.down = function (x, y, obj) {
+ useShield();
+};
+trapBtn.down = function (x, y, obj) {
+ useTrap();
+};
+// Dragging boss
+function handleMove(x, y, obj) {
+ if (dragNode) {
+ // Clamp boss inside game area
+ var minX = boss.radius + 40;
+ var maxX = 2048 - boss.radius - 40;
+ var minY = boss.radius + 200;
+ var maxY = 2732 - boss.radius - 40;
+ boss.x = Math.max(minX, Math.min(maxX, x));
+ boss.y = Math.max(minY, Math.min(maxY, y));
+ if (boss.shieldObj) {
+ boss.shieldObj.x = boss.x;
+ boss.shieldObj.y = boss.y;
+ }
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Only drag if touch is on boss
+ var dx = x - boss.x;
+ var dy = y - boss.y;
+ if (dx * dx + dy * dy < boss.radius * boss.radius) {
+ dragNode = boss;
+ handleMove(x, y, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Main game update
+game.update = function () {
+ // Update boss
+ boss.update();
+ // Update ability cooldown text
+ var areaCd = boss.cooldowns.area > 0 ? Math.ceil(boss.cooldowns.area / 60) + 's' : 'Ready';
+ var shieldCd = boss.cooldowns.shield > 0 ? Math.ceil(boss.cooldowns.shield / 60) + 's' : 'Ready';
+ var trapCd = boss.cooldowns.trap > 0 ? Math.ceil(boss.cooldowns.trap / 60) + 's' : 'Ready';
+ abilityTxt.setText('Area: ' + areaCd + ' Shield: ' + shieldCd + ' Trap: ' + trapCd);
+ // Update heroes
+ for (var i = heroes.length - 1; i >= 0; --i) {
+ var h = heroes[i];
+ h.update();
+ // Check collision with shield
+ if (boss.shieldActive && boss.shieldObj && circlesIntersect(boss, SHIELD_RADIUS, h, 60)) {
+ // Repel hero
+ var dx = h.x - boss.x;
+ var dy = h.y - boss.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > 0) {
+ h.x += dx / dist * 40;
+ h.y += dy / dist * 40;
+ }
+ LK.effects.flashObject(h, 0x00e5ff, 200);
+ }
+ // Check collision with traps
+ for (var t = traps.length - 1; t >= 0; --t) {
+ var trap = traps[t];
+ if (circlesIntersect(h, 60, trap, TRAP_RADIUS)) {
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ LK.getSound('heroHit').play();
+ h.destroy();
+ heroes.splice(i, 1);
+ trap.destroy();
+ traps.splice(t, 1);
+ break;
+ }
+ }
+ // Check collision with core
+ var nowIntersectingCore = circlesIntersect(h, 60, core, 80);
+ if (!h.lastIntersectingCore && nowIntersectingCore) {
+ // Game over
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ return;
+ }
+ h.lastIntersectingCore = nowIntersectingCore;
+ }
+ // Update traps
+ for (var i = traps.length - 1; i >= 0; --i) {
+ traps[i].update();
+ }
+ // Remove area attack visuals if needed
+ for (var i = areaAttacks.length - 1; i >= 0; --i) {
+ // No update needed, handled by tween
+ }
+ // Spawn heroes
+ if (LK.ticks % 45 === 0) {
+ spawnHero();
+ }
+ // Win condition: survive 60 heroes
+ if (LK.getScore() >= 60) {
+ LK.showYouWin();
+ }
+};
\ No newline at end of file
earthquake image. In-Game asset. 2d. High contrast. No shadows
It's a scary monster, it has a 50-meter sword in its hand, it looks like the full moon sword in the game Metin2.. In-Game asset. 2d. High contrast. No shadows
game Charakter. In-Game asset. 2d. High contrast. No shadows
shield. In-Game asset. 2d. High contrast. No shadows
trap. In-Game asset. 2d. High contrast. No shadows
2d dungeon. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat