User prompt
Pon el apartado skins al lado del apartado shop de forma simétrica
User prompt
Mueve en apartado de skins para que no se fusione con otros apartados
User prompt
Haz un apartado llamado skins en el menú principal donde salgan las skins compradas y que esas skins cuando las compres en la shop se quiten de ella ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Elimina la skin naranja de la tienda
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'shopContainer.addChild(aircraftTitleText);' Line Number: 2374
User prompt
Elimina la skin naranja de la tienda
User prompt
Cambia el nombre shop por skins
User prompt
Haz que la skin naranja solo se pueda conseguir con el código, y una vez ya introducido el código aparezca en la tienda ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Cambia el código orangefrreskin por orangefreeskin
User prompt
Haz que la línea de meta aparezca en el punto donde el progreso termina
User prompt
Haz que la línea de meta aparezca justo cuando el progreso termina
User prompt
En la tienda, baja el botón de atras
User prompt
En el menú principal, donde pone BETA, cámbialo por 0.00.02
User prompt
Pon una separación un poco mayor entre torres
User prompt
Pero haz que el hueco entre torres conecte con las siguientes torres para que no sea imposible pasarse el nivel
User prompt
Haz una dos líneas imaginarias en el centro del mapa, delimitando la zona en la que las torres se puedan generar, para que no sea imposible
User prompt
Vuelve a mejorar la generación de las torres, en algunos niveles es imposible pasarlas
User prompt
Haz que en la generación de las torres, no sea imposible de pasarlas, ya que algunos niveles no se pueden superar
User prompt
Aumenta la velocidad del avión, de forma en la que por cada nivel que pase, la velocidad sea mayor, pero que deje de aumentar en un nivel determinado para que no sea incontrolable
User prompt
Crea un código llamado ORANGEFRRESKIN que al reclamarlo te de un color de avión naranja y se te añada gratis a la tienda ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
En el menú principal, en la parte de abajo, pon versión: (la versión que es, en este caso la BETA)
User prompt
Haz un apartado en el menu principal que ponga el score total que has conseguido ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Soluciona el bug del progreso y la linea de meta, la linea de meta debe estar justo en los numeros propuestos del progreso
User prompt
Mejora la skin del avion
User prompt
Mejora todo lo que puedas el juego ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1"); var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Aircraft = Container.expand(function () { var self = Container.call(this); // Main aircraft fuselage (body) var aircraftGraphics = self.attachAsset('aircraft', { anchorX: 0.5, anchorY: 0.5 }); // Main wings (positioned lower on fuselage for realism) var mainWing = self.attachAsset('aircraftWing', { anchorX: 0.5, anchorY: 0.5 }); mainWing.x = -15; mainWing.y = 0; // Aircraft tail (vertical stabilizer) var tail = self.attachAsset('aircraftTail', { anchorX: 0.5, anchorY: 0.5 }); tail.x = -60; tail.y = 0; tail.rotation = Math.PI / 2; // Vertical orientation // Horizontal stabilizer (smaller wing at tail) var horizontalStab = self.attachAsset('aircraftWing', { anchorX: 0.5, anchorY: 0.5 }); horizontalStab.x = -55; horizontalStab.y = 0; horizontalStab.scaleX = 0.4; horizontalStab.scaleY = 0.6; // Cockpit window var cockpit = self.attachAsset('aircraftCockpit', { anchorX: 0.5, anchorY: 0.5 }); cockpit.x = 35; cockpit.y = -2; // Engine nacelles under wings var leftEngine = self.attachAsset('aircraftEngine', { anchorX: 0.5, anchorY: 0.5 }); leftEngine.x = -20; leftEngine.y = 12; var rightEngine = self.attachAsset('aircraftEngine', { anchorX: 0.5, anchorY: 0.5 }); rightEngine.x = -20; rightEngine.y = -12; // Propeller at front var propeller = self.attachAsset('aircraftPropeller', { anchorX: 0.5, anchorY: 0.5 }); propeller.x = 70; propeller.y = 0; // Animate propeller rotation propeller.rotationSpeed = 0.3; self.speed = 3; self.lastY = 0; self.update = function () { // Update last position for collision detection self.lastY = self.y; // Animate propeller spinning with variable speed propeller.rotation += propeller.rotationSpeed * (1 + self.speed * 0.1); // Create engine trail particles with enhanced effects if (LK.ticks % 3 === 0 && gameStarted) { createEngineParticle(self.x - 50, self.y); // Add occasional spark effects if (Math.random() < 0.3) { createSparkParticle(self.x - 40, self.y + (Math.random() - 0.5) * 20); } } // Add subtle floating animation for more dynamic feel if (!self.floatingTween) { self.floatingTween = true; var originalY = self.y; tween(self, { y: originalY + 8 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { y: originalY - 8 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { self.floatingTween = false; } }); } }); } }; return self; }); var Cloud = Container.expand(function () { var self = Container.call(this); // Choose random cloud type var cloudTypes = ['cloud1', 'cloud2', 'cloud3']; var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)]; // Main cloud body var mainCloud = self.attachAsset(cloudType, { anchorX: 0.5, anchorY: 0.5 }); // Add smaller cloud parts for more realistic shape var cloud2 = self.attachAsset(cloudType, { anchorX: 0.5, anchorY: 0.5 }); cloud2.x = -30 + Math.random() * 60; cloud2.y = -15 + Math.random() * 30; cloud2.scaleX = 0.6 + Math.random() * 0.4; cloud2.scaleY = 0.6 + Math.random() * 0.4; cloud2.alpha = 0.8; var cloud3 = self.attachAsset(cloudType, { anchorX: 0.5, anchorY: 0.5 }); cloud3.x = -20 + Math.random() * 40; cloud3.y = -10 + Math.random() * 20; cloud3.scaleX = 0.4 + Math.random() * 0.3; cloud3.scaleY = 0.4 + Math.random() * 0.3; cloud3.alpha = 0.6; // Set random speed and scale self.speed = 0.5 + Math.random() * 1.5; self.scaleX = 0.8 + Math.random() * 0.6; self.scaleY = 0.8 + Math.random() * 0.6; self.alpha = 0.7 + Math.random() * 0.3; self.update = function () { // Move cloud from right to left self.x -= self.speed; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); // Coin visual var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); // Floating and spinning animation self.floatOffset = Math.random() * Math.PI * 2; self.collected = false; self.update = function () { // Floating animation self.y += Math.sin(LK.ticks * 0.15 + self.floatOffset) * 0.8; // Spinning animation coinGraphics.rotation += 0.1; // Pulsing scale effect var scale = 1.2 + Math.sin(LK.ticks * 0.08) * 0.2; coinGraphics.scaleX = scale; coinGraphics.scaleY = scale; // Move from right to left var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); self.x -= speed; }; return self; }); var FinishLine = Container.expand(function () { var self = Container.call(this); // Main finish line var lineGraphics = self.attachAsset('finishLine', { anchorX: 0.5, anchorY: 0.5 }); // Add flags at top and bottom for visibility var topFlag = self.attachAsset('finishFlag', { anchorX: 0.5, anchorY: 0.5 }); topFlag.y = -1300; var bottomFlag = self.attachAsset('finishFlag', { anchorX: 0.5, anchorY: 0.5 }); bottomFlag.y = 1300; self.lastX = 0; self.crossed = false; self.update = function () { // Update last position before moving self.lastX = self.x; // Move finish line from right to left (match tower speed for levels 1-100) var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); // Match tower speed progression self.x -= speed; }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); // Small particle visual var particleGraphics = self.attachAsset('cloud1', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1 }); particleGraphics.alpha = 0.7; particleGraphics.tint = 0xFF6600; // Orange-ish color self.velocityX = -2 - Math.random() * 3; self.velocityY = (Math.random() - 0.5) * 2; self.life = 60; // 1 second at 60fps self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.life--; particleGraphics.alpha *= 0.98; // Fade out particleGraphics.scaleX *= 0.99; // Shrink particleGraphics.scaleY *= 0.99; if (self.life <= 0) { self.destroy(); var index = particles.indexOf(self); if (index > -1) particles.splice(index, 1); } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); // Power-up visual var powerUpGraphics = self.attachAsset('finishFlag', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); powerUpGraphics.tint = 0x00FFFF; // Cyan color for power-ups // Floating animation self.floatOffset = Math.random() * Math.PI * 2; self.collected = false; self.update = function () { // Floating animation self.y += Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.5; // Rotation animation powerUpGraphics.rotation += 0.05; // Move from right to left var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); self.x -= speed; }; return self; }); var SparkParticle = Container.expand(function () { var self = Container.call(this); // Small spark visual var sparkGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.05, scaleY: 0.05 }); sparkGraphics.alpha = 1; sparkGraphics.tint = 0xFFAA00; // Orange spark color self.velocityX = -1 - Math.random() * 2; self.velocityY = (Math.random() - 0.5) * 3; self.life = 30; // Half second at 60fps self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.velocityY += 0.1; // Gravity effect self.life--; sparkGraphics.alpha *= 0.95; // Faster fade than regular particles sparkGraphics.scaleX *= 0.98; sparkGraphics.scaleY *= 0.98; sparkGraphics.rotation += 0.2; // Spinning effect if (self.life <= 0) { self.destroy(); var index = sparkParticles.indexOf(self); if (index > -1) sparkParticles.splice(index, 1); } }; return self; }); var Tower = Container.expand(function () { var self = Container.call(this); // Tower base var towerBase = self.attachAsset('towerBase', { anchorX: 0.5, anchorY: 0.5 }); // Tower top var towerTop = self.attachAsset('towerTop', { anchorX: 0.5, anchorY: 0.5 }); towerTop.y = -420; // Position at top of tower // Add windows to make it look more realistic for (var w = 0; w < 3; w++) { var window1 = self.attachAsset('towerWindow', { anchorX: 0.5, anchorY: 0.5 }); window1.x = -30; window1.y = -300 + w * 150; var window2 = self.attachAsset('towerWindow', { anchorX: 0.5, anchorY: 0.5 }); window2.x = 30; window2.y = -300 + w * 150; } self.lastX = 0; self.passed = false; self.update = function () { // Update last position before moving self.lastX = self.x; // Move tower from right to left (progressive speed increase for levels 1-100) var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); // Gradual speed increase, capped at 6 self.x -= speed; }; return self; }); /**** * Initialize Game ****/ // Game variables var game = new LK.Game({ backgroundColor: 0x87CEFA // More realistic sky blue background }); /**** * Game Code ****/ //Storage plugin for persistent game data // Game variables // Initialize assets for the tower dodge flight game var aircraft; var towers = []; var clouds = []; var finishLine = null; var showingMenu = false; var currentLevel = storage.currentLevel || 1; var levelScore = 0; var towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc. var towerSpawnTimer = 0; var gameStarted = false; var menuContainer = null; var mainMenuContainer = null; var showingMainMenu = true; var showingCodesMenu = false; var codesMenuContainer = null; var adminMode = false; var adminModeEndTime = 0; // Enhanced settings storage var gameSettings = storage.gameSettings || { soundEnabled: true, musicEnabled: true, difficulty: 'normal', highestLevelReached: 1, particlesEnabled: true, screenshakeEnabled: true }; // Additional game variables var powerUps = []; var particles = []; var sparkParticles = []; var powerUpSpawnTimer = 0; var invulnerabilityTime = 0; var comboMultiplier = 1; var lastPowerUpTime = 0; var musicPlaying = false; var coins = []; var coinSpawnTimer = 0; var showingShop = false; var shopContainer = null; // Initialize player coins and shop items var playerCoins = storage.playerCoins || 0; var ownedAircraftStyles = storage.ownedAircraftStyles || ['default']; var ownedTowerStyles = storage.ownedTowerStyles || ['default']; var currentAircraftStyle = storage.currentAircraftStyle || 'default'; var currentTowerStyle = storage.currentTowerStyle || 'default'; // Shop items with prices var aircraftStyles = [{ id: 'default', name: 'Classic', price: 0, color: 0xf0f0f0 }, { id: 'red', name: 'Fire Bird', price: 100, color: 0xff4444 }, { id: 'blue', name: 'Sky Runner', price: 150, color: 0x4444ff }, { id: 'green', name: 'Forest Wing', price: 200, color: 0x44ff44 }, { id: 'purple', name: 'Royal Jet', price: 300, color: 0x8844ff }, { id: 'gold', name: 'Golden Eagle', price: 500, color: 0xffd700 }]; var towerStyles = [{ id: 'default', name: 'Stone Tower', price: 0, color: 0x8b4513 }, { id: 'metal', name: 'Metal Tower', price: 120, color: 0x778899 }, { id: 'crystal', name: 'Crystal Tower', price: 180, color: 0x99ddff }, { id: 'dark', name: 'Dark Tower', price: 250, color: 0x444444 }, { id: 'rainbow', name: 'Rainbow Tower', price: 400, color: 0xff6699 }]; // Update settings when needed if (currentLevel > gameSettings.highestLevelReached) { gameSettings.highestLevelReached = currentLevel; storage.gameSettings = gameSettings; } // Check if admin mode is still active from previous session var storedAdminEndTime = storage.adminModeEndTime || 0; if (storedAdminEndTime > Date.now()) { adminMode = true; adminModeEndTime = storedAdminEndTime; } // UI Elements var levelText = new Text2('Level: 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); LK.gui.topLeft.addChild(levelText); levelText.x = 120; // Avoid top-left menu area levelText.y = 20; var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); var progressText = new Text2('Progress: 0/10', { size: 50, fill: 0xFFFFFF }); progressText.anchor.set(0.5, 0); LK.gui.top.addChild(progressText); progressText.y = 100; var coinsText = new Text2('Coins: ' + playerCoins, { size: 50, fill: 0xFFD700 }); coinsText.anchor.set(0, 0); LK.gui.topLeft.addChild(coinsText); coinsText.x = 120; coinsText.y = 80; // Initialize aircraft aircraft = game.addChild(new Aircraft()); aircraft.x = 300; aircraft.y = 1366; // Center vertically aircraft.lastIntersecting = false; // Show main menu at start createMainMenu(); // Touch controls for aircraft movement var dragActive = false; game.down = function (x, y, obj) { if (showingMainMenu || showingMenu) return; dragActive = true; }; game.up = function (x, y, obj) { if (showingMainMenu || showingMenu) return; dragActive = false; }; game.move = function (x, y, obj) { if (showingMainMenu || showingMenu) return; var targetY = y; if (dragActive) { targetY = y; } // Keep aircraft within screen bounds if (targetY < 50) targetY = 50; if (targetY > 2680) targetY = 2680; // Smooth tween animation for aircraft movement tween.stop(aircraft, { y: true }); tween(aircraft, { y: targetY }, { duration: 200, easing: tween.easeOut }); }; // Function to spawn tower function spawnTower() { var tower = new Tower(); tower.x = 2200; // Start from right edge // Random height position with gap for aircraft to pass (adjusted for levels 1-100) var gapSize = Math.max(300, 700 - Math.min(currentLevel, 10) * 30); // Gradual decrease, minimum gap of 300 var gapPosition = Math.random() * (2732 - gapSize - 200) + 100; // Create top tower var topTower = game.addChild(new Tower()); topTower.x = tower.x; topTower.y = gapPosition / 2; topTower.lastIntersecting = false; towers.push(topTower); // Apply current tower style var currentTowerStyleData = towerStyles.find(function (style) { return style.id === currentTowerStyle; }); if (currentTowerStyleData) { topTower.children[0].tint = currentTowerStyleData.color; // Tower base topTower.children[1].tint = currentTowerStyleData.color; // Tower top } // Create bottom tower var bottomTower = game.addChild(new Tower()); bottomTower.x = tower.x; bottomTower.y = gapPosition + gapSize + (2732 - gapPosition - gapSize) / 2; bottomTower.lastIntersecting = false; towers.push(bottomTower); // Apply current tower style if (currentTowerStyleData) { bottomTower.children[0].tint = currentTowerStyleData.color; // Tower base bottomTower.children[1].tint = currentTowerStyleData.color; // Tower top } } // Function to spawn clouds function spawnCloud() { var cloud = new Cloud(); cloud.x = 2200 + Math.random() * 400; // Start from right edge with some variation cloud.y = 200 + Math.random() * 2300; // Random height across screen clouds.push(cloud); game.addChild(cloud); } // Function to spawn finish line function spawnFinishLine() { if (finishLine) return; // Don't spawn if already exists finishLine = game.addChild(new FinishLine()); finishLine.x = 2500; // Start further right than towers finishLine.y = 1366; // Center vertically finishLine.lastIntersecting = false; } // Function to create engine particles function createEngineParticle(x, y) { if (!gameSettings.particlesEnabled || particles.length > 20) return; var particle = new Particle(); particle.x = x + (Math.random() - 0.5) * 20; particle.y = y + (Math.random() - 0.5) * 10; particles.push(particle); game.addChild(particle); } // Function to create spark particles function createSparkParticle(x, y) { if (!gameSettings.particlesEnabled || sparkParticles.length > 15) return; var spark = new SparkParticle(); spark.x = x; spark.y = y; sparkParticles.push(spark); game.addChild(spark); } // Function to create tower destruction effect function createTowerDestructionEffect(x, y) { if (!gameSettings.particlesEnabled) return; // Create multiple debris particles for (var i = 0; i < 8; i++) { var debris = new Particle(); debris.x = x + (Math.random() - 0.5) * 100; debris.y = y + (Math.random() - 0.5) * 200; debris.children[0].tint = 0x8B4513; // Brown debris color debris.velocityX = (Math.random() - 0.5) * 8; debris.velocityY = -Math.random() * 5; debris.life = 120; // Longer life for debris particles.push(debris); game.addChild(debris); } // Create sparks for (var j = 0; j < 5; j++) { createSparkParticle(x + (Math.random() - 0.5) * 80, y + (Math.random() - 0.5) * 150); } } // Function to spawn coin function spawnCoin() { var coin = new Coin(); coin.x = 2200; coin.y = 200 + Math.random() * 2300; coin.lastIntersecting = false; coins.push(coin); game.addChild(coin); } // Function to spawn power-up function spawnPowerUp() { var powerUp = new PowerUp(); powerUp.x = 2200; powerUp.y = 200 + Math.random() * 2300; powerUp.lastIntersecting = false; powerUps.push(powerUp); game.addChild(powerUp); } // Function to apply power-up effect function applyPowerUpEffect() { invulnerabilityTime = 300; // 5 seconds at 60fps comboMultiplier = Math.min(comboMultiplier + 0.5, 3); // Max 3x multiplier lastPowerUpTime = LK.ticks; // Visual feedback LK.effects.flashObject(aircraft, 0x00FFFF, 500); LK.getSound('powerup').play(); // Update aircraft appearance during invulnerability tween(aircraft, { alpha: 0.7 }, { duration: 100, onFinish: function onFinish() { tween(aircraft, { alpha: 1 }, { duration: 100 }); } }); } // Function to create level completion menu function createLevelMenu() { showingMenu = true; menuContainer = new Container(); game.addChild(menuContainer); // Semi-transparent background var menuBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 2, alpha: 0.8 }); menuBg.x = 1024; menuBg.y = 1366; menuContainer.addChild(menuBg); // Title text var titleText = new Text2('Level ' + currentLevel + ' Complete!', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 1200; menuContainer.addChild(titleText); // Retry button var retryText = new Text2('Retry Level', { size: 60, fill: 0x00FF00 }); retryText.anchor.set(0.5, 0.5); retryText.x = 1024; retryText.y = 1300; retryText.interactive = true; retryText.down = function () { restartCurrentLevel(); }; menuContainer.addChild(retryText); // Next level button var nextText = new Text2('Next Level', { size: 60, fill: 0x0080FF }); nextText.anchor.set(0.5, 0.5); nextText.x = 1024; nextText.y = 1400; nextText.interactive = true; nextText.down = function () { goToNextLevel(); }; menuContainer.addChild(nextText); // Return to level 1 button var returnText = new Text2('Return to Level 1', { size: 60, fill: 0xFF8000 }); returnText.anchor.set(0.5, 0.5); returnText.x = 1024; returnText.y = 1500; returnText.interactive = true; returnText.down = function () { returnToLevel1(); }; menuContainer.addChild(returnText); } // Function to restart current level function restartCurrentLevel() { hideMenu(); levelScore = 0; // Clear existing towers and finish line clearLevel(); // Reset aircraft position aircraft.x = 300; aircraft.y = 1366; // Update UI progressText.setText('Progress: 0/' + towersToComplete); } // Function to go to next level function goToNextLevel() { hideMenu(); completeLevel(); } // Function to return to level 1 function returnToLevel1() { hideMenu(); currentLevel = 1; storage.currentLevel = 1; levelScore = 0; towersToComplete = 5 * currentLevel; // Clear existing towers and finish line clearLevel(); // Reset aircraft position aircraft.x = 300; aircraft.y = 1366; // Update UI levelText.setText('Level: ' + currentLevel); progressText.setText('Progress: 0/' + towersToComplete); } // Function to create main menu function createMainMenu() { showingMainMenu = true; mainMenuContainer = new Container(); game.addChild(mainMenuContainer); // Start menu music if (gameSettings.musicEnabled) { LK.stopMusic(); LK.playMusic('menuMusic', { loop: true }); musicPlaying = false; // Reset flag so game music can start } // Semi-transparent background var menuBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 4, alpha: 0.9 }); menuBg.x = 1024; menuBg.y = 1366; mainMenuContainer.addChild(menuBg); // Game title var titleText = new Text2('TOWER DODGE', { size: 120, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; titleText.alpha = 0; mainMenuContainer.addChild(titleText); // Animate title entrance tween(titleText, { y: 750, alpha: 1 }, { duration: 1000, easing: tween.bounceOut }); // Subtitle var subtitleText = new Text2('Navigate through the towers!', { size: 60, fill: 0xFFFFFF }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 850; mainMenuContainer.addChild(subtitleText); // Play button var playText = new Text2('PLAY', { size: 80, fill: 0x00FF00 }); playText.anchor.set(0.5, 0.5); playText.x = 1024; playText.y = 1000; playText.alpha = 0; playText.scaleX = 0.5; playText.scaleY = 0.5; playText.interactive = true; playText.down = function () { // Add button press animation tween(playText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(playText, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); hideMainMenu(); startGame(); }; mainMenuContainer.addChild(playText); // Animate play button entrance with delay tween(playText, { y: 1050, alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.elasticOut }); // Shop button var shopText = new Text2('SHOP', { size: 80, fill: 0x00FFFF }); shopText.anchor.set(0.5, 0.5); shopText.x = 1024; shopText.y = 1150; shopText.interactive = true; shopText.down = function () { hideMainMenu(); showShop(); }; mainMenuContainer.addChild(shopText); // Codes button var codesText = new Text2('CODES', { size: 80, fill: 0xFF8000 }); codesText.anchor.set(0.5, 0.5); codesText.x = 1024; codesText.y = 1250; codesText.interactive = true; codesText.down = function () { hideMainMenu(); showCodesMenu(); }; mainMenuContainer.addChild(codesText); // Current level indicator var levelIndicatorText = new Text2('Continue from Level ' + currentLevel, { size: 50, fill: 0xFFFF00 }); levelIndicatorText.anchor.set(0.5, 0.5); levelIndicatorText.x = 1024; levelIndicatorText.y = 1350; mainMenuContainer.addChild(levelIndicatorText); // Enhanced coins display section with background var coinsDisplayBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.5, scaleY: 0.7, alpha: 0.4 }); coinsDisplayBg.x = 1024; coinsDisplayBg.y = 1450; mainMenuContainer.addChild(coinsDisplayBg); // Coins icon simulation using coin asset var coinsIcon = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); coinsIcon.x = 850; coinsIcon.y = 1450; mainMenuContainer.addChild(coinsIcon); // Enhanced coins indicator with larger, more prominent text var coinsIndicatorText = new Text2('Your Coins: ' + playerCoins, { size: 55, fill: 0xFFD700 }); coinsIndicatorText.anchor.set(0.5, 0.5); coinsIndicatorText.x = 1100; coinsIndicatorText.y = 1450; mainMenuContainer.addChild(coinsIndicatorText); // Add subtle animation to coins display coinsIcon.rotationSpeed = 0.02; tween(coinsIcon, { rotation: Math.PI * 2 }, { duration: 3000, loop: true, easing: tween.linear }); // Add pulsing effect to coins text tween(coinsIndicatorText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 1500, loop: true, yoyo: true, easing: tween.easeInOut }); } // Function to show codes menu function showCodesMenu() { showingCodesMenu = true; codesMenuContainer = new Container(); game.addChild(codesMenuContainer); // Create layered background for depth effect var outerBorder = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 11, scaleY: 4.5, alpha: 0.2 }); outerBorder.x = 1024; outerBorder.y = 1366; codesMenuContainer.addChild(outerBorder); // Main background with gradient effect var codesBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10.5, scaleY: 4.2, alpha: 0.95 }); codesBg.x = 1024; codesBg.y = 1366; codesMenuContainer.addChild(codesBg); // Inner frame for modern look var innerFrame = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 4, alpha: 0.15 }); innerFrame.x = 1024; innerFrame.y = 1366; codesMenuContainer.addChild(innerFrame); // Title with enhanced styling and glow effect var titleBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 1, alpha: 0.4 }); titleBg.x = 1024; titleBg.y = 750; codesMenuContainer.addChild(titleBg); var titleText = new Text2('ENTER CODE', { size: 95, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 750; codesMenuContainer.addChild(titleText); // Add animated title underline var titleUnderline = LK.getAsset('finishLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 0, scaleY: 0.15 }); titleUnderline.x = 1024; titleUnderline.y = 815; codesMenuContainer.addChild(titleUnderline); // Animate underline appearance tween(titleUnderline, { scaleX: 5 }, { duration: 800, easing: tween.easeOut }); // Enhanced code input display with multiple layers var inputOuterBorder = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 6.5, scaleY: 0.65, alpha: 0.2 }); inputOuterBorder.x = 1024; inputOuterBorder.y = 950; codesMenuContainer.addChild(inputOuterBorder); var inputBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 6, scaleY: 0.55, alpha: 0.4 }); inputBg.x = 1024; inputBg.y = 950; codesMenuContainer.addChild(inputBg); var inputInner = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 5.5, scaleY: 0.45, alpha: 0.8 }); inputInner.x = 1024; inputInner.y = 950; codesMenuContainer.addChild(inputInner); var codeInputText = new Text2('', { size: 70, fill: 0x000000 }); codeInputText.anchor.set(0.5, 0.5); codeInputText.x = 1024; codeInputText.y = 950; codesMenuContainer.addChild(codeInputText); // Enhanced instructions with icon-like styling var instructionBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 4.5, scaleY: 0.4, alpha: 0.3 }); instructionBg.x = 1024; instructionBg.y = 1050; codesMenuContainer.addChild(instructionBg); var instructionText = new Text2('Tap keys below to enter your code', { size: 48, fill: 0xF0F0F0 }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 1050; codesMenuContainer.addChild(instructionText); // Create enhanced virtual keyboard with modern styling var currentCode = ''; var keyboardRows = ['QWERTYUIOP', 'ASDFGHJKL', 'ZXCVBNM']; var keySize = 70; var keySpacing = 130; var rowSpacing = 140; // Calculate starting positions for each row to center them perfectly with improved spacing var rowStartPositions = [1024 - (keyboardRows[0].length - 1) * keySpacing / 2, // QWERTY row 1024 - (keyboardRows[1].length - 1) * keySpacing / 2, // ASDF row 1024 - (keyboardRows[2].length - 1) * keySpacing / 2 // ZXCV row ]; for (var row = 0; row < keyboardRows.length; row++) { var letters = keyboardRows[row]; for (var col = 0; col < letters.length; col++) { var letter = letters[col]; // Create layered key design for modern look var keyShadow = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.45, scaleY: 0.65, alpha: 0.3 }); keyShadow.x = rowStartPositions[row] + col * keySpacing + 2; keyShadow.y = 1320 + row * rowSpacing + 2; codesMenuContainer.addChild(keyShadow); var keyBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.48, scaleY: 0.65, alpha: 0.9 }); keyBg.x = rowStartPositions[row] + col * keySpacing; keyBg.y = 1320 + row * rowSpacing; codesMenuContainer.addChild(keyBg); var keyHighlight = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.44, scaleY: 0.61, alpha: 0.6 }); keyHighlight.x = rowStartPositions[row] + col * keySpacing; keyHighlight.y = 1315 + row * rowSpacing; codesMenuContainer.addChild(keyHighlight); var keyText = new Text2(letter, { size: 140, fill: 0x000000 }); keyText.anchor.set(0.5, 0.5); keyText.x = rowStartPositions[row] + col * keySpacing; keyText.y = 1320 + row * rowSpacing; keyText.interactive = true; keyText.letter = letter; keyText.keyBg = keyBg; keyText.keyHighlight = keyHighlight; keyText.keyShadow = keyShadow; keyText.down = function () { // Enhanced button press animation with multiple elements tween(this, { scaleX: 1.15, scaleY: 1.15, y: this.y + 3 }, { duration: 80, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1, y: this.y - 3 }, { duration: 120, easing: tween.easeOut }); }.bind(this) }); // Animate key background tween(this.keyBg, { scaleX: 0.48, scaleY: 0.68, alpha: 1 }, { duration: 80, onFinish: function () { tween(this.keyBg, { scaleX: 0.42, scaleY: 0.62, alpha: 0.9 }, { duration: 120 }); }.bind(this) }); // Animate highlight tween(this.keyHighlight, { scaleX: 0.44, scaleY: 0.64, alpha: 0.8 }, { duration: 80, onFinish: function () { tween(this.keyHighlight, { scaleX: 0.38, scaleY: 0.58, alpha: 0.6 }, { duration: 120 }); }.bind(this) }); if (currentCode.length < 25) { currentCode += this.letter; codeInputText.setText(currentCode); // Animate input text when adding character tween(codeInputText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(codeInputText, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } }; codesMenuContainer.addChild(keyText); } } // Add numbers row (0-9) above the letters var numbersRow = '0123456789'; var numberRowY = 1120; var numberRowStartX = 1024 - (numbersRow.length - 1) * keySpacing / 2; for (var numCol = 0; numCol < numbersRow.length; numCol++) { var number = numbersRow[numCol]; // Add number key shadow for depth var numKeyShadow = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.51, scaleY: 0.68, alpha: 0.3 }); numKeyShadow.x = numberRowStartX + numCol * keySpacing + 2; numKeyShadow.y = numberRowY + 2; codesMenuContainer.addChild(numKeyShadow); // Add number key background var numKeyBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.48, scaleY: 0.65, alpha: 0.9 }); numKeyBg.x = numberRowStartX + numCol * keySpacing; numKeyBg.y = numberRowY; codesMenuContainer.addChild(numKeyBg); // Add number key highlight var numKeyHighlight = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.44, scaleY: 0.61, alpha: 0.6 }); numKeyHighlight.x = numberRowStartX + numCol * keySpacing; numKeyHighlight.y = numberRowY - 2; codesMenuContainer.addChild(numKeyHighlight); var numKeyText = new Text2(number, { size: 135, fill: 0x0080FF }); numKeyText.anchor.set(0.5, 0.5); numKeyText.x = numberRowStartX + numCol * keySpacing; numKeyText.y = numberRowY; numKeyText.interactive = true; numKeyText.letter = number; numKeyText.keyBg = numKeyBg; numKeyText.keyHighlight = numKeyHighlight; numKeyText.keyShadow = numKeyShadow; numKeyText.down = function () { // Enhanced button press animation matching letter keys tween(this, { scaleX: 1.15, scaleY: 1.15, y: this.y + 3 }, { duration: 80, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1, y: this.y - 3 }, { duration: 120, easing: tween.easeOut }); }.bind(this) }); // Animate key background tween(this.keyBg, { scaleX: 0.54, scaleY: 0.71, alpha: 1 }, { duration: 80, onFinish: function () { tween(this.keyBg, { scaleX: 0.48, scaleY: 0.65, alpha: 0.9 }, { duration: 120 }); }.bind(this) }); // Animate highlight tween(this.keyHighlight, { scaleX: 0.50, scaleY: 0.67, alpha: 0.8 }, { duration: 80, onFinish: function () { tween(this.keyHighlight, { scaleX: 0.44, scaleY: 0.61, alpha: 0.6 }, { duration: 120 }); }.bind(this) }); if (currentCode.length < 25) { currentCode += this.letter; codeInputText.setText(currentCode); // Animate input text when adding character tween(codeInputText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(codeInputText, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } }; codesMenuContainer.addChild(numKeyText); } // Create enhanced control button layout with improved design var buttonY = 1720; var buttonSpacing = 280; // Clear button with layered design (left) var clearShadow = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.3, scaleY: 0.85, alpha: 0.3 }); clearShadow.x = 1024 - buttonSpacing + 3; clearShadow.y = buttonY + 3; codesMenuContainer.addChild(clearShadow); var clearBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.25, scaleY: 0.82, alpha: 0.9 }); clearBg.x = 1024 - buttonSpacing; clearBg.y = buttonY; codesMenuContainer.addChild(clearBg); var clearHighlight = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.1, scaleY: 0.68, alpha: 0.4 }); clearHighlight.x = 1024 - buttonSpacing; clearHighlight.y = buttonY - 5; codesMenuContainer.addChild(clearHighlight); var clearText = new Text2('CLEAR', { size: 58, fill: 0x000000 }); clearText.anchor.set(0.5, 0.5); clearText.x = 1024 - buttonSpacing; clearText.y = buttonY; clearText.interactive = true; clearText.clearBg = clearBg; clearText.clearHighlight = clearHighlight; clearText.down = function () { // Enhanced button animation with 3D effect tween(this, { scaleX: 1.05, scaleY: 1.05, y: this.y + 2 }, { duration: 80, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1, y: this.y - 2 }, { duration: 120, easing: tween.easeOut }); }.bind(this) }); // Animate background elements tween(this.clearBg, { scaleX: 1.35, scaleY: 0.9, alpha: 1 }, { duration: 80, onFinish: function () { tween(this.clearBg, { scaleX: 1.25, scaleY: 0.82, alpha: 0.9 }, { duration: 120 }); }.bind(this) }); currentCode = ''; codeInputText.setText(''); // Animate input clearing tween(codeInputText, { alpha: 0.3 }, { duration: 200, onFinish: function onFinish() { tween(codeInputText, { alpha: 1 }, { duration: 200 }); } }); }; codesMenuContainer.addChild(clearText); // Submit button with layered design (right) var submitShadow = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.3, scaleY: 0.85, alpha: 0.3 }); submitShadow.x = 1024 + buttonSpacing + 3; submitShadow.y = buttonY + 3; codesMenuContainer.addChild(submitShadow); var submitBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.25, scaleY: 0.82, alpha: 0.9 }); submitBg.x = 1024 + buttonSpacing; submitBg.y = buttonY; codesMenuContainer.addChild(submitBg); var submitHighlight = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.1, scaleY: 0.68, alpha: 0.4 }); submitHighlight.x = 1024 + buttonSpacing; submitHighlight.y = buttonY - 5; codesMenuContainer.addChild(submitHighlight); var submitText = new Text2('SUBMIT', { size: 58, fill: 0x000000 }); submitText.anchor.set(0.5, 0.5); submitText.x = 1024 + buttonSpacing; submitText.y = buttonY; submitText.interactive = true; submitText.submitBg = submitBg; submitText.down = function () { // Enhanced button animation tween(this, { scaleX: 1.05, scaleY: 1.05, y: this.y + 2 }, { duration: 80, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1, y: this.y - 2 }, { duration: 120, easing: tween.easeOut }); }.bind(this) }); tween(this.submitBg, { scaleX: 1.35, scaleY: 0.9, alpha: 1 }, { duration: 80, onFinish: function () { tween(this.submitBg, { scaleX: 1.25, scaleY: 0.82, alpha: 0.9 }, { duration: 120 }); }.bind(this) }); if (currentCode === 'ZKUIT1GAMESSTAFFMODE') { // Success animation before activating admin mode tween(codeInputText, { fill: 0x00FF00, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { // Activate admin mode for 15 minutes adminMode = true; adminModeEndTime = Date.now() + 15 * 60 * 1000; // 15 minutes in milliseconds storage.adminModeEndTime = adminModeEndTime; hideCodesMenu(); showAdminMenu(); } }); } else if (currentCode === 'LEVELS') { // Success animation before showing levels menu tween(codeInputText, { fill: 0x00FF00, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { hideCodesMenu(); showLevelsMenu(); } }); } else if (currentCode === 'RESETALL') { // Success animation before resetting to level 1 tween(codeInputText, { fill: 0x00FF00, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { // Reset player progress to level 1 currentLevel = 1; storage.currentLevel = 1; levelScore = 0; towersToComplete = 5 * currentLevel; // Update game settings gameSettings.highestLevelReached = 1; storage.gameSettings = gameSettings; // Clear level and reset aircraft clearLevel(); aircraft.x = 300; aircraft.y = 1366; hideCodesMenu(); createMainMenu(); } }); } else if (currentCode === 'FREEMONEYBETA2025') { // Check if this code has already been used var usedCodes = storage.usedCodes || []; if (usedCodes.indexOf('FREEMONEYBETA2025') >= 0) { // Code already used - show error tween(codeInputText, { scaleX: 1.3, scaleY: 0.8, fill: 0xFF0000 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(codeInputText, { scaleX: 1, scaleY: 1, fill: 0x000000 }, { duration: 300, easing: tween.easeInOut }); } }); currentCode = ''; codeInputText.setText('CODE ALREADY USED'); LK.setTimeout(function () { codeInputText.setText(''); }, 2000); } else { // Success animation before awarding coins tween(codeInputText, { fill: 0x00FF00, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { // Award 200 coins playerCoins += 200; storage.playerCoins = playerCoins; // Mark code as used usedCodes.push('FREEMONEYBETA2025'); storage.usedCodes = usedCodes; // Flash screen gold for success LK.effects.flashScreen(0xFFD700, 500); // Play coin sound if available if (LK.getSound('coinCollect')) { LK.getSound('coinCollect').play(); } hideCodesMenu(); createMainMenu(); } }); } } else if (currentCode.indexOf('TPLEVELSTAFFLV') === 0) { // Extract level number from code (format: TPLEVELSTAFFLVnumero) var levelNumberStr = currentCode.substring(14); // Remove 'TPLEVELSTAFFLV' prefix var targetLevel = parseInt(levelNumberStr, 10); // Validate level number (must be between 1 and 100) if (!isNaN(targetLevel) && targetLevel >= 1 && targetLevel <= 100) { // Success animation before teleporting to level tween(codeInputText, { fill: 0x00FF00, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, onFinish: function onFinish() { // Transport player to specified level currentLevel = targetLevel; storage.currentLevel = currentLevel; levelScore = 0; towersToComplete = 5 * currentLevel; // Update game settings if new level is higher than previous highest if (currentLevel > gameSettings.highestLevelReached) { gameSettings.highestLevelReached = currentLevel; storage.gameSettings = gameSettings; } // Clear level and reset aircraft clearLevel(); aircraft.x = 300; aircraft.y = 1366; hideCodesMenu(); createMainMenu(); } }); } else { // Invalid level number - treat as wrong code tween(codeInputText, { scaleX: 1.3, scaleY: 0.8, fill: 0xFF0000 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(codeInputText, { scaleX: 1, scaleY: 1, fill: 0x000000 }, { duration: 300, easing: tween.easeInOut }); } }); currentCode = ''; codeInputText.setText('INVALID LEVEL'); LK.setTimeout(function () { codeInputText.setText(''); }, 2000); } } else { // Enhanced wrong code animation tween(codeInputText, { scaleX: 1.3, scaleY: 0.8, fill: 0xFF0000 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(codeInputText, { scaleX: 1, scaleY: 1, fill: 0x000000 }, { duration: 300, easing: tween.easeInOut }); } }); currentCode = ''; codeInputText.setText('INVALID CODE'); LK.setTimeout(function () { codeInputText.setText(''); }, 2000); } }; codesMenuContainer.addChild(submitText); // Back button with enhanced design (centered at bottom) var backShadow = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.1, scaleY: 0.75, alpha: 0.3 }); backShadow.x = 1024 + 2; backShadow.y = 1870 + 2; codesMenuContainer.addChild(backShadow); var backBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.05, scaleY: 0.72, alpha: 0.9 }); backBg.x = 1024; backBg.y = 1870; codesMenuContainer.addChild(backBg); var backText = new Text2('BACK', { size: 58, fill: 0x000000 }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 1870; backText.interactive = true; backText.backBg = backBg; backText.down = function () { // Enhanced back button animation tween(this, { scaleX: 1.05, scaleY: 1.05, y: this.y + 2 }, { duration: 80, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1, y: this.y - 2 }, { duration: 120, easing: tween.easeOut }); }.bind(this) }); tween(this.backBg, { scaleX: 1.15, scaleY: 0.8, alpha: 1 }, { duration: 80, onFinish: function () { tween(this.backBg, { scaleX: 1.05, scaleY: 0.72, alpha: 0.9 }, { duration: 120 }); }.bind(this) }); hideCodesMenu(); createMainMenu(); }; codesMenuContainer.addChild(backText); // Add sophisticated entrance animations with staggered timing // Animate title with bounce effect titleText.alpha = 0; titleText.scaleX = 0.3; titleText.scaleY = 0.3; titleText.y = titleText.y - 50; tween(titleText, { alpha: 1, scaleX: 1, scaleY: 1, y: titleText.y + 50 }, { duration: 800, easing: tween.bounceOut }); // Animate input area with cascading effect inputOuterBorder.alpha = 0; inputBg.alpha = 0; inputInner.alpha = 0; codeInputText.alpha = 0; instructionText.alpha = 0; instructionBg.alpha = 0; // Staggered input area animations tween(inputOuterBorder, { alpha: 0.2 }, { duration: 300 }); LK.setTimeout(function () { tween(inputBg, { alpha: 0.4 }, { duration: 300 }); }, 100); LK.setTimeout(function () { tween(inputInner, { alpha: 0.8 }, { duration: 300 }); }, 200); LK.setTimeout(function () { tween(codeInputText, { alpha: 1 }, { duration: 400 }); }, 300); LK.setTimeout(function () { tween(instructionBg, { alpha: 0.3 }, { duration: 300 }); }, 400); LK.setTimeout(function () { tween(instructionText, { alpha: 1 }, { duration: 400 }); }, 500); // Animate keyboard keys with wave effect for (var animRow = 0; animRow < keyboardRows.length; animRow++) { for (var animCol = 0; animCol < keyboardRows[animRow].length; animCol++) { (function (row, col) { LK.setTimeout(function () { var keyIndex = row * 10 + col; // Approximate index for timing var targetKey = codesMenuContainer.children.filter(function (child) { return child.letter && child.x === rowStartPositions[row] + col * keySpacing && child.y === 1320 + row * rowSpacing; })[0]; if (targetKey) { targetKey.alpha = 0; targetKey.scaleX = 0.5; targetKey.scaleY = 0.5; tween(targetKey, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } }, 600 + row * 50 + col * 20); })(animRow, animCol); } } // Animate number keys for (var numAnimCol = 0; numAnimCol < numbersRow.length; numAnimCol++) { (function (col) { LK.setTimeout(function () { var targetNumKey = codesMenuContainer.children.filter(function (child) { return child.letter && child.x === numberRowStartX + col * keySpacing && child.y === numberRowY; })[0]; if (targetNumKey) { targetNumKey.alpha = 0; targetNumKey.scaleX = 0.5; targetNumKey.scaleY = 0.5; tween(targetNumKey, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } }, 550 + col * 25); })(numAnimCol); } // Animate control buttons with final cascade LK.setTimeout(function () { clearText.alpha = 0; clearText.scaleX = 0.8; clearText.scaleY = 0.8; tween(clearText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 400, easing: tween.easeOut }); }, 1200); LK.setTimeout(function () { submitText.alpha = 0; submitText.scaleX = 0.8; submitText.scaleY = 0.8; tween(submitText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 400, easing: tween.easeOut }); }, 1300); LK.setTimeout(function () { backText.alpha = 0; backText.scaleX = 0.8; backText.scaleY = 0.8; tween(backText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 400, easing: tween.easeOut }); }, 1400); } // Function to show shop function showShop() { showingShop = true; shopContainer = new Container(); game.addChild(shopContainer); // Simple main background var shopBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 4.5, alpha: 0.9 }); shopBg.x = 1024; shopBg.y = 1366; shopContainer.addChild(shopBg); // Clean title var titleText = new Text2('SHOP', { size: 80, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; shopContainer.addChild(titleText); // Simple coins display var coinsDisplayText = new Text2('Coins: ' + playerCoins, { size: 50, fill: 0xFFD700 }); coinsDisplayText.anchor.set(0.5, 0.5); coinsDisplayText.x = 1024; coinsDisplayText.y = 480; shopContainer.addChild(coinsDisplayText); // Store reference to update coins display throughout shop shopContainer.coinsDisplayText = coinsDisplayText; // Add function to update coins display with animation shopContainer.updateCoinsDisplay = function (newAmount) { // Flash effect on coins change tween(this.coinsDisplayText, { scaleX: 1.2, scaleY: 1.2, fill: 0x00FF00 }, { duration: 200, onFinish: function () { this.coinsDisplayText.setText('Coins: ' + newAmount); tween(this.coinsDisplayText, { scaleX: 1, scaleY: 1, fill: 0xFFD700 }, { duration: 300, easing: tween.bounceOut }); }.bind(this) }); }; // Simple centered layout with increased spacing var centerX = 1024; var itemStartY = 600; var itemSpacing = 120; // Aircraft styles section title var aircraftTitleText = new Text2('AIRCRAFT STYLES', { size: 55, fill: 0xFFFFFF }); aircraftTitleText.anchor.set(0.5, 0.5); aircraftTitleText.x = centerX; aircraftTitleText.y = 560; shopContainer.addChild(aircraftTitleText); // Aircraft items with clean design for (var a = 0; a < aircraftStyles.length; a++) { var aircraftItem = aircraftStyles[a]; var isOwned = ownedAircraftStyles.indexOf(aircraftItem.id) >= 0; var isEquipped = currentAircraftStyle === aircraftItem.id; // Simple item card var itemBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 6, scaleY: 1.2, alpha: isEquipped ? 0.9 : 0.7 }); itemBg.x = centerX; itemBg.y = itemStartY + a * itemSpacing; if (isEquipped) itemBg.tint = 0x00AA66; shopContainer.addChild(itemBg); // Aircraft preview var previewAircraft = LK.getAsset('aircraft', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); previewAircraft.x = centerX - 250; previewAircraft.y = itemStartY + a * itemSpacing; previewAircraft.tint = aircraftItem.color; shopContainer.addChild(previewAircraft); // Item name var itemNameText = new Text2(aircraftItem.name, { size: 44, fill: 0x000000 }); itemNameText.anchor.set(0, 0.5); itemNameText.x = centerX - 120; itemNameText.y = itemStartY + a * itemSpacing; shopContainer.addChild(itemNameText); // Purchase button var buttonText = isOwned ? isEquipped ? 'EQUIPPED' : 'EQUIP' : 'BUY ' + aircraftItem.price; var buttonColor = isOwned ? isEquipped ? 0x888888 : 0x00AA00 : playerCoins >= aircraftItem.price ? 0x0066CC : 0xCC0000; var itemButton = new Text2(buttonText, { size: 38, fill: buttonColor }); itemButton.anchor.set(0.5, 0.5); itemButton.x = centerX + 200; itemButton.y = itemStartY + a * itemSpacing; itemButton.aircraftItem = aircraftItem; itemButton.isOwned = isOwned; itemButton.isEquipped = isEquipped; if (!isEquipped) { itemButton.interactive = true; itemButton.down = function () { // Simple button animation tween(this, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, easing: tween.easeOut, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }.bind(this) }); if (this.isOwned) { // Equip item currentAircraftStyle = this.aircraftItem.id; storage.currentAircraftStyle = currentAircraftStyle; updateAircraftStyle(); LK.effects.flashScreen(0x00FF00, 300); hideShop(); showShop(); } else if (playerCoins >= this.aircraftItem.price) { // Purchase item playerCoins -= this.aircraftItem.price; storage.playerCoins = playerCoins; ownedAircraftStyles.push(this.aircraftItem.id); storage.ownedAircraftStyles = ownedAircraftStyles; currentAircraftStyle = this.aircraftItem.id; storage.currentAircraftStyle = currentAircraftStyle; updateAircraftStyle(); LK.effects.flashScreen(0xFFD700, 500); if (LK.getSound('coinCollect')) { LK.getSound('coinCollect').play(); } hideShop(); showShop(); } else { // Insufficient funds LK.effects.flashObject(this, 0xFF0000, 300); } }; } shopContainer.addChild(itemButton); } // Simple back button var backText = new Text2('BACK', { size: 50, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 1300; backText.interactive = true; backText.down = function () { // Simple button animation tween(this, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }.bind(this) }); hideShop(); createMainMenu(); }; shopContainer.addChild(backText); // Simple fade-in animation shopContainer.alpha = 0; tween(shopContainer, { alpha: 1 }, { duration: 300 }); } // Function to hide shop function hideShop() { if (shopContainer) { shopContainer.destroy(); shopContainer = null; } showingShop = false; } // Function to update aircraft style function updateAircraftStyle() { var styleData = aircraftStyles.find(function (style) { return style.id === currentAircraftStyle; }); if (styleData && aircraft) { aircraft.children[0].tint = styleData.color; // Main aircraft body } } // Function to hide codes menu function hideCodesMenu() { if (codesMenuContainer) { codesMenuContainer.destroy(); codesMenuContainer = null; } showingCodesMenu = false; } // Function to show levels menu function showLevelsMenu() { var levelsMenuContainer = new Container(); game.addChild(levelsMenuContainer); // Semi-transparent background var levelsBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 4.5, alpha: 0.95 }); levelsBg.x = 1024; levelsBg.y = 1366; levelsMenuContainer.addChild(levelsBg); // Title var titleText = new Text2('ALL LEVELS', { size: 90, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; levelsMenuContainer.addChild(titleText); // Subtitle with completion info var completedLevels = gameSettings.highestLevelReached; var subtitleText = new Text2('Completed: ' + completedLevels + '/100', { size: 60, fill: 0x00FF00 }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 500; levelsMenuContainer.addChild(subtitleText); // Add coins balance display in levels menu var levelCoinsDisplayBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 0.5, alpha: 0.4 }); levelCoinsDisplayBg.x = 1024; levelCoinsDisplayBg.y = 550; levelsMenuContainer.addChild(levelCoinsDisplayBg); var levelCoinsText = new Text2('Your Coins: ' + playerCoins, { size: 45, fill: 0xFFD700 }); levelCoinsText.anchor.set(0.5, 0.5); levelCoinsText.x = 1024; levelCoinsText.y = 550; levelsMenuContainer.addChild(levelCoinsText); // Create scrollable container for levels var scrollContainer = new Container(); levelsMenuContainer.addChild(scrollContainer); // Create level display in grid format (10 columns, 10 rows for 100 levels) for (var level = 1; level <= 100; level++) { var isCompleted = level <= completedLevels; var levelButton = new Text2(level.toString(), { size: 35, fill: isCompleted ? 0x00FF00 : 0x888888 // Green if completed, gray if not }); levelButton.anchor.set(0.5, 0.5); // Position in 10x10 grid levelButton.x = 300 + (level - 1) % 10 * 145; levelButton.y = 650 + Math.floor((level - 1) / 10) * 60; // Add background for better visibility var levelBg = LK.getAsset('towerTop', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7, alpha: isCompleted ? 0.8 : 0.3 }); levelBg.x = levelButton.x; levelBg.y = levelButton.y; scrollContainer.addChild(levelBg); scrollContainer.addChild(levelButton); // Add completion checkmark for completed levels if (isCompleted) { var checkmark = new Text2('✓', { size: 25, fill: 0xFFD700 }); checkmark.anchor.set(0.5, 0.5); checkmark.x = levelButton.x + 25; checkmark.y = levelButton.y - 25; scrollContainer.addChild(checkmark); } } // Add scroll instruction var scrollText = new Text2('Scroll to see all levels', { size: 45, fill: 0xFFFF00 }); scrollText.anchor.set(0.5, 0.5); scrollText.x = 1024; scrollText.y = 600; levelsMenuContainer.addChild(scrollText); // Add scroll functionality var scrollY = 0; var maxScroll = Math.max(0, Math.ceil(100 / 10) * 60 - 500); levelsMenuContainer.interactive = true; levelsMenuContainer.move = function (x, y, obj) { if (obj.deltaY) { scrollY -= obj.deltaY * 2; scrollY = Math.max(-maxScroll, Math.min(0, scrollY)); scrollContainer.y = scrollY; } }; // Back button var backText = new Text2('BACK', { size: 60, fill: 0xFF8000 }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 1600; backText.interactive = true; backText.down = function () { levelsMenuContainer.destroy(); createMainMenu(); }; levelsMenuContainer.addChild(backText); // Add entrance animation levelsMenuContainer.alpha = 0; tween(levelsMenuContainer, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); } // Function to show admin menu function showAdminMenu() { var adminMenuContainer = new Container(); game.addChild(adminMenuContainer); // Semi-transparent background var adminBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 4, alpha: 0.9 }); adminBg.x = 1024; adminBg.y = 1366; adminMenuContainer.addChild(adminBg); // Title var titleText = new Text2('ADMIN MODE ACTIVATED', { size: 70, fill: 0xFF0000 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; adminMenuContainer.addChild(titleText); // Level selection title var levelSelectText = new Text2('SELECT LEVEL:', { size: 60, fill: 0xFFFFFF }); levelSelectText.anchor.set(0.5, 0.5); levelSelectText.x = 1024; levelSelectText.y = 800; adminMenuContainer.addChild(levelSelectText); // Create scrollable level buttons (1-100) var scrollContainer = new Container(); adminMenuContainer.addChild(scrollContainer); // Create level buttons in a grid layout for (var level = 1; level <= 100; level++) { var levelButton = new Text2(level.toString(), { size: 35, fill: 0x00FF00 }); levelButton.anchor.set(0.5, 0.5); // 10 columns, 10 rows for 100 levels levelButton.x = 300 + (level - 1) % 10 * 145; levelButton.y = 900 + Math.floor((level - 1) / 10) * 60; levelButton.interactive = true; levelButton.targetLevel = level; levelButton.down = function () { currentLevel = this.targetLevel; storage.currentLevel = currentLevel; adminMenuContainer.destroy(); createMainMenu(); }; scrollContainer.addChild(levelButton); } // Add scroll instruction text var scrollText = new Text2('Scroll to see all 100 levels', { size: 40, fill: 0xFFFF00 }); scrollText.anchor.set(0.5, 0.5); scrollText.x = 1024; scrollText.y = 850; adminMenuContainer.addChild(scrollText); // Add scroll functionality var scrollY = 0; var maxScroll = Math.max(0, Math.ceil(100 / 10) * 60 - 400); // Adjust based on visible area adminMenuContainer.interactive = true; adminMenuContainer.move = function (x, y, obj) { if (obj.deltaY) { scrollY -= obj.deltaY * 2; scrollY = Math.max(-maxScroll, Math.min(0, scrollY)); scrollContainer.y = scrollY; } }; // Back button var backText = new Text2('BACK TO MENU', { size: 50, fill: 0xFF8000 }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 1500; backText.interactive = true; backText.down = function () { adminMenuContainer.destroy(); createMainMenu(); }; adminMenuContainer.addChild(backText); } // Function to hide main menu function hideMainMenu() { if (mainMenuContainer) { mainMenuContainer.destroy(); mainMenuContainer = null; } showingMainMenu = false; } // Function to start game function startGame() { gameStarted = true; // Reset game state levelScore = 0; towersToComplete = 5 * currentLevel; invulnerabilityTime = 0; comboMultiplier = 1; powerUpSpawnTimer = 0; // Clear any existing game objects clearLevel(); // Reset aircraft position aircraft.x = 300; aircraft.y = 1366; // Update UI levelText.setText('Level: ' + currentLevel); progressText.setText('Progress: 0/' + towersToComplete); scoreText.setText('Score: ' + LK.getScore()); coinsText.setText('Coins: ' + playerCoins); // Apply current aircraft style updateAircraftStyle(); // Start background music if (gameSettings.musicEnabled && !musicPlaying) { LK.stopMusic(); // Stop any menu music LK.playMusic('backgroundMusic', { loop: true }); musicPlaying = true; } } // Function to hide menu function hideMenu() { if (menuContainer) { menuContainer.destroy(); menuContainer = null; } showingMenu = false; gameStarted = true; } // Function to clear level objects function clearLevel() { // Clear existing towers for (var i = towers.length - 1; i >= 0; i--) { towers[i].destroy(); towers.splice(i, 1); } // Clear finish line if (finishLine) { finishLine.destroy(); finishLine = null; } // Clear existing clouds for (var c = clouds.length - 1; c >= 0; c--) { clouds[c].destroy(); clouds.splice(c, 1); } // Clear power-ups for (var p = powerUps.length - 1; p >= 0; p--) { powerUps[p].destroy(); powerUps.splice(p, 1); } // Clear particles for (var pt = particles.length - 1; pt >= 0; pt--) { particles[pt].destroy(); particles.splice(pt, 1); } // Clear spark particles for (var sp = sparkParticles.length - 1; sp >= 0; sp--) { sparkParticles[sp].destroy(); sparkParticles.splice(sp, 1); } // Clear coins for (var co = coins.length - 1; co >= 0; co--) { coins[co].destroy(); coins.splice(co, 1); } } // Function to complete level function completeLevel() { currentLevel++; // Save progress to storage storage.currentLevel = currentLevel; levelScore = 0; towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc. // Reset power-up system invulnerabilityTime = 0; comboMultiplier = 1; powerUpSpawnTimer = 0; // Clear existing towers and finish line clearLevel(); // Reset aircraft position aircraft.x = 300; aircraft.y = 1366; // Update UI levelText.setText('Level: ' + currentLevel); progressText.setText('Progress: 0/' + towersToComplete); // Enhanced level completion effects with camera shake startCameraShake(10, 60); // Gentle celebration shake LK.effects.flashScreen(0x00ff00, 1000); LK.getSound('levelComplete').play(); // Bonus score for completing level with progressive rewards var bonusScore = 100 * currentLevel * comboMultiplier; var milestoneBonus = 0; // Milestone bonuses for every 10 levels if (currentLevel % 10 === 0) { milestoneBonus = 1000 * (currentLevel / 10); playerCoins += 50; // Bonus coins for milestone storage.playerCoins = playerCoins; coinsText.setText('Coins: ' + playerCoins); } LK.setScore(LK.getScore() + bonusScore + milestoneBonus); scoreText.setText('Score: ' + LK.getScore()); // Create celebration particles for (var i = 0; i < 10; i++) { LK.setTimeout(function () { createSparkParticle(aircraft.x + (Math.random() - 0.5) * 200, aircraft.y + (Math.random() - 0.5) * 100); }, i * 50); } } // Enhanced camera shake system var cameraShake = { active: false, intensity: 0, duration: 0, originalX: 0, originalY: 0 }; function startCameraShake(intensity, duration) { if (!gameSettings.screenshakeEnabled) return; cameraShake.active = true; cameraShake.intensity = intensity; cameraShake.duration = duration; cameraShake.originalX = game.x; cameraShake.originalY = game.y; } function updateCameraShake() { if (!cameraShake.active) return; cameraShake.duration--; if (cameraShake.duration <= 0) { cameraShake.active = false; game.x = cameraShake.originalX; game.y = cameraShake.originalY; return; } var shakeX = (Math.random() - 0.5) * cameraShake.intensity; var shakeY = (Math.random() - 0.5) * cameraShake.intensity; game.x = cameraShake.originalX + shakeX; game.y = cameraShake.originalY + shakeY; } // Function to handle game over function gameOver() { // Save current level to storage so player can restart from this level storage.currentLevel = currentLevel; // Enhanced screen shake for dramatic effect startCameraShake(25, 120); LK.effects.flashScreen(0xff0000, 1000); LK.getSound('crash').play(); LK.showGameOver(); } // Main game update loop game.update = function () { // Update camera shake system updateCameraShake(); // Check if admin mode has expired if (adminMode && Date.now() > adminModeEndTime) { adminMode = false; adminModeEndTime = 0; storage.adminModeEndTime = 0; } if (!gameStarted || showingMenu || showingMainMenu || showingCodesMenu || showingShop) return; // Update invulnerability if (invulnerabilityTime > 0) { invulnerabilityTime--; if (invulnerabilityTime === 0) { aircraft.alpha = 1; // Restore normal appearance } } // Update combo multiplier decay if (LK.ticks - lastPowerUpTime > 1800) { // 30 seconds comboMultiplier = Math.max(1, comboMultiplier - 0.01); } // Spawn clouds for background atmosphere if (LK.ticks % 180 === 0) { // Spawn cloud every 3 seconds at 60fps spawnCloud(); } // Spawn coins coinSpawnTimer++; if (coinSpawnTimer > 180 + Math.random() * 120) { // Every 3-5 seconds spawnCoin(); coinSpawnTimer = 0; } // Spawn power-ups powerUpSpawnTimer++; if (powerUpSpawnTimer > 600 + Math.random() * 300) { // Every 10-15 seconds spawnPowerUp(); powerUpSpawnTimer = 0; } // Update clouds for (var c = clouds.length - 1; c >= 0; c--) { var cloud = clouds[c]; // Remove clouds that have moved off screen if (cloud.x < -200) { cloud.destroy(); clouds.splice(c, 1); } } // Update coins for (var co = coins.length - 1; co >= 0; co--) { var coin = coins[co]; // Remove if off screen if (coin.x < -100) { coin.destroy(); coins.splice(co, 1); continue; } // Check collection var coinIntersecting = aircraft.intersects(coin); if (!coin.lastIntersecting && coinIntersecting && !coin.collected) { coin.collected = true; playerCoins += 5; // Award 5 coins per collection storage.playerCoins = playerCoins; coinsText.setText('Coins: ' + playerCoins); // Coin collection effect LK.effects.flashObject(coin, 0xFFD700, 300); LK.getSound('coinCollect').play(); // Create coin text popup var coinPopup = new Text2('+5', { size: 40, fill: 0xFFD700 }); coinPopup.anchor.set(0.5, 0.5); coinPopup.x = coin.x; coinPopup.y = coin.y; game.addChild(coinPopup); tween(coinPopup, { y: coinPopup.y - 80, alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { coinPopup.destroy(); } }); coin.destroy(); coins.splice(co, 1); continue; } coin.lastIntersecting = coinIntersecting; } // Update spark particles for (var sp = sparkParticles.length - 1; sp >= 0; sp--) { var spark = sparkParticles[sp]; // Particles are automatically removed in their update method } // Update power-ups for (var p = powerUps.length - 1; p >= 0; p--) { var powerUp = powerUps[p]; // Remove if off screen if (powerUp.x < -100) { powerUp.destroy(); powerUps.splice(p, 1); continue; } // Check collection var currentIntersecting = aircraft.intersects(powerUp); if (!powerUp.lastIntersecting && currentIntersecting && !powerUp.collected) { powerUp.collected = true; applyPowerUpEffect(); powerUp.destroy(); powerUps.splice(p, 1); continue; } powerUp.lastIntersecting = currentIntersecting; } // Spawn towers based on level difficulty (adjusted for levels 1-100) var spawnRate = Math.max(60, 300 - Math.min(currentLevel, 15) * 15); // Gradual increase, cap at level 15 difficulty if (LK.ticks % spawnRate === 0) { spawnTower(); } // Check if we should spawn finish line var progress = Math.floor(levelScore / 2); if (progress >= towersToComplete && !finishLine) { spawnFinishLine(); } // Update finish line if (finishLine) { // Check if finish line went off screen if (finishLine.lastX >= -200 && finishLine.x < -200) { finishLine.destroy(); finishLine = null; } // Check if aircraft crossed finish line if (!finishLine.crossed && finishLine.x < aircraft.x) { finishLine.crossed = true; createLevelMenu(); return; } } // Update towers for (var i = towers.length - 1; i >= 0; i--) { var tower = towers[i]; // Check if tower went off screen if (tower.lastX >= -200 && tower.x < -200) { towers.splice(i, 1); tower.destroy(); continue; } // Check collision with aircraft (skip if invulnerable) var currentIntersecting = aircraft.intersects(tower); if (!tower.lastIntersecting && currentIntersecting && invulnerabilityTime <= 0) { // Create dramatic collision effect createTowerDestructionEffect(tower.x, tower.y); startCameraShake(30, 100); LK.getSound('crash').play(); gameOver(); return; } tower.lastIntersecting = currentIntersecting; // Check if aircraft passed tower (score point) if (!tower.passed && tower.x < aircraft.x - 100) { tower.passed = true; levelScore++; var basePoints = 10 * currentLevel; var bonusPoints = Math.floor(basePoints * comboMultiplier); LK.setScore(LK.getScore() + bonusPoints); LK.getSound('dodge').play(); LK.getSound('whoosh').play(); // Update progress var progress = Math.floor(levelScore / 2); // Two towers per obstacle progressText.setText('Progress: ' + progress + '/' + towersToComplete); scoreText.setText('Score: ' + LK.getScore()); // Create score popup for bonus points if (comboMultiplier > 1) { var bonusText = new Text2('+' + bonusPoints + ' (x' + comboMultiplier.toFixed(1) + ')', { size: 40, fill: 0xFFD700 }); bonusText.anchor.set(0.5, 0.5); bonusText.x = aircraft.x; bonusText.y = aircraft.y - 50; game.addChild(bonusText); // Animate bonus text tween(bonusText, { y: bonusText.y - 100, alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { bonusText.destroy(); } }); } // Animate score text to highlight points earned tween.stop(scoreText, { scaleX: true, scaleY: true }); tween(scoreText, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(scoreText, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); } } // Dynamic background color system based on level var targetBackgroundColor = 0x87CEFA; // Default sky blue if (currentLevel >= 80) { targetBackgroundColor = 0x2F1B69; // Deep purple for high levels } else if (currentLevel >= 60) { targetBackgroundColor = 0x1a1a2e; // Dark blue } else if (currentLevel >= 40) { targetBackgroundColor = 0x16213e; // Navy blue } else if (currentLevel >= 20) { targetBackgroundColor = 0x0f3460; // Medium blue } // Gradually transition background color every few seconds if (LK.ticks % 300 === 0) { // Every 5 seconds var currentBg = game.backgroundColor || 0x87CEFA; if (currentBg !== targetBackgroundColor) { // Simple color transition by setting it directly game.setBackgroundColor(targetBackgroundColor); } } // Aircraft stays stationary while towers move to create forward movement illusion };
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1");
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Aircraft = Container.expand(function () {
var self = Container.call(this);
// Main aircraft fuselage (body)
var aircraftGraphics = self.attachAsset('aircraft', {
anchorX: 0.5,
anchorY: 0.5
});
// Main wings (positioned lower on fuselage for realism)
var mainWing = self.attachAsset('aircraftWing', {
anchorX: 0.5,
anchorY: 0.5
});
mainWing.x = -15;
mainWing.y = 0;
// Aircraft tail (vertical stabilizer)
var tail = self.attachAsset('aircraftTail', {
anchorX: 0.5,
anchorY: 0.5
});
tail.x = -60;
tail.y = 0;
tail.rotation = Math.PI / 2; // Vertical orientation
// Horizontal stabilizer (smaller wing at tail)
var horizontalStab = self.attachAsset('aircraftWing', {
anchorX: 0.5,
anchorY: 0.5
});
horizontalStab.x = -55;
horizontalStab.y = 0;
horizontalStab.scaleX = 0.4;
horizontalStab.scaleY = 0.6;
// Cockpit window
var cockpit = self.attachAsset('aircraftCockpit', {
anchorX: 0.5,
anchorY: 0.5
});
cockpit.x = 35;
cockpit.y = -2;
// Engine nacelles under wings
var leftEngine = self.attachAsset('aircraftEngine', {
anchorX: 0.5,
anchorY: 0.5
});
leftEngine.x = -20;
leftEngine.y = 12;
var rightEngine = self.attachAsset('aircraftEngine', {
anchorX: 0.5,
anchorY: 0.5
});
rightEngine.x = -20;
rightEngine.y = -12;
// Propeller at front
var propeller = self.attachAsset('aircraftPropeller', {
anchorX: 0.5,
anchorY: 0.5
});
propeller.x = 70;
propeller.y = 0;
// Animate propeller rotation
propeller.rotationSpeed = 0.3;
self.speed = 3;
self.lastY = 0;
self.update = function () {
// Update last position for collision detection
self.lastY = self.y;
// Animate propeller spinning with variable speed
propeller.rotation += propeller.rotationSpeed * (1 + self.speed * 0.1);
// Create engine trail particles with enhanced effects
if (LK.ticks % 3 === 0 && gameStarted) {
createEngineParticle(self.x - 50, self.y);
// Add occasional spark effects
if (Math.random() < 0.3) {
createSparkParticle(self.x - 40, self.y + (Math.random() - 0.5) * 20);
}
}
// Add subtle floating animation for more dynamic feel
if (!self.floatingTween) {
self.floatingTween = true;
var originalY = self.y;
tween(self, {
y: originalY + 8
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
y: originalY - 8
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.floatingTween = false;
}
});
}
});
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Choose random cloud type
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
// Main cloud body
var mainCloud = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5
});
// Add smaller cloud parts for more realistic shape
var cloud2 = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5
});
cloud2.x = -30 + Math.random() * 60;
cloud2.y = -15 + Math.random() * 30;
cloud2.scaleX = 0.6 + Math.random() * 0.4;
cloud2.scaleY = 0.6 + Math.random() * 0.4;
cloud2.alpha = 0.8;
var cloud3 = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5
});
cloud3.x = -20 + Math.random() * 40;
cloud3.y = -10 + Math.random() * 20;
cloud3.scaleX = 0.4 + Math.random() * 0.3;
cloud3.scaleY = 0.4 + Math.random() * 0.3;
cloud3.alpha = 0.6;
// Set random speed and scale
self.speed = 0.5 + Math.random() * 1.5;
self.scaleX = 0.8 + Math.random() * 0.6;
self.scaleY = 0.8 + Math.random() * 0.6;
self.alpha = 0.7 + Math.random() * 0.3;
self.update = function () {
// Move cloud from right to left
self.x -= self.speed;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
// Coin visual
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
// Floating and spinning animation
self.floatOffset = Math.random() * Math.PI * 2;
self.collected = false;
self.update = function () {
// Floating animation
self.y += Math.sin(LK.ticks * 0.15 + self.floatOffset) * 0.8;
// Spinning animation
coinGraphics.rotation += 0.1;
// Pulsing scale effect
var scale = 1.2 + Math.sin(LK.ticks * 0.08) * 0.2;
coinGraphics.scaleX = scale;
coinGraphics.scaleY = scale;
// Move from right to left
var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05));
self.x -= speed;
};
return self;
});
var FinishLine = Container.expand(function () {
var self = Container.call(this);
// Main finish line
var lineGraphics = self.attachAsset('finishLine', {
anchorX: 0.5,
anchorY: 0.5
});
// Add flags at top and bottom for visibility
var topFlag = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 0.5
});
topFlag.y = -1300;
var bottomFlag = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 0.5
});
bottomFlag.y = 1300;
self.lastX = 0;
self.crossed = false;
self.update = function () {
// Update last position before moving
self.lastX = self.x;
// Move finish line from right to left (match tower speed for levels 1-100)
var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); // Match tower speed progression
self.x -= speed;
};
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
// Small particle visual
var particleGraphics = self.attachAsset('cloud1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1
});
particleGraphics.alpha = 0.7;
particleGraphics.tint = 0xFF6600; // Orange-ish color
self.velocityX = -2 - Math.random() * 3;
self.velocityY = (Math.random() - 0.5) * 2;
self.life = 60; // 1 second at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.life--;
particleGraphics.alpha *= 0.98; // Fade out
particleGraphics.scaleX *= 0.99; // Shrink
particleGraphics.scaleY *= 0.99;
if (self.life <= 0) {
self.destroy();
var index = particles.indexOf(self);
if (index > -1) particles.splice(index, 1);
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
// Power-up visual
var powerUpGraphics = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
powerUpGraphics.tint = 0x00FFFF; // Cyan color for power-ups
// Floating animation
self.floatOffset = Math.random() * Math.PI * 2;
self.collected = false;
self.update = function () {
// Floating animation
self.y += Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.5;
// Rotation animation
powerUpGraphics.rotation += 0.05;
// Move from right to left
var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05));
self.x -= speed;
};
return self;
});
var SparkParticle = Container.expand(function () {
var self = Container.call(this);
// Small spark visual
var sparkGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.05,
scaleY: 0.05
});
sparkGraphics.alpha = 1;
sparkGraphics.tint = 0xFFAA00; // Orange spark color
self.velocityX = -1 - Math.random() * 2;
self.velocityY = (Math.random() - 0.5) * 3;
self.life = 30; // Half second at 60fps
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += 0.1; // Gravity effect
self.life--;
sparkGraphics.alpha *= 0.95; // Faster fade than regular particles
sparkGraphics.scaleX *= 0.98;
sparkGraphics.scaleY *= 0.98;
sparkGraphics.rotation += 0.2; // Spinning effect
if (self.life <= 0) {
self.destroy();
var index = sparkParticles.indexOf(self);
if (index > -1) sparkParticles.splice(index, 1);
}
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
// Tower base
var towerBase = self.attachAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5
});
// Tower top
var towerTop = self.attachAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5
});
towerTop.y = -420; // Position at top of tower
// Add windows to make it look more realistic
for (var w = 0; w < 3; w++) {
var window1 = self.attachAsset('towerWindow', {
anchorX: 0.5,
anchorY: 0.5
});
window1.x = -30;
window1.y = -300 + w * 150;
var window2 = self.attachAsset('towerWindow', {
anchorX: 0.5,
anchorY: 0.5
});
window2.x = 30;
window2.y = -300 + w * 150;
}
self.lastX = 0;
self.passed = false;
self.update = function () {
// Update last position before moving
self.lastX = self.x;
// Move tower from right to left (progressive speed increase for levels 1-100)
var speed = Math.max(1.5, Math.min(6, 1.5 + currentLevel * 0.05)); // Gradual speed increase, capped at 6
self.x -= speed;
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x87CEFA // More realistic sky blue background
});
/****
* Game Code
****/
//Storage plugin for persistent game data
// Game variables
// Initialize assets for the tower dodge flight game
var aircraft;
var towers = [];
var clouds = [];
var finishLine = null;
var showingMenu = false;
var currentLevel = storage.currentLevel || 1;
var levelScore = 0;
var towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc.
var towerSpawnTimer = 0;
var gameStarted = false;
var menuContainer = null;
var mainMenuContainer = null;
var showingMainMenu = true;
var showingCodesMenu = false;
var codesMenuContainer = null;
var adminMode = false;
var adminModeEndTime = 0;
// Enhanced settings storage
var gameSettings = storage.gameSettings || {
soundEnabled: true,
musicEnabled: true,
difficulty: 'normal',
highestLevelReached: 1,
particlesEnabled: true,
screenshakeEnabled: true
};
// Additional game variables
var powerUps = [];
var particles = [];
var sparkParticles = [];
var powerUpSpawnTimer = 0;
var invulnerabilityTime = 0;
var comboMultiplier = 1;
var lastPowerUpTime = 0;
var musicPlaying = false;
var coins = [];
var coinSpawnTimer = 0;
var showingShop = false;
var shopContainer = null;
// Initialize player coins and shop items
var playerCoins = storage.playerCoins || 0;
var ownedAircraftStyles = storage.ownedAircraftStyles || ['default'];
var ownedTowerStyles = storage.ownedTowerStyles || ['default'];
var currentAircraftStyle = storage.currentAircraftStyle || 'default';
var currentTowerStyle = storage.currentTowerStyle || 'default';
// Shop items with prices
var aircraftStyles = [{
id: 'default',
name: 'Classic',
price: 0,
color: 0xf0f0f0
}, {
id: 'red',
name: 'Fire Bird',
price: 100,
color: 0xff4444
}, {
id: 'blue',
name: 'Sky Runner',
price: 150,
color: 0x4444ff
}, {
id: 'green',
name: 'Forest Wing',
price: 200,
color: 0x44ff44
}, {
id: 'purple',
name: 'Royal Jet',
price: 300,
color: 0x8844ff
}, {
id: 'gold',
name: 'Golden Eagle',
price: 500,
color: 0xffd700
}];
var towerStyles = [{
id: 'default',
name: 'Stone Tower',
price: 0,
color: 0x8b4513
}, {
id: 'metal',
name: 'Metal Tower',
price: 120,
color: 0x778899
}, {
id: 'crystal',
name: 'Crystal Tower',
price: 180,
color: 0x99ddff
}, {
id: 'dark',
name: 'Dark Tower',
price: 250,
color: 0x444444
}, {
id: 'rainbow',
name: 'Rainbow Tower',
price: 400,
color: 0xff6699
}];
// Update settings when needed
if (currentLevel > gameSettings.highestLevelReached) {
gameSettings.highestLevelReached = currentLevel;
storage.gameSettings = gameSettings;
}
// Check if admin mode is still active from previous session
var storedAdminEndTime = storage.adminModeEndTime || 0;
if (storedAdminEndTime > Date.now()) {
adminMode = true;
adminModeEndTime = storedAdminEndTime;
}
// UI Elements
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topLeft.addChild(levelText);
levelText.x = 120; // Avoid top-left menu area
levelText.y = 20;
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
var progressText = new Text2('Progress: 0/10', {
size: 50,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0);
LK.gui.top.addChild(progressText);
progressText.y = 100;
var coinsText = new Text2('Coins: ' + playerCoins, {
size: 50,
fill: 0xFFD700
});
coinsText.anchor.set(0, 0);
LK.gui.topLeft.addChild(coinsText);
coinsText.x = 120;
coinsText.y = 80;
// Initialize aircraft
aircraft = game.addChild(new Aircraft());
aircraft.x = 300;
aircraft.y = 1366; // Center vertically
aircraft.lastIntersecting = false;
// Show main menu at start
createMainMenu();
// Touch controls for aircraft movement
var dragActive = false;
game.down = function (x, y, obj) {
if (showingMainMenu || showingMenu) return;
dragActive = true;
};
game.up = function (x, y, obj) {
if (showingMainMenu || showingMenu) return;
dragActive = false;
};
game.move = function (x, y, obj) {
if (showingMainMenu || showingMenu) return;
var targetY = y;
if (dragActive) {
targetY = y;
}
// Keep aircraft within screen bounds
if (targetY < 50) targetY = 50;
if (targetY > 2680) targetY = 2680;
// Smooth tween animation for aircraft movement
tween.stop(aircraft, {
y: true
});
tween(aircraft, {
y: targetY
}, {
duration: 200,
easing: tween.easeOut
});
};
// Function to spawn tower
function spawnTower() {
var tower = new Tower();
tower.x = 2200; // Start from right edge
// Random height position with gap for aircraft to pass (adjusted for levels 1-100)
var gapSize = Math.max(300, 700 - Math.min(currentLevel, 10) * 30); // Gradual decrease, minimum gap of 300
var gapPosition = Math.random() * (2732 - gapSize - 200) + 100;
// Create top tower
var topTower = game.addChild(new Tower());
topTower.x = tower.x;
topTower.y = gapPosition / 2;
topTower.lastIntersecting = false;
towers.push(topTower);
// Apply current tower style
var currentTowerStyleData = towerStyles.find(function (style) {
return style.id === currentTowerStyle;
});
if (currentTowerStyleData) {
topTower.children[0].tint = currentTowerStyleData.color; // Tower base
topTower.children[1].tint = currentTowerStyleData.color; // Tower top
}
// Create bottom tower
var bottomTower = game.addChild(new Tower());
bottomTower.x = tower.x;
bottomTower.y = gapPosition + gapSize + (2732 - gapPosition - gapSize) / 2;
bottomTower.lastIntersecting = false;
towers.push(bottomTower);
// Apply current tower style
if (currentTowerStyleData) {
bottomTower.children[0].tint = currentTowerStyleData.color; // Tower base
bottomTower.children[1].tint = currentTowerStyleData.color; // Tower top
}
}
// Function to spawn clouds
function spawnCloud() {
var cloud = new Cloud();
cloud.x = 2200 + Math.random() * 400; // Start from right edge with some variation
cloud.y = 200 + Math.random() * 2300; // Random height across screen
clouds.push(cloud);
game.addChild(cloud);
}
// Function to spawn finish line
function spawnFinishLine() {
if (finishLine) return; // Don't spawn if already exists
finishLine = game.addChild(new FinishLine());
finishLine.x = 2500; // Start further right than towers
finishLine.y = 1366; // Center vertically
finishLine.lastIntersecting = false;
}
// Function to create engine particles
function createEngineParticle(x, y) {
if (!gameSettings.particlesEnabled || particles.length > 20) return;
var particle = new Particle();
particle.x = x + (Math.random() - 0.5) * 20;
particle.y = y + (Math.random() - 0.5) * 10;
particles.push(particle);
game.addChild(particle);
}
// Function to create spark particles
function createSparkParticle(x, y) {
if (!gameSettings.particlesEnabled || sparkParticles.length > 15) return;
var spark = new SparkParticle();
spark.x = x;
spark.y = y;
sparkParticles.push(spark);
game.addChild(spark);
}
// Function to create tower destruction effect
function createTowerDestructionEffect(x, y) {
if (!gameSettings.particlesEnabled) return;
// Create multiple debris particles
for (var i = 0; i < 8; i++) {
var debris = new Particle();
debris.x = x + (Math.random() - 0.5) * 100;
debris.y = y + (Math.random() - 0.5) * 200;
debris.children[0].tint = 0x8B4513; // Brown debris color
debris.velocityX = (Math.random() - 0.5) * 8;
debris.velocityY = -Math.random() * 5;
debris.life = 120; // Longer life for debris
particles.push(debris);
game.addChild(debris);
}
// Create sparks
for (var j = 0; j < 5; j++) {
createSparkParticle(x + (Math.random() - 0.5) * 80, y + (Math.random() - 0.5) * 150);
}
}
// Function to spawn coin
function spawnCoin() {
var coin = new Coin();
coin.x = 2200;
coin.y = 200 + Math.random() * 2300;
coin.lastIntersecting = false;
coins.push(coin);
game.addChild(coin);
}
// Function to spawn power-up
function spawnPowerUp() {
var powerUp = new PowerUp();
powerUp.x = 2200;
powerUp.y = 200 + Math.random() * 2300;
powerUp.lastIntersecting = false;
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Function to apply power-up effect
function applyPowerUpEffect() {
invulnerabilityTime = 300; // 5 seconds at 60fps
comboMultiplier = Math.min(comboMultiplier + 0.5, 3); // Max 3x multiplier
lastPowerUpTime = LK.ticks;
// Visual feedback
LK.effects.flashObject(aircraft, 0x00FFFF, 500);
LK.getSound('powerup').play();
// Update aircraft appearance during invulnerability
tween(aircraft, {
alpha: 0.7
}, {
duration: 100,
onFinish: function onFinish() {
tween(aircraft, {
alpha: 1
}, {
duration: 100
});
}
});
}
// Function to create level completion menu
function createLevelMenu() {
showingMenu = true;
menuContainer = new Container();
game.addChild(menuContainer);
// Semi-transparent background
var menuBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 2,
alpha: 0.8
});
menuBg.x = 1024;
menuBg.y = 1366;
menuContainer.addChild(menuBg);
// Title text
var titleText = new Text2('Level ' + currentLevel + ' Complete!', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1200;
menuContainer.addChild(titleText);
// Retry button
var retryText = new Text2('Retry Level', {
size: 60,
fill: 0x00FF00
});
retryText.anchor.set(0.5, 0.5);
retryText.x = 1024;
retryText.y = 1300;
retryText.interactive = true;
retryText.down = function () {
restartCurrentLevel();
};
menuContainer.addChild(retryText);
// Next level button
var nextText = new Text2('Next Level', {
size: 60,
fill: 0x0080FF
});
nextText.anchor.set(0.5, 0.5);
nextText.x = 1024;
nextText.y = 1400;
nextText.interactive = true;
nextText.down = function () {
goToNextLevel();
};
menuContainer.addChild(nextText);
// Return to level 1 button
var returnText = new Text2('Return to Level 1', {
size: 60,
fill: 0xFF8000
});
returnText.anchor.set(0.5, 0.5);
returnText.x = 1024;
returnText.y = 1500;
returnText.interactive = true;
returnText.down = function () {
returnToLevel1();
};
menuContainer.addChild(returnText);
}
// Function to restart current level
function restartCurrentLevel() {
hideMenu();
levelScore = 0;
// Clear existing towers and finish line
clearLevel();
// Reset aircraft position
aircraft.x = 300;
aircraft.y = 1366;
// Update UI
progressText.setText('Progress: 0/' + towersToComplete);
}
// Function to go to next level
function goToNextLevel() {
hideMenu();
completeLevel();
}
// Function to return to level 1
function returnToLevel1() {
hideMenu();
currentLevel = 1;
storage.currentLevel = 1;
levelScore = 0;
towersToComplete = 5 * currentLevel;
// Clear existing towers and finish line
clearLevel();
// Reset aircraft position
aircraft.x = 300;
aircraft.y = 1366;
// Update UI
levelText.setText('Level: ' + currentLevel);
progressText.setText('Progress: 0/' + towersToComplete);
}
// Function to create main menu
function createMainMenu() {
showingMainMenu = true;
mainMenuContainer = new Container();
game.addChild(mainMenuContainer);
// Start menu music
if (gameSettings.musicEnabled) {
LK.stopMusic();
LK.playMusic('menuMusic', {
loop: true
});
musicPlaying = false; // Reset flag so game music can start
}
// Semi-transparent background
var menuBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 4,
alpha: 0.9
});
menuBg.x = 1024;
menuBg.y = 1366;
mainMenuContainer.addChild(menuBg);
// Game title
var titleText = new Text2('TOWER DODGE', {
size: 120,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
titleText.alpha = 0;
mainMenuContainer.addChild(titleText);
// Animate title entrance
tween(titleText, {
y: 750,
alpha: 1
}, {
duration: 1000,
easing: tween.bounceOut
});
// Subtitle
var subtitleText = new Text2('Navigate through the towers!', {
size: 60,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 850;
mainMenuContainer.addChild(subtitleText);
// Play button
var playText = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = 1000;
playText.alpha = 0;
playText.scaleX = 0.5;
playText.scaleY = 0.5;
playText.interactive = true;
playText.down = function () {
// Add button press animation
tween(playText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(playText, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
hideMainMenu();
startGame();
};
mainMenuContainer.addChild(playText);
// Animate play button entrance with delay
tween(playText, {
y: 1050,
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.elasticOut
});
// Shop button
var shopText = new Text2('SHOP', {
size: 80,
fill: 0x00FFFF
});
shopText.anchor.set(0.5, 0.5);
shopText.x = 1024;
shopText.y = 1150;
shopText.interactive = true;
shopText.down = function () {
hideMainMenu();
showShop();
};
mainMenuContainer.addChild(shopText);
// Codes button
var codesText = new Text2('CODES', {
size: 80,
fill: 0xFF8000
});
codesText.anchor.set(0.5, 0.5);
codesText.x = 1024;
codesText.y = 1250;
codesText.interactive = true;
codesText.down = function () {
hideMainMenu();
showCodesMenu();
};
mainMenuContainer.addChild(codesText);
// Current level indicator
var levelIndicatorText = new Text2('Continue from Level ' + currentLevel, {
size: 50,
fill: 0xFFFF00
});
levelIndicatorText.anchor.set(0.5, 0.5);
levelIndicatorText.x = 1024;
levelIndicatorText.y = 1350;
mainMenuContainer.addChild(levelIndicatorText);
// Enhanced coins display section with background
var coinsDisplayBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 0.7,
alpha: 0.4
});
coinsDisplayBg.x = 1024;
coinsDisplayBg.y = 1450;
mainMenuContainer.addChild(coinsDisplayBg);
// Coins icon simulation using coin asset
var coinsIcon = LK.getAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
coinsIcon.x = 850;
coinsIcon.y = 1450;
mainMenuContainer.addChild(coinsIcon);
// Enhanced coins indicator with larger, more prominent text
var coinsIndicatorText = new Text2('Your Coins: ' + playerCoins, {
size: 55,
fill: 0xFFD700
});
coinsIndicatorText.anchor.set(0.5, 0.5);
coinsIndicatorText.x = 1100;
coinsIndicatorText.y = 1450;
mainMenuContainer.addChild(coinsIndicatorText);
// Add subtle animation to coins display
coinsIcon.rotationSpeed = 0.02;
tween(coinsIcon, {
rotation: Math.PI * 2
}, {
duration: 3000,
loop: true,
easing: tween.linear
});
// Add pulsing effect to coins text
tween(coinsIndicatorText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1500,
loop: true,
yoyo: true,
easing: tween.easeInOut
});
}
// Function to show codes menu
function showCodesMenu() {
showingCodesMenu = true;
codesMenuContainer = new Container();
game.addChild(codesMenuContainer);
// Create layered background for depth effect
var outerBorder = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 11,
scaleY: 4.5,
alpha: 0.2
});
outerBorder.x = 1024;
outerBorder.y = 1366;
codesMenuContainer.addChild(outerBorder);
// Main background with gradient effect
var codesBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10.5,
scaleY: 4.2,
alpha: 0.95
});
codesBg.x = 1024;
codesBg.y = 1366;
codesMenuContainer.addChild(codesBg);
// Inner frame for modern look
var innerFrame = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 4,
alpha: 0.15
});
innerFrame.x = 1024;
innerFrame.y = 1366;
codesMenuContainer.addChild(innerFrame);
// Title with enhanced styling and glow effect
var titleBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 1,
alpha: 0.4
});
titleBg.x = 1024;
titleBg.y = 750;
codesMenuContainer.addChild(titleBg);
var titleText = new Text2('ENTER CODE', {
size: 95,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 750;
codesMenuContainer.addChild(titleText);
// Add animated title underline
var titleUnderline = LK.getAsset('finishLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0.15
});
titleUnderline.x = 1024;
titleUnderline.y = 815;
codesMenuContainer.addChild(titleUnderline);
// Animate underline appearance
tween(titleUnderline, {
scaleX: 5
}, {
duration: 800,
easing: tween.easeOut
});
// Enhanced code input display with multiple layers
var inputOuterBorder = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6.5,
scaleY: 0.65,
alpha: 0.2
});
inputOuterBorder.x = 1024;
inputOuterBorder.y = 950;
codesMenuContainer.addChild(inputOuterBorder);
var inputBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.55,
alpha: 0.4
});
inputBg.x = 1024;
inputBg.y = 950;
codesMenuContainer.addChild(inputBg);
var inputInner = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5.5,
scaleY: 0.45,
alpha: 0.8
});
inputInner.x = 1024;
inputInner.y = 950;
codesMenuContainer.addChild(inputInner);
var codeInputText = new Text2('', {
size: 70,
fill: 0x000000
});
codeInputText.anchor.set(0.5, 0.5);
codeInputText.x = 1024;
codeInputText.y = 950;
codesMenuContainer.addChild(codeInputText);
// Enhanced instructions with icon-like styling
var instructionBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.5,
scaleY: 0.4,
alpha: 0.3
});
instructionBg.x = 1024;
instructionBg.y = 1050;
codesMenuContainer.addChild(instructionBg);
var instructionText = new Text2('Tap keys below to enter your code', {
size: 48,
fill: 0xF0F0F0
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1050;
codesMenuContainer.addChild(instructionText);
// Create enhanced virtual keyboard with modern styling
var currentCode = '';
var keyboardRows = ['QWERTYUIOP', 'ASDFGHJKL', 'ZXCVBNM'];
var keySize = 70;
var keySpacing = 130;
var rowSpacing = 140;
// Calculate starting positions for each row to center them perfectly with improved spacing
var rowStartPositions = [1024 - (keyboardRows[0].length - 1) * keySpacing / 2,
// QWERTY row
1024 - (keyboardRows[1].length - 1) * keySpacing / 2,
// ASDF row
1024 - (keyboardRows[2].length - 1) * keySpacing / 2 // ZXCV row
];
for (var row = 0; row < keyboardRows.length; row++) {
var letters = keyboardRows[row];
for (var col = 0; col < letters.length; col++) {
var letter = letters[col];
// Create layered key design for modern look
var keyShadow = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.45,
scaleY: 0.65,
alpha: 0.3
});
keyShadow.x = rowStartPositions[row] + col * keySpacing + 2;
keyShadow.y = 1320 + row * rowSpacing + 2;
codesMenuContainer.addChild(keyShadow);
var keyBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.48,
scaleY: 0.65,
alpha: 0.9
});
keyBg.x = rowStartPositions[row] + col * keySpacing;
keyBg.y = 1320 + row * rowSpacing;
codesMenuContainer.addChild(keyBg);
var keyHighlight = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.44,
scaleY: 0.61,
alpha: 0.6
});
keyHighlight.x = rowStartPositions[row] + col * keySpacing;
keyHighlight.y = 1315 + row * rowSpacing;
codesMenuContainer.addChild(keyHighlight);
var keyText = new Text2(letter, {
size: 140,
fill: 0x000000
});
keyText.anchor.set(0.5, 0.5);
keyText.x = rowStartPositions[row] + col * keySpacing;
keyText.y = 1320 + row * rowSpacing;
keyText.interactive = true;
keyText.letter = letter;
keyText.keyBg = keyBg;
keyText.keyHighlight = keyHighlight;
keyText.keyShadow = keyShadow;
keyText.down = function () {
// Enhanced button press animation with multiple elements
tween(this, {
scaleX: 1.15,
scaleY: 1.15,
y: this.y + 3
}, {
duration: 80,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1,
y: this.y - 3
}, {
duration: 120,
easing: tween.easeOut
});
}.bind(this)
});
// Animate key background
tween(this.keyBg, {
scaleX: 0.48,
scaleY: 0.68,
alpha: 1
}, {
duration: 80,
onFinish: function () {
tween(this.keyBg, {
scaleX: 0.42,
scaleY: 0.62,
alpha: 0.9
}, {
duration: 120
});
}.bind(this)
});
// Animate highlight
tween(this.keyHighlight, {
scaleX: 0.44,
scaleY: 0.64,
alpha: 0.8
}, {
duration: 80,
onFinish: function () {
tween(this.keyHighlight, {
scaleX: 0.38,
scaleY: 0.58,
alpha: 0.6
}, {
duration: 120
});
}.bind(this)
});
if (currentCode.length < 25) {
currentCode += this.letter;
codeInputText.setText(currentCode);
// Animate input text when adding character
tween(codeInputText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(codeInputText, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
};
codesMenuContainer.addChild(keyText);
}
}
// Add numbers row (0-9) above the letters
var numbersRow = '0123456789';
var numberRowY = 1120;
var numberRowStartX = 1024 - (numbersRow.length - 1) * keySpacing / 2;
for (var numCol = 0; numCol < numbersRow.length; numCol++) {
var number = numbersRow[numCol];
// Add number key shadow for depth
var numKeyShadow = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.51,
scaleY: 0.68,
alpha: 0.3
});
numKeyShadow.x = numberRowStartX + numCol * keySpacing + 2;
numKeyShadow.y = numberRowY + 2;
codesMenuContainer.addChild(numKeyShadow);
// Add number key background
var numKeyBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.48,
scaleY: 0.65,
alpha: 0.9
});
numKeyBg.x = numberRowStartX + numCol * keySpacing;
numKeyBg.y = numberRowY;
codesMenuContainer.addChild(numKeyBg);
// Add number key highlight
var numKeyHighlight = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.44,
scaleY: 0.61,
alpha: 0.6
});
numKeyHighlight.x = numberRowStartX + numCol * keySpacing;
numKeyHighlight.y = numberRowY - 2;
codesMenuContainer.addChild(numKeyHighlight);
var numKeyText = new Text2(number, {
size: 135,
fill: 0x0080FF
});
numKeyText.anchor.set(0.5, 0.5);
numKeyText.x = numberRowStartX + numCol * keySpacing;
numKeyText.y = numberRowY;
numKeyText.interactive = true;
numKeyText.letter = number;
numKeyText.keyBg = numKeyBg;
numKeyText.keyHighlight = numKeyHighlight;
numKeyText.keyShadow = numKeyShadow;
numKeyText.down = function () {
// Enhanced button press animation matching letter keys
tween(this, {
scaleX: 1.15,
scaleY: 1.15,
y: this.y + 3
}, {
duration: 80,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1,
y: this.y - 3
}, {
duration: 120,
easing: tween.easeOut
});
}.bind(this)
});
// Animate key background
tween(this.keyBg, {
scaleX: 0.54,
scaleY: 0.71,
alpha: 1
}, {
duration: 80,
onFinish: function () {
tween(this.keyBg, {
scaleX: 0.48,
scaleY: 0.65,
alpha: 0.9
}, {
duration: 120
});
}.bind(this)
});
// Animate highlight
tween(this.keyHighlight, {
scaleX: 0.50,
scaleY: 0.67,
alpha: 0.8
}, {
duration: 80,
onFinish: function () {
tween(this.keyHighlight, {
scaleX: 0.44,
scaleY: 0.61,
alpha: 0.6
}, {
duration: 120
});
}.bind(this)
});
if (currentCode.length < 25) {
currentCode += this.letter;
codeInputText.setText(currentCode);
// Animate input text when adding character
tween(codeInputText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(codeInputText, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
};
codesMenuContainer.addChild(numKeyText);
}
// Create enhanced control button layout with improved design
var buttonY = 1720;
var buttonSpacing = 280;
// Clear button with layered design (left)
var clearShadow = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 0.85,
alpha: 0.3
});
clearShadow.x = 1024 - buttonSpacing + 3;
clearShadow.y = buttonY + 3;
codesMenuContainer.addChild(clearShadow);
var clearBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.25,
scaleY: 0.82,
alpha: 0.9
});
clearBg.x = 1024 - buttonSpacing;
clearBg.y = buttonY;
codesMenuContainer.addChild(clearBg);
var clearHighlight = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.68,
alpha: 0.4
});
clearHighlight.x = 1024 - buttonSpacing;
clearHighlight.y = buttonY - 5;
codesMenuContainer.addChild(clearHighlight);
var clearText = new Text2('CLEAR', {
size: 58,
fill: 0x000000
});
clearText.anchor.set(0.5, 0.5);
clearText.x = 1024 - buttonSpacing;
clearText.y = buttonY;
clearText.interactive = true;
clearText.clearBg = clearBg;
clearText.clearHighlight = clearHighlight;
clearText.down = function () {
// Enhanced button animation with 3D effect
tween(this, {
scaleX: 1.05,
scaleY: 1.05,
y: this.y + 2
}, {
duration: 80,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1,
y: this.y - 2
}, {
duration: 120,
easing: tween.easeOut
});
}.bind(this)
});
// Animate background elements
tween(this.clearBg, {
scaleX: 1.35,
scaleY: 0.9,
alpha: 1
}, {
duration: 80,
onFinish: function () {
tween(this.clearBg, {
scaleX: 1.25,
scaleY: 0.82,
alpha: 0.9
}, {
duration: 120
});
}.bind(this)
});
currentCode = '';
codeInputText.setText('');
// Animate input clearing
tween(codeInputText, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(codeInputText, {
alpha: 1
}, {
duration: 200
});
}
});
};
codesMenuContainer.addChild(clearText);
// Submit button with layered design (right)
var submitShadow = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.3,
scaleY: 0.85,
alpha: 0.3
});
submitShadow.x = 1024 + buttonSpacing + 3;
submitShadow.y = buttonY + 3;
codesMenuContainer.addChild(submitShadow);
var submitBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.25,
scaleY: 0.82,
alpha: 0.9
});
submitBg.x = 1024 + buttonSpacing;
submitBg.y = buttonY;
codesMenuContainer.addChild(submitBg);
var submitHighlight = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.68,
alpha: 0.4
});
submitHighlight.x = 1024 + buttonSpacing;
submitHighlight.y = buttonY - 5;
codesMenuContainer.addChild(submitHighlight);
var submitText = new Text2('SUBMIT', {
size: 58,
fill: 0x000000
});
submitText.anchor.set(0.5, 0.5);
submitText.x = 1024 + buttonSpacing;
submitText.y = buttonY;
submitText.interactive = true;
submitText.submitBg = submitBg;
submitText.down = function () {
// Enhanced button animation
tween(this, {
scaleX: 1.05,
scaleY: 1.05,
y: this.y + 2
}, {
duration: 80,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1,
y: this.y - 2
}, {
duration: 120,
easing: tween.easeOut
});
}.bind(this)
});
tween(this.submitBg, {
scaleX: 1.35,
scaleY: 0.9,
alpha: 1
}, {
duration: 80,
onFinish: function () {
tween(this.submitBg, {
scaleX: 1.25,
scaleY: 0.82,
alpha: 0.9
}, {
duration: 120
});
}.bind(this)
});
if (currentCode === 'ZKUIT1GAMESSTAFFMODE') {
// Success animation before activating admin mode
tween(codeInputText, {
fill: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
// Activate admin mode for 15 minutes
adminMode = true;
adminModeEndTime = Date.now() + 15 * 60 * 1000; // 15 minutes in milliseconds
storage.adminModeEndTime = adminModeEndTime;
hideCodesMenu();
showAdminMenu();
}
});
} else if (currentCode === 'LEVELS') {
// Success animation before showing levels menu
tween(codeInputText, {
fill: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
hideCodesMenu();
showLevelsMenu();
}
});
} else if (currentCode === 'RESETALL') {
// Success animation before resetting to level 1
tween(codeInputText, {
fill: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
// Reset player progress to level 1
currentLevel = 1;
storage.currentLevel = 1;
levelScore = 0;
towersToComplete = 5 * currentLevel;
// Update game settings
gameSettings.highestLevelReached = 1;
storage.gameSettings = gameSettings;
// Clear level and reset aircraft
clearLevel();
aircraft.x = 300;
aircraft.y = 1366;
hideCodesMenu();
createMainMenu();
}
});
} else if (currentCode === 'FREEMONEYBETA2025') {
// Check if this code has already been used
var usedCodes = storage.usedCodes || [];
if (usedCodes.indexOf('FREEMONEYBETA2025') >= 0) {
// Code already used - show error
tween(codeInputText, {
scaleX: 1.3,
scaleY: 0.8,
fill: 0xFF0000
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(codeInputText, {
scaleX: 1,
scaleY: 1,
fill: 0x000000
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
currentCode = '';
codeInputText.setText('CODE ALREADY USED');
LK.setTimeout(function () {
codeInputText.setText('');
}, 2000);
} else {
// Success animation before awarding coins
tween(codeInputText, {
fill: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
// Award 200 coins
playerCoins += 200;
storage.playerCoins = playerCoins;
// Mark code as used
usedCodes.push('FREEMONEYBETA2025');
storage.usedCodes = usedCodes;
// Flash screen gold for success
LK.effects.flashScreen(0xFFD700, 500);
// Play coin sound if available
if (LK.getSound('coinCollect')) {
LK.getSound('coinCollect').play();
}
hideCodesMenu();
createMainMenu();
}
});
}
} else if (currentCode.indexOf('TPLEVELSTAFFLV') === 0) {
// Extract level number from code (format: TPLEVELSTAFFLVnumero)
var levelNumberStr = currentCode.substring(14); // Remove 'TPLEVELSTAFFLV' prefix
var targetLevel = parseInt(levelNumberStr, 10);
// Validate level number (must be between 1 and 100)
if (!isNaN(targetLevel) && targetLevel >= 1 && targetLevel <= 100) {
// Success animation before teleporting to level
tween(codeInputText, {
fill: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
// Transport player to specified level
currentLevel = targetLevel;
storage.currentLevel = currentLevel;
levelScore = 0;
towersToComplete = 5 * currentLevel;
// Update game settings if new level is higher than previous highest
if (currentLevel > gameSettings.highestLevelReached) {
gameSettings.highestLevelReached = currentLevel;
storage.gameSettings = gameSettings;
}
// Clear level and reset aircraft
clearLevel();
aircraft.x = 300;
aircraft.y = 1366;
hideCodesMenu();
createMainMenu();
}
});
} else {
// Invalid level number - treat as wrong code
tween(codeInputText, {
scaleX: 1.3,
scaleY: 0.8,
fill: 0xFF0000
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(codeInputText, {
scaleX: 1,
scaleY: 1,
fill: 0x000000
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
currentCode = '';
codeInputText.setText('INVALID LEVEL');
LK.setTimeout(function () {
codeInputText.setText('');
}, 2000);
}
} else {
// Enhanced wrong code animation
tween(codeInputText, {
scaleX: 1.3,
scaleY: 0.8,
fill: 0xFF0000
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(codeInputText, {
scaleX: 1,
scaleY: 1,
fill: 0x000000
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
currentCode = '';
codeInputText.setText('INVALID CODE');
LK.setTimeout(function () {
codeInputText.setText('');
}, 2000);
}
};
codesMenuContainer.addChild(submitText);
// Back button with enhanced design (centered at bottom)
var backShadow = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.75,
alpha: 0.3
});
backShadow.x = 1024 + 2;
backShadow.y = 1870 + 2;
codesMenuContainer.addChild(backShadow);
var backBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.05,
scaleY: 0.72,
alpha: 0.9
});
backBg.x = 1024;
backBg.y = 1870;
codesMenuContainer.addChild(backBg);
var backText = new Text2('BACK', {
size: 58,
fill: 0x000000
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1870;
backText.interactive = true;
backText.backBg = backBg;
backText.down = function () {
// Enhanced back button animation
tween(this, {
scaleX: 1.05,
scaleY: 1.05,
y: this.y + 2
}, {
duration: 80,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1,
y: this.y - 2
}, {
duration: 120,
easing: tween.easeOut
});
}.bind(this)
});
tween(this.backBg, {
scaleX: 1.15,
scaleY: 0.8,
alpha: 1
}, {
duration: 80,
onFinish: function () {
tween(this.backBg, {
scaleX: 1.05,
scaleY: 0.72,
alpha: 0.9
}, {
duration: 120
});
}.bind(this)
});
hideCodesMenu();
createMainMenu();
};
codesMenuContainer.addChild(backText);
// Add sophisticated entrance animations with staggered timing
// Animate title with bounce effect
titleText.alpha = 0;
titleText.scaleX = 0.3;
titleText.scaleY = 0.3;
titleText.y = titleText.y - 50;
tween(titleText, {
alpha: 1,
scaleX: 1,
scaleY: 1,
y: titleText.y + 50
}, {
duration: 800,
easing: tween.bounceOut
});
// Animate input area with cascading effect
inputOuterBorder.alpha = 0;
inputBg.alpha = 0;
inputInner.alpha = 0;
codeInputText.alpha = 0;
instructionText.alpha = 0;
instructionBg.alpha = 0;
// Staggered input area animations
tween(inputOuterBorder, {
alpha: 0.2
}, {
duration: 300
});
LK.setTimeout(function () {
tween(inputBg, {
alpha: 0.4
}, {
duration: 300
});
}, 100);
LK.setTimeout(function () {
tween(inputInner, {
alpha: 0.8
}, {
duration: 300
});
}, 200);
LK.setTimeout(function () {
tween(codeInputText, {
alpha: 1
}, {
duration: 400
});
}, 300);
LK.setTimeout(function () {
tween(instructionBg, {
alpha: 0.3
}, {
duration: 300
});
}, 400);
LK.setTimeout(function () {
tween(instructionText, {
alpha: 1
}, {
duration: 400
});
}, 500);
// Animate keyboard keys with wave effect
for (var animRow = 0; animRow < keyboardRows.length; animRow++) {
for (var animCol = 0; animCol < keyboardRows[animRow].length; animCol++) {
(function (row, col) {
LK.setTimeout(function () {
var keyIndex = row * 10 + col; // Approximate index for timing
var targetKey = codesMenuContainer.children.filter(function (child) {
return child.letter && child.x === rowStartPositions[row] + col * keySpacing && child.y === 1320 + row * rowSpacing;
})[0];
if (targetKey) {
targetKey.alpha = 0;
targetKey.scaleX = 0.5;
targetKey.scaleY = 0.5;
tween(targetKey, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
}, 600 + row * 50 + col * 20);
})(animRow, animCol);
}
}
// Animate number keys
for (var numAnimCol = 0; numAnimCol < numbersRow.length; numAnimCol++) {
(function (col) {
LK.setTimeout(function () {
var targetNumKey = codesMenuContainer.children.filter(function (child) {
return child.letter && child.x === numberRowStartX + col * keySpacing && child.y === numberRowY;
})[0];
if (targetNumKey) {
targetNumKey.alpha = 0;
targetNumKey.scaleX = 0.5;
targetNumKey.scaleY = 0.5;
tween(targetNumKey, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
}, 550 + col * 25);
})(numAnimCol);
}
// Animate control buttons with final cascade
LK.setTimeout(function () {
clearText.alpha = 0;
clearText.scaleX = 0.8;
clearText.scaleY = 0.8;
tween(clearText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 1200);
LK.setTimeout(function () {
submitText.alpha = 0;
submitText.scaleX = 0.8;
submitText.scaleY = 0.8;
tween(submitText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 1300);
LK.setTimeout(function () {
backText.alpha = 0;
backText.scaleX = 0.8;
backText.scaleY = 0.8;
tween(backText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}, 1400);
}
// Function to show shop
function showShop() {
showingShop = true;
shopContainer = new Container();
game.addChild(shopContainer);
// Simple main background
var shopBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 4.5,
alpha: 0.9
});
shopBg.x = 1024;
shopBg.y = 1366;
shopContainer.addChild(shopBg);
// Clean title
var titleText = new Text2('SHOP', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
shopContainer.addChild(titleText);
// Simple coins display
var coinsDisplayText = new Text2('Coins: ' + playerCoins, {
size: 50,
fill: 0xFFD700
});
coinsDisplayText.anchor.set(0.5, 0.5);
coinsDisplayText.x = 1024;
coinsDisplayText.y = 480;
shopContainer.addChild(coinsDisplayText);
// Store reference to update coins display throughout shop
shopContainer.coinsDisplayText = coinsDisplayText;
// Add function to update coins display with animation
shopContainer.updateCoinsDisplay = function (newAmount) {
// Flash effect on coins change
tween(this.coinsDisplayText, {
scaleX: 1.2,
scaleY: 1.2,
fill: 0x00FF00
}, {
duration: 200,
onFinish: function () {
this.coinsDisplayText.setText('Coins: ' + newAmount);
tween(this.coinsDisplayText, {
scaleX: 1,
scaleY: 1,
fill: 0xFFD700
}, {
duration: 300,
easing: tween.bounceOut
});
}.bind(this)
});
};
// Simple centered layout with increased spacing
var centerX = 1024;
var itemStartY = 600;
var itemSpacing = 120;
// Aircraft styles section title
var aircraftTitleText = new Text2('AIRCRAFT STYLES', {
size: 55,
fill: 0xFFFFFF
});
aircraftTitleText.anchor.set(0.5, 0.5);
aircraftTitleText.x = centerX;
aircraftTitleText.y = 560;
shopContainer.addChild(aircraftTitleText);
// Aircraft items with clean design
for (var a = 0; a < aircraftStyles.length; a++) {
var aircraftItem = aircraftStyles[a];
var isOwned = ownedAircraftStyles.indexOf(aircraftItem.id) >= 0;
var isEquipped = currentAircraftStyle === aircraftItem.id;
// Simple item card
var itemBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 1.2,
alpha: isEquipped ? 0.9 : 0.7
});
itemBg.x = centerX;
itemBg.y = itemStartY + a * itemSpacing;
if (isEquipped) itemBg.tint = 0x00AA66;
shopContainer.addChild(itemBg);
// Aircraft preview
var previewAircraft = LK.getAsset('aircraft', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
previewAircraft.x = centerX - 250;
previewAircraft.y = itemStartY + a * itemSpacing;
previewAircraft.tint = aircraftItem.color;
shopContainer.addChild(previewAircraft);
// Item name
var itemNameText = new Text2(aircraftItem.name, {
size: 44,
fill: 0x000000
});
itemNameText.anchor.set(0, 0.5);
itemNameText.x = centerX - 120;
itemNameText.y = itemStartY + a * itemSpacing;
shopContainer.addChild(itemNameText);
// Purchase button
var buttonText = isOwned ? isEquipped ? 'EQUIPPED' : 'EQUIP' : 'BUY ' + aircraftItem.price;
var buttonColor = isOwned ? isEquipped ? 0x888888 : 0x00AA00 : playerCoins >= aircraftItem.price ? 0x0066CC : 0xCC0000;
var itemButton = new Text2(buttonText, {
size: 38,
fill: buttonColor
});
itemButton.anchor.set(0.5, 0.5);
itemButton.x = centerX + 200;
itemButton.y = itemStartY + a * itemSpacing;
itemButton.aircraftItem = aircraftItem;
itemButton.isOwned = isOwned;
itemButton.isEquipped = isEquipped;
if (!isEquipped) {
itemButton.interactive = true;
itemButton.down = function () {
// Simple button animation
tween(this, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}.bind(this)
});
if (this.isOwned) {
// Equip item
currentAircraftStyle = this.aircraftItem.id;
storage.currentAircraftStyle = currentAircraftStyle;
updateAircraftStyle();
LK.effects.flashScreen(0x00FF00, 300);
hideShop();
showShop();
} else if (playerCoins >= this.aircraftItem.price) {
// Purchase item
playerCoins -= this.aircraftItem.price;
storage.playerCoins = playerCoins;
ownedAircraftStyles.push(this.aircraftItem.id);
storage.ownedAircraftStyles = ownedAircraftStyles;
currentAircraftStyle = this.aircraftItem.id;
storage.currentAircraftStyle = currentAircraftStyle;
updateAircraftStyle();
LK.effects.flashScreen(0xFFD700, 500);
if (LK.getSound('coinCollect')) {
LK.getSound('coinCollect').play();
}
hideShop();
showShop();
} else {
// Insufficient funds
LK.effects.flashObject(this, 0xFF0000, 300);
}
};
}
shopContainer.addChild(itemButton);
}
// Simple back button
var backText = new Text2('BACK', {
size: 50,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1300;
backText.interactive = true;
backText.down = function () {
// Simple button animation
tween(this, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function () {
tween(this, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}.bind(this)
});
hideShop();
createMainMenu();
};
shopContainer.addChild(backText);
// Simple fade-in animation
shopContainer.alpha = 0;
tween(shopContainer, {
alpha: 1
}, {
duration: 300
});
}
// Function to hide shop
function hideShop() {
if (shopContainer) {
shopContainer.destroy();
shopContainer = null;
}
showingShop = false;
}
// Function to update aircraft style
function updateAircraftStyle() {
var styleData = aircraftStyles.find(function (style) {
return style.id === currentAircraftStyle;
});
if (styleData && aircraft) {
aircraft.children[0].tint = styleData.color; // Main aircraft body
}
}
// Function to hide codes menu
function hideCodesMenu() {
if (codesMenuContainer) {
codesMenuContainer.destroy();
codesMenuContainer = null;
}
showingCodesMenu = false;
}
// Function to show levels menu
function showLevelsMenu() {
var levelsMenuContainer = new Container();
game.addChild(levelsMenuContainer);
// Semi-transparent background
var levelsBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 4.5,
alpha: 0.95
});
levelsBg.x = 1024;
levelsBg.y = 1366;
levelsMenuContainer.addChild(levelsBg);
// Title
var titleText = new Text2('ALL LEVELS', {
size: 90,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
levelsMenuContainer.addChild(titleText);
// Subtitle with completion info
var completedLevels = gameSettings.highestLevelReached;
var subtitleText = new Text2('Completed: ' + completedLevels + '/100', {
size: 60,
fill: 0x00FF00
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 500;
levelsMenuContainer.addChild(subtitleText);
// Add coins balance display in levels menu
var levelCoinsDisplayBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 0.5,
alpha: 0.4
});
levelCoinsDisplayBg.x = 1024;
levelCoinsDisplayBg.y = 550;
levelsMenuContainer.addChild(levelCoinsDisplayBg);
var levelCoinsText = new Text2('Your Coins: ' + playerCoins, {
size: 45,
fill: 0xFFD700
});
levelCoinsText.anchor.set(0.5, 0.5);
levelCoinsText.x = 1024;
levelCoinsText.y = 550;
levelsMenuContainer.addChild(levelCoinsText);
// Create scrollable container for levels
var scrollContainer = new Container();
levelsMenuContainer.addChild(scrollContainer);
// Create level display in grid format (10 columns, 10 rows for 100 levels)
for (var level = 1; level <= 100; level++) {
var isCompleted = level <= completedLevels;
var levelButton = new Text2(level.toString(), {
size: 35,
fill: isCompleted ? 0x00FF00 : 0x888888 // Green if completed, gray if not
});
levelButton.anchor.set(0.5, 0.5);
// Position in 10x10 grid
levelButton.x = 300 + (level - 1) % 10 * 145;
levelButton.y = 650 + Math.floor((level - 1) / 10) * 60;
// Add background for better visibility
var levelBg = LK.getAsset('towerTop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7,
alpha: isCompleted ? 0.8 : 0.3
});
levelBg.x = levelButton.x;
levelBg.y = levelButton.y;
scrollContainer.addChild(levelBg);
scrollContainer.addChild(levelButton);
// Add completion checkmark for completed levels
if (isCompleted) {
var checkmark = new Text2('✓', {
size: 25,
fill: 0xFFD700
});
checkmark.anchor.set(0.5, 0.5);
checkmark.x = levelButton.x + 25;
checkmark.y = levelButton.y - 25;
scrollContainer.addChild(checkmark);
}
}
// Add scroll instruction
var scrollText = new Text2('Scroll to see all levels', {
size: 45,
fill: 0xFFFF00
});
scrollText.anchor.set(0.5, 0.5);
scrollText.x = 1024;
scrollText.y = 600;
levelsMenuContainer.addChild(scrollText);
// Add scroll functionality
var scrollY = 0;
var maxScroll = Math.max(0, Math.ceil(100 / 10) * 60 - 500);
levelsMenuContainer.interactive = true;
levelsMenuContainer.move = function (x, y, obj) {
if (obj.deltaY) {
scrollY -= obj.deltaY * 2;
scrollY = Math.max(-maxScroll, Math.min(0, scrollY));
scrollContainer.y = scrollY;
}
};
// Back button
var backText = new Text2('BACK', {
size: 60,
fill: 0xFF8000
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1600;
backText.interactive = true;
backText.down = function () {
levelsMenuContainer.destroy();
createMainMenu();
};
levelsMenuContainer.addChild(backText);
// Add entrance animation
levelsMenuContainer.alpha = 0;
tween(levelsMenuContainer, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
// Function to show admin menu
function showAdminMenu() {
var adminMenuContainer = new Container();
game.addChild(adminMenuContainer);
// Semi-transparent background
var adminBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 4,
alpha: 0.9
});
adminBg.x = 1024;
adminBg.y = 1366;
adminMenuContainer.addChild(adminBg);
// Title
var titleText = new Text2('ADMIN MODE ACTIVATED', {
size: 70,
fill: 0xFF0000
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
adminMenuContainer.addChild(titleText);
// Level selection title
var levelSelectText = new Text2('SELECT LEVEL:', {
size: 60,
fill: 0xFFFFFF
});
levelSelectText.anchor.set(0.5, 0.5);
levelSelectText.x = 1024;
levelSelectText.y = 800;
adminMenuContainer.addChild(levelSelectText);
// Create scrollable level buttons (1-100)
var scrollContainer = new Container();
adminMenuContainer.addChild(scrollContainer);
// Create level buttons in a grid layout
for (var level = 1; level <= 100; level++) {
var levelButton = new Text2(level.toString(), {
size: 35,
fill: 0x00FF00
});
levelButton.anchor.set(0.5, 0.5);
// 10 columns, 10 rows for 100 levels
levelButton.x = 300 + (level - 1) % 10 * 145;
levelButton.y = 900 + Math.floor((level - 1) / 10) * 60;
levelButton.interactive = true;
levelButton.targetLevel = level;
levelButton.down = function () {
currentLevel = this.targetLevel;
storage.currentLevel = currentLevel;
adminMenuContainer.destroy();
createMainMenu();
};
scrollContainer.addChild(levelButton);
}
// Add scroll instruction text
var scrollText = new Text2('Scroll to see all 100 levels', {
size: 40,
fill: 0xFFFF00
});
scrollText.anchor.set(0.5, 0.5);
scrollText.x = 1024;
scrollText.y = 850;
adminMenuContainer.addChild(scrollText);
// Add scroll functionality
var scrollY = 0;
var maxScroll = Math.max(0, Math.ceil(100 / 10) * 60 - 400); // Adjust based on visible area
adminMenuContainer.interactive = true;
adminMenuContainer.move = function (x, y, obj) {
if (obj.deltaY) {
scrollY -= obj.deltaY * 2;
scrollY = Math.max(-maxScroll, Math.min(0, scrollY));
scrollContainer.y = scrollY;
}
};
// Back button
var backText = new Text2('BACK TO MENU', {
size: 50,
fill: 0xFF8000
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1500;
backText.interactive = true;
backText.down = function () {
adminMenuContainer.destroy();
createMainMenu();
};
adminMenuContainer.addChild(backText);
}
// Function to hide main menu
function hideMainMenu() {
if (mainMenuContainer) {
mainMenuContainer.destroy();
mainMenuContainer = null;
}
showingMainMenu = false;
}
// Function to start game
function startGame() {
gameStarted = true;
// Reset game state
levelScore = 0;
towersToComplete = 5 * currentLevel;
invulnerabilityTime = 0;
comboMultiplier = 1;
powerUpSpawnTimer = 0;
// Clear any existing game objects
clearLevel();
// Reset aircraft position
aircraft.x = 300;
aircraft.y = 1366;
// Update UI
levelText.setText('Level: ' + currentLevel);
progressText.setText('Progress: 0/' + towersToComplete);
scoreText.setText('Score: ' + LK.getScore());
coinsText.setText('Coins: ' + playerCoins);
// Apply current aircraft style
updateAircraftStyle();
// Start background music
if (gameSettings.musicEnabled && !musicPlaying) {
LK.stopMusic(); // Stop any menu music
LK.playMusic('backgroundMusic', {
loop: true
});
musicPlaying = true;
}
}
// Function to hide menu
function hideMenu() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
}
showingMenu = false;
gameStarted = true;
}
// Function to clear level objects
function clearLevel() {
// Clear existing towers
for (var i = towers.length - 1; i >= 0; i--) {
towers[i].destroy();
towers.splice(i, 1);
}
// Clear finish line
if (finishLine) {
finishLine.destroy();
finishLine = null;
}
// Clear existing clouds
for (var c = clouds.length - 1; c >= 0; c--) {
clouds[c].destroy();
clouds.splice(c, 1);
}
// Clear power-ups
for (var p = powerUps.length - 1; p >= 0; p--) {
powerUps[p].destroy();
powerUps.splice(p, 1);
}
// Clear particles
for (var pt = particles.length - 1; pt >= 0; pt--) {
particles[pt].destroy();
particles.splice(pt, 1);
}
// Clear spark particles
for (var sp = sparkParticles.length - 1; sp >= 0; sp--) {
sparkParticles[sp].destroy();
sparkParticles.splice(sp, 1);
}
// Clear coins
for (var co = coins.length - 1; co >= 0; co--) {
coins[co].destroy();
coins.splice(co, 1);
}
}
// Function to complete level
function completeLevel() {
currentLevel++;
// Save progress to storage
storage.currentLevel = currentLevel;
levelScore = 0;
towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc.
// Reset power-up system
invulnerabilityTime = 0;
comboMultiplier = 1;
powerUpSpawnTimer = 0;
// Clear existing towers and finish line
clearLevel();
// Reset aircraft position
aircraft.x = 300;
aircraft.y = 1366;
// Update UI
levelText.setText('Level: ' + currentLevel);
progressText.setText('Progress: 0/' + towersToComplete);
// Enhanced level completion effects with camera shake
startCameraShake(10, 60); // Gentle celebration shake
LK.effects.flashScreen(0x00ff00, 1000);
LK.getSound('levelComplete').play();
// Bonus score for completing level with progressive rewards
var bonusScore = 100 * currentLevel * comboMultiplier;
var milestoneBonus = 0;
// Milestone bonuses for every 10 levels
if (currentLevel % 10 === 0) {
milestoneBonus = 1000 * (currentLevel / 10);
playerCoins += 50; // Bonus coins for milestone
storage.playerCoins = playerCoins;
coinsText.setText('Coins: ' + playerCoins);
}
LK.setScore(LK.getScore() + bonusScore + milestoneBonus);
scoreText.setText('Score: ' + LK.getScore());
// Create celebration particles
for (var i = 0; i < 10; i++) {
LK.setTimeout(function () {
createSparkParticle(aircraft.x + (Math.random() - 0.5) * 200, aircraft.y + (Math.random() - 0.5) * 100);
}, i * 50);
}
}
// Enhanced camera shake system
var cameraShake = {
active: false,
intensity: 0,
duration: 0,
originalX: 0,
originalY: 0
};
function startCameraShake(intensity, duration) {
if (!gameSettings.screenshakeEnabled) return;
cameraShake.active = true;
cameraShake.intensity = intensity;
cameraShake.duration = duration;
cameraShake.originalX = game.x;
cameraShake.originalY = game.y;
}
function updateCameraShake() {
if (!cameraShake.active) return;
cameraShake.duration--;
if (cameraShake.duration <= 0) {
cameraShake.active = false;
game.x = cameraShake.originalX;
game.y = cameraShake.originalY;
return;
}
var shakeX = (Math.random() - 0.5) * cameraShake.intensity;
var shakeY = (Math.random() - 0.5) * cameraShake.intensity;
game.x = cameraShake.originalX + shakeX;
game.y = cameraShake.originalY + shakeY;
}
// Function to handle game over
function gameOver() {
// Save current level to storage so player can restart from this level
storage.currentLevel = currentLevel;
// Enhanced screen shake for dramatic effect
startCameraShake(25, 120);
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('crash').play();
LK.showGameOver();
}
// Main game update loop
game.update = function () {
// Update camera shake system
updateCameraShake();
// Check if admin mode has expired
if (adminMode && Date.now() > adminModeEndTime) {
adminMode = false;
adminModeEndTime = 0;
storage.adminModeEndTime = 0;
}
if (!gameStarted || showingMenu || showingMainMenu || showingCodesMenu || showingShop) return;
// Update invulnerability
if (invulnerabilityTime > 0) {
invulnerabilityTime--;
if (invulnerabilityTime === 0) {
aircraft.alpha = 1; // Restore normal appearance
}
}
// Update combo multiplier decay
if (LK.ticks - lastPowerUpTime > 1800) {
// 30 seconds
comboMultiplier = Math.max(1, comboMultiplier - 0.01);
}
// Spawn clouds for background atmosphere
if (LK.ticks % 180 === 0) {
// Spawn cloud every 3 seconds at 60fps
spawnCloud();
}
// Spawn coins
coinSpawnTimer++;
if (coinSpawnTimer > 180 + Math.random() * 120) {
// Every 3-5 seconds
spawnCoin();
coinSpawnTimer = 0;
}
// Spawn power-ups
powerUpSpawnTimer++;
if (powerUpSpawnTimer > 600 + Math.random() * 300) {
// Every 10-15 seconds
spawnPowerUp();
powerUpSpawnTimer = 0;
}
// Update clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
// Remove clouds that have moved off screen
if (cloud.x < -200) {
cloud.destroy();
clouds.splice(c, 1);
}
}
// Update coins
for (var co = coins.length - 1; co >= 0; co--) {
var coin = coins[co];
// Remove if off screen
if (coin.x < -100) {
coin.destroy();
coins.splice(co, 1);
continue;
}
// Check collection
var coinIntersecting = aircraft.intersects(coin);
if (!coin.lastIntersecting && coinIntersecting && !coin.collected) {
coin.collected = true;
playerCoins += 5; // Award 5 coins per collection
storage.playerCoins = playerCoins;
coinsText.setText('Coins: ' + playerCoins);
// Coin collection effect
LK.effects.flashObject(coin, 0xFFD700, 300);
LK.getSound('coinCollect').play();
// Create coin text popup
var coinPopup = new Text2('+5', {
size: 40,
fill: 0xFFD700
});
coinPopup.anchor.set(0.5, 0.5);
coinPopup.x = coin.x;
coinPopup.y = coin.y;
game.addChild(coinPopup);
tween(coinPopup, {
y: coinPopup.y - 80,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
coinPopup.destroy();
}
});
coin.destroy();
coins.splice(co, 1);
continue;
}
coin.lastIntersecting = coinIntersecting;
}
// Update spark particles
for (var sp = sparkParticles.length - 1; sp >= 0; sp--) {
var spark = sparkParticles[sp];
// Particles are automatically removed in their update method
}
// Update power-ups
for (var p = powerUps.length - 1; p >= 0; p--) {
var powerUp = powerUps[p];
// Remove if off screen
if (powerUp.x < -100) {
powerUp.destroy();
powerUps.splice(p, 1);
continue;
}
// Check collection
var currentIntersecting = aircraft.intersects(powerUp);
if (!powerUp.lastIntersecting && currentIntersecting && !powerUp.collected) {
powerUp.collected = true;
applyPowerUpEffect();
powerUp.destroy();
powerUps.splice(p, 1);
continue;
}
powerUp.lastIntersecting = currentIntersecting;
}
// Spawn towers based on level difficulty (adjusted for levels 1-100)
var spawnRate = Math.max(60, 300 - Math.min(currentLevel, 15) * 15); // Gradual increase, cap at level 15 difficulty
if (LK.ticks % spawnRate === 0) {
spawnTower();
}
// Check if we should spawn finish line
var progress = Math.floor(levelScore / 2);
if (progress >= towersToComplete && !finishLine) {
spawnFinishLine();
}
// Update finish line
if (finishLine) {
// Check if finish line went off screen
if (finishLine.lastX >= -200 && finishLine.x < -200) {
finishLine.destroy();
finishLine = null;
}
// Check if aircraft crossed finish line
if (!finishLine.crossed && finishLine.x < aircraft.x) {
finishLine.crossed = true;
createLevelMenu();
return;
}
}
// Update towers
for (var i = towers.length - 1; i >= 0; i--) {
var tower = towers[i];
// Check if tower went off screen
if (tower.lastX >= -200 && tower.x < -200) {
towers.splice(i, 1);
tower.destroy();
continue;
}
// Check collision with aircraft (skip if invulnerable)
var currentIntersecting = aircraft.intersects(tower);
if (!tower.lastIntersecting && currentIntersecting && invulnerabilityTime <= 0) {
// Create dramatic collision effect
createTowerDestructionEffect(tower.x, tower.y);
startCameraShake(30, 100);
LK.getSound('crash').play();
gameOver();
return;
}
tower.lastIntersecting = currentIntersecting;
// Check if aircraft passed tower (score point)
if (!tower.passed && tower.x < aircraft.x - 100) {
tower.passed = true;
levelScore++;
var basePoints = 10 * currentLevel;
var bonusPoints = Math.floor(basePoints * comboMultiplier);
LK.setScore(LK.getScore() + bonusPoints);
LK.getSound('dodge').play();
LK.getSound('whoosh').play();
// Update progress
var progress = Math.floor(levelScore / 2); // Two towers per obstacle
progressText.setText('Progress: ' + progress + '/' + towersToComplete);
scoreText.setText('Score: ' + LK.getScore());
// Create score popup for bonus points
if (comboMultiplier > 1) {
var bonusText = new Text2('+' + bonusPoints + ' (x' + comboMultiplier.toFixed(1) + ')', {
size: 40,
fill: 0xFFD700
});
bonusText.anchor.set(0.5, 0.5);
bonusText.x = aircraft.x;
bonusText.y = aircraft.y - 50;
game.addChild(bonusText);
// Animate bonus text
tween(bonusText, {
y: bonusText.y - 100,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
bonusText.destroy();
}
});
}
// Animate score text to highlight points earned
tween.stop(scoreText, {
scaleX: true,
scaleY: true
});
tween(scoreText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
// Dynamic background color system based on level
var targetBackgroundColor = 0x87CEFA; // Default sky blue
if (currentLevel >= 80) {
targetBackgroundColor = 0x2F1B69; // Deep purple for high levels
} else if (currentLevel >= 60) {
targetBackgroundColor = 0x1a1a2e; // Dark blue
} else if (currentLevel >= 40) {
targetBackgroundColor = 0x16213e; // Navy blue
} else if (currentLevel >= 20) {
targetBackgroundColor = 0x0f3460; // Medium blue
}
// Gradually transition background color every few seconds
if (LK.ticks % 300 === 0) {
// Every 5 seconds
var currentBg = game.backgroundColor || 0x87CEFA;
if (currentBg !== targetBackgroundColor) {
// Simple color transition by setting it directly
game.setBackgroundColor(targetBackgroundColor);
}
}
// Aircraft stays stationary while towers move to create forward movement illusion
};