/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var AOEAttack = Container.expand(function () { var self = Container.call(this); var aoeGraphics = self.attachAsset('aoeIndicator', { anchorX: 0.5, anchorY: 0.5 }); self.warningTime = 90; self.activeTime = 30; self.phase = 'warning'; aoeGraphics.alpha = 0.3; self.update = function () { if (self.phase === 'warning') { self.warningTime--; aoeGraphics.alpha = 0.3 + Math.sin(LK.ticks * 0.3) * 0.2; if (self.warningTime <= 0) { self.phase = 'active'; aoeGraphics.alpha = 0.8; aoeGraphics.tint = 0xff0000; } } else if (self.phase === 'active') { self.activeTime--; if (self.activeTime <= 0) { self.shouldDestroy = true; } } }; return self; }); var AmmoPickup = Container.expand(function () { var self = Container.call(this); var pickupGraphics = self.attachAsset('ammoPickup', { anchorX: 0.5, anchorY: 0.5 }); // Add visual effect - pulsing animation self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; pickupGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.2; pickupGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.2; }; return self; }); var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1000; self.maxHealth = 1000; self.phase = 1; self.attackTimer = 0; self.attackCooldown = 120; self.currentAttack = 0; self.takeDamage = function (damage) { self.health -= damage; // Flash effect tween(bossGraphics, { tint: 0xffffff }, { duration: 100 }); tween(bossGraphics, { tint: 0xe74c3c }, { duration: 100 }); if (self.health <= 0) { // Ensure health doesn't go below 0 self.health = 0; LK.showYouWin(); } // Phase transitions if (self.health <= 750 && self.phase === 1) { self.phase = 2; self.attackCooldown = 90; } else if (self.health <= 200 && self.phase === 2) { self.phase = 3; self.attackCooldown = 60; } else if (self.health <= 100 && self.phase === 3) { self.phase = 4; self.attackCooldown = 45; } }; self.update = function () { self.attackTimer++; if (self.attackTimer >= self.attackCooldown) { self.attackTimer = 0; self.performAttack(); } }; self.performAttack = function () { LK.getSound('bossAttack').play(); if (self.phase === 1) { // Simple projectile attack self.projectileAttack(); } else if (self.phase === 2) { // Phase 2: Original attacks plus 2 new ones var attackType = Math.floor(Math.random() * 4); if (attackType === 0) { self.multiProjectileAttack(); } else if (attackType === 1) { self.aoeAttack(); } else if (attackType === 2) { self.chargeAttack(); } else { self.spiralAttack(); } } else if (self.phase === 3) { // All attacks randomly var attackType = Math.floor(Math.random() * 6); if (attackType === 0) { self.multiProjectileAttack(); } else if (attackType === 1) { self.aoeAttack(); } else if (attackType === 2) { self.chargeAttack(); } else if (attackType === 3) { self.spiralAttack(); } else if (attackType === 4) { self.waveAttack(); } else { self.rapidFireAttack(); } } else if (self.phase === 4) { // Phase 4: All attacks with higher frequency var attackType = Math.floor(Math.random() * 6); if (attackType === 0) { self.multiProjectileAttack(); } else if (attackType === 1) { self.aoeAttack(); } else if (attackType === 2) { self.chargeAttack(); } else if (attackType === 3) { self.spiralAttack(); } else if (attackType === 4) { self.waveAttack(); } else { self.rapidFireAttack(); } } }; self.projectileAttack = function () { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.targetX = player.x; projectile.targetY = player.y; projectiles.push(projectile); game.addChild(projectile); }; self.multiProjectileAttack = function () { for (var i = 0; i < 5; i++) { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; var angle = Math.PI * 2 * i / 5; projectile.velocityX = Math.cos(angle) * 4; projectile.velocityY = Math.sin(angle) * 4; projectiles.push(projectile); game.addChild(projectile); } }; self.aoeAttack = function () { var aoe = new AOEAttack(); aoe.x = player.x; aoe.y = player.y; aoeAttacks.push(aoe); game.addChild(aoe); }; self.chargeAttack = function () { var originalX = self.x; var originalY = self.y; tween(self, { x: player.x, y: player.y }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { // Check collision with player if (self.intersects(player)) { player.takeDamage(30); } // Return to original position tween(self, { x: originalX, y: originalY }, { duration: 600, easing: tween.easeInOut }); } }); }; self.spiralAttack = function () { for (var i = 0; i < 8; i++) { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; var angle = Math.PI * 2 * i / 8 + LK.ticks * 0.1; projectile.velocityX = Math.cos(angle) * 3; projectile.velocityY = Math.sin(angle) * 3; projectiles.push(projectile); game.addChild(projectile); } }; self.waveAttack = function () { for (var i = 0; i < 7; i++) { var projectile = new Projectile(); projectile.x = self.x - 200 + i * 70; projectile.y = self.y; projectile.velocityX = 0; projectile.velocityY = 4; projectiles.push(projectile); game.addChild(projectile); } }; self.rapidFireAttack = function () { for (var i = 0; i < 3; i++) { LK.setTimeout(function () { var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.targetX = player.x; projectile.targetY = player.y; projectiles.push(projectile); game.addChild(projectile); }, i * 200); } }; return self; }); var FireButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('fireButton', { anchorX: 0.5, anchorY: 0.5 }); // Add visual feedback self.isPressed = false; self.down = function (x, y, obj) { if (!self.isPressed && player.attackCooldown <= 0) { self.isPressed = true; buttonGraphics.scaleX = 0.9; buttonGraphics.scaleY = 0.9; buttonGraphics.tint = 0xff4500; // Fire bullet var bullet = new PlayerBullet(); bullet.x = player.x; bullet.y = player.y; if (boss) { var dx = boss.x - player.x; var dy = boss.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.velocityX = dx / distance * bullet.speed; bullet.velocityY = dy / distance * bullet.speed; } playerBullets.push(bullet); game.addChild(bullet); if (player.ammo > 0) { player.ammo--; } player.attackCooldown = 30; // 30 frames cooldown (0.5 seconds at 60fps) LK.getSound('shoot').play(); } } }; self.up = function (x, y, obj) { self.isPressed = false; buttonGraphics.scaleX = 1.0; buttonGraphics.scaleY = 1.0; buttonGraphics.tint = 0xff6b35; }; return self; }); var HealthPickup = Container.expand(function () { var self = Container.call(this); var pickupGraphics = self.attachAsset('healthPickup', { anchorX: 0.5, anchorY: 0.5 }); // Add visual effect - pulsing animation self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; pickupGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.3; pickupGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.3; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.speed = 8; self.shootCooldown = 0; self.invulnerable = false; self.ammo = 30; self.maxAmmo = 30; self.attackCooldown = 0; self.rechargeAmmo = function () { self.ammo = self.maxAmmo; }; self.heal = function (amount) { self.health += amount; if (self.health > self.maxHealth) { self.health = self.maxHealth; } }; self.takeDamage = function (damage) { if (self.invulnerable) return; self.health -= damage; self.invulnerable = true; // Flash effect tween(playerGraphics, { alpha: 0.3 }, { duration: 100 }); tween(playerGraphics, { alpha: 1 }, { duration: 100 }); LK.getSound('hit').play(); LK.setTimeout(function () { self.invulnerable = false; }, 500); if (self.health <= 0) { LK.showGameOver(); } }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.attackCooldown > 0) { self.attackCooldown--; } }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.speed = 10; self.lifetime = 180; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; } }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.targetX = 0; self.targetY = 0; self.velocityX = 0; self.velocityY = 0; self.speed = 5; self.lifetime = 300; self.update = function () { if (self.velocityX === 0 && self.velocityY === 0) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.velocityX = dx / distance * self.speed; self.velocityY = dy / distance * self.speed; } } self.x += self.velocityX; self.y += self.velocityY; self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ var arena = game.attachAsset('arena', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); var player = game.addChild(new Player()); player.x = 2048 / 2; player.y = 2732 / 2 + 300; var boss = game.addChild(new Boss()); boss.x = 2048 / 2; boss.y = 2732 / 2 - 300; var projectiles = []; var aoeAttacks = []; var playerBullets = []; // Arena boundaries var arenaLeft = arena.x - arena.width / 2; var arenaRight = arena.x + arena.width / 2; var arenaTop = arena.y - arena.height / 2; var arenaBottom = arena.y + arena.height / 2; // UI var healthText = new Text2('Health: 100', { size: 60, fill: 0xFFFFFF }); healthText.anchor.set(0, 0); LK.gui.topLeft.addChild(healthText); healthText.x = 150; healthText.y = 50; var bossHealthText = new Text2('Boss: 1000', { size: 60, fill: 0xFF0000 }); bossHealthText.anchor.set(0.5, 0); LK.gui.top.addChild(bossHealthText); bossHealthText.y = 50; var ammoText = new Text2('Ammo: 30', { size: 60, fill: 0x00FF00 }); ammoText.anchor.set(0, 0); LK.gui.topLeft.addChild(ammoText); ammoText.x = 150; ammoText.y = 120; var dragNode = null; var touchStartX = 0; var touchStartY = 0; var ammoPickups = []; var ammoSpawnTimer = 0; var healthPickups = []; var healthSpawnTimer = 0; // Add fire button to GUI var fireButton = new FireButton(); LK.gui.bottomRight.addChild(fireButton); fireButton.x = -100; fireButton.y = -100; game.down = function (x, y, obj) { dragNode = player; touchStartX = x; touchStartY = y; }; game.move = function (x, y, obj) { if (dragNode) { var newX = x; var newY = y; // Clamp to arena boundaries if (newX < arenaLeft + 40) newX = arenaLeft + 40; if (newX > arenaRight - 40) newX = arenaRight - 40; if (newY < arenaTop + 40) newY = arenaTop + 40; if (newY > arenaBottom - 40) newY = arenaBottom - 40; dragNode.x = newX; dragNode.y = newY; } }; game.up = function (x, y, obj) { dragNode = null; }; game.update = function () { // Update UI healthText.setText('Health: ' + player.health); ammoText.setText('Ammo: ' + player.ammo); bossHealthText.setText('Boss: ' + boss.health); // Spawn ammo pickups periodically ammoSpawnTimer++; if (ammoSpawnTimer >= 600) { // Every 10 seconds at 60fps ammoSpawnTimer = 0; var pickup = new AmmoPickup(); pickup.x = arenaLeft + Math.random() * (arenaRight - arenaLeft); pickup.y = arenaTop + Math.random() * (arenaBottom - arenaTop); ammoPickups.push(pickup); game.addChild(pickup); } // Spawn health pickups periodically healthSpawnTimer++; if (healthSpawnTimer >= 900) { // Every 15 seconds at 60fps healthSpawnTimer = 0; var healthPickup = new HealthPickup(); healthPickup.x = arenaLeft + Math.random() * (arenaRight - arenaLeft); healthPickup.y = arenaTop + Math.random() * (arenaBottom - arenaTop); healthPickups.push(healthPickup); game.addChild(healthPickup); } // Check ammo pickup collisions for (var i = ammoPickups.length - 1; i >= 0; i--) { var pickup = ammoPickups[i]; if (pickup.intersects(player)) { player.rechargeAmmo(); pickup.destroy(); ammoPickups.splice(i, 1); } } // Check health pickup collisions for (var i = healthPickups.length - 1; i >= 0; i--) { var healthPickup = healthPickups[i]; if (healthPickup.intersects(player)) { player.heal(10); healthPickup.destroy(); healthPickups.splice(i, 1); } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; if (projectile.shouldDestroy) { projectile.destroy(); projectiles.splice(i, 1); continue; } // Check collision with player if (projectile.intersects(player)) { player.takeDamage(20); projectile.destroy(); projectiles.splice(i, 1); continue; } // Check if out of arena if (projectile.x < arenaLeft - 100 || projectile.x > arenaRight + 100 || projectile.y < arenaTop - 100 || projectile.y > arenaBottom + 100) { projectile.destroy(); projectiles.splice(i, 1); } } // Update AOE attacks for (var i = aoeAttacks.length - 1; i >= 0; i--) { var aoe = aoeAttacks[i]; if (aoe.shouldDestroy) { aoe.destroy(); aoeAttacks.splice(i, 1); continue; } // Check collision with player during active phase if (aoe.phase === 'active' && aoe.intersects(player)) { player.takeDamage(25); } } // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (bullet.shouldDestroy) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with boss if (boss && bullet.intersects(boss)) { // Calculate distance between player and boss var dx = player.x - boss.x; var dy = player.y - boss.y; var distance = Math.sqrt(dx * dx + dy * dy); // Double damage if player is close to boss (within 200 pixels) var damage = distance <= 200 ? 20 : 10; boss.takeDamage(damage); bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check if out of arena if (bullet.x < arenaLeft - 100 || bullet.x > arenaRight + 100 || bullet.y < arenaTop - 100 || bullet.y > arenaBottom + 100) { bullet.destroy(); playerBullets.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AOEAttack = Container.expand(function () {
var self = Container.call(this);
var aoeGraphics = self.attachAsset('aoeIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
self.warningTime = 90;
self.activeTime = 30;
self.phase = 'warning';
aoeGraphics.alpha = 0.3;
self.update = function () {
if (self.phase === 'warning') {
self.warningTime--;
aoeGraphics.alpha = 0.3 + Math.sin(LK.ticks * 0.3) * 0.2;
if (self.warningTime <= 0) {
self.phase = 'active';
aoeGraphics.alpha = 0.8;
aoeGraphics.tint = 0xff0000;
}
} else if (self.phase === 'active') {
self.activeTime--;
if (self.activeTime <= 0) {
self.shouldDestroy = true;
}
}
};
return self;
});
var AmmoPickup = Container.expand(function () {
var self = Container.call(this);
var pickupGraphics = self.attachAsset('ammoPickup', {
anchorX: 0.5,
anchorY: 0.5
});
// Add visual effect - pulsing animation
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.1;
pickupGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.2;
pickupGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.2;
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1000;
self.maxHealth = 1000;
self.phase = 1;
self.attackTimer = 0;
self.attackCooldown = 120;
self.currentAttack = 0;
self.takeDamage = function (damage) {
self.health -= damage;
// Flash effect
tween(bossGraphics, {
tint: 0xffffff
}, {
duration: 100
});
tween(bossGraphics, {
tint: 0xe74c3c
}, {
duration: 100
});
if (self.health <= 0) {
// Ensure health doesn't go below 0
self.health = 0;
LK.showYouWin();
}
// Phase transitions
if (self.health <= 750 && self.phase === 1) {
self.phase = 2;
self.attackCooldown = 90;
} else if (self.health <= 200 && self.phase === 2) {
self.phase = 3;
self.attackCooldown = 60;
} else if (self.health <= 100 && self.phase === 3) {
self.phase = 4;
self.attackCooldown = 45;
}
};
self.update = function () {
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown) {
self.attackTimer = 0;
self.performAttack();
}
};
self.performAttack = function () {
LK.getSound('bossAttack').play();
if (self.phase === 1) {
// Simple projectile attack
self.projectileAttack();
} else if (self.phase === 2) {
// Phase 2: Original attacks plus 2 new ones
var attackType = Math.floor(Math.random() * 4);
if (attackType === 0) {
self.multiProjectileAttack();
} else if (attackType === 1) {
self.aoeAttack();
} else if (attackType === 2) {
self.chargeAttack();
} else {
self.spiralAttack();
}
} else if (self.phase === 3) {
// All attacks randomly
var attackType = Math.floor(Math.random() * 6);
if (attackType === 0) {
self.multiProjectileAttack();
} else if (attackType === 1) {
self.aoeAttack();
} else if (attackType === 2) {
self.chargeAttack();
} else if (attackType === 3) {
self.spiralAttack();
} else if (attackType === 4) {
self.waveAttack();
} else {
self.rapidFireAttack();
}
} else if (self.phase === 4) {
// Phase 4: All attacks with higher frequency
var attackType = Math.floor(Math.random() * 6);
if (attackType === 0) {
self.multiProjectileAttack();
} else if (attackType === 1) {
self.aoeAttack();
} else if (attackType === 2) {
self.chargeAttack();
} else if (attackType === 3) {
self.spiralAttack();
} else if (attackType === 4) {
self.waveAttack();
} else {
self.rapidFireAttack();
}
}
};
self.projectileAttack = function () {
var projectile = new Projectile();
projectile.x = self.x;
projectile.y = self.y;
projectile.targetX = player.x;
projectile.targetY = player.y;
projectiles.push(projectile);
game.addChild(projectile);
};
self.multiProjectileAttack = function () {
for (var i = 0; i < 5; i++) {
var projectile = new Projectile();
projectile.x = self.x;
projectile.y = self.y;
var angle = Math.PI * 2 * i / 5;
projectile.velocityX = Math.cos(angle) * 4;
projectile.velocityY = Math.sin(angle) * 4;
projectiles.push(projectile);
game.addChild(projectile);
}
};
self.aoeAttack = function () {
var aoe = new AOEAttack();
aoe.x = player.x;
aoe.y = player.y;
aoeAttacks.push(aoe);
game.addChild(aoe);
};
self.chargeAttack = function () {
var originalX = self.x;
var originalY = self.y;
tween(self, {
x: player.x,
y: player.y
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Check collision with player
if (self.intersects(player)) {
player.takeDamage(30);
}
// Return to original position
tween(self, {
x: originalX,
y: originalY
}, {
duration: 600,
easing: tween.easeInOut
});
}
});
};
self.spiralAttack = function () {
for (var i = 0; i < 8; i++) {
var projectile = new Projectile();
projectile.x = self.x;
projectile.y = self.y;
var angle = Math.PI * 2 * i / 8 + LK.ticks * 0.1;
projectile.velocityX = Math.cos(angle) * 3;
projectile.velocityY = Math.sin(angle) * 3;
projectiles.push(projectile);
game.addChild(projectile);
}
};
self.waveAttack = function () {
for (var i = 0; i < 7; i++) {
var projectile = new Projectile();
projectile.x = self.x - 200 + i * 70;
projectile.y = self.y;
projectile.velocityX = 0;
projectile.velocityY = 4;
projectiles.push(projectile);
game.addChild(projectile);
}
};
self.rapidFireAttack = function () {
for (var i = 0; i < 3; i++) {
LK.setTimeout(function () {
var projectile = new Projectile();
projectile.x = self.x;
projectile.y = self.y;
projectile.targetX = player.x;
projectile.targetY = player.y;
projectiles.push(projectile);
game.addChild(projectile);
}, i * 200);
}
};
return self;
});
var FireButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('fireButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Add visual feedback
self.isPressed = false;
self.down = function (x, y, obj) {
if (!self.isPressed && player.attackCooldown <= 0) {
self.isPressed = true;
buttonGraphics.scaleX = 0.9;
buttonGraphics.scaleY = 0.9;
buttonGraphics.tint = 0xff4500;
// Fire bullet
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y;
if (boss) {
var dx = boss.x - player.x;
var dy = boss.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.velocityX = dx / distance * bullet.speed;
bullet.velocityY = dy / distance * bullet.speed;
}
playerBullets.push(bullet);
game.addChild(bullet);
if (player.ammo > 0) {
player.ammo--;
}
player.attackCooldown = 30; // 30 frames cooldown (0.5 seconds at 60fps)
LK.getSound('shoot').play();
}
}
};
self.up = function (x, y, obj) {
self.isPressed = false;
buttonGraphics.scaleX = 1.0;
buttonGraphics.scaleY = 1.0;
buttonGraphics.tint = 0xff6b35;
};
return self;
});
var HealthPickup = Container.expand(function () {
var self = Container.call(this);
var pickupGraphics = self.attachAsset('healthPickup', {
anchorX: 0.5,
anchorY: 0.5
});
// Add visual effect - pulsing animation
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.1;
pickupGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.3;
pickupGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.3;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 8;
self.shootCooldown = 0;
self.invulnerable = false;
self.ammo = 30;
self.maxAmmo = 30;
self.attackCooldown = 0;
self.rechargeAmmo = function () {
self.ammo = self.maxAmmo;
};
self.heal = function (amount) {
self.health += amount;
if (self.health > self.maxHealth) {
self.health = self.maxHealth;
}
};
self.takeDamage = function (damage) {
if (self.invulnerable) return;
self.health -= damage;
self.invulnerable = true;
// Flash effect
tween(playerGraphics, {
alpha: 0.3
}, {
duration: 100
});
tween(playerGraphics, {
alpha: 1
}, {
duration: 100
});
LK.getSound('hit').play();
LK.setTimeout(function () {
self.invulnerable = false;
}, 500);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 10;
self.lifetime = 180;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0) {
self.shouldDestroy = true;
}
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.velocityX = 0;
self.velocityY = 0;
self.speed = 5;
self.lifetime = 300;
self.update = function () {
if (self.velocityX === 0 && self.velocityY === 0) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
}
}
self.x += self.velocityX;
self.y += self.velocityY;
self.lifetime--;
if (self.lifetime <= 0) {
self.shouldDestroy = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
var arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2 + 300;
var boss = game.addChild(new Boss());
boss.x = 2048 / 2;
boss.y = 2732 / 2 - 300;
var projectiles = [];
var aoeAttacks = [];
var playerBullets = [];
// Arena boundaries
var arenaLeft = arena.x - arena.width / 2;
var arenaRight = arena.x + arena.width / 2;
var arenaTop = arena.y - arena.height / 2;
var arenaBottom = arena.y + arena.height / 2;
// UI
var healthText = new Text2('Health: 100', {
size: 60,
fill: 0xFFFFFF
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 150;
healthText.y = 50;
var bossHealthText = new Text2('Boss: 1000', {
size: 60,
fill: 0xFF0000
});
bossHealthText.anchor.set(0.5, 0);
LK.gui.top.addChild(bossHealthText);
bossHealthText.y = 50;
var ammoText = new Text2('Ammo: 30', {
size: 60,
fill: 0x00FF00
});
ammoText.anchor.set(0, 0);
LK.gui.topLeft.addChild(ammoText);
ammoText.x = 150;
ammoText.y = 120;
var dragNode = null;
var touchStartX = 0;
var touchStartY = 0;
var ammoPickups = [];
var ammoSpawnTimer = 0;
var healthPickups = [];
var healthSpawnTimer = 0;
// Add fire button to GUI
var fireButton = new FireButton();
LK.gui.bottomRight.addChild(fireButton);
fireButton.x = -100;
fireButton.y = -100;
game.down = function (x, y, obj) {
dragNode = player;
touchStartX = x;
touchStartY = y;
};
game.move = function (x, y, obj) {
if (dragNode) {
var newX = x;
var newY = y;
// Clamp to arena boundaries
if (newX < arenaLeft + 40) newX = arenaLeft + 40;
if (newX > arenaRight - 40) newX = arenaRight - 40;
if (newY < arenaTop + 40) newY = arenaTop + 40;
if (newY > arenaBottom - 40) newY = arenaBottom - 40;
dragNode.x = newX;
dragNode.y = newY;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Update UI
healthText.setText('Health: ' + player.health);
ammoText.setText('Ammo: ' + player.ammo);
bossHealthText.setText('Boss: ' + boss.health);
// Spawn ammo pickups periodically
ammoSpawnTimer++;
if (ammoSpawnTimer >= 600) {
// Every 10 seconds at 60fps
ammoSpawnTimer = 0;
var pickup = new AmmoPickup();
pickup.x = arenaLeft + Math.random() * (arenaRight - arenaLeft);
pickup.y = arenaTop + Math.random() * (arenaBottom - arenaTop);
ammoPickups.push(pickup);
game.addChild(pickup);
}
// Spawn health pickups periodically
healthSpawnTimer++;
if (healthSpawnTimer >= 900) {
// Every 15 seconds at 60fps
healthSpawnTimer = 0;
var healthPickup = new HealthPickup();
healthPickup.x = arenaLeft + Math.random() * (arenaRight - arenaLeft);
healthPickup.y = arenaTop + Math.random() * (arenaBottom - arenaTop);
healthPickups.push(healthPickup);
game.addChild(healthPickup);
}
// Check ammo pickup collisions
for (var i = ammoPickups.length - 1; i >= 0; i--) {
var pickup = ammoPickups[i];
if (pickup.intersects(player)) {
player.rechargeAmmo();
pickup.destroy();
ammoPickups.splice(i, 1);
}
}
// Check health pickup collisions
for (var i = healthPickups.length - 1; i >= 0; i--) {
var healthPickup = healthPickups[i];
if (healthPickup.intersects(player)) {
player.heal(10);
healthPickup.destroy();
healthPickups.splice(i, 1);
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
if (projectile.shouldDestroy) {
projectile.destroy();
projectiles.splice(i, 1);
continue;
}
// Check collision with player
if (projectile.intersects(player)) {
player.takeDamage(20);
projectile.destroy();
projectiles.splice(i, 1);
continue;
}
// Check if out of arena
if (projectile.x < arenaLeft - 100 || projectile.x > arenaRight + 100 || projectile.y < arenaTop - 100 || projectile.y > arenaBottom + 100) {
projectile.destroy();
projectiles.splice(i, 1);
}
}
// Update AOE attacks
for (var i = aoeAttacks.length - 1; i >= 0; i--) {
var aoe = aoeAttacks[i];
if (aoe.shouldDestroy) {
aoe.destroy();
aoeAttacks.splice(i, 1);
continue;
}
// Check collision with player during active phase
if (aoe.phase === 'active' && aoe.intersects(player)) {
player.takeDamage(25);
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.shouldDestroy) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with boss
if (boss && bullet.intersects(boss)) {
// Calculate distance between player and boss
var dx = player.x - boss.x;
var dy = player.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Double damage if player is close to boss (within 200 pixels)
var damage = distance <= 200 ? 20 : 10;
boss.takeDamage(damage);
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check if out of arena
if (bullet.x < arenaLeft - 100 || bullet.x > arenaRight + 100 || bullet.y < arenaTop - 100 || bullet.y > arenaBottom + 100) {
bullet.destroy();
playerBullets.splice(i, 1);
}
}
};