User prompt
Si no corto ninguna fruta en la primera ronda se elimina inmediatamente la primer fruta de la segunda ronda, puedes averiguar porque y corregirlo?
Code edit (8 edits merged)
Please save this source code
User prompt
Limpia el codigo.
User prompt
Si cualquier fruta supera la altura fuera de la pantalla hacia arriba en Y+ eliminar inmediatamente.
User prompt
Si no corto algunas frutas, afecta a las que salen despues, desaparecen o no son disparadas, puedes arreglarlo?
Code edit (1 edits merged)
Please save this source code
User prompt
No esta siguiendo el orden, la tercera y cuarta fruta de disapara casi al mismo tiempo.
User prompt
Necesito que se dispare la primera fruta, despues un delay de .5 segundos se dispare la segunda fruta, un delay de 1 segundo y se dispare la tercera, por ultimo un delay de .5 y se dispare la cuarta.
Code edit (3 edits merged)
Please save this source code
User prompt
Agrega una tercera etapa, se dispararan 4 frutas, esta inicia 5 segundos después de haber iniciado la segunda.
User prompt
Modificaste la segunda etapa y no debias hacerlo, solo agregar la nueva etapa al ultimo.
User prompt
Agrega una tercera etapa, esta sera 13 segundos despues de iniciar la primera etapa, se dispararan 5 frutas, la primera al iniciar la etapa/ronda3, .2 segundos despues la siguiente, .8 segundos despues la siguiente y .2 segundos despues la siguiente, la ultima .1 segundos despues.
Code edit (1 edits merged)
Please save this source code
User prompt
Necesito que solo en la segunda etapa la velocidad de las frutas en la parte superior sea más alta
Code edit (1 edits merged)
Please save this source code
User prompt
No, no debias ahumentar la velocidad de las frutas. Lo que necesito es que el tiempo desde que desaparece la fruta en la parte inferior a que aparesca nuevamente en la parte superior sea menos.
User prompt
En la segunda etapa necesito que el tiempo de trnsición de las frutas de la parte de abajo a la parte de arriba sea diferente al tiempo de la etapa 1. Que sea menor.
Code edit (1 edits merged)
Please save this source code
User prompt
La segunda etapa de Frutas debe inicar 8 segundos despues de que inicia la primera, son tres frutas con .5 segundos de delay entre cada una. Quita la revisión de waitingFruits, porque ya no depende de si hya o no frutas de la etapa anterior.
User prompt
Aplicalo en el codigo.
Code edit (1 edits merged)
Please save this source code
User prompt
No esta ejecutando la segunda etapa en ningún momento.
User prompt
Si, porque estan saliendo las frutas o siendo cortadas y la segunda etapa nunca inicia, ignora los contadores 1 2 y go!, despues de haber trigueado la primera etapa espera 8 segundos y ejecuta la segunda, que no dependa si desaparecieron las frutas o no.
User prompt
Me refiero a que no esta iniciando la segunda etapa y debria iniciar despues de que termine la primera.
User prompt
Nunca inicia la segunda etapa.
/**** 
* 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 fruitSpeed = 25;
var fruitSpeedStage1 = 25;
var fruitSpeedStage2 = 40; // Faster speed for stage 2
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 = 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;
				}, 10300); // 8 seconds
			}
		} else if (currentStage === 2) {
			roundBullets = 3; // 3 fruits only, no countdown
			countdownObjectsFired = 3; // Skip countdown in stage 2
		}
		// 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') {
		// 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);
				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 = 5; // 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 = 5; // 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 = 5; // 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;
				}
			} 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 - 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);
			}
			roundBulletsFired++;
			// After Go!, wait 1.3 seconds before next bullet
			if (countdownObjectsFired === 3 && roundBulletsFired === 3) {
				roundNextBulletTick = LK.ticks + 78; // 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)
				}
			}
		}
		// 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];
		if (fruit.state === 'rising') {
			// Use stage-specific speed
			var currentSpeed = currentStage === 2 ? fruitSpeedStage2 : fruitSpeedStage1;
			fruit.y -= currentSpeed;
			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), 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;
				// El tiempo de espera es diferente según la etapa
				var appearDelayMs = currentStage === 2 ? 1500 : 2700; // 1.5s para etapa 2, 2.7s para etapa 1
				// Solo programar aparición en la parte superior si NO es uno de los tres primeros objetos de cuenta regresiva
				// Detecta si es un objeto de cuenta regresiva por su clase
				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 () {
							// Si la fruta ya fue destruida antes del tiempo, no hacer nada
							if (fruitRef.roundMeta.destroyed) {
								return;
							}
							// Eliminar de fruits[] y crear en pantalla superior
							var fruitType = fruitRef.fruitType;
							var x = fruitRef.x;
							// Eliminar fruta oculta
							fruitRef.destroy();
							for (var j = 0; j < fruitsArr.length; j++) {
								if (fruitsArr[j] === fruitRef) {
									fruitsArr.splice(j, 1);
									break;
								}
							}
							// Crear fruta en pantalla superior
							var fallingFruit = new Fruit();
							// Asegura que fruitType esté definido correctamente antes de usarlo
							if (typeof fruitType === "undefined" || !fruitType) {
								// Si no está definido, usa el tipo por defecto del objeto
								fruitType = fallingFruit.fruitType;
							} else {
								fallingFruit.fruitType = fruitType;
							}
							// Si ya existe un asset, destrúyelo antes de crear el nuevo
							if (fallingFruit.fruitAsset) {
								fallingFruit.fruitAsset.destroy();
							}
							fallingFruit.fruitAsset = fallingFruit.attachAsset(fallingFruit.fruitType, {
								anchorX: 0.5,
								anchorY: 0.5
							});
							fallingFruit.x = x;
							// Baja la fruta 400px respecto a la posición original (menos que antes)
							fallingFruit.y = 2732 / 2 + 420 + 100;
							fallingFruit.startY = fallingFruit.y;
							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);
							// Asegura que la línea negra esté sobre las frutas 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);
							}
						};
					}(fruit, fruits, i), appearDelayMs);
				}
			}
			// 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;
			}
		}
	}
	// 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') {
			// Use stage-specific speed
			var currentSpeed = currentStage === 2 ? fruitSpeedStage2 : fruitSpeedStage1;
			fruit.y -= currentSpeed;
		}
		// --- 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 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
				var currentSpeed = currentStage === 2 ? fruitSpeedStage2 : fruitSpeedStage1;
				fruit.y -= currentSpeed;
				// 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) {
		// 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);
			}
		}
		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 = [];
				// Do not reset round state - game ends here
				frutasFalladas = 0;
				frutasGeneradas = 0;
				updateScore(0);
				frutasFalladasTimeout = null;
				showCountdownInMiddleDone = false;
			}, 2000);
		}
		return;
	}
};
updateScore(0); ===================================================================
--- original.js
+++ change.js
@@ -714,10 +714,10 @@
 			if (!fruit.roundMeta.hasCrossed && fruit.y <= fruit.targetY) {
 				fruit.roundMeta.hasCrossed = true;
 				fruit.roundMeta.crossedTick = LK.ticks;
 				fruit.visible = false;
-				// El tiempo de espera es 2.5 segundos fijo
-				var appearDelayMs = 2700; // 2.5s de espera
+				// El tiempo de espera es diferente según la etapa
+				var appearDelayMs = currentStage === 2 ? 1500 : 2700; // 1.5s para etapa 2, 2.7s para etapa 1
 				// Solo programar aparición en la parte superior si NO es uno de los tres primeros objetos de cuenta regresiva
 				// Detecta si es un objeto de cuenta regresiva por su clase
 				var isCountdownObject = fruit instanceof CountdownOne || fruit instanceof CountdownTwo || fruit instanceof CountdownGo;
 				if (!isCountdownObject) {
:quality(85)/https://cdn.frvr.ai/6847923147dd86adb904036e.png%3F3) 
 Kiwi Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486857cb246617ce46e53a.png%3F3) 
 Limon Circular Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/684868a9cb246617ce46e543.png%3F3) 
 Naranja Circular Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/684868e1cb246617ce46e54f.png%3F3) 
 Manzana Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486929cb246617ce46e55b.png%3F3) 
 Ciruela Fruta con ojos lindos. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486b55cb246617ce46e584.png%3F3) 
 Manzana Fruta cortada a la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486cedcb246617ce46e592.png%3F3) 
 Kiwi Fruta cortado por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486d24cb246617ce46e59c.png%3F3) 
 Limon Circular Cortado por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486d5ccb246617ce46e5a9.png%3F3) 
 Naranja Circular Cortada por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/68486dd7cb246617ce46e5b4.png%3F3) 
 Ciruela Fruta cortada por la mitad. In-Game asset. 2d. High contrast. No shadows. Cartoon.
:quality(85)/https://cdn.frvr.ai/6848753dcb246617ce46e64d.png%3F3) 
 Agrega una rueda en la parte trasera del cañon.
:quality(85)/https://cdn.frvr.ai/68488dfc7a3d18c1111026d3.png%3F3) 
 En lugar del numero 2 un numero 1
:quality(85)/https://cdn.frvr.ai/68488f6f7a3d18c11110270e.png%3F3) 
 Letars GO! dentro del circulo.
:quality(85)/https://cdn.frvr.ai/6848a9cd7a3d18c111102788.png%3F3) 
 Red cicle thiner but maintan the image size
:quality(85)/https://cdn.frvr.ai/684ae5d2299d5df1765e403a.png%3F3) 
 En lugar del numero 1 un numero 2
:quality(85)/https://cdn.frvr.ai/684ae647299d5df1765e4044.png%3F3) 
 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.
:quality(85)/https://cdn.frvr.ai/684ae708299d5df1765e4064.png%3F3) 
 En lugar del numero 3 un numero 4
:quality(85)/https://cdn.frvr.ai/684ae73e299d5df1765e406e.png%3F3) 
 En lugar del numero 4 un numero 5
:quality(85)/https://cdn.frvr.ai/684ae76a299d5df1765e4078.png%3F3) 
 En lugar del numero 5 un numero 6
:quality(85)/https://cdn.frvr.ai/684ae796299d5df1765e4085.png%3F3) 
 En lugar del numero 6 un numero 7
:quality(85)/https://cdn.frvr.ai/684ae918299d5df1765e40bb.png%3F3) 
 En lugar del numero 1 un numero 8
:quality(85)/https://cdn.frvr.ai/684ae95f299d5df1765e40c3.png%3F3) 
 En lugar del numero 1 un numero 9
:quality(85)/https://cdn.frvr.ai/684ae99d299d5df1765e40cf.png%3F3) 
 En lugar del numero 9 un numero 10
:quality(85)/https://cdn.frvr.ai/684aed95299d5df1765e40e9.png%3F3) 
 En lugar del numero 1 un numero 11
:quality(85)/https://cdn.frvr.ai/684aedcd299d5df1765e40ec.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/684b0215299d5df1765e41c5.png%3F3) 
 Boton de juego que diga "START". In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684b0281299d5df1765e41d3.png%3F3) 
 Boton de juego que diga "RESTART". In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684b0341299d5df1765e41f3.png%3F3) 
 Boton de juego Azul que diga "MENU". In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684b0c0c299d5df1765e4279.png%3F3) 
 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
:quality(85)/https://cdn.frvr.ai/684b58d5fd7bcb3658f97698.png%3F3) 
 "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
:quality(85)/https://cdn.frvr.ai/684c3fb2f87acceebab3392e.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/684c407df87acceebab33935.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/684c43d23b8676df2ec65752.png%3F3) 
 Barra verde horizontal estilo caricatura.. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/684c647082414a33973865f9.png%3F3)