User prompt
Add soda
User prompt
Add energy drinks
User prompt
The boombox music constantly gets replaced by the default music whenever a new boss spawns.
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'gameInventory[itemId] = {' Line Number: 908 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
They spawn just out of reach
User prompt
Spawn them into the next boss instead of the current to ensure availability
User prompt
Add a inventory system ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Fix Goosandra spawning to always spawn when Glen is above 0 health and the spawner is clicked
User prompt
The basic Battle theme keeps playing
User prompt
Add new music. You choose what and where.
User prompt
Add a starting cutscene ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now add a guide button which tells you how to play, each boss and subtle hints for Easter eggs.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { inventory: {}, inventoryUnlocked: false }); /**** * Classes ****/ var Boss = Container.expand(function () { var self = Container.call(this); self.maxHealth = 100; self.health = self.maxHealth; self.attackCooldown = 0; self.movePattern = 0; self.speed = 2; self.damage = 10; self.takeDamage = function (damage) { 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(); bossDefeated = true; LK.setScore(LK.getScore() + 100 * currentBossLevel); }; return self; }); var Goosandra = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('viggen', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x800080; // Purple tint for Goosandra graphics.scaleX = 8; // Make Goosandra much larger graphics.scaleY = 8; // Make Goosandra much larger self.maxHealth = 1000; self.health = self.maxHealth; self.speed = 4; self.secretPhase = 1; self.phaseTimer = 0; self.update = function () { self.phaseTimer++; if (self.secretPhase == 1) { // Phase 1: Chaotic movement self.x += Math.sin(self.phaseTimer * 0.03) * 4; self.y += Math.cos(self.phaseTimer * 0.02) * 2; self.attackCooldown--; if (self.attackCooldown <= 0) { self.chaosAttack(); self.attackCooldown = 25; } if (self.health < self.maxHealth * 0.6) { self.secretPhase = 2; self.phaseTimer = 0; } } else if (self.secretPhase == 2) { // Phase 2: Ultimate chaos self.x += Math.sin(self.phaseTimer * 0.05) * 6; self.y += Math.cos(self.phaseTimer * 0.04) * 3; self.attackCooldown--; if (self.attackCooldown <= 0) { self.ultimateAttack(); self.attackCooldown = 25; } } }; self.chaosAttack = function () { // Spiral chaos shot for (var i = 0; i < 6; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 6 * Math.PI * 2 + self.phaseTimer * 0.1; bullet.targetX = self.x + Math.cos(angle) * 800; bullet.targetY = self.y + Math.sin(angle) * 800; bossBullets.push(bullet); game.addChild(bullet); } // Add 1 Viggen every chaos attack for (var j = 0; j < 1; j++) { var viggen = getPooledViggen(); viggen.x = self.x + (j - 0.5) * 100; viggen.y = self.y + 80; viggen.velocityX = (Math.random() - 0.5) * 2; viggen.velocityY = Math.random() * 2 + 1; viggen.lifetime = 300; viggens.push(viggen); game.addChild(viggen); } }; self.ultimateAttack = function () { // Ultimate chaos burst for (var i = 0; i < 12; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 12 * Math.PI * 2 + self.phaseTimer * 0.2; bullet.targetX = self.x + Math.cos(angle) * 900; bullet.targetY = self.y + Math.sin(angle) * 900; bossBullets.push(bullet); game.addChild(bullet); } // Random laser bursts if (self.phaseTimer % 120 == 0) { for (var j = 0; j < 2; j++) { var laser = new BossLaser(); laser.x = 200 + Math.random() * 1648; laser.y = 0; bossLasers.push(laser); game.addChild(laser); } } // Add 2 Viggens during ultimate attack for (var k = 0; k < 2; k++) { var viggen = getPooledViggen(); viggen.x = self.x + (k - 0.5) * 80; viggen.y = self.y + 100; viggen.velocityX = (Math.random() - 0.5) * 3; viggen.velocityY = Math.random() * 3 + 2; viggen.lifetime = 300; viggens.push(viggen); game.addChild(viggen); } }; self.onDefeat = function () { LK.getSound('bossDefeat').play(); LK.setScore(LK.getScore() + 2000); secretBossDefeated = true; storage.secretBossDefeated = true; // Update Glen's lore text if currently viewing boss 2 if (currentBossLevel == 2) { bossLoreText.setText(getBossLore(2)); } // Dramatic defeat cutscene LK.effects.flashScreen(0x800080, 2000); // Spin and shrink effect tween(self, { rotation: Math.PI * 8, scaleX: 0, scaleY: 0 }, { duration: 2000, easing: tween.easeIn }); // Fade out all UI elements dramatically tween(levelText, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 1500, easing: tween.easeIn }); tween(bossNameText, { alpha: 0 }, { duration: 1500, easing: tween.easeIn }); tween(bossHealthBar, { alpha: 0, scaleX: 0.3, scaleY: 0.3 }, { duration: 1500, easing: tween.easeIn }); tween(healthBar, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 1500, easing: tween.easeIn }); tween(instructionText, { alpha: 0, y: instructionText.y + 100 }, { duration: 1500, easing: tween.easeIn }); tween(bossGuideText, { alpha: 0 }, { duration: 1500, easing: tween.easeIn }); tween(bossLoreText, { alpha: 0 }, { duration: 1500, easing: tween.easeIn }); // Restore UI after 2 seconds LK.setTimeout(function () { // Restore all UI elements with bounce-in effect tween(levelText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.bounceOut }); tween(bossNameText, { alpha: 1 }, { duration: 800, easing: tween.bounceOut }); tween(bossHealthBar, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.bounceOut }); tween(healthBar, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.bounceOut }); tween(instructionText, { alpha: 1, y: instructionText.y - 100 }, { duration: 800, easing: tween.bounceOut }); tween(bossGuideText, { alpha: 1 }, { duration: 800, easing: tween.bounceOut }); tween(bossLoreText, { alpha: 1 }, { duration: 800, easing: tween.bounceOut }); }, 2000); // Wait for dramatic effect before showing win LK.setTimeout(function () { LK.showYouWin(); }, 2500); }; return self; }); var FinalBoss = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('finalBoss', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 800; self.health = self.maxHealth; self.phase = 1; self.phaseTimer = 0; self.speed = 2; self.update = function () { self.phaseTimer++; if (self.phase == 1) { // Phase 1: Slow movement, regular attacks self.x += Math.sin(self.phaseTimer * 0.01) * 2; self.attackCooldown--; if (self.attackCooldown <= 0) { self.phase1Attack(); self.attackCooldown = 60; } if (self.health < self.maxHealth * 0.5) { self.phase = 2; self.phaseTimer = 0; } } else if (self.phase == 2) { // Phase 2: Aggressive attacks self.attackCooldown--; if (self.attackCooldown <= 0) { self.phase2Attack(); self.attackCooldown = 30; } } }; self.phase1Attack = function () { // Triple spread shot for (var i = -2; i <= 2; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 150; bullet.targetX = player.x + i * 100; bullet.targetY = player.y; bossBullets.push(bullet); game.addChild(bullet); } }; self.phase2Attack = function () { // Radial burst + laser for (var i = 0; i < 12; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 12 * Math.PI * 2; bullet.targetX = self.x + Math.cos(angle) * 600; bullet.targetY = self.y + Math.sin(angle) * 600; bossBullets.push(bullet); game.addChild(bullet); } if (self.phaseTimer % 120 == 0) { var laser = new BossLaser(); laser.x = player.x; laser.y = 0; bossLasers.push(laser); game.addChild(laser); } }; self.onDefeat = function () { LK.getSound('bossDefeat').play(); LK.setScore(LK.getScore() + 1000); // Play victory fanfare LK.playMusic('victoryFanfare', { loop: false }); // Unlock victory fanfare if (!unlockedMusic.victoryFanfare) { unlockedMusic.victoryFanfare = true; storage.unlockedMusic = unlockedMusic; } // Delay showing win screen to let fanfare play LK.setTimeout(function () { LK.showYouWin(); }, 3000); }; return self; }); var Boss5 = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('boss2', { anchorX: 0.5, anchorY: 0.5 }); graphics.scaleX = 1.5; graphics.scaleY = 1.5; self.maxHealth = 750; self.health = self.maxHealth; self.speed = 3; self.teleportTimer = 0; self.laserWaveTimer = 0; self.update = function () { self.teleportTimer++; self.laserWaveTimer++; // Teleport movement if (self.teleportTimer % 120 == 0) { var newX = 300 + Math.random() * 1448; var newY = 300 + Math.random() * 400; tween(self, { x: newX, y: newY }, { duration: 300 }); LK.effects.flashObject(self, 0xffffff, 300); } // Attack patterns self.attackCooldown--; if (self.attackCooldown <= 0) { self.attack(); self.attackCooldown = 35; } // Laser wave attack if (self.laserWaveTimer % 240 == 0) { self.laserWave(); } }; self.attack = function () { // Homing missiles for (var i = 0; i < 4; i++) { var bullet = new BossBullet(); bullet.x = self.x + (i - 1.5) * 80; bullet.y = self.y + 100; bullet.targetX = player.x + (Math.random() - 0.5) * 200; bullet.targetY = player.y + (Math.random() - 0.5) * 200; bossBullets.push(bullet); game.addChild(bullet); } }; self.laserWave = function () { // Create multiple lasers across the screen for (var i = 0; i < 5; i++) { var laser = new BossLaser(); laser.x = 200 + i * 400; laser.y = 0; bossLasers.push(laser); game.addChild(laser); } }; return self; }); var Boss4 = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('boss3', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 600; self.health = self.maxHealth; self.speed = 5; self.spiralAngle = 0; self.burstTimer = 0; self.update = function () { // Spiral movement pattern self.spiralAngle += 0.05; self.x = 1024 + Math.cos(self.spiralAngle) * 400; self.y = 500 + Math.sin(self.spiralAngle * 0.7) * 150; // Multiple attack patterns self.attackCooldown--; self.burstTimer++; if (self.attackCooldown <= 0) { self.attack(); self.attackCooldown = 40; } // Burst attack every 3 seconds if (self.burstTimer % 180 == 0) { self.burstAttack(); } }; self.attack = function () { // Spiral shot pattern for (var i = 0; i < 6; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 6 * Math.PI * 2 + self.spiralAngle * 2; bullet.targetX = self.x + Math.cos(angle) * 600; bullet.targetY = self.y + Math.sin(angle) * 600; bossBullets.push(bullet); game.addChild(bullet); } }; self.burstAttack = function () { // Massive radial burst for (var i = 0; i < 16; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 16 * Math.PI * 2; bullet.targetX = self.x + Math.cos(angle) * 700; bullet.targetY = self.y + Math.sin(angle) * 700; bossBullets.push(bullet); game.addChild(bullet); } }; return self; }); var Boss3 = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('boss3', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 400; self.health = self.maxHealth; self.speed = 4; self.laserCooldown = 0; self.update = function () { // Aggressive movement toward player var dx = player.x - self.x; var dy = player.y - self.y; var distanceSquared = dx * dx + dy * dy; if (distanceSquared > 0) { var distance = Math.sqrt(distanceSquared); self.x += dx / distance * self.speed * 0.5; self.y += dy / distance * self.speed * 0.3; } // Multiple attack patterns self.attackCooldown--; self.laserCooldown--; if (self.attackCooldown <= 0) { self.attack(); self.attackCooldown = 45; } if (self.laserCooldown <= 0) { self.laserAttack(); self.laserCooldown = 180; } }; self.attack = function () { // Radial shot for (var i = 0; i < 8; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y; var angle = i / 8 * Math.PI * 2; bullet.targetX = self.x + Math.cos(angle) * 500; bullet.targetY = self.y + Math.sin(angle) * 500; bossBullets.push(bullet); game.addChild(bullet); } }; self.laserAttack = function () { var laser = new BossLaser(); laser.x = self.x; laser.y = self.y + 100; bossLasers.push(laser); game.addChild(laser); }; return self; }); var Boss2 = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('boss2', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 250; self.health = self.maxHealth; self.speed = 3; self.angle = 0; self.update = function () { // Circular movement self.angle += 0.02; self.x = 1024 + Math.cos(self.angle) * 300; self.y = 600 + Math.sin(self.angle) * 200; // Faster shooting self.attackCooldown--; if (self.attackCooldown <= 0) { self.attack(); self.attackCooldown = 60; } }; self.attack = function () { // Spread shot for (var i = -1; i <= 1; i++) { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 90; bullet.targetX = player.x + i * 150; bullet.targetY = player.y; bossBullets.push(bullet); game.addChild(bullet); } }; return self; }); var Boss1 = Boss.expand(function () { var self = Boss.call(this); var graphics = self.attachAsset('boss1', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 150; self.health = self.maxHealth; self.moveDirection = 1; self.update = function () { // Simple horizontal movement self.x += self.speed * self.moveDirection; if (self.x > 1800 || self.x < 250) { self.moveDirection *= -1; } // Simple shooting pattern self.attackCooldown--; if (self.attackCooldown <= 0) { self.attack(); self.attackCooldown = 90; } }; self.attack = function () { var bullet = new BossBullet(); bullet.x = self.x; bullet.y = self.y + 75; bullet.targetX = player.x; bullet.targetY = player.y; bossBullets.push(bullet); game.addChild(bullet); }; return self; }); var BossBullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bossBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.targetX = 0; self.targetY = 0; self.velocityX = 0; self.velocityY = 0; 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; }; return self; }); var BossLaser = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('bossLaser', { anchorX: 0.5, anchorY: 0.5 }); self.lifetime = 120; self.update = function () { self.lifetime--; graphics.alpha = self.lifetime / 120; }; return self; }); var Item = Container.expand(function () { var self = Container.call(this); self.itemId = ''; self.itemName = ''; self.itemType = 'common'; self.description = ''; self.rarity = 'common'; self.collectEffect = function () { // Override in specific items }; return self; }); var ViggenCrystal = Item.expand(function () { var self = Item.call(this); var graphics = self.attachAsset('viggen', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x800080; graphics.scaleX = 0.8; graphics.scaleY = 0.8; self.itemId = 'viggen_crystal'; self.itemName = 'Viggen Crystal'; self.itemType = 'trophy'; self.description = 'A crystallized essence of defeated Viggens'; self.rarity = 'epic'; self.collectEffect = function () { LK.effects.flashObject(player, 0x800080, 1000); addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity); }; return self; }); var Soda = Item.expand(function () { var self = Item.call(this); var graphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0xFF4500; // Orange red for soda graphics.scaleX = 1.3; graphics.scaleY = 1.3; self.itemId = 'soda'; self.itemName = 'Soda'; self.itemType = 'consumable'; self.description = 'Restores 30 health and increases fire rate for 10 seconds'; self.rarity = 'common'; self.healAmount = 30; self.fireRateBoostDuration = 600; // 10 seconds at 60fps self.collectEffect = function () { LK.effects.flashObject(player, 0xFF4500, 600); addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity); }; return self; }); var PowerCore = Item.expand(function () { var self = Item.call(this); var graphics = self.attachAsset('bossBullet', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0xFFD700; graphics.scaleX = 2; graphics.scaleY = 2; self.itemId = 'power_core'; self.itemName = 'Power Core'; self.itemType = 'upgrade'; self.description = 'Increases damage permanently'; self.rarity = 'rare'; self.collectEffect = function () { LK.effects.flashObject(player, 0xFFD700, 800); addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity); }; return self; }); var HealthPotion = Item.expand(function () { var self = Item.call(this); var graphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x00FF00; graphics.scaleX = 1.5; graphics.scaleY = 1.5; self.itemId = 'health_potion'; self.itemName = 'Health Potion'; self.itemType = 'consumable'; self.description = 'Restores 50 health points'; self.rarity = 'common'; self.healAmount = 50; self.collectEffect = function () { LK.effects.flashObject(player, 0x00FF00, 500); addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity); }; return self; }); var EnergyDrink = Item.expand(function () { var self = Item.call(this); var graphics = self.attachAsset('viggen', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x00BFFF; // Deep sky blue for energy graphics.scaleX = 0.6; graphics.scaleY = 0.6; self.itemId = 'energy_drink'; self.itemName = 'Energy Drink'; self.itemType = 'consumable'; self.description = 'Increases movement speed for 15 seconds'; self.rarity = 'rare'; self.speedBoostDuration = 900; // 15 seconds at 60fps self.collectEffect = function () { LK.effects.flashObject(player, 0x00BFFF, 700); addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 100; self.health = self.maxHealth; self.shootCooldown = 0; self.speed = 8; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 300); LK.getSound('hit').play(); if (self.health <= 0) { self.health = 0; isGameOver = true; } }; self.shoot = function () { if (self.shootCooldown <= 0) { var bullet = getPooledPlayerBullet(); bullet.x = self.x; bullet.y = self.y - 50; playerBullets.push(bullet); game.addChild(bullet); self.shootCooldown = 10; LK.getSound('shoot').play(); } }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.update = function () { self.y += self.speed; }; return self; }); var Viggen = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('viggen', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x00ffff; // Cyan tint for Viggens self.speed = 4; self.homingForce = 0.2; self.velocityX = 0; self.velocityY = 0; self.lifetime = 300; // 5 seconds at 60fps self.update = function () { self.lifetime--; // Homing behavior toward player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.velocityX += dx / distance * self.homingForce; self.velocityY += dy / distance * self.homingForce; } // Apply velocity with speed limit var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY); if (currentSpeed > self.speed) { self.velocityX = self.velocityX / currentSpeed * self.speed; self.velocityY = self.velocityY / currentSpeed * self.speed; } self.x += self.velocityX; self.y += self.velocityY; // Fade out as lifetime decreases graphics.alpha = Math.min(1, self.lifetime / 60); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000011 }); /**** * Game Code ****/ var player; var currentBoss; var currentBossLevel = 1; var playerBullets = []; var bossBullets = []; var bossLasers = []; var viggens = []; // Object pools for performance optimization var playerBulletPool = []; var bossBulletPool = []; var bossLaserPool = []; var viggenPool = []; function getPooledPlayerBullet() { if (playerBulletPool.length > 0) { return playerBulletPool.pop(); } return new PlayerBullet(); } function getPooledBossBullet() { if (bossBulletPool.length > 0) { return bossBulletPool.pop(); } return new BossBullet(); } function getPooledBossLaser() { if (bossLaserPool.length > 0) { return bossLaserPool.pop(); } return new BossLaser(); } function getPooledViggen() { if (viggenPool.length > 0) { return viggenPool.pop(); } return new Viggen(); } function returnToPool(bullet, pool) { bullet.x = 0; bullet.y = 0; bullet.velocityX = 0; bullet.velocityY = 0; bullet.targetX = 0; bullet.targetY = 0; pool.push(bullet); } var bossDefeated = false; var isGameOver = false; var transitionTimer = 0; var dragNode = null; var bossNames = ['Shant', 'Glen', 'Octo', 'Benjaminsen', 'Upit Developer', 'The Upit Collective']; var secretBossUnlocked = false; var secretBossDefeated = storage.secretBossDefeated || false; var sparklingWaterUnlocked = storage.sparklingWaterUnlocked || false; // Music unlocking system var unlockedMusic = storage.unlockedMusic || { battleMusic: false, goosandraTheme: false, epicFinale: false, mysteryTheme: false, victoryFanfare: false }; var currentlyPlayingMusic = 'battleMusic'; // Easter egg variables var konamiCode = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]; // Up Up Down Down Left Right Left Right B A var konamiProgress = 0; var rapidFireUnlocked = storage.rapidFireUnlocked || false; var rainbowModeUnlocked = storage.rainbowModeUnlocked || false; var clickCounter = 0; var lastClickTime = 0; var easterEggTimer = 0; var energyDrinkActive = false; var energyDrinkTimer = 0; var basePlayerSpeed = 8; var sodaFireRateActive = false; var sodaFireRateTimer = 0; // UI Elements var healthBar; var bossHealthBar; var levelText; var instructionText; // Inventory system variables var gameInventory = storage.inventory || {}; var inventoryUnlocked = storage.inventoryUnlocked || false; var droppedItems = []; var showingInventory = false; var inventoryOverlay = null; var inventoryDisplayText = null; var inventoryCloseButton = null; var inventoryItems = []; // Inventory system functions function addToInventory(itemId, itemName, itemType, description, rarity) { if (!gameInventory[itemId]) { gameInventory[itemId + '_name'] = itemName; gameInventory[itemId + '_type'] = itemType; gameInventory[itemId + '_description'] = description; gameInventory[itemId + '_rarity'] = rarity; gameInventory[itemId + '_quantity'] = 0; } gameInventory[itemId + '_quantity']++; storage.inventory = gameInventory; // Show collection message var collectMsg = new Text2('+ ' + itemName, { size: 45, fill: getRarityColor(rarity) }); collectMsg.anchor.set(0.5, 0.5); collectMsg.x = 1024; collectMsg.y = 1800; collectMsg.alpha = 0; game.addChild(collectMsg); tween(collectMsg, { alpha: 1, y: 1600, scaleX: 1.2, scaleY: 1.2 }, { duration: 800, onFinish: function onFinish() { tween(collectMsg, { alpha: 0, y: 1400 }, { duration: 600, onFinish: function onFinish() { collectMsg.destroy(); } }); } }); // Unlock inventory after first item if (!inventoryUnlocked) { inventoryUnlocked = true; storage.inventoryUnlocked = true; var unlockMsg = new Text2('📦 INVENTORY UNLOCKED! 📦\nCheck the INVENTORY button!', { size: 50, fill: 0xFFD700 }); unlockMsg.anchor.set(0.5, 0.5); unlockMsg.x = 1024; unlockMsg.y = 1366; game.addChild(unlockMsg); tween(unlockMsg, { scaleX: 1.3, scaleY: 1.3, alpha: 0 }, { duration: 3000, onFinish: function onFinish() { unlockMsg.destroy(); } }); } } function getRarityColor(rarity) { if (rarity === 'common') return 0xFFFFFF; if (rarity === 'rare') return 0x0099FF; if (rarity === 'epic') return 0x9933FF; if (rarity === 'legendary') return 0xFF6600; return 0xFFFFFF; } function useItem(itemId) { var quantity = gameInventory[itemId + '_quantity'] || 0; if (quantity <= 0) return false; if (itemId === 'health_potion') { player.health = Math.min(player.maxHealth, player.health + 50); LK.effects.flashObject(player, 0x00FF00, 500); gameInventory[itemId + '_quantity']--; if (gameInventory[itemId + '_quantity'] <= 0) { delete gameInventory[itemId + '_name']; delete gameInventory[itemId + '_type']; delete gameInventory[itemId + '_description']; delete gameInventory[itemId + '_rarity']; delete gameInventory[itemId + '_quantity']; } storage.inventory = gameInventory; return true; } else if (itemId === 'energy_drink') { if (!energyDrinkActive) { energyDrinkActive = true; energyDrinkTimer = 900; // 15 seconds player.speed = basePlayerSpeed * 1.8; // 80% speed increase LK.effects.flashObject(player, 0x00BFFF, 700); // Show speed boost message var speedMsg = new Text2('⚡ SPEED BOOST ACTIVE! ⚡', { size: 50, fill: 0x00BFFF }); speedMsg.anchor.set(0.5, 0.5); speedMsg.x = 1024; speedMsg.y = 1800; game.addChild(speedMsg); tween(speedMsg, { alpha: 0, y: 1600, scaleX: 1.3, scaleY: 1.3 }, { duration: 2000, onFinish: function onFinish() { speedMsg.destroy(); } }); gameInventory[itemId + '_quantity']--; if (gameInventory[itemId + '_quantity'] <= 0) { delete gameInventory[itemId + '_name']; delete gameInventory[itemId + '_type']; delete gameInventory[itemId + '_description']; delete gameInventory[itemId + '_rarity']; delete gameInventory[itemId + '_quantity']; } storage.inventory = gameInventory; return true; } } else if (itemId === 'soda') { // Heal first player.health = Math.min(player.maxHealth, player.health + 30); LK.effects.flashObject(player, 0xFF4500, 600); // Activate fire rate boost if (!sodaFireRateActive) { sodaFireRateActive = true; sodaFireRateTimer = 600; // 10 seconds // Show fire rate boost message var fireRateMsg = new Text2('🥤 FIRE RATE BOOST! 🥤', { size: 50, fill: 0xFF4500 }); fireRateMsg.anchor.set(0.5, 0.5); fireRateMsg.x = 1024; fireRateMsg.y = 1800; game.addChild(fireRateMsg); tween(fireRateMsg, { alpha: 0, y: 1600, scaleX: 1.3, scaleY: 1.3 }, { duration: 2000, onFinish: function onFinish() { fireRateMsg.destroy(); } }); } gameInventory[itemId + '_quantity']--; if (gameInventory[itemId + '_quantity'] <= 0) { delete gameInventory[itemId + '_name']; delete gameInventory[itemId + '_type']; delete gameInventory[itemId + '_description']; delete gameInventory[itemId + '_rarity']; delete gameInventory[itemId + '_quantity']; } storage.inventory = gameInventory; return true; } return false; } function spawnRandomItem(x, y) { if (Math.random() < 0.3) { // 30% chance to spawn item var itemType = Math.random(); var newItem; if (itemType < 0.3) { newItem = new HealthPotion(); } else if (itemType < 0.5) { newItem = new PowerCore(); } else if (itemType < 0.65) { newItem = new EnergyDrink(); } else if (itemType < 0.85) { newItem = new Soda(); } else { newItem = new ViggenCrystal(); } newItem.x = Math.max(100, Math.min(1948, x + (Math.random() - 0.5) * 200)); newItem.y = Math.max(1200, Math.min(2600, y + (Math.random() - 0.5) * 200)); newItem.collectTimer = 600; // 10 seconds to collect droppedItems.push(newItem); game.addChild(newItem); // Animate spawn newItem.alpha = 0; newItem.scaleX = 0; newItem.scaleY = 0; tween(newItem, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.bounceOut }); } } // Initialize UI healthBar = new Text2('Health: 100', { size: 60, fill: 0x00FF00 }); healthBar.anchor.set(0, 0); LK.gui.topLeft.addChild(healthBar); bossHealthBar = new Text2('Boss Health: 0', { size: 60, fill: 0xFF0000 }); bossHealthBar.anchor.set(0.5, 0); LK.gui.top.addChild(bossHealthBar); // Add click handler to boss health bar for secret boss bossHealthBar.down = function (x, y, obj) { if (currentBossLevel == 3 && currentBoss && !sparklingWaterUnlocked) { // Special Easter egg: Sparkling water gift during Octo fight sparklingWaterUnlocked = true; storage.sparklingWaterUnlocked = true; // Create sparkling water gift effect LK.effects.flashScreen(0x87CEEB, 1500); // Show sparkling water message var sparklingMsg = new Text2('💧 SPARKLING WATER GIFTED! 💧\n\nA refreshing reward for your\nexceptional Easter egg hunting!', { size: 50, fill: 0x87CEEB }); sparklingMsg.anchor.set(0.5, 0.5); sparklingMsg.x = 1024; sparklingMsg.y = 1366; game.addChild(sparklingMsg); // Animate sparkling water message tween(sparklingMsg, { scaleX: 1.3, scaleY: 1.3, alpha: 0 }, { duration: 4000, onFinish: function onFinish() { sparklingMsg.destroy(); } }); // Create bubbling particle effect for (var i = 0; i < 15; i++) { var bubble = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, x: 1024 + (Math.random() - 0.5) * 600, y: 1366 + (Math.random() - 0.5) * 200, scaleX: 0.5, scaleY: 0.5 }); bubble.tint = 0x87CEEB; // Sky blue for water bubbles game.addChild(bubble); // Animate bubbles floating up tween(bubble, { y: bubble.y - 400 - Math.random() * 200, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 3000 + Math.random() * 1000, onFinish: function onFinish() { bubble.destroy(); } }); } } if (currentBossLevel == 2 && currentBoss && currentBoss.health > 0 && !secretBossUnlocked) { secretBossUnlocked = true; // Cancel the normal boss defeat process bossDefeated = false; transitionTimer = 0; // Destroy Glen and spawn Goosandra currentBoss.destroy(); currentBoss = game.addChild(new Goosandra()); currentBoss.x = 1024; currentBoss.y = -300; // Start above screen for dramatic entrance levelText.setText('Secret Boss: Goosandra'); bossNameText.setText('Secret Boss: Goosandra'); bossGuideText.setText('CHAOS! Two phases, homing Viggens, ultimate mayhem!'); bossLoreText.setText(getGoosandraLore()); // Play Goosandra's theme song LK.playMusic('goosandraTheme'); // Unlock Goosandra theme after experiencing it if (!unlockedMusic.goosandraTheme) { unlockedMusic.goosandraTheme = true; storage.unlockedMusic = unlockedMusic; } // Dramatic entrance cutscene LK.effects.flashScreen(0x800080, 1000); // Easter egg: Extra special effects if both Easter eggs are unlocked if (rapidFireUnlocked && rainbowModeUnlocked) { // Create rainbow particle effect for (var i = 0; i < 20; i++) { var particle = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, x: 1024 + (Math.random() - 0.5) * 400, y: 1366 + (Math.random() - 0.5) * 400, scaleX: 2, scaleY: 2 }); particle.tint = Math.random() * 0xFFFFFF; game.addChild(particle); // Animate particles tween(particle, { x: particle.x + (Math.random() - 0.5) * 800, y: particle.y + (Math.random() - 0.5) * 800, alpha: 0, rotation: Math.PI * 4 }, { duration: 2000, onFinish: function onFinish() { particle.destroy(); } }); } // Special message for Easter egg hunters var easterMsg = new Text2('🥚 TRUE EASTER EGG HUNTER! 🥚', { size: 50, fill: 0xFF69B4 }); easterMsg.anchor.set(0.5, 0.5); easterMsg.x = 1024; easterMsg.y = 1100; game.addChild(easterMsg); tween(easterMsg, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 4000, onFinish: function onFinish() { easterMsg.destroy(); } }); } // Make UI text dramatic entrance tween(levelText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 500, easing: tween.bounceOut }); tween(bossNameText, { scaleX: 1.3, scaleY: 1.3 }, { duration: 600, easing: tween.elasticOut }); // Goosandra dramatic entrance from above tween(currentBoss, { y: 400 }, { duration: 2000, easing: tween.bounceOut }); // Add spinning entrance effect tween(currentBoss, { rotation: Math.PI * 4 }, { duration: 2000, easing: tween.easeOut }); // Pulsing size effect tween(currentBoss, { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(currentBoss, { scaleX: 1, scaleY: 1 }, { duration: 1000, easing: tween.easeInOut }); } }); } }; levelText = new Text2('Boss Level: 1', { size: 80, fill: 0xFFFF00 }); levelText.anchor.set(1, 0); LK.gui.topRight.addChild(levelText); instructionText = new Text2('Drag to move, tap to shoot!', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionText); var bossNameText = new Text2('Boss 1: Shant', { size: 70, fill: 0xFF6600 }); bossNameText.anchor.set(0.5, 0); bossNameText.y = 100; LK.gui.top.addChild(bossNameText); // Easter egg: Rapid click on boss name for rainbow mode bossNameText.down = function (x, y, obj) { var currentTime = Date.now(); if (currentTime - lastClickTime < 200) { // Clicks within 200ms clickCounter++; if (clickCounter >= 7) { if (!rainbowModeUnlocked) { rainbowModeUnlocked = true; storage.rainbowModeUnlocked = true; LK.effects.flashScreen(0xFFFFFF, 1000); // Show rainbow message var rainbowMsg = new Text2('🌈 RAINBOW MODE ACTIVATED! 🌈', { size: 60, fill: 0xFF00FF }); rainbowMsg.anchor.set(0.5, 0.5); rainbowMsg.x = 1024; rainbowMsg.y = 1366; game.addChild(rainbowMsg); // Animate message tween(rainbowMsg, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 3000, onFinish: function onFinish() { rainbowMsg.destroy(); } }); } clickCounter = 0; } } else { clickCounter = 1; } lastClickTime = currentTime; }; var bossGuideText = new Text2('', { size: 40, fill: 0xAAAAA }); bossGuideText.anchor.set(0.5, 0); bossGuideText.y = 180; LK.gui.top.addChild(bossGuideText); var bossLoreText = new Text2('', { size: 35, fill: 0xCCCCCC }); bossLoreText.anchor.set(0.5, 0); bossLoreText.y = 240; LK.gui.top.addChild(bossLoreText); // Add lore button var loreButton = new Text2('📖 LORE', { size: 50, fill: 0xFFD700 }); loreButton.anchor.set(0, 1); loreButton.x = 50; loreButton.y = -50; LK.gui.bottomLeft.addChild(loreButton); // Add guide button var guideButton = new Text2('📖 GUIDE', { size: 45, fill: 0x00FF88 }); guideButton.anchor.set(0, 1); guideButton.x = 50; guideButton.y = -190; LK.gui.bottomLeft.addChild(guideButton); // Add boombox button var boomboxButton = new Text2('🎵 BOOMBOX', { size: 45, fill: 0x00FFFF }); boomboxButton.anchor.set(0, 1); boomboxButton.x = 50; boomboxButton.y = -120; LK.gui.bottomLeft.addChild(boomboxButton); // Add inventory button var inventoryButton = new Text2('📦 INVENTORY', { size: 45, fill: inventoryUnlocked ? 0xFFD700 : 0x666666 }); inventoryButton.anchor.set(0, 1); inventoryButton.x = 50; inventoryButton.y = -260; LK.gui.bottomLeft.addChild(inventoryButton); // Lore display overlay var loreOverlay = null; var loreDisplayText = null; var loreCloseButton = null; var showingLore = false; // Boombox overlay variables var boomboxOverlay = null; var boomboxDisplayText = null; var boomboxCloseButton = null; var showingBoombox = false; var musicButtons = []; // Guide overlay variables var guideOverlay = null; var guideDisplayText = null; var guideCloseButton = null; var showingGuide = false; // Lore button click handler loreButton.down = function (x, y, obj) { if (!showingLore) { showingLore = true; // Create dark overlay loreOverlay = LK.getAsset('boss1', { anchorX: 0, anchorY: 0, x: 0, y: 0, scaleX: 13.65, scaleY: 18.21, alpha: 0.8 }); loreOverlay.tint = 0x000000; game.addChild(loreOverlay); // Create lore text var loreContent = getGameLore(); loreDisplayText = new Text2(loreContent, { size: 45, fill: 0xFFFFFF }); loreDisplayText.anchor.set(0.5, 0.5); loreDisplayText.x = 1024; loreDisplayText.y = 1366; game.addChild(loreDisplayText); // Create close button loreCloseButton = new Text2('❌ CLOSE', { size: 60, fill: 0xFF4444 }); loreCloseButton.anchor.set(0.5, 0.5); loreCloseButton.x = 1024; loreCloseButton.y = 2400; game.addChild(loreCloseButton); // Close button handler loreCloseButton.down = function (x, y, obj) { closeLoreDisplay(); }; // Animate entrance tween(loreOverlay, { alpha: 0.9 }, { duration: 500 }); tween(loreDisplayText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.bounceOut }); tween(loreCloseButton, { scaleX: 1.2, scaleY: 1.2 }, { duration: 400, easing: tween.elasticOut }); } }; function closeLoreDisplay() { if (showingLore) { showingLore = false; if (loreOverlay) { loreOverlay.destroy(); loreOverlay = null; } if (loreDisplayText) { loreDisplayText.destroy(); loreDisplayText = null; } if (loreCloseButton) { loreCloseButton.destroy(); loreCloseButton = null; } } } // Guide button click handler guideButton.down = function (x, y, obj) { if (!showingGuide) { showingGuide = true; // Create dark overlay guideOverlay = LK.getAsset('boss1', { anchorX: 0, anchorY: 0, x: 0, y: 0, scaleX: 13.65, scaleY: 18.21, alpha: 0.8 }); guideOverlay.tint = 0x000000; game.addChild(guideOverlay); // Create guide text var guideContent = getGameGuide(); guideDisplayText = new Text2(guideContent, { size: 45, fill: 0x00FF88 }); guideDisplayText.anchor.set(0.5, 0.5); guideDisplayText.x = 1024; guideDisplayText.y = 1366; game.addChild(guideDisplayText); // Create close button guideCloseButton = new Text2('❌ CLOSE', { size: 60, fill: 0xFF4444 }); guideCloseButton.anchor.set(0.5, 0.5); guideCloseButton.x = 1024; guideCloseButton.y = 2400; game.addChild(guideCloseButton); // Close button handler guideCloseButton.down = function (x, y, obj) { closeGuideDisplay(); }; // Animate entrance tween(guideOverlay, { alpha: 0.9 }, { duration: 500 }); tween(guideDisplayText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.bounceOut }); tween(guideCloseButton, { scaleX: 1.2, scaleY: 1.2 }, { duration: 400, easing: tween.elasticOut }); } }; function closeGuideDisplay() { if (showingGuide) { showingGuide = false; if (guideOverlay) { guideOverlay.destroy(); guideOverlay = null; } if (guideDisplayText) { guideDisplayText.destroy(); guideDisplayText = null; } if (guideCloseButton) { guideCloseButton.destroy(); guideCloseButton = null; } } } // Inventory button click handler inventoryButton.down = function (x, y, obj) { if (inventoryUnlocked && !showingInventory) { showingInventory = true; // Create dark overlay inventoryOverlay = LK.getAsset('boss1', { anchorX: 0, anchorY: 0, x: 0, y: 0, scaleX: 13.65, scaleY: 18.21, alpha: 0.8 }); inventoryOverlay.tint = 0x000000; game.addChild(inventoryOverlay); // Create inventory display createInventoryDisplay(); // Create close button inventoryCloseButton = new Text2('❌ CLOSE', { size: 60, fill: 0xFF4444 }); inventoryCloseButton.anchor.set(0.5, 0.5); inventoryCloseButton.x = 1024; inventoryCloseButton.y = 2400; game.addChild(inventoryCloseButton); inventoryCloseButton.down = function (x, y, obj) { closeInventoryDisplay(); }; // Animate entrance tween(inventoryOverlay, { alpha: 0.9 }, { duration: 500 }); } }; function createInventoryDisplay() { // Clear existing inventory items for (var i = 0; i < inventoryItems.length; i++) { inventoryItems[i].destroy(); } inventoryItems = []; // Create title inventoryDisplayText = new Text2('📦 INVENTORY 📦\n\nCollected Items:', { size: 50, fill: 0xFFD700 }); inventoryDisplayText.anchor.set(0.5, 0); inventoryDisplayText.x = 1024; inventoryDisplayText.y = 400; game.addChild(inventoryDisplayText); inventoryItems.push(inventoryDisplayText); var yPos = 700; var itemCount = 0; // Display each inventory item var processedItems = {}; for (var key in gameInventory) { if (key.endsWith('_quantity')) { var itemId = key.replace('_quantity', ''); var quantity = gameInventory[key]; if (quantity > 0) { var itemName = gameInventory[itemId + '_name'] || 'Unknown'; var itemDescription = gameInventory[itemId + '_description'] || ''; var itemType = gameInventory[itemId + '_type'] || 'common'; var itemRarity = gameInventory[itemId + '_rarity'] || 'common'; var itemText = new Text2(itemName + ' x' + quantity + '\n' + itemDescription, { size: 40, fill: getRarityColor(itemRarity) }); itemText.anchor.set(0.5, 0.5); itemText.x = 1024; itemText.y = yPos; game.addChild(itemText); inventoryItems.push(itemText); // Add use button for consumables if (itemType === 'consumable') { var useButton = new Text2('USE', { size: 35, fill: 0x00FF00 }); useButton.anchor.set(0.5, 0.5); useButton.x = 1400; useButton.y = yPos; game.addChild(useButton); inventoryItems.push(useButton); // Create closure to capture itemId (function (capturedItemId) { useButton.down = function (x, y, obj) { if (useItem(capturedItemId)) { closeInventoryDisplay(); // Reopen to refresh display LK.setTimeout(function () { inventoryButton.down(0, 0, {}); }, 100); } }; })(itemId); } yPos += 120; itemCount++; } } } if (itemCount === 0) { var emptyText = new Text2('No items collected yet!\nDefeat bosses and collect drops!', { size: 45, fill: 0x888888 }); emptyText.anchor.set(0.5, 0.5); emptyText.x = 1024; emptyText.y = 1000; game.addChild(emptyText); inventoryItems.push(emptyText); } } function closeInventoryDisplay() { if (showingInventory) { showingInventory = false; if (inventoryOverlay) { inventoryOverlay.destroy(); inventoryOverlay = null; } // Clear all inventory display items for (var i = 0; i < inventoryItems.length; i++) { inventoryItems[i].destroy(); } inventoryItems = []; if (inventoryCloseButton) { inventoryCloseButton.destroy(); inventoryCloseButton = null; } } } function getGameGuide() { return "🎮 HOW TO PLAY\n\n" + "• Drag to move your green ship\n" + "• Tap anywhere to shoot\n" + "• Defeat all 6 bosses to win!\n\n" + "⚔️ BOSS STRATEGIES\n\n" + "Boss 1 (Shant): Simple horizontal movement\n" + "Stay mobile, avoid single shots\n\n" + "Boss 2 (Glen): Circular pattern, spread shots\n" + "Predict movement, dodge spread fire\n\n" + "Boss 3 (Octo): Aggressive homing + lasers\n" + "Keep distance, watch for laser telegraphs\n\n" + "Boss 4 (Benjaminsen): Spiral + burst attacks\n" + "Learn patterns, time your movements\n\n" + "Boss 5 (Upit Dev): Teleports + homing missiles\n" + "Stay alert, unpredictable positioning\n\n" + "Final Boss: Two phases, everything combined\n" + "Ultimate challenge, use all your skills!\n\n" + "🥚 EASTER EGG HINTS\n\n" + "• Double-tap your ship for surprises...\n" + "• Rapidly click boss names for effects...\n" + "• Try clicking UI during boss fights...\n" + "• Secret bosses exist for the worthy...\n" + "• Music unlocks through experience...\n" + "• Some rewards are refreshingly hidden...\n\n" + "Good luck, pilot! 🚀"; } // Boombox button click handler boomboxButton.down = function (x, y, obj) { if (!showingBoombox) { showingBoombox = true; // Create dark overlay boomboxOverlay = LK.getAsset('boss1', { anchorX: 0, anchorY: 0, x: 0, y: 0, scaleX: 13.65, scaleY: 18.21, alpha: 0.8 }); boomboxOverlay.tint = 0x000000; game.addChild(boomboxOverlay); // Create boombox title boomboxDisplayText = new Text2('🎵 MUSIC BOOMBOX 🎵\n\nEach track must be experienced in its\nnatural environment before access!', { size: 50, fill: 0x00FFFF }); boomboxDisplayText.anchor.set(0.5, 0); boomboxDisplayText.x = 1024; boomboxDisplayText.y = 400; game.addChild(boomboxDisplayText); // Create music control buttons createMusicButtons(); // Create close button boomboxCloseButton = new Text2('❌ CLOSE', { size: 60, fill: 0xFF4444 }); boomboxCloseButton.anchor.set(0.5, 0.5); boomboxCloseButton.x = 1024; boomboxCloseButton.y = 2400; game.addChild(boomboxCloseButton); // Close button handler boomboxCloseButton.down = function (x, y, obj) { closeBoomboxDisplay(); }; // Animate entrance tween(boomboxOverlay, { alpha: 0.9 }, { duration: 500 }); tween(boomboxDisplayText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.bounceOut }); } }; function createMusicButtons() { // Clear existing buttons for (var i = 0; i < musicButtons.length; i++) { musicButtons[i].destroy(); } musicButtons = []; var yStart = 700; var spacing = 120; // Battle Music button var battleButton = new Text2('♪ Battle Music', { size: 50, fill: unlockedMusic.battleMusic ? 0x00FF00 : 0x888888 }); battleButton.anchor.set(0.5, 0.5); battleButton.x = 1024; battleButton.y = yStart; game.addChild(battleButton); musicButtons.push(battleButton); if (unlockedMusic.battleMusic) { battleButton.down = function (x, y, obj) { currentlyPlayingMusic = 'battleMusic'; LK.playMusic('battleMusic'); updateMusicButtonColors(); }; } // Mystery Theme button var mysteryButton = new Text2('♪ Mystery Theme', { size: 50, fill: unlockedMusic.mysteryTheme ? 0x4B0082 : 0x888888 }); mysteryButton.anchor.set(0.5, 0.5); mysteryButton.x = 1024; mysteryButton.y = yStart + spacing; game.addChild(mysteryButton); musicButtons.push(mysteryButton); if (unlockedMusic.mysteryTheme) { mysteryButton.down = function (x, y, obj) { currentlyPlayingMusic = 'mysteryTheme'; LK.playMusic('mysteryTheme'); updateMusicButtonColors(); }; } // Epic Finale button var epicButton = new Text2('♫ Epic Finale', { size: 50, fill: unlockedMusic.epicFinale ? 0xFF4500 : 0x888888 }); epicButton.anchor.set(0.5, 0.5); epicButton.x = 1024; epicButton.y = yStart + spacing * 2; game.addChild(epicButton); musicButtons.push(epicButton); if (unlockedMusic.epicFinale) { epicButton.down = function (x, y, obj) { currentlyPlayingMusic = 'epicFinale'; LK.playMusic('epicFinale'); updateMusicButtonColors(); }; } // Goosandra Theme button var goosandraButton = new Text2('♫ Goosandra Theme', { size: 50, fill: unlockedMusic.goosandraTheme ? 0x800080 : 0x888888 }); goosandraButton.anchor.set(0.5, 0.5); goosandraButton.x = 1024; goosandraButton.y = yStart + spacing * 3; game.addChild(goosandraButton); musicButtons.push(goosandraButton); if (unlockedMusic.goosandraTheme) { goosandraButton.down = function (x, y, obj) { currentlyPlayingMusic = 'goosandraTheme'; LK.playMusic('goosandraTheme'); updateMusicButtonColors(); }; } // Victory Fanfare button var victoryButton = new Text2('♫ Victory Fanfare', { size: 50, fill: unlockedMusic.victoryFanfare ? 0xFFD700 : 0x888888 }); victoryButton.anchor.set(0.5, 0.5); victoryButton.x = 1024; victoryButton.y = yStart + spacing * 4; game.addChild(victoryButton); musicButtons.push(victoryButton); if (unlockedMusic.victoryFanfare) { victoryButton.down = function (x, y, obj) { currentlyPlayingMusic = 'victoryFanfare'; LK.playMusic('victoryFanfare', { loop: false }); updateMusicButtonColors(); }; } // Status text var statusText = new Text2(getUnlockStatus(), { size: 40, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0.5); statusText.x = 1024; statusText.y = yStart + spacing * 5; game.addChild(statusText); musicButtons.push(statusText); updateMusicButtonColors(); } function updateMusicButtonColors() { if (musicButtons.length >= 5) { // Battle music button musicButtons[0].tint = currentlyPlayingMusic === 'battleMusic' && unlockedMusic.battleMusic ? 0xFFFF00 : unlockedMusic.battleMusic ? 0x00FF00 : 0x888888; // Mystery theme button musicButtons[1].tint = currentlyPlayingMusic === 'mysteryTheme' && unlockedMusic.mysteryTheme ? 0xFFFF00 : unlockedMusic.mysteryTheme ? 0x4B0082 : 0x888888; // Epic finale button musicButtons[2].tint = currentlyPlayingMusic === 'epicFinale' && unlockedMusic.epicFinale ? 0xFFFF00 : unlockedMusic.epicFinale ? 0xFF4500 : 0x888888; // Goosandra theme button musicButtons[3].tint = currentlyPlayingMusic === 'goosandraTheme' && unlockedMusic.goosandraTheme ? 0xFFFF00 : unlockedMusic.goosandraTheme ? 0x800080 : 0x888888; // Victory fanfare button musicButtons[4].tint = currentlyPlayingMusic === 'victoryFanfare' && unlockedMusic.victoryFanfare ? 0xFFFF00 : unlockedMusic.victoryFanfare ? 0xFFD700 : 0x888888; } } function getUnlockStatus() { var unlocked = 0; var total = 5; if (unlockedMusic.battleMusic) unlocked++; if (unlockedMusic.goosandraTheme) unlocked++; if (unlockedMusic.epicFinale) unlocked++; if (unlockedMusic.mysteryTheme) unlocked++; if (unlockedMusic.victoryFanfare) unlocked++; return 'Unlocked: ' + unlocked + '/' + total + ' tracks'; } function closeBoomboxDisplay() { if (showingBoombox) { showingBoombox = false; if (boomboxOverlay) { boomboxOverlay.destroy(); boomboxOverlay = null; } if (boomboxDisplayText) { boomboxDisplayText.destroy(); boomboxDisplayText = null; } if (boomboxCloseButton) { boomboxCloseButton.destroy(); boomboxCloseButton = null; } // Clear music buttons for (var i = 0; i < musicButtons.length; i++) { musicButtons[i].destroy(); } musicButtons = []; } } function getGameLore() { return "THE UPIT WARS: GENESIS\n\n" + "Long ago, in the digital realm of FRVR,\n" + "the UPIT Collective ruled with algorithms\n" + "and code. But power corrupted their minds,\n" + "transforming them into digital tyrants.\n\n" + "Each member became a Boss, wielding\n" + "their programming skills as weapons:\n\n" + "• Shant - The Beat Master\n" + "• Glen - The Haskell God\n" + "• Octo - The Hunter-Killer\n" + "• Benjaminsen - The Strategist\n" + "• The Upit Developer - Reality Bender\n" + "• The Collective - Merged Consciousness\n\n" + "In the shadows lurks Goosandra,\n" + "the Certified Viggener, responsible\n" + "for multiple digital genocides.\n\n" + "You are humanity's last hope.\n" + "Defeat the UPIT Bosses and restore\n" + "balance to the digital realm!\n\n" + "May the code be with you..."; } // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 2200; // Easter egg: Double tap player for rapid fire var playerClickCount = 0; var playerLastClickTime = 0; player.down = function (x, y, obj) { var currentTime = Date.now(); if (currentTime - playerLastClickTime < 300) { // Double tap within 300ms playerClickCount++; if (playerClickCount >= 2 && !rapidFireUnlocked) { rapidFireUnlocked = true; storage.rapidFireUnlocked = true; LK.effects.flashObject(player, 0xFFFF00, 1000); // Show rapid fire message var rapidMsg = new Text2('⚡ RAPID FIRE UNLOCKED! ⚡', { size: 60, fill: 0xFFFF00 }); rapidMsg.anchor.set(0.5, 0.5); rapidMsg.x = 1024; rapidMsg.y = 1500; game.addChild(rapidMsg); // Animate message tween(rapidMsg, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 2000, onFinish: function onFinish() { rapidMsg.destroy(); } }); playerClickCount = 0; } } else { playerClickCount = 1; } playerLastClickTime = currentTime; }; // Starting cutscene variables var cutsceneActive = true; var cutsceneTimer = 0; var cutsceneText1 = null; var cutsceneText2 = null; var cutsceneText3 = null; // Create starting cutscene function startCutscene() { // Hide player during cutscene player.alpha = 0; // First text: Title cutsceneText1 = new Text2('THE UPIT WARS', { size: 120, fill: 0xFFFF00 }); cutsceneText1.anchor.set(0.5, 0.5); cutsceneText1.x = 1024; cutsceneText1.y = 800; cutsceneText1.alpha = 0; game.addChild(cutsceneText1); // Second text: Subtitle cutsceneText2 = new Text2('GENESIS', { size: 80, fill: 0xFF6600 }); cutsceneText2.anchor.set(0.5, 0.5); cutsceneText2.x = 1024; cutsceneText2.y = 950; cutsceneText2.alpha = 0; game.addChild(cutsceneText2); // Third text: Mission briefing cutsceneText3 = new Text2('Defeat the UPIT Collective\nSave the digital realm', { size: 60, fill: 0x00FFFF }); cutsceneText3.anchor.set(0.5, 0.5); cutsceneText3.x = 1024; cutsceneText3.y = 1200; cutsceneText3.alpha = 0; game.addChild(cutsceneText3); // Animate title entrance tween(cutsceneText1, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.easeOut }); // Animate subtitle entrance (delayed) LK.setTimeout(function () { tween(cutsceneText2, { alpha: 1, y: 950 }, { duration: 800, easing: tween.bounceOut }); }, 500); // Animate mission briefing (delayed) LK.setTimeout(function () { tween(cutsceneText3, { alpha: 1, scaleX: 1.1, scaleY: 1.1 }, { duration: 600, easing: tween.elasticOut }); }, 1200); // Flash screen effect LK.setTimeout(function () { LK.effects.flashScreen(0x000088, 800); }, 2000); // Start fade out sequence LK.setTimeout(function () { // Fade out all cutscene text tween(cutsceneText1, { alpha: 0, y: 600 }, { duration: 1000, easing: tween.easeIn }); tween(cutsceneText2, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 1000, easing: tween.easeIn }); tween(cutsceneText3, { alpha: 0, y: 1400 }, { duration: 1000, easing: tween.easeIn }); // Reveal player ship with dramatic entrance tween(player, { alpha: 1, y: 2200, scaleX: 1.2, scaleY: 1.2 }, { duration: 1500, easing: tween.bounceOut, onFinish: function onFinish() { // Return player to normal size tween(player, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeOut }); } }); // Clean up cutscene after animations complete LK.setTimeout(function () { if (cutsceneText1) { cutsceneText1.destroy(); cutsceneText1 = null; } if (cutsceneText2) { cutsceneText2.destroy(); cutsceneText2 = null; } if (cutsceneText3) { cutsceneText3.destroy(); cutsceneText3 = null; } cutsceneActive = false; }, 1500); }, 3500); } // Start the cutscene startCutscene(); // Start with soft ambient music during cutscene LK.playMusic('mysteryTheme', { volume: 0.3, fade: { start: 0, end: 0.3, duration: 2000 } }); // Transition to battle music after cutscene ends LK.setTimeout(function () { if (!secretBossUnlocked) { // Only if not fighting secret boss LK.playMusic('battleMusic', { fade: { start: 0, end: 1, duration: 2000 } }); currentlyPlayingMusic = 'battleMusic'; // Unlock battle music if (!unlockedMusic.battleMusic) { unlockedMusic.battleMusic = true; storage.unlockedMusic = unlockedMusic; } } }, 5000); // 5 seconds - after cutscene completes // Start first boss function getBossGuide(bossLevel) { if (bossLevel == 1) { return 'Simple movement, single shots. Stay mobile!'; } else if (bossLevel == 2) { return 'Circular pattern, spread shots. Predict the path!'; } else if (bossLevel == 3) { return 'Homing movement, radial + laser attacks. Keep distance!'; } else if (bossLevel == 4) { return 'Spiral movement, burst attacks. Watch for patterns!'; } else if (bossLevel == 5) { return 'Teleports randomly, homing missiles + laser waves!'; } else if (bossLevel >= 6) { return 'Two phases, radial bursts + targeted lasers!'; } return ''; } function getBossLore(bossLevel) { if (bossLevel == 1) { var baseLore = 'A simple UPIT creator, mostly known for The Last Beat'; if (rapidFireUnlocked && rainbowModeUnlocked) { return baseLore + ' 🎵 *hums The Last Beat* 🎵'; } return baseLore; } else if (bossLevel == 2) { // Check if secret boss has been defeated to reveal Goosandra's name if (secretBossDefeated) { return 'Haskell god, Goosandra\'s friend'; } else { return 'Haskell god, #########\'s friend'; } } else if (bossLevel == 3) { var baseLore = 'An aggressive hunter-killer with advanced targeting.'; if (rainbowModeUnlocked) { return baseLore + ' 🐙 Surprisingly, loves rainbow colors! 🌈'; } return baseLore; } else if (bossLevel == 4) { var baseLore = 'A master strategist who fights with calculated precision.'; if (rapidFireUnlocked) { return baseLore + ' ⚡ Respects your rapid fire skills! ⚡'; } return baseLore; } else if (bossLevel == 5) { return 'The lead developer, wielding reality-bending code.'; } else if (bossLevel >= 6) { var baseLore = 'The merged consciousness of all UPIT minds.'; if (rapidFireUnlocked && rainbowModeUnlocked) { return baseLore + ' 🧠✨ They are impressed by your Easter egg hunting! ✨🧠'; } return baseLore; } return ''; } function getGoosandraLore() { return 'Certified Viggener, responsible for multiple genocides. Pounds sand with geese.'; } function spawnBoss() { if (currentBoss) { currentBoss.destroy(); } bossDefeated = false; transitionTimer = 0; // Clear bullets for (var i = bossBullets.length - 1; i >= 0; i--) { bossBullets[i].destroy(); bossBullets.splice(i, 1); } // Clear viggens for (var i = viggens.length - 1; i >= 0; i--) { viggens[i].destroy(); viggens.splice(i, 1); } // Spawn appropriate boss if (currentBossLevel == 1) { currentBoss = game.addChild(new Boss1()); currentBoss.x = 1024; currentBoss.y = 400; levelText.setText('Boss 1: Shant'); bossNameText.setText('Boss 1: Shant'); bossGuideText.setText(getBossGuide(1)); bossLoreText.setText(getBossLore(1)); } else if (currentBossLevel == 2) { currentBoss = game.addChild(new Boss2()); currentBoss.x = 1024; currentBoss.y = 600; levelText.setText('Boss 2: Glen'); bossNameText.setText('Boss 2: Glen'); bossGuideText.setText(getBossGuide(2)); bossLoreText.setText(getBossLore(2)); } else if (currentBossLevel == 3) { currentBoss = game.addChild(new Boss3()); currentBoss.x = 1024; currentBoss.y = 500; levelText.setText('Boss 3: Octo'); bossNameText.setText('Boss 3: Octo'); bossGuideText.setText(getBossGuide(3)); bossLoreText.setText(getBossLore(3)); } else if (currentBossLevel == 4) { currentBoss = game.addChild(new Boss4()); currentBoss.x = 1024; currentBoss.y = 500; levelText.setText('Boss 4: Benjaminsen'); bossNameText.setText('Boss 4: Benjaminsen'); bossGuideText.setText(getBossGuide(4)); bossLoreText.setText(getBossLore(4)); } else if (currentBossLevel == 5) { currentBoss = game.addChild(new Boss5()); currentBoss.x = 1024; currentBoss.y = 400; levelText.setText('Boss 5: Upit Developer'); bossNameText.setText('Boss 5: Upit Developer'); bossGuideText.setText(getBossGuide(5)); bossLoreText.setText(getBossLore(5)); } else if (currentBossLevel >= 6) { currentBoss = game.addChild(new FinalBoss()); currentBoss.x = 1024; currentBoss.y = 400; levelText.setText('Final Boss: The Upit Collective'); bossNameText.setText('Final Boss: The Upit Collective'); bossGuideText.setText(getBossGuide(6)); bossLoreText.setText(getBossLore(6)); } // Choose appropriate music for boss level // Only change music if user hasn't manually selected music from boombox var shouldChangeMusicForBoss = true; // Check if user has manually selected music from boombox by comparing with expected boss music var expectedBossMusic = ''; if (currentBossLevel >= 6) { expectedBossMusic = 'epicFinale'; } else if (currentBossLevel == 4 || currentBossLevel == 5) { expectedBossMusic = 'mysteryTheme'; } else { expectedBossMusic = 'battleMusic'; } // If currently playing music doesn't match what boss would normally play, preserve user choice if (currentlyPlayingMusic !== expectedBossMusic && (currentlyPlayingMusic === 'battleMusic' || currentlyPlayingMusic === 'goosandraTheme' || currentlyPlayingMusic === 'epicFinale' || currentlyPlayingMusic === 'mysteryTheme' || currentlyPlayingMusic === 'victoryFanfare')) { shouldChangeMusicForBoss = false; } if (shouldChangeMusicForBoss) { // LK.playMusic automatically stops any currently playing music if (currentBossLevel >= 6) { // Play epic finale music for final boss LK.playMusic('epicFinale', { fade: { start: 0, end: 1, duration: 1500 } }); currentlyPlayingMusic = 'epicFinale'; // Unlock epic finale music if (!unlockedMusic.epicFinale) { unlockedMusic.epicFinale = true; storage.unlockedMusic = unlockedMusic; } } else if (currentBossLevel == 4 || currentBossLevel == 5) { // Play mystery theme for mid-tier bosses LK.playMusic('mysteryTheme', { fade: { start: 0, end: 0.8, duration: 1000 } }); currentlyPlayingMusic = 'mysteryTheme'; // Unlock mystery theme if (!unlockedMusic.mysteryTheme) { unlockedMusic.mysteryTheme = true; storage.unlockedMusic = unlockedMusic; } } else { // Play regular battle music for early bosses (levels 1-3) // Only play if not already playing battle music to avoid restart if (currentlyPlayingMusic !== 'battleMusic') { LK.playMusic('battleMusic', { fade: { start: 0, end: 1, duration: 1000 } }); currentlyPlayingMusic = 'battleMusic'; } // Unlock battle music after experiencing it if (!unlockedMusic.battleMusic) { unlockedMusic.battleMusic = true; storage.unlockedMusic = unlockedMusic; } } } else { // Still unlock music tracks even if not playing them if (currentBossLevel >= 6 && !unlockedMusic.epicFinale) { unlockedMusic.epicFinale = true; storage.unlockedMusic = unlockedMusic; } else if ((currentBossLevel == 4 || currentBossLevel == 5) && !unlockedMusic.mysteryTheme) { unlockedMusic.mysteryTheme = true; storage.unlockedMusic = unlockedMusic; } else if (currentBossLevel <= 3 && !unlockedMusic.battleMusic) { unlockedMusic.battleMusic = true; storage.unlockedMusic = unlockedMusic; } } } spawnBoss(); // Event handlers function handleMove(x, y, obj) { if (dragNode && !isGameOver && !cutsceneActive) { dragNode.x = Math.max(40, Math.min(2008, x)); dragNode.y = Math.max(1000, Math.min(2692, y)); } } game.move = handleMove; game.down = function (x, y, obj) { if (!isGameOver && !cutsceneActive) { dragNode = player; handleMove(x, y, obj); player.shoot(); } }; game.up = function (x, y, obj) { dragNode = null; }; // Main game loop game.update = function () { // Handle cutscene if (cutsceneActive) { cutsceneTimer++; return; // Skip all game logic during cutscene } if (isGameOver) { LK.showGameOver(); return; } // Handle boss transition if (bossDefeated) { transitionTimer++; if (transitionTimer > 120) { currentBossLevel++; if (currentBossLevel > 6) { currentBossLevel = 6; // Stay at final boss } spawnBoss(); // Spawn items for the new boss to ensure availability if (currentBoss) { spawnRandomItem(currentBoss.x, currentBoss.y); spawnRandomItem(currentBoss.x + 100, currentBoss.y + 100); } // Heal player slightly between bosses player.health = Math.min(player.maxHealth, player.health + 20); } } // Update dropped items for (var i = droppedItems.length - 1; i >= 0; i--) { var item = droppedItems[i]; item.collectTimer--; // Pulsing effect var pulse = 1 + Math.sin(LK.ticks * 0.1) * 0.2; item.scaleX = pulse; item.scaleY = pulse; // Fade out as time runs out if (item.collectTimer < 120) { item.alpha = item.collectTimer / 120; } // Remove expired items if (item.collectTimer <= 0) { item.destroy(); droppedItems.splice(i, 1); continue; } // Check collection by player if (item.intersects(player)) { item.collectEffect(); item.destroy(); droppedItems.splice(i, 1); continue; } } // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (bullet.y < -50) { game.removeChild(bullet); returnToPool(bullet, playerBulletPool); playerBullets.splice(i, 1); continue; } // Check collision with boss if (currentBoss && bullet.intersects(currentBoss)) { currentBoss.takeDamage(25); game.removeChild(bullet); returnToPool(bullet, playerBulletPool); playerBullets.splice(i, 1); continue; } } // Update boss bullets for (var i = bossBullets.length - 1; i >= 0; i--) { var bullet = bossBullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { game.removeChild(bullet); returnToPool(bullet, bossBulletPool); bossBullets.splice(i, 1); continue; } // Check collision with player if (bullet.intersects(player)) { player.takeDamage(15); game.removeChild(bullet); returnToPool(bullet, bossBulletPool); bossBullets.splice(i, 1); continue; } } // Update boss lasers for (var i = bossLasers.length - 1; i >= 0; i--) { var laser = bossLasers[i]; if (laser.lifetime <= 0) { game.removeChild(laser); laser.lifetime = 120; // Reset lifetime for pooling returnToPool(laser, bossLaserPool); bossLasers.splice(i, 1); continue; } // Check collision with player if (laser.intersects(player)) { player.takeDamage(2); // Continuous damage } } // Update viggens for (var i = viggens.length - 1; i >= 0; i--) { var viggen = viggens[i]; if (viggen.lifetime <= 0 || viggen.x < -50 || viggen.x > 2098 || viggen.y < -50 || viggen.y > 2782) { game.removeChild(viggen); viggen.lifetime = 300; // Reset lifetime for pooling returnToPool(viggen, viggenPool); viggens.splice(i, 1); continue; } // Check collision with player if (viggen.intersects(player)) { player.takeDamage(20); game.removeChild(viggen); viggen.lifetime = 300; // Reset lifetime for pooling returnToPool(viggen, viggenPool); viggens.splice(i, 1); continue; } } // Update UI (only every 10 frames to reduce text update overhead) if (LK.ticks % 10 === 0) { healthBar.setText('Health: ' + player.health); if (currentBoss) { bossHealthBar.setText('Boss Health: ' + currentBoss.health); } // Update inventory button color inventoryButton.tint = inventoryUnlocked ? 0xFFD700 : 0x666666; } // Easter egg: Pulsing effect for unlocked features if (rapidFireUnlocked) { var pulseScale = 1 + Math.sin(easterEggTimer * 0.15) * 0.1; player.scaleX = pulseScale; player.scaleY = pulseScale; } // Auto-shoot (with rapid fire Easter egg and soda boost) var shootInterval = rapidFireUnlocked ? 5 : 15; if (sodaFireRateActive) { shootInterval = Math.max(3, Math.floor(shootInterval * 0.6)); // 40% faster fire rate } if (LK.ticks % shootInterval == 0 && !isGameOver) { player.shoot(); } // Handle energy drink effect if (energyDrinkActive) { energyDrinkTimer--; // Add sparkling particle effect while active if (LK.ticks % 10 === 0) { var sparkle = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, x: player.x + (Math.random() - 0.5) * 80, y: player.y + (Math.random() - 0.5) * 80, scaleX: 0.3, scaleY: 0.3 }); sparkle.tint = 0x00BFFF; game.addChild(sparkle); tween(sparkle, { alpha: 0, y: sparkle.y - 100, scaleX: 0.8, scaleY: 0.8 }, { duration: 800, onFinish: function onFinish() { sparkle.destroy(); } }); } if (energyDrinkTimer <= 0) { energyDrinkActive = false; player.speed = basePlayerSpeed; // Reset to normal speed // Show effect ended message var endMsg = new Text2('Speed boost ended', { size: 40, fill: 0x888888 }); endMsg.anchor.set(0.5, 0.5); endMsg.x = 1024; endMsg.y = 1900; game.addChild(endMsg); tween(endMsg, { alpha: 0, y: 1700 }, { duration: 1500, onFinish: function onFinish() { endMsg.destroy(); } }); } } // Handle soda fire rate boost effect if (sodaFireRateActive) { sodaFireRateTimer--; // Add fizzy particle effect while active if (LK.ticks % 15 === 0) { var fizz = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, x: player.x + (Math.random() - 0.5) * 60, y: player.y + (Math.random() - 0.5) * 60, scaleX: 0.2, scaleY: 0.2 }); fizz.tint = 0xFF4500; game.addChild(fizz); tween(fizz, { alpha: 0, y: fizz.y - 80, scaleX: 0.6, scaleY: 0.6 }, { duration: 600, onFinish: function onFinish() { fizz.destroy(); } }); } if (sodaFireRateTimer <= 0) { sodaFireRateActive = false; // Show effect ended message var endMsg = new Text2('Fire rate boost ended', { size: 40, fill: 0x888888 }); endMsg.anchor.set(0.5, 0.5); endMsg.x = 1024; endMsg.y = 1900; game.addChild(endMsg); tween(endMsg, { alpha: 0, y: 1700 }, { duration: 1500, onFinish: function onFinish() { endMsg.destroy(); } }); } } // Easter egg effects easterEggTimer++; // Rainbow mode effect if (rainbowModeUnlocked) { var rainbowColor = Math.sin(easterEggTimer * 0.1) * 0.5 + 0.5; var r = Math.sin(easterEggTimer * 0.1) * 127 + 128; var g = Math.sin(easterEggTimer * 0.1 + 2) * 127 + 128; var b = Math.sin(easterEggTimer * 0.1 + 4) * 127 + 128; var color = (Math.floor(r) << 16) + (Math.floor(g) << 8) + Math.floor(b); // Apply rainbow effect to UI elements if (easterEggTimer % 3 == 0) { bossNameText.tint = color; levelText.tint = color; } } // Easter egg: Hidden developer message appears randomly if (easterEggTimer % 3600 == 0) { // Every 60 seconds var messages = ["The developer is watching... 👁️", "Viggens are secretly plotting...", "Glen approves of your gameplay", "Goosandra whispers your name...", "The code is strong with this one", "FRVR games are the best games! 🎮"]; var randomMsg = messages[Math.floor(Math.random() * messages.length)]; var devMsg = new Text2(randomMsg, { size: 40, fill: 0x00FFFF }); devMsg.anchor.set(0.5, 0.5); devMsg.x = 1024; devMsg.y = 2000; devMsg.alpha = 0; game.addChild(devMsg); // Fade in and out tween(devMsg, { alpha: 1, y: 1800 }, { duration: 1000, onFinish: function onFinish() { tween(devMsg, { alpha: 0, y: 1600 }, { duration: 1000, onFinish: function onFinish() { devMsg.destroy(); } }); } }); } };
===================================================================
--- original.js
+++ change.js
@@ -659,8 +659,30 @@
addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity);
};
return self;
});
+var Soda = Item.expand(function () {
+ var self = Item.call(this);
+ var graphics = self.attachAsset('playerBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ graphics.tint = 0xFF4500; // Orange red for soda
+ graphics.scaleX = 1.3;
+ graphics.scaleY = 1.3;
+ self.itemId = 'soda';
+ self.itemName = 'Soda';
+ self.itemType = 'consumable';
+ self.description = 'Restores 30 health and increases fire rate for 10 seconds';
+ self.rarity = 'common';
+ self.healAmount = 30;
+ self.fireRateBoostDuration = 600; // 10 seconds at 60fps
+ self.collectEffect = function () {
+ LK.effects.flashObject(player, 0xFF4500, 600);
+ addToInventory(self.itemId, self.itemName, self.itemType, self.description, self.rarity);
+ };
+ return self;
+});
var PowerCore = Item.expand(function () {
var self = Item.call(this);
var graphics = self.attachAsset('bossBullet', {
anchorX: 0.5,
@@ -889,8 +911,10 @@
var easterEggTimer = 0;
var energyDrinkActive = false;
var energyDrinkTimer = 0;
var basePlayerSpeed = 8;
+var sodaFireRateActive = false;
+var sodaFireRateTimer = 0;
// UI Elements
var healthBar;
var bossHealthBar;
var levelText;
@@ -1027,22 +1051,63 @@
}
storage.inventory = gameInventory;
return true;
}
+ } else if (itemId === 'soda') {
+ // Heal first
+ player.health = Math.min(player.maxHealth, player.health + 30);
+ LK.effects.flashObject(player, 0xFF4500, 600);
+ // Activate fire rate boost
+ if (!sodaFireRateActive) {
+ sodaFireRateActive = true;
+ sodaFireRateTimer = 600; // 10 seconds
+ // Show fire rate boost message
+ var fireRateMsg = new Text2('🥤 FIRE RATE BOOST! 🥤', {
+ size: 50,
+ fill: 0xFF4500
+ });
+ fireRateMsg.anchor.set(0.5, 0.5);
+ fireRateMsg.x = 1024;
+ fireRateMsg.y = 1800;
+ game.addChild(fireRateMsg);
+ tween(fireRateMsg, {
+ alpha: 0,
+ y: 1600,
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ fireRateMsg.destroy();
+ }
+ });
+ }
+ gameInventory[itemId + '_quantity']--;
+ if (gameInventory[itemId + '_quantity'] <= 0) {
+ delete gameInventory[itemId + '_name'];
+ delete gameInventory[itemId + '_type'];
+ delete gameInventory[itemId + '_description'];
+ delete gameInventory[itemId + '_rarity'];
+ delete gameInventory[itemId + '_quantity'];
+ }
+ storage.inventory = gameInventory;
+ return true;
}
return false;
}
function spawnRandomItem(x, y) {
if (Math.random() < 0.3) {
// 30% chance to spawn item
var itemType = Math.random();
var newItem;
- if (itemType < 0.4) {
+ if (itemType < 0.3) {
newItem = new HealthPotion();
- } else if (itemType < 0.65) {
+ } else if (itemType < 0.5) {
newItem = new PowerCore();
- } else if (itemType < 0.85) {
+ } else if (itemType < 0.65) {
newItem = new EnergyDrink();
+ } else if (itemType < 0.85) {
+ newItem = new Soda();
} else {
newItem = new ViggenCrystal();
}
newItem.x = Math.max(100, Math.min(1948, x + (Math.random() - 0.5) * 200));
@@ -2451,10 +2516,13 @@
var pulseScale = 1 + Math.sin(easterEggTimer * 0.15) * 0.1;
player.scaleX = pulseScale;
player.scaleY = pulseScale;
}
- // Auto-shoot (with rapid fire Easter egg)
+ // Auto-shoot (with rapid fire Easter egg and soda boost)
var shootInterval = rapidFireUnlocked ? 5 : 15;
+ if (sodaFireRateActive) {
+ shootInterval = Math.max(3, Math.floor(shootInterval * 0.6)); // 40% faster fire rate
+ }
if (LK.ticks % shootInterval == 0 && !isGameOver) {
player.shoot();
}
// Handle energy drink effect
@@ -2506,8 +2574,57 @@
}
});
}
}
+ // Handle soda fire rate boost effect
+ if (sodaFireRateActive) {
+ sodaFireRateTimer--;
+ // Add fizzy particle effect while active
+ if (LK.ticks % 15 === 0) {
+ var fizz = LK.getAsset('playerBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: player.x + (Math.random() - 0.5) * 60,
+ y: player.y + (Math.random() - 0.5) * 60,
+ scaleX: 0.2,
+ scaleY: 0.2
+ });
+ fizz.tint = 0xFF4500;
+ game.addChild(fizz);
+ tween(fizz, {
+ alpha: 0,
+ y: fizz.y - 80,
+ scaleX: 0.6,
+ scaleY: 0.6
+ }, {
+ duration: 600,
+ onFinish: function onFinish() {
+ fizz.destroy();
+ }
+ });
+ }
+ if (sodaFireRateTimer <= 0) {
+ sodaFireRateActive = false;
+ // Show effect ended message
+ var endMsg = new Text2('Fire rate boost ended', {
+ size: 40,
+ fill: 0x888888
+ });
+ endMsg.anchor.set(0.5, 0.5);
+ endMsg.x = 1024;
+ endMsg.y = 1900;
+ game.addChild(endMsg);
+ tween(endMsg, {
+ alpha: 0,
+ y: 1700
+ }, {
+ duration: 1500,
+ onFinish: function onFinish() {
+ endMsg.destroy();
+ }
+ });
+ }
+ }
// Easter egg effects
easterEggTimer++;
// Rainbow mode effect
if (rainbowModeUnlocked) {