/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { language: "spanish" }); /**** * Classes ****/ var Door = Container.expand(function () { var self = Container.call(this); var doorGraphics = self.attachAsset('door', { anchorX: 0.5, anchorY: 0.5 }); self.locked = true; self.update = function () { if (self.locked && panterasDefeated >= 2 && mouse.pastafrolas >= 10) { self.locked = false; doorGraphics.tint = 0x90EE90; // Light green when unlocked } if (!self.locked && self.intersects(mouse)) { // Show congratulations screen showCongratulationsScreen(); } }; return self; }); // Game constants var Mouse = Container.expand(function () { var self = Container.call(this); var mouseGraphics = self.attachAsset('mouse', { anchorX: 0.5, anchorY: 0.5 }); self.isMoving = false; self.targetX = 0; self.targetY = 0; self.speed = 8; self.pastafrolas = 0; self.moveTo = function (x, y) { var adjustedY = y - MAZE_OFFSET_Y; var gridX = Math.floor(x / CELL_SIZE); var gridY = Math.floor(adjustedY / CELL_SIZE); if (isWalkable(gridX, gridY)) { self.targetX = x; self.targetY = y; self.isMoving = true; } }; self.update = function () { if (self.isMoving) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Calculate rotation angle based on movement direction var targetRotation = Math.atan2(dy, dx) + Math.PI / 2 + Math.PI; // Add PI/2 because mouse starts pointing down, plus PI to correct direction tween(mouseGraphics, { rotation: targetRotation }, { duration: 150, easing: tween.easeOut }); if (distance < self.speed) { self.x = self.targetX; self.y = self.targetY; self.isMoving = false; } else { var newX = self.x + dx / distance * self.speed; var newY = self.y + dy / distance * self.speed; var adjustedY = newY - MAZE_OFFSET_Y; var gridX = Math.floor(newX / CELL_SIZE); var gridY = Math.floor(adjustedY / CELL_SIZE); // Check collision during movement if (isWalkable(gridX, gridY)) { self.x = newX; self.y = newY; } else { // Stop movement if hitting wall self.isMoving = false; } } } }; return self; }); var Pantera = Container.expand(function () { var self = Container.call(this); var panteraGraphics = self.attachAsset('pantera', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.defeated = false; // Override the width and height for collision detection to match block size self.width = 102; // CELL_SIZE self.height = 102; // CELL_SIZE self.takeDamage = function (damage) { if (!self.defeated) { self.health -= damage; LK.getSound('hit').play(); LK.getSound('panterasgolpe').play(); if (self.health <= 0) { self.health = 0; self.defeated = true; self.visible = false; panterasDefeated++; // Spawn new pastafrola when pantera is defeated spawnPastafrola(); } // Visual feedback LK.effects.flashObject(self, 0xFF0000, 300); } }; self.down = function (x, y, obj) { if (!self.defeated && mouse.pastafrolas > 0) { // Calculate distance between mouse and pantera centers var dx = mouse.x - self.x; var dy = mouse.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var maxAttackDistance = CELL_SIZE * 3; // Must be within 3 cells // Convert positions to grid coordinates for more reliable line of sight check var mouseGridX = Math.floor(mouse.x / CELL_SIZE); var mouseGridY = Math.floor((mouse.y - MAZE_OFFSET_Y) / CELL_SIZE); var panteraGridX = Math.floor(self.x / CELL_SIZE); var panteraGridY = Math.floor((self.y - MAZE_OFFSET_Y) / CELL_SIZE); // Calculate grid distance (Manhattan distance for more lenient attack range) var gridDistance = Math.abs(mouseGridX - panteraGridX) + Math.abs(panteraGridY - mouseGridY); // Check if mouse is close enough (within 3 grid cells) and has line of sight if (gridDistance <= 3 && hasLineOfSight(mouse.x, mouse.y, self.x, self.y)) { mouse.pastafrolas--; self.takeDamage(20); LK.getSound('attack').play(); updateUI(); } else { // Show notification if attack failed due to distance or obstacles if (gridDistance > 3) { showNotification(currentLanguage === 'spanish' ? '¡Muy lejos para atacar!' : 'Too far to attack!'); } else { showNotification(currentLanguage === 'spanish' ? '¡Hay obstáculos en el camino!' : 'Obstacles are blocking the way!'); } } } }; return self; }); var Pastafrola = Container.expand(function () { var self = Container.call(this); var pastaGraphics = self.attachAsset('pastafrola', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.update = function () { // Initialize lastIntersecting state if not set if (self.lastIntersecting === undefined) { self.lastIntersecting = false; } // Check current intersection state var currentIntersecting = self.intersects(mouse); // Only collect if we just started intersecting (transition from false to true) if (!self.collected && !self.lastIntersecting && currentIntersecting) { self.collected = true; mouse.pastafrolas++; pastafrolarCollas++; LK.getSound('pastafrolasound').play(); self.visible = false; updateUI(); } // Update last intersecting state self.lastIntersecting = currentIntersecting; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x8B4513 }); /**** * Game Code ****/ // Game state management var gameStarted = false; var startButton; var selectedLevel = null; var showingLanguageMenu = false; var currentLanguage = storage.language || 'spanish'; // Timer variables var gameTimer = 120000; // 2 minutes in milliseconds var gameStartTime = 0; var timeRemainingText; var pausedTime = 0; // Track total paused time var pauseStartTime = 0; // Track when pause started var isPaused = false; // Track pause state // Translations object var translations = { spanish: { play: 'JUGAR', language: 'LENGUAJE', tutorial: 'TUTORIAL', selectLanguage: 'SELECCIONA IDIOMA', spanish: 'ESPAÑOL', english: 'INGLÉS', congratulations: 'FELICIDADES', youWon: '¡GANASTE!', pastafrolas: 'Pastafrolas', panteras: 'Panteras', instructionCollect: 'Haz clic para moverte. ¡Recoge pastafrolas y derrota panteras!', instructionDefeat: '¡Derrota todas las panteras primero!', instructionNeed10: '¡Necesitas 10 pastafrolas en tu inventario!', instructionComplete: '¡Todos los objetivos completados! ¡Ve a la puerta verde!', allDefeated: '¡Todas las panteras derrotadas! Necesitas tener 10 pastafrolas en tu inventario para abrir la puerta', defeatEnemy: 'Derrota al enemigo de esta zona para continuar', tutorialText: 'Para moverte presiona el lugar donde quieras ir, para ganar derrota a los enemigos lanzándoles pastafrolas, recoléctalas pasando sobre ellas, y lánzaselas presionando al enemigo que quieras atacar! Tienes un contador que te indica cuantas pastafrolas tienes recolectadas.', defeat: '¡PERDISTE!', betterNextTime: 'mejor la próxima vez', timeRemaining: 'Tiempo restante', opciones: 'OPCIONES', lenguaje: 'LENGUAJE', niveles: 'NIVELES', volver: 'VOLVER', cerrar: 'CERRAR', firstSelectLevel: 'primero selecciona el nivel que quieras jugar', levelBlocked: 'ups, este nivel está bloqueado!', tutorialLevel1: 'Para moverte presiona el lugar donde quieras ir, para ganar derrota a los enemigos lanzándoles pastafrolas, recoléctalas pasando sobre ellas, y lánzaselas presionando al enemigo que quieras atacar! Tienes un contador que te indica cuantas pastafrolas tienes recolectadas. ¡y un límite de tiempo de 2 minutos para completar el nivel!' }, english: { play: 'PLAY', language: 'LANGUAGE', tutorial: 'TUTORIAL', selectLanguage: 'SELECT LANGUAGE', spanish: 'SPANISH', english: 'ENGLISH', congratulations: 'CONGRATULATIONS', youWon: 'YOU WON!', pastafrolas: 'Pastafrolas', panteras: 'Panthers', instructionCollect: 'Click to move. Collect pastafrolas and defeat panthers!', instructionDefeat: 'Defeat all panthers first!', instructionNeed10: 'You need 10 pastafrolas in your inventory!', instructionComplete: 'All objectives complete! Head to the green door!', allDefeated: 'All panthers defeated! You need to have 10 pastafrolas in your inventory to open the door', defeatEnemy: 'Defeat the enemy in this area to continue', tutorialText: 'To move press the place where you want to go, to win defeat the enemies by throwing pastafrolas at them, collect them by passing over them, and throw them by pressing the enemy you want to attack! You have a counter that indicates how many pastafrolas you have collected.', defeat: 'YOU LOST!', betterNextTime: 'better luck next time', timeRemaining: 'Time remaining', opciones: 'OPTIONS', lenguaje: 'LANGUAGE', niveles: 'LEVELS', volver: 'BACK', cerrar: 'CLOSE', firstSelectLevel: 'first select the level you want to play', levelBlocked: 'oops, this level is blocked!', tutorialLevel1: 'To move press the place where you want to go, to win defeat the enemies by throwing pastafrolas at them, collect them by passing over them, and throw them by pressing the enemy you want to attack! You have a counter that indicates how many pastafrolas you have collected. and a time limit of 2 minutes to complete the level!' } }; function getText(key) { return translations[currentLanguage][key] || key; } // Game constants var CELL_SIZE = 102; var MAZE_WIDTH = 20; var MAZE_HEIGHT = 22; var MAZE_OFFSET_Y = 300; // Vertical offset to move maze down // Game variables var mouse; var door; var pastafrolas = []; var panteras = []; var pastafrolarCollas = 0; var panterasDefeated = 0; var lastPanterasDefeated = 0; // Track last pantera count to detect changes // UI elements var pastafrolarText; var panteraText; var instructionText; var notificationText; // Simple maze layout (1 = wall, 0 = walkable) var mazeData = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]; function showCongratulationsScreen() { // Play victory sound LK.getSound('victoria').play(); // Stop the game timer by setting gameStarted to false gameStarted = false; // Remove fondonegro background if (backgroundAsset && backgroundAsset.parent) { game.removeChild(backgroundAsset); backgroundAsset = null; } // Hide UI counters immediately if (pastafrolarText && pastafrolarText.parent) { pastafrolarText.visible = false; } if (panteraText && panteraText.parent) { panteraText.visible = false; } if (instructionText && instructionText.parent) { instructionText.visible = false; } if (notificationText && notificationText.parent) { notificationText.visible = false; } if (timeRemainingText && timeRemainingText.parent) { timeRemainingText.visible = false; } // Create congratulations background var congratsBackground = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 25, scaleY: 35, tint: 0x000000, alpha: 0.8 }); game.addChild(congratsBackground); // Create congratulations title var congratsTitle = new Text2(getText('congratulations'), { size: 120, fill: 0xFFD700 }); congratsTitle.anchor.set(0.5, 0.5); congratsTitle.x = 1024; congratsTitle.y = 1200; game.addChild(congratsTitle); // Create you won text var youWonText = new Text2(getText('youWon'), { size: 100, fill: 0x00FF00 }); youWonText.anchor.set(0.5, 0.5); youWonText.x = 1024; youWonText.y = 1400; game.addChild(youWonText); // Automatically return to menu after 3 seconds LK.setTimeout(function () { // Remove congratulations screen elements if (congratsBackground.parent) game.removeChild(congratsBackground); if (congratsTitle.parent) game.removeChild(congratsTitle); if (youWonText.parent) game.removeChild(youWonText); if (timeRemainingText && timeRemainingText.parent) LK.gui.top.removeChild(timeRemainingText); // Reset game state and return to main menu resetGameState(); showStartScreen(); }, 3000); } function showDefeatScreen() { // Play defeat sound LK.getSound('derrota').play(); // Remove fondonegro background if (backgroundAsset && backgroundAsset.parent) { game.removeChild(backgroundAsset); backgroundAsset = null; } // Hide UI counters immediately if (pastafrolarText && pastafrolarText.parent) { pastafrolarText.visible = false; } if (panteraText && panteraText.parent) { panteraText.visible = false; } if (instructionText && instructionText.parent) { instructionText.visible = false; } if (notificationText && notificationText.parent) { notificationText.visible = false; } if (timeRemainingText && timeRemainingText.parent) { timeRemainingText.visible = false; } // Create defeat background var defeatBackground = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 25, scaleY: 35, tint: 0x000000, alpha: 0.8 }); game.addChild(defeatBackground); // Create defeat title var defeatTitle = new Text2(getText('defeat'), { size: 120, fill: 0xFF4444 }); defeatTitle.anchor.set(0.5, 0.5); defeatTitle.x = 1024; defeatTitle.y = 1200; game.addChild(defeatTitle); // Create better next time text var betterNextTimeText = new Text2(getText('betterNextTime'), { size: 80, fill: 0xFFFFFF }); betterNextTimeText.anchor.set(0.5, 0.5); betterNextTimeText.x = 1024; betterNextTimeText.y = 1400; game.addChild(betterNextTimeText); // Automatically return to menu after 3 seconds LK.setTimeout(function () { // Remove defeat screen elements if (defeatBackground.parent) game.removeChild(defeatBackground); if (defeatTitle.parent) game.removeChild(defeatTitle); if (betterNextTimeText.parent) game.removeChild(betterNextTimeText); // Reset game state and return to main menu resetGameState(); showStartScreen(); }, 3000); } function showStartScreen() { // Set background to FONDOMENU with 20% brightness (tint to make it darker) game.setBackgroundColor(0x000000); // Set to black first var menuBackground = LK.getAsset('FONDOMENU', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 20.48, // Scale to fill width (2048/100) scaleY: 19.54, // Scale to fill height (2732/139.89) alpha: 0.2 // 20% brightness }); game.addChild(menuBackground); // Create start screen title using titulo asset var titleText = LK.getAsset('titulo', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 800, scaleX: 1.3, scaleY: 1.3 }); game.addChild(titleText); // Add pulsing animation to title function animateTitle() { tween(titleText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { scaleX: 1.3, scaleY: 1.3 }, { duration: 1000, easing: tween.easeInOut, onFinish: animateTitle }); } }); } animateTitle(); // Create JUGAR button startButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, scaleX: 4.5, scaleY: 1.5, tint: 0x4CAF50 }); game.addChild(startButton); // Create button text var buttonText = new Text2(getText('play'), { size: 80, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 1024; buttonText.y = 1200; game.addChild(buttonText); // Create OPCIONES button var opcionesButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, scaleX: 5, scaleY: 1.5, tint: 0x2196F3 }); game.addChild(opcionesButton); // Create opciones button text var opcionesButtonText = new Text2(getText('opciones'), { size: 80, fill: 0xFFFFFF }); opcionesButtonText.anchor.set(0.5, 0.5); opcionesButtonText.x = 1024; opcionesButtonText.y = 1400; game.addChild(opcionesButtonText); // Add click handler to start button startButton.down = function (x, y, obj) { if (!selectedLevel) { showNotificationMessage(getText('firstSelectLevel')); return; } gameStarted = true; // Set background to black (0% brightness) when game starts game.setBackgroundColor(0x000000); // gameStarted flag will stop menumusical sound from looping // Remove start screen elements game.removeChild(titleText); game.removeChild(startButton); game.removeChild(buttonText); game.removeChild(opcionesButton); game.removeChild(opcionesButtonText); // Initialize the actual game initializeGame(); }; // Add click handler to opciones button opcionesButton.down = function (x, y, obj) { // Remove start screen elements if (game.children[0] && game.children[0].texture && game.children[0].texture.textureCacheIds && game.children[0].texture.textureCacheIds.indexOf('FONDOMENU') !== -1) { game.removeChild(game.children[0]); // Remove menuBackground } game.removeChild(titleText); game.removeChild(startButton); game.removeChild(buttonText); game.removeChild(opcionesButton); game.removeChild(opcionesButtonText); // Show options screen showOptionsScreen(); }; } function showLanguageScreen() { showingLanguageMenu = true; // Create title var languageTitle = new Text2(getText('selectLanguage'), { size: 100, fill: 0xFFFFFF }); languageTitle.anchor.set(0.5, 0.5); languageTitle.x = 1024; languageTitle.y = 800; game.addChild(languageTitle); // Create Spanish button var spanishButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1100, scaleX: 3, scaleY: 1.5, tint: currentLanguage === 'spanish' ? 0x4CAF50 : 0x757575 }); game.addChild(spanishButton); var spanishButtonText = new Text2(getText('spanish'), { size: 70, fill: 0xFFFFFF }); spanishButtonText.anchor.set(0.5, 0.5); spanishButtonText.x = 1024; spanishButtonText.y = 1100; game.addChild(spanishButtonText); // Create English button var englishButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1300, scaleX: 3, scaleY: 1.5, tint: currentLanguage === 'english' ? 0x4CAF50 : 0x757575 }); game.addChild(englishButton); var englishButtonText = new Text2(getText('english'), { size: 70, fill: 0xFFFFFF }); englishButtonText.anchor.set(0.5, 0.5); englishButtonText.x = 1024; englishButtonText.y = 1300; game.addChild(englishButtonText); // Spanish button click handler spanishButton.down = function (x, y, obj) { currentLanguage = 'spanish'; storage.language = 'spanish'; // Remove language screen elements game.removeChild(languageTitle); game.removeChild(spanishButton); game.removeChild(spanishButtonText); game.removeChild(englishButton); game.removeChild(englishButtonText); showingLanguageMenu = false; // Return to options screen showOptionsScreen(); }; // English button click handler englishButton.down = function (x, y, obj) { currentLanguage = 'english'; storage.language = 'english'; // Remove language screen elements game.removeChild(languageTitle); game.removeChild(spanishButton); game.removeChild(spanishButtonText); game.removeChild(englishButton); game.removeChild(englishButtonText); showingLanguageMenu = false; // Return to options screen showOptionsScreen(); }; } function showTutorialScreen() { // Create tutorial background var tutorialBackground = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 24, scaleY: 32, tint: 0x1A1A1A, alpha: 0.9 }); game.addChild(tutorialBackground); // Create tutorial title var tutorialTitle = new Text2(getText('tutorial'), { size: 100, fill: 0xFFD700 }); tutorialTitle.anchor.set(0.5, 0.5); tutorialTitle.x = 1024; tutorialTitle.y = 400; game.addChild(tutorialTitle); // Create tutorial text - break into multiple lines for better readability var tutorialText = new Text2(getText('tutorialText'), { size: 50, fill: 0xFFFFFF, wordWrap: true, wordWrapWidth: 1800 }); tutorialText.anchor.set(0.5, 0.5); tutorialText.x = 1024; tutorialText.y = 1000; game.addChild(tutorialText); // Create back button var backButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1700, scaleX: 2.5, scaleY: 1.2, tint: 0x4CAF50 }); game.addChild(backButton); // Create back button text var backButtonText = new Text2(getText('volver'), { size: 60, fill: 0xFFFFFF }); backButtonText.anchor.set(0.5, 0.5); backButtonText.x = 1024; backButtonText.y = 1700; game.addChild(backButtonText); // Add click handler to back button backButton.down = function (x, y, obj) { // Remove tutorial screen elements game.removeChild(tutorialBackground); game.removeChild(tutorialTitle); game.removeChild(tutorialText); game.removeChild(backButton); game.removeChild(backButtonText); // Return to start screen showStartScreen(); }; } function showOptionsScreen() { // Create options title var optionsTitle = new Text2(getText('opciones'), { size: 100, fill: 0xFFFFFF }); optionsTitle.anchor.set(0.5, 0.5); optionsTitle.x = 1024; optionsTitle.y = 600; game.addChild(optionsTitle); // Create language button var languageButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1000, scaleX: 4, scaleY: 1.5, tint: 0x2196F3 }); game.addChild(languageButton); var languageButtonText = new Text2(getText('lenguaje'), { size: 70, fill: 0xFFFFFF }); languageButtonText.anchor.set(0.5, 0.5); languageButtonText.x = 1024; languageButtonText.y = 1000; game.addChild(languageButtonText); // Create niveles button var nivelesButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, scaleX: 4, scaleY: 1.5, tint: 0xFF9800 }); game.addChild(nivelesButton); var nivelesButtonText = new Text2(getText('niveles'), { size: 70, fill: 0xFFFFFF }); nivelesButtonText.anchor.set(0.5, 0.5); nivelesButtonText.x = 1024; nivelesButtonText.y = 1200; game.addChild(nivelesButtonText); // Create back button var backButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1500, scaleX: 2.5, scaleY: 1.2, tint: 0x4CAF50 }); game.addChild(backButton); var backButtonText = new Text2(getText('volver'), { size: 60, fill: 0xFFFFFF }); backButtonText.anchor.set(0.5, 0.5); backButtonText.x = 1024; backButtonText.y = 1500; game.addChild(backButtonText); // Language button click handler languageButton.down = function (x, y, obj) { // Remove options screen elements game.removeChild(optionsTitle); game.removeChild(languageButton); game.removeChild(languageButtonText); game.removeChild(nivelesButton); game.removeChild(nivelesButtonText); game.removeChild(backButton); game.removeChild(backButtonText); // Show language selection screen showLanguageScreen(); }; // Niveles button click handler nivelesButton.down = function (x, y, obj) { // Remove options screen elements game.removeChild(optionsTitle); game.removeChild(languageButton); game.removeChild(languageButtonText); game.removeChild(nivelesButton); game.removeChild(nivelesButtonText); game.removeChild(backButton); game.removeChild(backButtonText); // Show levels screen showLevelsScreen(); }; // Back button click handler backButton.down = function (x, y, obj) { // Remove options screen elements game.removeChild(optionsTitle); game.removeChild(languageButton); game.removeChild(languageButtonText); game.removeChild(nivelesButton); game.removeChild(nivelesButtonText); game.removeChild(backButton); game.removeChild(backButtonText); // Return to start screen showStartScreen(); }; } function showLevelsScreen() { // Create levels title var levelsTitle = new Text2(getText('niveles'), { size: 100, fill: 0xFFFFFF }); levelsTitle.anchor.set(0.5, 0.5); levelsTitle.x = 1024; levelsTitle.y = 600; game.addChild(levelsTitle); // Create level1 button var level1Button = LK.getAsset('level1', { anchorX: 0.5, anchorY: 0.5, x: 512, y: 900, scaleX: 3, scaleY: 3 }); game.addChild(level1Button); // Create level2 button var level2Button = LK.getAsset('level2', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 900, scaleX: 3, scaleY: 3 }); game.addChild(level2Button); // Create candado (lock) for level2 var candadoButton = LK.getAsset('candado', { anchorX: 0.5, anchorY: 0.5, x: 1200, y: 900, scaleX: 1, scaleY: 1 }); game.addChild(candadoButton); // Create tutorial button for level1 var tutorialLevel1Button = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 512, y: 1100, scaleX: 2, scaleY: 1, tint: 0x4CAF50 }); game.addChild(tutorialLevel1Button); var tutorialLevel1Text = new Text2(getText('tutorial'), { size: 40, fill: 0xFFFFFF }); tutorialLevel1Text.anchor.set(0.5, 0.5); tutorialLevel1Text.x = 512; tutorialLevel1Text.y = 1100; game.addChild(tutorialLevel1Text); // Create tutorial button for level2 var tutorialLevel2Button = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1100, scaleX: 2, scaleY: 1, tint: 0x757575 }); game.addChild(tutorialLevel2Button); var tutorialLevel2Text = new Text2(getText('tutorial'), { size: 40, fill: 0xFFFFFF }); tutorialLevel2Text.anchor.set(0.5, 0.5); tutorialLevel2Text.x = 1024; tutorialLevel2Text.y = 1100; game.addChild(tutorialLevel2Text); // Create back button var backButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, scaleX: 2.5, scaleY: 1.2, tint: 0x4CAF50 }); game.addChild(backButton); var backButtonText = new Text2(getText('volver'), { size: 60, fill: 0xFFFFFF }); backButtonText.anchor.set(0.5, 0.5); backButtonText.x = 1024; backButtonText.y = 1400; game.addChild(backButtonText); // Level1 button click handler level1Button.down = function (x, y, obj) { selectedLevel = 1; // Remove levels screen elements game.removeChild(levelsTitle); game.removeChild(level1Button); game.removeChild(level2Button); game.removeChild(candadoButton); game.removeChild(tutorialLevel1Button); game.removeChild(tutorialLevel1Text); game.removeChild(tutorialLevel2Button); game.removeChild(tutorialLevel2Text); game.removeChild(backButton); game.removeChild(backButtonText); // Return to main menu showStartScreen(); }; // Tutorial Level1 button click handler tutorialLevel1Button.down = function (x, y, obj) { showTutorialMessage(getText('tutorialLevel1')); }; // Tutorial Level2 button click handler tutorialLevel2Button.down = function (x, y, obj) { showTutorialMessage(getText('levelBlocked')); }; // Back button click handler backButton.down = function (x, y, obj) { // Remove levels screen elements game.removeChild(levelsTitle); game.removeChild(level1Button); game.removeChild(level2Button); game.removeChild(candadoButton); game.removeChild(tutorialLevel1Button); game.removeChild(tutorialLevel1Text); game.removeChild(tutorialLevel2Button); game.removeChild(tutorialLevel2Text); game.removeChild(backButton); game.removeChild(backButtonText); // Return to options screen showOptionsScreen(); }; } function showTutorialMessage(message) { // Create tutorial background var tutorialBackground = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 24, scaleY: 32, tint: 0x1A1A1A, alpha: 0.9 }); game.addChild(tutorialBackground); // Create tutorial text var tutorialText = new Text2(message, { size: 50, fill: 0xFFFFFF, wordWrap: true, wordWrapWidth: 1800 }); tutorialText.anchor.set(0.5, 0.5); tutorialText.x = 1024; tutorialText.y = 1200; game.addChild(tutorialText); // Create close button var closeButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1600, scaleX: 2.5, scaleY: 1.2, tint: 0x4CAF50 }); game.addChild(closeButton); var closeButtonText = new Text2(getText('cerrar'), { size: 60, fill: 0xFFFFFF }); closeButtonText.anchor.set(0.5, 0.5); closeButtonText.x = 1024; closeButtonText.y = 1600; game.addChild(closeButtonText); // Close button click handler closeButton.down = function (x, y, obj) { // Remove tutorial message elements game.removeChild(tutorialBackground); game.removeChild(tutorialText); game.removeChild(closeButton); game.removeChild(closeButtonText); }; } function showNotificationMessage(message) { // Create notification background var notificationBackground = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 20, scaleY: 8, tint: 0x1A1A1A, alpha: 0.9 }); game.addChild(notificationBackground); // Create notification text var notificationText = new Text2(message, { size: 60, fill: 0xFFFFFF, wordWrap: true, wordWrapWidth: 1600 }); notificationText.anchor.set(0.5, 0.5); notificationText.x = 1024; notificationText.y = 1300; game.addChild(notificationText); // Create close button var closeButton = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1500, scaleX: 2, scaleY: 1, tint: 0x4CAF50 }); game.addChild(closeButton); var closeButtonText = new Text2('OK', { size: 50, fill: 0xFFFFFF }); closeButtonText.anchor.set(0.5, 0.5); closeButtonText.x = 1024; closeButtonText.y = 1500; game.addChild(closeButtonText); // Close button click handler closeButton.down = function (x, y, obj) { // Remove notification message elements game.removeChild(notificationBackground); game.removeChild(notificationText); game.removeChild(closeButton); game.removeChild(closeButtonText); }; } var backgroundAsset; // Global variable to track background function initializeGame() { // Remove FONDOMENU background asset if it exists if (game.children.length > 0) { var menuBackground = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i].texture && game.children[i].texture.textureCacheIds && game.children[i].texture.textureCacheIds.indexOf('FONDOMENU') !== -1) { menuBackground = game.children[i]; break; } } if (menuBackground) { game.removeChild(menuBackground); } } // Set background to black game.setBackgroundColor(0x000000); // Add fondonegro background behind maze and letters backgroundAsset = LK.getAsset('fondonegro', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 20.48, // Scale to fill width (2048/100) scaleY: 27.32 // Scale to fill height (2732/100) }); game.addChild(backgroundAsset); // Build the maze for (var y = 0; y < MAZE_HEIGHT; y++) { for (var x = 0; x < MAZE_WIDTH; x++) { if (y < mazeData.length && mazeData[y][x] === 1) { var wall = LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5, x: x * CELL_SIZE + CELL_SIZE / 2, y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y }); game.addChild(wall); } else if (y < mazeData.length) { var floor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: x * CELL_SIZE + CELL_SIZE / 2, y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y }); game.addChild(floor); } } } // Create mouse mouse = new Mouse(); mouse.x = 1.5 * CELL_SIZE; mouse.y = 1.5 * CELL_SIZE + MAZE_OFFSET_Y; game.addChild(mouse); // Create door at the bottom right door = new Door(); door.x = 18 * CELL_SIZE + CELL_SIZE / 2; door.y = (MAZE_HEIGHT - 2) * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y; game.addChild(door); // Spawn initial pastafrolas for (var i = 0; i < 20; i++) { spawnPastafrola(); } // Spawn 2 panteras in strategic positions var panteraPositions = [{ x: 5, y: 5 }, { x: 15, y: 8 }]; for (var i = 0; i < panteraPositions.length; i++) { var pos = panteraPositions[i]; if (isWalkable(pos.x, pos.y)) { var pantera = new Pantera(); pantera.x = pos.x * CELL_SIZE + CELL_SIZE / 2; pantera.y = pos.y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y; panteras.push(pantera); game.addChild(pantera); } } // Setup UI - all elements in top area to avoid click interference pastafrolarText = new Text2(getText('pastafrolas') + ': 0', { size: 60, fill: 0xFFFFFF }); pastafrolarText.anchor.set(0.5, 0); pastafrolarText.y = 0; // At very top LK.gui.top.addChild(pastafrolarText); // Add panteras defeated text below pastafrolas text panteraText = new Text2(getText('panteras') + ': 0/2', { size: 50, fill: 0xFFFFFF }); panteraText.anchor.set(0.5, 0); panteraText.y = 70; // Below pastafrola text LK.gui.top.addChild(panteraText); instructionText = new Text2(getText('instructionCollect'), { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); instructionText.y = 130; // Below pantera text LK.gui.top.addChild(instructionText); notificationText = new Text2('', { size: 45, fill: 0xFF4444 }); notificationText.anchor.set(0.5, 1); notificationText.visible = false; LK.gui.bottom.addChild(notificationText); // Initialize game timer gameStartTime = Date.now(); // Create time remaining display timeRemainingText = new Text2(getText('timeRemaining') + ': 2:00', { size: 50, fill: 0xFFFFFF }); timeRemainingText.anchor.set(0.5, 0); timeRemainingText.y = 180; // Below instruction text LK.gui.top.addChild(timeRemainingText); // Update UI updateUI(); } // Show start screen initially showStartScreen(); function isWalkable(gridX, gridY) { if (gridX < 0 || gridX >= MAZE_WIDTH || gridY < 0 || gridY >= MAZE_HEIGHT) { return false; } return mazeData[gridY][gridX] === 0; } function hasLineOfSight(x1, y1, x2, y2) { // Convert world coordinates to grid coordinates more accurately var gridX1 = Math.floor(x1 / CELL_SIZE); var gridY1 = Math.floor((y1 - MAZE_OFFSET_Y) / CELL_SIZE); var gridX2 = Math.floor(x2 / CELL_SIZE); var gridY2 = Math.floor((y2 - MAZE_OFFSET_Y) / CELL_SIZE); // Ensure coordinates are within bounds if (gridX1 < 0 || gridX1 >= MAZE_WIDTH || gridY1 < 0 || gridY1 >= MAZE_HEIGHT || gridX2 < 0 || gridX2 >= MAZE_WIDTH || gridY2 < 0 || gridY2 >= MAZE_HEIGHT) { return false; } // Use Bresenham's line algorithm to check each grid cell between the two points var dx = Math.abs(gridX2 - gridX1); var dy = Math.abs(gridY2 - gridY1); var x = gridX1; var y = gridY1; var xInc = gridX1 < gridX2 ? 1 : -1; var yInc = gridY1 < gridY2 ? 1 : -1; var error = dx - dy; // Don't check the starting position (mouse position) as it's always walkable var stepCount = 0; while (true) { // If we reached the target, we have clear line of sight if (x === gridX2 && y === gridY2) { break; } var error2 = 2 * error; if (error2 > -dy) { error -= dy; x += xInc; } if (error2 < dx) { error += dx; y += yInc; } stepCount++; // Check if current position is a wall (not walkable), but skip first and last positions if (stepCount > 0 && (x !== gridX2 || y !== gridY2) && !isWalkable(x, y)) { return false; // Wall blocks line of sight } // Prevent infinite loops if (stepCount > 50) { return false; } } return true; // Clear line of sight } var barriers = []; // Global array to track barriers function canAccessArea(gridX, gridY) { // Define restricted areas that unlock as panteras are defeated var restrictedAreas = [{ minX: 0, maxX: 6, minY: 0, maxY: 8, requiredDefeats: 0 }, // Starting area { minX: 7, maxX: 13, minY: 0, maxY: 8, requiredDefeats: 1 }, // Second area { minX: 14, maxX: 19, minY: 0, maxY: 8, requiredDefeats: 2 }, // Third area { minX: 0, maxX: 6, minY: 9, maxY: 17, requiredDefeats: 2 }, // Fourth area { minX: 7, maxX: 13, minY: 9, maxY: 17, requiredDefeats: 3 }, // Fifth area { minX: 14, maxX: 19, minY: 9, maxY: 17, requiredDefeats: 4 }, // Sixth area { minX: 0, maxX: 19, minY: 18, maxY: 26, requiredDefeats: 5 } // Final area ]; for (var i = 0; i < restrictedAreas.length; i++) { var area = restrictedAreas[i]; if (gridX >= area.minX && gridX <= area.maxX && gridY >= area.minY && gridY <= area.maxY) { if (panterasDefeated < area.requiredDefeats) { showNotification(getText('defeatEnemy')); return false; } return true; } } return true; // Default allow access } function createBarriers() { // Create barriers at area boundaries var barrierPositions = [ // Vertical barrier between areas 1 and 2 { x: 6, y: 1 }, { x: 6, y: 2 }, { x: 6, y: 3 }, { x: 6, y: 4 }, { x: 6, y: 5 }, { x: 6, y: 6 }, { x: 6, y: 7 }, // Vertical barrier between areas 2 and 3 { x: 13, y: 1 }, { x: 13, y: 2 }, { x: 13, y: 3 }, { x: 13, y: 4 }, { x: 13, y: 5 }, { x: 13, y: 6 }, { x: 13, y: 7 }, // Horizontal barrier between upper and middle sections { x: 1, y: 8 }, { x: 2, y: 8 }, { x: 3, y: 8 }, { x: 4, y: 8 }, { x: 5, y: 8 }, { x: 7, y: 8 }, { x: 8, y: 8 }, { x: 9, y: 8 }, { x: 10, y: 8 }, { x: 11, y: 8 }, { x: 12, y: 8 }, { x: 14, y: 8 }, { x: 15, y: 8 }, { x: 16, y: 8 }, { x: 17, y: 8 }, { x: 18, y: 8 }, // Vertical barriers in middle section { x: 6, y: 10 }, { x: 6, y: 11 }, { x: 6, y: 13 }, { x: 6, y: 14 }, { x: 6, y: 15 }, { x: 6, y: 16 }, { x: 13, y: 10 }, { x: 13, y: 11 }, { x: 13, y: 13 }, { x: 13, y: 14 }, { x: 13, y: 15 }, { x: 13, y: 16 }, // Horizontal barrier between middle and bottom sections { x: 1, y: 17 }, { x: 2, y: 17 }, { x: 3, y: 17 }, { x: 4, y: 17 }, { x: 5, y: 17 }, { x: 6, y: 17 }, { x: 7, y: 17 }, { x: 8, y: 17 }, { x: 9, y: 17 }, { x: 10, y: 17 }, { x: 11, y: 17 }, { x: 12, y: 17 }, { x: 13, y: 17 }, { x: 14, y: 17 }, { x: 15, y: 17 }, { x: 16, y: 17 }, { x: 17, y: 17 }, { x: 18, y: 17 }]; for (var i = 0; i < barrierPositions.length; i++) { var pos = barrierPositions[i]; if (isWalkable(pos.x, pos.y)) { var barrier = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, x: pos.x * CELL_SIZE + CELL_SIZE / 2, y: pos.y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y, alpha: 0.7 }); barriers.push(barrier); game.addChild(barrier); } } } function updateBarrierVisibility() { // Hide barriers in unlocked areas for (var i = 0; i < barriers.length; i++) { var barrier = barriers[i]; var gridX = Math.floor((barrier.x - CELL_SIZE / 2) / CELL_SIZE); var gridY = Math.floor((barrier.y - CELL_SIZE / 2 - MAZE_OFFSET_Y) / CELL_SIZE); // Check if this barrier should be visible based on area access var shouldShow = !canAccessAreaSilent(gridX, gridY); barrier.visible = shouldShow; } } function canAccessAreaSilent(gridX, gridY) { // Same as canAccessArea but without showing notification var restrictedAreas = [{ minX: 0, maxX: 6, minY: 0, maxY: 8, requiredDefeats: 0 }, { minX: 7, maxX: 13, minY: 0, maxY: 8, requiredDefeats: 1 }, { minX: 14, maxX: 19, minY: 0, maxY: 8, requiredDefeats: 2 }, { minX: 0, maxX: 6, minY: 9, maxY: 17, requiredDefeats: 2 }, { minX: 7, maxX: 13, minY: 9, maxY: 17, requiredDefeats: 3 }, { minX: 14, maxX: 19, minY: 9, maxY: 17, requiredDefeats: 4 }, { minX: 0, maxX: 19, minY: 18, maxY: 26, requiredDefeats: 5 }]; for (var i = 0; i < restrictedAreas.length; i++) { var area = restrictedAreas[i]; if (gridX >= area.minX && gridX <= area.maxX && gridY >= area.minY && gridY <= area.maxY) { return panterasDefeated >= area.requiredDefeats; } } return true; } function getRandomWalkablePosition() { var attempts = 0; while (attempts < 100) { var x = Math.floor(Math.random() * MAZE_WIDTH); var y = Math.floor(Math.random() * MAZE_HEIGHT); if (isWalkable(x, y)) { return { x: x * CELL_SIZE + CELL_SIZE / 2, y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y }; } attempts++; } return { x: 1.5 * CELL_SIZE, y: 1.5 * CELL_SIZE + MAZE_OFFSET_Y }; // Fallback position } function getRandomWalkablePositionIncludingRestricted() { var attempts = 0; while (attempts < 100) { var x = Math.floor(Math.random() * MAZE_WIDTH); var y = Math.floor(Math.random() * MAZE_HEIGHT); // Allow spawning in any walkable area, including restricted ones if (isWalkable(x, y)) { return { x: x * CELL_SIZE + CELL_SIZE / 2, y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y }; } attempts++; } return { x: 1.5 * CELL_SIZE, y: 1.5 * CELL_SIZE + MAZE_OFFSET_Y }; // Fallback position } function spawnPastafrola() { var position = getRandomWalkablePositionIncludingRestricted(); var pastafrola = new Pastafrola(); pastafrola.x = position.x; pastafrola.y = position.y; pastafrolas.push(pastafrola); game.addChild(pastafrola); } function resetGameState() { // Reset game state gameStarted = false; pastafrolarCollas = 0; panterasDefeated = 0; lastPanterasDefeated = 0; gameTimer = 120000; gameStartTime = 0; pausedTime = 0; pauseStartTime = 0; isPaused = false; // Remove fondonegro background if it exists if (backgroundAsset && backgroundAsset.parent) { game.removeChild(backgroundAsset); backgroundAsset = null; } // Clear all game objects if (mouse) { game.removeChild(mouse); mouse = null; } if (door) { game.removeChild(door); door = null; } // Clear arrays and remove objects for (var i = 0; i < pastafrolas.length; i++) { if (pastafrolas[i].parent) { game.removeChild(pastafrolas[i]); } } pastafrolas = []; for (var i = 0; i < panteras.length; i++) { if (panteras[i].parent) { game.removeChild(panteras[i]); } } panteras = []; for (var i = 0; i < barriers.length; i++) { if (barriers[i].parent) { game.removeChild(barriers[i]); } } barriers = []; // Clear UI elements if (pastafrolarText && pastafrolarText.parent) { LK.gui.top.removeChild(pastafrolarText); pastafrolarText = null; } if (panteraText && panteraText.parent) { LK.gui.top.removeChild(panteraText); panteraText = null; } if (instructionText && instructionText.parent) { LK.gui.top.removeChild(instructionText); instructionText = null; } if (notificationText && notificationText.parent) { LK.gui.bottom.removeChild(notificationText); notificationText = null; } if (timeRemainingText && timeRemainingText.parent) { LK.gui.top.removeChild(timeRemainingText); timeRemainingText = null; } // Clear all remaining children from game - create a copy of the array to avoid modification during iteration var childrenToRemove = []; for (var i = 0; i < game.children.length; i++) { childrenToRemove.push(game.children[i]); } for (var i = 0; i < childrenToRemove.length; i++) { if (childrenToRemove[i].parent === game) { game.removeChild(childrenToRemove[i]); } } } function showNotification(message) { if (notificationText) { notificationText.setText(message); notificationText.visible = true; LK.setTimeout(function () { if (notificationText) { notificationText.visible = false; } }, 2000); } } function updateUI() { pastafrolarText.setText(getText('pastafrolas') + ': ' + mouse.pastafrolas); panteraText.setText(getText('panteras') + ': ' + panterasDefeated + '/2'); if (panterasDefeated < 2) { instructionText.setText(getText('instructionDefeat') + ' (' + panterasDefeated + '/2)'); } else if (mouse.pastafrolas < 10) { instructionText.setText(getText('instructionNeed10') + ' (' + mouse.pastafrolas + '/10)'); } else { instructionText.setText(getText('instructionComplete')); } } // Game initialization now handled by start screen // Game controls game.down = function (x, y, obj) { if (gameStarted && mouse) { mouse.moveTo(x, y); } }; // Handle pause events LK.on('pause', function () { if (gameStarted && !isPaused) { isPaused = true; pauseStartTime = Date.now(); } }); LK.on('resume', function () { if (gameStarted && isPaused) { isPaused = false; pausedTime += Date.now() - pauseStartTime; } }); // Main game loop game.update = function () { if (!gameStarted) return; // Update timer var currentTime = Date.now(); var elapsedTime = currentTime - gameStartTime - pausedTime; var timeLeft = Math.max(0, gameTimer - elapsedTime); // Update timer display if (timeRemainingText) { var secondsLeft = Math.ceil(timeLeft / 1000); var minutes = Math.floor(secondsLeft / 60); var seconds = secondsLeft % 60; var timeStr = minutes + ':' + (seconds < 10 ? '0' : '') + seconds; timeRemainingText.setText(getText('timeRemaining') + ': ' + timeStr); // Change color when time is running out if (timeLeft <= 30000) { // Last 30 seconds timeRemainingText.tint = 0xFF4444; } else if (timeLeft <= 60000) { // Last minute timeRemainingText.tint = 0xFFAA00; } else { timeRemainingText.tint = 0xFFFFFF; } } // Check if time is up if (timeLeft <= 0) { showDefeatScreen(); return; } // Check if we just defeated all panteras (transition from not all defeated to all defeated) if (lastPanterasDefeated < 2 && panterasDefeated >= 2) { showNotification(getText('allDefeated')); } lastPanterasDefeated = panterasDefeated; // Update mouse if (mouse) { mouse.update(); } // Update pastafrolas for (var i = 0; i < pastafrolas.length; i++) { pastafrolas[i].update(); } // Update panteras for (var i = 0; i < panteras.length; i++) { if (!panteras[i].defeated) { // Simple AI: panteras don't move but can be clicked for combat } } // Update door if (door) { door.update(); } // Barrier visibility removed - no restrictions // Spawn more pastafrolas if needed and not all collected if (pastafrolarCollas < 10 && pastafrolas.filter(function (p) { return !p.collected; }).length < 15) { if (Math.random() < 0.05) { // 5% chance per frame spawnPastafrola(); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
language: "spanish"
});
/****
* Classes
****/
var Door = Container.expand(function () {
var self = Container.call(this);
var doorGraphics = self.attachAsset('door', {
anchorX: 0.5,
anchorY: 0.5
});
self.locked = true;
self.update = function () {
if (self.locked && panterasDefeated >= 2 && mouse.pastafrolas >= 10) {
self.locked = false;
doorGraphics.tint = 0x90EE90; // Light green when unlocked
}
if (!self.locked && self.intersects(mouse)) {
// Show congratulations screen
showCongratulationsScreen();
}
};
return self;
});
// Game constants
var Mouse = Container.expand(function () {
var self = Container.call(this);
var mouseGraphics = self.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
});
self.isMoving = false;
self.targetX = 0;
self.targetY = 0;
self.speed = 8;
self.pastafrolas = 0;
self.moveTo = function (x, y) {
var adjustedY = y - MAZE_OFFSET_Y;
var gridX = Math.floor(x / CELL_SIZE);
var gridY = Math.floor(adjustedY / CELL_SIZE);
if (isWalkable(gridX, gridY)) {
self.targetX = x;
self.targetY = y;
self.isMoving = true;
}
};
self.update = function () {
if (self.isMoving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Calculate rotation angle based on movement direction
var targetRotation = Math.atan2(dy, dx) + Math.PI / 2 + Math.PI; // Add PI/2 because mouse starts pointing down, plus PI to correct direction
tween(mouseGraphics, {
rotation: targetRotation
}, {
duration: 150,
easing: tween.easeOut
});
if (distance < self.speed) {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
} else {
var newX = self.x + dx / distance * self.speed;
var newY = self.y + dy / distance * self.speed;
var adjustedY = newY - MAZE_OFFSET_Y;
var gridX = Math.floor(newX / CELL_SIZE);
var gridY = Math.floor(adjustedY / CELL_SIZE);
// Check collision during movement
if (isWalkable(gridX, gridY)) {
self.x = newX;
self.y = newY;
} else {
// Stop movement if hitting wall
self.isMoving = false;
}
}
}
};
return self;
});
var Pantera = Container.expand(function () {
var self = Container.call(this);
var panteraGraphics = self.attachAsset('pantera', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.defeated = false;
// Override the width and height for collision detection to match block size
self.width = 102; // CELL_SIZE
self.height = 102; // CELL_SIZE
self.takeDamage = function (damage) {
if (!self.defeated) {
self.health -= damage;
LK.getSound('hit').play();
LK.getSound('panterasgolpe').play();
if (self.health <= 0) {
self.health = 0;
self.defeated = true;
self.visible = false;
panterasDefeated++;
// Spawn new pastafrola when pantera is defeated
spawnPastafrola();
}
// Visual feedback
LK.effects.flashObject(self, 0xFF0000, 300);
}
};
self.down = function (x, y, obj) {
if (!self.defeated && mouse.pastafrolas > 0) {
// Calculate distance between mouse and pantera centers
var dx = mouse.x - self.x;
var dy = mouse.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var maxAttackDistance = CELL_SIZE * 3; // Must be within 3 cells
// Convert positions to grid coordinates for more reliable line of sight check
var mouseGridX = Math.floor(mouse.x / CELL_SIZE);
var mouseGridY = Math.floor((mouse.y - MAZE_OFFSET_Y) / CELL_SIZE);
var panteraGridX = Math.floor(self.x / CELL_SIZE);
var panteraGridY = Math.floor((self.y - MAZE_OFFSET_Y) / CELL_SIZE);
// Calculate grid distance (Manhattan distance for more lenient attack range)
var gridDistance = Math.abs(mouseGridX - panteraGridX) + Math.abs(panteraGridY - mouseGridY);
// Check if mouse is close enough (within 3 grid cells) and has line of sight
if (gridDistance <= 3 && hasLineOfSight(mouse.x, mouse.y, self.x, self.y)) {
mouse.pastafrolas--;
self.takeDamage(20);
LK.getSound('attack').play();
updateUI();
} else {
// Show notification if attack failed due to distance or obstacles
if (gridDistance > 3) {
showNotification(currentLanguage === 'spanish' ? '¡Muy lejos para atacar!' : 'Too far to attack!');
} else {
showNotification(currentLanguage === 'spanish' ? '¡Hay obstáculos en el camino!' : 'Obstacles are blocking the way!');
}
}
}
};
return self;
});
var Pastafrola = Container.expand(function () {
var self = Container.call(this);
var pastaGraphics = self.attachAsset('pastafrola', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
// Initialize lastIntersecting state if not set
if (self.lastIntersecting === undefined) {
self.lastIntersecting = false;
}
// Check current intersection state
var currentIntersecting = self.intersects(mouse);
// Only collect if we just started intersecting (transition from false to true)
if (!self.collected && !self.lastIntersecting && currentIntersecting) {
self.collected = true;
mouse.pastafrolas++;
pastafrolarCollas++;
LK.getSound('pastafrolasound').play();
self.visible = false;
updateUI();
}
// Update last intersecting state
self.lastIntersecting = currentIntersecting;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
// Game state management
var gameStarted = false;
var startButton;
var selectedLevel = null;
var showingLanguageMenu = false;
var currentLanguage = storage.language || 'spanish';
// Timer variables
var gameTimer = 120000; // 2 minutes in milliseconds
var gameStartTime = 0;
var timeRemainingText;
var pausedTime = 0; // Track total paused time
var pauseStartTime = 0; // Track when pause started
var isPaused = false; // Track pause state
// Translations object
var translations = {
spanish: {
play: 'JUGAR',
language: 'LENGUAJE',
tutorial: 'TUTORIAL',
selectLanguage: 'SELECCIONA IDIOMA',
spanish: 'ESPAÑOL',
english: 'INGLÉS',
congratulations: 'FELICIDADES',
youWon: '¡GANASTE!',
pastafrolas: 'Pastafrolas',
panteras: 'Panteras',
instructionCollect: 'Haz clic para moverte. ¡Recoge pastafrolas y derrota panteras!',
instructionDefeat: '¡Derrota todas las panteras primero!',
instructionNeed10: '¡Necesitas 10 pastafrolas en tu inventario!',
instructionComplete: '¡Todos los objetivos completados! ¡Ve a la puerta verde!',
allDefeated: '¡Todas las panteras derrotadas! Necesitas tener 10 pastafrolas en tu inventario para abrir la puerta',
defeatEnemy: 'Derrota al enemigo de esta zona para continuar',
tutorialText: 'Para moverte presiona el lugar donde quieras ir, para ganar derrota a los enemigos lanzándoles pastafrolas, recoléctalas pasando sobre ellas, y lánzaselas presionando al enemigo que quieras atacar! Tienes un contador que te indica cuantas pastafrolas tienes recolectadas.',
defeat: '¡PERDISTE!',
betterNextTime: 'mejor la próxima vez',
timeRemaining: 'Tiempo restante',
opciones: 'OPCIONES',
lenguaje: 'LENGUAJE',
niveles: 'NIVELES',
volver: 'VOLVER',
cerrar: 'CERRAR',
firstSelectLevel: 'primero selecciona el nivel que quieras jugar',
levelBlocked: 'ups, este nivel está bloqueado!',
tutorialLevel1: 'Para moverte presiona el lugar donde quieras ir, para ganar derrota a los enemigos lanzándoles pastafrolas, recoléctalas pasando sobre ellas, y lánzaselas presionando al enemigo que quieras atacar! Tienes un contador que te indica cuantas pastafrolas tienes recolectadas. ¡y un límite de tiempo de 2 minutos para completar el nivel!'
},
english: {
play: 'PLAY',
language: 'LANGUAGE',
tutorial: 'TUTORIAL',
selectLanguage: 'SELECT LANGUAGE',
spanish: 'SPANISH',
english: 'ENGLISH',
congratulations: 'CONGRATULATIONS',
youWon: 'YOU WON!',
pastafrolas: 'Pastafrolas',
panteras: 'Panthers',
instructionCollect: 'Click to move. Collect pastafrolas and defeat panthers!',
instructionDefeat: 'Defeat all panthers first!',
instructionNeed10: 'You need 10 pastafrolas in your inventory!',
instructionComplete: 'All objectives complete! Head to the green door!',
allDefeated: 'All panthers defeated! You need to have 10 pastafrolas in your inventory to open the door',
defeatEnemy: 'Defeat the enemy in this area to continue',
tutorialText: 'To move press the place where you want to go, to win defeat the enemies by throwing pastafrolas at them, collect them by passing over them, and throw them by pressing the enemy you want to attack! You have a counter that indicates how many pastafrolas you have collected.',
defeat: 'YOU LOST!',
betterNextTime: 'better luck next time',
timeRemaining: 'Time remaining',
opciones: 'OPTIONS',
lenguaje: 'LANGUAGE',
niveles: 'LEVELS',
volver: 'BACK',
cerrar: 'CLOSE',
firstSelectLevel: 'first select the level you want to play',
levelBlocked: 'oops, this level is blocked!',
tutorialLevel1: 'To move press the place where you want to go, to win defeat the enemies by throwing pastafrolas at them, collect them by passing over them, and throw them by pressing the enemy you want to attack! You have a counter that indicates how many pastafrolas you have collected. and a time limit of 2 minutes to complete the level!'
}
};
function getText(key) {
return translations[currentLanguage][key] || key;
}
// Game constants
var CELL_SIZE = 102;
var MAZE_WIDTH = 20;
var MAZE_HEIGHT = 22;
var MAZE_OFFSET_Y = 300; // Vertical offset to move maze down
// Game variables
var mouse;
var door;
var pastafrolas = [];
var panteras = [];
var pastafrolarCollas = 0;
var panterasDefeated = 0;
var lastPanterasDefeated = 0; // Track last pantera count to detect changes
// UI elements
var pastafrolarText;
var panteraText;
var instructionText;
var notificationText;
// Simple maze layout (1 = wall, 0 = walkable)
var mazeData = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
function showCongratulationsScreen() {
// Play victory sound
LK.getSound('victoria').play();
// Stop the game timer by setting gameStarted to false
gameStarted = false;
// Remove fondonegro background
if (backgroundAsset && backgroundAsset.parent) {
game.removeChild(backgroundAsset);
backgroundAsset = null;
}
// Hide UI counters immediately
if (pastafrolarText && pastafrolarText.parent) {
pastafrolarText.visible = false;
}
if (panteraText && panteraText.parent) {
panteraText.visible = false;
}
if (instructionText && instructionText.parent) {
instructionText.visible = false;
}
if (notificationText && notificationText.parent) {
notificationText.visible = false;
}
if (timeRemainingText && timeRemainingText.parent) {
timeRemainingText.visible = false;
}
// Create congratulations background
var congratsBackground = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 25,
scaleY: 35,
tint: 0x000000,
alpha: 0.8
});
game.addChild(congratsBackground);
// Create congratulations title
var congratsTitle = new Text2(getText('congratulations'), {
size: 120,
fill: 0xFFD700
});
congratsTitle.anchor.set(0.5, 0.5);
congratsTitle.x = 1024;
congratsTitle.y = 1200;
game.addChild(congratsTitle);
// Create you won text
var youWonText = new Text2(getText('youWon'), {
size: 100,
fill: 0x00FF00
});
youWonText.anchor.set(0.5, 0.5);
youWonText.x = 1024;
youWonText.y = 1400;
game.addChild(youWonText);
// Automatically return to menu after 3 seconds
LK.setTimeout(function () {
// Remove congratulations screen elements
if (congratsBackground.parent) game.removeChild(congratsBackground);
if (congratsTitle.parent) game.removeChild(congratsTitle);
if (youWonText.parent) game.removeChild(youWonText);
if (timeRemainingText && timeRemainingText.parent) LK.gui.top.removeChild(timeRemainingText);
// Reset game state and return to main menu
resetGameState();
showStartScreen();
}, 3000);
}
function showDefeatScreen() {
// Play defeat sound
LK.getSound('derrota').play();
// Remove fondonegro background
if (backgroundAsset && backgroundAsset.parent) {
game.removeChild(backgroundAsset);
backgroundAsset = null;
}
// Hide UI counters immediately
if (pastafrolarText && pastafrolarText.parent) {
pastafrolarText.visible = false;
}
if (panteraText && panteraText.parent) {
panteraText.visible = false;
}
if (instructionText && instructionText.parent) {
instructionText.visible = false;
}
if (notificationText && notificationText.parent) {
notificationText.visible = false;
}
if (timeRemainingText && timeRemainingText.parent) {
timeRemainingText.visible = false;
}
// Create defeat background
var defeatBackground = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 25,
scaleY: 35,
tint: 0x000000,
alpha: 0.8
});
game.addChild(defeatBackground);
// Create defeat title
var defeatTitle = new Text2(getText('defeat'), {
size: 120,
fill: 0xFF4444
});
defeatTitle.anchor.set(0.5, 0.5);
defeatTitle.x = 1024;
defeatTitle.y = 1200;
game.addChild(defeatTitle);
// Create better next time text
var betterNextTimeText = new Text2(getText('betterNextTime'), {
size: 80,
fill: 0xFFFFFF
});
betterNextTimeText.anchor.set(0.5, 0.5);
betterNextTimeText.x = 1024;
betterNextTimeText.y = 1400;
game.addChild(betterNextTimeText);
// Automatically return to menu after 3 seconds
LK.setTimeout(function () {
// Remove defeat screen elements
if (defeatBackground.parent) game.removeChild(defeatBackground);
if (defeatTitle.parent) game.removeChild(defeatTitle);
if (betterNextTimeText.parent) game.removeChild(betterNextTimeText);
// Reset game state and return to main menu
resetGameState();
showStartScreen();
}, 3000);
}
function showStartScreen() {
// Set background to FONDOMENU with 20% brightness (tint to make it darker)
game.setBackgroundColor(0x000000); // Set to black first
var menuBackground = LK.getAsset('FONDOMENU', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 20.48,
// Scale to fill width (2048/100)
scaleY: 19.54,
// Scale to fill height (2732/139.89)
alpha: 0.2 // 20% brightness
});
game.addChild(menuBackground);
// Create start screen title using titulo asset
var titleText = LK.getAsset('titulo', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800,
scaleX: 1.3,
scaleY: 1.3
});
game.addChild(titleText);
// Add pulsing animation to title
function animateTitle() {
tween(titleText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(titleText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: animateTitle
});
}
});
}
animateTitle();
// Create JUGAR button
startButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200,
scaleX: 4.5,
scaleY: 1.5,
tint: 0x4CAF50
});
game.addChild(startButton);
// Create button text
var buttonText = new Text2(getText('play'), {
size: 80,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 1024;
buttonText.y = 1200;
game.addChild(buttonText);
// Create OPCIONES button
var opcionesButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400,
scaleX: 5,
scaleY: 1.5,
tint: 0x2196F3
});
game.addChild(opcionesButton);
// Create opciones button text
var opcionesButtonText = new Text2(getText('opciones'), {
size: 80,
fill: 0xFFFFFF
});
opcionesButtonText.anchor.set(0.5, 0.5);
opcionesButtonText.x = 1024;
opcionesButtonText.y = 1400;
game.addChild(opcionesButtonText);
// Add click handler to start button
startButton.down = function (x, y, obj) {
if (!selectedLevel) {
showNotificationMessage(getText('firstSelectLevel'));
return;
}
gameStarted = true;
// Set background to black (0% brightness) when game starts
game.setBackgroundColor(0x000000);
// gameStarted flag will stop menumusical sound from looping
// Remove start screen elements
game.removeChild(titleText);
game.removeChild(startButton);
game.removeChild(buttonText);
game.removeChild(opcionesButton);
game.removeChild(opcionesButtonText);
// Initialize the actual game
initializeGame();
};
// Add click handler to opciones button
opcionesButton.down = function (x, y, obj) {
// Remove start screen elements
if (game.children[0] && game.children[0].texture && game.children[0].texture.textureCacheIds && game.children[0].texture.textureCacheIds.indexOf('FONDOMENU') !== -1) {
game.removeChild(game.children[0]); // Remove menuBackground
}
game.removeChild(titleText);
game.removeChild(startButton);
game.removeChild(buttonText);
game.removeChild(opcionesButton);
game.removeChild(opcionesButtonText);
// Show options screen
showOptionsScreen();
};
}
function showLanguageScreen() {
showingLanguageMenu = true;
// Create title
var languageTitle = new Text2(getText('selectLanguage'), {
size: 100,
fill: 0xFFFFFF
});
languageTitle.anchor.set(0.5, 0.5);
languageTitle.x = 1024;
languageTitle.y = 800;
game.addChild(languageTitle);
// Create Spanish button
var spanishButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1100,
scaleX: 3,
scaleY: 1.5,
tint: currentLanguage === 'spanish' ? 0x4CAF50 : 0x757575
});
game.addChild(spanishButton);
var spanishButtonText = new Text2(getText('spanish'), {
size: 70,
fill: 0xFFFFFF
});
spanishButtonText.anchor.set(0.5, 0.5);
spanishButtonText.x = 1024;
spanishButtonText.y = 1100;
game.addChild(spanishButtonText);
// Create English button
var englishButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1300,
scaleX: 3,
scaleY: 1.5,
tint: currentLanguage === 'english' ? 0x4CAF50 : 0x757575
});
game.addChild(englishButton);
var englishButtonText = new Text2(getText('english'), {
size: 70,
fill: 0xFFFFFF
});
englishButtonText.anchor.set(0.5, 0.5);
englishButtonText.x = 1024;
englishButtonText.y = 1300;
game.addChild(englishButtonText);
// Spanish button click handler
spanishButton.down = function (x, y, obj) {
currentLanguage = 'spanish';
storage.language = 'spanish';
// Remove language screen elements
game.removeChild(languageTitle);
game.removeChild(spanishButton);
game.removeChild(spanishButtonText);
game.removeChild(englishButton);
game.removeChild(englishButtonText);
showingLanguageMenu = false;
// Return to options screen
showOptionsScreen();
};
// English button click handler
englishButton.down = function (x, y, obj) {
currentLanguage = 'english';
storage.language = 'english';
// Remove language screen elements
game.removeChild(languageTitle);
game.removeChild(spanishButton);
game.removeChild(spanishButtonText);
game.removeChild(englishButton);
game.removeChild(englishButtonText);
showingLanguageMenu = false;
// Return to options screen
showOptionsScreen();
};
}
function showTutorialScreen() {
// Create tutorial background
var tutorialBackground = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 24,
scaleY: 32,
tint: 0x1A1A1A,
alpha: 0.9
});
game.addChild(tutorialBackground);
// Create tutorial title
var tutorialTitle = new Text2(getText('tutorial'), {
size: 100,
fill: 0xFFD700
});
tutorialTitle.anchor.set(0.5, 0.5);
tutorialTitle.x = 1024;
tutorialTitle.y = 400;
game.addChild(tutorialTitle);
// Create tutorial text - break into multiple lines for better readability
var tutorialText = new Text2(getText('tutorialText'), {
size: 50,
fill: 0xFFFFFF,
wordWrap: true,
wordWrapWidth: 1800
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1000;
game.addChild(tutorialText);
// Create back button
var backButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1700,
scaleX: 2.5,
scaleY: 1.2,
tint: 0x4CAF50
});
game.addChild(backButton);
// Create back button text
var backButtonText = new Text2(getText('volver'), {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 1700;
game.addChild(backButtonText);
// Add click handler to back button
backButton.down = function (x, y, obj) {
// Remove tutorial screen elements
game.removeChild(tutorialBackground);
game.removeChild(tutorialTitle);
game.removeChild(tutorialText);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Return to start screen
showStartScreen();
};
}
function showOptionsScreen() {
// Create options title
var optionsTitle = new Text2(getText('opciones'), {
size: 100,
fill: 0xFFFFFF
});
optionsTitle.anchor.set(0.5, 0.5);
optionsTitle.x = 1024;
optionsTitle.y = 600;
game.addChild(optionsTitle);
// Create language button
var languageButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1000,
scaleX: 4,
scaleY: 1.5,
tint: 0x2196F3
});
game.addChild(languageButton);
var languageButtonText = new Text2(getText('lenguaje'), {
size: 70,
fill: 0xFFFFFF
});
languageButtonText.anchor.set(0.5, 0.5);
languageButtonText.x = 1024;
languageButtonText.y = 1000;
game.addChild(languageButtonText);
// Create niveles button
var nivelesButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200,
scaleX: 4,
scaleY: 1.5,
tint: 0xFF9800
});
game.addChild(nivelesButton);
var nivelesButtonText = new Text2(getText('niveles'), {
size: 70,
fill: 0xFFFFFF
});
nivelesButtonText.anchor.set(0.5, 0.5);
nivelesButtonText.x = 1024;
nivelesButtonText.y = 1200;
game.addChild(nivelesButtonText);
// Create back button
var backButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
scaleX: 2.5,
scaleY: 1.2,
tint: 0x4CAF50
});
game.addChild(backButton);
var backButtonText = new Text2(getText('volver'), {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 1500;
game.addChild(backButtonText);
// Language button click handler
languageButton.down = function (x, y, obj) {
// Remove options screen elements
game.removeChild(optionsTitle);
game.removeChild(languageButton);
game.removeChild(languageButtonText);
game.removeChild(nivelesButton);
game.removeChild(nivelesButtonText);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Show language selection screen
showLanguageScreen();
};
// Niveles button click handler
nivelesButton.down = function (x, y, obj) {
// Remove options screen elements
game.removeChild(optionsTitle);
game.removeChild(languageButton);
game.removeChild(languageButtonText);
game.removeChild(nivelesButton);
game.removeChild(nivelesButtonText);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Show levels screen
showLevelsScreen();
};
// Back button click handler
backButton.down = function (x, y, obj) {
// Remove options screen elements
game.removeChild(optionsTitle);
game.removeChild(languageButton);
game.removeChild(languageButtonText);
game.removeChild(nivelesButton);
game.removeChild(nivelesButtonText);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Return to start screen
showStartScreen();
};
}
function showLevelsScreen() {
// Create levels title
var levelsTitle = new Text2(getText('niveles'), {
size: 100,
fill: 0xFFFFFF
});
levelsTitle.anchor.set(0.5, 0.5);
levelsTitle.x = 1024;
levelsTitle.y = 600;
game.addChild(levelsTitle);
// Create level1 button
var level1Button = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 900,
scaleX: 3,
scaleY: 3
});
game.addChild(level1Button);
// Create level2 button
var level2Button = LK.getAsset('level2', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 900,
scaleX: 3,
scaleY: 3
});
game.addChild(level2Button);
// Create candado (lock) for level2
var candadoButton = LK.getAsset('candado', {
anchorX: 0.5,
anchorY: 0.5,
x: 1200,
y: 900,
scaleX: 1,
scaleY: 1
});
game.addChild(candadoButton);
// Create tutorial button for level1
var tutorialLevel1Button = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 1100,
scaleX: 2,
scaleY: 1,
tint: 0x4CAF50
});
game.addChild(tutorialLevel1Button);
var tutorialLevel1Text = new Text2(getText('tutorial'), {
size: 40,
fill: 0xFFFFFF
});
tutorialLevel1Text.anchor.set(0.5, 0.5);
tutorialLevel1Text.x = 512;
tutorialLevel1Text.y = 1100;
game.addChild(tutorialLevel1Text);
// Create tutorial button for level2
var tutorialLevel2Button = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1100,
scaleX: 2,
scaleY: 1,
tint: 0x757575
});
game.addChild(tutorialLevel2Button);
var tutorialLevel2Text = new Text2(getText('tutorial'), {
size: 40,
fill: 0xFFFFFF
});
tutorialLevel2Text.anchor.set(0.5, 0.5);
tutorialLevel2Text.x = 1024;
tutorialLevel2Text.y = 1100;
game.addChild(tutorialLevel2Text);
// Create back button
var backButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400,
scaleX: 2.5,
scaleY: 1.2,
tint: 0x4CAF50
});
game.addChild(backButton);
var backButtonText = new Text2(getText('volver'), {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 1024;
backButtonText.y = 1400;
game.addChild(backButtonText);
// Level1 button click handler
level1Button.down = function (x, y, obj) {
selectedLevel = 1;
// Remove levels screen elements
game.removeChild(levelsTitle);
game.removeChild(level1Button);
game.removeChild(level2Button);
game.removeChild(candadoButton);
game.removeChild(tutorialLevel1Button);
game.removeChild(tutorialLevel1Text);
game.removeChild(tutorialLevel2Button);
game.removeChild(tutorialLevel2Text);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Return to main menu
showStartScreen();
};
// Tutorial Level1 button click handler
tutorialLevel1Button.down = function (x, y, obj) {
showTutorialMessage(getText('tutorialLevel1'));
};
// Tutorial Level2 button click handler
tutorialLevel2Button.down = function (x, y, obj) {
showTutorialMessage(getText('levelBlocked'));
};
// Back button click handler
backButton.down = function (x, y, obj) {
// Remove levels screen elements
game.removeChild(levelsTitle);
game.removeChild(level1Button);
game.removeChild(level2Button);
game.removeChild(candadoButton);
game.removeChild(tutorialLevel1Button);
game.removeChild(tutorialLevel1Text);
game.removeChild(tutorialLevel2Button);
game.removeChild(tutorialLevel2Text);
game.removeChild(backButton);
game.removeChild(backButtonText);
// Return to options screen
showOptionsScreen();
};
}
function showTutorialMessage(message) {
// Create tutorial background
var tutorialBackground = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 24,
scaleY: 32,
tint: 0x1A1A1A,
alpha: 0.9
});
game.addChild(tutorialBackground);
// Create tutorial text
var tutorialText = new Text2(message, {
size: 50,
fill: 0xFFFFFF,
wordWrap: true,
wordWrapWidth: 1800
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1200;
game.addChild(tutorialText);
// Create close button
var closeButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1600,
scaleX: 2.5,
scaleY: 1.2,
tint: 0x4CAF50
});
game.addChild(closeButton);
var closeButtonText = new Text2(getText('cerrar'), {
size: 60,
fill: 0xFFFFFF
});
closeButtonText.anchor.set(0.5, 0.5);
closeButtonText.x = 1024;
closeButtonText.y = 1600;
game.addChild(closeButtonText);
// Close button click handler
closeButton.down = function (x, y, obj) {
// Remove tutorial message elements
game.removeChild(tutorialBackground);
game.removeChild(tutorialText);
game.removeChild(closeButton);
game.removeChild(closeButtonText);
};
}
function showNotificationMessage(message) {
// Create notification background
var notificationBackground = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 20,
scaleY: 8,
tint: 0x1A1A1A,
alpha: 0.9
});
game.addChild(notificationBackground);
// Create notification text
var notificationText = new Text2(message, {
size: 60,
fill: 0xFFFFFF,
wordWrap: true,
wordWrapWidth: 1600
});
notificationText.anchor.set(0.5, 0.5);
notificationText.x = 1024;
notificationText.y = 1300;
game.addChild(notificationText);
// Create close button
var closeButton = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
scaleX: 2,
scaleY: 1,
tint: 0x4CAF50
});
game.addChild(closeButton);
var closeButtonText = new Text2('OK', {
size: 50,
fill: 0xFFFFFF
});
closeButtonText.anchor.set(0.5, 0.5);
closeButtonText.x = 1024;
closeButtonText.y = 1500;
game.addChild(closeButtonText);
// Close button click handler
closeButton.down = function (x, y, obj) {
// Remove notification message elements
game.removeChild(notificationBackground);
game.removeChild(notificationText);
game.removeChild(closeButton);
game.removeChild(closeButtonText);
};
}
var backgroundAsset; // Global variable to track background
function initializeGame() {
// Remove FONDOMENU background asset if it exists
if (game.children.length > 0) {
var menuBackground = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i].texture && game.children[i].texture.textureCacheIds && game.children[i].texture.textureCacheIds.indexOf('FONDOMENU') !== -1) {
menuBackground = game.children[i];
break;
}
}
if (menuBackground) {
game.removeChild(menuBackground);
}
}
// Set background to black
game.setBackgroundColor(0x000000);
// Add fondonegro background behind maze and letters
backgroundAsset = LK.getAsset('fondonegro', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 20.48,
// Scale to fill width (2048/100)
scaleY: 27.32 // Scale to fill height (2732/100)
});
game.addChild(backgroundAsset);
// Build the maze
for (var y = 0; y < MAZE_HEIGHT; y++) {
for (var x = 0; x < MAZE_WIDTH; x++) {
if (y < mazeData.length && mazeData[y][x] === 1) {
var wall = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: x * CELL_SIZE + CELL_SIZE / 2,
y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y
});
game.addChild(wall);
} else if (y < mazeData.length) {
var floor = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: x * CELL_SIZE + CELL_SIZE / 2,
y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y
});
game.addChild(floor);
}
}
}
// Create mouse
mouse = new Mouse();
mouse.x = 1.5 * CELL_SIZE;
mouse.y = 1.5 * CELL_SIZE + MAZE_OFFSET_Y;
game.addChild(mouse);
// Create door at the bottom right
door = new Door();
door.x = 18 * CELL_SIZE + CELL_SIZE / 2;
door.y = (MAZE_HEIGHT - 2) * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
game.addChild(door);
// Spawn initial pastafrolas
for (var i = 0; i < 20; i++) {
spawnPastafrola();
}
// Spawn 2 panteras in strategic positions
var panteraPositions = [{
x: 5,
y: 5
}, {
x: 15,
y: 8
}];
for (var i = 0; i < panteraPositions.length; i++) {
var pos = panteraPositions[i];
if (isWalkable(pos.x, pos.y)) {
var pantera = new Pantera();
pantera.x = pos.x * CELL_SIZE + CELL_SIZE / 2;
pantera.y = pos.y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y;
panteras.push(pantera);
game.addChild(pantera);
}
}
// Setup UI - all elements in top area to avoid click interference
pastafrolarText = new Text2(getText('pastafrolas') + ': 0', {
size: 60,
fill: 0xFFFFFF
});
pastafrolarText.anchor.set(0.5, 0);
pastafrolarText.y = 0; // At very top
LK.gui.top.addChild(pastafrolarText);
// Add panteras defeated text below pastafrolas text
panteraText = new Text2(getText('panteras') + ': 0/2', {
size: 50,
fill: 0xFFFFFF
});
panteraText.anchor.set(0.5, 0);
panteraText.y = 70; // Below pastafrola text
LK.gui.top.addChild(panteraText);
instructionText = new Text2(getText('instructionCollect'), {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 130; // Below pantera text
LK.gui.top.addChild(instructionText);
notificationText = new Text2('', {
size: 45,
fill: 0xFF4444
});
notificationText.anchor.set(0.5, 1);
notificationText.visible = false;
LK.gui.bottom.addChild(notificationText);
// Initialize game timer
gameStartTime = Date.now();
// Create time remaining display
timeRemainingText = new Text2(getText('timeRemaining') + ': 2:00', {
size: 50,
fill: 0xFFFFFF
});
timeRemainingText.anchor.set(0.5, 0);
timeRemainingText.y = 180; // Below instruction text
LK.gui.top.addChild(timeRemainingText);
// Update UI
updateUI();
}
// Show start screen initially
showStartScreen();
function isWalkable(gridX, gridY) {
if (gridX < 0 || gridX >= MAZE_WIDTH || gridY < 0 || gridY >= MAZE_HEIGHT) {
return false;
}
return mazeData[gridY][gridX] === 0;
}
function hasLineOfSight(x1, y1, x2, y2) {
// Convert world coordinates to grid coordinates more accurately
var gridX1 = Math.floor(x1 / CELL_SIZE);
var gridY1 = Math.floor((y1 - MAZE_OFFSET_Y) / CELL_SIZE);
var gridX2 = Math.floor(x2 / CELL_SIZE);
var gridY2 = Math.floor((y2 - MAZE_OFFSET_Y) / CELL_SIZE);
// Ensure coordinates are within bounds
if (gridX1 < 0 || gridX1 >= MAZE_WIDTH || gridY1 < 0 || gridY1 >= MAZE_HEIGHT || gridX2 < 0 || gridX2 >= MAZE_WIDTH || gridY2 < 0 || gridY2 >= MAZE_HEIGHT) {
return false;
}
// Use Bresenham's line algorithm to check each grid cell between the two points
var dx = Math.abs(gridX2 - gridX1);
var dy = Math.abs(gridY2 - gridY1);
var x = gridX1;
var y = gridY1;
var xInc = gridX1 < gridX2 ? 1 : -1;
var yInc = gridY1 < gridY2 ? 1 : -1;
var error = dx - dy;
// Don't check the starting position (mouse position) as it's always walkable
var stepCount = 0;
while (true) {
// If we reached the target, we have clear line of sight
if (x === gridX2 && y === gridY2) {
break;
}
var error2 = 2 * error;
if (error2 > -dy) {
error -= dy;
x += xInc;
}
if (error2 < dx) {
error += dx;
y += yInc;
}
stepCount++;
// Check if current position is a wall (not walkable), but skip first and last positions
if (stepCount > 0 && (x !== gridX2 || y !== gridY2) && !isWalkable(x, y)) {
return false; // Wall blocks line of sight
}
// Prevent infinite loops
if (stepCount > 50) {
return false;
}
}
return true; // Clear line of sight
}
var barriers = []; // Global array to track barriers
function canAccessArea(gridX, gridY) {
// Define restricted areas that unlock as panteras are defeated
var restrictedAreas = [{
minX: 0,
maxX: 6,
minY: 0,
maxY: 8,
requiredDefeats: 0
},
// Starting area
{
minX: 7,
maxX: 13,
minY: 0,
maxY: 8,
requiredDefeats: 1
},
// Second area
{
minX: 14,
maxX: 19,
minY: 0,
maxY: 8,
requiredDefeats: 2
},
// Third area
{
minX: 0,
maxX: 6,
minY: 9,
maxY: 17,
requiredDefeats: 2
},
// Fourth area
{
minX: 7,
maxX: 13,
minY: 9,
maxY: 17,
requiredDefeats: 3
},
// Fifth area
{
minX: 14,
maxX: 19,
minY: 9,
maxY: 17,
requiredDefeats: 4
},
// Sixth area
{
minX: 0,
maxX: 19,
minY: 18,
maxY: 26,
requiredDefeats: 5
} // Final area
];
for (var i = 0; i < restrictedAreas.length; i++) {
var area = restrictedAreas[i];
if (gridX >= area.minX && gridX <= area.maxX && gridY >= area.minY && gridY <= area.maxY) {
if (panterasDefeated < area.requiredDefeats) {
showNotification(getText('defeatEnemy'));
return false;
}
return true;
}
}
return true; // Default allow access
}
function createBarriers() {
// Create barriers at area boundaries
var barrierPositions = [
// Vertical barrier between areas 1 and 2
{
x: 6,
y: 1
}, {
x: 6,
y: 2
}, {
x: 6,
y: 3
}, {
x: 6,
y: 4
}, {
x: 6,
y: 5
}, {
x: 6,
y: 6
}, {
x: 6,
y: 7
},
// Vertical barrier between areas 2 and 3
{
x: 13,
y: 1
}, {
x: 13,
y: 2
}, {
x: 13,
y: 3
}, {
x: 13,
y: 4
}, {
x: 13,
y: 5
}, {
x: 13,
y: 6
}, {
x: 13,
y: 7
},
// Horizontal barrier between upper and middle sections
{
x: 1,
y: 8
}, {
x: 2,
y: 8
}, {
x: 3,
y: 8
}, {
x: 4,
y: 8
}, {
x: 5,
y: 8
}, {
x: 7,
y: 8
}, {
x: 8,
y: 8
}, {
x: 9,
y: 8
}, {
x: 10,
y: 8
}, {
x: 11,
y: 8
}, {
x: 12,
y: 8
}, {
x: 14,
y: 8
}, {
x: 15,
y: 8
}, {
x: 16,
y: 8
}, {
x: 17,
y: 8
}, {
x: 18,
y: 8
},
// Vertical barriers in middle section
{
x: 6,
y: 10
}, {
x: 6,
y: 11
}, {
x: 6,
y: 13
}, {
x: 6,
y: 14
}, {
x: 6,
y: 15
}, {
x: 6,
y: 16
}, {
x: 13,
y: 10
}, {
x: 13,
y: 11
}, {
x: 13,
y: 13
}, {
x: 13,
y: 14
}, {
x: 13,
y: 15
}, {
x: 13,
y: 16
},
// Horizontal barrier between middle and bottom sections
{
x: 1,
y: 17
}, {
x: 2,
y: 17
}, {
x: 3,
y: 17
}, {
x: 4,
y: 17
}, {
x: 5,
y: 17
}, {
x: 6,
y: 17
}, {
x: 7,
y: 17
}, {
x: 8,
y: 17
}, {
x: 9,
y: 17
}, {
x: 10,
y: 17
}, {
x: 11,
y: 17
}, {
x: 12,
y: 17
}, {
x: 13,
y: 17
}, {
x: 14,
y: 17
}, {
x: 15,
y: 17
}, {
x: 16,
y: 17
}, {
x: 17,
y: 17
}, {
x: 18,
y: 17
}];
for (var i = 0; i < barrierPositions.length; i++) {
var pos = barrierPositions[i];
if (isWalkable(pos.x, pos.y)) {
var barrier = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
x: pos.x * CELL_SIZE + CELL_SIZE / 2,
y: pos.y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y,
alpha: 0.7
});
barriers.push(barrier);
game.addChild(barrier);
}
}
}
function updateBarrierVisibility() {
// Hide barriers in unlocked areas
for (var i = 0; i < barriers.length; i++) {
var barrier = barriers[i];
var gridX = Math.floor((barrier.x - CELL_SIZE / 2) / CELL_SIZE);
var gridY = Math.floor((barrier.y - CELL_SIZE / 2 - MAZE_OFFSET_Y) / CELL_SIZE);
// Check if this barrier should be visible based on area access
var shouldShow = !canAccessAreaSilent(gridX, gridY);
barrier.visible = shouldShow;
}
}
function canAccessAreaSilent(gridX, gridY) {
// Same as canAccessArea but without showing notification
var restrictedAreas = [{
minX: 0,
maxX: 6,
minY: 0,
maxY: 8,
requiredDefeats: 0
}, {
minX: 7,
maxX: 13,
minY: 0,
maxY: 8,
requiredDefeats: 1
}, {
minX: 14,
maxX: 19,
minY: 0,
maxY: 8,
requiredDefeats: 2
}, {
minX: 0,
maxX: 6,
minY: 9,
maxY: 17,
requiredDefeats: 2
}, {
minX: 7,
maxX: 13,
minY: 9,
maxY: 17,
requiredDefeats: 3
}, {
minX: 14,
maxX: 19,
minY: 9,
maxY: 17,
requiredDefeats: 4
}, {
minX: 0,
maxX: 19,
minY: 18,
maxY: 26,
requiredDefeats: 5
}];
for (var i = 0; i < restrictedAreas.length; i++) {
var area = restrictedAreas[i];
if (gridX >= area.minX && gridX <= area.maxX && gridY >= area.minY && gridY <= area.maxY) {
return panterasDefeated >= area.requiredDefeats;
}
}
return true;
}
function getRandomWalkablePosition() {
var attempts = 0;
while (attempts < 100) {
var x = Math.floor(Math.random() * MAZE_WIDTH);
var y = Math.floor(Math.random() * MAZE_HEIGHT);
if (isWalkable(x, y)) {
return {
x: x * CELL_SIZE + CELL_SIZE / 2,
y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y
};
}
attempts++;
}
return {
x: 1.5 * CELL_SIZE,
y: 1.5 * CELL_SIZE + MAZE_OFFSET_Y
}; // Fallback position
}
function getRandomWalkablePositionIncludingRestricted() {
var attempts = 0;
while (attempts < 100) {
var x = Math.floor(Math.random() * MAZE_WIDTH);
var y = Math.floor(Math.random() * MAZE_HEIGHT);
// Allow spawning in any walkable area, including restricted ones
if (isWalkable(x, y)) {
return {
x: x * CELL_SIZE + CELL_SIZE / 2,
y: y * CELL_SIZE + CELL_SIZE / 2 + MAZE_OFFSET_Y
};
}
attempts++;
}
return {
x: 1.5 * CELL_SIZE,
y: 1.5 * CELL_SIZE + MAZE_OFFSET_Y
}; // Fallback position
}
function spawnPastafrola() {
var position = getRandomWalkablePositionIncludingRestricted();
var pastafrola = new Pastafrola();
pastafrola.x = position.x;
pastafrola.y = position.y;
pastafrolas.push(pastafrola);
game.addChild(pastafrola);
}
function resetGameState() {
// Reset game state
gameStarted = false;
pastafrolarCollas = 0;
panterasDefeated = 0;
lastPanterasDefeated = 0;
gameTimer = 120000;
gameStartTime = 0;
pausedTime = 0;
pauseStartTime = 0;
isPaused = false;
// Remove fondonegro background if it exists
if (backgroundAsset && backgroundAsset.parent) {
game.removeChild(backgroundAsset);
backgroundAsset = null;
}
// Clear all game objects
if (mouse) {
game.removeChild(mouse);
mouse = null;
}
if (door) {
game.removeChild(door);
door = null;
}
// Clear arrays and remove objects
for (var i = 0; i < pastafrolas.length; i++) {
if (pastafrolas[i].parent) {
game.removeChild(pastafrolas[i]);
}
}
pastafrolas = [];
for (var i = 0; i < panteras.length; i++) {
if (panteras[i].parent) {
game.removeChild(panteras[i]);
}
}
panteras = [];
for (var i = 0; i < barriers.length; i++) {
if (barriers[i].parent) {
game.removeChild(barriers[i]);
}
}
barriers = [];
// Clear UI elements
if (pastafrolarText && pastafrolarText.parent) {
LK.gui.top.removeChild(pastafrolarText);
pastafrolarText = null;
}
if (panteraText && panteraText.parent) {
LK.gui.top.removeChild(panteraText);
panteraText = null;
}
if (instructionText && instructionText.parent) {
LK.gui.top.removeChild(instructionText);
instructionText = null;
}
if (notificationText && notificationText.parent) {
LK.gui.bottom.removeChild(notificationText);
notificationText = null;
}
if (timeRemainingText && timeRemainingText.parent) {
LK.gui.top.removeChild(timeRemainingText);
timeRemainingText = null;
}
// Clear all remaining children from game - create a copy of the array to avoid modification during iteration
var childrenToRemove = [];
for (var i = 0; i < game.children.length; i++) {
childrenToRemove.push(game.children[i]);
}
for (var i = 0; i < childrenToRemove.length; i++) {
if (childrenToRemove[i].parent === game) {
game.removeChild(childrenToRemove[i]);
}
}
}
function showNotification(message) {
if (notificationText) {
notificationText.setText(message);
notificationText.visible = true;
LK.setTimeout(function () {
if (notificationText) {
notificationText.visible = false;
}
}, 2000);
}
}
function updateUI() {
pastafrolarText.setText(getText('pastafrolas') + ': ' + mouse.pastafrolas);
panteraText.setText(getText('panteras') + ': ' + panterasDefeated + '/2');
if (panterasDefeated < 2) {
instructionText.setText(getText('instructionDefeat') + ' (' + panterasDefeated + '/2)');
} else if (mouse.pastafrolas < 10) {
instructionText.setText(getText('instructionNeed10') + ' (' + mouse.pastafrolas + '/10)');
} else {
instructionText.setText(getText('instructionComplete'));
}
}
// Game initialization now handled by start screen
// Game controls
game.down = function (x, y, obj) {
if (gameStarted && mouse) {
mouse.moveTo(x, y);
}
};
// Handle pause events
LK.on('pause', function () {
if (gameStarted && !isPaused) {
isPaused = true;
pauseStartTime = Date.now();
}
});
LK.on('resume', function () {
if (gameStarted && isPaused) {
isPaused = false;
pausedTime += Date.now() - pauseStartTime;
}
});
// Main game loop
game.update = function () {
if (!gameStarted) return;
// Update timer
var currentTime = Date.now();
var elapsedTime = currentTime - gameStartTime - pausedTime;
var timeLeft = Math.max(0, gameTimer - elapsedTime);
// Update timer display
if (timeRemainingText) {
var secondsLeft = Math.ceil(timeLeft / 1000);
var minutes = Math.floor(secondsLeft / 60);
var seconds = secondsLeft % 60;
var timeStr = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timeRemainingText.setText(getText('timeRemaining') + ': ' + timeStr);
// Change color when time is running out
if (timeLeft <= 30000) {
// Last 30 seconds
timeRemainingText.tint = 0xFF4444;
} else if (timeLeft <= 60000) {
// Last minute
timeRemainingText.tint = 0xFFAA00;
} else {
timeRemainingText.tint = 0xFFFFFF;
}
}
// Check if time is up
if (timeLeft <= 0) {
showDefeatScreen();
return;
}
// Check if we just defeated all panteras (transition from not all defeated to all defeated)
if (lastPanterasDefeated < 2 && panterasDefeated >= 2) {
showNotification(getText('allDefeated'));
}
lastPanterasDefeated = panterasDefeated;
// Update mouse
if (mouse) {
mouse.update();
}
// Update pastafrolas
for (var i = 0; i < pastafrolas.length; i++) {
pastafrolas[i].update();
}
// Update panteras
for (var i = 0; i < panteras.length; i++) {
if (!panteras[i].defeated) {
// Simple AI: panteras don't move but can be clicked for combat
}
}
// Update door
if (door) {
door.update();
}
// Barrier visibility removed - no restrictions
// Spawn more pastafrolas if needed and not all collected
if (pastafrolarCollas < 10 && pastafrolas.filter(function (p) {
return !p.collected;
}).length < 15) {
if (Math.random() < 0.05) {
// 5% chance per frame
spawnPastafrola();
}
}
};