User prompt
En las frutas de adorno del menu principal, puedes agregar una sombre que este un poco desfasada.
Code edit (12 edits merged)
Please save this source code
User prompt
Me ayudas realizando estas modificaciones en el codigo.
User prompt
Añade un fondo a esta pantalla de inicio, que sea un asset para que lo pueda modificar, que cubra toda la pantalla del juego y que este atras de todos los elementos.
Code edit (1 edits merged)
Please save this source code
User prompt
Al principio se ve bien, pero las que empiezas a generar no traen el desfase. en las filas horizontales impares.
User prompt
Mismo error, cuando inciia el segundo bucle, cuando empiezan a generar las que estan fuera de cmaara, la primera, tercera y quinta linea, todas las filas impares horizontalmente parece que no tienen ese desfase.
User prompt
Al principio del juego se ve excelente pero las que se van generando ya no siguen este patron, luego lo vuelven a seguir y luego no. hay algo masl con la generación del segundo bucle
User prompt
Excelente, pero hay veces en las que una linea vertical se pone sobre otra y hay dos frutas encimadas, tambien necesito que la primera fila horrizontal este 180° más adelante, la segunda sin desfase, la tercera con despafe de 180°, la cuarta no y asi progresivamente.
User prompt
Que sean de tamaño normal y faltan filas en la parte de abajo, que cubran todo el juego pero que el boton de START siempre este sobre ellas.
User prompt
En el menu inicial del juego, agrega frutas que se muevan del lado izquierdo de la pantalla al lado derecho y estén rotando con las manecillas del reloj, que sean simetricas con la altura y espaciadas simetricamente entre ellas, de un tamaño 10% su tamaño normal en todas las filas que quepan.
User prompt
Mueve más abajo el boton de MENU.
User prompt
El efecto sigue siendo solo cuando se hace click, el efecto deberia ser cuando se pone el mouse sobre el boton aunque no se haga click.
User prompt
Solo hacen el efecto de ser más opacos hasta que es presionado, me gustaria el fecto fuera inmediato cuando el mouse esta sobre ellos, se haga click o no.
User prompt
Cuando paso el mouse por encima de los botones de Jugar Reiniciar y Menu, haz que se hagan má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 menú 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 tamaño y ahumentar su tamañ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
/****
* 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;
// Make sure overlay is visible when scene is activated
if (self.overlay) {
self.overlay.visible = true;
}
};
self.deactivate = function () {
self.isActive = false;
self.visible = false;
// Make sure to hide overlay to prevent black background
if (self.overlay) {
self.overlay.visible = false;
}
};
return self;
});
// Menu Scene
var MenuScene = Scene.expand(function () {
var self = Scene.call(this);
// Full screen background (added first so it's behind everything)
var menuBg = self.attachAsset('menu_background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Create decorative fruits container to ensure proper layering
var fruitsContainer = new Container();
self.addChild(fruitsContainer);
// Play button (will be added after fruits container)
var playButton = self.attachAsset('button_play', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Button interaction
playButton.interactive = true;
playButton.down = function () {
playButton.tint = 0xcccccc;
};
playButton.up = function () {
playButton.tint = 0xffffff;
if (game.onPlayPressed) {
game.onPlayPressed();
}
};
// Decorative fruits
var decorativeFruits = [];
var fruitTypes = ['fruit_apple', 'fruit_lemon', 'fruit_orange', 'fruit_kiwi', 'fruit_plum'];
var fruitScale = 1; // Normal size
var fruitSpacing = 250; // Horizontal spacing between fruits
var verticalSpacing = 200; // Vertical spacing between rows
var baseY = 150; // Starting Y position for first row
var fruitSpeed = 2; // Horizontal movement speed
// Calculate how many rows we can fit
var availableHeight = 2732 - 100;
var numRows = Math.floor(availableHeight / verticalSpacing);
// Create fruits for each row
for (var row = 0; row < numRows; row++) {
var y = baseY + row * verticalSpacing;
var numFruits = Math.ceil((2048 + fruitSpacing * 2) / fruitSpacing);
var rowOffset = row % 2 === 1 ? fruitSpacing / 2 : 0;
var initialRotation = row % 2 === 1 ? Math.PI : 0; // 180° for odd rows
for (var col = 0; col < numFruits; col++) {
var fruitType = fruitTypes[(row + col) % fruitTypes.length];
var x = col * fruitSpacing - fruitSpacing + rowOffset;
// Create shadow first (so it appears behind the fruit)
var shadow = self.attachAsset(fruitType, {
anchorX: 0.5,
anchorY: 0.5,
x: x + 15,
// Offset shadow 15 pixels to the right
y: y + 15,
// Offset shadow 15 pixels down
scaleX: fruitScale,
scaleY: fruitScale,
rotation: initialRotation,
tint: 0x000000,
// Make shadow black
alpha: 0.3 // Make shadow semi-transparent
});
shadow.startX = x + 15;
shadow.rotationSpeed = 0.02;
shadow.isShadow = true; // Mark as shadow for update logic
decorativeFruits.push(shadow);
fruitsContainer.addChild(shadow);
// Create actual fruit on top
var fruit = self.attachAsset(fruitType, {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y,
scaleX: fruitScale,
scaleY: fruitScale,
rotation: initialRotation
});
fruit.startX = x;
fruit.rotationSpeed = 0.02;
fruit.isShadow = false; // Mark as not shadow
decorativeFruits.push(fruit);
fruitsContainer.addChild(fruit);
}
}
// Update function for menu scene
self.updateMenu = function () {
for (var i = 0; i < decorativeFruits.length; i++) {
var fruit = decorativeFruits[i];
fruit.x += fruitSpeed;
fruit.rotation += fruit.rotationSpeed;
if (fruit.x > 2048 + fruitSpacing) {
if (fruit.isShadow) {
fruit.x = -400 + 15; // Keep shadow offset
} else {
fruit.x = -400;
}
}
}
};
// Add hover effect
self.move = function (x, y, obj) {
// Convert coordinates to button's local space
var globalPos = self.toGlobal({
x: x,
y: y
});
var localPos = playButton.toLocal(globalPos);
var halfWidth = playButton.width / 2;
var halfHeight = playButton.height / 2;
if (localPos.x >= -halfWidth && localPos.x <= halfWidth && localPos.y >= -halfHeight && localPos.y <= halfHeight) {
playButton.alpha = 0.8; // Make more opaque (less transparent) when hovering
} else {
playButton.alpha = 1; // Normal opacity (fully visible)
}
};
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);
// Set game start delay if coming from menu or restart
self.gameStartDelay = LK.ticks; // 0.2 seconds delay (12 ticks at 60fps)
};
// 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) {
// Check if game start delay has passed
if (self.gameStartDelay && LK.ticks < self.gameStartDelay) {
return;
}
tryCutFruit(x, y);
}
};
self.updateGame = function () {
if (!self.isActive) {
return;
}
// Wait for game start delay before processing any game logic
if (self.gameStartDelay && LK.ticks < self.gameStartDelay) {
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 () {
// Set Inicio to true when game ends for the first time
if (!Inicio) {
Inicio = true;
}
// 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 with proper scene management
self.deactivate();
if (game.endScene) {
game.endScene.activate();
game.currentScene = game.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
self.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('button_restart', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1200
});
// Menu button
var menuButton = self.attachAsset('button_menu', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1600
});
// Button interactions
restartButton.interactive = true;
menuButton.interactive = true;
restartButton.down = function () {
restartButton.tint = 0xcccccc;
};
restartButton.up = function () {
restartButton.tint = 0xffffff;
if (game.onRestartPressed) {
game.onRestartPressed();
}
};
menuButton.down = function () {
menuButton.tint = 0xcccccc;
};
menuButton.up = function () {
menuButton.tint = 0xffffff;
if (game.onMenuPressed) {
game.onMenuPressed();
}
};
// Add hover effect
self.move = function (x, y, obj) {
// Convert coordinates to button's local space
var globalPos = self.toGlobal({
x: x,
y: y
});
// Check if mouse is over restart button
var localPosRestart = restartButton.toLocal(globalPos);
var halfWidthRestart = restartButton.width / 2;
var halfHeightRestart = restartButton.height / 2;
if (localPosRestart.x >= -halfWidthRestart && localPosRestart.x <= halfWidthRestart && localPosRestart.y >= -halfHeightRestart && localPosRestart.y <= halfHeightRestart) {
restartButton.alpha = 0.8; // Make more opaque (less transparent) when hovering
} else {
restartButton.alpha = 1; // Normal opacity (fully visible)
}
// Check if mouse is over menu button
var localPosMenu = menuButton.toLocal(globalPos);
var halfWidthMenu = menuButton.width / 2;
var halfHeightMenu = menuButton.height / 2;
if (localPosMenu.x >= -halfWidthMenu && localPosMenu.x <= halfWidthMenu && localPosMenu.y >= -halfHeightMenu && localPosMenu.y <= halfHeightMenu) {
menuButton.alpha = 0.8; // Make more opaque (less transparent) when hovering
} else {
menuButton.alpha = 1; // Normal opacity (fully visible)
}
};
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;
var Inicio = false; // Track if game has ended for the first time
// Create scenes
menuScene = new MenuScene();
gameScene = new GameScene();
endScene = new EndScene();
// Add scenes to game
game.addChild(menuScene);
game.addChild(gameScene);
game.addChild(endScene);
// Store references in game object for access from GameScene
game.menuScene = menuScene;
game.gameScene = gameScene;
game.endScene = endScene;
game.currentScene = currentScene;
// Initially show menu
menuScene.activate();
gameScene.deactivate();
endScene.deactivate();
currentScene = menuScene;
// Scene transition handlers
game.onPlayPressed = function () {
menuScene.deactivate();
endScene.deactivate();
// Initialize game before activating scene
if (!gameScene.gameInitialized) {
gameScene.initGame();
gameScene.gameInitialized = true;
}
gameScene.activate();
currentScene = gameScene;
// Start music after scene is fully initialized
if (Inicio) {
// Delay music by 0.2 seconds if game has been played before
LK.setTimeout(function () {
LK.playMusic('bgmusic', {
loop: false
});
}, 200);
} else {
LK.playMusic('bgmusic', {
loop: false
});
}
};
game.onRestartPressed = function () {
endScene.deactivate();
// Reset game scene
gameScene.deactivate();
game.removeChild(gameScene);
gameScene = new GameScene();
game.addChild(gameScene);
// Initialize before activating
gameScene.initGame();
gameScene.gameInitialized = true;
gameScene.activate();
currentScene = gameScene;
// Restart music after initialization
LK.stopMusic();
if (Inicio) {
// Delay music by 0.2 seconds if game has been played before
LK.setTimeout(function () {
LK.playMusic('bgmusic', {
loop: false
});
}, 200);
} else {
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;
};
// Global move handler to propagate to active scene
game.move = function (x, y, obj) {
if (currentScene && currentScene.move) {
currentScene.move(x, y, obj);
}
};
// Main game update loop
game.update = function () {
if (currentScene && currentScene.updateGame) {
currentScene.updateGame();
}
if (currentScene && currentScene.updateMenu) {
currentScene.updateMenu();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -358,8 +358,29 @@
var initialRotation = row % 2 === 1 ? Math.PI : 0; // 180° for odd rows
for (var col = 0; col < numFruits; col++) {
var fruitType = fruitTypes[(row + col) % fruitTypes.length];
var x = col * fruitSpacing - fruitSpacing + rowOffset;
+ // Create shadow first (so it appears behind the fruit)
+ var shadow = self.attachAsset(fruitType, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: x + 15,
+ // Offset shadow 15 pixels to the right
+ y: y + 15,
+ // Offset shadow 15 pixels down
+ scaleX: fruitScale,
+ scaleY: fruitScale,
+ rotation: initialRotation,
+ tint: 0x000000,
+ // Make shadow black
+ alpha: 0.3 // Make shadow semi-transparent
+ });
+ shadow.startX = x + 15;
+ shadow.rotationSpeed = 0.02;
+ shadow.isShadow = true; // Mark as shadow for update logic
+ decorativeFruits.push(shadow);
+ fruitsContainer.addChild(shadow);
+ // Create actual fruit on top
var fruit = self.attachAsset(fruitType, {
anchorX: 0.5,
anchorY: 0.5,
x: x,
@@ -369,8 +390,9 @@
rotation: initialRotation
});
fruit.startX = x;
fruit.rotationSpeed = 0.02;
+ fruit.isShadow = false; // Mark as not shadow
decorativeFruits.push(fruit);
fruitsContainer.addChild(fruit);
}
}
@@ -380,9 +402,13 @@
var fruit = decorativeFruits[i];
fruit.x += fruitSpeed;
fruit.rotation += fruit.rotationSpeed;
if (fruit.x > 2048 + fruitSpacing) {
- fruit.x = -400;
+ if (fruit.isShadow) {
+ fruit.x = -400 + 15; // Keep shadow offset
+ } else {
+ fruit.x = -400;
+ }
}
}
};
// Add hover effect
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