User prompt
as que todas las esferas que aparesen arriva que aparescan por todo el techo de el minijuego 3
User prompt
agrega que al lanzar la esfera en el minijuego 3 tenga que esperar a que colicione con otra esfera para bolver a lanzar , as que la esfera que este por lanzar tambien se mueva junto al cañon , osea que al mover el raton el cañon y las esferas se muevan a donde estoy apuntando ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
busca y elimina la parte de el codigo que interfiere con el cañon de el minijuego Nro 3 para que funcione
User prompt
intenta aser que funcione el disparo de el cañon para lanzar las esferas ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Implementación Urgente: Sistema de Disparo del Nivel 3 Necesito que la IA implemente la lógica de física y colisión para el BubbleShooter (Nivel 3). El código actual carece de movimiento, rebote y adhesión del proyectil. Funciones a Implementar Mecánica de Lanzamiento: Crear la función self.shootBubble(angle) para tomar self.currentBubble, convertirlo en self.shootingBubble, y asignarle velocidad (vx, vy) basada en el angle y self.shootPower. Motor Físico (update): Implementar la lógica dentro del ciclo de juego (o en un update de BubbleShooter) para que self.shootingBubble se mueva con su vx y vy. Añadir la detección y corrección de rebote al colisionar con los bordes laterales de la pantalla (2048px). Colisión y Adhesión a la Grilla (Lógica Central): Implementar la detección de colisión circular (self.checkCollision) entre self.shootingBubble y todas las burbujas estáticas en self.bubbleGrid. Al colisionar con una burbuja estática o el techo (y <= self.startY): La burbuja disparada debe detenerse. Debe ejecutarse self.findClosestGridPosition() para encontrar la celda hexagonal vacía más cercana y adherir la burbuja a esa posición con sus coordenadas exactas de la grilla. Después de la adhesión, debe llamarse a self.processBubbleElimination() para verificar si hay un match de 3 o más. CRÍTICO: Asegurar que la lógica de conteo de disparos fallidos (self.missedShots) y el posterior descenso de la grilla (self.moveGridDown()) se ejecuten solo cuando no haya un match. Con estas funciones, el Nivel 3 será completamente jugable. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Urgente: Corrección y Funcionalidad del Nivel 3 (Bubble Shooter) El código base del Nivel 3 está incompleto y tiene errores de lógica. Necesito que la IA implemente las siguientes correcciones y características críticas: 1. Implementación de Física y Colisión (Motor Principal) ESTA ES LA PARTE MÁS CRÍTICA: Implementar el Lanzamiento: Añadir la lógica de movimiento (velocidad shootPower = 15) y la trayectoria rectilínea para self.shootingBubble después de que el jugador dispare. Rebote en Paredes: La burbuja lanzada debe rebotar con ángulo inverso al chocar contra los límites izquierdo y derecho de la pantalla, como un rayo de luz. Detección de Colisión: La burbuja lanzada debe detectar la colisión de forma precisa (usando su caja de colisión circular) contra: Cualquier burbuja estática en la grilla (self.bubbleGrid). El límite superior de la pantalla (y <= self.startY). Ajuste de Adhesión (A la Grilla): Al detectarse la colisión, la burbuja lanzada debe detenerse inmediatamente y ajustar su posición central a la coordenada hexagonal vacía más cercana en self.bubbleGrid. 2. Correcciones de Lógica de la Grilla y Assets Corregir Límite de Grilla: Ajustar las funciones de la grilla (getNeighbors, createInitialBubbles, etc.) para que la grilla hexagonal se centre perfectamente y no desborde los bordes de la pantalla de 2048px. Corregir Color Faltante: El código de la clase Bubble menciona el color 'bubble_orange' (tipo 5), pero este asset no existe. Debes eliminar el color 5 o añadir el asset correspondiente. El número de colores debe coincidir con los assets disponibles. Línea de Muerte Dinámica: En self.checkLose(), la dangerLine debe ser una posición visible y fija cerca del fondo de la pantalla (ej., y = 2400), independientemente de si la grilla baja. 3. Funcionalidad de la Interfaz (UI) Activar Botón MENÚ: El botón 'MENÚ' en la esquina inferior derecha debe volverse interactivo. Al ser pulsado, debe ejecutar la acción de regresar a la pantalla de selección de niveles (cambiando el gameState). Ocultar UI Irrelevante: Asegúrate de que los textos de UI que no aplican a Bubble Shooter (ej., heightText o timerText) estén ocultos (alpha: 0) cuando se inicia el Nivel 3, para mantener la interfaz limpia. Mostrar Contador de Disparos Fallidos: Añade un texto de UI visible que muestre el valor actual de self.missedShots / self.maxMissedShots para indicar al jugador cuándo descenderá la grilla. Prioridad: La corrección del punto 1 (Física y Colisión) es absolutamente vital para que el juego sea funciona ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
elimina el codigo que dice el taimin nesesario para lanzar el proyectil de el nivel 3 / minijuego 3
User prompt
cambia el taiming de el disparo , eliminalo al taiming
User prompt
, ahora no lanza el proyectil , arreglalo
User prompt
arregla el taiming de disparo , el problema es que al intentar lanzar la una esfera tarda y ademas que agarra la trayectoria de la anterior luego de intental lanzar una luego de otra , ponle un taiming de 0.05 s ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
arregla el texto de menu para que este sentrado en el rectangulo de el
User prompt
elimina del codigo esos cuadrados berdes de el nivel 3 , y cambia la pocicion de el boton de menu , cambialo acia la esquina inferior de la pantalla en la derecha
User prompt
acomoda las coliciones de las esferas y sus tamaños , para que sea mas parejo y que las coliciones sean correctas
User prompt
que las esferas sean otro tipo de imagen , genera imagenes que te parescan adecuadas para las esferas , as que esas esferas sean mas grandes y que abansen y se generen otras desde eltecho , espande el lugar donde estan , quiero que ocupe toda la parte superior de la pantalla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'destroy')' in or related to this line: 'bubble.destroy();' Line Number: 220
User prompt
Nivel 3: Esferas en Caída Libre (Bubble Shooter) El Nivel 3 es un juego de puntería y gestión de espacio sin límite de tiempo, que exige al jugador evitar que una matriz de esferas descienda hasta la línea de peligro. 1. Elementos y Estructura del Tablero Esferas (Puntos): Se utiliza un mínimo de 5 a 6 colores de esferas distintas para formar la estructura y la munición. Diseño de Matriz: La estructura inicial de esferas debe estar organizada en una matriz hexagonal (tipo panal) en la parte superior. Esto es crucial para la correcta adhesión y lógica de conexión. Cañón y Apuntado: Un cañón en la parte inferior dispara una esfera a la vez. Debe mostrar la siguiente esfera a disparar. El sistema de apuntado incluye una línea de guía que muestra los rebotes en las paredes. 2. Lógica de Colisión y Reglas de Juego (El Código Crítico) Hitbox y Adhesión: Todas las esferas deben usar cajas de colisión circulares. Al impactar, la esfera disparada debe ajustar su posición automáticamente a la coordenada hexagonal vacía más cercana para unirse correctamente a la matriz. Explosión: La eliminación ocurre cuando tres (3) o más esferas del mismo color se conectan directamente. Gravedad y Combo (Caída en Cadena): CRÍTICO: Después de una explosión, debe ejecutarse un algoritmo de búsqueda de camino. Cualquier esfera que ya no tenga un camino de conexión al techo (la parte superior de la pantalla) debe ser marcada como 'flotante' y caer por gravedad fuera de la pantalla. Aumento de Presión: Para evitar que el juego se estanque, la matriz de esferas desciende una fila por cada 5 disparos que no resulten en una explosión. 3. Condiciones y Navegación Tiempo de Juego: El juego es continuo y no tiene límite de tiempo. Condición de Derrota: Ocurre si las esferas cruzan la Línea de Muerte inferior de la pantalla. Condición de Victoria: El jugador gana el nivel cuando despeja toda la pantalla de esferas. Botón de Menú: El texto interactivo 'MENÚ' en la esquina inferior derecha debe estar presente. Al ser pulsado, el jugador debe regresar a la pantalla principal (o de selección de juegos). ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que en el minijuego 2 que se no se gane , sino que se juege asta perder
User prompt
pon un rectangulo con el texto que diga menu , el cual te mande a la seleccion de los minijuegos
User prompt
as que al legar a los 5 mil puntos el jugador gane , luego se restablescan los puntos a 0 luego de ganar , as que en las tiendas al tocar en el boton de saltar que se esquipee el tiempo para elegir las mejoras
User prompt
tambien elimina el bloqueo de los demas niveles , y cambia el texto de los niveles , ponlos como minijuegos 1 2 3 4 y asi
User prompt
elimina el pedaso de codigo que indica que se borren los puntos luego de 5 jugadas
User prompt
elimina el codigo que ase que los textos desaparescan luedgo de el tiempo que esta establesido
User prompt
elimina la barra de energia de el codigo para que no moleste , enves de la barra mueve el contador de esferas acumuladas en donde estava la barra de energia
User prompt
tambien tienes que ponerle que al terminar el tiempo de la tienda desaparesca el texto tiendas de mejoras para que no moleste en la pantalla de el juego , as que no desaparescan los textos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
elimina de el codigo los textos de seleccionar el nivel , para que no estorbe , tambien el texto que indica para seleccionar mejora
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var CorruptedMemory = Container.expand(function () {
var self = Container.call(this);
var memoryGraphics = self.attachAsset('corruptedMemory', {
anchorX: 0.5,
anchorY: 0.5
});
// Add spikes around the corrupted memory
var spike1 = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
spike1.x = -30;
spike1.y = -30;
spike1.rotation = Math.PI / 4;
var spike2 = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
spike2.x = 30;
spike2.y = -30;
spike2.rotation = -Math.PI / 4;
var spike3 = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
spike3.x = 30;
spike3.y = 30;
spike3.rotation = Math.PI / 4;
var spike4 = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
spike4.x = -30;
spike4.y = 30;
spike4.rotation = -Math.PI / 4;
self.speed = 4;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EmotionCharacter = Container.expand(function (emotionType) {
var self = Container.call(this);
var characterGraphics = self.attachAsset(emotionType, {
anchorX: 0.5,
anchorY: 0.5
});
self.emotionType = emotionType;
self.health = 100;
self.maxHealth = 100;
return self;
});
var GoldenMemory = Container.expand(function () {
var self = Container.call(this);
var memoryGraphics = self.attachAsset('goldenMemory', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.lastY = undefined;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Pipe = Container.expand(function (isTop, gapY) {
var self = Container.call(this);
var pipeGraphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: isTop ? 1 : 0
});
pipeGraphics.tint = 0x4CAF50;
pipeGraphics.width = pipeWidth;
pipeGraphics.height = isTop ? gapY - pipeGap / 2 : 2732 - (gapY + pipeGap / 2);
self.speed = 4;
self.isTop = isTop;
self.scored = false;
self.lastX = undefined;
self.update = function () {
self.x -= self.speed;
};
return self;
});
var SideSpike = Container.expand(function (fromLeft) {
var self = Container.call(this);
var spikeGraphics = self.attachAsset('espinas', {
anchorX: 0.5,
anchorY: 0.5
});
self.fromLeft = fromLeft;
self.speed = fromLeft ? 8 : -8;
self.lastX = undefined;
self.update = function () {
self.x += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// All previously requested features have been successfully implemented:
// - Invisible hitboxes for JUGAR button and character selection
// - Jumpscare with 22.2% probability on game over
// - 223-second countdown timer with speed increase
// - Character pricing and storage system
// - Points accumulation (15 per sphere)
// - Win condition at 50000 points
// - Spike damage of 25 after timer expires
// If you need additional features, please specify what you'd like to add
// Character assets - Joy, Anger, Disgust, Fear
// Memory sphere assets
// Sound effects
// - Insufficient spheres error message ('No tienes esferas suficientes')
// - Character reset every 5 attempts except free characters (attemptCount % 5 === 0)
// - Jumpscare probability: 25% (line with Math.random() < 0.25)
// All requested features are already properly implemented:
var selectedEmotion = storage.selectedEmotion || 'joy';
var gameStarted = false;
var countdownActive = false;
var countdownValue = 3;
var character = null;
var goldenMemories = [];
var corruptedMemories = [];
var spawnTimer = 0;
var difficultyLevel = 1;
var health = 100;
var maxHealth = 100;
// Game state management
var gameState = 'menu'; // 'menu', 'levelSelection', 'characterSelection', 'countdown', 'playing'
var currentLevel = storage.currentLevel || 1;
var levelBoxes = [];
var characterSelectionActive = false;
var selectionButtons = [];
// Timer variables
var gameTimer = 223; // 223 seconds
var timerActive = false;
var speedIncreased = false;
// Character pricing and spheres
var totalSpheres = storage.totalSpheres || 0;
var attemptCount = storage.attemptCount || 0;
var characterPrices = {
joy: 0,
// Free
anger: 60,
disgust: 120,
fear: 180,
tristesa: 240
};
var ownedCharacters = storage.ownedCharacters || ['joy']; // Joy is free by default
// Level-specific attempt tracking
var levelAttempts = storage.levelAttempts || {};
// Track which levels are unlocked (level 1 is always unlocked)
var unlockedLevels = storage.unlockedLevels || [1];
// Speed boost variables for level 1
var speedBoostActive = false;
var speedBoostTimer = 0;
var isLeftMouseDown = false;
// Energy system variables
var maxEnergy = 100;
var currentEnergy = storage.currentEnergy || maxEnergy;
var energyBar = null;
var energyBarBg = null;
// Upgrade system variables
var sphereMultiplier = storage.sphereMultiplier || 1;
var speedMultiplier = storage.speedMultiplier || 1;
var maxHealthBonus = storage.maxHealthBonus || 0;
var shopItems = [];
// Shop timer variables
var shopTimer = 5;
var shopTimerActive = false;
var shopTimerText = null;
var shopTimerInterval = null;
// Level 2 specific variables - Flappy Bird style
var sideSpikes = [];
var birdVelocity = 0;
var gravity = 0.8;
var flapStrength = -12;
var pipes = [];
var pipeGap = 400;
var pipeWidth = 100;
var distanceTraveled = 0;
var scoreCounter = 0;
var heightText = new Text2('Distancia: 0m', {
size: 50,
fill: 0xFFFFFF
});
heightText.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(heightText);
heightText.y = 100;
// Add invisible collision box to heightText
var heightTextBox = LK.getAsset('level1', {
anchorX: 0,
anchorY: 0,
scaleX: 1.5,
scaleY: 0.5
});
heightTextBox.alpha = 0;
heightTextBox.x = 0;
heightTextBox.y = 100;
heightTextBox.textElement = heightText;
LK.gui.bottomLeft.addChild(heightTextBox);
// Auto-hide heightText after 10 seconds when visible
var heightTimeout = null;
heightText.showWithTimeout = function () {
if (heightTimeout) LK.clearTimeout(heightTimeout);
heightTimeout = LK.setTimeout(function () {
tween(heightText, {
alpha: 0
}, {
duration: 1000
});
tween(heightTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
// UI Elements
var scoreText = new Text2('Puntos: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.alpha = 0; // Hide initially
LK.gui.top.addChild(scoreText);
// Add invisible collision box to scoreText
var scoreTextBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 0.6
});
scoreTextBox.alpha = 0;
scoreTextBox.x = 0;
scoreTextBox.y = 0;
scoreTextBox.textElement = scoreText;
LK.gui.top.addChild(scoreTextBox);
// Auto-hide scoreText after 10 seconds when visible
var scoreTimeout = null;
scoreText.showWithTimeout = function () {
if (scoreTimeout) LK.clearTimeout(scoreTimeout);
scoreTimeout = LK.setTimeout(function () {
tween(scoreText, {
alpha: 0
}, {
duration: 1000
});
tween(scoreTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
var healthText = new Text2('Vida: 100/100', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(1, 0);
LK.gui.topRight.addChild(healthText);
// Add invisible collision box to healthText
var healthTextBox = LK.getAsset('level1', {
anchorX: 1,
anchorY: 0,
scaleX: 1.2,
scaleY: 0.5
});
healthTextBox.alpha = 0;
healthTextBox.x = 0;
healthTextBox.y = 0;
healthTextBox.textElement = healthText;
LK.gui.topRight.addChild(healthTextBox);
// Auto-hide healthText after 10 seconds when visible
var healthTimeout = null;
healthText.showWithTimeout = function () {
if (healthTimeout) LK.clearTimeout(healthTimeout);
healthTimeout = LK.setTimeout(function () {
tween(healthText, {
alpha: 0
}, {
duration: 1000
});
tween(healthTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
// Timer display
var timerText = new Text2('Tiempo: 223', {
size: 50,
fill: 0xFFFFFF
});
timerText.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(timerText);
// Add invisible collision box to timerText
var timerTextBox = LK.getAsset('level1', {
anchorX: 0,
anchorY: 1,
scaleX: 1.2,
scaleY: 0.5
});
timerTextBox.alpha = 0;
timerTextBox.x = 0;
timerTextBox.y = 0;
timerTextBox.textElement = timerText;
LK.gui.bottomLeft.addChild(timerTextBox);
// Auto-hide timerText after 10 seconds when visible
var timerTimeout = null;
timerText.showWithTimeout = function () {
if (timerTimeout) LK.clearTimeout(timerTimeout);
timerTimeout = LK.setTimeout(function () {
tween(timerText, {
alpha: 0
}, {
duration: 1000
});
tween(timerTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
// Energy bar background (dark blue)
energyBarBg = LK.getAsset('spike', {
anchorX: 1,
anchorY: 0,
scaleX: 8,
scaleY: 1
});
energyBarBg.tint = 0x000080;
energyBarBg.x = -20;
energyBarBg.y = 120;
LK.gui.topRight.addChild(energyBarBg);
// Energy bar (blue)
energyBar = LK.getAsset('spike', {
anchorX: 1,
anchorY: 0,
scaleX: 8,
scaleY: 1
});
energyBar.tint = 0x0099ff;
energyBar.x = -20;
energyBar.y = 120;
LK.gui.topRight.addChild(energyBar);
// Energy text
var energyText = new Text2('Energía', {
size: 30,
fill: 0xFFFFFF
});
energyText.anchor.set(1, 0);
energyText.x = -20;
energyText.y = 80;
LK.gui.topRight.addChild(energyText);
// Add invisible collision box to energyText
var energyTextBox = LK.getAsset('level1', {
anchorX: 1,
anchorY: 0,
scaleX: 0.8,
scaleY: 0.3
});
energyTextBox.alpha = 0;
energyTextBox.x = -20;
energyTextBox.y = 80;
energyTextBox.textElement = energyText;
LK.gui.topRight.addChild(energyTextBox);
// Auto-hide energyText after 10 seconds when visible
var energyTimeout = null;
energyText.showWithTimeout = function () {
if (energyTimeout) LK.clearTimeout(energyTimeout);
energyTimeout = LK.setTimeout(function () {
tween(energyText, {
alpha: 0
}, {
duration: 1000
});
tween(energyTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
// Main Menu UI
var titleText = new Text2('INTENSAMENTE', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
game.addChild(titleText);
// Add invisible collision box to titleText
var titleTextBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
titleTextBox.alpha = 0;
titleTextBox.x = titleText.x;
titleTextBox.y = titleText.y;
titleTextBox.textElement = titleText;
game.addChild(titleTextBox);
// Auto-hide titleText after 10 seconds
LK.setTimeout(function () {
tween(titleText, {
alpha: 0
}, {
duration: 1000
});
tween(titleTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
var playButton = new Text2('JUGAR', {
size: 80,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.x = 1024;
playButton.y = 1200;
game.addChild(playButton);
// Add invisible collision box to playButton
var playButtonBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8
});
playButtonBox.alpha = 0;
playButtonBox.x = playButton.x;
playButtonBox.y = playButton.y;
playButtonBox.textElement = playButton;
game.addChild(playButtonBox);
// Auto-hide playButton after 10 seconds
LK.setTimeout(function () {
tween(playButton, {
alpha: 0
}, {
duration: 1000
});
tween(playButtonBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
var instructionText = new Text2('Selecciona tu personaje', {
size: 80,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 600;
instructionText.alpha = 0;
instructionText.visible = false;
game.addChild(instructionText);
// Add invisible collision box to instructionText
var instructionTextBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 0.8
});
instructionTextBox.alpha = 0;
instructionTextBox.x = instructionText.x;
instructionTextBox.y = instructionText.y;
instructionTextBox.textElement = instructionText;
game.addChild(instructionTextBox);
// Auto-hide instructionText after 10 seconds when visible
var instructionTimeout = null;
var originalInstructionAlpha = instructionText.alpha;
instructionText.showWithTimeout = function () {
instructionText.alpha = 1;
instructionText.visible = true;
if (instructionTimeout) LK.clearTimeout(instructionTimeout);
instructionTimeout = LK.setTimeout(function () {
tween(instructionText, {
alpha: 0
}, {
duration: 1000
});
tween(instructionTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
var countdownText = new Text2('3', {
size: 200,
fill: 0xFFFFFF
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 1024;
countdownText.y = 1366;
countdownText.alpha = 0;
countdownText.visible = false;
game.addChild(countdownText);
// Add invisible collision box to countdownText
var countdownTextBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
countdownTextBox.alpha = 0;
countdownTextBox.x = countdownText.x;
countdownTextBox.y = countdownText.y;
countdownTextBox.textElement = countdownText;
game.addChild(countdownTextBox);
// Auto-hide countdownText after 10 seconds when visible
var countdownTimeout = null;
countdownText.showWithTimeout = function () {
countdownText.alpha = 1;
countdownText.visible = true;
if (countdownTimeout) LK.clearTimeout(countdownTimeout);
countdownTimeout = LK.setTimeout(function () {
tween(countdownText, {
alpha: 0
}, {
duration: 1000
});
tween(countdownTextBox, {
alpha: 0
}, {
duration: 1000
});
}, 10000);
};
// Spawn static character selection spheres in center
function spawnCharacterSelectionSpheres() {
// Only spawn once
if (goldenMemories.length === 0) {
var emotions = [{
type: 'joy',
name: 'ALEGRÍA',
color: 0xffeb3b,
x: 524,
y: 800
}, {
type: 'anger',
name: 'ENOJO',
color: 0xf44336,
x: 1524,
y: 800
}, {
type: 'disgust',
name: 'DESAGRADO',
color: 0x4caf50,
x: 524,
y: 1200
}, {
type: 'fear',
name: 'MIEDO',
color: 0x9c27b0,
x: 1024,
y: 1200
}, {
type: 'tristesa',
name: 'TRISTEZA',
color: 0x2196f3,
x: 1524,
y: 1200
}];
// Hide score text in character selection
scoreText.alpha = 0;
// Add spheres counter display only if not lvl1
if (currentLevel !== 1) {
var spheresText = new Text2('Esferas: ' + totalSpheres, {
size: 60,
fill: 0xFFD700
});
spheresText.anchor.set(0.5, 0.5);
spheresText.x = 1024;
spheresText.y = 500;
game.addChild(spheresText);
}
for (var i = 0; i < emotions.length; i++) {
var emotionData = emotions[i];
// Create character image instead of sphere
var characterImage = LK.getAsset(emotionData.type, {
anchorX: 0.5,
anchorY: 0.5
});
characterImage.x = emotionData.x;
characterImage.y = emotionData.y;
characterImage.characterType = emotionData.type;
game.addChild(characterImage);
goldenMemories.push(characterImage);
// Check if character is owned or affordable
var isOwned = ownedCharacters.indexOf(emotionData.type) !== -1;
var canAfford = totalSpheres >= characterPrices[emotionData.type];
var price = characterPrices[emotionData.type];
// Dim character if not owned and can't afford
if (!isOwned && !canAfford) {
characterImage.alpha = 0.3;
}
// Add text label with price
var labelText = emotionData.name;
if (!isOwned) {
labelText += '\nPrecio: ' + price + ' esferas';
} else {
labelText += '\nDISPONIBLE';
}
var nameText = new Text2(labelText, {
size: 35,
fill: isOwned ? 0x00FF00 : canAfford ? 0xFFFFFF : 0xFF6666
});
nameText.anchor.set(0.5, 0.5);
nameText.x = emotionData.x;
nameText.y = emotionData.y + 150;
game.addChild(nameText);
characterImage.nameText = nameText;
characterImage.isOwned = isOwned;
characterImage.canAfford = canAfford;
}
}
}
// Handle sphere selection for character choice
function handleSphereSelection(sphere) {
if (sphere.characterType) {
var characterType = sphere.characterType;
var isOwned = ownedCharacters.indexOf(characterType) !== -1;
var canAfford = totalSpheres >= characterPrices[characterType];
var price = characterPrices[characterType];
// Check if character can be selected
if (!isOwned && !canAfford) {
// Flash red to indicate can't select
LK.effects.flashObject(sphere, 0xFF0000, 500);
// Play error sound
LK.getSound('error').play();
// Show insufficient spheres message
var errorText = new Text2('No tienes esferas suficientes', {
size: 60,
fill: 0xFF0000
});
errorText.anchor.set(0.5, 0.5);
errorText.x = 1024;
errorText.y = 2200;
game.addChild(errorText);
// Remove error message after 2 seconds
LK.setTimeout(function () {
errorText.destroy();
}, 2000);
return;
}
// If not owned but can afford, purchase the character
if (!isOwned && canAfford) {
totalSpheres -= price;
ownedCharacters.push(characterType);
storage.totalSpheres = totalSpheres;
storage.ownedCharacters = ownedCharacters;
// Update spheres display after purchase
var spheresTextElements = [];
for (var k = 0; k < game.children.length; k++) {
if (game.children[k].text && game.children[k].text.indexOf('Esferas:') === 0) {
game.children[k].setText('Esferas: ' + totalSpheres);
break;
}
}
} else if (isOwned) {
// Character is already owned, no need to purchase again
} else {
// Character not owned and can't afford - deduct price anyway and add to owned
totalSpheres -= price;
if (totalSpheres < 0) totalSpheres = 0; // Prevent negative spheres
ownedCharacters.push(characterType);
storage.totalSpheres = totalSpheres;
storage.ownedCharacters = ownedCharacters;
// Update spheres display after purchase
for (var k = 0; k < game.children.length; k++) {
if (game.children[k].text && game.children[k].text.indexOf('Esferas:') === 0) {
game.children[k].setText('Esferas: ' + totalSpheres);
break;
}
}
}
selectedEmotion = characterType;
storage.selectedEmotion = selectedEmotion;
// Flash selected sphere
LK.effects.flashObject(sphere, 0xFFFFFF, 500);
// Clear all spheres and their labels
for (var i = goldenMemories.length - 1; i >= 0; i--) {
if (goldenMemories[i].nameText) {
goldenMemories[i].nameText.destroy();
}
goldenMemories[i].destroy();
goldenMemories.splice(i, 1);
}
// Instruction text already removed, no hiding needed
// Go to shop before starting game
LK.setTimeout(function () {
createShop();
}, 600);
}
}
// Create level selection UI
function createLevelSelection() {
gameState = 'levelSelection';
// Hide menu elements
titleText.alpha = 0;
playButton.alpha = 0;
// Level selection title removed to avoid interference
// Create level boxes in a grid (2 columns, 5 rows)
var levelNames = ['lvl1', 'lvl2', 'lvl3', 'lvl4', 'lvl5', 'lvl6', 'lvl7', 'lvl8', 'lvl9', 'lvl10'];
var levelAssets = ['level1', 'level2', 'level3', 'level4', 'level5', 'level6', 'level7', 'level8', 'level9', 'level10'];
for (var i = 0; i < 10; i++) {
var col = i % 2;
var row = Math.floor(i / 2);
var levelBox = LK.getAsset(levelAssets[i], {
anchorX: 0.5,
anchorY: 0.5
});
levelBox.x = 600 + col * 848; // 600 and 1448 for two columns
levelBox.y = 700 + row * 280; // Spacing between rows
levelBox.levelNumber = i + 1;
levelBox.levelName = levelNames[i];
game.addChild(levelBox);
levelBoxes.push(levelBox);
// Check if level is unlocked
var isUnlocked = unlockedLevels.indexOf(i + 1) !== -1;
// Dim locked levels
if (!isUnlocked) {
levelBox.alpha = 0.3;
}
// Add level text with lock status
var levelText = new Text2(levelNames[i].toUpperCase() + (isUnlocked ? '' : '\nBLOQUEADO'), {
size: isUnlocked ? 50 : 40,
fill: isUnlocked ? 0xFFFFFF : 0xFF6666
});
levelText.anchor.set(0.5, 0.5);
levelText.x = levelBox.x;
levelText.y = levelBox.y;
game.addChild(levelText);
levelBox.levelText = levelText;
levelBox.isUnlocked = isUnlocked;
}
}
// Create shop screen
function createShop() {
gameState = 'shop';
// Hide other UI elements
titleText.alpha = 0;
playButton.alpha = 0;
instructionText.alpha = 0;
// Shop title
var shopTitle = new Text2('TIENDA DE MEJORAS', {
size: 80,
fill: 0xFFD700
});
shopTitle.anchor.set(0.5, 0.5);
shopTitle.x = 1024;
shopTitle.y = 400;
game.addChild(shopTitle);
// Show current spheres
var spheresDisplay = new Text2('Esferas: ' + totalSpheres, {
size: 60,
fill: 0xFFFFFF
});
spheresDisplay.anchor.set(0.5, 0.5);
spheresDisplay.x = 1024;
spheresDisplay.y = 500;
game.addChild(spheresDisplay);
// Create shop items
var shopItemsData = [{
name: 'Multiplicador\nde Esferas',
description: 'x' + (sphereMultiplier + 0.2).toFixed(1),
price: Math.floor(50 * Math.pow(sphereMultiplier, 2)),
type: 'sphere_multiplier',
x: 524,
y: 800
}, {
name: 'Multiplicador\nde Velocidad',
description: '+5% Velocidad',
price: Math.floor(30 * Math.pow(speedMultiplier, 1.5)),
type: 'speed_multiplier',
x: 1024,
y: 800
}, {
name: 'Aumento\nde Vida',
description: '+5 Vida Max',
price: Math.floor(40 * Math.pow(maxHealthBonus / 5 + 1, 1.2)),
type: 'health_bonus',
x: 1524,
y: 800
}];
for (var i = 0; i < shopItemsData.length; i++) {
var itemData = shopItemsData[i];
// Create item box
var itemBox = LK.getAsset('level1', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
itemBox.x = itemData.x;
itemBox.y = itemData.y;
itemBox.itemType = itemData.type;
itemBox.price = itemData.price;
itemBox.tint = 0x00FF00;
game.addChild(itemBox);
shopItems.push(itemBox);
// Item name
var nameText = new Text2(itemData.name, {
size: 35,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.x = itemData.x;
nameText.y = itemData.y - 40;
game.addChild(nameText);
itemBox.nameText = nameText;
// Item description
var descText = new Text2(itemData.description, {
size: 30,
fill: 0xFFD700
});
descText.anchor.set(0.5, 0.5);
descText.x = itemData.x;
descText.y = itemData.y;
game.addChild(descText);
itemBox.descText = descText;
// Item price
var priceText = new Text2('Precio: ' + itemData.price, {
size: 30,
fill: totalSpheres >= itemData.price ? 0x00FF00 : 0xFF0000
});
priceText.anchor.set(0.5, 0.5);
priceText.x = itemData.x;
priceText.y = itemData.y + 40;
game.addChild(priceText);
itemBox.priceText = priceText;
}
// Continue button
var continueBtn = new Text2('CONTINUAR', {
size: 60,
fill: 0x00FF00
});
continueBtn.anchor.set(0.5, 0.5);
continueBtn.x = 1024;
continueBtn.y = 1200;
game.addChild(continueBtn);
shopItems.push(continueBtn);
continueBtn.isContinueBtn = true;
// Skip button
var skipBtn = new Text2('SALTAR', {
size: 60,
fill: 0x00FF00
});
skipBtn.anchor.set(0.5, 0.5);
skipBtn.x = 1024;
skipBtn.y = 1300;
game.addChild(skipBtn);
shopItems.push(skipBtn);
skipBtn.isSkipBtn = true;
// Shop timer display
shopTimerText = new Text2('Tiempo: 5', {
size: 60,
fill: 0xFF0000
});
shopTimerText.anchor.set(0.5, 0.5);
shopTimerText.x = 1024;
shopTimerText.y = 1000;
game.addChild(shopTimerText);
shopItems.push(shopTimerText);
// Start shop timer
shopTimer = 5;
shopTimerActive = true;
shopTimerInterval = LK.setInterval(function () {
shopTimer--;
shopTimerText.setText('Tiempo: ' + shopTimer);
if (shopTimer <= 0) {
LK.clearInterval(shopTimerInterval);
shopTimerActive = false;
// Auto-proceed when timer expires
// Clear shop UI
for (var j = shopItems.length - 1; j >= 0; j--) {
if (shopItems[j].nameText) shopItems[j].nameText.destroy();
if (shopItems[j].descText) shopItems[j].descText.destroy();
if (shopItems[j].priceText) shopItems[j].priceText.destroy();
shopItems[j].destroy();
}
shopItems = [];
// Clear shop title and spheres display
for (var k = game.children.length - 1; k >= 0; k--) {
if (game.children[k].text && (game.children[k].text.indexOf('TIENDA') === 0 || game.children[k].text.indexOf('Esferas:') === 0)) {
tween(game.children[k], {
alpha: 0
}, {
duration: 1000
});
LK.setTimeout(function (element) {
return function () {
if (element && element.destroy) {
element.destroy();
}
};
}(game.children[k]), 1000);
}
}
// Go to countdown
startCountdown();
}
}, 1000);
}
// Start character selection
function startCharacterSelection() {
gameState = 'characterSelection';
// Hide menu elements
titleText.alpha = 0;
playButton.alpha = 0;
// Character selection instruction text removed to avoid interference
// Spawn character selection spheres
spawnCharacterSelectionSpheres();
}
// Start countdown before game
function startCountdown() {
gameState = 'countdown';
countdownActive = true;
countdownValue = 3;
countdownText.showWithTimeout();
countdownText.setText('3');
var countdownInterval = LK.setInterval(function () {
countdownValue--;
if (countdownValue > 0) {
countdownText.setText(countdownValue.toString());
} else if (countdownValue === 0) {
countdownText.setText('¡Juega!');
} else {
LK.clearInterval(countdownInterval);
countdownText.alpha = 0;
countdownText.visible = false;
startActualGame();
}
}, 1000);
}
// Start the actual game
function startActualGame() {
gameState = 'playing';
countdownActive = false;
gameStarted = true;
// Initialize timer
gameTimer = 223;
timerActive = true;
speedIncreased = false;
// Show/hide UI elements based on level
if (currentLevel === 1) {
// Level 1: Show health, score, timer, energy
scoreText.alpha = 1;
scoreText.showWithTimeout();
healthText.alpha = 1;
healthText.showWithTimeout();
timerText.alpha = 1;
timerText.showWithTimeout();
heightText.alpha = 0;
energyBar.alpha = 1;
energyBarBg.alpha = 1;
energyText.alpha = 1;
energyText.showWithTimeout();
} else if (currentLevel === 2) {
// Level 2: Show only distance and score
scoreText.alpha = 1;
scoreText.showWithTimeout();
healthText.alpha = 0;
timerText.alpha = 0;
heightText.alpha = 1;
heightText.showWithTimeout();
energyBar.alpha = 0;
energyBarBg.alpha = 0;
energyText.alpha = 0;
} else {
// Other levels: Show score only
scoreText.alpha = 1;
scoreText.showWithTimeout();
healthText.alpha = 0;
timerText.alpha = 0;
heightText.alpha = 0;
energyBar.alpha = 1;
energyBarBg.alpha = 1;
energyText.alpha = 1;
energyText.showWithTimeout();
}
// Create player character
character = new EmotionCharacter(selectedEmotion);
if (currentLevel === 2) {
// Spawn in middle of screen for Flappy Bird level
character.x = 1024;
character.y = 1366; // Middle of screen vertically
// Reset level 2 specific variables
birdVelocity = 0;
distanceTraveled = 0;
scoreCounter = 0;
// Clear any existing pipes
for (var p = pipes.length - 1; p >= 0; p--) {
pipes[p].destroy();
}
pipes = [];
} else {
character.x = 1024;
character.y = 2400;
// Reset level 1 specific variables with upgrades
health = 100 + maxHealthBonus;
maxHealth = 100 + maxHealthBonus;
healthText.setText('Vida: ' + health + '/' + maxHealth);
// Clear any existing memories
for (var g = goldenMemories.length - 1; g >= 0; g--) {
goldenMemories[g].destroy();
}
goldenMemories = [];
for (var c = corruptedMemories.length - 1; c >= 0; c--) {
corruptedMemories[c].destroy();
}
corruptedMemories = [];
}
game.addChild(character);
// Start level-specific background music
if (currentLevel === 2) {
LK.playMusic('musica_de_nivel_2');
} else {
LK.playMusic('gameMusic');
}
}
// Spawn memory function
function spawnMemory() {
if (gameState === 'characterSelection') {
// Character selection phase - spawn static character spheres in center
spawnCharacterSelectionSpheres();
} else if (gameState === 'playing') {
// Game phase - spawn colored spheres and corrupted ones
var spawnX = Math.random() * (2048 - 160) + 80;
var randomType = Math.random();
// Define sphere colors for optimization
var sphereColors = [0xffeb3b, 0x4caf50, 0x2196f3, 0xf44336];
var colorThresholds = [0.15, 0.3, 0.45, 0.6];
// Calculate time-based spine multiplier - more spines as time progresses
var initialTimer = 223;
var timeElapsed = initialTimer - gameTimer;
var timeProgressRatio = Math.min(timeElapsed / initialTimer, 1); // 0 to 1 progression
// Base spine spawn probability increases with time (starts at 0.33, goes up to 0.85)
var baseSpineProbability = 0.33 + timeProgressRatio * 0.52;
// Check for golden memory creation - probability decreases over time to allow for more spines
var goldenProbability = 0.67 * (1 - timeProgressRatio * 0.6); // Decreases from 0.67 to ~0.27
var createGolden = false;
var tintColor = 0xffeb3b;
for (var i = 0; i < colorThresholds.length; i++) {
if (randomType < colorThresholds[i] * goldenProbability) {
createGolden = true;
tintColor = sphereColors[i];
break;
}
}
if (createGolden) {
var memory = new GoldenMemory();
memory.x = spawnX;
memory.y = -100;
memory.lastY = memory.y;
memory.children[0].tint = tintColor;
goldenMemories.push(memory);
game.addChild(memory);
} else {
// Corrupted memory with spikes - spawn rate increases dramatically over time
var corrupted = new CorruptedMemory();
corrupted.x = spawnX;
corrupted.y = -100;
corrupted.lastY = corrupted.y;
corruptedMemories.push(corrupted);
game.addChild(corrupted);
}
}
}
// Game event handlers
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if JUGAR button was clicked with invisible hitbox
var playButtonX = playButton.x - playButton.width / 2;
var playButtonY = playButton.y - playButton.height / 2;
var playButtonWidth = playButton.width;
var playButtonHeight = playButton.height;
if (x >= playButtonX && x <= playButtonX + playButtonWidth && y >= playButtonY && y <= playButtonY + playButtonHeight) {
createLevelSelection();
}
} else if (gameState === 'levelSelection') {
// Check if any level box was clicked
for (var i = 0; i < levelBoxes.length; i++) {
var levelBox = levelBoxes[i];
var boxX = levelBox.x - 150; // Half of width (300/2)
var boxY = levelBox.y - 100; // Half of height (200/2)
var boxWidth = 300;
var boxHeight = 200;
if (x >= boxX && x <= boxX + boxWidth && y >= boxY && y <= boxY + boxHeight) {
// Check if level is unlocked
if (!levelBox.isUnlocked) {
// Flash red to indicate locked
LK.effects.flashObject(levelBox, 0xFF0000, 500);
LK.getSound('error').play();
return;
}
// Flash selected level
LK.effects.flashObject(levelBox, 0xFFFFFF, 500);
// Set current level
currentLevel = levelBox.levelNumber;
storage.currentLevel = currentLevel;
// Clear level selection UI
for (var j = levelBoxes.length - 1; j >= 0; j--) {
if (levelBoxes[j].levelText) {
levelBoxes[j].levelText.destroy();
}
levelBoxes[j].destroy();
}
levelBoxes = [];
// Level selection title already removed, no cleanup needed
// Start character selection after short delay
LK.setTimeout(function () {
startCharacterSelection();
}, 600);
break;
}
}
} else if (gameState === 'shop') {
// Handle shop item clicks
for (var i = 0; i < shopItems.length; i++) {
var item = shopItems[i];
var itemX = item.x - 150;
var itemY = item.y - 100;
var itemWidth = 300;
var itemHeight = 200;
if (x >= itemX && x <= itemX + itemWidth && y >= itemY && y <= itemY + itemHeight) {
if (item.isContinueBtn || item.isSkipBtn) {
// Clear shop timer
if (shopTimerInterval) {
LK.clearInterval(shopTimerInterval);
shopTimerActive = false;
}
// Clear shop UI
for (var j = shopItems.length - 1; j >= 0; j--) {
if (shopItems[j].nameText) shopItems[j].nameText.destroy();
if (shopItems[j].descText) shopItems[j].descText.destroy();
if (shopItems[j].priceText) shopItems[j].priceText.destroy();
shopItems[j].destroy();
}
shopItems = [];
// Clear shop title and spheres display
for (var k = game.children.length - 1; k >= 0; k--) {
if (game.children[k].text && (game.children[k].text.indexOf('TIENDA') === 0 || game.children[k].text.indexOf('Esferas:') === 0)) {
game.children[k].destroy();
}
}
if (item.isSkipBtn) {
// Skip shop, go directly to countdown
startCountdown();
} else {
startCharacterSelection();
}
break;
} else if (totalSpheres >= item.price) {
// Purchase item
totalSpheres -= item.price;
storage.totalSpheres = totalSpheres;
if (item.itemType === 'sphere_multiplier') {
sphereMultiplier += 0.2;
storage.sphereMultiplier = sphereMultiplier;
} else if (item.itemType === 'speed_multiplier') {
speedMultiplier += 0.05;
storage.speedMultiplier = speedMultiplier;
} else if (item.itemType === 'health_bonus') {
maxHealthBonus += 5;
storage.maxHealthBonus = maxHealthBonus;
}
LK.effects.flashObject(item, 0x00FF00, 300);
LK.getSound('collect').play();
// Clear shop timer before recreating
if (shopTimerInterval) {
LK.clearInterval(shopTimerInterval);
shopTimerActive = false;
}
// Recreate shop to update prices
for (var j = shopItems.length - 1; j >= 0; j--) {
if (shopItems[j].nameText) shopItems[j].nameText.destroy();
if (shopItems[j].descText) shopItems[j].descText.destroy();
if (shopItems[j].priceText) shopItems[j].priceText.destroy();
shopItems[j].destroy();
}
shopItems = [];
for (var k = game.children.length - 1; k >= 0; k--) {
if (game.children[k].text && (game.children[k].text.indexOf('TIENDA') === 0 || game.children[k].text.indexOf('Esferas:') === 0)) {
game.children[k].destroy();
}
}
createShop();
break;
} else {
LK.effects.flashObject(item, 0xFF0000, 300);
LK.getSound('error').play();
}
}
}
} else if (gameState === 'characterSelection') {
// Check if any character sphere was clicked with invisible hitboxes
for (var i = 0; i < goldenMemories.length; i++) {
var sphere = goldenMemories[i];
var sphereX = sphere.x - 60; // Sphere width is 120, so half is 60
var sphereY = sphere.y - 60; // Sphere height is 120, so half is 60
var sphereWidth = 120;
var sphereHeight = 120;
if (x >= sphereX && x <= sphereX + sphereWidth && y >= sphereY && y <= sphereY + sphereHeight) {
handleSphereSelection(sphere);
break;
}
}
} else if (gameState === 'playing' && currentLevel === 2) {
// Handle flapping in lvl2 - Flappy Bird style
if (character) {
birdVelocity = flapStrength;
}
} else if (gameState === 'playing' && currentLevel === 1) {
// Handle speed boost for level 1
isLeftMouseDown = true;
// Activate speed boost if player has energy
if (currentEnergy > 0 && !speedBoostActive) {
speedBoostActive = true;
speedBoostTimer = 0;
// Flash screen to indicate speed boost activation
LK.effects.flashScreen(0x00FF00, 200);
}
}
};
game.up = function (x, y, obj) {
if (gameState === 'playing' && currentLevel === 1) {
// Stop speed boost when left click is released
isLeftMouseDown = false;
if (speedBoostActive) {
speedBoostActive = false;
speedBoostTimer = 0;
// Flash screen to indicate speed boost deactivation
LK.effects.flashScreen(0xFF0000, 200);
}
}
};
game.move = function (x, y, obj) {
if (gameStarted && character) {
if (currentLevel === 2) {
// In lvl2, character stays in middle horizontal position for Flappy Bird
character.x = 1024;
// Y position is handled by gravity and flapping in update
} else {
// Original behavior for lvl1
var targetX = Math.max(60, Math.min(1988, x));
var targetY = Math.max(60, Math.min(2672, y));
character.x = targetX;
character.y = targetY;
}
}
};
// Start spawning spheres for character selection
// Main game update loop
game.update = function () {
// Handle different game states
if (gameState === 'menu') {
// Stop any playing music in menu
LK.stopMusic();
return; // No updates needed in menu
}
if (gameState === 'levelSelection') {
// Static level boxes, no updates needed
return;
}
if (gameState === 'characterSelection') {
// Static spheres, no updates needed
return;
}
if (gameState === 'countdown') {
return; // Countdown handles itself
}
if (gameState !== 'playing') {
return;
}
// Handle energy system for level 1
if (currentLevel === 1) {
if (speedBoostActive && isLeftMouseDown && currentEnergy > 0) {
// Consume energy while speed boost is active
currentEnergy -= 2; // 2 energy per frame
if (currentEnergy <= 0) {
currentEnergy = 0;
speedBoostActive = false;
isLeftMouseDown = false;
LK.effects.flashScreen(0xFF0000, 200);
}
} else if (!speedBoostActive || !isLeftMouseDown) {
speedBoostActive = false;
}
// Update energy bar visual
var energyPercent = currentEnergy / maxEnergy;
energyBar.scaleX = 8 * energyPercent;
// Keep energy bar anchored to the right
energyBar.x = -20;
storage.currentEnergy = currentEnergy;
}
// Update timer
if (timerActive && LK.ticks % 60 === 0) {
// Update every second (60 ticks = 1 second at 60 FPS)
gameTimer--;
timerText.setText('Tiempo: ' + gameTimer);
// When timer reaches 0, increase speed
if (gameTimer <= 0 && !speedIncreased) {
speedIncreased = true;
timerActive = false;
// Speed increase will be handled in the speed calculation section below
}
}
// Game playing state - spawn spheres or spikes based on level
spawnTimer++;
if (currentLevel === 2) {
// Level 2: Flappy Bird mechanics - completely separate from other levels
// Spawn pipes
var pipeSpawnRate = 120; // Spawn pipe every 2 seconds
if (spawnTimer >= pipeSpawnRate) {
var gapY = Math.random() * (2000 - 700) + 700; // Random gap position between y 700-2000
// Create top pipe
var topPipe = new Pipe(true, gapY);
topPipe.x = 2100;
topPipe.y = gapY - pipeGap / 2;
topPipe.lastX = topPipe.x;
pipes.push(topPipe);
game.addChild(topPipe);
// Create bottom pipe
var bottomPipe = new Pipe(false, gapY);
bottomPipe.x = 2100;
bottomPipe.y = gapY + pipeGap / 2;
bottomPipe.lastX = bottomPipe.x;
pipes.push(bottomPipe);
game.addChild(bottomPipe);
spawnTimer = 0;
}
// Handle Flappy Bird physics
if (character) {
// Apply gravity
birdVelocity += gravity;
character.y += birdVelocity;
// Check boundaries - only bounce off top, die on bottom and left
if (character.y < 50) {
character.y = 50;
birdVelocity = 0;
}
// Check win condition for level 2 - complete at 1000m distance
if (distanceTraveled >= 1000) {
// Unlock next level if current level is completed
var nextLevel = currentLevel + 1;
if (nextLevel <= 10 && unlockedLevels.indexOf(nextLevel) === -1) {
unlockedLevels.push(nextLevel);
storage.unlockedLevels = unlockedLevels;
}
// Convert distance to spheres and add to total
var spheresEarned = Math.floor(distanceTraveled / 10);
totalSpheres += spheresEarned;
storage.totalSpheres = totalSpheres;
// Show level completed
LK.showYouWin();
return;
}
// Check death conditions: left edge or bottom
if (character.x <= 0 || character.y > 2680) {
// Hit left edge or ground - game over
attemptCount++;
storage.attemptCount = attemptCount;
// Track level-specific attempts
if (!levelAttempts[currentLevel]) {
levelAttempts[currentLevel] = 0;
}
levelAttempts[currentLevel]++;
storage.levelAttempts = levelAttempts;
// Reset spheres after 5 attempts in this level
if (levelAttempts[currentLevel] % 5 === 0) {
totalSpheres = 0;
storage.totalSpheres = 0;
// Reset owned characters except free ones
ownedCharacters = ['joy'];
storage.ownedCharacters = ownedCharacters;
} else {
// Convert distance to spheres (divide by 10)
var spheresEarned = Math.floor(distanceTraveled / 10);
totalSpheres += spheresEarned;
storage.totalSpheres = totalSpheres;
}
LK.showGameOver();
return;
}
// Update distance
distanceTraveled += 4; // Distance increases as pipes move
heightText.setText('Distancia: ' + Math.floor(distanceTraveled) + 'm');
}
// Update pipes and check collisions
for (var p = pipes.length - 1; p >= 0; p--) {
var pipe = pipes[p];
if (pipe.lastX === undefined) pipe.lastX = pipe.x;
var shouldRemovePipe = false;
// Check if off screen
if (pipe.lastX >= -pipeWidth && pipe.x < -pipeWidth) {
shouldRemovePipe = true;
}
// Check collision with character - bounce instead of game over
if (character && pipe.intersects(character)) {
// Bounce character away from pipe
if (pipe.isTop) {
// Hit top pipe - bounce down
character.y = pipe.y + pipe.height + 20;
birdVelocity = 5; // Push down
} else {
// Hit bottom pipe - bounce up
character.y = pipe.y - 20;
birdVelocity = -5; // Push up
}
// Flash character red to indicate collision
LK.effects.flashObject(character, 0xFF0000, 300);
}
// Check if passed pipe for scoring (only check bottom pipes to avoid double scoring)
if (!pipe.isTop && !pipe.scored && pipe.lastX >= character.x && pipe.x < character.x) {
pipe.scored = true;
scoreCounter++;
LK.setScore(scoreCounter);
scoreText.setText('Puntos: ' + LK.getScore());
LK.getSound('collect').play();
}
if (shouldRemovePipe) {
pipe.destroy();
pipes.splice(p, 1);
} else {
pipe.lastX = pipe.x;
}
}
// Level 2 specific updates only
return; // Skip level 1 logic for level 2
} else if (currentLevel === 1) {
// Level 1 logic - completely separate from other levels
var spawnRate = Math.max(30, 90 - difficultyLevel * 5);
if (spawnTimer >= spawnRate) {
spawnMemory();
spawnTimer = 0;
}
}
// Increase difficulty over time
if (LK.getScore() > 0 && LK.getScore() % 10 === 0) {
difficultyLevel = Math.floor(LK.getScore() / 10) + 1;
}
// Spawn rate already handled at top of update function
// Only update memories for level 1
if (currentLevel === 1) {
// Update golden memories
for (var i = goldenMemories.length - 1; i >= 0; i--) {
var golden = goldenMemories[i];
// Initialize lastY if needed
if (golden.lastY === undefined) golden.lastY = golden.y;
var shouldRemove = false;
// Check if off screen
if (golden.lastY <= 2732 && golden.y > 2732) {
shouldRemove = true;
} else if (character && gameStarted && golden.intersects(character)) {
// Check collision with character for game phase
var spherePoints = Math.floor(3 * sphereMultiplier);
// Disgust character gets 2x spheres
if (selectedEmotion === 'disgust') {
spherePoints = Math.floor(6 * sphereMultiplier);
}
LK.setScore(LK.getScore() + spherePoints);
scoreText.setText('Puntos: ' + LK.getScore());
LK.getSound('collect').play();
// Flash character gold
LK.effects.flashObject(character, 0xFFD700, 300);
// Recharge energy
currentEnergy = Math.min(maxEnergy, currentEnergy + 15);
shouldRemove = true;
} else if (!gameStarted && !countdownActive && golden.characterType && golden.y > 500 && golden.y < 2000) {
// Check collision for character selection phase
handleSphereSelection(golden);
shouldRemove = true;
}
if (shouldRemove) {
golden.destroy();
goldenMemories.splice(i, 1);
} else {
golden.lastY = golden.y;
}
}
// Update corrupted memories
for (var j = corruptedMemories.length - 1; j >= 0; j--) {
var corrupted = corruptedMemories[j];
// Initialize lastY if needed
if (corrupted.lastY === undefined) corrupted.lastY = corrupted.y;
var shouldRemove = false;
// Check if off screen
if (corrupted.lastY <= 2732 && corrupted.y > 2732) {
shouldRemove = true;
} else if (character && corrupted.intersects(character)) {
// Check collision with character
var damage = speedIncreased ? 25 : 20;
health -= damage;
healthText.setText('Vida: ' + health + '/' + maxHealth);
LK.getSound('damage').play();
// Flash character red
LK.effects.flashObject(character, 0xFF0000, 500);
shouldRemove = true;
// Check game over
if (health <= 0) {
// Stop character from following cursor
if (character) {
tween.stop(character);
}
// Increment attempt counter
attemptCount++;
storage.attemptCount = attemptCount;
// Track level-specific attempts
if (!levelAttempts[currentLevel]) {
levelAttempts[currentLevel] = 0;
}
levelAttempts[currentLevel]++;
storage.levelAttempts = levelAttempts;
// Reset accumulated points every 5 attempts in this level
if (levelAttempts[currentLevel] % 5 === 0) {
totalSpheres = 0;
storage.totalSpheres = 0;
// Reset owned characters except free ones
ownedCharacters = ['joy'];
storage.ownedCharacters = ownedCharacters;
} else {
// Add accumulated points to total spheres
totalSpheres += LK.getScore();
storage.totalSpheres = totalSpheres;
}
// Show game over immediately
LK.showGameOver();
return;
}
}
if (shouldRemove) {
corrupted.destroy();
corruptedMemories.splice(j, 1);
} else {
corrupted.lastY = corrupted.y;
}
}
}
// Calculate speed only for level 1
if (currentLevel === 1) {
var goldenBaseSpeed = (3 + difficultyLevel * 0.5) * speedMultiplier;
var corruptedBaseSpeed = (4 + difficultyLevel * 0.5) * speedMultiplier;
if (speedIncreased) {
goldenBaseSpeed += goldenBaseSpeed * 0.5;
corruptedBaseSpeed += corruptedBaseSpeed * 0.5;
}
// Double speed for lvl1
goldenBaseSpeed *= 2;
corruptedBaseSpeed *= 2;
// Apply speed boost multiplier if active
if (speedBoostActive) {
goldenBaseSpeed *= 2;
corruptedBaseSpeed *= 2;
}
// Apply calculated speeds
for (var k = 0; k < goldenMemories.length; k++) {
goldenMemories[k].speed = goldenBaseSpeed;
}
for (var l = 0; l < corruptedMemories.length; l++) {
corruptedMemories[l].speed = corruptedBaseSpeed;
}
}
// Check win condition (500 spheres)
if (totalSpheres >= 500) {
// Create large green "GANASTE" text
var winText = new Text2('GANASTE', {
size: 200,
fill: 0x00FF00
});
winText.anchor.set(0.5, 0.5);
winText.x = 1024;
winText.y = 1366;
game.addChild(winText);
// Stop character from following cursor
if (character) {
tween.stop(character);
}
// Unlock next level if current level is completed
var nextLevel = currentLevel + 1;
if (nextLevel <= 10 && unlockedLevels.indexOf(nextLevel) === -1) {
unlockedLevels.push(nextLevel);
storage.unlockedLevels = unlockedLevels;
}
// Reset accumulated spheres to 0 when winning
totalSpheres = 0;
storage.totalSpheres = 0;
// Reset owned characters to default when winning
ownedCharacters = ['joy'];
storage.ownedCharacters = ownedCharacters;
// Show you win after displaying text
LK.setTimeout(function () {
LK.showYouWin();
}, 3000);
}
// Check win condition (score of 50000)
if (LK.getScore() >= 50000) {
// Stop character from following cursor
if (character) {
tween.stop(character);
}
// Unlock next level if current level is completed
var nextLevel = currentLevel + 1;
if (nextLevel <= 10 && unlockedLevels.indexOf(nextLevel) === -1) {
unlockedLevels.push(nextLevel);
storage.unlockedLevels = unlockedLevels;
}
// Increment attempt counter
attemptCount++;
storage.attemptCount = attemptCount;
// Track level-specific attempts
if (!levelAttempts[currentLevel]) {
levelAttempts[currentLevel] = 0;
}
levelAttempts[currentLevel]++;
storage.levelAttempts = levelAttempts;
// Reset accumulated points every 5 attempts in this level
if (levelAttempts[currentLevel] % 5 === 0) {
totalSpheres = 0;
storage.totalSpheres = 0;
// Reset owned characters except free ones
ownedCharacters = ['joy'];
storage.ownedCharacters = ownedCharacters;
} else {
// Add accumulated points to total spheres
totalSpheres += LK.getScore();
storage.totalSpheres = totalSpheres;
}
// Also reset owned characters when winning with high score
ownedCharacters = ['joy'];
storage.ownedCharacters = ownedCharacters;
LK.showYouWin();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -908,9 +908,20 @@
shopItems = [];
// Clear shop title and spheres display
for (var k = game.children.length - 1; k >= 0; k--) {
if (game.children[k].text && (game.children[k].text.indexOf('TIENDA') === 0 || game.children[k].text.indexOf('Esferas:') === 0)) {
- game.children[k].destroy();
+ tween(game.children[k], {
+ alpha: 0
+ }, {
+ duration: 1000
+ });
+ LK.setTimeout(function (element) {
+ return function () {
+ if (element && element.destroy) {
+ element.destroy();
+ }
+ };
+ }(game.children[k]), 1000);
}
}
// Go to countdown
startCountdown();