/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var FallingItem = Container.expand(function (type, specificFood) { var self = Container.call(this); self.type = type; self.specificFood = specificFood; // Set different speeds based on type and add randomness if (type === 'anxiety') { self.speed = fallSpeed * 1.5; // Anxiety bombs fall faster } else if (type === 'water') { self.speed = fallSpeed * 0.8; // Water bottles fall slower } else { // Food items have variable speeds between 1.2x and 2.0x base speed (much faster) var speedMultiplier = 1.2 + Math.random() * 0.8; // Increase speed significantly during expert mode if (anxietyBombsActive) { speedMultiplier *= 2.2; // Make items fall 120% faster in expert mode } self.speed = fallSpeed * speedMultiplier; } var assetName = specificFood || 'waterBottle'; if (type === 'water') assetName = 'waterBottle';else if (type === 'anxiety') assetName = 'anxietyBomb'; var graphic = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.y += self.speed; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerBody = self.attachAsset('player', { anchorX: 0.5, anchorY: 1.0 }); var basket = self.attachAsset('basket', { anchorX: 0.5, anchorY: 0.5, y: -110 }); self.speed = 8; self.targetX = self.x; self.update = function () { var dx = self.targetX - self.x; if (Math.abs(dx) > 5) { self.x += dx * 0.15; } else { self.x = self.targetX; } // Keep player within bounds if (self.x < 150) self.x = 150; if (self.x > 2048 - 150) self.x = 2048 - 150; }; self.moveTo = function (targetX) { self.targetX = targetX; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Fake Healthy Foods // Junk Foods // Healthy Foods - Proteins & Grains // Healthy Foods - Vegetables // Healthy Foods - Fruits // Game variables // Healthy foods // Junk foods // Fake healthy foods // Game elements var player; var fallingItems = []; var energy = 15; var lives = 3; var fallSpeed = 350 / 60; // 350px/s converted to pixels per frame (much faster) var lastSpeedIncrease = 0; var lastWaterSpawn = 0; var gameStartTime = 0; var foodsCaught = 0; var anxietyBombsActive = false; var lastSpawnTime = 0; var lastAnxietySpawnTime = 0; var expertMessageShown = false; var gameActive = true; // Track if game is active // Food tracking variables var foodCounts = { 'apple': 0, 'banana': 0, 'hardEgg': 0, 'broccoli': 0, 'carrot': 0, 'wholeBread': 0, 'waterBottle': 0 }; // UI elements var livesText; var scoreText; var energyText; var energyBarBg; var energyBarFill; // Initialize UI function initializeUI() { // Energy text with larger size energyText = new Text2('Energía: 15/30', { size: 72, fill: 0xFFFFFF, font: "Impact" }); energyText.anchor.set(0, 0); LK.gui.topLeft.addChild(energyText); energyText.x = 150; energyText.y = 20; // Energy bar background energyBarBg = LK.getAsset('energyBarBg', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(energyBarBg); energyBarBg.x = 150; energyBarBg.y = 100; // Energy bar fill energyBarFill = LK.getAsset('energyBarFill', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(energyBarFill); energyBarFill.x = 150; energyBarFill.y = 100; // Lives text with larger size livesText = new Text2('Vidas: 3', { size: 84, fill: 0xFF0000, font: "Impact" }); livesText.anchor.set(1, 0); LK.gui.topRight.addChild(livesText); livesText.x = -20; livesText.y = 20; // Score text with larger size scoreText = new Text2('Puntuación: 0', { size: 78, fill: 0xFFFFFF, font: "Impact" }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 160; } // Update UI function updateUI() { energyText.setText('Energía: ' + energy + '/30'); livesText.setText('Vidas: ' + lives); scoreText.setText('Puntuación: ' + LK.getScore()); // Update energy bar fill based on current energy (0-30 range) var energyPercentage = energy / 30; energyBarFill.width = 400 * energyPercentage; // Change energy bar color based on energy level if (energy >= 20) { energyBarFill.tint = 0x00ff00; // Green for high energy } else if (energy >= 10) { energyBarFill.tint = 0xffff00; // Yellow for medium energy } else { energyBarFill.tint = 0xff0000; // Red for low energy } } // Flash effect function flashScreen(color) { LK.effects.flashScreen(color, 300); } // Food arrays for variety - exactly 10 sprite types + 2 fake healthy var healthyFoods = ['banana', 'apple', 'carrot', 'broccoli', 'wholeBread', 'hardEgg']; var junkFoods = ['soda', 'chips', 'candy', 'burger']; var fakeFoods = ['cerealBar', 'flavoredYogurt']; // Spawn falling item function spawnFallingItem() { var type = 'healthy'; var specificFood = null; var rand = Math.random(); if (foodsCaught > 0 && foodsCaught % 20 === 0 && lastWaterSpawn !== foodsCaught) { type = 'water'; lastWaterSpawn = foodsCaught; } else if (rand < 0.3) { type = 'junk'; specificFood = junkFoods[Math.floor(Math.random() * junkFoods.length)]; } else if (rand < 0.5) { type = 'fake'; specificFood = fakeFoods[Math.floor(Math.random() * fakeFoods.length)]; } else { type = 'healthy'; specificFood = healthyFoods[Math.floor(Math.random() * healthyFoods.length)]; } var item = new FallingItem(type, specificFood); item.x = Math.random() * (2048 - 350) + 175; item.y = -175; fallingItems.push(item); game.addChild(item); } // Spawn anxiety bomb function spawnAnxietyBomb() { var item = new FallingItem('anxiety', null); item.x = Math.random() * (2048 - 350) + 175; item.y = -175; fallingItems.push(item); game.addChild(item); } // Helper function for player visual feedback function playerFeedback(color, duration, scaleEffect) { if (scaleEffect) { tween(player, { scaleX: 1.2, scaleY: 1.2 }, { duration: duration, onFinish: function onFinish() { tween(player, { scaleX: 1.0, scaleY: 1.0 }, { duration: duration }); } }); } else { tween(player, { tint: color }, { duration: duration, onFinish: function onFinish() { tween(player, { tint: 0xFFFFFF }, { duration: duration }); } }); } } // Helper function for vibration feedback function vibrateDevice() { if (navigator && navigator.vibrate) { navigator.vibrate(100); } } // Handle item collision function handleItemCollision(item) { switch (item.type) { case 'healthy': energy = Math.min(30, energy + 1); LK.setScore(LK.getScore() + 1); LK.getSound('ping').play(); flashScreen(0x32CD32); playerFeedback(0x32CD32, 100, false); foodsCaught++; // Track healthy food counts if (item.specificFood && foodCounts.hasOwnProperty(item.specificFood)) { foodCounts[item.specificFood]++; } break; case 'junk': lives--; energy = Math.max(0, energy - 2); LK.getSound('buzz').play(); vibrateDevice(); flashScreen(0xFF4500); playerFeedback(0xFF4500, 100, false); break; case 'fake': energy = Math.max(0, energy - 2); LK.getSound('buzz').play(); vibrateDevice(); flashScreen(0xFFD700); playerFeedback(0xFFD700, 100, false); break; case 'water': energy = Math.min(30, energy + 3); LK.setScore(LK.getScore() + 3); LK.getSound('powerup').play(); flashScreen(0x00BFFF); playerFeedback(0x00BFFF, 150, true); // Track water bottle counts foodCounts['waterBottle']++; break; case 'anxiety': energy = Math.max(0, energy - 5); LK.getSound('explosion').play(); vibrateDevice(); flashScreen(0x8B008B); playerFeedback(0x8B008B, 300, false); break; } } // Initialize game function initializeGame() { gameStartTime = LK.ticks; // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 - 100; game.addChild(player); // Initialize UI initializeUI(); updateUI(); } // Game input handling game.down = function (x, y, obj) { var gamePos = game.toLocal({ x: x, y: y }); player.moveTo(gamePos.x); }; game.move = function (x, y, obj) { var gamePos = game.toLocal({ x: x, y: y }); player.moveTo(gamePos.x); }; // Main game update loop game.update = function () { // Don't update game logic if game is not active if (!gameActive) { return; } var currentTime = LK.ticks; var gameTime = (currentTime - gameStartTime) / 60; // Convert to seconds // Increase speed every 15 seconds if (gameTime - lastSpeedIncrease >= 15) { fallSpeed += 20 / 60; // Increase by 20px/s (double the previous increment) lastSpeedIncrease = gameTime; } // Activate anxiety bombs after 30 seconds if (gameTime >= 30 && !anxietyBombsActive) { anxietyBombsActive = true; lastAnxietySpawnTime = currentTime; // Only show expert message after the first 30 seconds of actual gameplay if (gameTime >= 30 && !expertMessageShown) { expertMessageShown = true; // Create full screen overlay for expert message var expertOverlay = LK.getAsset('basket', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); expertOverlay.tint = 0x000000; expertOverlay.alpha = 0.9; game.addChild(expertOverlay); // Show expert challenge message with attractive styling var expertText = new Text2('¡RETO EXPERTO!', { size: 150, fill: 0xFFD700, font: "Impact" }); expertText.anchor.set(0.5, 0.5); expertText.x = 2048 / 2; expertText.y = 2732 / 2 - 100; game.addChild(expertText); // Add subtitle text var subtitleText = new Text2('¡Los alimentos caen más rápido!', { size: 75, fill: 0xFF4500, font: "Impact" }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 2048 / 2; subtitleText.y = 2732 / 2 + 50; game.addChild(subtitleText); // Animate expert message with pulsing effect tween(expertText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(expertText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut }); } }); // Animate and remove message after 4 seconds tween(expertOverlay, { alpha: 0 }, { duration: 4000, onFinish: function onFinish() { expertOverlay.destroy(); } }); tween(expertText, { alpha: 0 }, { duration: 4000, onFinish: function onFinish() { expertText.destroy(); } }); tween(subtitleText, { alpha: 0 }, { duration: 4000, onFinish: function onFinish() { subtitleText.destroy(); } }); } } // Spawn items every 1.5 seconds if (currentTime - lastSpawnTime >= 90) { // 1.5 * 60 = 90 frames spawnFallingItem(); lastSpawnTime = currentTime; } // Spawn anxiety bombs every 40 seconds after activation if (anxietyBombsActive && currentTime - lastAnxietySpawnTime >= 2400) { // 40 * 60 = 2400 frames spawnAnxietyBomb(); lastAnxietySpawnTime = currentTime; } // Update falling items for (var i = fallingItems.length - 1; i >= 0; i--) { var item = fallingItems[i]; // Check collision with player if (item.intersects(player)) { handleItemCollision(item); item.destroy(); fallingItems.splice(i, 1); continue; } // Remove items that fall off screen if (item.y > 2732 + 350) { item.destroy(); fallingItems.splice(i, 1); } } // Update UI updateUI(); // Check game over conditions if (energy >= 30) { // Store final stats for victory storage.finalEnergy = energy; storage.finalTime = Math.floor(gameTime); storage.gameEndReason = 'victoria'; gameActive = false; // Stop game updates showVictoryMessage(); } else if (lives <= 0) { // Store final stats when lives reach 0 storage.finalEnergy = energy; storage.finalTime = Math.floor(gameTime); storage.gameEndReason = 'colapso'; gameActive = false; // Stop game updates showGameOver(); } else if (energy <= 0) { // Store final stats storage.finalEnergy = energy; storage.finalTime = Math.floor(gameTime); storage.gameEndReason = 'fatiga'; gameActive = false; // Stop game updates showCustomGameOver(); } }; // Get nutritional information for the most caught food function getNutritionalInfo() { var maxCount = 0; var mostCaughtFood = null; // Find the food with highest count for (var food in foodCounts) { if (foodCounts[food] > maxCount) { maxCount = foodCounts[food]; mostCaughtFood = food; } } if (!mostCaughtFood || maxCount === 0) { return { title: "¡Sigue practicando!", info: "Intenta atrapar más alimentos saludables la próxima vez." }; } var nutritionalData = { 'apple': { title: "Manzana (1 unidad mediana)", info: "✅ Rica en fibra (4g), mejora la digestión.\n✅ Aporta vitamina C (8% de la recomendación diaria).\n✅ Tiene antioxidantes que protegen las células.\n⚖️ Solo 95 kcal y 0 grasa." }, 'banana': { title: "Plátano (1 unidad mediana)", info: "✅ Rico en potasio (400–450 mg), ideal para los músculos.\n✅ Contiene vitamina B6, que ayuda al sistema nervioso.\n✅ Da energía rápida gracias a sus azúcares naturales." }, 'hardEgg': { title: "Huevo duro (1 unidad)", info: "✅ Aporta proteínas completas (6g por huevo).\n✅ Rico en colina, esencial para la memoria y el cerebro.\n✅ Contiene vitamina D y hierro.\n⚠️ Contiene algo de colesterol, pero no es dañino en jóvenes sanos." }, 'broccoli': { title: "Brócoli (1 taza cocida)", info: "✅ Altísimo en vitamina C y vitamina K.\n✅ Fuente de fibra y antioxidantes.\n✅ Tiene compuestos que ayudan a prevenir el cáncer." }, 'carrot': { title: "Zanahoria (1 mediana cruda)", info: "✅ Altísima en betacaroteno (vitamina A), buena para la vista.\n✅ Solo 25 kcal y con fibra.\n✅ Rica en antioxidantes, fortalece el sistema inmune." }, 'wholeBread': { title: "Pan integral (1 rebanada)", info: "✅ Buena fuente de fibra (2–3 g por porción).\n✅ Aporta carbohidratos complejos que dan energía duradera.\n✅ Tiene hierro y vitaminas del grupo B." }, 'waterBottle': { title: "Agua (1 vaso / 240ml)", info: "✅ Hidratación esencial para todo el cuerpo.\n✅ Regula la temperatura, transporta nutrientes y limpia toxinas.\n✅ 0 calorías, 0 azúcar, 100% necesaria." } }; return nutritionalData[mostCaughtFood] || { title: "¡Sigue practicando!", info: "Intenta atrapar más alimentos saludables la próxima vez." }; } // Show victory message when energy reaches 30 function showVictoryMessage() { var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60); // Create full screen overlay var overlay = LK.getAsset('basket', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); overlay.tint = 0x000000; overlay.alpha = 0.9; game.addChild(overlay); // Victory title var titleText = new Text2('¡FELICITACIONES!', { size: 120, fill: 0xFFD700, font: "Impact" }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; game.addChild(titleText); // Victory message var messageText = new Text2('¡Alcanzaste el nivel máximo de energía saludable!', { size: 70, fill: 0x32CD32, font: "Impact" }); messageText.anchor.set(0.5, 0.5); messageText.x = 2048 / 2; messageText.y = 600; game.addChild(messageText); // Additional message lines var message2Text = new Text2('Tu cuerpo y tu mente están listas para todo.', { size: 60, fill: 0x00BFFF, font: "Impact" }); message2Text.anchor.set(0.5, 0.5); message2Text.x = 2048 / 2; message2Text.y = 750; game.addChild(message2Text); var message3Text = new Text2('Elegiste bien, vivís mejor.', { size: 60, fill: 0xFF69B4, font: "Impact" }); message3Text.anchor.set(0.5, 0.5); message3Text.x = 2048 / 2; message3Text.y = 900; game.addChild(message3Text); // Score section var scoreText = new Text2('Puntuación Final: ' + LK.getScore(), { size: 70, fill: 0xFFD700, font: "Impact" }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 2048 / 2; scoreText.y = 1100; game.addChild(scoreText); // Time played section var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', { size: 60, fill: 0xFFFFFF, font: "Impact" }); timeText.anchor.set(0.5, 0.5); timeText.x = 2048 / 2; timeText.y = 1200; game.addChild(timeText); // Create animated restart button var restartButton = LK.getAsset('restartButton', { width: 500, height: 100, color: 0x32CD32, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); restartButton.x = 2048 / 2; restartButton.y = 1400; game.addChild(restartButton); var restartText = new Text2('Jugar de nuevo', { size: 65, fill: 0xFFFFFF, font: "Impact" }); restartText.anchor.set(0.5, 0.5); restartText.x = 2048 / 2; restartText.y = 1400; game.addChild(restartText); // Animate button with pulsing effect function animateVictoryRestartButton() { tween(restartButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: animateVictoryRestartButton }); } }); tween(restartText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut }); } }); } animateVictoryRestartButton(); // Add click handler for restart restartButton.down = function () { startCountdown(); }; restartText.down = function () { startCountdown(); }; } // Show game over message when lives reach 0 function showGameOver() { var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60); // Create full screen overlay var overlay = LK.getAsset('basket', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); overlay.tint = 0x000000; overlay.alpha = 0.9; game.addChild(overlay); // Game Over title var gameOverText = new Text2('GAME OVER', { size: 150, fill: 0xFF0000, font: "Impact" }); gameOverText.anchor.set(0.5, 0.5); gameOverText.x = 2048 / 2; gameOverText.y = 600; game.addChild(gameOverText); // Score section var scoreText = new Text2('Puntuación Final: ' + LK.getScore(), { size: 70, fill: 0xFFD700, font: "Impact" }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 2048 / 2; scoreText.y = 800; game.addChild(scoreText); // Time played section var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', { size: 60, fill: 0xFFFFFF, font: "Impact" }); timeText.anchor.set(0.5, 0.5); timeText.x = 2048 / 2; timeText.y = 900; game.addChild(timeText); // Add nutritional information section var nutritionalInfo = getNutritionalInfo(); var nutritionTitleText = new Text2(nutritionalInfo.title, { size: 60, fill: 0xFFD700, font: "Impact" }); nutritionTitleText.anchor.set(0.5, 0.5); nutritionTitleText.x = 2048 / 2; nutritionTitleText.y = 1050; game.addChild(nutritionTitleText); var nutritionInfoText = new Text2(nutritionalInfo.info, { size: 40, fill: 0xFFFFFF, font: "Impact" }); nutritionInfoText.anchor.set(0.5, 0); nutritionInfoText.x = 2048 / 2; nutritionInfoText.y = 1100; game.addChild(nutritionInfoText); // Create animated restart button var restartButton = LK.getAsset('restartButton', { width: 500, height: 100, color: 0x32CD32, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); restartButton.x = 2048 / 2; restartButton.y = 1450; game.addChild(restartButton); var restartText = new Text2('Jugar de nuevo', { size: 65, fill: 0xFFFFFF, font: "Impact" }); restartText.anchor.set(0.5, 0.5); restartText.x = 2048 / 2; restartText.y = 1450; game.addChild(restartText); // Animate button with pulsing effect function animateGameOverRestartButton() { tween(restartButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: animateGameOverRestartButton }); } }); tween(restartText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut }); } }); } animateGameOverRestartButton(); // Add click handler for restart restartButton.down = function () { startCountdown(); }; restartText.down = function () { startCountdown(); }; } // Show custom game over message for energy depletion function showCustomGameOver() { var finalEnergy = storage.finalEnergy || energy; var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60); var reason = storage.gameEndReason || 'fatiga'; var message = ''; if (finalEnergy >= 25) { message = '¡NutriMáster!'; } else if (finalEnergy >= 15) { message = '¡Buen cazador de nutrientes!'; } else { message = 'Sigue practicando, revisa tus elecciones'; } // Create full screen overlay var overlay = LK.getAsset('basket', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); overlay.tint = 0x000000; overlay.alpha = 0.9; game.addChild(overlay); // Title var titleText = new Text2('PANTALLA FINAL', { size: 100, fill: 0xFFD700, font: "Impact" }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; game.addChild(titleText); // Score section var scoreText = new Text2('Puntuación: ' + LK.getScore(), { size: 70, fill: 0x32CD32, font: "Impact" }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 2048 / 2; scoreText.y = 600; game.addChild(scoreText); // Time played section var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', { size: 70, fill: 0x00BFFF, font: "Impact" }); timeText.anchor.set(0.5, 0.5); timeText.x = 2048 / 2; timeText.y = 750; game.addChild(timeText); // Message section with color based on performance var messageColor = 0xFFFFFF; if (finalEnergy >= 25) { messageColor = 0xFFD700; // Gold for NutriMaster } else if (finalEnergy >= 15) { messageColor = 0x32CD32; // Green for good hunter } else { messageColor = 0xFF4500; // Orange for keep practicing } var messageText = new Text2(message, { size: 80, fill: messageColor, font: "Impact" }); messageText.anchor.set(0.5, 0.5); messageText.x = 2048 / 2; messageText.y = 950; game.addChild(messageText); // Add nutritional information section var nutritionalInfo = getNutritionalInfo(); var nutritionTitleText = new Text2(nutritionalInfo.title, { size: 60, fill: 0xFFD700, font: "Impact" }); nutritionTitleText.anchor.set(0.5, 0.5); nutritionTitleText.x = 2048 / 2; nutritionTitleText.y = 1100; game.addChild(nutritionTitleText); var nutritionInfoText = new Text2(nutritionalInfo.info, { size: 40, fill: 0xFFFFFF, font: "Impact" }); nutritionInfoText.anchor.set(0.5, 0); nutritionInfoText.x = 2048 / 2; nutritionInfoText.y = 1150; game.addChild(nutritionInfoText); // Create animated restart button var restartButton = LK.getAsset('restartButton', { width: 500, height: 100, color: 0x32CD32, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); restartButton.x = 2048 / 2; restartButton.y = 1500; game.addChild(restartButton); var restartText = new Text2('Jugar de nuevo', { size: 65, fill: 0xFFFFFF, font: "Impact" }); restartText.anchor.set(0.5, 0.5); restartText.x = 2048 / 2; restartText.y = 1500; game.addChild(restartText); // Animate button with pulsing effect function animateRestartButton() { tween(restartButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: animateRestartButton }); } }); tween(restartText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(restartText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut }); } }); } animateRestartButton(); // Add click handler for restart restartButton.down = function () { startCountdown(); }; restartText.down = function () { startCountdown(); }; } // Start countdown and restart game function startCountdown() { // Clear all game objects for (var i = fallingItems.length - 1; i >= 0; i--) { fallingItems[i].destroy(); } fallingItems = []; game.removeChildren(); // Reset all game variables energy = 15; lives = 3; fallSpeed = 350 / 60; lastSpeedIncrease = 0; lastWaterSpawn = 0; gameStartTime = 0; foodsCaught = 0; anxietyBombsActive = false; lastSpawnTime = 0; lastAnxietySpawnTime = 0; expertMessageShown = false; gameActive = true; // Reactivate game LK.setScore(0); // Clear GUI elements to reset them properly LK.gui.topLeft.removeChildren(); LK.gui.topRight.removeChildren(); LK.gui.top.removeChildren(); // Reset food counts foodCounts = { 'apple': 0, 'banana': 0, 'hardEgg': 0, 'broccoli': 0, 'carrot': 0, 'wholeBread': 0, 'waterBottle': 0 }; // Show countdown var countdownNumbers = [3, 2, 1]; var currentCount = 0; function showCountdownNumber() { if (currentCount < countdownNumbers.length) { var countText = new Text2(countdownNumbers[currentCount].toString(), { size: 250, fill: 0xFFFF00, font: "Impact" }); countText.anchor.set(0.5, 0.5); countText.x = 2048 / 2; countText.y = 2732 / 2; game.addChild(countText); // Animate countdown number tween(countText, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { countText.destroy(); currentCount++; if (currentCount < countdownNumbers.length) { showCountdownNumber(); } else { // Start new game initializeGame(); // Force UI update after initialization to show correct values updateUI(); } } }); } } showCountdownNumber(); } // Initialize the game initializeGame(); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var FallingItem = Container.expand(function (type, specificFood) {
var self = Container.call(this);
self.type = type;
self.specificFood = specificFood;
// Set different speeds based on type and add randomness
if (type === 'anxiety') {
self.speed = fallSpeed * 1.5; // Anxiety bombs fall faster
} else if (type === 'water') {
self.speed = fallSpeed * 0.8; // Water bottles fall slower
} else {
// Food items have variable speeds between 1.2x and 2.0x base speed (much faster)
var speedMultiplier = 1.2 + Math.random() * 0.8;
// Increase speed significantly during expert mode
if (anxietyBombsActive) {
speedMultiplier *= 2.2; // Make items fall 120% faster in expert mode
}
self.speed = fallSpeed * speedMultiplier;
}
var assetName = specificFood || 'waterBottle';
if (type === 'water') assetName = 'waterBottle';else if (type === 'anxiety') assetName = 'anxietyBomb';
var graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerBody = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
var basket = self.attachAsset('basket', {
anchorX: 0.5,
anchorY: 0.5,
y: -110
});
self.speed = 8;
self.targetX = self.x;
self.update = function () {
var dx = self.targetX - self.x;
if (Math.abs(dx) > 5) {
self.x += dx * 0.15;
} else {
self.x = self.targetX;
}
// Keep player within bounds
if (self.x < 150) self.x = 150;
if (self.x > 2048 - 150) self.x = 2048 - 150;
};
self.moveTo = function (targetX) {
self.targetX = targetX;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Fake Healthy Foods
// Junk Foods
// Healthy Foods - Proteins & Grains
// Healthy Foods - Vegetables
// Healthy Foods - Fruits
// Game variables
// Healthy foods
// Junk foods
// Fake healthy foods
// Game elements
var player;
var fallingItems = [];
var energy = 15;
var lives = 3;
var fallSpeed = 350 / 60; // 350px/s converted to pixels per frame (much faster)
var lastSpeedIncrease = 0;
var lastWaterSpawn = 0;
var gameStartTime = 0;
var foodsCaught = 0;
var anxietyBombsActive = false;
var lastSpawnTime = 0;
var lastAnxietySpawnTime = 0;
var expertMessageShown = false;
var gameActive = true; // Track if game is active
// Food tracking variables
var foodCounts = {
'apple': 0,
'banana': 0,
'hardEgg': 0,
'broccoli': 0,
'carrot': 0,
'wholeBread': 0,
'waterBottle': 0
};
// UI elements
var livesText;
var scoreText;
var energyText;
var energyBarBg;
var energyBarFill;
// Initialize UI
function initializeUI() {
// Energy text with larger size
energyText = new Text2('Energía: 15/30', {
size: 72,
fill: 0xFFFFFF,
font: "Impact"
});
energyText.anchor.set(0, 0);
LK.gui.topLeft.addChild(energyText);
energyText.x = 150;
energyText.y = 20;
// Energy bar background
energyBarBg = LK.getAsset('energyBarBg', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(energyBarBg);
energyBarBg.x = 150;
energyBarBg.y = 100;
// Energy bar fill
energyBarFill = LK.getAsset('energyBarFill', {
anchorX: 0,
anchorY: 0
});
LK.gui.topLeft.addChild(energyBarFill);
energyBarFill.x = 150;
energyBarFill.y = 100;
// Lives text with larger size
livesText = new Text2('Vidas: 3', {
size: 84,
fill: 0xFF0000,
font: "Impact"
});
livesText.anchor.set(1, 0);
LK.gui.topRight.addChild(livesText);
livesText.x = -20;
livesText.y = 20;
// Score text with larger size
scoreText = new Text2('Puntuación: 0', {
size: 78,
fill: 0xFFFFFF,
font: "Impact"
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 160;
}
// Update UI
function updateUI() {
energyText.setText('Energía: ' + energy + '/30');
livesText.setText('Vidas: ' + lives);
scoreText.setText('Puntuación: ' + LK.getScore());
// Update energy bar fill based on current energy (0-30 range)
var energyPercentage = energy / 30;
energyBarFill.width = 400 * energyPercentage;
// Change energy bar color based on energy level
if (energy >= 20) {
energyBarFill.tint = 0x00ff00; // Green for high energy
} else if (energy >= 10) {
energyBarFill.tint = 0xffff00; // Yellow for medium energy
} else {
energyBarFill.tint = 0xff0000; // Red for low energy
}
}
// Flash effect
function flashScreen(color) {
LK.effects.flashScreen(color, 300);
}
// Food arrays for variety - exactly 10 sprite types + 2 fake healthy
var healthyFoods = ['banana', 'apple', 'carrot', 'broccoli', 'wholeBread', 'hardEgg'];
var junkFoods = ['soda', 'chips', 'candy', 'burger'];
var fakeFoods = ['cerealBar', 'flavoredYogurt'];
// Spawn falling item
function spawnFallingItem() {
var type = 'healthy';
var specificFood = null;
var rand = Math.random();
if (foodsCaught > 0 && foodsCaught % 20 === 0 && lastWaterSpawn !== foodsCaught) {
type = 'water';
lastWaterSpawn = foodsCaught;
} else if (rand < 0.3) {
type = 'junk';
specificFood = junkFoods[Math.floor(Math.random() * junkFoods.length)];
} else if (rand < 0.5) {
type = 'fake';
specificFood = fakeFoods[Math.floor(Math.random() * fakeFoods.length)];
} else {
type = 'healthy';
specificFood = healthyFoods[Math.floor(Math.random() * healthyFoods.length)];
}
var item = new FallingItem(type, specificFood);
item.x = Math.random() * (2048 - 350) + 175;
item.y = -175;
fallingItems.push(item);
game.addChild(item);
}
// Spawn anxiety bomb
function spawnAnxietyBomb() {
var item = new FallingItem('anxiety', null);
item.x = Math.random() * (2048 - 350) + 175;
item.y = -175;
fallingItems.push(item);
game.addChild(item);
}
// Helper function for player visual feedback
function playerFeedback(color, duration, scaleEffect) {
if (scaleEffect) {
tween(player, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: duration,
onFinish: function onFinish() {
tween(player, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: duration
});
}
});
} else {
tween(player, {
tint: color
}, {
duration: duration,
onFinish: function onFinish() {
tween(player, {
tint: 0xFFFFFF
}, {
duration: duration
});
}
});
}
}
// Helper function for vibration feedback
function vibrateDevice() {
if (navigator && navigator.vibrate) {
navigator.vibrate(100);
}
}
// Handle item collision
function handleItemCollision(item) {
switch (item.type) {
case 'healthy':
energy = Math.min(30, energy + 1);
LK.setScore(LK.getScore() + 1);
LK.getSound('ping').play();
flashScreen(0x32CD32);
playerFeedback(0x32CD32, 100, false);
foodsCaught++;
// Track healthy food counts
if (item.specificFood && foodCounts.hasOwnProperty(item.specificFood)) {
foodCounts[item.specificFood]++;
}
break;
case 'junk':
lives--;
energy = Math.max(0, energy - 2);
LK.getSound('buzz').play();
vibrateDevice();
flashScreen(0xFF4500);
playerFeedback(0xFF4500, 100, false);
break;
case 'fake':
energy = Math.max(0, energy - 2);
LK.getSound('buzz').play();
vibrateDevice();
flashScreen(0xFFD700);
playerFeedback(0xFFD700, 100, false);
break;
case 'water':
energy = Math.min(30, energy + 3);
LK.setScore(LK.getScore() + 3);
LK.getSound('powerup').play();
flashScreen(0x00BFFF);
playerFeedback(0x00BFFF, 150, true);
// Track water bottle counts
foodCounts['waterBottle']++;
break;
case 'anxiety':
energy = Math.max(0, energy - 5);
LK.getSound('explosion').play();
vibrateDevice();
flashScreen(0x8B008B);
playerFeedback(0x8B008B, 300, false);
break;
}
}
// Initialize game
function initializeGame() {
gameStartTime = LK.ticks;
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 100;
game.addChild(player);
// Initialize UI
initializeUI();
updateUI();
}
// Game input handling
game.down = function (x, y, obj) {
var gamePos = game.toLocal({
x: x,
y: y
});
player.moveTo(gamePos.x);
};
game.move = function (x, y, obj) {
var gamePos = game.toLocal({
x: x,
y: y
});
player.moveTo(gamePos.x);
};
// Main game update loop
game.update = function () {
// Don't update game logic if game is not active
if (!gameActive) {
return;
}
var currentTime = LK.ticks;
var gameTime = (currentTime - gameStartTime) / 60; // Convert to seconds
// Increase speed every 15 seconds
if (gameTime - lastSpeedIncrease >= 15) {
fallSpeed += 20 / 60; // Increase by 20px/s (double the previous increment)
lastSpeedIncrease = gameTime;
}
// Activate anxiety bombs after 30 seconds
if (gameTime >= 30 && !anxietyBombsActive) {
anxietyBombsActive = true;
lastAnxietySpawnTime = currentTime;
// Only show expert message after the first 30 seconds of actual gameplay
if (gameTime >= 30 && !expertMessageShown) {
expertMessageShown = true;
// Create full screen overlay for expert message
var expertOverlay = LK.getAsset('basket', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
expertOverlay.tint = 0x000000;
expertOverlay.alpha = 0.9;
game.addChild(expertOverlay);
// Show expert challenge message with attractive styling
var expertText = new Text2('¡RETO EXPERTO!', {
size: 150,
fill: 0xFFD700,
font: "Impact"
});
expertText.anchor.set(0.5, 0.5);
expertText.x = 2048 / 2;
expertText.y = 2732 / 2 - 100;
game.addChild(expertText);
// Add subtitle text
var subtitleText = new Text2('¡Los alimentos caen más rápido!', {
size: 75,
fill: 0xFF4500,
font: "Impact"
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 2048 / 2;
subtitleText.y = 2732 / 2 + 50;
game.addChild(subtitleText);
// Animate expert message with pulsing effect
tween(expertText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(expertText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
// Animate and remove message after 4 seconds
tween(expertOverlay, {
alpha: 0
}, {
duration: 4000,
onFinish: function onFinish() {
expertOverlay.destroy();
}
});
tween(expertText, {
alpha: 0
}, {
duration: 4000,
onFinish: function onFinish() {
expertText.destroy();
}
});
tween(subtitleText, {
alpha: 0
}, {
duration: 4000,
onFinish: function onFinish() {
subtitleText.destroy();
}
});
}
}
// Spawn items every 1.5 seconds
if (currentTime - lastSpawnTime >= 90) {
// 1.5 * 60 = 90 frames
spawnFallingItem();
lastSpawnTime = currentTime;
}
// Spawn anxiety bombs every 40 seconds after activation
if (anxietyBombsActive && currentTime - lastAnxietySpawnTime >= 2400) {
// 40 * 60 = 2400 frames
spawnAnxietyBomb();
lastAnxietySpawnTime = currentTime;
}
// Update falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
var item = fallingItems[i];
// Check collision with player
if (item.intersects(player)) {
handleItemCollision(item);
item.destroy();
fallingItems.splice(i, 1);
continue;
}
// Remove items that fall off screen
if (item.y > 2732 + 350) {
item.destroy();
fallingItems.splice(i, 1);
}
}
// Update UI
updateUI();
// Check game over conditions
if (energy >= 30) {
// Store final stats for victory
storage.finalEnergy = energy;
storage.finalTime = Math.floor(gameTime);
storage.gameEndReason = 'victoria';
gameActive = false; // Stop game updates
showVictoryMessage();
} else if (lives <= 0) {
// Store final stats when lives reach 0
storage.finalEnergy = energy;
storage.finalTime = Math.floor(gameTime);
storage.gameEndReason = 'colapso';
gameActive = false; // Stop game updates
showGameOver();
} else if (energy <= 0) {
// Store final stats
storage.finalEnergy = energy;
storage.finalTime = Math.floor(gameTime);
storage.gameEndReason = 'fatiga';
gameActive = false; // Stop game updates
showCustomGameOver();
}
};
// Get nutritional information for the most caught food
function getNutritionalInfo() {
var maxCount = 0;
var mostCaughtFood = null;
// Find the food with highest count
for (var food in foodCounts) {
if (foodCounts[food] > maxCount) {
maxCount = foodCounts[food];
mostCaughtFood = food;
}
}
if (!mostCaughtFood || maxCount === 0) {
return {
title: "¡Sigue practicando!",
info: "Intenta atrapar más alimentos saludables la próxima vez."
};
}
var nutritionalData = {
'apple': {
title: "Manzana (1 unidad mediana)",
info: "✅ Rica en fibra (4g), mejora la digestión.\n✅ Aporta vitamina C (8% de la recomendación diaria).\n✅ Tiene antioxidantes que protegen las células.\n⚖️ Solo 95 kcal y 0 grasa."
},
'banana': {
title: "Plátano (1 unidad mediana)",
info: "✅ Rico en potasio (400–450 mg), ideal para los músculos.\n✅ Contiene vitamina B6, que ayuda al sistema nervioso.\n✅ Da energía rápida gracias a sus azúcares naturales."
},
'hardEgg': {
title: "Huevo duro (1 unidad)",
info: "✅ Aporta proteínas completas (6g por huevo).\n✅ Rico en colina, esencial para la memoria y el cerebro.\n✅ Contiene vitamina D y hierro.\n⚠️ Contiene algo de colesterol, pero no es dañino en jóvenes sanos."
},
'broccoli': {
title: "Brócoli (1 taza cocida)",
info: "✅ Altísimo en vitamina C y vitamina K.\n✅ Fuente de fibra y antioxidantes.\n✅ Tiene compuestos que ayudan a prevenir el cáncer."
},
'carrot': {
title: "Zanahoria (1 mediana cruda)",
info: "✅ Altísima en betacaroteno (vitamina A), buena para la vista.\n✅ Solo 25 kcal y con fibra.\n✅ Rica en antioxidantes, fortalece el sistema inmune."
},
'wholeBread': {
title: "Pan integral (1 rebanada)",
info: "✅ Buena fuente de fibra (2–3 g por porción).\n✅ Aporta carbohidratos complejos que dan energía duradera.\n✅ Tiene hierro y vitaminas del grupo B."
},
'waterBottle': {
title: "Agua (1 vaso / 240ml)",
info: "✅ Hidratación esencial para todo el cuerpo.\n✅ Regula la temperatura, transporta nutrientes y limpia toxinas.\n✅ 0 calorías, 0 azúcar, 100% necesaria."
}
};
return nutritionalData[mostCaughtFood] || {
title: "¡Sigue practicando!",
info: "Intenta atrapar más alimentos saludables la próxima vez."
};
}
// Show victory message when energy reaches 30
function showVictoryMessage() {
var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60);
// Create full screen overlay
var overlay = LK.getAsset('basket', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
overlay.tint = 0x000000;
overlay.alpha = 0.9;
game.addChild(overlay);
// Victory title
var titleText = new Text2('¡FELICITACIONES!', {
size: 120,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 400;
game.addChild(titleText);
// Victory message
var messageText = new Text2('¡Alcanzaste el nivel máximo de energía saludable!', {
size: 70,
fill: 0x32CD32,
font: "Impact"
});
messageText.anchor.set(0.5, 0.5);
messageText.x = 2048 / 2;
messageText.y = 600;
game.addChild(messageText);
// Additional message lines
var message2Text = new Text2('Tu cuerpo y tu mente están listas para todo.', {
size: 60,
fill: 0x00BFFF,
font: "Impact"
});
message2Text.anchor.set(0.5, 0.5);
message2Text.x = 2048 / 2;
message2Text.y = 750;
game.addChild(message2Text);
var message3Text = new Text2('Elegiste bien, vivís mejor.', {
size: 60,
fill: 0xFF69B4,
font: "Impact"
});
message3Text.anchor.set(0.5, 0.5);
message3Text.x = 2048 / 2;
message3Text.y = 900;
game.addChild(message3Text);
// Score section
var scoreText = new Text2('Puntuación Final: ' + LK.getScore(), {
size: 70,
fill: 0xFFD700,
font: "Impact"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 2048 / 2;
scoreText.y = 1100;
game.addChild(scoreText);
// Time played section
var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
timeText.anchor.set(0.5, 0.5);
timeText.x = 2048 / 2;
timeText.y = 1200;
game.addChild(timeText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 500,
height: 100,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1400;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 65,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1400;
game.addChild(restartText);
// Animate button with pulsing effect
function animateVictoryRestartButton() {
tween(restartButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: animateVictoryRestartButton
});
}
});
tween(restartText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
animateVictoryRestartButton();
// Add click handler for restart
restartButton.down = function () {
startCountdown();
};
restartText.down = function () {
startCountdown();
};
}
// Show game over message when lives reach 0
function showGameOver() {
var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60);
// Create full screen overlay
var overlay = LK.getAsset('basket', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
overlay.tint = 0x000000;
overlay.alpha = 0.9;
game.addChild(overlay);
// Game Over title
var gameOverText = new Text2('GAME OVER', {
size: 150,
fill: 0xFF0000,
font: "Impact"
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.x = 2048 / 2;
gameOverText.y = 600;
game.addChild(gameOverText);
// Score section
var scoreText = new Text2('Puntuación Final: ' + LK.getScore(), {
size: 70,
fill: 0xFFD700,
font: "Impact"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 2048 / 2;
scoreText.y = 800;
game.addChild(scoreText);
// Time played section
var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
timeText.anchor.set(0.5, 0.5);
timeText.x = 2048 / 2;
timeText.y = 900;
game.addChild(timeText);
// Add nutritional information section
var nutritionalInfo = getNutritionalInfo();
var nutritionTitleText = new Text2(nutritionalInfo.title, {
size: 60,
fill: 0xFFD700,
font: "Impact"
});
nutritionTitleText.anchor.set(0.5, 0.5);
nutritionTitleText.x = 2048 / 2;
nutritionTitleText.y = 1050;
game.addChild(nutritionTitleText);
var nutritionInfoText = new Text2(nutritionalInfo.info, {
size: 40,
fill: 0xFFFFFF,
font: "Impact"
});
nutritionInfoText.anchor.set(0.5, 0);
nutritionInfoText.x = 2048 / 2;
nutritionInfoText.y = 1100;
game.addChild(nutritionInfoText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 500,
height: 100,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1450;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 65,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1450;
game.addChild(restartText);
// Animate button with pulsing effect
function animateGameOverRestartButton() {
tween(restartButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: animateGameOverRestartButton
});
}
});
tween(restartText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
animateGameOverRestartButton();
// Add click handler for restart
restartButton.down = function () {
startCountdown();
};
restartText.down = function () {
startCountdown();
};
}
// Show custom game over message for energy depletion
function showCustomGameOver() {
var finalEnergy = storage.finalEnergy || energy;
var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60);
var reason = storage.gameEndReason || 'fatiga';
var message = '';
if (finalEnergy >= 25) {
message = '¡NutriMáster!';
} else if (finalEnergy >= 15) {
message = '¡Buen cazador de nutrientes!';
} else {
message = 'Sigue practicando, revisa tus elecciones';
}
// Create full screen overlay
var overlay = LK.getAsset('basket', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
overlay.tint = 0x000000;
overlay.alpha = 0.9;
game.addChild(overlay);
// Title
var titleText = new Text2('PANTALLA FINAL', {
size: 100,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 400;
game.addChild(titleText);
// Score section
var scoreText = new Text2('Puntuación: ' + LK.getScore(), {
size: 70,
fill: 0x32CD32,
font: "Impact"
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 2048 / 2;
scoreText.y = 600;
game.addChild(scoreText);
// Time played section
var timeText = new Text2('Tiempo jugado: ' + finalTime + ' segundos', {
size: 70,
fill: 0x00BFFF,
font: "Impact"
});
timeText.anchor.set(0.5, 0.5);
timeText.x = 2048 / 2;
timeText.y = 750;
game.addChild(timeText);
// Message section with color based on performance
var messageColor = 0xFFFFFF;
if (finalEnergy >= 25) {
messageColor = 0xFFD700; // Gold for NutriMaster
} else if (finalEnergy >= 15) {
messageColor = 0x32CD32; // Green for good hunter
} else {
messageColor = 0xFF4500; // Orange for keep practicing
}
var messageText = new Text2(message, {
size: 80,
fill: messageColor,
font: "Impact"
});
messageText.anchor.set(0.5, 0.5);
messageText.x = 2048 / 2;
messageText.y = 950;
game.addChild(messageText);
// Add nutritional information section
var nutritionalInfo = getNutritionalInfo();
var nutritionTitleText = new Text2(nutritionalInfo.title, {
size: 60,
fill: 0xFFD700,
font: "Impact"
});
nutritionTitleText.anchor.set(0.5, 0.5);
nutritionTitleText.x = 2048 / 2;
nutritionTitleText.y = 1100;
game.addChild(nutritionTitleText);
var nutritionInfoText = new Text2(nutritionalInfo.info, {
size: 40,
fill: 0xFFFFFF,
font: "Impact"
});
nutritionInfoText.anchor.set(0.5, 0);
nutritionInfoText.x = 2048 / 2;
nutritionInfoText.y = 1150;
game.addChild(nutritionInfoText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 500,
height: 100,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1500;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 65,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1500;
game.addChild(restartText);
// Animate button with pulsing effect
function animateRestartButton() {
tween(restartButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: animateRestartButton
});
}
});
tween(restartText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(restartText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
animateRestartButton();
// Add click handler for restart
restartButton.down = function () {
startCountdown();
};
restartText.down = function () {
startCountdown();
};
}
// Start countdown and restart game
function startCountdown() {
// Clear all game objects
for (var i = fallingItems.length - 1; i >= 0; i--) {
fallingItems[i].destroy();
}
fallingItems = [];
game.removeChildren();
// Reset all game variables
energy = 15;
lives = 3;
fallSpeed = 350 / 60;
lastSpeedIncrease = 0;
lastWaterSpawn = 0;
gameStartTime = 0;
foodsCaught = 0;
anxietyBombsActive = false;
lastSpawnTime = 0;
lastAnxietySpawnTime = 0;
expertMessageShown = false;
gameActive = true; // Reactivate game
LK.setScore(0);
// Clear GUI elements to reset them properly
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
LK.gui.top.removeChildren();
// Reset food counts
foodCounts = {
'apple': 0,
'banana': 0,
'hardEgg': 0,
'broccoli': 0,
'carrot': 0,
'wholeBread': 0,
'waterBottle': 0
};
// Show countdown
var countdownNumbers = [3, 2, 1];
var currentCount = 0;
function showCountdownNumber() {
if (currentCount < countdownNumbers.length) {
var countText = new Text2(countdownNumbers[currentCount].toString(), {
size: 250,
fill: 0xFFFF00,
font: "Impact"
});
countText.anchor.set(0.5, 0.5);
countText.x = 2048 / 2;
countText.y = 2732 / 2;
game.addChild(countText);
// Animate countdown number
tween(countText, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
countText.destroy();
currentCount++;
if (currentCount < countdownNumbers.length) {
showCountdownNumber();
} else {
// Start new game
initializeGame();
// Force UI update after initialization to show correct values
updateUI();
}
}
});
}
}
showCountdownNumber();
}
// Initialize the game
initializeGame();
;