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