/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); self.maxHealth = 300; self.health = self.maxHealth; self.patternIndex = 0; self.patternTimer = 0; self.isVulnerable = false; self.vulnerabilityTimer = 0; self.attackPatterns = []; self.attackPatternsPhase2 = []; self.currentPhase = 1; self.lastHealthPercentage = 1.0; self.takeDamage = function (damage) { if (self.isVulnerable) { self.health -= damage; LK.effects.flashObject(self, 0xffffff, 200); LK.getSound('bossHit').play(); if (self.health <= 0) { self.health = 0; self.onDefeat(); } } }; self.onDefeat = function () { LK.getSound('bossDefeat').play(); // Make boss vanish and stop attacking self.visible = false; self.alpha = 0; // Stop player shooting when boss is defeated if (player) { player.canShoot = false; player.health = player.maxHealth; } console.log("Boss defeated. Current index:", currentBossIndex, "Total bosses:", bossConfigs.length); // Check if this is the final boss (Boss4 at index 3) if (currentBossIndex === 3) { console.log("All 4 bosses defeated - showing win screen"); LK.showYouWin(); } else { // Show Next Stage button instead of auto-progressing showNextStageButton(); } }; self.executePattern = function () { // Override in specific boss classes }; self.update = function () { // Stop all attacks and patterns if health is 0 if (self.health <= 0) { return; } self.patternTimer++; if (self.vulnerabilityTimer > 0) { self.vulnerabilityTimer--; if (self.vulnerabilityTimer <= 0) { self.isVulnerable = false; } } // Check for phase transition at 50% health var currentHealthPercentage = self.health / self.maxHealth; if (self.currentPhase === 1 && currentHealthPercentage <= 0.5 && self.lastHealthPercentage > 0.5) { self.currentPhase = 2; self.patternIndex = 0; self.patternTimer = 0; LK.effects.flashObject(self, 0xffffff, 1000); // Start phase 2 flashing effect self.startPhase2Flash(); } self.lastHealthPercentage = currentHealthPercentage; self.executePattern(); }; return self; }); var Boss4 = Boss.expand(function () { var self = Boss.call(this); var bossGraphics = self.attachAsset('boss4', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0 }); self.maxHealth = 600; self.health = self.maxHealth; self.attackPatterns = [{ duration: 120, action: 'ultimate_sweep' }, { duration: 100, action: 'chaos_storm' }, { duration: 150, action: 'teleport_barrage' }, { duration: 120, action: 'gravity_pull' }, { duration: 80, action: 'laser_grid' }, { duration: 90, action: 'vulnerable' }]; self.attackPatternsPhase2 = [{ duration: 80, action: 'apocalypse_sweep' }, { duration: 60, action: 'death_spiral' }, { duration: 100, action: 'final_barrage' }, { duration: 120, action: 'dimensional_rift' }, { duration: 70, action: 'omega_grid' }, { duration: 60, action: 'vulnerable' }]; self.executePattern = function () { var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2; var currentPattern = patterns[self.patternIndex]; if (self.patternTimer >= currentPattern.duration) { self.patternTimer = 0; self.patternIndex = (self.patternIndex + 1) % patterns.length; } switch (currentPattern.action) { case 'ultimate_sweep': if (self.patternTimer % 8 === 0) { self.ultimateSweep(); } break; case 'chaos_storm': if (self.patternTimer % 4 === 0) { self.chaosStorm(); } break; case 'teleport_barrage': if (self.patternTimer % 25 === 0) { self.teleportBarrage(); } break; case 'gravity_pull': if (self.patternTimer === 1) { self.gravityPull(); } break; case 'laser_grid': if (self.patternTimer % 15 === 0) { self.laserGrid(); } break; case 'vulnerable': self.isVulnerable = true; self.vulnerabilityTimer = 90; tween(bossGraphics, { alpha: 0.4 }, { duration: 200 }); break; case 'apocalypse_sweep': if (self.patternTimer % 5 === 0) { self.apocalypseSweep(); } break; case 'death_spiral': if (self.patternTimer % 6 === 0) { self.deathSpiral(); } break; case 'final_barrage': if (self.patternTimer % 3 === 0) { self.finalBarrage(); } break; case 'dimensional_rift': if (self.patternTimer % 20 === 0) { self.dimensionalRift(); } break; case 'omega_grid': if (self.patternTimer % 10 === 0) { self.omegaGrid(); } break; } }; self.ultimateSweep = function () { for (var i = 0; i < 7; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 3) * 40; bullet.y = self.y + 50; bullet.direction = { x: (i - 3) * 0.2, y: 1 }; bullet.speed = 7; bossBullets.push(bullet); game.addChild(bullet); } }; self.chaosStorm = function () { for (var i = 0; i < 4; i++) { var bullet = new BossBullet(); bullet.x = self.x + (Math.random() - 0.5) * 400; bullet.y = self.y + 50; bullet.direction = { x: (Math.random() - 0.5) * 4, y: 0.8 + Math.random() * 0.4 }; bullet.speed = 6 + Math.random() * 3; bossBullets.push(bullet); game.addChild(bullet); } }; self.teleportBarrage = function () { var teleportPositions = [{ x: arenaLeft + 200, y: arenaTop + 250 }, { x: arenaRight - 200, y: arenaTop + 250 }, { x: 1024, y: arenaTop + 150 }, { x: arenaLeft + 300, y: arenaTop + 400 }, { x: arenaRight - 300, y: arenaTop + 400 }]; var randomPos = teleportPositions[Math.floor(Math.random() * teleportPositions.length)]; tween(self, { x: randomPos.x, y: randomPos.y }, { duration: 200 }); // Massive bullet spread after teleport LK.setTimeout(function () { for (var i = 0; i < 12; i++) { var angle = i / 12 * Math.PI * 2; var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; bullet.direction = { x: Math.cos(angle), y: Math.sin(angle) }; bullet.speed = 5; bossBullets.push(bullet); game.addChild(bullet); } }, 300); }; self.gravityPull = function () { // Pull effect - move towards player position over time var targetX = Math.max(arenaLeft + 200, Math.min(arenaRight - 200, player.x)); var targetY = Math.max(arenaTop + 200, Math.min(arenaBottom - 300, player.y - 150)); tween(self, { x: targetX, y: targetY }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Explosion of bullets in all directions for (var i = 0; i < 16; i++) { var angle = i / 16 * Math.PI * 2; var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; bullet.direction = { x: Math.cos(angle), y: Math.sin(angle) }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } } }); }; self.laserGrid = function () { // Create grid pattern of bullets for (var row = 0; row < 3; row++) { for (var col = 0; col < 5; col++) { var bullet = new BossBullet(); bullet.x = arenaLeft + 200 + col * 300; bullet.y = self.y + row * 80; bullet.direction = { x: 0, y: 1 }; bullet.speed = 4 + row; bossBullets.push(bullet); game.addChild(bullet); } } }; self.apocalypseSweep = function () { // Even more intense sweep for phase 2 for (var i = 0; i < 9; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 4) * 35; bullet.y = self.y + 50; bullet.direction = { x: (i - 4) * 0.25, y: 1 }; bullet.speed = 8; bossBullets.push(bullet); game.addChild(bullet); } }; self.deathSpiral = function () { // Rotating spiral pattern var spiralCount = 6; for (var i = 0; i < spiralCount; i++) { var angle = (self.patternTimer * 0.3 + i * Math.PI * 2 / spiralCount) % (Math.PI * 2); var bullet = new BossBullet(); bullet.x = self.x + Math.cos(angle) * 100; bullet.y = self.y + Math.sin(angle) * 50 + 50; bullet.direction = { x: Math.cos(angle + Math.PI / 4) * 0.8, y: Math.sin(angle + Math.PI / 4) * 0.8 + 0.6 }; bullet.speed = 7; bossBullets.push(bullet); game.addChild(bullet); } }; self.finalBarrage = function () { // Overwhelming bullet hell for (var i = 0; i < 6; i++) { var bullet = new BossBullet(); bullet.x = self.x + (Math.random() - 0.5) * 500; bullet.y = self.y + Math.random() * 100; var angleToPlayer = Math.atan2(player.y - bullet.y, player.x - bullet.x); bullet.direction = { x: Math.cos(angleToPlayer + (Math.random() - 0.5) * 0.8), y: Math.sin(angleToPlayer + (Math.random() - 0.5) * 0.8) }; bullet.speed = 5 + Math.random() * 4; bossBullets.push(bullet); game.addChild(bullet); } }; self.dimensionalRift = function () { // Teleport to multiple positions rapidly var positions = [{ x: arenaLeft + 150, y: arenaTop + 200 }, { x: arenaRight - 150, y: arenaTop + 200 }, { x: 1024, y: arenaTop + 350 }, { x: arenaLeft + 300, y: arenaTop + 500 }, { x: arenaRight - 300, y: arenaTop + 500 }]; for (var p = 0; p < 3; p++) { var pos = positions[Math.floor(Math.random() * positions.length)]; LK.setTimeout(function () { tween(self, { x: pos.x, y: pos.y }, { duration: 150 }); // Shoot bullets from each position for (var j = 0; j < 8; j++) { var angle = j / 8 * Math.PI * 2; var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; bullet.direction = { x: Math.cos(angle), y: Math.sin(angle) }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }, p * 200); } }; self.omegaGrid = function () { // Ultimate grid attack for (var row = 0; row < 4; row++) { for (var col = 0; col < 7; col++) { var bullet = new BossBullet(); bullet.x = arenaLeft + 150 + col * 250; bullet.y = self.y + row * 60; bullet.direction = { x: (col - 3) * 0.1, y: 1 }; bullet.speed = 5 + row; bossBullets.push(bullet); game.addChild(bullet); } } }; self.startPhase2Flash = function () { var flashToGold = function flashToGold() { tween(bossGraphics, { tint: 0xFFD700 }, { duration: 600, easing: tween.easeInOut, onFinish: flashToWhite }); }; var flashToWhite = function flashToWhite() { tween(bossGraphics, { tint: 0xFFFFFF }, { duration: 600, easing: tween.easeInOut, onFinish: flashToGold }); }; flashToGold(); }; return self; }); var Boss3 = Boss.expand(function () { var self = Boss.call(this); var bossGraphics = self.attachAsset('boss3', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0 }); self.maxHealth = 250; self.health = self.maxHealth; self.attackPatterns = [{ duration: 60, action: 'laser_sweep' }, { duration: 50, action: 'bullet_hell' }, { duration: 80, action: 'dash_attack' }, { duration: 100, action: 'dive_attack' }, { duration: 70, action: 'horizontal_sweep' }, { duration: 80, action: 'diagonal_attack' }, { duration: 80, action: 'vulnerable' }]; self.attackPatternsPhase2 = [{ duration: 50, action: 'mega_laser_sweep' }, { duration: 40, action: 'chaos_bullets' }, { duration: 70, action: 'triple_dash' }, { duration: 80, action: 'power_dive' }, { duration: 50, action: 'spiral_sweep' }, { duration: 60, action: 'diagonal_barrage' }, { duration: 60, action: 'vulnerable' }]; self.executePattern = function () { var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2; var currentPattern = patterns[self.patternIndex]; if (self.patternTimer >= currentPattern.duration) { self.patternTimer = 0; self.patternIndex = (self.patternIndex + 1) % patterns.length; } switch (currentPattern.action) { case 'laser_sweep': if (self.patternTimer % 15 === 0) { self.shootLaser(); } break; case 'bullet_hell': if (self.patternTimer % 8 === 0) { self.shootRandomBullets(); } break; case 'dash_attack': if (self.patternTimer === 1) { var targetY = Math.min(player.y, arenaBottom - 150); tween(self, { y: targetY }, { duration: 500 }); } break; case 'dive_attack': if (self.patternTimer === 1) { self.diveAttack(); } break; case 'vulnerable': self.isVulnerable = true; self.vulnerabilityTimer = 60; tween(bossGraphics, { alpha: 0.5 }, { duration: 200 }); break; case 'mega_laser_sweep': if (self.patternTimer % 10 === 0) { self.shootMegaLaser(); } break; case 'chaos_bullets': if (self.patternTimer % 6 === 0) { self.shootChaosBullets(); } break; case 'triple_dash': if (self.patternTimer % 30 === 0) { self.tripleDash(); } break; case 'power_dive': if (self.patternTimer === 1) { self.powerDive(); } break; case 'horizontal_sweep': if (self.patternTimer % 20 === 0) { self.horizontalSweep(); } break; case 'diagonal_attack': if (self.patternTimer % 15 === 0) { self.diagonalAttack(); } break; case 'spiral_sweep': if (self.patternTimer % 12 === 0) { self.spiralSweep(); } break; case 'diagonal_barrage': if (self.patternTimer % 8 === 0) { self.diagonalBarrage(); } break; } }; self.shootLaser = function () { for (var i = 0; i < 3; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 50 + i * 20; bullet.direction = { x: 0, y: 1 }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }; self.shootRandomBullets = function () { var bullet = new BossBullet(); bullet.x = self.x + (Math.random() - 0.5) * 200; bullet.y = self.y + 50; bullet.direction = { x: (Math.random() - 0.5) * 2, y: 1 }; bossBullets.push(bullet); game.addChild(bullet); }; self.shootMegaLaser = function () { for (var i = 0; i < 5; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 50 + i * 15; bullet.direction = { x: 0, y: 1 }; bullet.speed = 8; bossBullets.push(bullet); game.addChild(bullet); } }; self.shootChaosBullets = function () { for (var i = 0; i < 3; i++) { var bullet = new BossBullet(); bullet.x = self.x + (Math.random() - 0.5) * 300; bullet.y = self.y + 50; bullet.direction = { x: (Math.random() - 0.5) * 3, y: 1 }; bullet.speed = 7; bossBullets.push(bullet); game.addChild(bullet); } }; self.tripleDash = function () { var dashTargets = [player.y - 100, player.y, player.y + 100]; for (var j = 0; j < dashTargets.length; j++) { dashTargets[j] = Math.min(dashTargets[j], arenaBottom - 150); } for (var i = 0; i < dashTargets.length; i++) { tween(self, { y: dashTargets[i] }, { duration: 200, delay: i * 100 }); } }; self.diveAttack = function () { tween(self, { y: arenaBottom - 100 }, { duration: 800, easing: tween.easeIn, onFinish: function onFinish() { LK.setTimeout(function () { tween(self, { y: arenaTop + 200 }, { duration: 600, easing: tween.easeOut }); }, 300); } }); }; self.powerDive = function () { tween(self, { y: arenaBottom - 80 }, { duration: 600, easing: tween.easeIn, onFinish: function onFinish() { for (var i = 0; i < 5; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 2) * 40; bullet.y = self.y; bullet.direction = { x: (i - 2) * 0.3, y: -1 }; bullet.speed = 5; bossBullets.push(bullet); game.addChild(bullet); } LK.setTimeout(function () { tween(self, { y: arenaTop + 200 }, { duration: 400, easing: tween.easeOut }); }, 200); } }); }; self.horizontalSweep = function () { var targetX = self.x < 1024 ? arenaRight - 200 : arenaLeft + 200; tween(self, { x: targetX }, { duration: 1000, easing: tween.easeInOut }); for (var i = 0; i < 2; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 0.5) * 60; bullet.y = self.y + 50; bullet.direction = { x: 0, y: 1 }; bullet.speed = 5; bossBullets.push(bullet); game.addChild(bullet); } }; self.diagonalAttack = function () { var targetX = self.x < 1024 ? arenaRight - 150 : arenaLeft + 150; var targetY = Math.min(self.y + 100, arenaBottom - 200); tween(self, { x: targetX, y: targetY }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { x: 1024, y: arenaTop + 200 }, { duration: 600, easing: tween.easeOut }); } }); for (var i = 0; i < 3; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 40; bullet.direction = { x: (i - 1) * 0.5, y: 1 }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }; self.spiralSweep = function () { var targetX = self.x < 1024 ? arenaRight - 150 : arenaLeft + 150; tween(self, { x: targetX }, { duration: 600, easing: tween.easeInOut }); for (var i = 0; i < 4; i++) { var angle = (self.patternTimer * 0.2 + i * Math.PI / 2) % (Math.PI * 2); var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 50; bullet.direction = { x: Math.cos(angle) * 0.8, y: Math.sin(angle) * 0.8 + 0.5 }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }; self.diagonalBarrage = function () { var targets = [{ x: arenaLeft + 200, y: arenaTop + 300 }, { x: arenaRight - 200, y: arenaTop + 300 }, { x: 1024, y: arenaTop + 150 }]; var targetIndex = Math.floor(self.patternTimer / 30) % targets.length; var target = targets[targetIndex]; tween(self, { x: target.x, y: target.y }, { duration: 400, easing: tween.easeInOut }); for (var i = 0; i < 5; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 2) * 30; bullet.y = self.y + 50; var angleToPlayer = Math.atan2(player.y - bullet.y, player.x - bullet.x); bullet.direction = { x: Math.cos(angleToPlayer + (i - 2) * 0.3), y: Math.sin(angleToPlayer + (i - 2) * 0.3) }; bullet.speed = 7; bossBullets.push(bullet); game.addChild(bullet); } }; self.startPhase2Flash = function () { var flashToYellow = function flashToYellow() { tween(bossGraphics, { tint: 0xFFFF00 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToRed }); }; var flashToRed = function flashToRed() { tween(bossGraphics, { tint: 0xFF0000 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToYellow }); }; flashToYellow(); }; return self; }); var Boss2 = Boss.expand(function () { var self = Boss.call(this); var bossGraphics = self.attachAsset('boss2', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0 }); self.maxHealth = 400; self.health = self.maxHealth; self.attackPatterns = [{ duration: 90, action: 'circle_pattern' }, { duration: 60, action: 'rapid_fire' }, { duration: 120, action: 'teleport' }, { duration: 80, action: 'vulnerable' }]; self.attackPatternsPhase2 = [{ duration: 70, action: 'double_circle' }, { duration: 45, action: 'homing_barrage' }, { duration: 90, action: 'shadow_teleport' }, { duration: 60, action: 'vulnerable' }]; self.executePattern = function () { var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2; var currentPattern = patterns[self.patternIndex]; if (self.patternTimer >= currentPattern.duration) { self.patternTimer = 0; self.patternIndex = (self.patternIndex + 1) % patterns.length; } switch (currentPattern.action) { case 'circle_pattern': if (self.patternTimer % 15 === 0) { self.shootCircle(); } break; case 'rapid_fire': if (self.patternTimer % 8 === 0) { self.shootAtPlayer(); } break; case 'teleport': if (self.patternTimer === 1) { var newX = arenaLeft + 200 + Math.random() * (arenaRight - arenaLeft - 400); tween(self, { x: newX }, { duration: 300 }); } break; case 'vulnerable': self.isVulnerable = true; self.vulnerabilityTimer = 80; tween(bossGraphics, { alpha: 0.6 }, { duration: 200 }); break; case 'double_circle': if (self.patternTimer % 12 === 0) { self.shootDoubleCircle(); } break; case 'homing_barrage': if (self.patternTimer % 6 === 0) { self.shootHomingBarrage(); } break; case 'shadow_teleport': if (self.patternTimer % 20 === 0) { self.shadowTeleport(); } break; } }; self.shootCircle = function () { for (var i = 0; i < 8; i++) { var angle = i / 8 * Math.PI * 2; var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; bullet.direction = { x: Math.cos(angle), y: Math.sin(angle) }; bossBullets.push(bullet); game.addChild(bullet); } }; self.shootAtPlayer = function () { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 50; var dx = player.x - self.x; var dy = player.y - self.y; var length = Math.sqrt(dx * dx + dy * dy); bullet.direction = { x: dx / length, y: dy / length }; bossBullets.push(bullet); game.addChild(bullet); }; self.shootDoubleCircle = function () { for (var ring = 0; ring < 2; ring++) { for (var i = 0; i < 6; i++) { var angle = i / 6 * Math.PI * 2 + ring * Math.PI / 6; var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; bullet.direction = { x: Math.cos(angle), y: Math.sin(angle) }; bullet.speed = 4 + ring * 2; bossBullets.push(bullet); game.addChild(bullet); } } }; self.shootHomingBarrage = function () { for (var i = 0; i < 2; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 0.5) * 40; bullet.y = self.y + 50; var dx = player.x - bullet.x; var dy = player.y - bullet.y; var length = Math.sqrt(dx * dx + dy * dy); bullet.direction = { x: dx / length, y: dy / length }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }; self.shadowTeleport = function () { var teleportPositions = [{ x: arenaLeft + 150, y: self.y }, { x: arenaRight - 150, y: self.y }, { x: 1024, y: arenaTop + 150 }]; var randomPos = teleportPositions[Math.floor(Math.random() * teleportPositions.length)]; tween(self, { x: randomPos.x, y: randomPos.y }, { duration: 250 }); }; self.startPhase2Flash = function () { var flashToYellow = function flashToYellow() { tween(bossGraphics, { tint: 0xFFFF00 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToRed }); }; var flashToRed = function flashToRed() { tween(bossGraphics, { tint: 0xFF0000 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToYellow }); }; flashToYellow(); }; return self; }); var Boss1 = Boss.expand(function () { var self = Boss.call(this); var bossGraphics = self.attachAsset('boss1', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0 }); self.attackPatterns = [{ duration: 120, action: 'move_left' }, { duration: 60, action: 'shoot_spread' }, { duration: 120, action: 'move_right' }, { duration: 60, action: 'shoot_spread' }, { duration: 90, action: 'vulnerable' }]; self.attackPatternsPhase2 = [{ duration: 80, action: 'speed_dash' }, { duration: 40, action: 'rapid_spread' }, { duration: 80, action: 'speed_dash' }, { duration: 40, action: 'rapid_spread' }, { duration: 70, action: 'vulnerable' }]; self.executePattern = function () { var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2; var currentPattern = patterns[self.patternIndex]; if (self.patternTimer >= currentPattern.duration) { self.patternTimer = 0; self.patternIndex = (self.patternIndex + 1) % patterns.length; } switch (currentPattern.action) { case 'move_left': if (self.x > arenaLeft + 100) { self.x -= 2; } break; case 'move_right': if (self.x < arenaRight - 100) { self.x += 2; } break; case 'shoot_spread': if (self.patternTimer % 20 === 0) { self.shootSpread(); } break; case 'vulnerable': self.isVulnerable = true; self.vulnerabilityTimer = 90; tween(bossGraphics, { alpha: 0.7 }, { duration: 200 }); break; case 'speed_dash': if (self.x > arenaLeft + 100 && self.patternTimer < 40) { self.x -= 4; } else if (self.x < arenaRight - 100 && self.patternTimer >= 40) { self.x += 4; } break; case 'rapid_spread': if (self.patternTimer % 10 === 0) { self.shootRapidSpread(); } break; } }; self.shootSpread = function () { for (var i = -2; i <= 2; i++) { var bullet = new BossBullet(); bullet.x = self.x + i * 30; bullet.y = self.y + 50; bullet.direction = { x: i * 0.3, y: 1 }; bossBullets.push(bullet); game.addChild(bullet); } }; self.shootRapidSpread = function () { for (var i = -3; i <= 3; i++) { var bullet = new BossBullet(); bullet.x = self.x + i * 25; bullet.y = self.y + 50; bullet.direction = { x: i * 0.4, y: 1 }; bullet.speed = 6; bossBullets.push(bullet); game.addChild(bullet); } }; self.startPhase2Flash = function () { var flashToYellow = function flashToYellow() { tween(bossGraphics, { tint: 0xFFFF00 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToRed }); }; var flashToRed = function flashToRed() { tween(bossGraphics, { tint: 0xFF0000 }, { duration: 800, easing: tween.easeInOut, onFinish: flashToYellow }); }; flashToYellow(); }; return self; }); var BossBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bossBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; self.damage = 15; self.direction = { x: 0, y: 1 }; self.update = function () { self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; }; return self; }); var BossIntroScreen = Container.expand(function () { var self = Container.call(this); self.showIntro = function (bossName, introAssetId) { var introGraphics = self.attachAsset(introAssetId, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, alpha: 0 }); tween(introGraphics, { alpha: 1 }, { duration: 800, easing: tween.easeInOut }); LK.setTimeout(function () { tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); }, 4000); }; return self; }); var DoubleShotPowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('doubleShotPowerUp', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.collected = false; self.update = function () { self.y += self.speed; }; return self; }); var HealthPowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('healthPowerUp', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.collected = false; self.update = function () { self.y += self.speed; }; return self; }); var IntroScreen = Container.expand(function () { var self = Container.call(this); var logoGraphics = self.attachAsset('gameLogo', { anchorX: 0.5, anchorY: 0.5 }); logoGraphics.x = 0; logoGraphics.y = -200; logoGraphics.alpha = 0; tween(logoGraphics, { alpha: 1 }, { duration: 800 }); return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerLeftGraphics = self.attachAsset('playerLeft', { anchorX: 0.5, anchorY: 0.5, visible: true, alpha: 1.0 }); var playerRightGraphics = self.attachAsset('playerRight', { anchorX: 0.5, anchorY: 0.5, visible: true, alpha: 1.0 }); self.maxHealth = 150; self.health = self.maxHealth; self.speed = 8; self.canShoot = false; self.shootCooldown = 0; self.lastX = 0; self.facing = 'left'; self.hasDoubleShot = false; self.doubleShotTimer = 0; self.power = 10; self.updateFacing = function () { var newFacing = self.facing; if (self.x < self.lastX - 5) { newFacing = 'left'; } else if (self.x > self.lastX + 5) { newFacing = 'right'; } if (newFacing !== self.facing) { self.facing = newFacing; playerLeftGraphics.visible = newFacing === 'left'; playerRightGraphics.visible = newFacing === 'right'; } self.lastX = self.x; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xff0000, 500); LK.getSound('playerHit').play(); }; self.shoot = function () { if (self.canShoot && self.shootCooldown <= 0) { if (self.hasDoubleShot) { var bullet1 = new PlayerBullet(); bullet1.x = self.x - 20; bullet1.y = self.y - 50; bullet1.damage = self.power; playerBullets.push(bullet1); game.addChild(bullet1); var bullet2 = new PlayerBullet(); bullet2.x = self.x + 20; bullet2.y = self.y - 50; bullet2.damage = self.power; playerBullets.push(bullet2); game.addChild(bullet2); } else { var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - 50; bullet.damage = self.power; playerBullets.push(bullet); game.addChild(bullet); } // Keep constant power for all shots self.shootCooldown = 9; LK.getSound('playerShoot').play(); } }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.doubleShotTimer > 0) { self.doubleShotTimer--; if (self.doubleShotTimer <= 0) { self.hasDoubleShot = false; } } // Auto-shoot very fast - every 3 frames instead of every frame if (LK.ticks % 3 === 0) { self.shoot(); } self.updateFacing(); }; self.collectDoubleShotPowerUp = function () { self.hasDoubleShot = true; self.doubleShotTimer = 600; LK.effects.flashObject(self, 0x00ff00, 300); }; self.collectHealthPowerUp = function () { var recoveryAmount = Math.ceil(self.maxHealth * 0.2); if (self.health >= self.maxHealth) { self.maxHealth += recoveryAmount; self.health = self.maxHealth; } else { self.health = Math.min(self.maxHealth, self.health + recoveryAmount); } LK.effects.flashObject(self, 0x00ff00, 500); }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.damage = 10; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ var gameStarted = false; var introScreen = null; var arena = game.attachAsset('arena', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, visible: false }); 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; var player = null; var playerBullets = []; var bossBullets = []; var doubleShotPowerUps = []; var healthPowerUps = []; var powerUpSpawnTimer = 0; var currentBoss = null; var currentBossIndex = 0; var bossConfigs = [{ "class": Boss1, name: "ZombiEagle" }, { "class": Boss2, name: "Cursed Ghost" }, { "class": Boss3, name: "Stone Gargoyle" }, { "class": Boss4, name: "Grey Dragon" }]; var playerHealthBar = null; var bossHealthBarContainer = null; var bossHealthBarBg = null; var bossHealthBarFill = null; var bossNameText = null; var nextStageButton = null; function showNextStageButton() { // If button already exists, just show it if (nextStageButton) { nextStageButton.visible = true; return; } // Create Next Stage button as clickable asset nextStageButton = game.attachAsset('nextStageButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); // Add button text overlay var buttonText = new Text2('Next Stage', { size: 60, fill: '#FFFF00', font: 'monospace', stroke: '#000000', strokeThickness: 4 }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 0; buttonText.y = 0; nextStageButton.addChild(buttonText); // Add button functionality nextStageButton.down = function (x, y, obj) { // Progress to next boss currentBossIndex++; console.log("Progressing to boss index:", currentBossIndex); // Hide the button instead of destroying it if (nextStageButton) { nextStageButton.visible = false; } // Spawn next boss with delay LK.setTimeout(function () { try { spawnNextBoss(); } catch (error) { console.error("Error spawning next boss:", error); } }, 500); }; } // Show intro screen introScreen = game.addChild(new IntroScreen()); introScreen.x = 1024; introScreen.y = 1366; // Start music when game logo appears LK.playMusic('epicboss'); // Auto-start game after 4 seconds LK.setTimeout(function () { if (!gameStarted) { startMainGame(); if (introScreen) { introScreen.destroy(); introScreen = null; } } }, 4000); function startMainGame() { gameStarted = true; arena.visible = true; game.setChildIndex(arena, 0); player = game.addChild(new Player()); player.x = 1024; player.y = 1366; player.lastX = player.x; game.setChildIndex(player, game.children.length - 1); playerHealthBar = new Text2('Health: 100', { size: 48, fill: '#FFFFFF', font: 'monospace', stroke: '#000000', strokeThickness: 6 }); playerHealthBar.x = arenaLeft + 50; playerHealthBar.y = arenaTop + 100; game.addChild(playerHealthBar); bossHealthBarContainer = new Container(); bossHealthBarContainer.x = 1024; bossHealthBarContainer.y = arenaTop + 50; game.addChild(bossHealthBarContainer); bossHealthBarBg = bossHealthBarContainer.attachAsset('bossHealthBarBg', { anchorX: 0.5, anchorY: 0.5 }); bossHealthBarFill = bossHealthBarContainer.attachAsset('bossHealthBarFill', { anchorX: 0.5, anchorY: 0.5 }); bossNameText = new Text2('ZombiEagle', { size: 56, fill: '#FFFF00', font: 'monospace', stroke: '#000000', strokeThickness: 6 }); bossNameText.anchor.set(0.5, 0); bossNameText.x = 1024; bossNameText.y = arenaTop + 10; game.addChild(bossNameText); spawnNextBoss(); } function spawnNextBoss() { console.log("Attempting to spawn boss at index", currentBossIndex, "of", bossConfigs.length, "total bosses"); if (currentBossIndex >= bossConfigs.length) { console.log("All bosses defeated in spawnNextBoss, currentBossIndex:", currentBossIndex); // Only show win if we've actually defeated all 4 bosses (indices 0,1,2,3) if (currentBossIndex >= 4) { LK.showYouWin(); } return; } if (!bossConfigs[currentBossIndex]) { console.error("Invalid boss index:", currentBossIndex, "available bosses:", bossConfigs.length); return; } if (currentBoss) { currentBoss.destroy(); currentBoss = null; } for (var i = bossBullets.length - 1; i >= 0; i--) { bossBullets[i].destroy(); bossBullets.splice(i, 1); } var bossConfig = bossConfigs[currentBossIndex]; var bossIntroScreen = game.addChild(new BossIntroScreen()); bossIntroScreen.x = 1024; bossIntroScreen.y = 1366; var introAssetId = 'boss' + (currentBossIndex + 1) + 'Intro'; bossIntroScreen.showIntro(bossConfig.name, introAssetId); LK.setTimeout(function () { try { var arenaAssetName = 'arena'; if (currentBossIndex === 1) { arenaAssetName = 'arena2'; } else if (currentBossIndex === 2) { arenaAssetName = 'arena3'; } else if (currentBossIndex === 3) { arenaAssetName = 'arena4'; } if (arena) { arena.destroy(); arena = null; } arena = game.attachAsset(arenaAssetName, { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, visible: true }); game.setChildIndex(arena, 0); arenaLeft = arena.x - arena.width / 2; arenaRight = arena.x + arena.width / 2; arenaTop = arena.y - arena.height / 2; arenaBottom = arena.y + arena.height / 2; currentBoss = game.addChild(new bossConfig["class"]()); currentBoss.x = 1024; currentBoss.y = arenaTop + 200; bossNameText.setText(bossConfig.name); if (player) { player.x = 1024; player.y = 1366; player.lastX = player.x; } if (bossHealthBarContainer) { bossHealthBarContainer.y = arenaTop + 50; } if (bossNameText) { bossNameText.y = arenaTop + 10; } if (playerHealthBar) { playerHealthBar.x = arenaLeft + 50; playerHealthBar.y = arenaTop + 100; } // Enable player shooting when boss intro ends and boss spawns if (player) { player.canShoot = true; } console.log("Successfully spawned boss", currentBossIndex + 1); } catch (error) { console.error("Error during boss spawn:", error); } }, 4000); } var dragActive = false; game.down = function (x, y, obj) { if (gameStarted) { dragActive = true; player.shoot(); } }; game.up = function (x, y, obj) { if (gameStarted) { dragActive = false; } }; game.move = function (x, y, obj) { if (gameStarted && dragActive) { var localPos = game.toLocal({ x: x, y: y }); player.x = Math.max(arenaLeft + 60, Math.min(arenaRight - 60, localPos.x)); player.y = Math.max(arenaTop + 60, Math.min(arenaBottom - 60, localPos.y)); } }; game.update = function () { if (!gameStarted) { return; } for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (bullet.y < arenaTop - 50) { bullet.destroy(); playerBullets.splice(i, 1); continue; } if (currentBoss && bullet.intersects(currentBoss)) { currentBoss.takeDamage(bullet.damage); bullet.destroy(); playerBullets.splice(i, 1); continue; } } for (var i = bossBullets.length - 1; i >= 0; i--) { var bullet = bossBullets[i]; if (bullet.x < arenaLeft - 50 || bullet.x > arenaRight + 50 || bullet.y < arenaTop - 50 || bullet.y > arenaBottom + 50) { bullet.destroy(); bossBullets.splice(i, 1); continue; } if (bullet.intersects(player)) { player.takeDamage(bullet.damage); bullet.destroy(); bossBullets.splice(i, 1); continue; } } powerUpSpawnTimer++; if (powerUpSpawnTimer >= 900 && Math.random() < 0.04) { var powerUpType = Math.random() < 0.5 ? 'double' : 'health'; if (powerUpType === 'double') { var powerUp = new DoubleShotPowerUp(); powerUp.x = arenaLeft + 100 + Math.random() * (arenaRight - arenaLeft - 200); powerUp.y = arenaTop - 50; doubleShotPowerUps.push(powerUp); game.addChild(powerUp); } else { var healthPowerUp = new HealthPowerUp(); healthPowerUp.x = arenaLeft + 100 + Math.random() * (arenaRight - arenaLeft - 200); healthPowerUp.y = arenaTop - 50; healthPowerUps.push(healthPowerUp); game.addChild(healthPowerUp); } powerUpSpawnTimer = 0; } for (var i = doubleShotPowerUps.length - 1; i >= 0; i--) { var powerUp = doubleShotPowerUps[i]; if (powerUp.y > arenaBottom + 50) { powerUp.destroy(); doubleShotPowerUps.splice(i, 1); continue; } if (!powerUp.collected && powerUp.intersects(player)) { player.collectDoubleShotPowerUp(); powerUp.collected = true; tween(powerUp, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { powerUp.destroy(); } }); doubleShotPowerUps.splice(i, 1); continue; } } for (var i = healthPowerUps.length - 1; i >= 0; i--) { var healthPowerUp = healthPowerUps[i]; if (healthPowerUp.y > arenaBottom + 50) { healthPowerUp.destroy(); healthPowerUps.splice(i, 1); continue; } if (!healthPowerUp.collected && healthPowerUp.intersects(player)) { player.collectHealthPowerUp(); healthPowerUp.collected = true; tween(healthPowerUp, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { healthPowerUp.destroy(); } }); healthPowerUps.splice(i, 1); continue; } } playerHealthBar.setText('Health: ' + player.health); if (currentBoss) { var healthPercentage = currentBoss.health / currentBoss.maxHealth; bossHealthBarFill.width = 400 * healthPercentage; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
self.maxHealth = 300;
self.health = self.maxHealth;
self.patternIndex = 0;
self.patternTimer = 0;
self.isVulnerable = false;
self.vulnerabilityTimer = 0;
self.attackPatterns = [];
self.attackPatternsPhase2 = [];
self.currentPhase = 1;
self.lastHealthPercentage = 1.0;
self.takeDamage = function (damage) {
if (self.isVulnerable) {
self.health -= damage;
LK.effects.flashObject(self, 0xffffff, 200);
LK.getSound('bossHit').play();
if (self.health <= 0) {
self.health = 0;
self.onDefeat();
}
}
};
self.onDefeat = function () {
LK.getSound('bossDefeat').play();
// Make boss vanish and stop attacking
self.visible = false;
self.alpha = 0;
// Stop player shooting when boss is defeated
if (player) {
player.canShoot = false;
player.health = player.maxHealth;
}
console.log("Boss defeated. Current index:", currentBossIndex, "Total bosses:", bossConfigs.length);
// Check if this is the final boss (Boss4 at index 3)
if (currentBossIndex === 3) {
console.log("All 4 bosses defeated - showing win screen");
LK.showYouWin();
} else {
// Show Next Stage button instead of auto-progressing
showNextStageButton();
}
};
self.executePattern = function () {
// Override in specific boss classes
};
self.update = function () {
// Stop all attacks and patterns if health is 0
if (self.health <= 0) {
return;
}
self.patternTimer++;
if (self.vulnerabilityTimer > 0) {
self.vulnerabilityTimer--;
if (self.vulnerabilityTimer <= 0) {
self.isVulnerable = false;
}
}
// Check for phase transition at 50% health
var currentHealthPercentage = self.health / self.maxHealth;
if (self.currentPhase === 1 && currentHealthPercentage <= 0.5 && self.lastHealthPercentage > 0.5) {
self.currentPhase = 2;
self.patternIndex = 0;
self.patternTimer = 0;
LK.effects.flashObject(self, 0xffffff, 1000);
// Start phase 2 flashing effect
self.startPhase2Flash();
}
self.lastHealthPercentage = currentHealthPercentage;
self.executePattern();
};
return self;
});
var Boss4 = Boss.expand(function () {
var self = Boss.call(this);
var bossGraphics = self.attachAsset('boss4', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0
});
self.maxHealth = 600;
self.health = self.maxHealth;
self.attackPatterns = [{
duration: 120,
action: 'ultimate_sweep'
}, {
duration: 100,
action: 'chaos_storm'
}, {
duration: 150,
action: 'teleport_barrage'
}, {
duration: 120,
action: 'gravity_pull'
}, {
duration: 80,
action: 'laser_grid'
}, {
duration: 90,
action: 'vulnerable'
}];
self.attackPatternsPhase2 = [{
duration: 80,
action: 'apocalypse_sweep'
}, {
duration: 60,
action: 'death_spiral'
}, {
duration: 100,
action: 'final_barrage'
}, {
duration: 120,
action: 'dimensional_rift'
}, {
duration: 70,
action: 'omega_grid'
}, {
duration: 60,
action: 'vulnerable'
}];
self.executePattern = function () {
var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2;
var currentPattern = patterns[self.patternIndex];
if (self.patternTimer >= currentPattern.duration) {
self.patternTimer = 0;
self.patternIndex = (self.patternIndex + 1) % patterns.length;
}
switch (currentPattern.action) {
case 'ultimate_sweep':
if (self.patternTimer % 8 === 0) {
self.ultimateSweep();
}
break;
case 'chaos_storm':
if (self.patternTimer % 4 === 0) {
self.chaosStorm();
}
break;
case 'teleport_barrage':
if (self.patternTimer % 25 === 0) {
self.teleportBarrage();
}
break;
case 'gravity_pull':
if (self.patternTimer === 1) {
self.gravityPull();
}
break;
case 'laser_grid':
if (self.patternTimer % 15 === 0) {
self.laserGrid();
}
break;
case 'vulnerable':
self.isVulnerable = true;
self.vulnerabilityTimer = 90;
tween(bossGraphics, {
alpha: 0.4
}, {
duration: 200
});
break;
case 'apocalypse_sweep':
if (self.patternTimer % 5 === 0) {
self.apocalypseSweep();
}
break;
case 'death_spiral':
if (self.patternTimer % 6 === 0) {
self.deathSpiral();
}
break;
case 'final_barrage':
if (self.patternTimer % 3 === 0) {
self.finalBarrage();
}
break;
case 'dimensional_rift':
if (self.patternTimer % 20 === 0) {
self.dimensionalRift();
}
break;
case 'omega_grid':
if (self.patternTimer % 10 === 0) {
self.omegaGrid();
}
break;
}
};
self.ultimateSweep = function () {
for (var i = 0; i < 7; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 3) * 40;
bullet.y = self.y + 50;
bullet.direction = {
x: (i - 3) * 0.2,
y: 1
};
bullet.speed = 7;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.chaosStorm = function () {
for (var i = 0; i < 4; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (Math.random() - 0.5) * 400;
bullet.y = self.y + 50;
bullet.direction = {
x: (Math.random() - 0.5) * 4,
y: 0.8 + Math.random() * 0.4
};
bullet.speed = 6 + Math.random() * 3;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.teleportBarrage = function () {
var teleportPositions = [{
x: arenaLeft + 200,
y: arenaTop + 250
}, {
x: arenaRight - 200,
y: arenaTop + 250
}, {
x: 1024,
y: arenaTop + 150
}, {
x: arenaLeft + 300,
y: arenaTop + 400
}, {
x: arenaRight - 300,
y: arenaTop + 400
}];
var randomPos = teleportPositions[Math.floor(Math.random() * teleportPositions.length)];
tween(self, {
x: randomPos.x,
y: randomPos.y
}, {
duration: 200
});
// Massive bullet spread after teleport
LK.setTimeout(function () {
for (var i = 0; i < 12; i++) {
var angle = i / 12 * Math.PI * 2;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
bullet.speed = 5;
bossBullets.push(bullet);
game.addChild(bullet);
}
}, 300);
};
self.gravityPull = function () {
// Pull effect - move towards player position over time
var targetX = Math.max(arenaLeft + 200, Math.min(arenaRight - 200, player.x));
var targetY = Math.max(arenaTop + 200, Math.min(arenaBottom - 300, player.y - 150));
tween(self, {
x: targetX,
y: targetY
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Explosion of bullets in all directions
for (var i = 0; i < 16; i++) {
var angle = i / 16 * Math.PI * 2;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
}
});
};
self.laserGrid = function () {
// Create grid pattern of bullets
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 5; col++) {
var bullet = new BossBullet();
bullet.x = arenaLeft + 200 + col * 300;
bullet.y = self.y + row * 80;
bullet.direction = {
x: 0,
y: 1
};
bullet.speed = 4 + row;
bossBullets.push(bullet);
game.addChild(bullet);
}
}
};
self.apocalypseSweep = function () {
// Even more intense sweep for phase 2
for (var i = 0; i < 9; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 4) * 35;
bullet.y = self.y + 50;
bullet.direction = {
x: (i - 4) * 0.25,
y: 1
};
bullet.speed = 8;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.deathSpiral = function () {
// Rotating spiral pattern
var spiralCount = 6;
for (var i = 0; i < spiralCount; i++) {
var angle = (self.patternTimer * 0.3 + i * Math.PI * 2 / spiralCount) % (Math.PI * 2);
var bullet = new BossBullet();
bullet.x = self.x + Math.cos(angle) * 100;
bullet.y = self.y + Math.sin(angle) * 50 + 50;
bullet.direction = {
x: Math.cos(angle + Math.PI / 4) * 0.8,
y: Math.sin(angle + Math.PI / 4) * 0.8 + 0.6
};
bullet.speed = 7;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.finalBarrage = function () {
// Overwhelming bullet hell
for (var i = 0; i < 6; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (Math.random() - 0.5) * 500;
bullet.y = self.y + Math.random() * 100;
var angleToPlayer = Math.atan2(player.y - bullet.y, player.x - bullet.x);
bullet.direction = {
x: Math.cos(angleToPlayer + (Math.random() - 0.5) * 0.8),
y: Math.sin(angleToPlayer + (Math.random() - 0.5) * 0.8)
};
bullet.speed = 5 + Math.random() * 4;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.dimensionalRift = function () {
// Teleport to multiple positions rapidly
var positions = [{
x: arenaLeft + 150,
y: arenaTop + 200
}, {
x: arenaRight - 150,
y: arenaTop + 200
}, {
x: 1024,
y: arenaTop + 350
}, {
x: arenaLeft + 300,
y: arenaTop + 500
}, {
x: arenaRight - 300,
y: arenaTop + 500
}];
for (var p = 0; p < 3; p++) {
var pos = positions[Math.floor(Math.random() * positions.length)];
LK.setTimeout(function () {
tween(self, {
x: pos.x,
y: pos.y
}, {
duration: 150
});
// Shoot bullets from each position
for (var j = 0; j < 8; j++) {
var angle = j / 8 * Math.PI * 2;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
}, p * 200);
}
};
self.omegaGrid = function () {
// Ultimate grid attack
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 7; col++) {
var bullet = new BossBullet();
bullet.x = arenaLeft + 150 + col * 250;
bullet.y = self.y + row * 60;
bullet.direction = {
x: (col - 3) * 0.1,
y: 1
};
bullet.speed = 5 + row;
bossBullets.push(bullet);
game.addChild(bullet);
}
}
};
self.startPhase2Flash = function () {
var flashToGold = function flashToGold() {
tween(bossGraphics, {
tint: 0xFFD700
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: flashToWhite
});
};
var flashToWhite = function flashToWhite() {
tween(bossGraphics, {
tint: 0xFFFFFF
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: flashToGold
});
};
flashToGold();
};
return self;
});
var Boss3 = Boss.expand(function () {
var self = Boss.call(this);
var bossGraphics = self.attachAsset('boss3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0
});
self.maxHealth = 250;
self.health = self.maxHealth;
self.attackPatterns = [{
duration: 60,
action: 'laser_sweep'
}, {
duration: 50,
action: 'bullet_hell'
}, {
duration: 80,
action: 'dash_attack'
}, {
duration: 100,
action: 'dive_attack'
}, {
duration: 70,
action: 'horizontal_sweep'
}, {
duration: 80,
action: 'diagonal_attack'
}, {
duration: 80,
action: 'vulnerable'
}];
self.attackPatternsPhase2 = [{
duration: 50,
action: 'mega_laser_sweep'
}, {
duration: 40,
action: 'chaos_bullets'
}, {
duration: 70,
action: 'triple_dash'
}, {
duration: 80,
action: 'power_dive'
}, {
duration: 50,
action: 'spiral_sweep'
}, {
duration: 60,
action: 'diagonal_barrage'
}, {
duration: 60,
action: 'vulnerable'
}];
self.executePattern = function () {
var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2;
var currentPattern = patterns[self.patternIndex];
if (self.patternTimer >= currentPattern.duration) {
self.patternTimer = 0;
self.patternIndex = (self.patternIndex + 1) % patterns.length;
}
switch (currentPattern.action) {
case 'laser_sweep':
if (self.patternTimer % 15 === 0) {
self.shootLaser();
}
break;
case 'bullet_hell':
if (self.patternTimer % 8 === 0) {
self.shootRandomBullets();
}
break;
case 'dash_attack':
if (self.patternTimer === 1) {
var targetY = Math.min(player.y, arenaBottom - 150);
tween(self, {
y: targetY
}, {
duration: 500
});
}
break;
case 'dive_attack':
if (self.patternTimer === 1) {
self.diveAttack();
}
break;
case 'vulnerable':
self.isVulnerable = true;
self.vulnerabilityTimer = 60;
tween(bossGraphics, {
alpha: 0.5
}, {
duration: 200
});
break;
case 'mega_laser_sweep':
if (self.patternTimer % 10 === 0) {
self.shootMegaLaser();
}
break;
case 'chaos_bullets':
if (self.patternTimer % 6 === 0) {
self.shootChaosBullets();
}
break;
case 'triple_dash':
if (self.patternTimer % 30 === 0) {
self.tripleDash();
}
break;
case 'power_dive':
if (self.patternTimer === 1) {
self.powerDive();
}
break;
case 'horizontal_sweep':
if (self.patternTimer % 20 === 0) {
self.horizontalSweep();
}
break;
case 'diagonal_attack':
if (self.patternTimer % 15 === 0) {
self.diagonalAttack();
}
break;
case 'spiral_sweep':
if (self.patternTimer % 12 === 0) {
self.spiralSweep();
}
break;
case 'diagonal_barrage':
if (self.patternTimer % 8 === 0) {
self.diagonalBarrage();
}
break;
}
};
self.shootLaser = function () {
for (var i = 0; i < 3; i++) {
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 50 + i * 20;
bullet.direction = {
x: 0,
y: 1
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.shootRandomBullets = function () {
var bullet = new BossBullet();
bullet.x = self.x + (Math.random() - 0.5) * 200;
bullet.y = self.y + 50;
bullet.direction = {
x: (Math.random() - 0.5) * 2,
y: 1
};
bossBullets.push(bullet);
game.addChild(bullet);
};
self.shootMegaLaser = function () {
for (var i = 0; i < 5; i++) {
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 50 + i * 15;
bullet.direction = {
x: 0,
y: 1
};
bullet.speed = 8;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.shootChaosBullets = function () {
for (var i = 0; i < 3; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (Math.random() - 0.5) * 300;
bullet.y = self.y + 50;
bullet.direction = {
x: (Math.random() - 0.5) * 3,
y: 1
};
bullet.speed = 7;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.tripleDash = function () {
var dashTargets = [player.y - 100, player.y, player.y + 100];
for (var j = 0; j < dashTargets.length; j++) {
dashTargets[j] = Math.min(dashTargets[j], arenaBottom - 150);
}
for (var i = 0; i < dashTargets.length; i++) {
tween(self, {
y: dashTargets[i]
}, {
duration: 200,
delay: i * 100
});
}
};
self.diveAttack = function () {
tween(self, {
y: arenaBottom - 100
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(self, {
y: arenaTop + 200
}, {
duration: 600,
easing: tween.easeOut
});
}, 300);
}
});
};
self.powerDive = function () {
tween(self, {
y: arenaBottom - 80
}, {
duration: 600,
easing: tween.easeIn,
onFinish: function onFinish() {
for (var i = 0; i < 5; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 2) * 40;
bullet.y = self.y;
bullet.direction = {
x: (i - 2) * 0.3,
y: -1
};
bullet.speed = 5;
bossBullets.push(bullet);
game.addChild(bullet);
}
LK.setTimeout(function () {
tween(self, {
y: arenaTop + 200
}, {
duration: 400,
easing: tween.easeOut
});
}, 200);
}
});
};
self.horizontalSweep = function () {
var targetX = self.x < 1024 ? arenaRight - 200 : arenaLeft + 200;
tween(self, {
x: targetX
}, {
duration: 1000,
easing: tween.easeInOut
});
for (var i = 0; i < 2; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 0.5) * 60;
bullet.y = self.y + 50;
bullet.direction = {
x: 0,
y: 1
};
bullet.speed = 5;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.diagonalAttack = function () {
var targetX = self.x < 1024 ? arenaRight - 150 : arenaLeft + 150;
var targetY = Math.min(self.y + 100, arenaBottom - 200);
tween(self, {
x: targetX,
y: targetY
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
x: 1024,
y: arenaTop + 200
}, {
duration: 600,
easing: tween.easeOut
});
}
});
for (var i = 0; i < 3; i++) {
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
bullet.direction = {
x: (i - 1) * 0.5,
y: 1
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.spiralSweep = function () {
var targetX = self.x < 1024 ? arenaRight - 150 : arenaLeft + 150;
tween(self, {
x: targetX
}, {
duration: 600,
easing: tween.easeInOut
});
for (var i = 0; i < 4; i++) {
var angle = (self.patternTimer * 0.2 + i * Math.PI / 2) % (Math.PI * 2);
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 50;
bullet.direction = {
x: Math.cos(angle) * 0.8,
y: Math.sin(angle) * 0.8 + 0.5
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.diagonalBarrage = function () {
var targets = [{
x: arenaLeft + 200,
y: arenaTop + 300
}, {
x: arenaRight - 200,
y: arenaTop + 300
}, {
x: 1024,
y: arenaTop + 150
}];
var targetIndex = Math.floor(self.patternTimer / 30) % targets.length;
var target = targets[targetIndex];
tween(self, {
x: target.x,
y: target.y
}, {
duration: 400,
easing: tween.easeInOut
});
for (var i = 0; i < 5; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 2) * 30;
bullet.y = self.y + 50;
var angleToPlayer = Math.atan2(player.y - bullet.y, player.x - bullet.x);
bullet.direction = {
x: Math.cos(angleToPlayer + (i - 2) * 0.3),
y: Math.sin(angleToPlayer + (i - 2) * 0.3)
};
bullet.speed = 7;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.startPhase2Flash = function () {
var flashToYellow = function flashToYellow() {
tween(bossGraphics, {
tint: 0xFFFF00
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToRed
});
};
var flashToRed = function flashToRed() {
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToYellow
});
};
flashToYellow();
};
return self;
});
var Boss2 = Boss.expand(function () {
var self = Boss.call(this);
var bossGraphics = self.attachAsset('boss2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0
});
self.maxHealth = 400;
self.health = self.maxHealth;
self.attackPatterns = [{
duration: 90,
action: 'circle_pattern'
}, {
duration: 60,
action: 'rapid_fire'
}, {
duration: 120,
action: 'teleport'
}, {
duration: 80,
action: 'vulnerable'
}];
self.attackPatternsPhase2 = [{
duration: 70,
action: 'double_circle'
}, {
duration: 45,
action: 'homing_barrage'
}, {
duration: 90,
action: 'shadow_teleport'
}, {
duration: 60,
action: 'vulnerable'
}];
self.executePattern = function () {
var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2;
var currentPattern = patterns[self.patternIndex];
if (self.patternTimer >= currentPattern.duration) {
self.patternTimer = 0;
self.patternIndex = (self.patternIndex + 1) % patterns.length;
}
switch (currentPattern.action) {
case 'circle_pattern':
if (self.patternTimer % 15 === 0) {
self.shootCircle();
}
break;
case 'rapid_fire':
if (self.patternTimer % 8 === 0) {
self.shootAtPlayer();
}
break;
case 'teleport':
if (self.patternTimer === 1) {
var newX = arenaLeft + 200 + Math.random() * (arenaRight - arenaLeft - 400);
tween(self, {
x: newX
}, {
duration: 300
});
}
break;
case 'vulnerable':
self.isVulnerable = true;
self.vulnerabilityTimer = 80;
tween(bossGraphics, {
alpha: 0.6
}, {
duration: 200
});
break;
case 'double_circle':
if (self.patternTimer % 12 === 0) {
self.shootDoubleCircle();
}
break;
case 'homing_barrage':
if (self.patternTimer % 6 === 0) {
self.shootHomingBarrage();
}
break;
case 'shadow_teleport':
if (self.patternTimer % 20 === 0) {
self.shadowTeleport();
}
break;
}
};
self.shootCircle = function () {
for (var i = 0; i < 8; i++) {
var angle = i / 8 * Math.PI * 2;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.shootAtPlayer = function () {
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 50;
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
bullet.direction = {
x: dx / length,
y: dy / length
};
bossBullets.push(bullet);
game.addChild(bullet);
};
self.shootDoubleCircle = function () {
for (var ring = 0; ring < 2; ring++) {
for (var i = 0; i < 6; i++) {
var angle = i / 6 * Math.PI * 2 + ring * Math.PI / 6;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.direction = {
x: Math.cos(angle),
y: Math.sin(angle)
};
bullet.speed = 4 + ring * 2;
bossBullets.push(bullet);
game.addChild(bullet);
}
}
};
self.shootHomingBarrage = function () {
for (var i = 0; i < 2; i++) {
var bullet = new BossBullet();
bullet.x = self.x + (i - 0.5) * 40;
bullet.y = self.y + 50;
var dx = player.x - bullet.x;
var dy = player.y - bullet.y;
var length = Math.sqrt(dx * dx + dy * dy);
bullet.direction = {
x: dx / length,
y: dy / length
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.shadowTeleport = function () {
var teleportPositions = [{
x: arenaLeft + 150,
y: self.y
}, {
x: arenaRight - 150,
y: self.y
}, {
x: 1024,
y: arenaTop + 150
}];
var randomPos = teleportPositions[Math.floor(Math.random() * teleportPositions.length)];
tween(self, {
x: randomPos.x,
y: randomPos.y
}, {
duration: 250
});
};
self.startPhase2Flash = function () {
var flashToYellow = function flashToYellow() {
tween(bossGraphics, {
tint: 0xFFFF00
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToRed
});
};
var flashToRed = function flashToRed() {
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToYellow
});
};
flashToYellow();
};
return self;
});
var Boss1 = Boss.expand(function () {
var self = Boss.call(this);
var bossGraphics = self.attachAsset('boss1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0
});
self.attackPatterns = [{
duration: 120,
action: 'move_left'
}, {
duration: 60,
action: 'shoot_spread'
}, {
duration: 120,
action: 'move_right'
}, {
duration: 60,
action: 'shoot_spread'
}, {
duration: 90,
action: 'vulnerable'
}];
self.attackPatternsPhase2 = [{
duration: 80,
action: 'speed_dash'
}, {
duration: 40,
action: 'rapid_spread'
}, {
duration: 80,
action: 'speed_dash'
}, {
duration: 40,
action: 'rapid_spread'
}, {
duration: 70,
action: 'vulnerable'
}];
self.executePattern = function () {
var patterns = self.currentPhase === 1 ? self.attackPatterns : self.attackPatternsPhase2;
var currentPattern = patterns[self.patternIndex];
if (self.patternTimer >= currentPattern.duration) {
self.patternTimer = 0;
self.patternIndex = (self.patternIndex + 1) % patterns.length;
}
switch (currentPattern.action) {
case 'move_left':
if (self.x > arenaLeft + 100) {
self.x -= 2;
}
break;
case 'move_right':
if (self.x < arenaRight - 100) {
self.x += 2;
}
break;
case 'shoot_spread':
if (self.patternTimer % 20 === 0) {
self.shootSpread();
}
break;
case 'vulnerable':
self.isVulnerable = true;
self.vulnerabilityTimer = 90;
tween(bossGraphics, {
alpha: 0.7
}, {
duration: 200
});
break;
case 'speed_dash':
if (self.x > arenaLeft + 100 && self.patternTimer < 40) {
self.x -= 4;
} else if (self.x < arenaRight - 100 && self.patternTimer >= 40) {
self.x += 4;
}
break;
case 'rapid_spread':
if (self.patternTimer % 10 === 0) {
self.shootRapidSpread();
}
break;
}
};
self.shootSpread = function () {
for (var i = -2; i <= 2; i++) {
var bullet = new BossBullet();
bullet.x = self.x + i * 30;
bullet.y = self.y + 50;
bullet.direction = {
x: i * 0.3,
y: 1
};
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.shootRapidSpread = function () {
for (var i = -3; i <= 3; i++) {
var bullet = new BossBullet();
bullet.x = self.x + i * 25;
bullet.y = self.y + 50;
bullet.direction = {
x: i * 0.4,
y: 1
};
bullet.speed = 6;
bossBullets.push(bullet);
game.addChild(bullet);
}
};
self.startPhase2Flash = function () {
var flashToYellow = function flashToYellow() {
tween(bossGraphics, {
tint: 0xFFFF00
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToRed
});
};
var flashToRed = function flashToRed() {
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: flashToYellow
});
};
flashToYellow();
};
return self;
});
var BossBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bossBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.damage = 15;
self.direction = {
x: 0,
y: 1
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var BossIntroScreen = Container.expand(function () {
var self = Container.call(this);
self.showIntro = function (bossName, introAssetId) {
var introGraphics = self.attachAsset(introAssetId, {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 0
});
tween(introGraphics, {
alpha: 1
}, {
duration: 800,
easing: tween.easeInOut
});
LK.setTimeout(function () {
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
}, 4000);
};
return self;
});
var DoubleShotPowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('doubleShotPowerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.collected = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var HealthPowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('healthPowerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.collected = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var IntroScreen = Container.expand(function () {
var self = Container.call(this);
var logoGraphics = self.attachAsset('gameLogo', {
anchorX: 0.5,
anchorY: 0.5
});
logoGraphics.x = 0;
logoGraphics.y = -200;
logoGraphics.alpha = 0;
tween(logoGraphics, {
alpha: 1
}, {
duration: 800
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerLeftGraphics = self.attachAsset('playerLeft', {
anchorX: 0.5,
anchorY: 0.5,
visible: true,
alpha: 1.0
});
var playerRightGraphics = self.attachAsset('playerRight', {
anchorX: 0.5,
anchorY: 0.5,
visible: true,
alpha: 1.0
});
self.maxHealth = 150;
self.health = self.maxHealth;
self.speed = 8;
self.canShoot = false;
self.shootCooldown = 0;
self.lastX = 0;
self.facing = 'left';
self.hasDoubleShot = false;
self.doubleShotTimer = 0;
self.power = 10;
self.updateFacing = function () {
var newFacing = self.facing;
if (self.x < self.lastX - 5) {
newFacing = 'left';
} else if (self.x > self.lastX + 5) {
newFacing = 'right';
}
if (newFacing !== self.facing) {
self.facing = newFacing;
playerLeftGraphics.visible = newFacing === 'left';
playerRightGraphics.visible = newFacing === 'right';
}
self.lastX = self.x;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('playerHit').play();
};
self.shoot = function () {
if (self.canShoot && self.shootCooldown <= 0) {
if (self.hasDoubleShot) {
var bullet1 = new PlayerBullet();
bullet1.x = self.x - 20;
bullet1.y = self.y - 50;
bullet1.damage = self.power;
playerBullets.push(bullet1);
game.addChild(bullet1);
var bullet2 = new PlayerBullet();
bullet2.x = self.x + 20;
bullet2.y = self.y - 50;
bullet2.damage = self.power;
playerBullets.push(bullet2);
game.addChild(bullet2);
} else {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
bullet.damage = self.power;
playerBullets.push(bullet);
game.addChild(bullet);
}
// Keep constant power for all shots
self.shootCooldown = 9;
LK.getSound('playerShoot').play();
}
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
if (self.doubleShotTimer > 0) {
self.doubleShotTimer--;
if (self.doubleShotTimer <= 0) {
self.hasDoubleShot = false;
}
}
// Auto-shoot very fast - every 3 frames instead of every frame
if (LK.ticks % 3 === 0) {
self.shoot();
}
self.updateFacing();
};
self.collectDoubleShotPowerUp = function () {
self.hasDoubleShot = true;
self.doubleShotTimer = 600;
LK.effects.flashObject(self, 0x00ff00, 300);
};
self.collectHealthPowerUp = function () {
var recoveryAmount = Math.ceil(self.maxHealth * 0.2);
if (self.health >= self.maxHealth) {
self.maxHealth += recoveryAmount;
self.health = self.maxHealth;
} else {
self.health = Math.min(self.maxHealth, self.health + recoveryAmount);
}
LK.effects.flashObject(self, 0x00ff00, 500);
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.damage = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
var gameStarted = false;
var introScreen = null;
var arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
visible: false
});
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;
var player = null;
var playerBullets = [];
var bossBullets = [];
var doubleShotPowerUps = [];
var healthPowerUps = [];
var powerUpSpawnTimer = 0;
var currentBoss = null;
var currentBossIndex = 0;
var bossConfigs = [{
"class": Boss1,
name: "ZombiEagle"
}, {
"class": Boss2,
name: "Cursed Ghost"
}, {
"class": Boss3,
name: "Stone Gargoyle"
}, {
"class": Boss4,
name: "Grey Dragon"
}];
var playerHealthBar = null;
var bossHealthBarContainer = null;
var bossHealthBarBg = null;
var bossHealthBarFill = null;
var bossNameText = null;
var nextStageButton = null;
function showNextStageButton() {
// If button already exists, just show it
if (nextStageButton) {
nextStageButton.visible = true;
return;
}
// Create Next Stage button as clickable asset
nextStageButton = game.attachAsset('nextStageButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Add button text overlay
var buttonText = new Text2('Next Stage', {
size: 60,
fill: '#FFFF00',
font: 'monospace',
stroke: '#000000',
strokeThickness: 4
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 0;
buttonText.y = 0;
nextStageButton.addChild(buttonText);
// Add button functionality
nextStageButton.down = function (x, y, obj) {
// Progress to next boss
currentBossIndex++;
console.log("Progressing to boss index:", currentBossIndex);
// Hide the button instead of destroying it
if (nextStageButton) {
nextStageButton.visible = false;
}
// Spawn next boss with delay
LK.setTimeout(function () {
try {
spawnNextBoss();
} catch (error) {
console.error("Error spawning next boss:", error);
}
}, 500);
};
}
// Show intro screen
introScreen = game.addChild(new IntroScreen());
introScreen.x = 1024;
introScreen.y = 1366;
// Start music when game logo appears
LK.playMusic('epicboss');
// Auto-start game after 4 seconds
LK.setTimeout(function () {
if (!gameStarted) {
startMainGame();
if (introScreen) {
introScreen.destroy();
introScreen = null;
}
}
}, 4000);
function startMainGame() {
gameStarted = true;
arena.visible = true;
game.setChildIndex(arena, 0);
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
player.lastX = player.x;
game.setChildIndex(player, game.children.length - 1);
playerHealthBar = new Text2('Health: 100', {
size: 48,
fill: '#FFFFFF',
font: 'monospace',
stroke: '#000000',
strokeThickness: 6
});
playerHealthBar.x = arenaLeft + 50;
playerHealthBar.y = arenaTop + 100;
game.addChild(playerHealthBar);
bossHealthBarContainer = new Container();
bossHealthBarContainer.x = 1024;
bossHealthBarContainer.y = arenaTop + 50;
game.addChild(bossHealthBarContainer);
bossHealthBarBg = bossHealthBarContainer.attachAsset('bossHealthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
bossHealthBarFill = bossHealthBarContainer.attachAsset('bossHealthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
bossNameText = new Text2('ZombiEagle', {
size: 56,
fill: '#FFFF00',
font: 'monospace',
stroke: '#000000',
strokeThickness: 6
});
bossNameText.anchor.set(0.5, 0);
bossNameText.x = 1024;
bossNameText.y = arenaTop + 10;
game.addChild(bossNameText);
spawnNextBoss();
}
function spawnNextBoss() {
console.log("Attempting to spawn boss at index", currentBossIndex, "of", bossConfigs.length, "total bosses");
if (currentBossIndex >= bossConfigs.length) {
console.log("All bosses defeated in spawnNextBoss, currentBossIndex:", currentBossIndex);
// Only show win if we've actually defeated all 4 bosses (indices 0,1,2,3)
if (currentBossIndex >= 4) {
LK.showYouWin();
}
return;
}
if (!bossConfigs[currentBossIndex]) {
console.error("Invalid boss index:", currentBossIndex, "available bosses:", bossConfigs.length);
return;
}
if (currentBoss) {
currentBoss.destroy();
currentBoss = null;
}
for (var i = bossBullets.length - 1; i >= 0; i--) {
bossBullets[i].destroy();
bossBullets.splice(i, 1);
}
var bossConfig = bossConfigs[currentBossIndex];
var bossIntroScreen = game.addChild(new BossIntroScreen());
bossIntroScreen.x = 1024;
bossIntroScreen.y = 1366;
var introAssetId = 'boss' + (currentBossIndex + 1) + 'Intro';
bossIntroScreen.showIntro(bossConfig.name, introAssetId);
LK.setTimeout(function () {
try {
var arenaAssetName = 'arena';
if (currentBossIndex === 1) {
arenaAssetName = 'arena2';
} else if (currentBossIndex === 2) {
arenaAssetName = 'arena3';
} else if (currentBossIndex === 3) {
arenaAssetName = 'arena4';
}
if (arena) {
arena.destroy();
arena = null;
}
arena = game.attachAsset(arenaAssetName, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
visible: true
});
game.setChildIndex(arena, 0);
arenaLeft = arena.x - arena.width / 2;
arenaRight = arena.x + arena.width / 2;
arenaTop = arena.y - arena.height / 2;
arenaBottom = arena.y + arena.height / 2;
currentBoss = game.addChild(new bossConfig["class"]());
currentBoss.x = 1024;
currentBoss.y = arenaTop + 200;
bossNameText.setText(bossConfig.name);
if (player) {
player.x = 1024;
player.y = 1366;
player.lastX = player.x;
}
if (bossHealthBarContainer) {
bossHealthBarContainer.y = arenaTop + 50;
}
if (bossNameText) {
bossNameText.y = arenaTop + 10;
}
if (playerHealthBar) {
playerHealthBar.x = arenaLeft + 50;
playerHealthBar.y = arenaTop + 100;
}
// Enable player shooting when boss intro ends and boss spawns
if (player) {
player.canShoot = true;
}
console.log("Successfully spawned boss", currentBossIndex + 1);
} catch (error) {
console.error("Error during boss spawn:", error);
}
}, 4000);
}
var dragActive = false;
game.down = function (x, y, obj) {
if (gameStarted) {
dragActive = true;
player.shoot();
}
};
game.up = function (x, y, obj) {
if (gameStarted) {
dragActive = false;
}
};
game.move = function (x, y, obj) {
if (gameStarted && dragActive) {
var localPos = game.toLocal({
x: x,
y: y
});
player.x = Math.max(arenaLeft + 60, Math.min(arenaRight - 60, localPos.x));
player.y = Math.max(arenaTop + 60, Math.min(arenaBottom - 60, localPos.y));
}
};
game.update = function () {
if (!gameStarted) {
return;
}
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.y < arenaTop - 50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
if (currentBoss && bullet.intersects(currentBoss)) {
currentBoss.takeDamage(bullet.damage);
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
}
for (var i = bossBullets.length - 1; i >= 0; i--) {
var bullet = bossBullets[i];
if (bullet.x < arenaLeft - 50 || bullet.x > arenaRight + 50 || bullet.y < arenaTop - 50 || bullet.y > arenaBottom + 50) {
bullet.destroy();
bossBullets.splice(i, 1);
continue;
}
if (bullet.intersects(player)) {
player.takeDamage(bullet.damage);
bullet.destroy();
bossBullets.splice(i, 1);
continue;
}
}
powerUpSpawnTimer++;
if (powerUpSpawnTimer >= 900 && Math.random() < 0.04) {
var powerUpType = Math.random() < 0.5 ? 'double' : 'health';
if (powerUpType === 'double') {
var powerUp = new DoubleShotPowerUp();
powerUp.x = arenaLeft + 100 + Math.random() * (arenaRight - arenaLeft - 200);
powerUp.y = arenaTop - 50;
doubleShotPowerUps.push(powerUp);
game.addChild(powerUp);
} else {
var healthPowerUp = new HealthPowerUp();
healthPowerUp.x = arenaLeft + 100 + Math.random() * (arenaRight - arenaLeft - 200);
healthPowerUp.y = arenaTop - 50;
healthPowerUps.push(healthPowerUp);
game.addChild(healthPowerUp);
}
powerUpSpawnTimer = 0;
}
for (var i = doubleShotPowerUps.length - 1; i >= 0; i--) {
var powerUp = doubleShotPowerUps[i];
if (powerUp.y > arenaBottom + 50) {
powerUp.destroy();
doubleShotPowerUps.splice(i, 1);
continue;
}
if (!powerUp.collected && powerUp.intersects(player)) {
player.collectDoubleShotPowerUp();
powerUp.collected = true;
tween(powerUp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
powerUp.destroy();
}
});
doubleShotPowerUps.splice(i, 1);
continue;
}
}
for (var i = healthPowerUps.length - 1; i >= 0; i--) {
var healthPowerUp = healthPowerUps[i];
if (healthPowerUp.y > arenaBottom + 50) {
healthPowerUp.destroy();
healthPowerUps.splice(i, 1);
continue;
}
if (!healthPowerUp.collected && healthPowerUp.intersects(player)) {
player.collectHealthPowerUp();
healthPowerUp.collected = true;
tween(healthPowerUp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
healthPowerUp.destroy();
}
});
healthPowerUps.splice(i, 1);
continue;
}
}
playerHealthBar.setText('Health: ' + player.health);
if (currentBoss) {
var healthPercentage = currentBoss.health / currentBoss.maxHealth;
bossHealthBarFill.width = 400 * healthPercentage;
}
};
Uma águia zumbi, vista aérea, estilo pixel art. In-Game asset. 2d. High contrast. No shadows
gota de sangue com contorno branco, pixel art, fundo transparente. In-Game asset. 2d. High contrast. No shadows
Um fantasma zumbi voador, arte pixel, vista aerea frontal. In-Game asset. 2d. High contrast. No shadows
um gárgula voador com olhos brilhantes, pixel 32bits art style, vista aerea frontal. In-Game asset. 2d. High contrast. No shadows
uma caverna escura estilo jogo de rpg, arte pixel, background game arena. In-Game asset. 2d. High contrast. No shadows
O telhado de um castelo medieval abandonado com suas torres. arte pixel 32 bits, vista aerea frontal. In-Game asset. 2d. High contrast. No shadows
um conjunto de montanhas de gelo, arte pixel 32bits, arena battle background. In-Game asset. 2d. High contrast. No shadows
MUDE A COR DA POÇÃO PARA AZUL
Escreva abaixo da poção o texto "HEALTH", ARTE PIXEL 32BITS
Make this dragon with 3 heads and a gray color scale
add details on left and right image to enlarge it