User prompt
Cuando paso el mouse por encima de los botones de Jugar Reiniciar y Menu, haz que se hagan maÌs opacos, como si los estuviera seleccionando, cuando se retire el mouse de ellos que vuelvan a su color normal.
User prompt
Excelente, ahora que los botones de Jugar, Reiniciar y Menu, haz que sean assets para ponerles la imagen que yo modifique.
User prompt
Cuando terminas el juego por primera vez, agrega una variable llamada Inicio, esta variable se hara true cuando termines el juego por primera vez, si la variable Inicio == true entonces retrasa el play a la musica .2 segundos.
Code edit (2 edits merged)
Please save this source code
User prompt
Ya aparecen los botones cuando voy a menu y reinicio pero detras todo se pone negro, no deberia, deberia verse asi. La otra es que despues de haber reiniciado o ir a menu, agregues un delay a todas las acciones del juego de .2 segundos al volver a iniciar. Asi ahunque la musica empiece un pcoo tarde todo ira en sincronia.
User prompt
Cuando reinicio, o voy a menu y vuelvo a jugar, la musica inicia un poco despues de lo que inicia normalmente y al final no aparecen los botones de menuÌ y reinicio.
User prompt
Bien, ahora necesito que todo este juego lo pongas en una segunda escena, el juego debe comenzar con un Menu, ese menu debe tener un boton y cuando se presione ese boton debe inicar esta escena con este juego sin modificar nada dentro del codigo de juego actual, cuando el juego termine despues de mostrar las estrellas muestra dos botones, uno de reinicio y uno de menu, el de menu te regresa al menu principal y el de reinicio reinicia esa escena.
User prompt
Si no cortaste ninguna fruta debe ser una nueva imagen, estrellas0.
User prompt
Cuando termina el juego deben aparecer estrellas, en el centro de la pantalla un nuevo Asset, Estrellas1, Estrellas2, Estrellas3. Si cortaste 6 frutas o menos sale Estrella1, si cortaste entre 6 a 11 frutas es Estrella2, si cortaste todas las estrellas sale Estrella3. Esto debe ser 18 segundos despues de haber disparado el Go!, tambien manda un sonido por cada estrella, cuando se Estrella1 inicia un sonido E1, con estrella2 un sonido E2, con estrella3 un sonid E3.
Code edit (2 edits merged)
Please save this source code
User prompt
La imagen de combo debe hacer spawn con el 50% de tamanÌo y ahumentar su tamanÌo para llegar al 100% en .1 segundos , .2 segundos se muestra y se hace fde out en .1 segundos. âȘđĄ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: tween.cancel is not a function' in or related to this line: 'tween.cancel(comboImage);' Line Number: 474
User prompt
Lo que esta pasando es que si la imagen es reemplazada por una nueva imagen de combo, el tiempo todavia transcurre y esa nueva imagen de combo se hace fade inmediatamente, necesito que si sse anÌade una nueva imagen de combo, el tiempo de fadese reinicie.
Code edit (5 edits merged)
Please save this source code
User prompt
Del Combo8 se regresa al 1, debe llegar hasta el 12
User prompt
En lugar del combo estar siempre en pantalla mostrarlo brevemente y hacer fade out .5 segundos despues. En lugar de un texto que sea una imagen Asset, el combo maximo es 12 asi que pon 12 objetos asset y llenare todos con la imagen combo que necesito en cada ocacion, no lo muestres centrado, muestralo en la parte superior derecha del juego. âȘđĄ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Si el mouse esta entre la posicioÌn vertical entre 350 y 750 cuando corta una linea suma 1 al contador de Combo, si corta una fruta fuera de ese espacio o una fruta es eliminada sin haber sido cortada regresa el contador de combo a 0.
Code edit (1 edits merged)
Please save this source code
Code edit (23 edits merged)
Please save this source code
User prompt
Aplica este cambio en el codigo.
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (17 edits merged)
Please save this source code
User prompt
Mismo error, la primera fruta de la tercera ronda sigue siendo eliminada inmediatamente despueÌs de ser disparada.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Clase Cannon para mostrar el cañón y animar disparo var Cannon = Container.expand(function () { var self = Container.call(this); // Asset del cañón (ahora usa la imagen personalizada) self.cannonAsset = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 1 }); // Efecto de fogonazo al disparar self.flash = null; // Estado self.isVisible = true; self.isShooting = false; // PosiciĂłn base (centrado horizontal, abajo) self.baseX = 2048 / 2; // Coloca el cañón pegado a la parte baja del juego (anchorY:1, asĂ que baseY es exactamente el borde inferior) self.baseY = 2732; self.x = self.baseX; self.y = self.baseY; // Mostrar cañón self.show = function () { self.visible = true; self.isVisible = true; // Animar subida si estaba oculto tween(self, { y: self.baseY }, { duration: 350, easing: tween.cubicOut }); }; // Animar disparo (pequeño retroceso y fogonazo) self.shoot = function () { if (self.isShooting) { return; } self.isShooting = true; // Retroceso rĂĄpido tween(self, { y: self.baseY - 60 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { // Regresa a posiciĂłn base tween(self, { y: self.baseY }, { duration: 120, easing: tween.cubicIn, onFinish: function onFinish() { self.isShooting = false; } }); } }); // Fogonazo visual if (!self.flash) { self.flash = self.attachAsset('cut_zone', { anchorX: 0.5, anchorY: 1, x: 0, y: -self.cannonAsset.height + 30, scaleX: 0.5, scaleY: 0.3, alpha: 0.0, color: 0xffffcc }); } self.flash.alpha = 0.7; self.flash.scaleX = 0.5; self.flash.scaleY = 0.3; tween(self.flash, { alpha: 0, scaleX: 1.2, scaleY: 0.7 }, { duration: 120, easing: tween.linear }); }; return self; }); // Clase para el objeto de cuenta regresiva "Go" var CountdownGo = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('Go', { anchorX: 0.5, anchorY: 0.5 }); self.radius = self.asset.width / 2; self.isActive = true; self.state = 'countdown'; self.destroyCountdown = function () { self.isActive = false; self.visible = false; self.destroy(); }; return self; }); // Clase para el objeto de cuenta regresiva "1" var CountdownOne = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('1', { anchorX: 0.5, anchorY: 0.5 }); self.radius = self.asset.width / 2; self.isActive = true; self.state = 'countdown'; self.destroyCountdown = function () { self.isActive = false; self.visible = false; self.destroy(); }; return self; }); // Clase para el objeto de cuenta regresiva "2" var CountdownTwo = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('2', { anchorX: 0.5, anchorY: 0.5 }); self.radius = self.asset.width / 2; self.isActive = true; self.state = 'countdown'; self.destroyCountdown = function () { self.isActive = false; self.visible = false; self.destroy(); }; return self; }); var Fruit = Container.expand(function () { var self = Container.call(this); // SelecciĂłn aleatoria de tipo de fruta var fruitTypes = ['fruit_apple', 'fruit_lemon', 'fruit_orange', 'fruit_kiwi', 'fruit_plum']; self.fruitType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)]; // Asset de la fruta self.fruitAsset = self.attachAsset(self.fruitType, { anchorX: 0.5, anchorY: 0.5 }); if (self.fruitAsset) { self.fruitAsset.scaleX = 1; // Empieza muy pequeño self.fruitAsset.scaleY = 1; } else if (self.children && self.children.length > 0) { var lastChild = self.children[self.children.length - 1]; lastChild.scaleX = 0.1; lastChild.scaleY = 0.1; self.fruitAsset = lastChild; } self.radius = self.fruitAsset.width * self.fruitAsset.scaleX / 2 + 60; // Estado self.isCut = false; self.isActive = true; // Agregamos la velocidad de crecimiento de escala (puedes ajustar) self.scaleGrowSpeed = 0.1; // escala por frame // MĂ©todo para actualizar la fruta cada frame (debe llamarse en el ciclo principal) self.update = function () { if (!self.isCut && self.fruitAsset) { // Incrementar escala hasta 0.5 (mĂĄximo) if (self.fruitAsset.scaleX < 0.5) { self.fruitAsset.scaleX = Math.min(0.5, self.fruitAsset.scaleX + self.scaleGrowSpeed); self.fruitAsset.scaleY = self.fruitAsset.scaleX; // Actualizar radius para hitbox self.radius = self.fruitAsset.width * self.fruitAsset.scaleX / 2 + 60; } } }; self.cut = function () { if (self.isCut) { return; } self.isCut = true; self.isActive = false; self.visible = false; }; return self; }); // Clase para la fruta cortada (dos mitades) var FruitCut = Container.expand(function () { var self = Container.call(this); // Recibe tipo de fruta, posiciĂłn base, rotaciĂłn y escala self.init = function (fruitType, x, y, rotation, scale) { if (typeof rotation === "undefined") { rotation = 0; } if (typeof scale === "undefined") { scale = 1; } // Para las frutas, usar assets de mitades cortadas especĂficos por tipo de fruta var leftAssetId = 'fruit_apple_cut_left'; var rightAssetId = 'fruit_apple_cut_right'; if (fruitType === 'fruit_apple') { leftAssetId = 'fruit_apple_cut_left'; rightAssetId = 'fruit_apple_cut_right'; } else if (fruitType === 'fruit_lemon') { leftAssetId = 'fruit_lemon_cut_left'; rightAssetId = 'fruit_lemon_cut_right'; } else if (fruitType === 'fruit_orange') { leftAssetId = 'fruit_orange_cut_left'; rightAssetId = 'fruit_orange_cut_right'; } else if (fruitType === 'fruit_plum') { leftAssetId = 'fruit_plum_cut_left'; rightAssetId = 'fruit_plum_cut_right'; } else if (fruitType === 'fruit_kiwi') { leftAssetId = 'fruit_kiwi_cut_left'; rightAssetId = 'fruit_kiwi_cut_right'; } // Mitad izquierda reflejada horizontalmente (flipX: 1) self.left = self.attachAsset(leftAssetId, { anchorX: 1, anchorY: 0.5, scaleX: scale, scaleY: scale, x: 0, y: 0, flipX: 1 }); // Mitad derecha normal self.right = self.attachAsset(rightAssetId, { anchorX: 0, anchorY: 0.5, scaleX: scale, scaleY: scale, x: 0, y: 0 }); self.x = x; self.y = y; self.left.rotation = rotation; self.right.rotation = rotation; self.rotation = rotation; }; // AnimaciĂłn de separaciĂłn self.animate = function (_onFinish) { // Reduce size to 80% immediately tween(self.left, { x: -80, rotation: self.left.rotation + 0.7, scaleX: self.left.scaleX * 0.8, scaleY: self.left.scaleY * 0.8 }, { duration: 500, easing: tween.cubicOut }); tween(self.right, { x: 80, rotation: self.right.rotation - 0.7, scaleX: self.right.scaleX * 0.8, scaleY: self.right.scaleY * 0.8 }, { duration: 500, easing: tween.cubicOut, onFinish: function onFinish() { // Fade out both halves after movement/scaling tween(self.left, { alpha: 0 }, { duration: 350, easing: tween.linear }); tween(self.right, { alpha: 0 }, { duration: 350, easing: tween.linear, onFinish: function onFinish() { if (_onFinish) { _onFinish(); } } }); } }); }; return self; }); // Base Scene class for scene management var Scene = Container.expand(function () { var self = Container.call(this); self.isActive = false; self.activate = function () { self.isActive = true; self.visible = true; }; self.deactivate = function () { self.isActive = false; self.visible = false; }; return self; }); // Menu Scene var MenuScene = Scene.expand(function () { var self = Scene.call(this); // Background var bg = self.attachAsset('top_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.5, scaleY: 1.5 }); // Play button var playButton = self.attachAsset('greenLine', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: 400, height: 150, alpha: 0.8 }); // Button text var playText = new Text2('JUGAR', { size: 80, fill: 0xFFFFFF }); playText.anchor.set(0.5, 0.5); playText.x = 1024; playText.y = 1366; self.addChild(playText); // Button interaction playButton.interactive = true; playButton.down = function () { playButton.alpha = 0.6; }; playButton.up = function () { playButton.alpha = 0.8; if (game.onPlayPressed) { game.onPlayPressed(); } }; return self; }); // Game Scene - wraps all the existing game logic var GameScene = Scene.expand(function () { var self = Scene.call(this); // All game variables var bottomBg, topBg, greenLine, destructionLine, scoreTxt; var comboImage = null; var comboFadeTimeout = null; var comboFadeTween = null; var horizontalLine, cannon; var frutasGeneradas = 0; var frutasFalladas = 0; var fruits = []; var fallingFruits = []; var cutFruits = []; var frutasFalladasTimeout = null; var fruitSpeed = 25; var comboCounter = 0; var cutZoneAsset, cutZoneRadius; var canCut = true; var lastTouchTick = -100; // Round system variables var roundState, roundBullets, roundFruitsQueue, roundFruitsActive; var roundBulletsFired, roundDelayTicks, currentStage; var roundDelayBetweenRounds, roundNextBulletTick, roundStartTick; var countdownObjectsFired, goShotTick, stage2Scheduled, stage3Scheduled; var roundJustReset, showCountdownInMiddleDone; // All game variables will be initialized here self.initGame = function () { // Fondo inferior cafĂ© bottomBg = LK.getAsset('bottom_bg', { anchorX: 0, anchorY: 1, x: 0, y: 2732 }); self.addChild(bottomBg); // Fondo superior azul topBg = LK.getAsset('top_bg', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); self.addChild(topBg); // LĂnea verde casi transparente greenLine = LK.getAsset('greenLine', { anchorX: 0, anchorY: 0.5, x: 0, y: 500, alpha: 0.2 }); self.addChild(greenLine); // LĂnea roja de destrucciĂłn destructionLine = LK.getAsset('vertical_line', { anchorX: 0, anchorY: 0.5, x: 0, y: -100, width: 2048, height: 10, color: 0xff0000, shape: 'box' }); self.addChild(destructionLine); // Score text (invisible) scoreTxt = new Text2('', { size: 1, fill: "#222", alpha: 0 }); scoreTxt.visible = false; // LĂnea negra horizontal horizontalLine = LK.getAsset('vertical_line', { anchorX: 0, anchorY: 0.5, x: 0, y: 2732 / 2 + 540, width: 2048, height: 120, color: 0x000000, shape: 'box' }); // Instancia el cañón cannon = new Cannon(); self.addChild(horizontalLine); self.addChild(cannon); cannon.show(); // Initialize cut zone cutZoneAsset = LK.getAsset('cut_zone', { anchorX: 0.5, anchorY: 0.5 }); cutZoneRadius = cutZoneAsset.width / 2; cutZoneAsset.destroy(); // Reset all game variables frutasGeneradas = 0; frutasFalladas = 0; fruits = []; fallingFruits = []; cutFruits = []; fruitSpeed = 25; comboCounter = 0; canCut = true; lastTouchTick = -100; roundState = undefined; countdownObjectsFired = undefined; goShotTick = undefined; stage2Scheduled = undefined; stage3Scheduled = undefined; roundJustReset = undefined; showCountdownInMiddleDone = undefined; // Reset score LK.setScore(0); updateScore(0); }; // Helper functions function updateScore(val) { LK.setScore(val); scoreTxt.setText(val); } function tryCutFruit(x, y) { if (!canCut) { return; } canCut = false; lastTouchTick = LK.ticks; for (var i = 0; i < fallingFruits.length; i++) { var fruit = fallingFruits[i]; if (!fruit.isActive) { continue; } if (fruit.state === 'cuttable') { var dx = x - fruit.x; var dy = y - fruit.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= fruit.radius * fruit.scaleX) { fruit.cut(); if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } LK.getSound('cut').play(); // Check if Y position is within combo zone (350-750) if (y >= 350 && y <= 750) { comboCounter++; if (comboCounter >= 13) { comboCounter = 1; // Reset to 1 after reaching 12 } } else { comboCounter = 0; } // Update combo image display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { // Cancel any ongoing tween on the previous combo image if (comboFadeTween) { comboFadeTween.stop(); comboFadeTween = null; } comboImage.destroy(); comboImage = null; } if (comboCounter > 0 && comboCounter <= 12) { comboImage = LK.getAsset('combo' + comboCounter, { anchorX: 1, anchorY: 0, alpha: 1, scaleX: 0.5, scaleY: 0.5 }); LK.gui.topRight.addChild(comboImage); comboImage.x = -20; // 20px from right edge comboImage.y = 20; // 20px from top // Scale up from 50% to 100% in 0.1 seconds tween(comboImage, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut }); // After 0.3 seconds (0.1s grow + 0.2s show), start fade out comboFadeTimeout = LK.setTimeout(function () { if (comboImage) { comboFadeTween = tween(comboImage, { alpha: 0 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { if (comboImage) { comboImage.destroy(); comboImage = null; } comboFadeTween = null; } }); } comboFadeTimeout = null; }, 300); } // AnimaciĂłn de corte para todas las frutas var fruitCut = new FruitCut(); fruitCut.init(fruit.fruitType, fruit.x, fruit.y, fruit.rotation, fruit.scaleX); self.addChild(fruitCut); // Asegura que la lĂnea negra estĂ© sobre las frutas cortadas pero debajo del cañón if (horizontalLine && horizontalLine.parent) { horizontalLine.parent.removeChild(horizontalLine); self.addChild(horizontalLine); } // Asegura que el cañón siempre estĂ© al frente if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); self.addChild(cannon); } fruitCut.animate(function () { fruitCut.destroy(); }); cutFruits.push(fruitCut); frutasGeneradas++; updateScore(LK.getScore() + 1); return; } } } } self.down = function (x, y, obj) { if (self.isActive) { tryCutFruit(x, y); } }; self.updateGame = function () { if (!self.isActive) return; // Permitir corte nuevamente tras 6 ticks (~100ms) if (!canCut && LK.ticks - lastTouchTick > 6) { canCut = true; } // --- SISTEMA DE BALAS POR RONDA (5 balas, 1s entre cada una, 7s delay antes de mostrar en pantalla superior) --- if (typeof roundState === "undefined") { // Estados posibles: 'waiting', 'spawning', 'waitingFruits' roundState = 'waiting'; roundBullets = 7; // 3 countdown objects + 4 fruits (stage 1) roundFruitsQueue = []; roundFruitsActive = []; roundBulletsFired = 0; roundDelayTicks = 0; currentStage = 1; // Track current stage (1 or 2) roundDelayBetweenRounds = 120; // 2 seconds between rounds } if (roundState === 'waiting') { // Limpiar arrays de frutas y mitades cortadas de la ronda anterior for (var i = fruits.length - 1; i >= 0; i--) { if (fruits[i]) { fruits[i].destroy(); } } fruits = []; for (var i = fallingFruits.length - 1; i >= 0; i--) { if (fallingFruits[i]) { fallingFruits[i].destroy(); } } fallingFruits = []; for (var i = cutFruits.length - 1; i >= 0; i--) { if (cutFruits[i]) { cutFruits[i].destroy(); } } cutFruits = []; // Limpiar arrays de control de ronda if (typeof roundFruitsQueue !== "undefined") { for (var i = roundFruitsQueue.length - 1; i >= 0; i--) { if (roundFruitsQueue[i] && roundFruitsQueue[i].destroy) { roundFruitsQueue[i].destroy(); } } } roundFruitsQueue = []; if (typeof roundFruitsActive !== "undefined") { for (var i = roundFruitsActive.length - 1; i >= 0; i--) { if (roundFruitsActive[i] && roundFruitsActive[i].destroy) { roundFruitsActive[i].destroy(); } } } roundFruitsActive = []; // Reset meta de ronda roundBulletsFired = 0; roundNextBulletTick = LK.ticks; roundDelayTicks = 0; // Set round bullets based on current stage if (currentStage === 1) { roundBullets = 7; // 3 countdown + 4 fruits // Schedule stage 2 to start 8 seconds after stage 1 begins if (typeof stage2Scheduled === "undefined" || !stage2Scheduled) { stage2Scheduled = true; LK.setTimeout(function () { // Start stage 2 currentStage = 2; roundState = 'waiting'; stage2Scheduled = false; // Schedule stage 3 to start 5 seconds after stage 2 begins if (typeof stage3Scheduled === "undefined" || !stage3Scheduled) { stage3Scheduled = true; LK.setTimeout(function () { currentStage = 3; roundState = 'waiting'; stage3Scheduled = false; }, 4000); // 5 seconds after stage 2 starts } }, 10300); // 8 seconds } } else if (currentStage === 2) { roundBullets = 4; // 3 fruits only, no countdown countdownObjectsFired = 4; // Skip countdown in stage 2 } else if (currentStage === 3) { // Reiniciar todas las variables para evitar errores en la generaciĂłn de frutas frutasGeneradas = 0; frutasFalladas = 0; fruits = []; fallingFruits = []; cutFruits = []; roundFruitsQueue = []; roundFruitsActive = []; roundBullets = 4; // 4 frutas en la tercera etapa countdownObjectsFired = 4; // No countdown en la etapa 3 // Clear any existing combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } } // Esperar un frame antes de permitir el spawn para evitar generaciĂłn mĂșltiple if (typeof roundJustReset === "undefined" || !roundJustReset) { roundJustReset = true; return; } else { roundJustReset = false; roundState = 'spawning'; goShotTick = undefined; } } if (roundState === 'spawning') { // Espera inicial antes de cualquier disparo if (typeof roundStartTick === "undefined") { roundStartTick = LK.ticks; } var delay = 20; // â±ïž Espera de 2 segundos (120 ticks) if (LK.ticks - roundStartTick < delay) { return; // âł AĂșn esperando el inicio } // Disparar los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos if (typeof countdownObjectsFired === "undefined") { countdownObjectsFired = 0; } if (roundBulletsFired < roundBullets && LK.ticks >= roundNextBulletTick) { var margin = 180; var fruitX = margin + Math.random() * (2048 - 2 * margin); cannon.x = fruitX; cannon.show(); cannon.shoot(); // Dispara "1", "2", "Go" en los primeros tres disparos if (countdownObjectsFired === 0) { var obj1 = new CountdownOne(); obj1.x = fruitX; obj1.y = 2732 + obj1.radius - 120; obj1.startY = obj1.y; obj1.targetY = 2732 / 2 + 600; obj1.state = 'rising'; obj1.ticks = 0; obj1.roundMeta = { hasCrossed: false, crossedTick: null, showScheduled: false, showTimeout: null, destroyed: false }; fruits.push(obj1); roundFruitsQueue.push(obj1); self.addChild(obj1); // Mostrar "1" centrado y gigante con fade out var centerObj1 = new CountdownOne(); centerObj1.x = 2048 / 2; centerObj1.y = 2732 / 2; centerObj1.scaleX = centerObj1.scaleY = 9; // Gigante centerObj1.alpha = 1; self.addChild(centerObj1); // Fade out despuĂ©s de 0.5 segundos LK.setTimeout(function () { tween(centerObj1, { alpha: 0 }, { duration: 300, easing: tween.linear, onFinish: function onFinish() { centerObj1.destroy(); } }); }, 500); countdownObjectsFired++; } else if (countdownObjectsFired === 1) { var obj2 = new CountdownTwo(); obj2.x = fruitX; obj2.y = 2732 + obj2.radius - 120; obj2.startY = obj2.y; obj2.targetY = 2732 / 2 + 600; obj2.state = 'rising'; obj2.ticks = 0; obj2.roundMeta = { hasCrossed: false, crossedTick: null, showScheduled: false, showTimeout: null, destroyed: false }; fruits.push(obj2); roundFruitsQueue.push(obj2); self.addChild(obj2); // Mostrar "2" centrado y gigante con fade out var centerObj2 = new CountdownTwo(); centerObj2.x = 2048 / 2; centerObj2.y = 2732 / 2; centerObj2.scaleX = centerObj2.scaleY = 9; // Gigante centerObj2.alpha = 1; self.addChild(centerObj2); // Fade out despuĂ©s de 0.5 segundos LK.setTimeout(function () { tween(centerObj2, { alpha: 0 }, { duration: 300, easing: tween.linear, onFinish: function onFinish() { centerObj2.destroy(); } }); }, 500); countdownObjectsFired++; } else if (countdownObjectsFired === 2) { var objGo = new CountdownGo(); objGo.x = fruitX; objGo.y = 2732 + objGo.radius - 120; objGo.startY = objGo.y; objGo.targetY = 2732 / 2 + 600; objGo.state = 'rising'; objGo.ticks = 0; objGo.roundMeta = { hasCrossed: false, crossedTick: null, showScheduled: false, showTimeout: null, destroyed: false }; fruits.push(objGo); roundFruitsQueue.push(objGo); self.addChild(objGo); // Mostrar "Go!" centrado y gigante con fade out var centerObjGo = new CountdownGo(); centerObjGo.x = 2048 / 2; centerObjGo.y = 2732 / 2; centerObjGo.scaleX = centerObjGo.scaleY = 9; // Gigante centerObjGo.alpha = 1; self.addChild(centerObjGo); // Fade out despuĂ©s de 0.5 segundos LK.setTimeout(function () { tween(centerObjGo, { alpha: 0 }, { duration: 300, easing: tween.linear, onFinish: function onFinish() { centerObjGo.destroy(); } }); }, 500); countdownObjectsFired++; // After Go!, wait 2 seconds before launching fruits if (typeof goShotTick === "undefined") { goShotTick = LK.ticks; // Schedule game end 18 seconds after Go! LK.setTimeout(function () { // Show stars based on fruits cut var starAsset; var starSound; if (LK.getScore() === 0) { starAsset = 'Estrellas0'; starSound = 'E1'; // Use E1 sound for 0 stars } else if (LK.getScore() <= 6) { starAsset = 'Estrellas1'; starSound = 'E1'; } else if (LK.getScore() <= 11) { starAsset = 'Estrellas2'; starSound = 'E2'; } else { starAsset = 'Estrellas3'; starSound = 'E3'; } // Create and display star var star = LK.getAsset(starAsset, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.addChild(star); // Play corresponding sound LK.getSound(starSound).play(); // Animate star appearance tween(star, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.cubicOut, onFinish: function onFinish() { // Keep star visible for a moment then show end scene LK.setTimeout(function () { // Stop music LK.stopMusic(); // Clean up combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } // Show end scene instead of game over endScene.activate(); currentScene = endScene; }, 2000); } }); }, 18000); // 18 seconds } } else { // Wait 1.3 seconds (78 ticks) after Go! before launching fruits if (typeof goShotTick !== "undefined" && LK.ticks - goShotTick < 60) { return; } // DespuĂ©s de los tres primeros, dispara frutas normales var fruit = new Fruit(); fruit.x = fruitX; fruit.y = 2732 + fruit.radius - 300; fruit.startY = fruit.y; fruit.targetY = 2732 / 2 + 600; fruit.state = 'rising'; fruit.ticks = 0; fruit.roundMeta = { hasCrossed: false, crossedTick: null, showScheduled: false, showTimeout: null, destroyed: false }; fruits.push(fruit); roundFruitsQueue.push(fruit); self.addChild(fruit); } // Asegura que el cañón siempre estĂ© al frente if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); self.addChild(cannon); } roundBulletsFired++; // After Go!, wait 1.3 seconds before next bullet if (countdownObjectsFired === 3 && roundBulletsFired === 3) { roundNextBulletTick = LK.ticks + 60; // 1.3s wait after Go! } else if (roundBulletsFired < 3) { // Original timing for countdown objects (1, 2, Go!) roundNextBulletTick = LK.ticks + 30; // 0.5s between countdown objects } else { // Timing between fruits based on stage if (currentStage === 1) { roundNextBulletTick = LK.ticks + 60; // 1s entre frutas (stage 1) } else if (currentStage === 2) { roundNextBulletTick = LK.ticks + 30; // 0.5s entre frutas (stage 2) } else if (currentStage === 3) { roundNextBulletTick = LK.ticks + 30; } } } // When all bullets are fired, round is complete if (roundBulletsFired >= roundBullets) { roundState = 'complete'; } } if (roundState === 'complete') { // Round completed - do nothing, no more spawning } // Mover frutas que suben desde abajo hasta el centro for (var i = fruits.length - 1; i >= 0; i--) { var fruit = fruits[i]; // Only destroy objects that are NOT rising (i.e., not going up from bottom) // This ensures fruits launched from bottom can reach the top before being destroyed if (fruit.state !== 'rising' && fruit.y < -100) { // Destroy cut zone circle if exists if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } // Mark as inactive fruit.isActive = false; // Mark as destroyed for round system if (fruit.roundMeta) { fruit.roundMeta.destroyed = true; } // Clear any scheduled timeouts if (fruit.roundMeta && fruit.roundMeta.showTimeout) { LK.clearTimeout(fruit.roundMeta.showTimeout); fruit.roundMeta.showTimeout = null; } // Remove from roundFruitsQueue if present if (typeof roundFruitsQueue !== "undefined") { for (var j = roundFruitsQueue.length - 1; j >= 0; j--) { if (roundFruitsQueue[j] === fruit) { roundFruitsQueue.splice(j, 1); break; } } } // Destroy the object completely fruit.destroy(); fruits.splice(i, 1); continue; // Skip rest of processing for this object } if (fruit.state === 'rising') { // Cambiar velocidad solo en etapa 2 var currentFruitSpeed = fruitSpeed; if (currentStage === 2) { currentFruitSpeed = 40; // velocidad mĂĄs rĂĄpida en etapa 2 } fruit.y -= currentFruitSpeed; fruit.ticks++; // Escalado segĂșn altura (mĂĄs arriba, mĂĄs grande) var minScale = 1.0; var maxScale = 1.5; var y0 = 2732 + fruit.radius + 10; var y1 = 2732 / 2 + 420; var t = (fruit.y - y1) / (y0 - y1); if (t < 0) { t = 0; } if (t > 1) { t = 1; } var scale = minScale + (maxScale - minScale) * (1 - t); fruit.scaleX = fruit.scaleY = scale; // RotaciĂłn en la parte de abajo (solo mientras sube) if (typeof fruit.rotation === "undefined") { fruit.rotation = Math.random() * Math.PI * 2; } if (typeof fruit.rotationSpeed === "undefined") { fruit.rotationSpeed = (Math.random() - 0.5) * 0.08; } fruit.rotation += fruit.rotationSpeed; if (fruit.fruitAsset) { fruit.fruitAsset.rotation = fruit.rotation; } // Cuando cruza la altura objetivo (centro), programar apariciĂłn en pantalla superior tras un tiempo proporcional al nĂșmero de frutas lanzadas if (!fruit.roundMeta.hasCrossed && fruit.y <= fruit.targetY) { fruit.roundMeta.hasCrossed = true; fruit.roundMeta.crossedTick = LK.ticks; fruit.visible = false; // Cambiar tiempo de espera solo en etapa 2 var appearDelayMs = 2700; // default 2.7s if (currentStage === 2) { appearDelayMs = 1100; // 1.5s en etapa 2 } if (currentStage === 3) { appearDelayMs = 1200; // 1.5s en etapa 2 } var isCountdownObject = fruit instanceof CountdownOne || fruit instanceof CountdownTwo || fruit instanceof CountdownGo; if (!isCountdownObject) { fruit.roundMeta.showScheduled = true; fruit.roundMeta.showTimeout = LK.setTimeout(function (fruitRef, fruitsArr, iIdx) { return function () { if (fruitRef.roundMeta.destroyed) { return; } var fruitType = fruitRef.fruitType; var x = fruitRef.x; fruitRef.destroy(); for (var j = 0; j < fruitsArr.length; j++) { if (fruitsArr[j] === fruitRef) { fruitsArr.splice(j, 1); break; } } var fallingFruit = new Fruit(); if (typeof fruitType === "undefined" || !fruitType) { fruitType = fallingFruit.fruitType; } else { fallingFruit.fruitType = fruitType; } if (fallingFruit.fruitAsset) { fallingFruit.fruitAsset.destroy(); } fallingFruit.fruitAsset = fallingFruit.attachAsset(fallingFruit.fruitType, { anchorX: 0.5, anchorY: 0.5 }); fallingFruit.x = x; fallingFruit.y = 2732 / 2 + 420 + 100; fallingFruit.startY = fallingFruit.y; fallingFruit.lastY = 2732; // Initialize lastY to a safe value well below destruction line fallingFruit.state = 'cuttable'; fallingFruit.ticks = 0; fallingFruit.rotation = Math.random() * Math.PI * 2; fallingFruit.rotationSpeed = (Math.random() - 0.5) * 0.04; fallingFruit.roundMeta = { destroyed: false }; fallingFruits.push(fallingFruit); roundFruitsActive.push(fallingFruit); self.addChild(fallingFruit); if (horizontalLine && horizontalLine.parent) { horizontalLine.parent.removeChild(horizontalLine); self.addChild(horizontalLine); } if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); self.addChild(cannon); } }; }(fruit, fruits, i), appearDelayMs); } } if (fruit.roundMeta.hasCrossed && fruit.roundMeta.showScheduled) { if (fruit.roundMeta.destroyed) { if (fruit.roundMeta.showTimeout) { LK.clearTimeout(fruit.roundMeta.showTimeout); fruit.roundMeta.showTimeout = null; } if (typeof roundFruitsQueue !== "undefined") { for (var j = roundFruitsQueue.length - 1; j >= 0; j--) { if (roundFruitsQueue[j] === fruit) { roundFruitsQueue.splice(j, 1); break; } } } fruits.splice(i, 1); } continue; } } } // Mover frutas que suben de nuevo y gestionar zona de corte visual // --- Asegura que la lĂnea negra estĂ© sobre los sprites de las frutas en cada frame --- if (horizontalLine && horizontalLine.parent) { horizontalLine.parent.removeChild(horizontalLine); self.addChild(horizontalLine); } // Asegura que la lĂnea roja de destrucciĂłn estĂ© visible encima de todo if (destructionLine && destructionLine.parent) { destructionLine.parent.removeChild(destructionLine); self.addChild(destructionLine); } // Volver a agregar la lĂnea roja al final para que estĂ© encima if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); self.addChild(cannon); } if (destructionLine && destructionLine.parent) { destructionLine.parent.removeChild(destructionLine); self.addChild(destructionLine); } for (var i = fallingFruits.length - 1; i >= 0; i--) { var fruit = fallingFruits[i]; // Check if falling fruit passes above Y=800 for complete destruction // Only destroy fruits that are falling down (cuttable or flyingup states) if (fruit.y < -100 && (fruit.state === 'cuttable' || fruit.state === 'flyingup')) { // Destroy cut zone circle if exists if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } // Mark as inactive fruit.isActive = false; // Mark as destroyed for round system if (fruit.roundMeta) { fruit.roundMeta.destroyed = true; } // Remove from roundFruitsActive if present if (typeof roundFruitsActive !== "undefined") { for (var j = roundFruitsActive.length - 1; j >= 0; j--) { if (roundFruitsActive[j] === fruit) { roundFruitsActive.splice(j, 1); break; } } } // Count as failed if not cut if (!fruit.isCut) { frutasFalladas++; frutasGeneradas++; comboCounter = 0; // Clear any existing combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } } // Destroy the fruit completely fruit.destroy(); fallingFruits.splice(i, 1); continue; // Skip rest of processing for this fruit } if (!fruit.isActive) { continue; } // Escalado segĂșn altura (mĂĄs arriba, mĂĄs grande) var minScale = 1.0; var maxScale = 1.25 * 1.3 * 1.3; //{45} // 60% mĂĄs grande en la parte superior var y0 = 2732 / 2 + 420; var y1 = 420; var t = (fruit.y - y1) / (y0 - y1); if (t < 0) { t = 0; } if (t > 1) { t = 1; } var scale = minScale + (maxScale - minScale) * (1 - t); fruit.scaleX = fruit.scaleY = scale; // RotaciĂłn suave if (typeof fruit.rotationSpeed !== "undefined") { fruit.rotation += fruit.rotationSpeed; if (fruit.fruitAsset) { fruit.fruitAsset.rotation = fruit.rotation; } } // Movimiento hacia arriba mientras sea cortable o volando hacia arriba if (fruit.state === 'cuttable' || fruit.state === 'flyingup') { var topFruitSpeed = fruitSpeed; if (currentStage === 2) { topFruitSpeed = 30; // velocidad mĂĄs alta en la segunda etapa } // Double speed if fruit has passed cutting zone if (fruit.doubledSpeed) { topFruitSpeed = topFruitSpeed * 2; } fruit.y -= topFruitSpeed; } // --- AnimaciĂłn progresiva del cĂrculo de corte --- // El cĂrculo aparece desde el inicio de la subida (cuttable), crece y se difumina progresivamente if (fruit.state === 'cuttable') { // Si no existe el cĂrculo, crearlo if (!fruit.cutZoneCircle) { fruit.cutZoneCircle = LK.getAsset('cut_zone', { anchorX: 0.5, anchorY: 0.5, x: fruit.x, y: fruit.y, alpha: 0.0, scaleX: 0.1, scaleY: 0.1 }); self.addChild(fruit.cutZoneCircle); // Asegura que la lĂnea negra estĂ© sobre el cĂrculo de corte pero debajo del cañón if (horizontalLine && horizontalLine.parent) { horizontalLine.parent.removeChild(horizontalLine); self.addChild(horizontalLine); } // Asegura que el cañón siempre estĂ© al frente if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); self.addChild(cannon); } } // ProgresiĂłn del cĂrculo: desde que inicia la subida hasta que llega cerca de la parte superior var appearT = (y0 - fruit.y) / (y0 - y1); if (appearT < 0) { appearT = 0; } if (appearT > 1) { appearT = 1; } var maxScaleZone = 0.85; // MĂĄs pequeño, para que quede dentro de la fruta var minScaleZone = 0.15; var maxAlpha = 0.38; // MĂĄs difuminado var minAlpha = 0.08; var scaleZone = minScaleZone + (maxScaleZone - minScaleZone) * appearT; var alphaZone = minAlpha + (maxAlpha - minAlpha) * appearT; fruit.cutZoneCircle.scaleX = fruit.cutZoneCircle.scaleY = scaleZone; fruit.cutZoneCircle.alpha = alphaZone; fruit.cutZoneCircle.x = fruit.x; fruit.cutZoneCircle.y = fruit.y; // Si la fruta sale por arriba, eliminar cĂrculo y pasar a flyingup if (fruit.y < y1) { // Si el cĂrculo de corte existe y la fruta no fue cortada, contar como fallada if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; if (fruit.isActive && !fruit.isCut) { frutasFalladas++; frutasGeneradas++; comboCounter = 0; // Clear any existing combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } } } fruit.state = 'flyingup'; // Double the speed when fruit can no longer be cut fruit.doubledSpeed = true; } } else { // Si no estĂĄ en estado cortable y existe el cĂrculo, destruirlo if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } } // Si fue cortada, eliminar cĂrculo visual inmediatamente pero mantener la fruta visible if (!fruit.isActive && fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } // Si estĂĄ cayendo, animar caĂda if (fruit.state === 'dropping') { fruit.dropSpeed += 2.5; // gravedad fruit.y += fruit.dropSpeed; // Escalado decreciente al caer fruit.scaleX = fruit.scaleY = Math.max(0.7, fruit.scaleX - 0.01); if (fruit.cutZoneCircle) { fruit.cutZoneCircle.x = fruit.x; fruit.cutZoneCircle.y = fruit.y; } // Si sale de pantalla, marcar como inactivo pero mantener visible if (fruit.y > 2732 + fruit.radius + 20) { if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } fruit.isActive = false; } } // Si la fruta sigue subiendo despuĂ©s de la zona de corte y no fue cortada if (fruit.state === 'flyingup') { // Al entrar por primera vez en flyingup, inicia temporizador de espera if (typeof fruit.waitTicks === "undefined") { fruit.waitTicks = 0; } fruit.waitTicks++; // Mantener la fruta visible y estĂĄtica durante 4 segundos (240 ticks) if (fruit.waitTicks < 240) { // Mantener posiciĂłn (opcional: podrĂas hacer que siga subiendo lentamente) // fruit.y -= fruitSpeed * 0.1; } else { // DespuĂ©s de 7 segundos, hacer que suba y desaparezca // Continue moving at current speed (already doubled if applicable) // Escalado sigue creciendo un poco fruit.scaleX = fruit.scaleY = Math.min(maxScale, fruit.scaleX + 0.01); // Check if fruit passes destruction line at Y=800 for complete destruction if (fruit.y < -100) { // Destroy cut zone circle if exists if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } // Mark as inactive fruit.isActive = false; // Mark as destroyed for round system if (fruit.roundMeta) { fruit.roundMeta.destroyed = true; } // Remove from roundFruitsActive if present if (typeof roundFruitsActive !== "undefined") { for (var j = roundFruitsActive.length - 1; j >= 0; j--) { if (roundFruitsActive[j] === fruit) { roundFruitsActive.splice(j, 1); break; } } } // Count as failed if not cut if (!fruit.isCut) { frutasFalladas++; frutasGeneradas++; comboCounter = 0; // Clear any existing combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } } // Destroy the fruit completely fruit.destroy(); fallingFruits.splice(i, 1); continue; // Skip rest of processing for this fruit } // Si sale de pantalla por arriba, marcar como inactiva y eliminar cĂrculo de corte si existe if (fruit.y < -fruit.radius - 20) { if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } fruit.isActive = false; // Marcar como destruida para el sistema de ronda if (fruit.roundMeta) { fruit.roundMeta.destroyed = true; } // Eliminar de roundFruitsActive si estĂĄ presente if (typeof roundFruitsActive !== "undefined") { for (var j = roundFruitsActive.length - 1; j >= 0; j--) { if (roundFruitsActive[j] === fruit) { roundFruitsActive.splice(j, 1); break; } } } // Aumentar frutasFalladas y frutasGeneradas solo si la fruta no fue cortada if (!fruit.isCut) { frutasFalladas++; frutasGeneradas++; comboCounter = 0; // Clear any existing combo display if (comboFadeTimeout) { LK.clearTimeout(comboFadeTimeout); comboFadeTimeout = null; } if (comboImage) { comboImage.destroy(); comboImage = null; } } } } } // Si la fruta ya fue cortada o saliĂł de pantalla, eliminar if (!fruit.isActive || fruit.y > 2732 + fruit.radius + 20 || fruit.y < -fruit.radius - 20) { if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; } // Marcar como destruida para el sistema de ronda if (fruit.roundMeta) { fruit.roundMeta.destroyed = true; } // Eliminar de roundFruitsActive si estĂĄ presente if (typeof roundFruitsActive !== "undefined") { for (var j = roundFruitsActive.length - 1; j >= 0; j--) { if (roundFruitsActive[j] === fruit) { roundFruitsActive.splice(j, 1); break; } } } fruit.destroy(); fallingFruits.splice(i, 1); } } // Limpiar mitades cortadas que ya terminaron animaciĂłn for (var i = cutFruits.length - 1; i >= 0; i--) { var fc = cutFruits[i]; if (!fc.left || !fc.right) { if (fc.destroy) { fc.destroy(); } cutFruits.splice(i, 1); } } // Variable para controlar el timeout (debe estar fuera de la funciĂłn que chequea frutasFalladas) if (frutasFalladas >= 5 || frutasGeneradas >= 5 && frutasFalladas < 5) { // Mostrar los sprites 1, 2, Go en el centro con fade in/fade out rĂĄpido solo una vez, SOLO al inicio del juego if ((typeof showCountdownInMiddleDone === "undefined" || !showCountdownInMiddleDone) && LK.ticks < 120) { showCountdownInMiddleDone = true; var centerX = 2048 / 2; var centerY = 2732 / 2; var countdownSprites = [{ cls: CountdownOne, delay: 0 }, { cls: CountdownTwo, delay: 350 }, { cls: CountdownGo, delay: 700 }]; for (var idx = 0; idx < countdownSprites.length; idx++) { (function (idx) { var conf = countdownSprites[idx]; LK.setTimeout(function () { var obj = new conf.cls(); obj.x = centerX; obj.y = centerY; obj.alpha = 0; self.addChild(obj); // Fade in rĂĄpido tween(obj, { alpha: 1 }, { duration: 180, easing: tween.cubicOut, onFinish: function onFinish() { // Fade out rĂĄpido tween(obj, { alpha: 0 }, { duration: 180, delay: 180, easing: tween.cubicIn, onFinish: function onFinish() { obj.destroy(); } }); } }); }, conf.delay); })(idx); } } return; } }; return self; }); // End Scene - shows after stars with restart and menu buttons var EndScene = Scene.expand(function () { var self = Scene.call(this); // Background overlay var overlay = self.attachAsset('vertical_line', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: 2048, height: 2732, alpha: 0.7 }); // Restart button var restartButton = self.attachAsset('greenLine', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, width: 350, height: 120, alpha: 0.8 }); var restartText = new Text2('REINICIAR', { size: 60, fill: 0xFFFFFF }); restartText.anchor.set(0.5, 0.5); restartText.x = 1024; restartText.y = 1200; self.addChild(restartText); // Menu button var menuButton = self.attachAsset('cut_zone', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, width: 350, height: 120, alpha: 0.8 }); var menuText = new Text2('MENU', { size: 60, fill: 0x000000 }); menuText.anchor.set(0.5, 0.5); menuText.x = 1024; menuText.y = 1400; self.addChild(menuText); // Button interactions restartButton.interactive = true; menuButton.interactive = true; restartButton.down = function () { restartButton.alpha = 0.6; }; restartButton.up = function () { restartButton.alpha = 0.8; if (game.onRestartPressed) { game.onRestartPressed(); } }; menuButton.down = function () { menuButton.alpha = 0.6; }; menuButton.up = function () { menuButton.alpha = 0.8; if (game.onMenuPressed) { game.onMenuPressed(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Scene management variables var currentScene = null; var menuScene = null; var gameScene = null; var endScene = null; // Create scenes menuScene = new MenuScene(); gameScene = new GameScene(); endScene = new EndScene(); // Add scenes to game game.addChild(menuScene); game.addChild(gameScene); game.addChild(endScene); // Initially show menu menuScene.activate(); gameScene.deactivate(); endScene.deactivate(); currentScene = menuScene; // Scene transition handlers game.onPlayPressed = function () { menuScene.deactivate(); gameScene.activate(); endScene.deactivate(); currentScene = gameScene; // Initialize game when transitioning to game scene if (!gameScene.gameInitialized) { gameScene.initGame(); gameScene.gameInitialized = true; } // Start music when game starts LK.playMusic('bgmusic', { loop: false }); }; game.onRestartPressed = function () { endScene.deactivate(); // Reset game scene gameScene.deactivate(); game.removeChild(gameScene); gameScene = new GameScene(); game.addChild(gameScene); gameScene.activate(); currentScene = gameScene; gameScene.initGame(); gameScene.gameInitialized = true; // Restart music LK.stopMusic(); LK.playMusic('bgmusic', { loop: false }); }; game.onMenuPressed = function () { endScene.deactivate(); gameScene.deactivate(); menuScene.activate(); currentScene = menuScene; // Stop music when returning to menu LK.stopMusic(); // Reset game scene for next play game.removeChild(gameScene); gameScene = new GameScene(); game.addChild(gameScene); gameScene.gameInitialized = false; }; // Main game update loop game.update = function () { if (currentScene && currentScene.updateGame) { currentScene.updateGame(); } };
===================================================================
--- original.js
+++ change.js
@@ -285,630 +285,900 @@
});
};
return self;
});
-
-/****
-* Initialize Game
-****/
-var game = new LK.Game({
- backgroundColor: 0x222222
+// Base Scene class for scene management
+var Scene = Container.expand(function () {
+ var self = Container.call(this);
+ self.isActive = false;
+ self.activate = function () {
+ self.isActive = true;
+ self.visible = true;
+ };
+ self.deactivate = function () {
+ self.isActive = false;
+ self.visible = false;
+ };
+ return self;
});
-
-/****
-* Game Code
-****/
-// Inicia la mĂșsica de fondo en loop al iniciar el juego
-LK.playMusic('bgmusic', {
- loop: false
+// Menu Scene
+var MenuScene = Scene.expand(function () {
+ var self = Scene.call(this);
+ // Background
+ var bg = self.attachAsset('top_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1366,
+ scaleX: 1.5,
+ scaleY: 1.5
+ });
+ // Play button
+ var playButton = self.attachAsset('greenLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1366,
+ width: 400,
+ height: 150,
+ alpha: 0.8
+ });
+ // Button text
+ var playText = new Text2('JUGAR', {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ playText.anchor.set(0.5, 0.5);
+ playText.x = 1024;
+ playText.y = 1366;
+ self.addChild(playText);
+ // Button interaction
+ playButton.interactive = true;
+ playButton.down = function () {
+ playButton.alpha = 0.6;
+ };
+ playButton.up = function () {
+ playButton.alpha = 0.8;
+ if (game.onPlayPressed) {
+ game.onPlayPressed();
+ }
+ };
+ return self;
});
-// Fondo superior azul
-// Fondo inferior café
-// Fondo inferior (parte baja de la pantalla) - café
-var bottomBg = LK.getAsset('bottom_bg', {
- anchorX: 0,
- anchorY: 1,
- x: 0,
- y: 2732
-});
-game.addChild(bottomBg);
-// Fondo superior (parte alta de la pantalla) - azul
-var topBg = LK.getAsset('top_bg', {
- anchorX: 0,
- anchorY: 0,
- x: 0,
- y: 0
-});
-game.addChild(topBg);
-// LĂnea verde casi transparente en la parte superior
-var greenLine = LK.getAsset('greenLine', {
- anchorX: 0,
- anchorY: 0.5,
- x: 0,
- y: 500,
- alpha: 0.2
-});
-game.addChild(greenLine);
-// LĂnea roja en la mitad de la pantalla para destrucciĂłn de frutas
-var destructionLine = LK.getAsset('vertical_line', {
- anchorX: 0,
- anchorY: 0.5,
- x: 0,
- y: -100,
- // Movida hacia arriba en Y positivo
- width: 2048,
- height: 10,
- // MĂĄs gruesa para mayor visibilidad
- color: 0xff0000,
- shape: 'box'
-});
-game.addChild(destructionLine);
-// Asset personalizado para el cañón (reemplaza el cut_line por una imagen de cañón)
-// scoreTxt oculto para evitar error de referencia y mantener compatibilidad con updateScore
-var scoreTxt = new Text2('', {
- size: 1,
- fill: "#222",
- alpha: 0 // completamente invisible
-});
-scoreTxt.visible = false;
-// Combo counter display using images
-var comboImage = null;
-var comboFadeTimeout = null;
-var comboFadeTween = null;
-// LĂnea negra horizontal de izquierda a derecha, aĂșn mĂĄs gruesa y un poco mĂĄs abajo en el eje Y
-var horizontalLine = LK.getAsset('vertical_line', {
- anchorX: 0,
- anchorY: 0.5,
- x: 0,
- // Baja la lĂnea: ahora 540px respecto al centro vertical
- y: 2732 / 2 + 540,
- width: 2048,
- height: 120,
- // mucho mĂĄs gruesa
- color: 0x000000,
- shape: 'box'
-});
-// Instancia y agrega el cañón
-var cannon = new Cannon();
-game.addChild(horizontalLine); // Asegura que la lĂnea estĂ© sobre el fondo pero debajo de frutas y cañón
-game.addChild(cannon);
-cannon.show();
-var frutasGeneradas = 0;
-var frutasFalladas = 0;
-var fruits = [];
-var fallingFruits = [];
-var cutFruits = [];
-var frutasFalladasTimeout = null;
-var fruitSpeed = 25;
-var comboCounter = 0;
-var cutZoneAsset = LK.getAsset('cut_zone', {
- anchorX: 0.5,
- anchorY: 0.5
-});
-var cutZoneRadius = cutZoneAsset.width / 2;
-cutZoneAsset.destroy();
-var canCut = true;
-var lastTouchTick = -100;
-function updateScore(val) {
- LK.setScore(val);
- scoreTxt.setText(val);
-}
-function tryCutFruit(x, y) {
- if (!canCut) {
- return;
+// Game Scene - wraps all the existing game logic
+var GameScene = Scene.expand(function () {
+ var self = Scene.call(this);
+ // All game variables
+ var bottomBg, topBg, greenLine, destructionLine, scoreTxt;
+ var comboImage = null;
+ var comboFadeTimeout = null;
+ var comboFadeTween = null;
+ var horizontalLine, cannon;
+ var frutasGeneradas = 0;
+ var frutasFalladas = 0;
+ var fruits = [];
+ var fallingFruits = [];
+ var cutFruits = [];
+ var frutasFalladasTimeout = null;
+ var fruitSpeed = 25;
+ var comboCounter = 0;
+ var cutZoneAsset, cutZoneRadius;
+ var canCut = true;
+ var lastTouchTick = -100;
+ // Round system variables
+ var roundState, roundBullets, roundFruitsQueue, roundFruitsActive;
+ var roundBulletsFired, roundDelayTicks, currentStage;
+ var roundDelayBetweenRounds, roundNextBulletTick, roundStartTick;
+ var countdownObjectsFired, goShotTick, stage2Scheduled, stage3Scheduled;
+ var roundJustReset, showCountdownInMiddleDone;
+ // All game variables will be initialized here
+ self.initGame = function () {
+ // Fondo inferior café
+ bottomBg = LK.getAsset('bottom_bg', {
+ anchorX: 0,
+ anchorY: 1,
+ x: 0,
+ y: 2732
+ });
+ self.addChild(bottomBg);
+ // Fondo superior azul
+ topBg = LK.getAsset('top_bg', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+ });
+ self.addChild(topBg);
+ // LĂnea verde casi transparente
+ greenLine = LK.getAsset('greenLine', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 0,
+ y: 500,
+ alpha: 0.2
+ });
+ self.addChild(greenLine);
+ // LĂnea roja de destrucciĂłn
+ destructionLine = LK.getAsset('vertical_line', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 0,
+ y: -100,
+ width: 2048,
+ height: 10,
+ color: 0xff0000,
+ shape: 'box'
+ });
+ self.addChild(destructionLine);
+ // Score text (invisible)
+ scoreTxt = new Text2('', {
+ size: 1,
+ fill: "#222",
+ alpha: 0
+ });
+ scoreTxt.visible = false;
+ // LĂnea negra horizontal
+ horizontalLine = LK.getAsset('vertical_line', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: 0,
+ y: 2732 / 2 + 540,
+ width: 2048,
+ height: 120,
+ color: 0x000000,
+ shape: 'box'
+ });
+ // Instancia el cañón
+ cannon = new Cannon();
+ self.addChild(horizontalLine);
+ self.addChild(cannon);
+ cannon.show();
+ // Initialize cut zone
+ cutZoneAsset = LK.getAsset('cut_zone', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ cutZoneRadius = cutZoneAsset.width / 2;
+ cutZoneAsset.destroy();
+ // Reset all game variables
+ frutasGeneradas = 0;
+ frutasFalladas = 0;
+ fruits = [];
+ fallingFruits = [];
+ cutFruits = [];
+ fruitSpeed = 25;
+ comboCounter = 0;
+ canCut = true;
+ lastTouchTick = -100;
+ roundState = undefined;
+ countdownObjectsFired = undefined;
+ goShotTick = undefined;
+ stage2Scheduled = undefined;
+ stage3Scheduled = undefined;
+ roundJustReset = undefined;
+ showCountdownInMiddleDone = undefined;
+ // Reset score
+ LK.setScore(0);
+ updateScore(0);
+ };
+ // Helper functions
+ function updateScore(val) {
+ LK.setScore(val);
+ scoreTxt.setText(val);
}
- canCut = false;
- lastTouchTick = LK.ticks;
- for (var i = 0; i < fallingFruits.length; i++) {
- var fruit = fallingFruits[i];
- if (!fruit.isActive) {
- continue;
+ function tryCutFruit(x, y) {
+ if (!canCut) {
+ return;
}
- if (fruit.state === 'cuttable') {
- var dx = x - fruit.x;
- var dy = y - fruit.y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- if (dist <= fruit.radius * fruit.scaleX) {
- fruit.cut();
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
+ canCut = false;
+ lastTouchTick = LK.ticks;
+ for (var i = 0; i < fallingFruits.length; i++) {
+ var fruit = fallingFruits[i];
+ if (!fruit.isActive) {
+ continue;
+ }
+ if (fruit.state === 'cuttable') {
+ var dx = x - fruit.x;
+ var dy = y - fruit.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist <= fruit.radius * fruit.scaleX) {
+ fruit.cut();
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
+ }
+ LK.getSound('cut').play();
+ // Check if Y position is within combo zone (350-750)
+ if (y >= 350 && y <= 750) {
+ comboCounter++;
+ if (comboCounter >= 13) {
+ comboCounter = 1; // Reset to 1 after reaching 12
+ }
+ } else {
+ comboCounter = 0;
+ }
+ // Update combo image display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
+ }
+ if (comboImage) {
+ // Cancel any ongoing tween on the previous combo image
+ if (comboFadeTween) {
+ comboFadeTween.stop();
+ comboFadeTween = null;
+ }
+ comboImage.destroy();
+ comboImage = null;
+ }
+ if (comboCounter > 0 && comboCounter <= 12) {
+ comboImage = LK.getAsset('combo' + comboCounter, {
+ anchorX: 1,
+ anchorY: 0,
+ alpha: 1,
+ scaleX: 0.5,
+ scaleY: 0.5
+ });
+ LK.gui.topRight.addChild(comboImage);
+ comboImage.x = -20; // 20px from right edge
+ comboImage.y = 20; // 20px from top
+ // Scale up from 50% to 100% in 0.1 seconds
+ tween(comboImage, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100,
+ easing: tween.cubicOut
+ });
+ // After 0.3 seconds (0.1s grow + 0.2s show), start fade out
+ comboFadeTimeout = LK.setTimeout(function () {
+ if (comboImage) {
+ comboFadeTween = tween(comboImage, {
+ alpha: 0
+ }, {
+ duration: 100,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
+ comboFadeTween = null;
+ }
+ });
+ }
+ comboFadeTimeout = null;
+ }, 300);
+ }
+ // AnimaciĂłn de corte para todas las frutas
+ var fruitCut = new FruitCut();
+ fruitCut.init(fruit.fruitType, fruit.x, fruit.y, fruit.rotation, fruit.scaleX);
+ self.addChild(fruitCut);
+ // Asegura que la lĂnea negra estĂ© sobre las frutas cortadas pero debajo del cañón
+ if (horizontalLine && horizontalLine.parent) {
+ horizontalLine.parent.removeChild(horizontalLine);
+ self.addChild(horizontalLine);
+ }
+ // Asegura que el cañón siempre esté al frente
+ if (cannon && cannon.parent) {
+ cannon.parent.removeChild(cannon);
+ self.addChild(cannon);
+ }
+ fruitCut.animate(function () {
+ fruitCut.destroy();
+ });
+ cutFruits.push(fruitCut);
+ frutasGeneradas++;
+ updateScore(LK.getScore() + 1);
+ return;
}
- LK.getSound('cut').play();
- // Check if Y position is within combo zone (350-750)
- if (y >= 350 && y <= 750) {
- comboCounter++;
- if (comboCounter >= 13) {
- comboCounter = 1; // Reset to 1 after reaching 12
+ }
+ }
+ }
+ self.down = function (x, y, obj) {
+ if (self.isActive) {
+ tryCutFruit(x, y);
+ }
+ };
+ self.updateGame = function () {
+ if (!self.isActive) return;
+ // Permitir corte nuevamente tras 6 ticks (~100ms)
+ if (!canCut && LK.ticks - lastTouchTick > 6) {
+ canCut = true;
+ }
+ // --- SISTEMA DE BALAS POR RONDA (5 balas, 1s entre cada una, 7s delay antes de mostrar en pantalla superior) ---
+ if (typeof roundState === "undefined") {
+ // Estados posibles: 'waiting', 'spawning', 'waitingFruits'
+ roundState = 'waiting';
+ roundBullets = 7; // 3 countdown objects + 4 fruits (stage 1)
+ roundFruitsQueue = [];
+ roundFruitsActive = [];
+ roundBulletsFired = 0;
+ roundDelayTicks = 0;
+ currentStage = 1; // Track current stage (1 or 2)
+ roundDelayBetweenRounds = 120; // 2 seconds between rounds
+ }
+ if (roundState === 'waiting') {
+ // Limpiar arrays de frutas y mitades cortadas de la ronda anterior
+ for (var i = fruits.length - 1; i >= 0; i--) {
+ if (fruits[i]) {
+ fruits[i].destroy();
+ }
+ }
+ fruits = [];
+ for (var i = fallingFruits.length - 1; i >= 0; i--) {
+ if (fallingFruits[i]) {
+ fallingFruits[i].destroy();
+ }
+ }
+ fallingFruits = [];
+ for (var i = cutFruits.length - 1; i >= 0; i--) {
+ if (cutFruits[i]) {
+ cutFruits[i].destroy();
+ }
+ }
+ cutFruits = [];
+ // Limpiar arrays de control de ronda
+ if (typeof roundFruitsQueue !== "undefined") {
+ for (var i = roundFruitsQueue.length - 1; i >= 0; i--) {
+ if (roundFruitsQueue[i] && roundFruitsQueue[i].destroy) {
+ roundFruitsQueue[i].destroy();
}
- } else {
- comboCounter = 0;
}
- // Update combo image display
+ }
+ roundFruitsQueue = [];
+ if (typeof roundFruitsActive !== "undefined") {
+ for (var i = roundFruitsActive.length - 1; i >= 0; i--) {
+ if (roundFruitsActive[i] && roundFruitsActive[i].destroy) {
+ roundFruitsActive[i].destroy();
+ }
+ }
+ }
+ roundFruitsActive = [];
+ // Reset meta de ronda
+ roundBulletsFired = 0;
+ roundNextBulletTick = LK.ticks;
+ roundDelayTicks = 0;
+ // Set round bullets based on current stage
+ if (currentStage === 1) {
+ roundBullets = 7; // 3 countdown + 4 fruits
+ // Schedule stage 2 to start 8 seconds after stage 1 begins
+ if (typeof stage2Scheduled === "undefined" || !stage2Scheduled) {
+ stage2Scheduled = true;
+ LK.setTimeout(function () {
+ // Start stage 2
+ currentStage = 2;
+ roundState = 'waiting';
+ stage2Scheduled = false;
+ // Schedule stage 3 to start 5 seconds after stage 2 begins
+ if (typeof stage3Scheduled === "undefined" || !stage3Scheduled) {
+ stage3Scheduled = true;
+ LK.setTimeout(function () {
+ currentStage = 3;
+ roundState = 'waiting';
+ stage3Scheduled = false;
+ }, 4000); // 5 seconds after stage 2 starts
+ }
+ }, 10300); // 8 seconds
+ }
+ } else if (currentStage === 2) {
+ roundBullets = 4; // 3 fruits only, no countdown
+ countdownObjectsFired = 4; // Skip countdown in stage 2
+ } else if (currentStage === 3) {
+ // Reiniciar todas las variables para evitar errores en la generaciĂłn de frutas
+ frutasGeneradas = 0;
+ frutasFalladas = 0;
+ fruits = [];
+ fallingFruits = [];
+ cutFruits = [];
+ roundFruitsQueue = [];
+ roundFruitsActive = [];
+ roundBullets = 4; // 4 frutas en la tercera etapa
+ countdownObjectsFired = 4; // No countdown en la etapa 3
+ // Clear any existing combo display
if (comboFadeTimeout) {
LK.clearTimeout(comboFadeTimeout);
comboFadeTimeout = null;
}
if (comboImage) {
- // Cancel any ongoing tween on the previous combo image
- if (comboFadeTween) {
- comboFadeTween.stop();
- comboFadeTween = null;
- }
comboImage.destroy();
comboImage = null;
}
- if (comboCounter > 0 && comboCounter <= 12) {
- comboImage = LK.getAsset('combo' + comboCounter, {
- anchorX: 1,
- anchorY: 0,
- alpha: 1,
- scaleX: 0.5,
- scaleY: 0.5
- });
- LK.gui.topRight.addChild(comboImage);
- comboImage.x = -20; // 20px from right edge
- comboImage.y = 20; // 20px from top
- // Scale up from 50% to 100% in 0.1 seconds
- tween(comboImage, {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 100,
- easing: tween.cubicOut
- });
- // After 0.3 seconds (0.1s grow + 0.2s show), start fade out
- comboFadeTimeout = LK.setTimeout(function () {
- if (comboImage) {
- comboFadeTween = tween(comboImage, {
- alpha: 0
+ }
+ // Esperar un frame antes de permitir el spawn para evitar generaciĂłn mĂșltiple
+ if (typeof roundJustReset === "undefined" || !roundJustReset) {
+ roundJustReset = true;
+ return;
+ } else {
+ roundJustReset = false;
+ roundState = 'spawning';
+ goShotTick = undefined;
+ }
+ }
+ if (roundState === 'spawning') {
+ // Espera inicial antes de cualquier disparo
+ if (typeof roundStartTick === "undefined") {
+ roundStartTick = LK.ticks;
+ }
+ var delay = 20; // â±ïž Espera de 2 segundos (120 ticks)
+ if (LK.ticks - roundStartTick < delay) {
+ return; // âł AĂșn esperando el inicio
+ }
+ // Disparar los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos
+ if (typeof countdownObjectsFired === "undefined") {
+ countdownObjectsFired = 0;
+ }
+ if (roundBulletsFired < roundBullets && LK.ticks >= roundNextBulletTick) {
+ var margin = 180;
+ var fruitX = margin + Math.random() * (2048 - 2 * margin);
+ cannon.x = fruitX;
+ cannon.show();
+ cannon.shoot();
+ // Dispara "1", "2", "Go" en los primeros tres disparos
+ if (countdownObjectsFired === 0) {
+ var obj1 = new CountdownOne();
+ obj1.x = fruitX;
+ obj1.y = 2732 + obj1.radius - 120;
+ obj1.startY = obj1.y;
+ obj1.targetY = 2732 / 2 + 600;
+ obj1.state = 'rising';
+ obj1.ticks = 0;
+ obj1.roundMeta = {
+ hasCrossed: false,
+ crossedTick: null,
+ showScheduled: false,
+ showTimeout: null,
+ destroyed: false
+ };
+ fruits.push(obj1);
+ roundFruitsQueue.push(obj1);
+ self.addChild(obj1);
+ // Mostrar "1" centrado y gigante con fade out
+ var centerObj1 = new CountdownOne();
+ centerObj1.x = 2048 / 2;
+ centerObj1.y = 2732 / 2;
+ centerObj1.scaleX = centerObj1.scaleY = 9; // Gigante
+ centerObj1.alpha = 1;
+ self.addChild(centerObj1);
+ // Fade out después de 0.5 segundos
+ LK.setTimeout(function () {
+ tween(centerObj1, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ centerObj1.destroy();
+ }
+ });
+ }, 500);
+ countdownObjectsFired++;
+ } else if (countdownObjectsFired === 1) {
+ var obj2 = new CountdownTwo();
+ obj2.x = fruitX;
+ obj2.y = 2732 + obj2.radius - 120;
+ obj2.startY = obj2.y;
+ obj2.targetY = 2732 / 2 + 600;
+ obj2.state = 'rising';
+ obj2.ticks = 0;
+ obj2.roundMeta = {
+ hasCrossed: false,
+ crossedTick: null,
+ showScheduled: false,
+ showTimeout: null,
+ destroyed: false
+ };
+ fruits.push(obj2);
+ roundFruitsQueue.push(obj2);
+ self.addChild(obj2);
+ // Mostrar "2" centrado y gigante con fade out
+ var centerObj2 = new CountdownTwo();
+ centerObj2.x = 2048 / 2;
+ centerObj2.y = 2732 / 2;
+ centerObj2.scaleX = centerObj2.scaleY = 9; // Gigante
+ centerObj2.alpha = 1;
+ self.addChild(centerObj2);
+ // Fade out después de 0.5 segundos
+ LK.setTimeout(function () {
+ tween(centerObj2, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ centerObj2.destroy();
+ }
+ });
+ }, 500);
+ countdownObjectsFired++;
+ } else if (countdownObjectsFired === 2) {
+ var objGo = new CountdownGo();
+ objGo.x = fruitX;
+ objGo.y = 2732 + objGo.radius - 120;
+ objGo.startY = objGo.y;
+ objGo.targetY = 2732 / 2 + 600;
+ objGo.state = 'rising';
+ objGo.ticks = 0;
+ objGo.roundMeta = {
+ hasCrossed: false,
+ crossedTick: null,
+ showScheduled: false,
+ showTimeout: null,
+ destroyed: false
+ };
+ fruits.push(objGo);
+ roundFruitsQueue.push(objGo);
+ self.addChild(objGo);
+ // Mostrar "Go!" centrado y gigante con fade out
+ var centerObjGo = new CountdownGo();
+ centerObjGo.x = 2048 / 2;
+ centerObjGo.y = 2732 / 2;
+ centerObjGo.scaleX = centerObjGo.scaleY = 9; // Gigante
+ centerObjGo.alpha = 1;
+ self.addChild(centerObjGo);
+ // Fade out después de 0.5 segundos
+ LK.setTimeout(function () {
+ tween(centerObjGo, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ centerObjGo.destroy();
+ }
+ });
+ }, 500);
+ countdownObjectsFired++;
+ // After Go!, wait 2 seconds before launching fruits
+ if (typeof goShotTick === "undefined") {
+ goShotTick = LK.ticks;
+ // Schedule game end 18 seconds after Go!
+ LK.setTimeout(function () {
+ // Show stars based on fruits cut
+ var starAsset;
+ var starSound;
+ if (LK.getScore() === 0) {
+ starAsset = 'Estrellas0';
+ starSound = 'E1'; // Use E1 sound for 0 stars
+ } else if (LK.getScore() <= 6) {
+ starAsset = 'Estrellas1';
+ starSound = 'E1';
+ } else if (LK.getScore() <= 11) {
+ starAsset = 'Estrellas2';
+ starSound = 'E2';
+ } else {
+ starAsset = 'Estrellas3';
+ starSound = 'E3';
+ }
+ // Create and display star
+ var star = LK.getAsset(starAsset, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2,
+ alpha: 0,
+ scaleX: 0.5,
+ scaleY: 0.5
+ });
+ self.addChild(star);
+ // Play corresponding sound
+ LK.getSound(starSound).play();
+ // Animate star appearance
+ tween(star, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
}, {
- duration: 100,
- easing: tween.linear,
+ duration: 500,
+ easing: tween.cubicOut,
onFinish: function onFinish() {
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
- }
- comboFadeTween = null;
+ // Keep star visible for a moment then show end scene
+ LK.setTimeout(function () {
+ // Stop music
+ LK.stopMusic();
+ // Clean up combo display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
+ }
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
+ // Show end scene instead of game over
+ endScene.activate();
+ currentScene = endScene;
+ }, 2000);
}
});
- }
- comboFadeTimeout = null;
- }, 300);
+ }, 18000); // 18 seconds
+ }
+ } else {
+ // Wait 1.3 seconds (78 ticks) after Go! before launching fruits
+ if (typeof goShotTick !== "undefined" && LK.ticks - goShotTick < 60) {
+ return;
+ }
+ // Después de los tres primeros, dispara frutas normales
+ var fruit = new Fruit();
+ fruit.x = fruitX;
+ fruit.y = 2732 + fruit.radius - 300;
+ fruit.startY = fruit.y;
+ fruit.targetY = 2732 / 2 + 600;
+ fruit.state = 'rising';
+ fruit.ticks = 0;
+ fruit.roundMeta = {
+ hasCrossed: false,
+ crossedTick: null,
+ showScheduled: false,
+ showTimeout: null,
+ destroyed: false
+ };
+ fruits.push(fruit);
+ roundFruitsQueue.push(fruit);
+ self.addChild(fruit);
}
- // AnimaciĂłn de corte para todas las frutas: mostrar sprite partido, NO el cĂrculo blanco
- var fruitCut = new FruitCut();
- fruitCut.init(fruit.fruitType, fruit.x, fruit.y, fruit.rotation, fruit.scaleX);
- game.addChild(fruitCut);
- // Asegura que la lĂnea negra estĂ© sobre las frutas cortadas pero debajo del cañón
- if (horizontalLine && horizontalLine.parent) {
- horizontalLine.parent.removeChild(horizontalLine);
- game.addChild(horizontalLine);
- }
// Asegura que el cañón siempre esté al frente
if (cannon && cannon.parent) {
cannon.parent.removeChild(cannon);
- game.addChild(cannon);
+ self.addChild(cannon);
}
- fruitCut.animate(function () {
- fruitCut.destroy();
- });
- cutFruits.push(fruitCut);
- frutasGeneradas++;
- updateScore(LK.getScore() + 1);
- return;
+ roundBulletsFired++;
+ // After Go!, wait 1.3 seconds before next bullet
+ if (countdownObjectsFired === 3 && roundBulletsFired === 3) {
+ roundNextBulletTick = LK.ticks + 60; // 1.3s wait after Go!
+ } else if (roundBulletsFired < 3) {
+ // Original timing for countdown objects (1, 2, Go!)
+ roundNextBulletTick = LK.ticks + 30; // 0.5s between countdown objects
+ } else {
+ // Timing between fruits based on stage
+ if (currentStage === 1) {
+ roundNextBulletTick = LK.ticks + 60; // 1s entre frutas (stage 1)
+ } else if (currentStage === 2) {
+ roundNextBulletTick = LK.ticks + 30; // 0.5s entre frutas (stage 2)
+ } else if (currentStage === 3) {
+ roundNextBulletTick = LK.ticks + 30;
+ }
+ }
}
- }
- }
-}
-game.down = function (x, y, obj) {
- tryCutFruit(x, y);
-};
-// Main update
-game.update = function () {
- // Permitir corte nuevamente tras 6 ticks (~100ms)
- if (!canCut && LK.ticks - lastTouchTick > 6) {
- canCut = true;
- }
- // --- SISTEMA DE BALAS POR RONDA (5 balas, 1s entre cada una, 7s delay antes de mostrar en pantalla superior) ---
- if (typeof roundState === "undefined") {
- // Estados posibles: 'waiting', 'spawning', 'waitingFruits'
- roundState = 'waiting';
- roundBullets = 7; // 3 countdown objects + 4 fruits (stage 1)
- roundFruitsQueue = [];
- roundFruitsActive = [];
- roundBulletsFired = 0;
- roundDelayTicks = 0;
- currentStage = 1; // Track current stage (1 or 2)
- roundDelayBetweenRounds = 120; // 2 seconds between rounds
- }
- if (roundState === 'waiting') {
- // Limpiar arrays de frutas y mitades cortadas de la ronda anterior
- for (var i = fruits.length - 1; i >= 0; i--) {
- if (fruits[i]) {
- fruits[i].destroy();
+ // When all bullets are fired, round is complete
+ if (roundBulletsFired >= roundBullets) {
+ roundState = 'complete';
}
}
- fruits = [];
- for (var i = fallingFruits.length - 1; i >= 0; i--) {
- if (fallingFruits[i]) {
- fallingFruits[i].destroy();
- }
+ if (roundState === 'complete') {
+ // Round completed - do nothing, no more spawning
}
- fallingFruits = [];
- for (var i = cutFruits.length - 1; i >= 0; i--) {
- if (cutFruits[i]) {
- cutFruits[i].destroy();
- }
- }
- cutFruits = [];
- // Limpiar arrays de control de ronda
- if (typeof roundFruitsQueue !== "undefined") {
- for (var i = roundFruitsQueue.length - 1; i >= 0; i--) {
- if (roundFruitsQueue[i] && roundFruitsQueue[i].destroy) {
- roundFruitsQueue[i].destroy();
+ // Mover frutas que suben desde abajo hasta el centro
+ for (var i = fruits.length - 1; i >= 0; i--) {
+ var fruit = fruits[i];
+ // Only destroy objects that are NOT rising (i.e., not going up from bottom)
+ // This ensures fruits launched from bottom can reach the top before being destroyed
+ if (fruit.state !== 'rising' && fruit.y < -100) {
+ // Destroy cut zone circle if exists
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
}
- }
- }
- roundFruitsQueue = [];
- if (typeof roundFruitsActive !== "undefined") {
- for (var i = roundFruitsActive.length - 1; i >= 0; i--) {
- if (roundFruitsActive[i] && roundFruitsActive[i].destroy) {
- roundFruitsActive[i].destroy();
+ // Mark as inactive
+ fruit.isActive = false;
+ // Mark as destroyed for round system
+ if (fruit.roundMeta) {
+ fruit.roundMeta.destroyed = true;
}
+ // Clear any scheduled timeouts
+ if (fruit.roundMeta && fruit.roundMeta.showTimeout) {
+ LK.clearTimeout(fruit.roundMeta.showTimeout);
+ fruit.roundMeta.showTimeout = null;
+ }
+ // Remove from roundFruitsQueue if present
+ if (typeof roundFruitsQueue !== "undefined") {
+ for (var j = roundFruitsQueue.length - 1; j >= 0; j--) {
+ if (roundFruitsQueue[j] === fruit) {
+ roundFruitsQueue.splice(j, 1);
+ break;
+ }
+ }
+ }
+ // Destroy the object completely
+ fruit.destroy();
+ fruits.splice(i, 1);
+ continue; // Skip rest of processing for this object
}
- }
- roundFruitsActive = [];
- // Reset meta de ronda
- roundBulletsFired = 0;
- roundNextBulletTick = LK.ticks;
- roundDelayTicks = 0;
- // Set round bullets based on current stage
- if (currentStage === 1) {
- roundBullets = 7; // 3 countdown + 4 fruits
- // Schedule stage 2 to start 8 seconds after stage 1 begins
- if (typeof stage2Scheduled === "undefined" || !stage2Scheduled) {
- stage2Scheduled = true;
- LK.setTimeout(function () {
- // Start stage 2
- currentStage = 2;
- roundState = 'waiting';
- stage2Scheduled = false;
- // Schedule stage 3 to start 5 seconds after stage 2 begins
- if (typeof stage3Scheduled === "undefined" || !stage3Scheduled) {
- stage3Scheduled = true;
- LK.setTimeout(function () {
- currentStage = 3;
- roundState = 'waiting';
- stage3Scheduled = false;
- }, 4000); // 5 seconds after stage 2 starts
+ if (fruit.state === 'rising') {
+ // Cambiar velocidad solo en etapa 2
+ var currentFruitSpeed = fruitSpeed;
+ if (currentStage === 2) {
+ currentFruitSpeed = 40; // velocidad mĂĄs rĂĄpida en etapa 2
+ }
+ fruit.y -= currentFruitSpeed;
+ fruit.ticks++;
+ // Escalado segĂșn altura (mĂĄs arriba, mĂĄs grande)
+ var minScale = 1.0;
+ var maxScale = 1.5;
+ var y0 = 2732 + fruit.radius + 10;
+ var y1 = 2732 / 2 + 420;
+ var t = (fruit.y - y1) / (y0 - y1);
+ if (t < 0) {
+ t = 0;
+ }
+ if (t > 1) {
+ t = 1;
+ }
+ var scale = minScale + (maxScale - minScale) * (1 - t);
+ fruit.scaleX = fruit.scaleY = scale;
+ // RotaciĂłn en la parte de abajo (solo mientras sube)
+ if (typeof fruit.rotation === "undefined") {
+ fruit.rotation = Math.random() * Math.PI * 2;
+ }
+ if (typeof fruit.rotationSpeed === "undefined") {
+ fruit.rotationSpeed = (Math.random() - 0.5) * 0.08;
+ }
+ fruit.rotation += fruit.rotationSpeed;
+ if (fruit.fruitAsset) {
+ fruit.fruitAsset.rotation = fruit.rotation;
+ }
+ // Cuando cruza la altura objetivo (centro), programar apariciĂłn en pantalla superior tras un tiempo proporcional al nĂșmero de frutas lanzadas
+ if (!fruit.roundMeta.hasCrossed && fruit.y <= fruit.targetY) {
+ fruit.roundMeta.hasCrossed = true;
+ fruit.roundMeta.crossedTick = LK.ticks;
+ fruit.visible = false;
+ // Cambiar tiempo de espera solo en etapa 2
+ var appearDelayMs = 2700; // default 2.7s
+ if (currentStage === 2) {
+ appearDelayMs = 1100; // 1.5s en etapa 2
}
- }, 10300); // 8 seconds
+ if (currentStage === 3) {
+ appearDelayMs = 1200; // 1.5s en etapa 2
+ }
+ var isCountdownObject = fruit instanceof CountdownOne || fruit instanceof CountdownTwo || fruit instanceof CountdownGo;
+ if (!isCountdownObject) {
+ fruit.roundMeta.showScheduled = true;
+ fruit.roundMeta.showTimeout = LK.setTimeout(function (fruitRef, fruitsArr, iIdx) {
+ return function () {
+ if (fruitRef.roundMeta.destroyed) {
+ return;
+ }
+ var fruitType = fruitRef.fruitType;
+ var x = fruitRef.x;
+ fruitRef.destroy();
+ for (var j = 0; j < fruitsArr.length; j++) {
+ if (fruitsArr[j] === fruitRef) {
+ fruitsArr.splice(j, 1);
+ break;
+ }
+ }
+ var fallingFruit = new Fruit();
+ if (typeof fruitType === "undefined" || !fruitType) {
+ fruitType = fallingFruit.fruitType;
+ } else {
+ fallingFruit.fruitType = fruitType;
+ }
+ if (fallingFruit.fruitAsset) {
+ fallingFruit.fruitAsset.destroy();
+ }
+ fallingFruit.fruitAsset = fallingFruit.attachAsset(fallingFruit.fruitType, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ fallingFruit.x = x;
+ fallingFruit.y = 2732 / 2 + 420 + 100;
+ fallingFruit.startY = fallingFruit.y;
+ fallingFruit.lastY = 2732; // Initialize lastY to a safe value well below destruction line
+ fallingFruit.state = 'cuttable';
+ fallingFruit.ticks = 0;
+ fallingFruit.rotation = Math.random() * Math.PI * 2;
+ fallingFruit.rotationSpeed = (Math.random() - 0.5) * 0.04;
+ fallingFruit.roundMeta = {
+ destroyed: false
+ };
+ fallingFruits.push(fallingFruit);
+ roundFruitsActive.push(fallingFruit);
+ self.addChild(fallingFruit);
+ if (horizontalLine && horizontalLine.parent) {
+ horizontalLine.parent.removeChild(horizontalLine);
+ self.addChild(horizontalLine);
+ }
+ if (cannon && cannon.parent) {
+ cannon.parent.removeChild(cannon);
+ self.addChild(cannon);
+ }
+ };
+ }(fruit, fruits, i), appearDelayMs);
+ }
+ }
+ if (fruit.roundMeta.hasCrossed && fruit.roundMeta.showScheduled) {
+ if (fruit.roundMeta.destroyed) {
+ if (fruit.roundMeta.showTimeout) {
+ LK.clearTimeout(fruit.roundMeta.showTimeout);
+ fruit.roundMeta.showTimeout = null;
+ }
+ if (typeof roundFruitsQueue !== "undefined") {
+ for (var j = roundFruitsQueue.length - 1; j >= 0; j--) {
+ if (roundFruitsQueue[j] === fruit) {
+ roundFruitsQueue.splice(j, 1);
+ break;
+ }
+ }
+ }
+ fruits.splice(i, 1);
+ }
+ continue;
+ }
}
- } else if (currentStage === 2) {
- roundBullets = 4; // 3 fruits only, no countdown
- countdownObjectsFired = 4; // Skip countdown in stage 2
- } else if (currentStage === 3) {
- // Reiniciar todas las variables para evitar errores en la generaciĂłn de frutas
- frutasGeneradas = 0;
- frutasFalladas = 0;
- fruits = [];
- fallingFruits = [];
- cutFruits = [];
- roundFruitsQueue = [];
- roundFruitsActive = [];
- roundBullets = 4; // 4 frutas en la tercera etapa
- countdownObjectsFired = 4; // No countdown en la etapa 3
- // Clear any existing combo display
- if (comboFadeTimeout) {
- LK.clearTimeout(comboFadeTimeout);
- comboFadeTimeout = null;
- }
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
- }
}
- // Esperar un frame antes de permitir el spawn para evitar generaciĂłn mĂșltiple
- if (typeof roundJustReset === "undefined" || !roundJustReset) {
- roundJustReset = true;
- return;
- } else {
- roundJustReset = false;
- roundState = 'spawning';
- goShotTick = undefined;
+ // Mover frutas que suben de nuevo y gestionar zona de corte visual
+ // --- Asegura que la lĂnea negra estĂ© sobre los sprites de las frutas en cada frame ---
+ if (horizontalLine && horizontalLine.parent) {
+ horizontalLine.parent.removeChild(horizontalLine);
+ self.addChild(horizontalLine);
}
- }
- if (roundState === 'spawning') {
- // Espera inicial antes de cualquier disparo
- if (typeof roundStartTick === "undefined") {
- roundStartTick = LK.ticks;
+ // Asegura que la lĂnea roja de destrucciĂłn estĂ© visible encima de todo
+ if (destructionLine && destructionLine.parent) {
+ destructionLine.parent.removeChild(destructionLine);
+ self.addChild(destructionLine);
}
- var delay = 20; // â±ïž Espera de 2 segundos (120 ticks)
- if (LK.ticks - roundStartTick < delay) {
- return; // âł AĂșn esperando el inicio
+ // Volver a agregar la lĂnea roja al final para que estĂ© encima
+ if (cannon && cannon.parent) {
+ cannon.parent.removeChild(cannon);
+ self.addChild(cannon);
}
- // Disparar los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos
- if (typeof countdownObjectsFired === "undefined") {
- countdownObjectsFired = 0;
+ if (destructionLine && destructionLine.parent) {
+ destructionLine.parent.removeChild(destructionLine);
+ self.addChild(destructionLine);
}
- if (roundBulletsFired < roundBullets && LK.ticks >= roundNextBulletTick) {
- var margin = 180;
- var fruitX = margin + Math.random() * (2048 - 2 * margin);
- cannon.x = fruitX;
- cannon.show();
- cannon.shoot();
- // Dispara "1", "2", "Go" en los primeros tres disparos
- if (countdownObjectsFired === 0) {
- var obj1 = new CountdownOne();
- obj1.x = fruitX;
- obj1.y = 2732 + obj1.radius - 120;
- obj1.startY = obj1.y;
- obj1.targetY = 2732 / 2 + 600;
- obj1.state = 'rising';
- obj1.ticks = 0;
- obj1.roundMeta = {
- hasCrossed: false,
- crossedTick: null,
- showScheduled: false,
- showTimeout: null,
- destroyed: false
- };
- fruits.push(obj1);
- roundFruitsQueue.push(obj1);
- game.addChild(obj1);
- // Mostrar "1" centrado y gigante con fade out
- var centerObj1 = new CountdownOne();
- centerObj1.x = 2048 / 2;
- centerObj1.y = 2732 / 2;
- centerObj1.scaleX = centerObj1.scaleY = 9; // Gigante
- centerObj1.alpha = 1;
- game.addChild(centerObj1);
- // Fade out después de 0.5 segundos
- LK.setTimeout(function () {
- tween(centerObj1, {
- alpha: 0
- }, {
- duration: 300,
- easing: tween.linear,
- onFinish: function onFinish() {
- centerObj1.destroy();
- }
- });
- }, 500);
- countdownObjectsFired++;
- } else if (countdownObjectsFired === 1) {
- var obj2 = new CountdownTwo();
- obj2.x = fruitX;
- obj2.y = 2732 + obj2.radius - 120;
- obj2.startY = obj2.y;
- obj2.targetY = 2732 / 2 + 600;
- obj2.state = 'rising';
- obj2.ticks = 0;
- obj2.roundMeta = {
- hasCrossed: false,
- crossedTick: null,
- showScheduled: false,
- showTimeout: null,
- destroyed: false
- };
- fruits.push(obj2);
- roundFruitsQueue.push(obj2);
- game.addChild(obj2);
- // Mostrar "2" centrado y gigante con fade out
- var centerObj2 = new CountdownTwo();
- centerObj2.x = 2048 / 2;
- centerObj2.y = 2732 / 2;
- centerObj2.scaleX = centerObj2.scaleY = 9; // Gigante
- centerObj2.alpha = 1;
- game.addChild(centerObj2);
- // Fade out después de 0.5 segundos
- LK.setTimeout(function () {
- tween(centerObj2, {
- alpha: 0
- }, {
- duration: 300,
- easing: tween.linear,
- onFinish: function onFinish() {
- centerObj2.destroy();
- }
- });
- }, 500);
- countdownObjectsFired++;
- } else if (countdownObjectsFired === 2) {
- var objGo = new CountdownGo();
- objGo.x = fruitX;
- objGo.y = 2732 + objGo.radius - 120;
- objGo.startY = objGo.y;
- objGo.targetY = 2732 / 2 + 600;
- objGo.state = 'rising';
- objGo.ticks = 0;
- objGo.roundMeta = {
- hasCrossed: false,
- crossedTick: null,
- showScheduled: false,
- showTimeout: null,
- destroyed: false
- };
- fruits.push(objGo);
- roundFruitsQueue.push(objGo);
- game.addChild(objGo);
- // Mostrar "Go!" centrado y gigante con fade out
- var centerObjGo = new CountdownGo();
- centerObjGo.x = 2048 / 2;
- centerObjGo.y = 2732 / 2;
- centerObjGo.scaleX = centerObjGo.scaleY = 9; // Gigante
- centerObjGo.alpha = 1;
- game.addChild(centerObjGo);
- // Fade out después de 0.5 segundos
- LK.setTimeout(function () {
- tween(centerObjGo, {
- alpha: 0
- }, {
- duration: 300,
- easing: tween.linear,
- onFinish: function onFinish() {
- centerObjGo.destroy();
- }
- });
- }, 500);
- countdownObjectsFired++;
- // After Go!, wait 2 seconds before launching fruits
- if (typeof goShotTick === "undefined") {
- goShotTick = LK.ticks;
- // Schedule game end 18 seconds after Go!
- LK.setTimeout(function () {
- // Show stars based on fruits cut
- var starAsset;
- var starSound;
- if (LK.getScore() === 0) {
- starAsset = 'Estrellas0';
- starSound = 'E1'; // Use E1 sound for 0 stars
- } else if (LK.getScore() <= 6) {
- starAsset = 'Estrellas1';
- starSound = 'E1';
- } else if (LK.getScore() <= 11) {
- starAsset = 'Estrellas2';
- starSound = 'E2';
- } else {
- starAsset = 'Estrellas3';
- starSound = 'E3';
- }
- // Create and display star
- var star = LK.getAsset(starAsset, {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 2048 / 2,
- y: 2732 / 2,
- alpha: 0,
- scaleX: 0.5,
- scaleY: 0.5
- });
- game.addChild(star);
- // Play corresponding sound
- LK.getSound(starSound).play();
- // Animate star appearance
- tween(star, {
- alpha: 1,
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 500,
- easing: tween.cubicOut,
- onFinish: function onFinish() {
- // Keep star visible for a moment then show game over
- LK.setTimeout(function () {
- LK.showGameOver();
- }, 2000);
- }
- });
- }, 18000); // 18 seconds
+ for (var i = fallingFruits.length - 1; i >= 0; i--) {
+ var fruit = fallingFruits[i];
+ // Check if falling fruit passes above Y=800 for complete destruction
+ // Only destroy fruits that are falling down (cuttable or flyingup states)
+ if (fruit.y < -100 && (fruit.state === 'cuttable' || fruit.state === 'flyingup')) {
+ // Destroy cut zone circle if exists
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
}
- } else {
- // Wait 1.3 seconds (78 ticks) after Go! before launching fruits
- if (typeof goShotTick !== "undefined" && LK.ticks - goShotTick < 60) {
- return;
+ // Mark as inactive
+ fruit.isActive = false;
+ // Mark as destroyed for round system
+ if (fruit.roundMeta) {
+ fruit.roundMeta.destroyed = true;
}
- // Después de los tres primeros, dispara frutas normales
- var fruit = new Fruit();
- fruit.x = fruitX;
- fruit.y = 2732 + fruit.radius - 300;
- fruit.startY = fruit.y;
- fruit.targetY = 2732 / 2 + 600;
- fruit.state = 'rising';
- fruit.ticks = 0;
- fruit.roundMeta = {
- hasCrossed: false,
- crossedTick: null,
- showScheduled: false,
- showTimeout: null,
- destroyed: false
- };
- fruits.push(fruit);
- roundFruitsQueue.push(fruit);
- game.addChild(fruit);
- }
- // Asegura que el cañón siempre esté al frente
- if (cannon && cannon.parent) {
- cannon.parent.removeChild(cannon);
- game.addChild(cannon);
- }
- roundBulletsFired++;
- // After Go!, wait 1.3 seconds before next bullet
- if (countdownObjectsFired === 3 && roundBulletsFired === 3) {
- roundNextBulletTick = LK.ticks + 60; // 1.3s wait after Go!
- } else if (roundBulletsFired < 3) {
- // Original timing for countdown objects (1, 2, Go!)
- roundNextBulletTick = LK.ticks + 30; // 0.5s between countdown objects
- } else {
- // Timing between fruits based on stage
- if (currentStage === 1) {
- roundNextBulletTick = LK.ticks + 60; // 1s entre frutas (stage 1)
- } else if (currentStage === 2) {
- roundNextBulletTick = LK.ticks + 30; // 0.5s entre frutas (stage 2)
- } else if (currentStage === 3) {
- roundNextBulletTick = LK.ticks + 30;
+ // Remove from roundFruitsActive if present
+ if (typeof roundFruitsActive !== "undefined") {
+ for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
+ if (roundFruitsActive[j] === fruit) {
+ roundFruitsActive.splice(j, 1);
+ break;
+ }
+ }
}
- }
- }
- // When all bullets are fired, round is complete
- if (roundBulletsFired >= roundBullets) {
- roundState = 'complete';
- }
- }
- if (roundState === 'complete') {
- // Round completed - do nothing, no more spawning
- }
- // Mover frutas que suben desde abajo hasta el centro
- for (var i = fruits.length - 1; i >= 0; i--) {
- var fruit = fruits[i];
- // Only destroy objects that are NOT rising (i.e., not going up from bottom)
- // This ensures fruits launched from bottom can reach the top before being destroyed
- if (fruit.state !== 'rising' && fruit.y < -100) {
- // Destroy cut zone circle if exists
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
- }
- // Mark as inactive
- fruit.isActive = false;
- // Mark as destroyed for round system
- if (fruit.roundMeta) {
- fruit.roundMeta.destroyed = true;
- }
- // Clear any scheduled timeouts
- if (fruit.roundMeta && fruit.roundMeta.showTimeout) {
- LK.clearTimeout(fruit.roundMeta.showTimeout);
- fruit.roundMeta.showTimeout = null;
- }
- // Remove from roundFruitsQueue if present
- if (typeof roundFruitsQueue !== "undefined") {
- for (var j = roundFruitsQueue.length - 1; j >= 0; j--) {
- if (roundFruitsQueue[j] === fruit) {
- roundFruitsQueue.splice(j, 1);
- break;
+ // Count as failed if not cut
+ if (!fruit.isCut) {
+ frutasFalladas++;
+ frutasGeneradas++;
+ comboCounter = 0;
+ // Clear any existing combo display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
}
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
}
+ // Destroy the fruit completely
+ fruit.destroy();
+ fallingFruits.splice(i, 1);
+ continue; // Skip rest of processing for this fruit
}
- // Destroy the object completely
- fruit.destroy();
- fruits.splice(i, 1);
- continue; // Skip rest of processing for this object
- }
- if (fruit.state === 'rising') {
- // Cambiar velocidad solo en etapa 2
- var currentFruitSpeed = fruitSpeed;
- if (currentStage === 2) {
- currentFruitSpeed = 40; // velocidad mĂĄs rĂĄpida en etapa 2
+ if (!fruit.isActive) {
+ continue;
}
- fruit.y -= currentFruitSpeed;
- fruit.ticks++;
// Escalado segĂșn altura (mĂĄs arriba, mĂĄs grande)
var minScale = 1.0;
- var maxScale = 1.5;
- var y0 = 2732 + fruit.radius + 10;
- var y1 = 2732 / 2 + 420;
+ var maxScale = 1.25 * 1.3 * 1.3; //{45} // 60% mĂĄs grande en la parte superior
+ var y0 = 2732 / 2 + 420;
+ var y1 = 420;
var t = (fruit.y - y1) / (y0 - y1);
if (t < 0) {
t = 0;
}
@@ -916,488 +1186,460 @@
t = 1;
}
var scale = minScale + (maxScale - minScale) * (1 - t);
fruit.scaleX = fruit.scaleY = scale;
- // RotaciĂłn en la parte de abajo (solo mientras sube)
- if (typeof fruit.rotation === "undefined") {
- fruit.rotation = Math.random() * Math.PI * 2;
+ // RotaciĂłn suave
+ if (typeof fruit.rotationSpeed !== "undefined") {
+ fruit.rotation += fruit.rotationSpeed;
+ if (fruit.fruitAsset) {
+ fruit.fruitAsset.rotation = fruit.rotation;
+ }
}
- if (typeof fruit.rotationSpeed === "undefined") {
- fruit.rotationSpeed = (Math.random() - 0.5) * 0.08;
- }
- fruit.rotation += fruit.rotationSpeed;
- if (fruit.fruitAsset) {
- fruit.fruitAsset.rotation = fruit.rotation;
- }
- // Cuando cruza la altura objetivo (centro), programar apariciĂłn en pantalla superior tras un tiempo proporcional al nĂșmero de frutas lanzadas
- if (!fruit.roundMeta.hasCrossed && fruit.y <= fruit.targetY) {
- fruit.roundMeta.hasCrossed = true;
- fruit.roundMeta.crossedTick = LK.ticks;
- fruit.visible = false;
- // Cambiar tiempo de espera solo en etapa 2
- var appearDelayMs = 2700; // default 2.7s
+ // Movimiento hacia arriba mientras sea cortable o volando hacia arriba
+ if (fruit.state === 'cuttable' || fruit.state === 'flyingup') {
+ var topFruitSpeed = fruitSpeed;
if (currentStage === 2) {
- appearDelayMs = 1100; // 1.5s en etapa 2
+ topFruitSpeed = 30; // velocidad mĂĄs alta en la segunda etapa
}
- if (currentStage === 3) {
- appearDelayMs = 1200; // 1.5s en etapa 2
+ // Double speed if fruit has passed cutting zone
+ if (fruit.doubledSpeed) {
+ topFruitSpeed = topFruitSpeed * 2;
}
- var isCountdownObject = fruit instanceof CountdownOne || fruit instanceof CountdownTwo || fruit instanceof CountdownGo;
- if (!isCountdownObject) {
- fruit.roundMeta.showScheduled = true;
- fruit.roundMeta.showTimeout = LK.setTimeout(function (fruitRef, fruitsArr, iIdx) {
- return function () {
- if (fruitRef.roundMeta.destroyed) {
- return;
- }
- var fruitType = fruitRef.fruitType;
- var x = fruitRef.x;
- fruitRef.destroy();
- for (var j = 0; j < fruitsArr.length; j++) {
- if (fruitsArr[j] === fruitRef) {
- fruitsArr.splice(j, 1);
- break;
- }
- }
- var fallingFruit = new Fruit();
- if (typeof fruitType === "undefined" || !fruitType) {
- fruitType = fallingFruit.fruitType;
- } else {
- fallingFruit.fruitType = fruitType;
- }
- if (fallingFruit.fruitAsset) {
- fallingFruit.fruitAsset.destroy();
- }
- fallingFruit.fruitAsset = fallingFruit.attachAsset(fallingFruit.fruitType, {
- anchorX: 0.5,
- anchorY: 0.5
- });
- fallingFruit.x = x;
- fallingFruit.y = 2732 / 2 + 420 + 100;
- fallingFruit.startY = fallingFruit.y;
- fallingFruit.lastY = 2732; // Initialize lastY to a safe value well below destruction line
- fallingFruit.state = 'cuttable';
- fallingFruit.ticks = 0;
- fallingFruit.rotation = Math.random() * Math.PI * 2;
- fallingFruit.rotationSpeed = (Math.random() - 0.5) * 0.04;
- fallingFruit.roundMeta = {
- destroyed: false
- };
- fallingFruits.push(fallingFruit);
- roundFruitsActive.push(fallingFruit);
- game.addChild(fallingFruit);
- if (horizontalLine && horizontalLine.parent) {
- horizontalLine.parent.removeChild(horizontalLine);
- game.addChild(horizontalLine);
- }
- if (cannon && cannon.parent) {
- cannon.parent.removeChild(cannon);
- game.addChild(cannon);
- }
- };
- }(fruit, fruits, i), appearDelayMs);
- }
+ fruit.y -= topFruitSpeed;
}
- if (fruit.roundMeta.hasCrossed && fruit.roundMeta.showScheduled) {
- if (fruit.roundMeta.destroyed) {
- if (fruit.roundMeta.showTimeout) {
- LK.clearTimeout(fruit.roundMeta.showTimeout);
- fruit.roundMeta.showTimeout = null;
+ // --- AnimaciĂłn progresiva del cĂrculo de corte ---
+ // El cĂrculo aparece desde el inicio de la subida (cuttable), crece y se difumina progresivamente
+ if (fruit.state === 'cuttable') {
+ // Si no existe el cĂrculo, crearlo
+ if (!fruit.cutZoneCircle) {
+ fruit.cutZoneCircle = LK.getAsset('cut_zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: fruit.x,
+ y: fruit.y,
+ alpha: 0.0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ });
+ self.addChild(fruit.cutZoneCircle);
+ // Asegura que la lĂnea negra estĂ© sobre el cĂrculo de corte pero debajo del cañón
+ if (horizontalLine && horizontalLine.parent) {
+ horizontalLine.parent.removeChild(horizontalLine);
+ self.addChild(horizontalLine);
}
- if (typeof roundFruitsQueue !== "undefined") {
- for (var j = roundFruitsQueue.length - 1; j >= 0; j--) {
- if (roundFruitsQueue[j] === fruit) {
- roundFruitsQueue.splice(j, 1);
- break;
- }
- }
+ // Asegura que el cañón siempre esté al frente
+ if (cannon && cannon.parent) {
+ cannon.parent.removeChild(cannon);
+ self.addChild(cannon);
}
- fruits.splice(i, 1);
}
- continue;
- }
- }
- }
- // Mover frutas que suben de nuevo y gestionar zona de corte visual
- // --- Asegura que la lĂnea negra estĂ© sobre los sprites de las frutas en cada frame ---
- if (horizontalLine && horizontalLine.parent) {
- horizontalLine.parent.removeChild(horizontalLine);
- game.addChild(horizontalLine);
- }
- // Asegura que la lĂnea roja de destrucciĂłn estĂ© visible encima de todo
- if (destructionLine && destructionLine.parent) {
- destructionLine.parent.removeChild(destructionLine);
- game.addChild(destructionLine);
- }
- // Volver a agregar la lĂnea roja al final para que estĂ© encima
- if (cannon && cannon.parent) {
- cannon.parent.removeChild(cannon);
- game.addChild(cannon);
- }
- if (destructionLine && destructionLine.parent) {
- destructionLine.parent.removeChild(destructionLine);
- game.addChild(destructionLine);
- }
- for (var i = fallingFruits.length - 1; i >= 0; i--) {
- var fruit = fallingFruits[i];
- // Check if falling fruit passes above Y=800 for complete destruction
- // Only destroy fruits that are falling down (cuttable or flyingup states)
- if (fruit.y < -100 && (fruit.state === 'cuttable' || fruit.state === 'flyingup')) {
- // Destroy cut zone circle if exists
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
- }
- // Mark as inactive
- fruit.isActive = false;
- // Mark as destroyed for round system
- if (fruit.roundMeta) {
- fruit.roundMeta.destroyed = true;
- }
- // Remove from roundFruitsActive if present
- if (typeof roundFruitsActive !== "undefined") {
- for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
- if (roundFruitsActive[j] === fruit) {
- roundFruitsActive.splice(j, 1);
- break;
- }
+ // ProgresiĂłn del cĂrculo: desde que inicia la subida hasta que llega cerca de la parte superior
+ var appearT = (y0 - fruit.y) / (y0 - y1);
+ if (appearT < 0) {
+ appearT = 0;
}
- }
- // Count as failed if not cut
- if (!fruit.isCut) {
- frutasFalladas++;
- frutasGeneradas++;
- comboCounter = 0;
- // Clear any existing combo display
- if (comboFadeTimeout) {
- LK.clearTimeout(comboFadeTimeout);
- comboFadeTimeout = null;
+ if (appearT > 1) {
+ appearT = 1;
}
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
+ var maxScaleZone = 0.85; // Mås pequeño, para que quede dentro de la fruta
+ var minScaleZone = 0.15;
+ var maxAlpha = 0.38; // MĂĄs difuminado
+ var minAlpha = 0.08;
+ var scaleZone = minScaleZone + (maxScaleZone - minScaleZone) * appearT;
+ var alphaZone = minAlpha + (maxAlpha - minAlpha) * appearT;
+ fruit.cutZoneCircle.scaleX = fruit.cutZoneCircle.scaleY = scaleZone;
+ fruit.cutZoneCircle.alpha = alphaZone;
+ fruit.cutZoneCircle.x = fruit.x;
+ fruit.cutZoneCircle.y = fruit.y;
+ // Si la fruta sale por arriba, eliminar cĂrculo y pasar a flyingup
+ if (fruit.y < y1) {
+ // Si el cĂrculo de corte existe y la fruta no fue cortada, contar como fallada
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
+ if (fruit.isActive && !fruit.isCut) {
+ frutasFalladas++;
+ frutasGeneradas++;
+ comboCounter = 0;
+ // Clear any existing combo display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
+ }
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
+ }
+ }
+ fruit.state = 'flyingup';
+ // Double the speed when fruit can no longer be cut
+ fruit.doubledSpeed = true;
}
- }
- // Destroy the fruit completely
- fruit.destroy();
- fallingFruits.splice(i, 1);
- continue; // Skip rest of processing for this fruit
- }
- if (!fruit.isActive) {
- continue;
- }
- // Escalado segĂșn altura (mĂĄs arriba, mĂĄs grande)
- var minScale = 1.0;
- var maxScale = 1.25 * 1.3 * 1.3; //{45} // 60% mĂĄs grande en la parte superior
- var y0 = 2732 / 2 + 420;
- var y1 = 420;
- var t = (fruit.y - y1) / (y0 - y1);
- if (t < 0) {
- t = 0;
- }
- if (t > 1) {
- t = 1;
- }
- var scale = minScale + (maxScale - minScale) * (1 - t);
- fruit.scaleX = fruit.scaleY = scale;
- // RotaciĂłn suave
- if (typeof fruit.rotationSpeed !== "undefined") {
- fruit.rotation += fruit.rotationSpeed;
- if (fruit.fruitAsset) {
- fruit.fruitAsset.rotation = fruit.rotation;
- }
- }
- // Movimiento hacia arriba mientras sea cortable o volando hacia arriba
- if (fruit.state === 'cuttable' || fruit.state === 'flyingup') {
- var topFruitSpeed = fruitSpeed;
- if (currentStage === 2) {
- topFruitSpeed = 30; // velocidad mĂĄs alta en la segunda etapa
- }
- // Double speed if fruit has passed cutting zone
- if (fruit.doubledSpeed) {
- topFruitSpeed = topFruitSpeed * 2;
- }
- fruit.y -= topFruitSpeed;
- }
- // --- AnimaciĂłn progresiva del cĂrculo de corte ---
- // El cĂrculo aparece desde el inicio de la subida (cuttable), crece y se difumina progresivamente
- if (fruit.state === 'cuttable') {
- // Si no existe el cĂrculo, crearlo
- if (!fruit.cutZoneCircle) {
- fruit.cutZoneCircle = LK.getAsset('cut_zone', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: fruit.x,
- y: fruit.y,
- alpha: 0.0,
- scaleX: 0.1,
- scaleY: 0.1
- });
- game.addChild(fruit.cutZoneCircle);
- // Asegura que la lĂnea negra estĂ© sobre el cĂrculo de corte pero debajo del cañón
- if (horizontalLine && horizontalLine.parent) {
- horizontalLine.parent.removeChild(horizontalLine);
- game.addChild(horizontalLine);
- }
- // Asegura que el cañón siempre esté al frente
- if (cannon && cannon.parent) {
- cannon.parent.removeChild(cannon);
- game.addChild(cannon);
- }
- }
- // ProgresiĂłn del cĂrculo: desde que inicia la subida hasta que llega cerca de la parte superior
- var appearT = (y0 - fruit.y) / (y0 - y1);
- if (appearT < 0) {
- appearT = 0;
- }
- if (appearT > 1) {
- appearT = 1;
- }
- var maxScaleZone = 0.85; // Mås pequeño, para que quede dentro de la fruta
- var minScaleZone = 0.15;
- var maxAlpha = 0.38; // MĂĄs difuminado
- var minAlpha = 0.08;
- var scaleZone = minScaleZone + (maxScaleZone - minScaleZone) * appearT;
- var alphaZone = minAlpha + (maxAlpha - minAlpha) * appearT;
- fruit.cutZoneCircle.scaleX = fruit.cutZoneCircle.scaleY = scaleZone;
- fruit.cutZoneCircle.alpha = alphaZone;
- fruit.cutZoneCircle.x = fruit.x;
- fruit.cutZoneCircle.y = fruit.y;
- // Si la fruta sale por arriba, eliminar cĂrculo y pasar a flyingup
- if (fruit.y < y1) {
- // Si el cĂrculo de corte existe y la fruta no fue cortada, contar como fallada
+ } else {
+ // Si no estĂĄ en estado cortable y existe el cĂrculo, destruirlo
if (fruit.cutZoneCircle) {
fruit.cutZoneCircle.destroy();
fruit.cutZoneCircle = null;
- if (fruit.isActive && !fruit.isCut) {
- frutasFalladas++;
- frutasGeneradas++;
- comboCounter = 0;
- // Clear any existing combo display
- if (comboFadeTimeout) {
- LK.clearTimeout(comboFadeTimeout);
- comboFadeTimeout = null;
- }
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
- }
- }
}
- fruit.state = 'flyingup';
- // Double the speed when fruit can no longer be cut
- fruit.doubledSpeed = true;
}
- } else {
- // Si no estĂĄ en estado cortable y existe el cĂrculo, destruirlo
- if (fruit.cutZoneCircle) {
+ // Si fue cortada, eliminar cĂrculo visual inmediatamente pero mantener la fruta visible
+ if (!fruit.isActive && fruit.cutZoneCircle) {
fruit.cutZoneCircle.destroy();
fruit.cutZoneCircle = null;
}
- }
- // Si fue cortada, eliminar cĂrculo visual inmediatamente pero mantener la fruta visible
- if (!fruit.isActive && fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
- }
- // Si estĂĄ cayendo, animar caĂda
- if (fruit.state === 'dropping') {
- fruit.dropSpeed += 2.5; // gravedad
- fruit.y += fruit.dropSpeed;
- // Escalado decreciente al caer
- fruit.scaleX = fruit.scaleY = Math.max(0.7, fruit.scaleX - 0.01);
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.x = fruit.x;
- fruit.cutZoneCircle.y = fruit.y;
- }
- // Si sale de pantalla, marcar como inactivo pero mantener visible
- if (fruit.y > 2732 + fruit.radius + 20) {
+ // Si estĂĄ cayendo, animar caĂda
+ if (fruit.state === 'dropping') {
+ fruit.dropSpeed += 2.5; // gravedad
+ fruit.y += fruit.dropSpeed;
+ // Escalado decreciente al caer
+ fruit.scaleX = fruit.scaleY = Math.max(0.7, fruit.scaleX - 0.01);
if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
+ fruit.cutZoneCircle.x = fruit.x;
+ fruit.cutZoneCircle.y = fruit.y;
}
- fruit.isActive = false;
- }
- }
- // Si la fruta sigue subiendo después de la zona de corte y no fue cortada
- if (fruit.state === 'flyingup') {
- // Al entrar por primera vez en flyingup, inicia temporizador de espera
- if (typeof fruit.waitTicks === "undefined") {
- fruit.waitTicks = 0;
- }
- fruit.waitTicks++;
- // Mantener la fruta visible y estĂĄtica durante 4 segundos (240 ticks)
- if (fruit.waitTicks < 240) {
- // Mantener posiciĂłn (opcional: podrĂas hacer que siga subiendo lentamente)
- // fruit.y -= fruitSpeed * 0.1;
- } else {
- // Después de 7 segundos, hacer que suba y desaparezca
- // Continue moving at current speed (already doubled if applicable)
- // Escalado sigue creciendo un poco
- fruit.scaleX = fruit.scaleY = Math.min(maxScale, fruit.scaleX + 0.01);
- // Check if fruit passes destruction line at Y=800 for complete destruction
- if (fruit.y < -100) {
- // Destroy cut zone circle if exists
+ // Si sale de pantalla, marcar como inactivo pero mantener visible
+ if (fruit.y > 2732 + fruit.radius + 20) {
if (fruit.cutZoneCircle) {
fruit.cutZoneCircle.destroy();
fruit.cutZoneCircle = null;
}
- // Mark as inactive
fruit.isActive = false;
- // Mark as destroyed for round system
- if (fruit.roundMeta) {
- fruit.roundMeta.destroyed = true;
- }
- // Remove from roundFruitsActive if present
- if (typeof roundFruitsActive !== "undefined") {
- for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
- if (roundFruitsActive[j] === fruit) {
- roundFruitsActive.splice(j, 1);
- break;
- }
+ }
+ }
+ // Si la fruta sigue subiendo después de la zona de corte y no fue cortada
+ if (fruit.state === 'flyingup') {
+ // Al entrar por primera vez en flyingup, inicia temporizador de espera
+ if (typeof fruit.waitTicks === "undefined") {
+ fruit.waitTicks = 0;
+ }
+ fruit.waitTicks++;
+ // Mantener la fruta visible y estĂĄtica durante 4 segundos (240 ticks)
+ if (fruit.waitTicks < 240) {
+ // Mantener posiciĂłn (opcional: podrĂas hacer que siga subiendo lentamente)
+ // fruit.y -= fruitSpeed * 0.1;
+ } else {
+ // Después de 7 segundos, hacer que suba y desaparezca
+ // Continue moving at current speed (already doubled if applicable)
+ // Escalado sigue creciendo un poco
+ fruit.scaleX = fruit.scaleY = Math.min(maxScale, fruit.scaleX + 0.01);
+ // Check if fruit passes destruction line at Y=800 for complete destruction
+ if (fruit.y < -100) {
+ // Destroy cut zone circle if exists
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
}
- }
- // Count as failed if not cut
- if (!fruit.isCut) {
- frutasFalladas++;
- frutasGeneradas++;
- comboCounter = 0;
- // Clear any existing combo display
- if (comboFadeTimeout) {
- LK.clearTimeout(comboFadeTimeout);
- comboFadeTimeout = null;
+ // Mark as inactive
+ fruit.isActive = false;
+ // Mark as destroyed for round system
+ if (fruit.roundMeta) {
+ fruit.roundMeta.destroyed = true;
}
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
+ // Remove from roundFruitsActive if present
+ if (typeof roundFruitsActive !== "undefined") {
+ for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
+ if (roundFruitsActive[j] === fruit) {
+ roundFruitsActive.splice(j, 1);
+ break;
+ }
+ }
}
- }
- // Destroy the fruit completely
- fruit.destroy();
- fallingFruits.splice(i, 1);
- continue; // Skip rest of processing for this fruit
- }
- // Si sale de pantalla por arriba, marcar como inactiva y eliminar cĂrculo de corte si existe
- if (fruit.y < -fruit.radius - 20) {
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
- }
- fruit.isActive = false;
- // Marcar como destruida para el sistema de ronda
- if (fruit.roundMeta) {
- fruit.roundMeta.destroyed = true;
- }
- // Eliminar de roundFruitsActive si estĂĄ presente
- if (typeof roundFruitsActive !== "undefined") {
- for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
- if (roundFruitsActive[j] === fruit) {
- roundFruitsActive.splice(j, 1);
- break;
+ // Count as failed if not cut
+ if (!fruit.isCut) {
+ frutasFalladas++;
+ frutasGeneradas++;
+ comboCounter = 0;
+ // Clear any existing combo display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
}
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
}
+ // Destroy the fruit completely
+ fruit.destroy();
+ fallingFruits.splice(i, 1);
+ continue; // Skip rest of processing for this fruit
}
- // Aumentar frutasFalladas y frutasGeneradas solo si la fruta no fue cortada
- if (!fruit.isCut) {
- frutasFalladas++;
- frutasGeneradas++;
- comboCounter = 0;
- // Clear any existing combo display
- if (comboFadeTimeout) {
- LK.clearTimeout(comboFadeTimeout);
- comboFadeTimeout = null;
+ // Si sale de pantalla por arriba, marcar como inactiva y eliminar cĂrculo de corte si existe
+ if (fruit.y < -fruit.radius - 20) {
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
}
- if (comboImage) {
- comboImage.destroy();
- comboImage = null;
+ fruit.isActive = false;
+ // Marcar como destruida para el sistema de ronda
+ if (fruit.roundMeta) {
+ fruit.roundMeta.destroyed = true;
}
+ // Eliminar de roundFruitsActive si estĂĄ presente
+ if (typeof roundFruitsActive !== "undefined") {
+ for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
+ if (roundFruitsActive[j] === fruit) {
+ roundFruitsActive.splice(j, 1);
+ break;
+ }
+ }
+ }
+ // Aumentar frutasFalladas y frutasGeneradas solo si la fruta no fue cortada
+ if (!fruit.isCut) {
+ frutasFalladas++;
+ frutasGeneradas++;
+ comboCounter = 0;
+ // Clear any existing combo display
+ if (comboFadeTimeout) {
+ LK.clearTimeout(comboFadeTimeout);
+ comboFadeTimeout = null;
+ }
+ if (comboImage) {
+ comboImage.destroy();
+ comboImage = null;
+ }
+ }
}
}
}
- }
- // Si la fruta ya fue cortada o saliĂł de pantalla, eliminar
- if (!fruit.isActive || fruit.y > 2732 + fruit.radius + 20 || fruit.y < -fruit.radius - 20) {
- if (fruit.cutZoneCircle) {
- fruit.cutZoneCircle.destroy();
- fruit.cutZoneCircle = null;
- }
- // Marcar como destruida para el sistema de ronda
- if (fruit.roundMeta) {
- fruit.roundMeta.destroyed = true;
- }
- // Eliminar de roundFruitsActive si estĂĄ presente
- if (typeof roundFruitsActive !== "undefined") {
- for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
- if (roundFruitsActive[j] === fruit) {
- roundFruitsActive.splice(j, 1);
- break;
+ // Si la fruta ya fue cortada o saliĂł de pantalla, eliminar
+ if (!fruit.isActive || fruit.y > 2732 + fruit.radius + 20 || fruit.y < -fruit.radius - 20) {
+ if (fruit.cutZoneCircle) {
+ fruit.cutZoneCircle.destroy();
+ fruit.cutZoneCircle = null;
+ }
+ // Marcar como destruida para el sistema de ronda
+ if (fruit.roundMeta) {
+ fruit.roundMeta.destroyed = true;
+ }
+ // Eliminar de roundFruitsActive si estĂĄ presente
+ if (typeof roundFruitsActive !== "undefined") {
+ for (var j = roundFruitsActive.length - 1; j >= 0; j--) {
+ if (roundFruitsActive[j] === fruit) {
+ roundFruitsActive.splice(j, 1);
+ break;
+ }
}
}
+ fruit.destroy();
+ fallingFruits.splice(i, 1);
}
- fruit.destroy();
- fallingFruits.splice(i, 1);
}
- }
- // Limpiar mitades cortadas que ya terminaron animaciĂłn
- for (var i = cutFruits.length - 1; i >= 0; i--) {
- var fc = cutFruits[i];
- if (!fc.left || !fc.right) {
- if (fc.destroy) {
- fc.destroy();
+ // Limpiar mitades cortadas que ya terminaron animaciĂłn
+ for (var i = cutFruits.length - 1; i >= 0; i--) {
+ var fc = cutFruits[i];
+ if (!fc.left || !fc.right) {
+ if (fc.destroy) {
+ fc.destroy();
+ }
+ cutFruits.splice(i, 1);
}
- cutFruits.splice(i, 1);
}
- }
- // Variable para controlar el timeout (debe estar fuera de la funciĂłn que chequea frutasFalladas)
- if (frutasFalladas >= 5 || frutasGeneradas >= 5 && frutasFalladas < 5) {
- // Mostrar los sprites 1, 2, Go en el centro con fade in/fade out rĂĄpido solo una vez, SOLO al inicio del juego
- if ((typeof showCountdownInMiddleDone === "undefined" || !showCountdownInMiddleDone) && LK.ticks < 120) {
- showCountdownInMiddleDone = true;
- var centerX = 2048 / 2;
- var centerY = 2732 / 2;
- var countdownSprites = [{
- cls: CountdownOne,
- delay: 0
- }, {
- cls: CountdownTwo,
- delay: 350
- }, {
- cls: CountdownGo,
- delay: 700
- }];
- for (var idx = 0; idx < countdownSprites.length; idx++) {
- (function (idx) {
- var conf = countdownSprites[idx];
- LK.setTimeout(function () {
- var obj = new conf.cls();
- obj.x = centerX;
- obj.y = centerY;
- obj.alpha = 0;
- game.addChild(obj);
- // Fade in rĂĄpido
- tween(obj, {
- alpha: 1
- }, {
- duration: 180,
- easing: tween.cubicOut,
- onFinish: function onFinish() {
- // Fade out rĂĄpido
- tween(obj, {
- alpha: 0
- }, {
- duration: 180,
- delay: 180,
- easing: tween.cubicIn,
- onFinish: function onFinish() {
- obj.destroy();
- }
- });
- }
- });
- }, conf.delay);
- })(idx);
+ // Variable para controlar el timeout (debe estar fuera de la funciĂłn que chequea frutasFalladas)
+ if (frutasFalladas >= 5 || frutasGeneradas >= 5 && frutasFalladas < 5) {
+ // Mostrar los sprites 1, 2, Go en el centro con fade in/fade out rĂĄpido solo una vez, SOLO al inicio del juego
+ if ((typeof showCountdownInMiddleDone === "undefined" || !showCountdownInMiddleDone) && LK.ticks < 120) {
+ showCountdownInMiddleDone = true;
+ var centerX = 2048 / 2;
+ var centerY = 2732 / 2;
+ var countdownSprites = [{
+ cls: CountdownOne,
+ delay: 0
+ }, {
+ cls: CountdownTwo,
+ delay: 350
+ }, {
+ cls: CountdownGo,
+ delay: 700
+ }];
+ for (var idx = 0; idx < countdownSprites.length; idx++) {
+ (function (idx) {
+ var conf = countdownSprites[idx];
+ LK.setTimeout(function () {
+ var obj = new conf.cls();
+ obj.x = centerX;
+ obj.y = centerY;
+ obj.alpha = 0;
+ self.addChild(obj);
+ // Fade in rĂĄpido
+ tween(obj, {
+ alpha: 1
+ }, {
+ duration: 180,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ // Fade out rĂĄpido
+ tween(obj, {
+ alpha: 0
+ }, {
+ duration: 180,
+ delay: 180,
+ easing: tween.cubicIn,
+ onFinish: function onFinish() {
+ obj.destroy();
+ }
+ });
+ }
+ });
+ }, conf.delay);
+ })(idx);
+ }
}
+ return;
}
- return;
+ };
+ return self;
+});
+// End Scene - shows after stars with restart and menu buttons
+var EndScene = Scene.expand(function () {
+ var self = Scene.call(this);
+ // Background overlay
+ var overlay = self.attachAsset('vertical_line', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1366,
+ width: 2048,
+ height: 2732,
+ alpha: 0.7
+ });
+ // Restart button
+ var restartButton = self.attachAsset('greenLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1200,
+ width: 350,
+ height: 120,
+ alpha: 0.8
+ });
+ var restartText = new Text2('REINICIAR', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ restartText.anchor.set(0.5, 0.5);
+ restartText.x = 1024;
+ restartText.y = 1200;
+ self.addChild(restartText);
+ // Menu button
+ var menuButton = self.attachAsset('cut_zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1400,
+ width: 350,
+ height: 120,
+ alpha: 0.8
+ });
+ var menuText = new Text2('MENU', {
+ size: 60,
+ fill: 0x000000
+ });
+ menuText.anchor.set(0.5, 0.5);
+ menuText.x = 1024;
+ menuText.y = 1400;
+ self.addChild(menuText);
+ // Button interactions
+ restartButton.interactive = true;
+ menuButton.interactive = true;
+ restartButton.down = function () {
+ restartButton.alpha = 0.6;
+ };
+ restartButton.up = function () {
+ restartButton.alpha = 0.8;
+ if (game.onRestartPressed) {
+ game.onRestartPressed();
+ }
+ };
+ menuButton.down = function () {
+ menuButton.alpha = 0.6;
+ };
+ menuButton.up = function () {
+ menuButton.alpha = 0.8;
+ if (game.onMenuPressed) {
+ game.onMenuPressed();
+ }
+ };
+ return self;
+});
+
+/****
+* Initialize Game
+****/
+var game = new LK.Game({
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Scene management variables
+var currentScene = null;
+var menuScene = null;
+var gameScene = null;
+var endScene = null;
+// Create scenes
+menuScene = new MenuScene();
+gameScene = new GameScene();
+endScene = new EndScene();
+// Add scenes to game
+game.addChild(menuScene);
+game.addChild(gameScene);
+game.addChild(endScene);
+// Initially show menu
+menuScene.activate();
+gameScene.deactivate();
+endScene.deactivate();
+currentScene = menuScene;
+// Scene transition handlers
+game.onPlayPressed = function () {
+ menuScene.deactivate();
+ gameScene.activate();
+ endScene.deactivate();
+ currentScene = gameScene;
+ // Initialize game when transitioning to game scene
+ if (!gameScene.gameInitialized) {
+ gameScene.initGame();
+ gameScene.gameInitialized = true;
}
+ // Start music when game starts
+ LK.playMusic('bgmusic', {
+ loop: false
+ });
};
-updateScore(0);
\ No newline at end of file
+game.onRestartPressed = function () {
+ endScene.deactivate();
+ // Reset game scene
+ gameScene.deactivate();
+ game.removeChild(gameScene);
+ gameScene = new GameScene();
+ game.addChild(gameScene);
+ gameScene.activate();
+ currentScene = gameScene;
+ gameScene.initGame();
+ gameScene.gameInitialized = true;
+ // Restart music
+ LK.stopMusic();
+ LK.playMusic('bgmusic', {
+ loop: false
+ });
+};
+game.onMenuPressed = function () {
+ endScene.deactivate();
+ gameScene.deactivate();
+ menuScene.activate();
+ currentScene = menuScene;
+ // Stop music when returning to menu
+ LK.stopMusic();
+ // Reset game scene for next play
+ game.removeChild(gameScene);
+ gameScene = new GameScene();
+ game.addChild(gameScene);
+ gameScene.gameInitialized = false;
+};
+// Main game update loop
+game.update = function () {
+ if (currentScene && currentScene.updateGame) {
+ currentScene.updateGame();
+ }
+};
\ No newline at end of file
Kiwi Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Limon Circular Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Naranja Circular Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Manzana Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Ciruela Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Manzana Fruta cortada a la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Kiwi Fruta cortado por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Limon Circular Cortado por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Naranja Circular Cortada por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Ciruela Fruta cortada por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
Agrega una rueda en la parte trasera del canÌon.
En lugar del numero 2 un numero 1
Letars GO! dentro del circulo.
Red cicle thiner but maintan the image size
En lugar del numero 1 un numero 2
Puedes hacer varias imagenes reemplazando el numero 2 por los numeros 3, 4, 5, 6, 7 y 8? Solo debe haber un numero en cada imagen.
En lugar del numero 3 un numero 4
En lugar del numero 4 un numero 5
En lugar del numero 5 un numero 6
En lugar del numero 6 un numero 7
En lugar del numero 1 un numero 8
En lugar del numero 1 un numero 9
En lugar del numero 9 un numero 10
En lugar del numero 1 un numero 11
Boton de juego que diga "START". In-Game asset. 2d. High contrast. No shadows
Boton de juego que diga "RESTART". In-Game asset. 2d. High contrast. No shadows
Boton de juego Azul que diga "MENU". In-Game asset. 2d. High contrast. No shadows
Un fondo colorido y brillante estilo caricatura. La escena es un bosque abierto alegre con colores pastel vibrantes, formas suaves y redondeadas, y un cielo azul claro con nubes esponjosas. El estilo es kawaii, juguetoÌn y fantaÌstico, con liÌneas suaves y una atmoÌsfera feliz y amigable, perfecto para una introduccioÌn divertida y cute de un juego. In-Game asset. 2d. High contrast. No shadows
"Beat the Fruit" titulo para el juego, muestra las letras en grande blancas con un borde negro y sin fondo, con algunas frutitas felices junto a las letras. In-Game asset. 2d. High contrast. No shadows
Barra verde horizontal estilo caricatura.. In-Game asset. 2d. High contrast. No shadows