User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1619
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1610
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1601
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1601
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1601
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1601
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1592
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1583
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1574
User prompt
Haz que para cada usuario se reinicie todo el progreso de las misiones, los nutripoints y la tienda. Que cada usuario empieze desde 0 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1539
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1539
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1539
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1530
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1530
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1530
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return;' Line Number: 1530
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var FAQScreen = Container.expand(function () {
var self = Container.call(this);
// Create background
var bg = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
bg.tint = 0xF8F9FA;
self.addChild(bg);
// Create scrollable container for FAQ content
var scrollContainer = new Container();
self.addChild(scrollContainer);
// Title
var titleText = new Text2('PREGUNTAS FRECUENTES', {
size: 80,
fill: 0x2C3E50,
font: "Impact"
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 150;
scrollContainer.addChild(titleText);
self.faqContainer = new Container();
self.faqContainer.x = 0;
self.faqContainer.y = 300;
scrollContainer.addChild(self.faqContainer);
// FAQ state tracking
self.openFAQIndex = -1; // Track which FAQ is currently open
self.faqItems = []; // Store FAQ item references
// Create FAQ items
self.createFAQItems = function () {
self.faqContainer.removeChildren();
self.faqItems = [];
var currentY = 0;
var itemSpacing = 20;
for (var i = 0; i < faqData.length; i++) {
var faq = faqData[i];
var isOpen = self.openFAQIndex === i;
// Question container with shadow effect
var questionContainer = new Container();
questionContainer.y = currentY;
self.faqContainer.addChild(questionContainer);
// Question background with rounded appearance
var questionBg = LK.getAsset('restartButton', {
width: 1800,
height: 160,
anchorX: 0.5,
anchorY: 0
});
questionBg.tint = isOpen ? 0x3498DB : 0x34495E;
questionBg.x = 2048 / 2;
questionBg.y = 0;
questionContainer.addChild(questionBg);
// Expand/collapse icon
var iconText = new Text2(isOpen ? '⊖' : '⊕', {
size: 70,
fill: 0xFFFFFF,
font: "Impact"
});
iconText.anchor.set(0, 0.5);
iconText.x = 250;
iconText.y = 80;
questionContainer.addChild(iconText);
// Question text
var questionText = new Text2(faq.question, {
size: 58,
fill: 0xFFFFFF,
font: "Impact"
});
questionText.anchor.set(0, 0.5);
questionText.x = 350;
questionText.y = 80;
questionContainer.addChild(questionText);
// Answer container (initially hidden if not open)
var answerContainer = new Container();
answerContainer.y = 170;
answerContainer.alpha = isOpen ? 1 : 0;
answerContainer.visible = isOpen;
questionContainer.addChild(answerContainer);
// Answer background
var answerBg = LK.getAsset('restartButton', {
width: 1700,
height: isOpen ? 240 : 0,
anchorX: 0.5,
anchorY: 0
});
answerBg.tint = 0xECF0F1;
answerBg.x = 2048 / 2;
answerBg.y = 0;
answerContainer.addChild(answerBg);
// Answer text with proper wrapping
var answerText = new Text2(faq.answer, {
size: 50,
fill: 0x2C3E50,
font: "Impact",
wordWrap: true,
wordWrapWidth: 1600
});
answerText.anchor.set(0.5, 0);
answerText.x = 2048 / 2;
answerText.y = 30;
answerContainer.addChild(answerText);
// Store references
var faqItem = {
index: i,
questionContainer: questionContainer,
questionBg: questionBg,
iconText: iconText,
answerContainer: answerContainer,
answerBg: answerBg,
isOpen: isOpen
};
self.faqItems.push(faqItem);
// Add click handlers with closure
(function (itemIndex) {
questionBg.down = function () {
self.toggleFAQ(itemIndex);
};
iconText.down = function () {
self.toggleFAQ(itemIndex);
};
questionText.down = function () {
self.toggleFAQ(itemIndex);
};
})(i);
// Calculate next Y position
currentY += 160 + itemSpacing;
if (isOpen) {
currentY += 240 + itemSpacing;
}
}
};
// Toggle FAQ open/close
self.toggleFAQ = function (index) {
if (index === self.openFAQIndex) {
// Close currently open FAQ
self.closeFAQ(index);
self.openFAQIndex = -1;
} else {
// Close currently open FAQ if any
if (self.openFAQIndex >= 0) {
self.closeFAQ(self.openFAQIndex);
}
// Open new FAQ
self.openFAQ(index);
self.openFAQIndex = index;
}
};
// Open FAQ with animation
self.openFAQ = function (index) {
var item = self.faqItems[index];
if (!item) return;
// Update icon and background color
item.iconText.setText('⊖');
tween(item.questionBg, {
tint: 0x3498DB
}, {
duration: 200
});
// Show and animate answer container
item.answerContainer.visible = true;
item.answerContainer.alpha = 0;
// Animate answer background height
tween(item.answerBg, {
height: 240
}, {
duration: 300,
easing: tween.easeOut
});
// Fade in answer container
tween(item.answerContainer, {
alpha: 1
}, {
duration: 250,
onFinish: function onFinish() {
// Recreate all items to adjust positions
LK.setTimeout(function () {
self.createFAQItems();
}, 50);
}
});
};
// Close FAQ with animation
self.closeFAQ = function (index) {
var item = self.faqItems[index];
if (!item) return;
// Update icon and background color
item.iconText.setText('⊕');
tween(item.questionBg, {
tint: 0x34495E
}, {
duration: 200
});
// Fade out and hide answer container
tween(item.answerContainer, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
item.answerContainer.visible = false;
// Animate answer background height to 0
tween(item.answerBg, {
height: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
// Recreate all items to adjust positions
LK.setTimeout(function () {
self.createFAQItems();
}, 50);
}
});
}
});
};
// Bottom back button
var bottomBackButton = LK.getAsset('restartButton', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5
});
bottomBackButton.tint = 0xFF6B35;
bottomBackButton.x = 2048 / 2;
bottomBackButton.y = 2600;
self.addChild(bottomBackButton);
var bottomBackText = new Text2('← VOLVER', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
bottomBackText.anchor.set(0.5, 0.5);
bottomBackText.x = 2048 / 2;
bottomBackText.y = 2600;
self.addChild(bottomBackText);
bottomBackButton.down = function () {
showStartScreen();
};
bottomBackText.down = function () {
showStartScreen();
};
return self;
});
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 MissionManager = Container.expand(function () {
var self = Container.call(this);
self.activeMissions = [];
self.init = function () {
self.loadActiveMissions();
};
self.loadActiveMissions = function () {
var today = new Date().toDateString();
var savedDate = storage.missionsDate;
if (savedDate !== today) {
self.generateNewDailyMissions();
} else {
var savedMissions = storage.activeMissions;
if (savedMissions && savedMissions.length > 0) {
self.activeMissions = [];
for (var i = 0; i < savedMissions.length; i++) {
self.activeMissions.push({
id: savedMissions['mission_' + i + '_id'],
text: savedMissions['mission_' + i + '_text'],
metaTotal: savedMissions['mission_' + i + '_metaTotal'],
type: savedMissions['mission_' + i + '_type'],
avanceActual: savedMissions['mission_' + i + '_avanceActual'] || 0,
completada: savedMissions['mission_' + i + '_completada'] || false
});
}
} else {
self.activeMissions = [];
}
missionManager.activeMissions = self.activeMissions;
}
};
self.generateNewDailyMissions = function () {
var shuffled = allMissions.slice();
for (var i = shuffled.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = shuffled[i];
shuffled[i] = shuffled[j];
shuffled[j] = temp;
}
self.activeMissions = shuffled.slice(0, 3).map(function (mission) {
return {
id: mission.id,
text: mission.text,
metaTotal: mission.metaTotal,
type: mission.type,
avanceActual: 0,
completada: false
};
});
missionManager.activeMissions = self.activeMissions;
var today = new Date().toDateString();
var storageData = {};
for (var i = 0; i < self.activeMissions.length; i++) {
var mission = self.activeMissions[i];
storageData['mission_' + i + '_id'] = mission.id;
storageData['mission_' + i + '_text'] = mission.text;
storageData['mission_' + i + '_metaTotal'] = mission.metaTotal;
storageData['mission_' + i + '_type'] = mission.type;
storageData['mission_' + i + '_avanceActual'] = mission.avanceActual;
storageData['mission_' + i + '_completada'] = mission.completada;
}
storageData.length = self.activeMissions.length;
storage.activeMissions = storageData;
storage.missionsDate = today;
};
self.emitEvent = function (eventType, data) {
for (var i = 0; i < self.activeMissions.length; i++) {
var mission = self.activeMissions[i];
if (mission.completada) continue;
var oldProgress = mission.avanceActual;
switch (mission.type) {
case "energia":
if (eventType === "energia_updated" && data.energia >= mission.metaTotal) {
mission.avanceActual = data.energia;
}
break;
case "frutas":
if (eventType === "fruta_atrapada") {
mission.avanceActual = Math.min(mission.avanceActual + 1, mission.metaTotal);
}
break;
case "tiempo_sin_gaseosas":
if (eventType === "frame_update" && data.gameTime >= 0) {
var timeSinceLastSoda = data.gameTime - missionManager.lastGaseosaTime;
mission.avanceActual = Math.min(timeSinceLastSoda, mission.metaTotal);
}
if (eventType === "gaseosa_atrapada") {
missionManager.lastGaseosaTime = data.gameTime;
mission.avanceActual = 0;
}
break;
case "nutripoints_total":
if (eventType === "nutripoints_updated") {
mission.avanceActual = Math.min(data.total, mission.metaTotal);
}
break;
case "agua":
if (eventType === "agua_atrapada") {
mission.avanceActual = Math.min(mission.avanceActual + 1, mission.metaTotal);
}
break;
case "partidas_consecutivas":
if (eventType === "partida_ganada") {
mission.avanceActual = Math.min(missionManager.consecutiveWins, mission.metaTotal);
}
break;
case "partida_vidas":
if (eventType === "partida_ganada" && data.vidasRestantes >= 3) {
mission.avanceActual = Math.min(mission.avanceActual + 1, mission.metaTotal);
}
break;
case "falsos_ganar":
if (eventType === "partida_ganada" && missionManager.falsosInCurrentGame >= 3) {
mission.avanceActual = Math.min(mission.avanceActual + 1, mission.metaTotal);
}
break;
case "partidas_energia_25":
if (eventType === "partida_ganada" && data.energia >= 25) {
mission.avanceActual = Math.min(missionManager.consecutiveHighEnergyWins, mission.metaTotal);
}
break;
case "tiempo_continuo":
if (eventType === "frame_update") {
var playTime = data.gameTime;
mission.avanceActual = Math.min(playTime, mission.metaTotal);
}
break;
}
// Animate progress bar if progress changed
if (oldProgress !== mission.avanceActual) {
self.animateProgressBar(i, oldProgress, mission.avanceActual);
}
// Check if mission completed
if (!mission.completada && mission.avanceActual >= mission.metaTotal) {
mission.completada = true;
sumarNutriPoints(2);
self.showMissionCompleted(mission);
// Replace completed mission with a new one after a short delay
LK.setTimeout(function () {
self.replaceCompletedMission(i);
// Refresh missions display if currently viewing missions
if (currentScreen === 'missions') {
updateMissionsDisplay();
}
}, 3000); // Wait 3 seconds before replacing
}
}
missionManager.activeMissions = self.activeMissions;
var storageData = {};
for (var i = 0; i < self.activeMissions.length; i++) {
var mission = self.activeMissions[i];
storageData['mission_' + i + '_id'] = mission.id;
storageData['mission_' + i + '_text'] = mission.text;
storageData['mission_' + i + '_metaTotal'] = mission.metaTotal;
storageData['mission_' + i + '_type'] = mission.type;
storageData['mission_' + i + '_avanceActual'] = mission.avanceActual;
storageData['mission_' + i + '_completada'] = mission.completada;
}
storageData.length = self.activeMissions.length;
storage.activeMissions = storageData;
};
self.animateProgressBar = function (missionIndex, oldProgress, newProgress) {
// Find progress bar for this mission and animate it
if (currentScreen === 'missions' && missionsScreen && missionsScreen.progressBars) {
var progressBar = missionsScreen.progressBars[missionIndex];
if (progressBar) {
var mission = self.activeMissions[missionIndex];
var newWidth = Math.min(newProgress / mission.metaTotal * 450, 450);
tween(progressBar, {
width: newWidth
}, {
duration: 300,
easing: tween.easeOut
});
}
}
};
self.replaceCompletedMission = function (missionIndex) {
// Get available missions that are not currently active
var availableMissions = [];
for (var i = 0; i < allMissions.length; i++) {
var isActive = false;
for (var j = 0; j < self.activeMissions.length; j++) {
if (self.activeMissions[j].id === allMissions[i].id) {
isActive = true;
break;
}
}
if (!isActive) {
availableMissions.push(allMissions[i]);
}
}
// If we have available missions, replace the completed one
if (availableMissions.length > 0) {
var randomIndex = Math.floor(Math.random() * availableMissions.length);
var newMission = availableMissions[randomIndex];
self.activeMissions[missionIndex] = {
id: newMission.id,
text: newMission.text,
metaTotal: newMission.metaTotal,
type: newMission.type,
avanceActual: 0,
completada: false
};
// Save updated missions
self.saveMissions();
}
};
self.saveMissions = function () {
var storageData = {};
for (var i = 0; i < self.activeMissions.length; i++) {
var mission = self.activeMissions[i];
storageData['mission_' + i + '_id'] = mission.id;
storageData['mission_' + i + '_text'] = mission.text;
storageData['mission_' + i + '_metaTotal'] = mission.metaTotal;
storageData['mission_' + i + '_type'] = mission.type;
storageData['mission_' + i + '_avanceActual'] = mission.avanceActual;
storageData['mission_' + i + '_completada'] = mission.completada;
}
storageData.length = self.activeMissions.length;
storage.activeMissions = storageData;
missionManager.activeMissions = self.activeMissions;
};
self.showMissionCompleted = function (mission) {
if (!gameActive) return;
// Create mission completed banner
var banner = LK.getAsset('restartButton', {
width: 800,
height: 120,
anchorX: 0.5,
anchorY: 0.5
});
banner.tint = 0x4CAF50;
banner.alpha = 0;
banner.x = 2048 / 2;
banner.y = 200;
game.addChild(banner);
var bannerText = new Text2('¡Misión cumplida: ' + mission.text.substring(0, 20) + '... +2 NP!', {
size: 35,
fill: 0xFFFFFF,
font: "Impact"
});
bannerText.anchor.set(0.5, 0.5);
bannerText.x = 2048 / 2;
bannerText.y = 200;
bannerText.alpha = 0;
game.addChild(bannerText);
// Play success sound
LK.getSound('powerup').play();
// Animate banner
tween(banner, {
alpha: 0.9
}, {
duration: 250,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(banner, {
alpha: 0
}, {
duration: 250,
onFinish: function onFinish() {
banner.destroy();
}
});
tween(bannerText, {
alpha: 0
}, {
duration: 250,
onFinish: function onFinish() {
bannerText.destroy();
}
});
}, 2500);
}
});
tween(bannerText, {
alpha: 1
}, {
duration: 250
});
};
return self;
});
var MissionsScreen = Container.expand(function () {
var self = Container.call(this);
// Create background
var bg = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
bg.tint = 0x2C3E50;
bg.alpha = 0.95;
self.addChild(bg);
// Title
var titleText = new Text2('MISIONES DIARIAS', {
size: 100,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 300;
self.addChild(titleText);
// Create scrollable container for missions
var scrollableArea = new Container();
scrollableArea.x = 0;
scrollableArea.y = 450; // Start below title
scrollableArea.scrollY = 0; // Track scroll position
self.addChild(scrollableArea);
// Create mask for scrollable area (visible area)
var scrollMask = LK.getAsset('energyBarBg', {
width: 2048,
height: 2000,
// Height available for scrolling (from y=450 to y=2450)
anchorX: 0,
anchorY: 0
});
scrollMask.x = 0;
scrollMask.y = 450;
scrollMask.alpha = 0; // Invisible mask
self.addChild(scrollMask);
scrollableArea.mask = scrollMask;
self.missionsContainer = new Container();
scrollableArea.addChild(self.missionsContainer);
// Store references for scrolling
self.scrollableArea = scrollableArea;
self.maxScrollY = 0; // Will be calculated based on content
self.scrollMask = scrollMask;
// Add scroll functionality
self.enableScrolling = function () {
// Touch/mouse wheel scrolling
var isDragging = false;
var lastY = 0;
var scrollSpeed = 2;
scrollableArea.down = function (x, y, obj) {
isDragging = true;
lastY = y;
};
scrollableArea.move = function (x, y, obj) {
if (isDragging) {
var deltaY = y - lastY;
self.scroll(deltaY * scrollSpeed);
lastY = y;
}
};
scrollableArea.up = function (x, y, obj) {
isDragging = false;
};
// Also enable scrolling on the background
bg.down = function (x, y, obj) {
isDragging = true;
lastY = y;
};
bg.move = function (x, y, obj) {
if (isDragging && y > 450 && y < 2450) {
// Only scroll in missions area
var deltaY = y - lastY;
self.scroll(deltaY * scrollSpeed);
lastY = y;
}
};
bg.up = function (x, y, obj) {
isDragging = false;
};
};
// Scroll function
self.scroll = function (deltaY) {
var newScrollY = self.scrollableArea.scrollY + deltaY;
// Calculate max scroll based on content height
var contentHeight = self.missionsContainer.height || 0;
var visibleHeight = 2000; // Height of visible area
self.maxScrollY = Math.max(0, contentHeight - visibleHeight);
// Constrain scroll within bounds
newScrollY = Math.max(-self.maxScrollY, Math.min(0, newScrollY));
self.scrollableArea.scrollY = newScrollY;
self.scrollableArea.y = 450 + newScrollY;
};
// Update content height calculation
self.updateScrollBounds = function () {
// Calculate total content height based on missions
var activeMissions = missionManager.activeMissions;
if (activeMissions && activeMissions.length > 0) {
var totalHeight = activeMissions.length * 320 + 100; // Each mission is 320px + padding
var visibleHeight = 2000;
self.maxScrollY = Math.max(0, totalHeight - visibleHeight);
// Reset scroll to top when content updates
self.scrollableArea.scrollY = 0;
self.scrollableArea.y = 450;
}
};
// Enable scrolling
self.enableScrolling();
// Bottom back button
var bottomBackButton = LK.getAsset('restartButton', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5
});
bottomBackButton.tint = 0xFF6B35;
bottomBackButton.x = 2048 / 2;
bottomBackButton.y = 2600;
self.addChild(bottomBackButton);
var bottomBackText = new Text2('← VOLVER', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
bottomBackText.anchor.set(0.5, 0.5);
bottomBackText.x = 2048 / 2;
bottomBackText.y = 2600;
self.addChild(bottomBackText);
bottomBackButton.down = function () {
showStartScreen();
};
bottomBackText.down = function () {
showStartScreen();
};
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;
});
var StartScreen = Container.expand(function () {
var self = Container.call(this);
// Create background
var bg = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
bg.tint = 0x5d6c16;
self.addChild(bg);
// Game title
var titleText = new Text2('Caza-ingredientes', {
size: 120,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 400;
self.addChild(titleText);
// Nutripoints display on start screen
var nutripointsDisplay = new Text2('Nutripoints: ' + (storage.totalNutripoints || 0), {
size: 75,
fill: 0x32CD32,
font: "Impact"
});
nutripointsDisplay.anchor.set(0.5, 0.5);
nutripointsDisplay.x = 2048 / 2;
nutripointsDisplay.y = 500;
self.addChild(nutripointsDisplay);
// Store reference for updates
self.nutripointsDisplay = nutripointsDisplay;
var subtitleText = new Text2('Elige bien, vive mejor', {
size: 80,
fill: 0x32CD32,
font: "Impact"
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 2048 / 2;
subtitleText.y = 580;
self.addChild(subtitleText);
// Create buttons
var buttonProps = [{
text: 'PLAY',
y: 850,
color: 0x32CD32
}, {
text: 'MISIONES',
y: 1050,
color: 0xFF6B35
}, {
text: 'TIENDA',
y: 1250,
color: 0x4ECDC4
}, {
text: 'PREGUNTAS',
y: 1450,
color: 0x9B59B6
}];
self.buttons = [];
for (var i = 0; i < buttonProps.length; i++) {
var buttonBg = LK.getAsset('restartButton', {
width: 600,
height: 120,
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.tint = buttonProps[i].color;
buttonBg.x = 2048 / 2;
buttonBg.y = buttonProps[i].y;
self.addChild(buttonBg);
var buttonText = new Text2(buttonProps[i].text, {
size: 70,
fill: 0xFFFFFF,
font: "Impact"
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 2048 / 2;
buttonText.y = buttonProps[i].y;
self.addChild(buttonText);
buttonBg.buttonType = buttonProps[i].text;
buttonText.buttonType = buttonProps[i].text;
self.buttons.push({
bg: buttonBg,
text: buttonText,
type: buttonProps[i].text
});
}
// Button click handlers
for (var j = 0; j < self.buttons.length; j++) {
(function (button) {
button.bg.down = function (x, y, obj) {
handleStartScreenButton(button.type);
};
button.text.down = function (x, y, obj) {
handleStartScreenButton(button.type);
};
})(self.buttons[j]);
}
return self;
});
var StoreScreen = Container.expand(function () {
var self = Container.call(this);
// Create background
var bg = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
bg.tint = 0x2C3E50;
bg.alpha = 0.95;
self.addChild(bg);
// Title
var titleText = new Text2('TIENDA', {
size: 100,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 250;
self.addChild(titleText);
// Nutripoints display
var nutripointsDisplay = new Text2('Nutripoints: ' + (storage.totalNutripoints || 0), {
size: 60,
fill: 0x32CD32,
font: "Impact"
});
nutripointsDisplay.anchor.set(0.5, 0.5);
nutripointsDisplay.x = 2048 / 2;
nutripointsDisplay.y = 350;
self.addChild(nutripointsDisplay);
// Store reference for updates
self.nutripointsDisplay = nutripointsDisplay;
self.storeContainer = new Container();
self.addChild(self.storeContainer);
// Bottom back button
var bottomBackButton = LK.getAsset('restartButton', {
width: 400,
height: 100,
anchorX: 0.5,
anchorY: 0.5
});
bottomBackButton.tint = 0xFF6B35;
bottomBackButton.x = 2048 / 2;
bottomBackButton.y = 2600;
self.addChild(bottomBackButton);
var bottomBackText = new Text2('← VOLVER', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
bottomBackText.anchor.set(0.5, 0.5);
bottomBackText.x = 2048 / 2;
bottomBackText.y = 2600;
self.addChild(bottomBackText);
bottomBackButton.down = function () {
showStartScreen();
};
bottomBackText.down = function () {
showStartScreen();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state management
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var currentScreen = 'start'; // 'start', 'game', 'missions', 'store', 'faq'
var gameStarted = false; // Track if game has been started via PLAY button
var gamePaused = false; // Track if game is paused
var pauseButton;
var pauseMenu;
var startScreen;
var missionsScreen;
var storeScreen;
var faqScreen;
// Mission system
var allMissions = [{
id: "energia_20",
text: "Alcanza 20 de Energía en una sola partida.",
metaTotal: 20,
type: "energia"
}, {
id: "frutas_10",
text: "Atrapa 10 frutas o verduras sanas en una partida.",
metaTotal: 10,
type: "frutas"
}, {
id: "evitar_gaseosas_60",
text: "Evita TODAS las gaseosas durante 60 segundos.",
metaTotal: 60,
type: "tiempo_sin_gaseosas"
}, {
id: "nutripoints_6",
text: "Consigue 6 Nutripoints en total.",
metaTotal: 6,
type: "nutripoints_total"
}, {
id: "agua_5",
text: "Recoge 5 botellas de agua (power-ups) en una sesión.",
metaTotal: 5,
type: "agua"
}, {
id: "partidas_3_sin_perder",
text: "Juega 3 partidas seguidas sin perder una vida.",
metaTotal: 3,
type: "partidas_consecutivas"
}, {
id: "partida_3_vidas",
text: "Completa una partida con al menos 3 vidas restantes.",
metaTotal: 1,
type: "partida_vidas"
}, {
id: "falsos_3_ganar",
text: "Atrapa 3 alimentos 'falsos sanos' y aún así gana.",
metaTotal: 3,
type: "falsos_ganar"
}, {
id: "energia_25_2_partidas",
text: "Gana 2 partidas consecutivas con Energía ≥25.",
metaTotal: 2,
type: "partidas_energia_25"
}, {
id: "tiempo_5_min",
text: "Juega durante 5 min. continuos sin colapsar.",
metaTotal: 300,
type: "tiempo_continuo"
}];
// Store items
var storeItems = [{
id: "skin_rojo",
nombre: "Skin Roja",
costo: 5,
tipo: "skin"
}, {
id: "skin_verde",
nombre: "Skin Verde",
costo: 5,
tipo: "skin"
}, {
id: "fondo_parque",
nombre: "Fondo Parque",
costo: 8,
tipo: "fondo"
}, {
id: "fondo_playa",
nombre: "Fondo Playa",
costo: 10,
tipo: "fondo"
}];
// FAQ data
var faqData = [{
question: "¿Cómo se juega \"Caza-ingredientes\"?",
answer: "Mueve tu avatar a izquierda y derecha y atrapa solo los alimentos saludables para sumar Energía. Evita los ultraprocesados y trampas."
}, {
question: "¿Para qué sirve la barra de Energía?",
answer: "Representa tu nivel de salud en el juego. Si llega a 0, pierdes. Si llegas a 30, ganas Nutripoints extra."
}, {
question: "¿Qué son los Nutripoints y cómo se consiguen?",
answer: "Son puntos que obtienes al ganar con Energía completa o cumpliendo misiones. Sirven para comprar skins y fondos en la Tienda."
}, {
question: "¿Cómo funciona la Tienda?",
answer: "En la Tienda puedes cambiar Nutripoints por apariencias nuevas para tu avatar o fondos temáticos para el juego."
}, {
question: "¿Cómo se completan las misiones?",
answer: "Ve a MISIONES, revisa las tareas diarias y juega hasta lograr cada objetivo. Al cumplirlas, recibes Nutripoints automáticamente."
}];
// Game elements
// Fake healthy foods
// Junk foods
// Healthy foods
// Game variables
// Healthy Foods - Fruits
// Healthy Foods - Vegetables
// Healthy Foods - Proteins & Grains
// Junk Foods
// Fake Healthy Foods
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
var expertModeTimer = 0; // Timer to track when expert mode should activate (20 seconds)
var expertModeStartTime = 1200; // 20 seconds * 60 fps = 1200 frames
// Nutripoints system variables and initialization
function initializeNutripoints() {
// Check if this is first time installation
if (storage.totalNutripoints === undefined) {
storage.totalNutripoints = 0;
}
// Check for daily login bonus
var today = new Date().toISOString().split('T')[0]; // Get YYYY-MM-DD format
var lastLoginDate = storage.lastLoginDate;
if (lastLoginDate !== today) {
// Award daily login bonus
storage.totalNutripoints = (storage.totalNutripoints || 0) + 1;
storage.lastLoginDate = today;
// Show login bonus message (non-intrusive)
if (lastLoginDate) {
// Don't show on first install, only subsequent days
LK.setTimeout(function () {
showLoginBonusMessage();
}, 1000);
}
}
}
// Global function to add nutripoints
function sumarNutriPoints(cantidad) {
totalNutripoints += cantidad;
storage.totalNutripoints = totalNutripoints;
// Update UI immediately
updateNutripointsDisplay();
}
// Function to show login bonus message
function showLoginBonusMessage() {
if (!gameStarted) {
// Only show on start screen
var banner = LK.getAsset('restartButton', {
width: 600,
height: 80,
anchorX: 0.5,
anchorY: 0.5
});
banner.tint = 0x32CD32;
banner.alpha = 0;
banner.x = 2048 / 2;
banner.y = 650;
if (startScreen) {
startScreen.addChild(banner);
var bannerText = new Text2('¡Has ganado 1 Nutripoint por iniciar hoy!', {
size: 45,
fill: 0xFFFFFF,
font: "Impact"
});
bannerText.anchor.set(0.5, 0.5);
bannerText.x = 2048 / 2;
bannerText.y = 650;
bannerText.alpha = 0;
startScreen.addChild(bannerText);
// Animate banner
tween(banner, {
alpha: 0.9
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(banner, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
banner.destroy();
}
});
tween(bannerText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
bannerText.destroy();
}
});
}, 3000);
}
});
tween(bannerText, {
alpha: 1
}, {
duration: 500
});
}
}
}
// Function to update nutripoints display across all screens
function updateNutripointsDisplay() {
// Update start screen display
if (startScreen && startScreen.nutripointsDisplay) {
startScreen.nutripointsDisplay.setText('Nutripoints: ' + totalNutripoints);
}
// Update store screen display
if (storeScreen && storeScreen.nutripointsDisplay) {
storeScreen.nutripointsDisplay.setText('Nutripoints: ' + totalNutripoints);
}
// Update game UI display
if (totalNutripointsText) {
totalNutripointsText.setText('Nutripoints: ' + totalNutripoints);
}
}
// Initialize nutripoints system
initializeNutripoints();
var totalNutripoints = storage.totalNutripoints || 0;
var gameNutripoints = 0; // Points earned in current game
// Mission tracking variables
var missionManager = {
activeMissions: [],
gameStartTime: 0,
lastGaseosaTime: 0,
consecutiveWins: 0,
falsosInCurrentGame: 0,
consecutiveHighEnergyWins: 0,
continuousPlayTime: 0
};
// Initialize mission progress from storage
var missionProgress = storage.missionProgress || {};
// 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;
var nutripointsText;
var totalNutripointsText;
// 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;
// Total Nutripoints display (made larger)
totalNutripointsText = new Text2('Nutripoints: ' + totalNutripoints, {
size: 72,
fill: 0x32CD32,
font: "Impact"
});
totalNutripointsText.anchor.set(1, 0);
LK.gui.topRight.addChild(totalNutripointsText);
totalNutripointsText.x = -20;
totalNutripointsText.y = 120;
// Pause button
pauseButton = LK.getAsset('pauseButton', {
anchorX: 0.5,
anchorY: 0.5
});
pauseButton.x = 2048 - 60;
pauseButton.y = 300;
LK.gui.topRight.addChild(pauseButton);
var pauseText = new Text2('⏸', {
size: 50,
fill: 0xFFFFFF,
font: "Impact"
});
pauseText.anchor.set(0.5, 0.5);
pauseText.x = 2048 - 60;
pauseText.y = 300;
LK.gui.topRight.addChild(pauseText);
pauseButton.down = function () {
showPauseMenu();
};
pauseText.down = function () {
showPauseMenu();
};
// Score text removed
}
// Update UI
function updateUI() {
if (energyText) energyText.setText('Energía: ' + energy + '/30');
if (livesText) livesText.setText('Vidas: ' + lives);
if (totalNutripointsText) totalNutripointsText.setText('Nutripoints: ' + totalNutripoints);
// Score text update removed
// Update energy bar fill based on current energy (0-30 range)
if (energyBarFill) {
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);
// Score increment removed
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]++;
}
// Emit mission event
missionManagerInstance.emitEvent("fruta_atrapada", {});
missionManagerInstance.emitEvent("energia_updated", {
energia: energy
});
break;
case 'junk':
lives--;
energy = Math.max(0, energy - 2);
LK.getSound('buzz').play();
vibrateDevice();
flashScreen(0xFF4500);
playerFeedback(0xFF4500, 100, false);
// Emit mission event for soda specifically
if (item.specificFood === 'soda') {
var gameTime = (LK.ticks - gameStartTime) / 60;
missionManagerInstance.emitEvent("gaseosa_atrapada", {
gameTime: gameTime
});
}
missionManagerInstance.emitEvent("energia_updated", {
energia: energy
});
break;
case 'fake':
energy = Math.max(0, energy - 2);
LK.getSound('buzz').play();
vibrateDevice();
flashScreen(0xFFD700);
playerFeedback(0xFFD700, 100, false);
missionManager.falsosInCurrentGame++;
missionManagerInstance.emitEvent("energia_updated", {
energia: energy
});
break;
case 'water':
energy = Math.min(30, energy + 3);
// Score increment removed
LK.getSound('powerup').play();
flashScreen(0x00BFFF);
playerFeedback(0x00BFFF, 150, true);
// Track water bottle counts
foodCounts['waterBottle']++;
// Emit mission events
missionManagerInstance.emitEvent("agua_atrapada", {});
missionManagerInstance.emitEvent("energia_updated", {
energia: energy
});
break;
case 'anxiety':
energy = Math.max(0, energy - 5);
LK.getSound('explosion').play();
vibrateDevice();
flashScreen(0x8B008B);
playerFeedback(0x8B008B, 300, false);
missionManagerInstance.emitEvent("energia_updated", {
energia: energy
});
break;
}
// Update nutripoints mission
missionManagerInstance.emitEvent("nutripoints_updated", {
total: totalNutripoints
});
}
// Initialize game
function initializeGame() {
gameStartTime = LK.ticks;
// Initialize mission tracking for this game
missionManager.gameStartTime = gameStartTime;
missionManager.falsosInCurrentGame = 0;
// 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) {
if (!player) return; // Check if player exists
var gamePos = game.toLocal({
x: x,
y: y
});
player.moveTo(gamePos.x);
};
game.move = function (x, y, obj) {
if (!player) return; // Check if player exists
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 hasn't started, is not active, or is paused
if (!gameStarted || !gameActive || gamePaused) {
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;
}
// Increment expert mode timer
expertModeTimer++;
// Activate anxiety bombs after 20 seconds (1200 frames)
if (expertModeTimer >= expertModeStartTime && !anxietyBombsActive) {
anxietyBombsActive = true;
lastAnxietySpawnTime = currentTime;
// Only show expert message when expert mode activates
if (expertModeTimer >= expertModeStartTime && !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
// Spawn 2-3 items at once for more food variety
var itemsToSpawn = 2 + Math.floor(Math.random() * 2); // 2 or 3 items
for (var s = 0; s < itemsToSpawn; s++) {
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();
// Emit frame update for missions
if (gameActive && gameStarted) {
var gameTime = (LK.ticks - gameStartTime) / 60;
missionManagerInstance.emitEvent("frame_update", {
gameTime: gameTime
});
}
// Check game over conditions
if (energy >= 30) {
// Store final stats for victory
storage.finalEnergy = energy;
storage.finalTime = Math.floor(gameTime);
storage.gameEndReason = 'victoria';
// Track mission progress for winning with high energy
missionManager.consecutiveWins++;
if (energy >= 25) {
missionManager.consecutiveHighEnergyWins++;
}
storage.consecutiveWins = missionManager.consecutiveWins;
storage.consecutiveHighEnergyWins = missionManager.consecutiveHighEnergyWins;
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';
// Reset consecutive wins on game over
missionManager.consecutiveWins = 0;
missionManager.consecutiveHighEnergyWins = 0;
storage.consecutiveWins = 0;
storage.consecutiveHighEnergyWins = 0;
gameActive = false; // Stop game updates
showGameOver();
} else if (energy <= 0) {
// Store final stats
storage.finalEnergy = energy;
storage.finalTime = Math.floor(gameTime);
storage.gameEndReason = 'fatiga';
// Reset consecutive wins on game over
missionManager.consecutiveWins = 0;
missionManager.consecutiveHighEnergyWins = 0;
storage.consecutiveWins = 0;
storage.consecutiveHighEnergyWins = 0;
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);
// Emit mission events for winning the game
missionManagerInstance.emitEvent("partida_ganada", {
energia: energy,
vidasRestantes: lives
});
// Award Nutripoints only for reaching maximum energy
if (energy >= 30) {
gameNutripoints = 2; // Award 2 Nutripoints for completing with max energy
sumarNutriPoints(gameNutripoints);
}
// Create full screen overlay
var overlay = LK.getAsset('energyBarBg', {
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 removed
// 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 = 1100;
game.addChild(timeText);
// Nutripoints message
var gameNutripointsText = new Text2('¡Ganaste 2 Nutripoints por llegar al máximo de energía!', {
size: 65,
fill: 0x32CD32,
font: "Impact"
});
gameNutripointsText.anchor.set(0.5, 0.5);
gameNutripointsText.x = 2048 / 2;
gameNutripointsText.y = 1200;
game.addChild(gameNutripointsText);
var totalNutripointsText = new Text2('Total acumulado: ' + totalNutripoints + ' Nutripoints', {
size: 55,
fill: 0xFFD700,
font: "Impact"
});
totalNutripointsText.anchor.set(0.5, 0.5);
totalNutripointsText.x = 2048 / 2;
totalNutripointsText.y = 1300;
game.addChild(totalNutripointsText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 700,
height: 140,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1600;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 80,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1600;
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 () {
showStartScreen();
};
restartText.down = function () {
showStartScreen();
};
}
// Show game over message when lives reach 0
function showGameOver() {
var finalTime = storage.finalTime || Math.floor((LK.ticks - gameStartTime) / 60);
// No Nutripoints awarded when not reaching maximum energy
// Create full screen overlay
var overlay = LK.getAsset('energyBarBg', {
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 removed
// 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 = 800;
game.addChild(timeText);
// Nutripoints encouragement message
var nutripointsEncourageText = new Text2('¡Sigue eligiendo bien para ganar Nutripoints!', {
size: 65,
fill: 0xFFD700,
font: "Impact"
});
nutripointsEncourageText.anchor.set(0.5, 0.5);
nutripointsEncourageText.x = 2048 / 2;
nutripointsEncourageText.y = 900;
game.addChild(nutripointsEncourageText);
// Add nutritional information section
var mostConsumedText = new Text2('Alimento que más consumiste en esta partida', {
size: 70,
fill: 0x32CD32,
font: "Impact"
});
mostConsumedText.anchor.set(0.5, 0.5);
mostConsumedText.x = 2048 / 2;
mostConsumedText.y = 1050;
game.addChild(mostConsumedText);
var nutritionalInfo = getNutritionalInfo();
var nutritionTitleText = new Text2(nutritionalInfo.title, {
size: 80,
fill: 0xFFD700,
font: "Impact"
});
nutritionTitleText.anchor.set(0.5, 0.5);
nutritionTitleText.x = 2048 / 2;
nutritionTitleText.y = 1200;
game.addChild(nutritionTitleText);
var nutritionInfoText = new Text2(nutritionalInfo.info, {
size: 55,
fill: 0xFFFFFF,
font: "Impact"
});
nutritionInfoText.anchor.set(0.5, 0);
nutritionInfoText.x = 2048 / 2;
nutritionInfoText.y = 1250;
game.addChild(nutritionInfoText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 700,
height: 140,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1650;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 80,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1650;
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 () {
showStartScreen();
};
restartText.down = function () {
showStartScreen();
};
}
// 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';
}
// No Nutripoints awarded when not reaching maximum energy
// Create full screen overlay
var overlay = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
overlay.tint = 0x000000;
overlay.alpha = 0.9;
game.addChild(overlay);
// Title
var titleText = new Text2('FATIGA, FALTA DE ENERGÍA', {
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 removed
// 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 = 700;
game.addChild(timeText);
// Nutripoints encouragement message
var nutripointsEncourageText = new Text2('¡Sigue eligiendo bien para ganar Nutripoints!', {
size: 65,
fill: 0xFFD700,
font: "Impact"
});
nutripointsEncourageText.anchor.set(0.5, 0.5);
nutripointsEncourageText.x = 2048 / 2;
nutripointsEncourageText.y = 800;
game.addChild(nutripointsEncourageText);
// 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 = 900;
game.addChild(messageText);
// Add nutritional information section
var mostConsumedText = new Text2('Alimento que más consumiste en esta partida', {
size: 70,
fill: 0x32CD32,
font: "Impact"
});
mostConsumedText.anchor.set(0.5, 0.5);
mostConsumedText.x = 2048 / 2;
mostConsumedText.y = 1000;
game.addChild(mostConsumedText);
var nutritionalInfo = getNutritionalInfo();
var nutritionTitleText = new Text2(nutritionalInfo.title, {
size: 80,
fill: 0xFFD700,
font: "Impact"
});
nutritionTitleText.anchor.set(0.5, 0.5);
nutritionTitleText.x = 2048 / 2;
nutritionTitleText.y = 1150;
game.addChild(nutritionTitleText);
var nutritionInfoText = new Text2(nutritionalInfo.info, {
size: 55,
fill: 0xFFFFFF,
font: "Impact"
});
nutritionInfoText.anchor.set(0.5, 0);
nutritionInfoText.x = 2048 / 2;
nutritionInfoText.y = 1200;
game.addChild(nutritionInfoText);
// Create animated restart button
var restartButton = LK.getAsset('restartButton', {
width: 700,
height: 140,
color: 0x32CD32,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
restartButton.x = 2048 / 2;
restartButton.y = 1600;
game.addChild(restartButton);
var restartText = new Text2('Jugar de nuevo', {
size: 80,
fill: 0xFFFFFF,
font: "Impact"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1600;
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 () {
showStartScreen();
};
restartText.down = function () {
showStartScreen();
};
}
// 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
gameStarted = true; // Ensure game logic runs during countdown and game
expertModeTimer = 0; // Reset expert mode timer
gameNutripoints = 0; // Reset current game Nutripoints
// Score reset removed
// Clear GUI elements to reset them properly
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
LK.gui.top.removeChildren();
// Reset UI variable references
totalNutripointsText = null;
pauseButton = null;
// 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();
}
// Screen management functions
function showStartScreen() {
currentScreen = 'start';
gameStarted = false; // Reset game started state
gamePaused = false; // Reset pause state
game.removeChildren();
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
if (!startScreen) {
startScreen = new StartScreen();
}
game.addChild(startScreen);
}
function handleStartScreenButton(buttonType) {
switch (buttonType) {
case 'PLAY':
// Find the PLAY button and animate it
for (var i = 0; i < startScreen.buttons.length; i++) {
if (startScreen.buttons[i].type === 'PLAY') {
var playButton = startScreen.buttons[i];
// Set gameStarted immediately to enable game logic
gameStarted = true;
// Animate button press
tween(playButton.bg, {
scaleX: 0.95,
scaleY: 0.95,
tint: 0x228B22
}, {
duration: 150,
onFinish: function onFinish() {
tween(playButton.bg, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0x32CD32
}, {
duration: 150,
onFinish: function onFinish() {
// Start game immediately after animation
startGame();
}
});
}
});
tween(playButton.text, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 150,
onFinish: function onFinish() {
tween(playButton.text, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150
});
}
});
break;
}
}
break;
case 'MISIONES':
showMissionsScreen();
break;
case 'TIENDA':
showStoreScreen();
break;
case 'PREGUNTAS':
showFAQScreen();
break;
}
}
function startGame() {
currentScreen = 'game';
game.removeChildren();
startCountdown();
}
function showMissionsScreen() {
currentScreen = 'missions';
game.removeChildren();
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
if (!missionsScreen) {
missionsScreen = new MissionsScreen();
}
game.addChild(missionsScreen);
updateMissionsDisplay();
}
function showStoreScreen() {
currentScreen = 'store';
game.removeChildren();
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
if (!storeScreen) {
storeScreen = new StoreScreen();
}
game.addChild(storeScreen);
updateStoreDisplay();
}
function showFAQScreen() {
currentScreen = 'faq';
game.removeChildren();
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
if (!faqScreen) {
faqScreen = new FAQScreen();
}
game.addChild(faqScreen);
updateFAQDisplay();
}
// Mission system functions - handled by MissionManager class
function updateMissionsDisplay() {
if (!missionsScreen) return;
missionsScreen.missionsContainer.removeChildren();
missionsScreen.progressBars = [];
// Ensure missionManager and its activeMissions exist
if (!missionManager || !missionManager.activeMissions) {
if (missionManagerInstance) {
missionManagerInstance.generateNewDailyMissions();
}
}
var activeMissions = null;
// Safe access to activeMissions with multiple checks
if (missionManager && missionManager.activeMissions && Array.isArray(missionManager.activeMissions)) {
activeMissions = missionManager.activeMissions;
} else if (missionManagerInstance && missionManagerInstance.activeMissions && Array.isArray(missionManagerInstance.activeMissions)) {
activeMissions = missionManagerInstance.activeMissions;
} else {
activeMissions = [];
}
if (!activeMissions || activeMissions.length === 0) {
if (missionManagerInstance) {
missionManagerInstance.generateNewDailyMissions();
// Re-check after generation with safe access
if (missionManager && missionManager.activeMissions && Array.isArray(missionManager.activeMissions)) {
activeMissions = missionManager.activeMissions;
} else if (missionManagerInstance && missionManagerInstance.activeMissions && Array.isArray(missionManagerInstance.activeMissions)) {
activeMissions = missionManagerInstance.activeMissions;
} else {
activeMissions = [];
}
}
}
// Final safety check after all attempts
if (!activeMissions || !Array.isArray(activeMissions) || activeMissions.length === 0) {
// Create default empty state display
var noMissionsText = new Text2('No hay misiones disponibles', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
noMissionsText.anchor.set(0.5, 0.5);
noMissionsText.x = 2048 / 2;
noMissionsText.y = 200;
missionsScreen.missionsContainer.addChild(noMissionsText);
return;
}
// Additional validation: check if array elements exist and are accessible
var validMissionsCount = 0;
if (activeMissions && Array.isArray(activeMissions) && activeMissions.length > 0) {
for (var checkIndex = 0; checkIndex < activeMissions.length; checkIndex++) {
if (checkIndex < activeMissions.length && activeMissions[checkIndex] && _typeof(activeMissions[checkIndex]) === 'object') {
validMissionsCount++;
}
}
}
if (validMissionsCount === 0) {
var noValidMissionsText = new Text2('Error: No se pudieron cargar las misiones', {
size: 60,
fill: 0xFF6B35,
font: "Impact"
});
noValidMissionsText.anchor.set(0.5, 0.5);
noValidMissionsText.x = 2048 / 2;
noValidMissionsText.y = 200;
missionsScreen.missionsContainer.addChild(noValidMissionsText);
return;
}
// Final safety check before loop
if (!activeMissions || !Array.isArray(activeMissions) || activeMissions.length === 0) {
return;
}
// Additional safety check to ensure array is properly formed
try {
// Test array access before loop
if (activeMissions.length > 0 && activeMissions[0] === undefined && activeMissions.length > 0) {
console.error('Array exists but elements are undefined');
return;
}
} catch (e) {
console.error('Error accessing activeMissions array:', e);
return;
}
for (var i = 0; i < activeMissions.length; i++) {
// Comprehensive safety check for array bounds and element existence
if (!activeMissions || !Array.isArray(activeMissions) || i >= activeMissions.length) {
continue;
}
// Additional bounds check
if (i < 0 || i >= activeMissions.length) {
continue;
}
// Safe access to array element with additional validation
var mission = null;
try {
// Extra safety check before accessing array element
if (activeMissions && Array.isArray(activeMissions) && i >= 0 && i < activeMissions.length) {
var arrayElement = activeMissions[i];
if (arrayElement !== undefined && arrayElement !== null) {
mission = arrayElement;
} else {
continue;
}
} else {
continue;
}
} catch (e) {
console.error('Error accessing mission at index', i, ':', e);
continue;
}
// Safety check for mission object
if (!mission || _typeof(mission) !== 'object') {
continue;
}
// Ensure mission has required properties
if (!mission.text || typeof mission.metaTotal === 'undefined' || typeof mission.avanceActual === 'undefined') {
continue;
}
var missionBg = LK.getAsset('restartButton', {
width: 1800,
height: 280,
anchorX: 0.5,
anchorY: 0.5
});
missionBg.tint = mission.completada ? 0x27AE60 : 0x34495E;
missionBg.x = 2048 / 2;
missionBg.y = 50 + i * 320; // Adjusted Y position to start from 0 in scrollable container
missionsScreen.missionsContainer.addChild(missionBg);
var missionText = new Text2((mission.completada ? '✔️ ' : '') + mission.text, {
size: 55,
fill: 0xFFFFFF,
font: "Impact"
});
missionText.anchor.set(0.5, 0.5);
missionText.x = 2048 / 2;
missionText.y = 30 + i * 320; // Adjusted Y position
missionsScreen.missionsContainer.addChild(missionText);
// Progress bar background
var progressBg = LK.getAsset('energyBarBg', {
width: 450,
height: 25,
anchorX: 0.5,
anchorY: 0.5
});
progressBg.tint = 0x666666;
progressBg.alpha = 0.4;
progressBg.x = 2048 / 2 - 225;
progressBg.y = 100 + i * 320; // Adjusted Y position
missionsScreen.missionsContainer.addChild(progressBg);
// Progress bar fill
var progressWidth = mission.avanceActual / mission.metaTotal * 450;
var progressFill = LK.getAsset('energyBarFill', {
width: progressWidth,
height: 25,
anchorX: 0,
anchorY: 0.5
});
progressFill.tint = 0x4CAF50;
progressFill.x = 2048 / 2 - 225;
progressFill.y = 100 + i * 320; // Adjusted Y position
missionsScreen.missionsContainer.addChild(progressFill);
missionsScreen.progressBars.push(progressFill);
// Progress text
var progressText = new Text2(mission.avanceActual + ' / ' + mission.metaTotal, {
size: 45,
fill: 0xFFFFFF,
font: "Impact"
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 2048 / 2 + 250;
progressText.y = 100 + i * 320; // Adjusted Y position
missionsScreen.missionsContainer.addChild(progressText);
if (mission.completada) {
var rewardText = new Text2('Completada ✔️ +2 Nutripoints', {
size: 45,
fill: 0xFFD700,
font: "Impact"
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 2048 / 2;
rewardText.y = 140 + i * 320; // Adjusted Y position
missionsScreen.missionsContainer.addChild(rewardText);
}
}
// Update scroll bounds after adding all missions
if (missionsScreen.updateScrollBounds) {
missionsScreen.updateScrollBounds();
}
}
// Store system functions
function updateStoreDisplay() {
if (!storeScreen) return;
storeScreen.storeContainer.removeChildren();
var playerNutripoints = storage.totalNutripoints || 0;
var ownedItems = storage.ownedItems || [];
for (var i = 0; i < storeItems.length; i++) {
var item = storeItems[i];
var owned = ownedItems.indexOf(item.id) !== -1;
var canAfford = playerNutripoints >= item.costo;
var itemBg = LK.getAsset('restartButton', {
width: 700,
height: 150,
anchorX: 0.5,
anchorY: 0.5
});
itemBg.tint = owned ? 0x27AE60 : canAfford ? 0x3498DB : 0x95A5A6;
itemBg.x = i % 2 * 800 + 500;
itemBg.y = 500 + Math.floor(i / 2) * 200;
storeScreen.storeContainer.addChild(itemBg);
var nameText = new Text2(item.nombre, {
size: 45,
fill: 0xFFFFFF,
font: "Impact"
});
nameText.anchor.set(0.5, 0.5);
nameText.x = itemBg.x;
nameText.y = itemBg.y - 20;
storeScreen.storeContainer.addChild(nameText);
var costText = new Text2(owned ? 'COMPRADO' : item.costo + ' Nutripoints', {
size: 35,
fill: owned ? 0x2ECC71 : canAfford ? 0xFFD700 : 0xE74C3C,
font: "Impact"
});
costText.anchor.set(0.5, 0.5);
costText.x = itemBg.x;
costText.y = itemBg.y + 20;
storeScreen.storeContainer.addChild(costText);
if (!owned && canAfford) {
itemBg.itemData = item;
(function (itemData) {
itemBg.down = function (x, y, obj) {
purchaseItem(itemData);
};
})(item);
}
}
}
function purchaseItem(item) {
if (!item || typeof item.costo === 'undefined') {
console.error('Invalid item data in purchaseItem');
return;
}
var playerNutripoints = storage.totalNutripoints || 0;
var ownedItems = storage.ownedItems || [];
if (playerNutripoints >= item.costo && ownedItems.indexOf(item.id) === -1) {
storage.totalNutripoints = playerNutripoints - item.costo;
ownedItems.push(item.id);
storage.ownedItems = ownedItems;
// Show purchase popup
var popup = LK.getAsset('restartButton', {
width: 800,
height: 200,
anchorX: 0.5,
anchorY: 0.5
});
popup.tint = 0x27AE60;
popup.x = 2048 / 2;
popup.y = 2732 / 2;
game.addChild(popup);
var popupText = new Text2('¡Nuevo artículo desbloqueado!', {
size: 60,
fill: 0xFFFFFF,
font: "Impact"
});
popupText.anchor.set(0.5, 0.5);
popupText.x = 2048 / 2;
popupText.y = 2732 / 2;
game.addChild(popupText);
LK.getSound('powerup').play();
// Remove popup after 2 seconds
LK.setTimeout(function () {
popup.destroy();
popupText.destroy();
updateStoreDisplay();
}, 2000);
}
}
// FAQ system functions
function updateFAQDisplay() {
if (!faqScreen) return;
// Initialize FAQ items with accordion functionality
faqScreen.createFAQItems();
}
// Initialize mission manager
var missionManagerInstance = new MissionManager();
missionManagerInstance.init();
// Initialize mission tracking variables properly
missionManager.gameStartTime = 0;
missionManager.lastGaseosaTime = -60; // Start with -60 to allow immediate tracking
missionManager.consecutiveWins = storage.consecutiveWins || 0;
missionManager.falsosInCurrentGame = 0;
missionManager.consecutiveHighEnergyWins = storage.consecutiveHighEnergyWins || 0;
missionManager.continuousPlayTime = storage.continuousPlayTime || 0;
// Initialize storage for persistent data
totalNutripoints = storage.totalNutripoints || 0;
// Pause menu functions
function showPauseMenu() {
if (!gameStarted || !gameActive) return;
gamePaused = true;
// Create overlay
var overlay = LK.getAsset('energyBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0
});
overlay.tint = 0x000000;
overlay.alpha = 0.8;
game.addChild(overlay);
// Pause menu container
pauseMenu = new Container();
game.addChild(pauseMenu);
// Title
var titleText = new Text2('JUEGO PAUSADO', {
size: 120,
fill: 0xFFD700,
font: "Impact"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 800;
pauseMenu.addChild(titleText);
// Buttons data
var buttonData = [{
text: 'REANUDAR',
y: 1100,
color: 0x27AE60,
action: 'resume'
}, {
text: 'REINICIAR',
y: 1300,
color: 0xF39C12,
action: 'restart'
}, {
text: 'MENÚ PRINCIPAL',
y: 1500,
color: 0xE74C3C,
action: 'menu'
}];
// Create buttons
for (var i = 0; i < buttonData.length; i++) {
var buttonBg = LK.getAsset('restartButton', {
width: 600,
height: 120,
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.tint = buttonData[i].color;
buttonBg.x = 2048 / 2;
buttonBg.y = buttonData[i].y;
pauseMenu.addChild(buttonBg);
var buttonText = new Text2(buttonData[i].text, {
size: 70,
fill: 0xFFFFFF,
font: "Impact"
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 2048 / 2;
buttonText.y = buttonData[i].y;
pauseMenu.addChild(buttonText);
// Add click handlers
(function (action) {
buttonBg.down = function () {
handlePauseMenuAction(action);
};
buttonText.down = function () {
handlePauseMenuAction(action);
};
})(buttonData[i].action);
}
// Store overlay reference for cleanup
pauseMenu.overlay = overlay;
}
function handlePauseMenuAction(action) {
switch (action) {
case 'resume':
resumeGame();
break;
case 'restart':
restartGame();
break;
case 'menu':
returnToMainMenu();
break;
}
}
function resumeGame() {
if (pauseMenu) {
pauseMenu.overlay.destroy();
pauseMenu.destroy();
pauseMenu = null;
}
gamePaused = false;
}
function restartGame() {
if (pauseMenu) {
pauseMenu.overlay.destroy();
pauseMenu.destroy();
pauseMenu = null;
}
gamePaused = false;
startGame();
}
function returnToMainMenu() {
if (pauseMenu) {
pauseMenu.overlay.destroy();
pauseMenu.destroy();
pauseMenu = null;
}
gamePaused = false;
gameActive = false;
gameStarted = false;
showStartScreen();
}
// Initialize the start screen as the first state
showStartScreen();
; ===================================================================
--- original.js
+++ change.js
@@ -2422,22 +2422,44 @@
// Final safety check before loop
if (!activeMissions || !Array.isArray(activeMissions) || activeMissions.length === 0) {
return;
}
+ // Additional safety check to ensure array is properly formed
+ try {
+ // Test array access before loop
+ if (activeMissions.length > 0 && activeMissions[0] === undefined && activeMissions.length > 0) {
+ console.error('Array exists but elements are undefined');
+ return;
+ }
+ } catch (e) {
+ console.error('Error accessing activeMissions array:', e);
+ return;
+ }
for (var i = 0; i < activeMissions.length; i++) {
// Comprehensive safety check for array bounds and element existence
if (!activeMissions || !Array.isArray(activeMissions) || i >= activeMissions.length) {
continue;
}
+ // Additional bounds check
+ if (i < 0 || i >= activeMissions.length) {
+ continue;
+ }
// Safe access to array element with additional validation
var mission = null;
try {
- if (activeMissions[i] !== undefined && activeMissions[i] !== null) {
- mission = activeMissions[i];
+ // Extra safety check before accessing array element
+ if (activeMissions && Array.isArray(activeMissions) && i >= 0 && i < activeMissions.length) {
+ var arrayElement = activeMissions[i];
+ if (arrayElement !== undefined && arrayElement !== null) {
+ mission = arrayElement;
+ } else {
+ continue;
+ }
} else {
continue;
}
} catch (e) {
+ console.error('Error accessing mission at index', i, ':', e);
continue;
}
// Safety check for mission object
if (!mission || _typeof(mission) !== 'object') {