User prompt
Ajusta el menú principal para que sea simétrico
User prompt
Quita el leaderboard
User prompt
Pues un amigo mío ha jugado y no sale en el leaderboard
User prompt
Haz que el asset crash suene cuando el avión se choque con una torre
User prompt
Haz que el asset backgroundMusic suene mientras está haciendo un nivel
User prompt
Haz que el asset coinCollect suene cuando coges una moneda
User prompt
Haz que el asset menuMusic suene mientras estás en el menú principal
User prompt
Separa los botones de la tienda
User prompt
Haz que los artículos de la tienda se vean más grandes
User prompt
Haz que los artículos de la tienda se vean más grandes
User prompt
Añade un código (Freemoneybeta2025) donde te añada 200 monedas, quiero que esto código sea de un solo uso por cada jugador ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Mejora el control del avión
User prompt
Añade un código que sea “tplevelstafflvnumero” (sustituyendo numero por el nivel al que se le debe transportar al jugador ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Haz la tienda más simple y bonita ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Añade un código “Resetall” que te lleve al nivel 1 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Añade música al juego
User prompt
Mejora la tienda ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Añade un apartado donde puedas ver el número de monedas que tienes ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Mejora el estilo y la simetría de la tienda ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Haz un apartado en el menú principal llamado “shop” donde puedes comprar diferentes estilos del avión o de las torres por monedas, haz que esas monedas se consigan en los niveles, haciendo que el jugador las tenga que atrapar ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Quita el control por cámara, y añade un código “Levels” que al ponerlo te salga un listado de todos los niveles que hay (solo ver los niveles que hay y cuáles has completado) ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Mejora todo lo que puedas el juego ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1, @upit/facekit.v1
User prompt
Agrega hasta el nivel 100 al juego
User prompt
Baja las letras para que estén separadas de los números ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Separa más las letras y los números ↪💡 Consider importing and using the following plugins: @upit/tween.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 propeller.rotation += propeller.rotationSpeed; // 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 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 var speed = Math.max(1.5, 3 - (5 - currentLevel) * 0.3); // Match tower speed self.x -= speed; }; 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 (much slower for level 1) var speed = Math.max(1.5, 3 - (5 - currentLevel) * 0.3); // Very slow for level 1 self.x -= speed; }; return self; }); /**** * Initialize Game ****/ // Game variables var game = new LK.Game({ backgroundColor: 0x87CEFA // More realistic sky blue background }); /**** * Game Code ****/ // Initialize assets for the tower dodge flight game // Game variables //Storage plugin for persistent game data 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 leaderboardContainer = null; var showingLeaderboard = false; var playerName = storage.playerName || generateRandomName(); 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 }; // 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; // 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 || showingLeaderboard || showingMenu) return; dragActive = true; }; game.up = function (x, y, obj) { if (showingMainMenu || showingLeaderboard || showingMenu) return; dragActive = false; }; game.move = function (x, y, obj) { if (showingMainMenu || showingLeaderboard || showingMenu) return; if (dragActive) { var 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 var gapSize = Math.max(400, 700 - currentLevel * 40); // Much larger gap for level 1, reduce more gradually 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); // 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); } // 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 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); // Leaderboard button var leaderboardText = new Text2('Leaderboard', { size: 60, fill: 0xFF00FF }); leaderboardText.anchor.set(0.5, 0.5); leaderboardText.x = 1024; leaderboardText.y = 1600; leaderboardText.interactive = true; leaderboardText.down = function () { showLeaderboard(); }; menuContainer.addChild(leaderboardText); } // 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); // 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: 800, 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 = 950; 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: 1200, alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.elasticOut }); // Leaderboard button var leaderboardText = new Text2('LEADERBOARD', { size: 80, fill: 0xFF00FF }); leaderboardText.anchor.set(0.5, 0.5); leaderboardText.x = 1024; leaderboardText.y = 1400; leaderboardText.interactive = true; leaderboardText.down = function () { hideMainMenu(); showLeaderboard(); }; mainMenuContainer.addChild(leaderboardText); // Codes button var codesText = new Text2('CODES', { size: 80, fill: 0xFF8000 }); codesText.anchor.set(0.5, 0.5); codesText.x = 1024; codesText.y = 1500; 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 = 1600; mainMenuContainer.addChild(levelIndicatorText); } // 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 = 1200 + 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 = 1200 + 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 = 1195 + 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 = 1200 + 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 = 1600; 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 { // 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 = 1750 + 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 = 1750; codesMenuContainer.addChild(backBg); var backText = new Text2('BACK', { size: 58, fill: 0x000000 }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 1750; 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; })[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 hide codes menu function hideCodesMenu() { if (codesMenuContainer) { codesMenuContainer.destroy(); codesMenuContainer = null; } showingCodesMenu = false; } // 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 level buttons (1-20) for (var level = 1; level <= 20; level++) { var levelButton = new Text2(level.toString(), { size: 40, fill: 0x00FF00 }); levelButton.anchor.set(0.5, 0.5); levelButton.x = 400 + (level - 1) % 10 * 120; levelButton.y = 900 + Math.floor((level - 1) / 10) * 80; levelButton.interactive = true; levelButton.targetLevel = level; levelButton.down = function () { currentLevel = this.targetLevel; storage.currentLevel = currentLevel; adminMenuContainer.destroy(); createMainMenu(); }; adminMenuContainer.addChild(levelButton); } // 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; // 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()); } // Function to generate random player name function generateRandomName() { var adjectives = ['Swift', 'Brave', 'Quick', 'Sharp', 'Bold', 'Fast', 'Smart', 'Cool', 'Wild', 'Free']; var nouns = ['Pilot', 'Ace', 'Flyer', 'Eagle', 'Hawk', 'Storm', 'Wing', 'Sky', 'Star', 'Hero']; var randomAdj = adjectives[Math.floor(Math.random() * adjectives.length)]; var randomNoun = nouns[Math.floor(Math.random() * nouns.length)]; var randomNum = Math.floor(Math.random() * 999) + 1; return randomAdj + randomNoun + randomNum; } // Function to hide menu function hideMenu() { if (menuContainer) { menuContainer.destroy(); menuContainer = null; } showingMenu = false; gameStarted = true; } // Function to show leaderboard function showLeaderboard() { showingLeaderboard = true; leaderboardContainer = new Container(); game.addChild(leaderboardContainer); // Semi-transparent background var leaderboardBg = LK.getAsset('towerBase', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 4, alpha: 0.9 }); leaderboardBg.x = 1024; leaderboardBg.y = 1366; leaderboardContainer.addChild(leaderboardBg); // Title var titleText = new Text2('LEADERBOARD - TOP 100', { size: 80, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 300; leaderboardContainer.addChild(titleText); // Get leaderboard data var leaderboardNames = storage.leaderboardNames || []; var leaderboardLevels = storage.leaderboardLevels || []; // Display top 10 entries (or all if less than 10) var displayCount = Math.min(10, leaderboardNames.length); for (var i = 0; i < displayCount; i++) { var rank = i + 1; var entryText = rank + '. ' + leaderboardNames[i] + ' - Level ' + leaderboardLevels[i]; var entryDisplay = new Text2(entryText, { size: 50, fill: i < 3 ? 0xFFD700 : 0xFFFFFF // Gold for top 3 }); entryDisplay.anchor.set(0.5, 0.5); entryDisplay.x = 1024; entryDisplay.y = 450 + i * 70; leaderboardContainer.addChild(entryDisplay); } // Show player's position if not in top 10 var playerRank = -1; for (var j = 0; j < leaderboardNames.length; j++) { if (leaderboardNames[j] === playerName) { playerRank = j + 1; break; } } if (playerRank > 10 && playerRank <= 100) { var playerEntryText = '...\n' + playerRank + '. ' + playerName + ' - Level ' + leaderboardLevels[playerRank - 1] + ' (You)'; var playerDisplay = new Text2(playerEntryText, { size: 45, fill: 0x00FF00 }); playerDisplay.anchor.set(0.5, 0.5); playerDisplay.x = 1024; playerDisplay.y = 1150; leaderboardContainer.addChild(playerDisplay); } // Close button var closeText = new Text2('Close', { size: 60, fill: 0xFF0000 }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 1300; closeText.interactive = true; closeText.down = function () { hideLeaderboard(); }; leaderboardContainer.addChild(closeText); } // Function to hide leaderboard function hideLeaderboard() { if (leaderboardContainer) { leaderboardContainer.destroy(); leaderboardContainer = null; } showingLeaderboard = false; // Return to main menu if game hasn't started if (!gameStarted) { createMainMenu(); } } // 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); } } // Function to update leaderboard function updateLeaderboard(level) { var leaderboardNames = storage.leaderboardNames || []; var leaderboardLevels = storage.leaderboardLevels || []; // Find if player already exists in leaderboard var playerIndex = -1; for (var i = 0; i < leaderboardNames.length; i++) { if (leaderboardNames[i] === playerName) { playerIndex = i; break; } } if (playerIndex >= 0) { // Update existing player if new level is higher if (level > leaderboardLevels[playerIndex]) { leaderboardLevels[playerIndex] = level; } } else { // Add new player leaderboardNames.push(playerName); leaderboardLevels.push(level); } // Create combined array for sorting var combined = []; for (var j = 0; j < leaderboardNames.length; j++) { combined.push({ name: leaderboardNames[j], level: leaderboardLevels[j] }); } // Sort by level (highest first) combined.sort(function (a, b) { return b.level - a.level; }); // Keep only top 100 if (combined.length > 100) { combined = combined.slice(0, 100); } // Split back into separate arrays leaderboardNames = []; leaderboardLevels = []; for (var k = 0; k < combined.length; k++) { leaderboardNames.push(combined[k].name); leaderboardLevels.push(combined[k].level); } storage.leaderboardNames = leaderboardNames; storage.leaderboardLevels = leaderboardLevels; storage.playerName = playerName; } // Function to complete level function completeLevel() { currentLevel++; // Update leaderboard with new level updateLeaderboard(currentLevel); // Save progress to storage storage.currentLevel = currentLevel; levelScore = 0; towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc. // 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); // Flash screen green for level completion LK.effects.flashScreen(0x00ff00, 1000); } // Function to handle game over function gameOver() { // Update leaderboard with current level reached updateLeaderboard(currentLevel); // Save current level to storage so player can restart from this level storage.currentLevel = currentLevel; // Add screen shake effect for more dramatic crash var originalX = game.x; var shakeIntensity = 20; var shakeDuration = 100; for (var s = 0; s < 5; s++) { tween(game, { x: originalX + (Math.random() - 0.5) * shakeIntensity }, { duration: shakeDuration }); } // Return to original position after shake LK.setTimeout(function () { tween(game, { x: originalX }, { duration: 200, easing: tween.easeOut }); }, 600); LK.effects.flashScreen(0xff0000, 1000); LK.getSound('crash').play(); LK.showGameOver(); } // Main game update loop game.update = function () { // Check if admin mode has expired if (adminMode && Date.now() > adminModeEndTime) { adminMode = false; adminModeEndTime = 0; storage.adminModeEndTime = 0; } if (!gameStarted || showingMenu || showingLeaderboard || showingMainMenu || showingCodesMenu) return; // Spawn clouds for background atmosphere if (LK.ticks % 180 === 0) { // Spawn cloud every 3 seconds at 60fps spawnCloud(); } // 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); } } // Spawn towers based on level difficulty var spawnRate = Math.max(120, 300 - currentLevel * 20); // Much slower spawning for level 1 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) { // Animate tower destruction tween(tower, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { tower.destroy(); } }); towers.splice(i, 1); continue; } // Check collision with aircraft var currentIntersecting = aircraft.intersects(tower); if (!tower.lastIntersecting && currentIntersecting) { gameOver(); return; } tower.lastIntersecting = currentIntersecting; // Check if aircraft passed tower (score point) if (!tower.passed && tower.x < aircraft.x - 100) { tower.passed = true; levelScore++; LK.setScore(LK.getScore() + 10 * currentLevel); // More points per level LK.getSound('dodge').play(); // Update progress var progress = Math.floor(levelScore / 2); // Two towers per obstacle progressText.setText('Progress: ' + progress + '/' + towersToComplete); scoreText.setText('Score: ' + LK.getScore()); // 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 }); } }); } } // 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
propeller.rotation += propeller.rotationSpeed;
// 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 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
var speed = Math.max(1.5, 3 - (5 - currentLevel) * 0.3); // Match tower speed
self.x -= speed;
};
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 (much slower for level 1)
var speed = Math.max(1.5, 3 - (5 - currentLevel) * 0.3); // Very slow for level 1
self.x -= speed;
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x87CEFA // More realistic sky blue background
});
/****
* Game Code
****/
// Initialize assets for the tower dodge flight game
// Game variables
//Storage plugin for persistent game data
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 leaderboardContainer = null;
var showingLeaderboard = false;
var playerName = storage.playerName || generateRandomName();
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
};
// 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;
// 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 || showingLeaderboard || showingMenu) return;
dragActive = true;
};
game.up = function (x, y, obj) {
if (showingMainMenu || showingLeaderboard || showingMenu) return;
dragActive = false;
};
game.move = function (x, y, obj) {
if (showingMainMenu || showingLeaderboard || showingMenu) return;
if (dragActive) {
var 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
var gapSize = Math.max(400, 700 - currentLevel * 40); // Much larger gap for level 1, reduce more gradually
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);
// 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);
}
// 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 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);
// Leaderboard button
var leaderboardText = new Text2('Leaderboard', {
size: 60,
fill: 0xFF00FF
});
leaderboardText.anchor.set(0.5, 0.5);
leaderboardText.x = 1024;
leaderboardText.y = 1600;
leaderboardText.interactive = true;
leaderboardText.down = function () {
showLeaderboard();
};
menuContainer.addChild(leaderboardText);
}
// 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);
// 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: 800,
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 = 950;
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: 1200,
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.elasticOut
});
// Leaderboard button
var leaderboardText = new Text2('LEADERBOARD', {
size: 80,
fill: 0xFF00FF
});
leaderboardText.anchor.set(0.5, 0.5);
leaderboardText.x = 1024;
leaderboardText.y = 1400;
leaderboardText.interactive = true;
leaderboardText.down = function () {
hideMainMenu();
showLeaderboard();
};
mainMenuContainer.addChild(leaderboardText);
// Codes button
var codesText = new Text2('CODES', {
size: 80,
fill: 0xFF8000
});
codesText.anchor.set(0.5, 0.5);
codesText.x = 1024;
codesText.y = 1500;
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 = 1600;
mainMenuContainer.addChild(levelIndicatorText);
}
// 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 = 1200 + 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 = 1200 + 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 = 1195 + 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 = 1200 + 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 = 1600;
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 {
// 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 = 1750 + 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 = 1750;
codesMenuContainer.addChild(backBg);
var backText = new Text2('BACK', {
size: 58,
fill: 0x000000
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1750;
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;
})[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 hide codes menu
function hideCodesMenu() {
if (codesMenuContainer) {
codesMenuContainer.destroy();
codesMenuContainer = null;
}
showingCodesMenu = false;
}
// 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 level buttons (1-20)
for (var level = 1; level <= 20; level++) {
var levelButton = new Text2(level.toString(), {
size: 40,
fill: 0x00FF00
});
levelButton.anchor.set(0.5, 0.5);
levelButton.x = 400 + (level - 1) % 10 * 120;
levelButton.y = 900 + Math.floor((level - 1) / 10) * 80;
levelButton.interactive = true;
levelButton.targetLevel = level;
levelButton.down = function () {
currentLevel = this.targetLevel;
storage.currentLevel = currentLevel;
adminMenuContainer.destroy();
createMainMenu();
};
adminMenuContainer.addChild(levelButton);
}
// 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;
// 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());
}
// Function to generate random player name
function generateRandomName() {
var adjectives = ['Swift', 'Brave', 'Quick', 'Sharp', 'Bold', 'Fast', 'Smart', 'Cool', 'Wild', 'Free'];
var nouns = ['Pilot', 'Ace', 'Flyer', 'Eagle', 'Hawk', 'Storm', 'Wing', 'Sky', 'Star', 'Hero'];
var randomAdj = adjectives[Math.floor(Math.random() * adjectives.length)];
var randomNoun = nouns[Math.floor(Math.random() * nouns.length)];
var randomNum = Math.floor(Math.random() * 999) + 1;
return randomAdj + randomNoun + randomNum;
}
// Function to hide menu
function hideMenu() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
}
showingMenu = false;
gameStarted = true;
}
// Function to show leaderboard
function showLeaderboard() {
showingLeaderboard = true;
leaderboardContainer = new Container();
game.addChild(leaderboardContainer);
// Semi-transparent background
var leaderboardBg = LK.getAsset('towerBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 4,
alpha: 0.9
});
leaderboardBg.x = 1024;
leaderboardBg.y = 1366;
leaderboardContainer.addChild(leaderboardBg);
// Title
var titleText = new Text2('LEADERBOARD - TOP 100', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
leaderboardContainer.addChild(titleText);
// Get leaderboard data
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardLevels = storage.leaderboardLevels || [];
// Display top 10 entries (or all if less than 10)
var displayCount = Math.min(10, leaderboardNames.length);
for (var i = 0; i < displayCount; i++) {
var rank = i + 1;
var entryText = rank + '. ' + leaderboardNames[i] + ' - Level ' + leaderboardLevels[i];
var entryDisplay = new Text2(entryText, {
size: 50,
fill: i < 3 ? 0xFFD700 : 0xFFFFFF // Gold for top 3
});
entryDisplay.anchor.set(0.5, 0.5);
entryDisplay.x = 1024;
entryDisplay.y = 450 + i * 70;
leaderboardContainer.addChild(entryDisplay);
}
// Show player's position if not in top 10
var playerRank = -1;
for (var j = 0; j < leaderboardNames.length; j++) {
if (leaderboardNames[j] === playerName) {
playerRank = j + 1;
break;
}
}
if (playerRank > 10 && playerRank <= 100) {
var playerEntryText = '...\n' + playerRank + '. ' + playerName + ' - Level ' + leaderboardLevels[playerRank - 1] + ' (You)';
var playerDisplay = new Text2(playerEntryText, {
size: 45,
fill: 0x00FF00
});
playerDisplay.anchor.set(0.5, 0.5);
playerDisplay.x = 1024;
playerDisplay.y = 1150;
leaderboardContainer.addChild(playerDisplay);
}
// Close button
var closeText = new Text2('Close', {
size: 60,
fill: 0xFF0000
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 1300;
closeText.interactive = true;
closeText.down = function () {
hideLeaderboard();
};
leaderboardContainer.addChild(closeText);
}
// Function to hide leaderboard
function hideLeaderboard() {
if (leaderboardContainer) {
leaderboardContainer.destroy();
leaderboardContainer = null;
}
showingLeaderboard = false;
// Return to main menu if game hasn't started
if (!gameStarted) {
createMainMenu();
}
}
// 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);
}
}
// Function to update leaderboard
function updateLeaderboard(level) {
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardLevels = storage.leaderboardLevels || [];
// Find if player already exists in leaderboard
var playerIndex = -1;
for (var i = 0; i < leaderboardNames.length; i++) {
if (leaderboardNames[i] === playerName) {
playerIndex = i;
break;
}
}
if (playerIndex >= 0) {
// Update existing player if new level is higher
if (level > leaderboardLevels[playerIndex]) {
leaderboardLevels[playerIndex] = level;
}
} else {
// Add new player
leaderboardNames.push(playerName);
leaderboardLevels.push(level);
}
// Create combined array for sorting
var combined = [];
for (var j = 0; j < leaderboardNames.length; j++) {
combined.push({
name: leaderboardNames[j],
level: leaderboardLevels[j]
});
}
// Sort by level (highest first)
combined.sort(function (a, b) {
return b.level - a.level;
});
// Keep only top 100
if (combined.length > 100) {
combined = combined.slice(0, 100);
}
// Split back into separate arrays
leaderboardNames = [];
leaderboardLevels = [];
for (var k = 0; k < combined.length; k++) {
leaderboardNames.push(combined[k].name);
leaderboardLevels.push(combined[k].level);
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardLevels = leaderboardLevels;
storage.playerName = playerName;
}
// Function to complete level
function completeLevel() {
currentLevel++;
// Update leaderboard with new level
updateLeaderboard(currentLevel);
// Save progress to storage
storage.currentLevel = currentLevel;
levelScore = 0;
towersToComplete = 5 * currentLevel; // Level 1: 5, Level 2: 10, Level 3: 15, etc.
// 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);
// Flash screen green for level completion
LK.effects.flashScreen(0x00ff00, 1000);
}
// Function to handle game over
function gameOver() {
// Update leaderboard with current level reached
updateLeaderboard(currentLevel);
// Save current level to storage so player can restart from this level
storage.currentLevel = currentLevel;
// Add screen shake effect for more dramatic crash
var originalX = game.x;
var shakeIntensity = 20;
var shakeDuration = 100;
for (var s = 0; s < 5; s++) {
tween(game, {
x: originalX + (Math.random() - 0.5) * shakeIntensity
}, {
duration: shakeDuration
});
}
// Return to original position after shake
LK.setTimeout(function () {
tween(game, {
x: originalX
}, {
duration: 200,
easing: tween.easeOut
});
}, 600);
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('crash').play();
LK.showGameOver();
}
// Main game update loop
game.update = function () {
// Check if admin mode has expired
if (adminMode && Date.now() > adminModeEndTime) {
adminMode = false;
adminModeEndTime = 0;
storage.adminModeEndTime = 0;
}
if (!gameStarted || showingMenu || showingLeaderboard || showingMainMenu || showingCodesMenu) return;
// Spawn clouds for background atmosphere
if (LK.ticks % 180 === 0) {
// Spawn cloud every 3 seconds at 60fps
spawnCloud();
}
// 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);
}
}
// Spawn towers based on level difficulty
var spawnRate = Math.max(120, 300 - currentLevel * 20); // Much slower spawning for level 1
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) {
// Animate tower destruction
tween(tower, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
tower.destroy();
}
});
towers.splice(i, 1);
continue;
}
// Check collision with aircraft
var currentIntersecting = aircraft.intersects(tower);
if (!tower.lastIntersecting && currentIntersecting) {
gameOver();
return;
}
tower.lastIntersecting = currentIntersecting;
// Check if aircraft passed tower (score point)
if (!tower.passed && tower.x < aircraft.x - 100) {
tower.passed = true;
levelScore++;
LK.setScore(LK.getScore() + 10 * currentLevel); // More points per level
LK.getSound('dodge').play();
// Update progress
var progress = Math.floor(levelScore / 2); // Two towers per obstacle
progressText.setText('Progress: ' + progress + '/' + towersToComplete);
scoreText.setText('Score: ' + LK.getScore());
// 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
});
}
});
}
}
// Aircraft stays stationary while towers move to create forward movement illusion
};