User prompt
Ahora todo hace Spawn al inicio, ne debias de modificar el spawn del 1, 2, GO! Solo quitar el bucle de las frutas.
User prompt
Please fix the bug: 'ReferenceError: roundSpawningDone is not defined' in or related to this line: 'if (!roundSpawningDone) {' Line Number: 513
User prompt
El spawn de las frutas esta haciendo bucle, no deberia, quita todos los bucles.
Code edit (3 edits merged)
Please save this source code
User prompt
Ahora, quita el bucle del spawn de las frutas
User prompt
Después de cada ronda aparece el 1, 2 y Go! al centro de la pantalla, quita esto solo debe ser al principio
User prompt
Exacto, pero mucho más grandes. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
En el momento que se dispara la figura mostrarla grande en el centro del juego, hacer fade out en .5 segundos. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Necesito que esos tres sprites que salen del cañon al principio lo muestres a la mitad del juego, que hagan un fade in y fade out de manera rapida. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Si se disparan los tres Objetos pero en la parte superior salen frutas, no quiero que salga nada con estos tres primeros objetos, solo en la primera ronda de disparos.
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'length')' in or related to this line: 'fallingFruit.fruitAsset = fallingFruit.attachAsset(fruitType, {' Line Number: 717
User prompt
Que al disparar las primeras tres veces en lugar de salir frutas que salgan tres objetos que yo editare en los assets, llamalos 1, 2, Go. Esos no deben salir por la parte superior, posterior a que estos tres sean disparados ahora si inicia el bucle de las frutas.
User prompt
Limpia el código.
User prompt
Limpia el codigo de todo lo que no se use o riva par algo.
User prompt
Ahora el delay es mayor, debia ser menos.
User prompt
Si pero dispara lento al principio, un poco más rapido
User prompt
Me gustaria que no solo se mostrara, que el cañon dispare la cuenta regresiva.
User prompt
Para los primeros tres disparos, que en lugar de salir frutas salgan números dentro de un circulo 2, 1, Go. Posterior ahora si empiece el cilo de las frutas
User prompt
Agrega una cacnion de fonde que este en bucle y se inicie al iniciar el juego.
User prompt
Puedes cambair el ritmo con el que salen las frutas disparadas? En lugar de 1 segundo que sea a 120 BPM.
User prompt
Please fix the bug: 'scoreTxt is not defined' in or related to this line: 'scoreTxt.setText(val);' Line Number: 334
User prompt
Oculta el contador de Frutas, hasta arriba hay un contador tambien retiralo.
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
El fondo inferior debe ser de color cafe y el azul de color azul, agregalos como Assets para poder modificarlos.
/**** * 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 }); }; // Ocultar cañón (bajarlo fuera de pantalla) self.hide = function () { self.isVisible = false; tween(self, { y: 2732 + 400 }, { duration: 400, easing: tween.cubicIn, onFinish: function onFinish() { self.visible = false; } }); }; // 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; }); // Clase para la fruta entera 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 }); self.radius = self.fruitAsset.width / 2; // Estado self.isCut = false; self.isActive = true; // Si está en juego // Para saber si ya fue cortada 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; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Inicia la música de fondo en loop al iniciar el juego LK.playMusic('bgmusic', { loop: true }); // 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); // 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; // 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 roundBullets = 5; var fruitSpeed = 22; // Variable de control para evitar spawn múltiple de frutas por ronda var roundSpawningDone = false; 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; } 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(); // 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); } fruitCut.animate(function () { fruitCut.destroy(); }); cutFruits.push(fruitCut); frutasGeneradas++; updateScore(LK.getScore() + 1); return; } } } } 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 = 5; roundFruitsQueue = []; roundFruitsActive = []; roundNextBulletTick = LK.ticks + 30; // primer disparo tras 0.5s roundBulletsFired = 0; roundDelayBetweenRounds = 120; // 2s entre rondas roundDelayTicks = 0; } 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; // 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'; } } if (roundState === 'spawning') { // Disparar los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos if (typeof countdownObjectsFired === "undefined") { countdownObjectsFired = 0; } // Solo permitir el spawn de frutas una vez, no en bucle if (!roundSpawningDone) { var margin = 180; // Dispara los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos for (var i = 0; i < 3; i++) { var fruitX = margin + Math.random() * (2048 - 2 * margin); cannon.x = fruitX; cannon.show(); cannon.shoot(); if (i === 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 mucho más grande en el centro con fade out var centerObj1 = new CountdownOne(); centerObj1.x = 2048 / 2; centerObj1.y = 2732 / 2; centerObj1.scaleX = centerObj1.scaleY = 6.0; centerObj1.alpha = 1; game.addChild(centerObj1); tween(centerObj1, { alpha: 0 }, { duration: 500, easing: tween.cubicIn, onFinish: function onFinish() { centerObj1.destroy(); } }); countdownObjectsFired++; } else if (i === 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 mucho más grande en el centro con fade out var centerObj2 = new CountdownTwo(); centerObj2.x = 2048 / 2; centerObj2.y = 2732 / 2; centerObj2.scaleX = centerObj2.scaleY = 6.0; centerObj2.alpha = 1; game.addChild(centerObj2); tween(centerObj2, { alpha: 0 }, { duration: 500, easing: tween.cubicIn, onFinish: function onFinish() { centerObj2.destroy(); } }); countdownObjectsFired++; } else if (i === 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 mucho más grande en el centro con fade out var centerObjGo = new CountdownGo(); centerObjGo.x = 2048 / 2; centerObjGo.y = 2732 / 2; centerObjGo.scaleX = centerObjGo.scaleY = 6.0; centerObjGo.alpha = 1; game.addChild(centerObjGo); tween(centerObjGo, { alpha: 0 }, { duration: 500, easing: tween.cubicIn, onFinish: function onFinish() { centerObjGo.destroy(); } }); countdownObjectsFired++; } // Asegura que el cañón siempre esté al frente if (cannon && cannon.parent) { cannon.parent.removeChild(cannon); game.addChild(cannon); } } // Ahora, solo después de los 1,2,Go! iniciales, dispara las frutas normales una sola vez for (var i = 3; i < roundBullets; i++) { var fruitX = margin + Math.random() * (2048 - 2 * margin); var fruit = new Fruit(); fruit.x = fruitX; fruit.y = 2732 + fruit.radius - 120; 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); } } roundSpawningDone = true; } // Cuando todas las balas han sido disparadas y ya no quedan frutas activas, pasar a siguiente estado // (pero solo cuando todas las frutas hayan sido destruidas o salidas de pantalla) var allGone = true; for (var i = 0; i < roundFruitsQueue.length; i++) { if (!roundFruitsQueue[i].roundMeta.destroyed) { allGone = false; break; } } for (var i = 0; i < roundFruitsActive.length; i++) { if (!roundFruitsActive[i].roundMeta.destroyed) { allGone = false; break; } } if (allGone) { // Oculta el cañón al terminar la ronda if (cannon) { cannon.hide(); } roundState = 'waitingFruits'; roundDelayTicks = 0; roundSpawningDone = false; } } if (roundState === 'waitingFruits') { // Espera 2s antes de reiniciar la ronda roundDelayTicks++; if (roundDelayTicks >= roundDelayBetweenRounds) { // Limpiar arrays de frutas activas y en cola antes de reiniciar la ronda 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 = []; roundFruitsQueue = []; roundFruitsActive = []; roundState = 'waiting'; } } // Mover frutas que suben desde abajo hasta el centro for (var i = fruits.length - 1; i >= 0; i--) { var fruit = fruits[i]; if (fruit.state === 'rising') { fruit.y -= fruitSpeed; fruit.ticks++; // Escalado según altura (más arriba, más grande) var minScale = 1.0; var maxScale = 1.25; 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), NO 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; // Ya no se programa aparición en la parte superior, simplemente se oculta la fruta. } // Si la fruta está oculta y esperando, no hacer nada más if (fruit.roundMeta.hasCrossed && fruit.roundMeta.showScheduled) { // Si la fruta fue destruida antes de los 7s, cancelar timeout y limpiar if (fruit.roundMeta.destroyed) { if (fruit.roundMeta.showTimeout) { LK.clearTimeout(fruit.roundMeta.showTimeout); fruit.roundMeta.showTimeout = null; } // Eliminar de roundFruitsQueue si está presente 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; } // Si la fruta sale de pantalla antes de cruzar, eliminar y marcar como destruida if (fruit.y < -fruit.radius) { // BAJA MUCHO MÁS el umbral de desaparición inferior fruit.roundMeta.destroyed = true; if (fruit.roundMeta.showTimeout) { LK.clearTimeout(fruit.roundMeta.showTimeout); fruit.roundMeta.showTimeout = null; } // Eliminar de roundFruitsQueue si está presente if (typeof roundFruitsQueue !== "undefined") { for (var j = roundFruitsQueue.length - 1; j >= 0; j--) { if (roundFruitsQueue[j] === fruit) { roundFruitsQueue.splice(j, 1); break; } } } // Aumentar frutasFalladas si la fruta se perdió antes de aparecer frutasFalladas++; frutasGeneradas++; fruit.destroy(); fruits.splice(i, 1); } } } // 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); } for (var i = fallingFruits.length - 1; i >= 0; i--) { var fruit = fallingFruits[i]; 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') { fruit.y -= fruitSpeed; } // --- 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 if (fruit.cutZoneCircle) { fruit.cutZoneCircle.destroy(); fruit.cutZoneCircle = null; if (fruit.isActive && !fruit.isCut) { frutasFalladas++; frutasGeneradas++; } } fruit.state = 'flyingup'; } } 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 7 segundos (420 ticks) if (fruit.waitTicks < 420) { // 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 fruit.y -= fruitSpeed; // Escalado sigue creciendo un poco fruit.scaleX = fruit.scaleY = Math.min(maxScale, fruit.scaleX + 0.01); // 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++; } } } } // 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) { if (!frutasFalladasTimeout) { frutasFalladasTimeout = LK.setTimeout(function () { 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 = []; 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 = []; roundState = 'waiting'; roundBulletsFired = 0; roundNextBulletTick = LK.ticks; roundDelayTicks = 0; frutasFalladas = 0; frutasGeneradas = 0; updateScore(0); frutasFalladasTimeout = null; showCountdownInMiddleDone = false; }, 2000); } return; } }; updateScore(0);
===================================================================
--- original.js
+++ change.js
@@ -484,9 +484,10 @@
}
// Solo permitir el spawn de frutas una vez, no en bucle
if (!roundSpawningDone) {
var margin = 180;
- for (var i = 0; i < roundBullets; i++) {
+ // Dispara los objetos de cuenta regresiva "1", "2", "Go" en los primeros tres disparos
+ for (var i = 0; i < 3; i++) {
var fruitX = margin + Math.random() * (2048 - 2 * margin);
cannon.x = fruitX;
cannon.show();
cannon.shoot();
@@ -594,34 +595,41 @@
centerObjGo.destroy();
}
});
countdownObjectsFired++;
- } else {
- // Después de los tres primeros, dispara frutas normales
- var fruit = new Fruit();
- fruit.x = fruitX;
- fruit.y = 2732 + fruit.radius - 120;
- 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);
}
}
+ // Ahora, solo después de los 1,2,Go! iniciales, dispara las frutas normales una sola vez
+ for (var i = 3; i < roundBullets; i++) {
+ var fruitX = margin + Math.random() * (2048 - 2 * margin);
+ var fruit = new Fruit();
+ fruit.x = fruitX;
+ fruit.y = 2732 + fruit.radius - 120;
+ 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);
+ }
+ }
roundSpawningDone = true;
}
// Cuando todas las balas han sido disparadas y ya no quedan frutas activas, pasar a siguiente estado
// (pero solo cuando todas las frutas hayan sido destruidas o salidas de pantalla)
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 cañ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, juguetón y fantástico, con líneas suaves y una atmósfera feliz y amigable, perfecto para una introducció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