User prompt
Add 2 new fruits a avocado and cranberry
User prompt
Add 2 new random fruits
User prompt
Make the fruits past watermelon slot in between the fruits better based on their size (ex. Lemon could be in between apple and orange
User prompt
Make the fruits the past watermelon fit in more and make them there real size irl
User prompt
Make the fruits not kill you until they touch a fruit or the ground
User prompt
Make it so fruit rain fruits can’t kill you until they touch a fruit or the ground
User prompt
Make only 1 fruit rain happen at a time
User prompt
Make 2 spawn
User prompt
Make the second biggest fruit the thing that spawns automatically
User prompt
Make a fruit with all mutations spawn automatically
User prompt
Make celestial super rare and give x15
User prompt
Make the ring a bit bigger than the size of the fruit it’s on
User prompt
Make the ring the same size as the fruit it’s on
User prompt
Make the ring the same size as the fruit it’s on but x1.5
User prompt
Make the ring grow based off how big the fruit it’s on is ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Give the ring its own asset
User prompt
Make a mutation called celestial that makes the fruit purple with a purple ring around it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the shines bigger
User prompt
Make the shine always move and spin like flys might ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the shines still move around and spin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the shines in the gold mutation appear randomly and then disappear super quickly ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a gold mutation that makes fruit gold and have shines that are there own asset ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make rainbow mutations save too ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Move the restart tutorial button to the save menu instead of the evolution
User prompt
Add things in the tutorial to show the save and music menus
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.velocityX = 0;
self.velocityY = 0;
self.angularVelocity = 0;
self.gravity = 1.2;
self.bounceX = 0.2;
self.bounceY = 0.1;
self.friction = 0.995;
self.rotationFriction = 0.85;
self.merged = false;
self.lastMergeCheck = false;
// Track if this fruit was created from fruit rain
self.isRainFruit = false;
// Track if this fruit has made contact with ground or another fruit
self.contactMade = false;
// Rainbow mutation - 5% chance for any fruit to be rainbow
self.isRainbow = Math.random() < 0.05;
// Gold mutation - 3% chance for any fruit to be gold
self.isGold = Math.random() < 0.03;
// Celestial mutation - 0.1% chance for any fruit to be celestial (super rare)
self.isCelestial = Math.random() < 0.001;
var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
var fruitScores = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231];
self.assetName = fruitAssets[type];
self.size = fruitSizes[type];
self.scoreValue = fruitScores[type];
var fruitGraphics = self.attachAsset(self.assetName, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply rainbow effect if this fruit is rainbow
if (self.isRainbow) {
self.rainbowTintIndex = 0;
self.rainbowColors = [0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0x0080ff, 0x8000ff];
fruitGraphics.tint = self.rainbowColors[0];
}
// Apply gold effect if this fruit is gold
if (self.isGold) {
fruitGraphics.tint = 0xffd700; // Gold color
self.shines = [];
// Create 3 shine effects around the fruit
for (var s = 0; s < 3; s++) {
var shine = self.attachAsset('shine', {
anchorX: 0.5,
anchorY: 0.5
});
shine.alpha = 0;
self.shines.push(shine);
}
}
// Apply celestial effect if this fruit is celestial
if (self.isCelestial) {
fruitGraphics.tint = 0x8a2be2; // Purple color
// Create purple ring around the fruit using celestial ring asset
self.celestialRing = self.attachAsset('celestialRing', {
anchorX: 0.5,
anchorY: 0.5
});
self.celestialRing.width = self.size + 80;
self.celestialRing.height = self.size + 80;
self.celestialRing.alpha = 0.6;
self.addChildAt(self.celestialRing, 0); // Add behind the fruit
}
self.getRadius = function () {
return self.size / 2;
};
self.update = function () {
if (typeof fruitsFrozen !== "undefined" && fruitsFrozen) {
return;
}
if (self.merged) {
return;
}
// Apply gravity
self.velocityY += self.gravity;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Calculate current speed
var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
var speedThreshold = 3.0; // Only rotate when moving fast enough
// Always apply rotation
self.rotation += self.angularVelocity;
// Apply friction
self.velocityX *= self.friction;
self.velocityY *= self.friction;
self.angularVelocity *= self.rotationFriction;
// Additional stability check - if fruit is moving very slowly, gradually bring it to rest
var totalSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (totalSpeed < 1.0 && totalSpeed > 0) {
var stabilityDamping = 0.8;
self.velocityX *= stabilityDamping;
self.velocityY *= stabilityDamping;
}
// Check if fruit is in cramped conditions
var nearbyFruits = 0;
if (typeof fruits !== "undefined") {
for (var k = 0; k < fruits.length; k++) {
if (fruits[k] !== self) {
var dist = Math.sqrt((self.x - fruits[k].x) * (self.x - fruits[k].x) + (self.y - fruits[k].y) * (self.y - fruits[k].y));
if (dist < self.getRadius() + fruits[k].getRadius() + 30) {
nearbyFruits++;
}
}
}
}
// Apply stronger rotational damping in cramped conditions
if (nearbyFruits >= 3) {
self.angularVelocity *= 0.6; // Much stronger damping when cramped
}
// Cap maximum rotation speed - lower limit for cramped conditions
var maxAngularVelocity = nearbyFruits >= 3 ? 0.05 : 0.1; // Reduced max rotation
if (self.angularVelocity > maxAngularVelocity) {
self.angularVelocity = maxAngularVelocity;
} else if (self.angularVelocity < -maxAngularVelocity) {
self.angularVelocity = -maxAngularVelocity;
}
// Rainbow color cycling for rainbow fruits
if (self.isRainbow && self.rainbowColors && LK.ticks % 30 === 0) {
self.rainbowTintIndex = (self.rainbowTintIndex + 1) % self.rainbowColors.length;
var fruitGraphics = self.children[0];
if (fruitGraphics) {
tween(fruitGraphics, {
tint: self.rainbowColors[self.rainbowTintIndex]
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
// Gold shine animation for gold fruits - always moving and spinning like flies
if (self.isGold && self.shines) {
for (var s = 0; s < self.shines.length; s++) {
var shine = self.shines[s];
// Initialize shine position if not set
if (shine.shineInitialized === undefined) {
shine.shineInitialized = true;
shine.alpha = 0.7;
shine.scaleX = 2.5;
shine.scaleY = 2.5;
var angle = s * 120 * Math.PI / 180;
var radius = self.getRadius() + 20;
shine.x = Math.cos(angle) * radius;
shine.y = Math.sin(angle) * radius;
shine.shineAngle = angle;
shine.shineSpeed = 0.02 + Math.random() * 0.02; // Random speed for each shine
shine.shineRadius = radius + Math.random() * 20;
shine.rotationSpeed = (Math.random() - 0.5) * 0.2; // Random rotation speed
}
// Update shine position in circular/erratic fly-like motion
shine.shineAngle += shine.shineSpeed;
var targetRadius = self.getRadius() + 15 + Math.sin(shine.shineAngle * 3) * 10; // Varying radius
var targetX = Math.cos(shine.shineAngle) * targetRadius + (Math.random() - 0.5) * 5;
var targetY = Math.sin(shine.shineAngle) * targetRadius + (Math.random() - 0.5) * 5;
// Smooth movement towards target position
shine.x += (targetX - shine.x) * 0.1;
shine.y += (targetY - shine.y) * 0.1;
// Continuous spinning
shine.rotation += shine.rotationSpeed;
// Slight alpha variation for flickering effect
shine.alpha = 0.5 + Math.sin(LK.ticks * 0.1 + s) * 0.3;
}
}
// Celestial ring animation for celestial fruits
if (self.isCelestial && self.celestialRing) {
// Slowly rotate the ring
self.celestialRing.rotation += 0.02;
// Pulsing alpha effect
self.celestialRing.alpha = 0.4 + Math.sin(LK.ticks * 0.05) * 0.2;
// Gentle size pulsing
var pulseScale = 1.0 + Math.sin(LK.ticks * 0.03) * 0.05;
self.celestialRing.scaleX = pulseScale;
self.celestialRing.scaleY = pulseScale;
}
// Prevent very small velocities that can cause sticking - increased threshold
if (Math.abs(self.velocityX) < 0.5) {
self.velocityX = 0;
}
if (Math.abs(self.velocityY) < 0.5) {
self.velocityY = 0;
}
// Higher threshold for stopping rotation in cramped conditions
var rotationStopThreshold = nearbyFruits >= 3 ? 0.02 : 0.005;
if (Math.abs(self.angularVelocity) < rotationStopThreshold) {
self.angularVelocity = 0;
// Bounce rotation back to neutral position when angular velocity stops
if (Math.abs(self.rotation) > 0.1) {
tween(self, {
rotation: 0
}, {
duration: nearbyFruits >= 3 ? 400 : 600,
// Faster correction when cramped
easing: tween.bounceOut
});
}
}
var radius = self.getRadius();
var containerLeft = containerX - containerWidth / 2;
var containerRight = containerX + containerWidth / 2;
var containerBottom = containerY + containerHeight / 2;
// Collision with container walls
if (self.x - radius < containerLeft) {
self.x = containerLeft + radius;
self.velocityX = -self.velocityX * self.bounceX;
self.contactMade = true; // Mark contact made when hitting wall
// Add rotational effect from wall collision only if movement is significant
if (Math.abs(self.velocityY) > 2.0) {
self.angularVelocity += self.velocityY * 0.01;
}
}
if (self.x + radius > containerRight) {
self.x = containerRight - radius;
self.velocityX = -self.velocityX * self.bounceX;
self.contactMade = true; // Mark contact made when hitting wall
// Add rotational effect from wall collision only if movement is significant
if (Math.abs(self.velocityY) > 2.0) {
self.angularVelocity -= self.velocityY * 0.01;
}
}
// Collision with container bottom
if (self.y + radius > containerBottom) {
self.y = containerBottom - radius;
self.velocityY = -self.velocityY * self.bounceY;
self.contactMade = true; // Mark contact made when hitting ground
// Add rotational effect from ground collision only if movement is significant
if (Math.abs(self.velocityX) > 2.0) {
self.angularVelocity += self.velocityX * 0.02;
}
if (Math.abs(self.velocityY) < 1) {
self.velocityY = 0;
}
// After ground collision, check speed threshold
var currentSpeed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
var speedThreshold = 3.0;
if (currentSpeed < speedThreshold) {
// Stop movement if below speed threshold after hitting ground
self.velocityX = 0;
self.velocityY = 0;
self.angularVelocity = 0;
// Bounce rotation back to neutral position
if (Math.abs(self.rotation) > 0.1) {
tween(self, {
rotation: 0
}, {
duration: 800,
easing: tween.elasticOut
});
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
// No backgroundColor, handled by asset
});
/****
* Game Code
****/
// Blue background asset (full screen)
// Attach blue background asset, ensure it's at the back
var blueBg = game.attachAsset('blueBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChildAt(blueBg, 0); // Add as the bottom-most child
// Music selection system (declare before any usage)
var musicTracks = ['music1', 'music2', 'music3', 'music4', 'music5'];
var musicNames = ['Classic Melody', 'Upbeat Bounce', 'Chill Vibes', 'Epic Adventure', 'Peaceful Garden'];
var currentMusicIndex = storage.selectedMusic || 0;
var musicStarted = true;
var musicMenuVisible = false;
// Game state
var gameState = 'playing';
var fruits = [];
var currentFruit = null;
var nextFruitType = 0;
var gameRunning = true;
var dropLine = 400;
var gameOverLine = 300;
var isDragging = false;
var previewFruit = null;
// Freeze fruits when evolution menu is open
var fruitsFrozen = false;
// Track which fruits have been discovered by the player
var discoveredFruits = storage.discoveredFruits || [];
// Initialize array if not in storage
if (discoveredFruits.length === 0) {
for (var i = 0; i < 21; i++) {
discoveredFruits[i] = false;
}
}
// Container dimensions and position
var containerWidth = 1900;
var containerHeight = 2200;
var containerX = 2048 / 2;
var containerY = 1366;
// Create container
var container = game.attachAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX,
y: containerY
});
// Score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0x000000
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Merge counter (load from storage or default to 0)
var totalMerges = storage.totalMerges || 0;
var mergeCounterTxt = new Text2('Merges: ' + totalMerges, {
size: 60,
fill: 0x000000
});
mergeCounterTxt.anchor.set(0.5, 0.5);
mergeCounterTxt.x = 2048 / 2;
mergeCounterTxt.y = 2732 / 2;
game.addChild(mergeCounterTxt);
// Load discovered fruits from storage, but ensure first 5 are always available
for (var i = 0; i < discoveredFruits.length; i++) {
if (i < 5) {
discoveredFruits[i] = true; // First 5 are always available to drop
} else if (storage.discoveredFruits && storage.discoveredFruits[i]) {
discoveredFruits[i] = true; // Keep unlocked fruits from storage
}
}
// Save to storage
storage.discoveredFruits = discoveredFruits;
// Next fruit preview
var nextFruitPreview = null;
var nextFruitLabel = new Text2('Next:', {
size: 60,
fill: 0x000000
});
nextFruitLabel.anchor.set(1, 0.5);
nextFruitLabel.x = 1580;
nextFruitLabel.y = 120;
game.addChild(nextFruitLabel);
// Drop line indicator
var dropLineIndicator = LK.getAsset('container', {
width: containerWidth,
height: 4,
anchorX: 0.5,
anchorY: 0.5
});
dropLineIndicator.x = containerX;
dropLineIndicator.y = dropLine;
dropLineIndicator.tint = 0x0000FF;
game.addChild(dropLineIndicator);
// Helper functions
function getRandomFruitType() {
return Math.floor(Math.random() * 5); // Only first 5 fruit types can be dropped
}
function createNextFruit() {
nextFruitType = getRandomFruitType();
if (nextFruitPreview) {
// Stop any existing tweens before destroying
tween.stop(nextFruitPreview);
nextFruitPreview.destroy();
}
var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple'];
var fruitSizes = [120, 160, 200, 240, 280];
nextFruitPreview = LK.getAsset(fruitAssets[nextFruitType], {
anchorX: 0.5,
anchorY: 0.5
});
nextFruitPreview.x = 1700;
nextFruitPreview.y = 120;
game.addChild(nextFruitPreview);
// Position the label based on fruit size to ensure it's always visible
var fruitRadius = fruitSizes[nextFruitType] / 2;
nextFruitLabel.x = nextFruitPreview.x - fruitRadius - 20; // 20px padding from fruit edge
// Add bobbing animation
var originalY = nextFruitPreview.y;
function bobUp() {
tween(nextFruitPreview, {
y: originalY - 15
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: bobDown
});
}
function bobDown() {
tween(nextFruitPreview, {
y: originalY + 15
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: bobUp
});
}
bobUp();
}
function dropFruit(x) {
if (!gameRunning || currentFruit) {
return;
}
currentFruit = new Fruit(nextFruitType);
currentFruit.x = Math.max(containerX - containerWidth / 2 + currentFruit.getRadius(), Math.min(x, containerX + containerWidth / 2 - currentFruit.getRadius()));
currentFruit.y = dropLine + currentFruit.getRadius() + 60; // Spawn lower below the line with more padding
// Mark this fruit as discovered
var newlyDiscovered = !discoveredFruits[nextFruitType];
discoveredFruits[nextFruitType] = true;
// Save to storage
storage.discoveredFruits = discoveredFruits;
if (newlyDiscovered) {
// Show notification for unlocking new fruit
var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var unlockedName = evoFruitNames[nextFruitType];
var notification = new Text2("You've unlocked " + unlockedName + "!", {
size: 90,
fill: 0x222222
});
notification.anchor.set(0.5, 0.5);
notification.x = 2048 / 2;
notification.y = 900;
notification.alpha = 0.0;
game.addChild(notification);
// Fade in, hold, then fade out
tween(notification, {
alpha: 1
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 1200);
}
});
}
// Add small random initial rotation
currentFruit.angularVelocity = (Math.random() - 0.5) * 0.05;
fruits.push(currentFruit);
game.addChild(currentFruit);
// Music and drop sound now start on tap/hold instead of drop
// Reset current fruit after a delay
LK.setTimeout(function () {
currentFruit = null;
}, 100);
createNextFruit();
}
function createPreviewFruit(x) {
if (previewFruit) {
previewFruit.destroy();
}
var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
previewFruit = LK.getAsset(fruitAssets[nextFruitType], {
anchorX: 0.5,
anchorY: 0.5
});
previewFruit.alpha = 0.7; // Make it semi-transparent
previewFruit.x = x;
previewFruit.y = dropLine;
game.addChild(previewFruit);
}
function updatePreviewFruit(x) {
if (!previewFruit) {
return;
}
var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
var radius = fruitSizes[nextFruitType] / 2;
previewFruit.x = Math.max(containerX - containerWidth / 2 + radius, Math.min(x, containerX + containerWidth / 2 - radius));
}
function destroyPreviewFruit() {
if (previewFruit) {
previewFruit.destroy();
previewFruit = null;
}
}
function checkCollision(fruit1, fruit2) {
var dx = fruit1.x - fruit2.x;
var dy = fruit1.y - fruit2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = fruit1.getRadius() + fruit2.getRadius();
return distance < minDistance;
}
function resolveFruitCollision(fruit1, fruit2) {
var dx = fruit1.x - fruit2.x;
var dy = fruit1.y - fruit2.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = fruit1.getRadius() + fruit2.getRadius();
if (distance < minDistance && distance > 0) {
var overlap = minDistance - distance;
// Reduced separation force to prevent oscillation
var separationForce = 0.6;
var separationX = dx / distance * overlap * separationForce;
var separationY = dy / distance * overlap * separationForce;
fruit1.x += separationX;
fruit1.y += separationY;
fruit2.x -= separationX;
fruit2.y -= separationY;
// Apply strong damping when fruits are very close to prevent vibration
var dampingFactor = Math.max(0.1, Math.min(1.0, distance / minDistance));
fruit1.velocityX *= dampingFactor;
fruit1.velocityY *= dampingFactor;
fruit2.velocityX *= dampingFactor;
fruit2.velocityY *= dampingFactor;
// Realistic elastic collision response
var relativeVelX = fruit1.velocityX - fruit2.velocityX;
var relativeVelY = fruit1.velocityY - fruit2.velocityY;
var normalVelX = dx / distance;
var normalVelY = dy / distance;
var separatingVel = relativeVelX * normalVelX + relativeVelY * normalVelY;
// Only resolve if objects are moving toward each other with sufficient velocity
if (separatingVel < -0.5) {
var restitution = 0.05; // Reduced bounciness factor
var impulse = -(1 + restitution) * separatingVel * 0.5; // Reduced impulse strength
var impulseX = impulse * normalVelX;
var impulseY = impulse * normalVelY;
fruit1.velocityX += impulseX;
fruit1.velocityY += impulseY;
fruit2.velocityX -= impulseX;
fruit2.velocityY -= impulseY;
// Add rotational effects from collision only if movement is significant and not in cramped conditions
var movementThreshold = 5.0; // Increased threshold to prevent micro-rotation
var totalImpulse = Math.abs(impulseX) + Math.abs(impulseY);
// Check if fruits are in cramped conditions by counting nearby fruits
var nearbyCount1 = 0;
var nearbyCount2 = 0;
for (var k = 0; k < fruits.length; k++) {
if (fruits[k] !== fruit1 && fruits[k] !== fruit2) {
var dist1 = Math.sqrt((fruit1.x - fruits[k].x) * (fruit1.x - fruits[k].x) + (fruit1.y - fruits[k].y) * (fruit1.y - fruits[k].y));
var dist2 = Math.sqrt((fruit2.x - fruits[k].x) * (fruit2.x - fruits[k].x) + (fruit2.y - fruits[k].y) * (fruit2.y - fruits[k].y));
if (dist1 < fruit1.getRadius() + fruits[k].getRadius() + 50) nearbyCount1++;
if (dist2 < fruit2.getRadius() + fruits[k].getRadius() + 50) nearbyCount2++;
}
}
// Only apply rotation if not cramped and movement is significant
if (totalImpulse > movementThreshold && nearbyCount1 < 3 && nearbyCount2 < 3) {
var rotationFactor = 0.008; // Reduced rotation factor
fruit1.angularVelocity += (impulseX + impulseY) * rotationFactor;
fruit2.angularVelocity -= (impulseX + impulseY) * rotationFactor;
}
}
}
}
function mergeFruits(fruit1, fruit2) {
if (fruit1.type !== fruit2.type || fruit1.merged || fruit2.merged) {
return false;
}
if (fruit1.type >= 20) {
return false;
} // Can't merge cranberry (highest fruit)
// Mark the new fruit type as discovered
var newlyDiscovered = !discoveredFruits[fruit1.type + 1];
discoveredFruits[fruit1.type + 1] = true;
// Save to storage
storage.discoveredFruits = discoveredFruits;
if (newlyDiscovered) {
// Show notification for unlocking new fruit
var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var unlockedName = evoFruitNames[fruit1.type + 1];
var notification = new Text2("You've unlocked " + unlockedName + "!", {
size: 90,
fill: 0x222222
});
notification.anchor.set(0.5, 0.5);
notification.x = 2048 / 2;
notification.y = 900;
notification.alpha = 0.0;
game.addChild(notification);
// Fade in, hold, then fade out
tween(notification, {
alpha: 1
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 1200);
}
});
}
// Create new fruit
var newFruit = new Fruit(fruit1.type + 1);
newFruit.x = (fruit1.x + fruit2.x) / 2;
newFruit.y = (fruit1.y + fruit2.y) / 2;
// Inherit contactMade status from parent fruits
newFruit.contactMade = fruit1.contactMade || fruit2.contactMade;
// Only give score if neither fruit is from rain
if (!fruit1.isRainFruit && !fruit2.isRainFruit) {
// Calculate score with rainbow and gold multipliers
var scoreToAdd = newFruit.scoreValue;
var multiplier = 1;
var notificationText = '';
var notificationColor = 0x00ff00;
if (fruit1.isRainbow || fruit2.isRainbow) {
multiplier *= 5;
notificationText = 'RAINBOW x5!';
notificationColor = 0xff00ff;
}
if (fruit1.isGold || fruit2.isGold) {
multiplier *= 3;
if (notificationText) {
notificationText = 'RAINBOW + GOLD x15!';
notificationColor = 0xffd700;
} else {
notificationText = 'GOLD x3!';
notificationColor = 0xffd700;
}
}
if (fruit1.isCelestial || fruit2.isCelestial) {
multiplier *= 15;
if (notificationText) {
if (notificationText.includes('RAINBOW') && notificationText.includes('GOLD')) {
notificationText = 'RAINBOW + GOLD + CELESTIAL x225!';
notificationColor = 0x8a2be2;
} else if (notificationText.includes('RAINBOW')) {
notificationText = 'RAINBOW + CELESTIAL x75!';
notificationColor = 0x8a2be2;
} else if (notificationText.includes('GOLD')) {
notificationText = 'GOLD + CELESTIAL x45!';
notificationColor = 0x8a2be2;
} else {
notificationText = 'CELESTIAL x15!';
notificationColor = 0x8a2be2;
}
} else {
notificationText = 'CELESTIAL x15!';
notificationColor = 0x8a2be2;
}
}
scoreToAdd *= multiplier;
// Show multiplier notification if applicable
if (notificationText) {
var multiplierScoreText = new Text2(notificationText, {
size: 80,
fill: notificationColor
});
multiplierScoreText.anchor.set(0.5, 0.5);
multiplierScoreText.x = newFruit.x;
multiplierScoreText.y = newFruit.y - 100;
multiplierScoreText.alpha = 0;
game.addChild(multiplierScoreText);
// Animate multiplier score text
tween(multiplierScoreText, {
alpha: 1,
y: multiplierScoreText.y - 50
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(multiplierScoreText, {
alpha: 0,
y: multiplierScoreText.y - 50
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
multiplierScoreText.destroy();
}
});
}
});
}
// Add score
LK.setScore(LK.getScore() + scoreToAdd);
scoreTxt.setText('Score: ' + LK.getScore());
}
// Update merge counter
totalMerges++;
mergeCounterTxt.setText('Merges: ' + totalMerges);
storage.totalMerges = totalMerges;
// Mark old fruits as merged
fruit1.merged = true;
fruit2.merged = true;
// Remove old fruits
for (var i = fruits.length - 1; i >= 0; i--) {
if (fruits[i] === fruit1 || fruits[i] === fruit2) {
fruits[i].destroy();
fruits.splice(i, 1);
}
}
// Add new fruit
fruits.push(newFruit);
game.addChild(newFruit);
LK.getSound('merge').play();
// Flash effect
tween(newFruit, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(newFruit, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
return true;
}
function performAutoMerge() {
var foundMerge = true;
// Keep merging until no more merges are possible
while (foundMerge) {
foundMerge = false;
// Check all fruit pairs for possible merges
for (var i = 0; i < fruits.length && !foundMerge; i++) {
for (var j = i + 1; j < fruits.length && !foundMerge; j++) {
var fruit1 = fruits[i];
var fruit2 = fruits[j];
// Skip if either fruit is already merged or different types
if (fruit1.merged || fruit2.merged || fruit1.type !== fruit2.type) {
continue;
}
// Skip if already at maximum fruit type (durian)
if (fruit1.type >= 16) {
continue;
}
// Auto merge merges ANY two fruits of the same type regardless of distance
// Perform the merge immediately
if (mergeFruits(fruit1, fruit2)) {
foundMerge = true;
break;
}
}
}
}
}
function checkGameOver() {
for (var i = 0; i < fruits.length; i++) {
var fruit = fruits[i];
// Only check game over for fruits that have made contact with ground or other fruits
if (fruit.contactMade && fruit.y - fruit.getRadius() < gameOverLine) {
return true;
}
}
return false;
}
// Fruit Mover button (leftmost)
var fruitMoverButton = new Text2('FRUIT MOVER!', {
size: 60,
fill: 0x000000
});
fruitMoverButton.anchor.set(0.5, 0.5);
// Place at far left
fruitMoverButton.x = 200;
fruitMoverButton.y = 2732 - 150;
game.addChild(fruitMoverButton);
// Cost text under fruit mover button
var fruitMoverCostText = new Text2('Cost: 125', {
size: 40,
fill: 0x000000
});
fruitMoverCostText.anchor.set(0.5, 0);
// Position just below the fruit mover button
fruitMoverCostText.x = fruitMoverButton.x;
fruitMoverCostText.y = fruitMoverButton.y + 60;
game.addChild(fruitMoverCostText);
// Randomize fruit button (second from left)
var randomizeButton = new Text2('RANDOMIZE!', {
size: 60,
fill: 0x000000
});
randomizeButton.anchor.set(0.5, 0.5);
// Place second from left
randomizeButton.x = 600;
randomizeButton.y = 2732 - 150;
game.addChild(randomizeButton);
// Cost text under randomize button
var randomizeCostText = new Text2('Cost: 300', {
size: 40,
fill: 0x000000
});
randomizeCostText.anchor.set(0.5, 0);
// Position just below the randomize button
randomizeCostText.x = randomizeButton.x;
randomizeCostText.y = randomizeButton.y + 60;
game.addChild(randomizeCostText);
// Shake button (center)
var shakeButton = new Text2('SHAKE!', {
size: 60,
fill: 0x000000
});
shakeButton.anchor.set(0.5, 0.5);
// Place at center
shakeButton.x = 2048 / 2;
shakeButton.y = 2732 - 150;
game.addChild(shakeButton);
// Cost text under shake button
var shakeCostText = new Text2('Cost: 450', {
size: 40,
fill: 0x000000
});
shakeCostText.anchor.set(0.5, 0);
// Position just below the shake button
shakeCostText.x = shakeButton.x;
shakeCostText.y = shakeButton.y + 60;
game.addChild(shakeCostText);
// Auto merge button (second from right)
var autoMergeButton = new Text2('AUTO MERGE!', {
size: 60,
fill: 0x000000
});
autoMergeButton.anchor.set(0.5, 0.5);
// Place second from right
autoMergeButton.x = 1448;
autoMergeButton.y = 2732 - 150;
game.addChild(autoMergeButton);
// Cost text under auto merge button
var autoMergeCostText = new Text2('Cost: 800', {
size: 40,
fill: 0x000000
});
autoMergeCostText.anchor.set(0.5, 0);
// Position just below the auto merge button
autoMergeCostText.x = autoMergeButton.x;
autoMergeCostText.y = autoMergeButton.y + 60;
game.addChild(autoMergeCostText);
// Fruit Rain button (rightmost)
var fruitRainButton = new Text2('FRUIT RAIN!', {
size: 60,
fill: 0x000000
});
fruitRainButton.anchor.set(0.5, 0.5);
// Place at far right
fruitRainButton.x = 1848;
fruitRainButton.y = 2732 - 150;
game.addChild(fruitRainButton);
// Cost text under fruit rain button
var fruitRainCostText = new Text2('Cost: 1000', {
size: 40,
fill: 0x000000
});
fruitRainCostText.anchor.set(0.5, 0);
// Position just below the fruit rain button
fruitRainCostText.x = fruitRainButton.x;
fruitRainCostText.y = fruitRainButton.y + 60;
game.addChild(fruitRainCostText);
// Add auto merge button click handler
autoMergeButton.down = function (x, y, obj) {
if (LK.getScore() >= 800 && fruits.length > 1) {
// Deduct score
LK.setScore(LK.getScore() - 800);
scoreTxt.setText('Score: ' + LK.getScore());
// Perform auto merge
performAutoMerge();
}
};
// Add randomize button click handler
randomizeButton.down = function (x, y, obj) {
if (LK.getScore() >= 300 && fruits.length > 1) {
// Deduct score
LK.setScore(LK.getScore() - 300);
scoreTxt.setText('Score: ' + LK.getScore());
// Store all current fruit positions
var positions = [];
for (var i = 0; i < fruits.length; i++) {
positions.push({
x: fruits[i].x,
y: fruits[i].y
});
}
// Shuffle the positions array
for (var i = positions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = positions[i];
positions[i] = positions[j];
positions[j] = temp;
}
// Apply shuffled positions to fruits
for (var i = 0; i < fruits.length; i++) {
fruits[i].x = positions[i].x;
fruits[i].y = positions[i].y;
// Reset velocities to prevent physics issues
fruits[i].velocityX = 0;
fruits[i].velocityY = 0;
fruits[i].angularVelocity = 0;
}
}
};
// Add fruit rain button click handler
fruitRainButton.down = function (x, y, obj) {
if (LK.getScore() >= 1000) {
// Deduct score
LK.setScore(LK.getScore() - 1000);
scoreTxt.setText('Score: ' + LK.getScore());
// Create fruit rain effect for 3 seconds
var rainDuration = 3000;
var rainStartTime = LK.ticks;
fruitRainActive = true;
// Create fruits every 100ms (0.1 seconds) during the rain
var rainInterval = LK.setInterval(function () {
if (LK.ticks - rainStartTime >= rainDuration / (1000 / 60)) {
// 3 seconds have passed
LK.clearInterval(rainInterval);
fruitRainActive = false;
return;
}
// Create a random lesser fruit (types 0-4: cherry, strawberry, grape, orange, apple)
var randomType = Math.floor(Math.random() * 5);
var rainFruit = new Fruit(randomType);
// Mark this fruit as a rain fruit (won't give score)
rainFruit.isRainFruit = true;
// Random X position within container bounds
var fruitRadius = rainFruit.getRadius();
var containerLeft = containerX - containerWidth / 2;
var containerRight = containerX + containerWidth / 2;
var randomX = containerLeft + fruitRadius + Math.random() * (containerRight - containerLeft - 2 * fruitRadius);
// Start from above the container
var containerTop = containerY - containerHeight / 2;
rainFruit.x = randomX;
rainFruit.y = containerTop - 200 - Math.random() * 300; // Start higher with some randomness
// Add slight random horizontal velocity for more natural effect
rainFruit.velocityX = (Math.random() - 0.5) * 2;
rainFruit.velocityY = Math.random() * 2 + 1; // Small downward velocity
rainFruit.angularVelocity = (Math.random() - 0.5) * 0.1;
// Mark as discovered
discoveredFruits[randomType] = true;
storage.discoveredFruits = discoveredFruits;
fruits.push(rainFruit);
game.addChild(rainFruit);
}, 100); // Create fruit every 100ms
}
};
// Global variables for fruit mover mode
var fruitMoverActive = false;
var fruitMoverSelectedFruit = null;
// Global variable for fruit rain mode
var fruitRainActive = false;
// Tutorial system variables
var tutorialActive = true; // Always allow tutorial to be available
var tutorialStep = 0;
var tutorialOverlay = null;
var tutorialText = null;
var tutorialArrow = null;
var tutorialVisuals = null; // Container for visual demonstrations
var tutorialTimeouts = []; // Track all tutorial timeouts for cleanup
var tutorialSteps = [{
text: "Welcome to Fruit Drop! Tap and hold to aim your fruit, then release to drop it.",
target: null,
highlight: {
x: 2048 / 2,
y: dropLine,
width: containerWidth,
height: 200
},
visual: "dropDemo"
}, {
text: "When two fruits of the same type touch, they merge into a bigger fruit!",
target: null,
highlight: null,
visual: "mergeDemo"
}, {
text: "Your score is shown here. Merging gives you points!",
target: "score",
highlight: null,
visual: "scoreDemo"
}, {
text: "Check your next fruit here to plan your strategy.",
target: "nextFruit",
highlight: null,
visual: "nextFruitDemo"
}, {
text: "Don't let fruits pile up above this blue line or it's game over!",
target: null,
highlight: {
x: containerX,
y: gameOverLine,
width: containerWidth,
height: 10
},
visual: "gameOverDemo"
}, {
text: "Use power-ups at the bottom to help when you're stuck!",
target: "powerups",
highlight: {
x: 2048 / 2,
y: 2732 - 150,
width: 1800,
height: 150
},
visual: "powerupDemo"
}, {
text: "Tap EVOLUTION to see all fruits you can discover!",
target: "evolution",
highlight: null,
visual: "evolutionDemo"
}, {
text: "Tap SAVE to save your game progress in multiple slots!",
target: "save",
highlight: null,
visual: "saveDemo"
}, {
text: "Tap MUSIC to change the background music anytime!",
target: "music",
highlight: null,
visual: "musicDemo"
}, {
text: "Great! Now you're ready to play. Try dropping your first fruit!",
target: null,
highlight: {
x: 2048 / 2,
y: dropLine,
width: containerWidth,
height: 200
},
visual: "readyDemo"
}];
// Tutorial visual creation functions
function createTutorialVisuals(visualType) {
if (tutorialVisuals) {
// Clean up existing visuals
tween.stop(tutorialVisuals);
tutorialVisuals.destroy();
tutorialVisuals = null;
}
tutorialVisuals = new Container();
if (tutorialOverlay) {
tutorialOverlay.addChild(tutorialVisuals);
}
switch (visualType) {
case "dropDemo":
// Animate dropping motion
var _dropAnimation = function dropAnimation() {
tween(demoFruit, {
y: dropLine + 300
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Reset position and repeat
demoFruit.y = dropLine - 100;
var dropTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_dropAnimation();
}
}, 500);
tutorialTimeouts.push(dropTimeout);
}
});
};
// Show animated fruit dropping
var demoFruit = LK.getAsset('cherry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX,
y: dropLine - 100
});
tutorialVisuals.addChild(demoFruit);
_dropAnimation();
break;
case "mergeDemo":
var _mergeAnimation = function mergeAnimation() {
// Move cherries together
tween(cherry1, {
x: containerX - 20
}, {
duration: 800,
easing: tween.easeOut
});
tween(cherry2, {
x: containerX + 20
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Flash effect
tween(cherry1, {
tint: 0xffffff,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
tween(cherry2, {
tint: 0xffffff,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
// Replace with strawberry
cherry1.destroy();
cherry2.destroy();
var strawberry = LK.getAsset('strawberry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX,
y: containerY
});
if (tutorialVisuals) {
tutorialVisuals.addChild(strawberry);
}
// Celebration effect
tween(strawberry, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Reset and repeat
var resetTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
strawberry.destroy();
cherry1 = LK.getAsset('cherry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX - 80,
y: containerY
});
cherry2 = LK.getAsset('cherry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + 80,
y: containerY
});
tutorialVisuals.addChild(cherry1);
tutorialVisuals.addChild(cherry2);
_mergeAnimation();
}
}, 1000);
tutorialTimeouts.push(resetTimeout);
}
});
}
});
}
});
};
// Show two cherries merging into strawberry
var cherry1 = LK.getAsset('cherry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX - 80,
y: containerY
});
var cherry2 = LK.getAsset('cherry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + 80,
y: containerY
});
tutorialVisuals.addChild(cherry1);
tutorialVisuals.addChild(cherry2);
_mergeAnimation();
break;
case "scoreDemo":
var _scoreAnimation = function scoreAnimation() {
var targetScore = currentScore + 50;
var scoreInterval = LK.setInterval(function () {
currentScore += 2;
scoreDisplay.setText('Score: ' + currentScore);
if (currentScore >= targetScore) {
LK.clearInterval(scoreInterval);
var scoreResetTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
currentScore = 0;
_scoreAnimation();
}
}, 1000);
tutorialTimeouts.push(scoreResetTimeout);
}
}, 50);
};
// Show animated score counting up
var scoreDisplay = new Text2('Score: 0', {
size: 60,
fill: 0x00ff00
});
scoreDisplay.anchor.set(0.5, 0.5);
scoreDisplay.x = containerX;
scoreDisplay.y = containerY - 200;
tutorialVisuals.addChild(scoreDisplay);
var currentScore = 0;
_scoreAnimation();
break;
case "nextFruitDemo":
var _pulseNext = function pulseNext() {
tween(nextDemo, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(nextDemo, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: _pulseNext
});
}
});
};
// Show next fruit preview with pulsing effect
var nextDemo = LK.getAsset('strawberry', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + 300,
y: containerY - 300
});
tutorialVisuals.addChild(nextDemo);
_pulseNext();
break;
case "gameOverDemo":
var _loop2 = function _loop2() {
pileFruit = LK.getAsset('orange', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + (i - 1) * 80,
y: gameOverLine - 50 - i * 60
});
pileFruit.tint = 0xff4444; // Red tint to show danger
tutorialVisuals.addChild(pileFruit);
// Shake animation
function shakeAnimation(fruit) {
tween(fruit, {
x: fruit.x + 10
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(fruit, {
x: fruit.x - 10
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
shakeAnimation(fruit);
}
});
}
});
}
shakeAnimation(pileFruit);
},
pileFruit;
// Show fruits piling up above the line
for (var i = 0; i < 3; i++) {
_loop2();
}
break;
case "powerupDemo":
var _miniShake = function miniShake() {
for (var i = 0; i < shakeFruits.length; i++) {
tween(shakeFruits[i], {
x: shakeFruits[i].x + Math.random() * 40 - 20,
y: shakeFruits[i].y + Math.random() * 40 - 20
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
if (i === shakeFruits.length - 1) {
var shakeTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_miniShake();
}
}, 1500);
tutorialTimeouts.push(shakeTimeout);
}
}
});
}
};
// Show mini versions of power-up effects
var demoContainer = new Container();
demoContainer.x = containerX;
demoContainer.y = containerY;
tutorialVisuals.addChild(demoContainer);
// Mini shake effect
var shakeFruits = [];
for (var i = 0; i < 4; i++) {
var shakeFruit = LK.getAsset('grape', {
anchorX: 0.5,
anchorY: 0.5,
x: (i - 1.5) * 60,
y: 0,
width: 40,
height: 40
});
demoContainer.addChild(shakeFruit);
shakeFruits.push(shakeFruit);
}
_miniShake();
break;
case "evolutionDemo":
// Glow effect on fruits
var _glowEvolution = function glowEvolution() {
for (var i = 0; i < tutorialVisuals.children.length; i++) {
var child = tutorialVisuals.children[i];
if (child !== tutorialVisuals.children[0]) {
// Skip first child
tween(child, {
tint: 0xffff88
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(child, {
tint: 0xffffff
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
}
var glowTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_glowEvolution();
}
}, 1600);
tutorialTimeouts.push(glowTimeout);
};
// Show fruit evolution chain
var evolutionChain = ['cherry', 'strawberry', 'grape'];
for (var i = 0; i < evolutionChain.length; i++) {
var evoFruit = LK.getAsset(evolutionChain[i], {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + (i - 1) * 120,
y: containerY - 100,
width: 80,
height: 80
});
tutorialVisuals.addChild(evoFruit);
if (i > 0) {
// Add arrow
var arrow = LK.getAsset('orangeCircle', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + (i - 1.5) * 120,
y: containerY - 100,
width: 30,
height: 30
});
arrow.tint = 0xffaa00;
tutorialVisuals.addChild(arrow);
}
}
_glowEvolution();
break;
case "saveDemo":
var _saveAnimation = function saveAnimation() {
tween(saveIcon, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0x4CAF50
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(saveIcon, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xffffff
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
var saveTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_saveAnimation();
}
}, 1000);
tutorialTimeouts.push(saveTimeout);
}
});
}
});
};
// Show save icon with slots
var saveIcon = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX,
y: containerY - 100,
width: 200,
height: 150
});
saveIcon.tint = 0xdddddd;
tutorialVisuals.addChild(saveIcon);
// Add slot indicators
for (var i = 0; i < 3; i++) {
var slot = LK.getAsset('nextFruit', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + (i - 1) * 80,
y: containerY + 50,
width: 60,
height: 60
});
slot.tint = 0x4CAF50;
tutorialVisuals.addChild(slot);
}
_saveAnimation();
break;
case "musicDemo":
var _musicAnimation = function musicAnimation() {
for (var i = 0; i < musicNotes.length; i++) {
tween(musicNotes[i], {
y: musicNotes[i].y - 30,
alpha: 1
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(this, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
this.y = containerY + 100;
this.alpha = 0.8;
}
});
}
});
}
var musicTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_musicAnimation();
}
}, 1200);
tutorialTimeouts.push(musicTimeout);
};
// Show musical notes animation
var musicNotes = [];
for (var i = 0; i < 5; i++) {
var note = LK.getAsset('nextFruit', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX + (i - 2) * 60,
y: containerY + 100,
width: 30,
height: 30
});
note.tint = 0xff9800;
note.alpha = 0.8;
tutorialVisuals.addChild(note);
musicNotes.push(note);
}
_musicAnimation();
break;
case "readyDemo":
var _encourageAnimation = function encourageAnimation() {
tween(readyFruit, {
scaleX: 1.3,
scaleY: 1.3,
rotation: 0.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(readyFruit, {
scaleX: 1.0,
scaleY: 1.0,
rotation: -0.2
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(readyFruit, {
rotation: 0
}, {
duration: 200,
onFinish: function onFinish() {
var encourageTimeout = LK.setTimeout(function () {
if (tutorialVisuals && !tutorialVisuals.destroyed) {
_encourageAnimation();
}
}, 1000);
tutorialTimeouts.push(encourageTimeout);
}
});
}
});
}
});
};
// Show encouraging "thumbs up" style visual
var readyFruit = LK.getAsset('apple', {
anchorX: 0.5,
anchorY: 0.5,
x: containerX,
y: containerY
});
tutorialVisuals.addChild(readyFruit);
_encourageAnimation();
break;
}
}
// Tutorial functions
function createTutorialOverlay() {
if (tutorialOverlay) {
tutorialOverlay.destroy();
}
tutorialOverlay = new Container();
game.addChild(tutorialOverlay);
// Semi-transparent background
var tutorialBg = LK.getAsset('container', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
tutorialBg.alpha = 0.7;
tutorialBg.tint = 0x000000;
tutorialOverlay.addChild(tutorialBg);
// Tutorial text background
var textBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 300,
width: 1800,
height: 250
});
textBg.alpha = 0.95;
textBg.tint = 0xffffff;
tutorialOverlay.addChild(textBg);
// Tutorial text
tutorialText = new Text2('', {
size: 50,
fill: 0x000000
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 2048 / 2;
tutorialText.y = 2732 - 300;
tutorialOverlay.addChild(tutorialText);
// Next button
var nextButton = new Text2('NEXT', {
size: 60,
fill: 0xffffff
});
nextButton.anchor.set(0.5, 0.5);
nextButton.x = 2048 / 2 + 600;
nextButton.y = 2732 - 200;
var nextButtonBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: nextButton.x,
y: nextButton.y,
width: 200,
height: 80
});
nextButtonBg.tint = 0x4CAF50;
tutorialOverlay.addChild(nextButtonBg);
tutorialOverlay.addChild(nextButton);
nextButton.down = function () {
nextTutorialStep();
};
// Skip button
var skipButton = new Text2('SKIP', {
size: 60,
fill: 0xffffff
});
skipButton.anchor.set(0.5, 0.5);
skipButton.x = 2048 / 2 - 600;
skipButton.y = 2732 - 200;
var skipButtonBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: skipButton.x,
y: skipButton.y,
width: 200,
height: 80
});
skipButtonBg.tint = 0xf44336;
tutorialOverlay.addChild(skipButtonBg);
tutorialOverlay.addChild(skipButton);
skipButton.down = function () {
completeTutorial();
};
// Store references to buttons for repositioning
tutorialOverlay.nextButton = nextButton;
tutorialOverlay.nextButtonBg = nextButtonBg;
tutorialOverlay.skipButton = skipButton;
tutorialOverlay.skipButtonBg = skipButtonBg;
}
function showTutorialStep() {
if (!tutorialActive || tutorialStep >= tutorialSteps.length) {
completeTutorial();
return;
}
createTutorialOverlay();
var step = tutorialSteps[tutorialStep];
tutorialText.setText(step.text);
// Determine tutorial text position based on content and targets
var textBg = tutorialOverlay.children[1]; // Text background
var textX = 2048 / 2;
var textY = 2732 - 300;
// Move tutorial text based on what we're explaining
if (step.target === "score") {
textX = 2048 / 2;
textY = 400; // Move down when pointing to score at top
} else if (step.target === "nextFruit") {
textX = 1024; // Move left when pointing to next fruit on right
textY = 400;
} else if (step.target === "evolution") {
textX = 2048 / 2;
textY = 500; // Move down when pointing to evolution button
} else if (step.target === "powerups") {
textX = 2048 / 2;
textY = 2732 - 600; // Move up when pointing to powerups at bottom
} else if (step.highlight && step.highlight.y < 1000) {
textY = 2000; // Move to bottom if highlighting something at top
} else if (step.highlight && step.highlight.y > 2000) {
textY = 800; // Move to top if highlighting something at bottom
}
// Animate tutorial text and background to new position
tween(textBg, {
x: textX,
y: textY
}, {
duration: 500,
easing: tween.easeOut
});
tween(tutorialText, {
x: textX,
y: textY
}, {
duration: 500,
easing: tween.easeOut
});
// Move tutorial buttons to follow the text
var buttonY = textY + 100;
if (tutorialOverlay.nextButton) {
tween(tutorialOverlay.nextButton, {
x: textX + 300,
y: buttonY
}, {
duration: 500,
easing: tween.easeOut
});
tween(tutorialOverlay.nextButtonBg, {
x: textX + 300,
y: buttonY
}, {
duration: 500,
easing: tween.easeOut
});
}
if (tutorialOverlay.skipButton) {
tween(tutorialOverlay.skipButton, {
x: textX - 300,
y: buttonY
}, {
duration: 500,
easing: tween.easeOut
});
tween(tutorialOverlay.skipButtonBg, {
x: textX - 300,
y: buttonY
}, {
duration: 500,
easing: tween.easeOut
});
}
// Add visual demonstration if specified
if (step.visual) {
createTutorialVisuals(step.visual);
}
// Add highlight if specified
if (step.highlight) {
// Pulsing animation
var pulseUp = function pulseUp() {
tween(highlight, {
alpha: 0.3,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseDown
});
};
var pulseDown = function pulseDown() {
tween(highlight, {
alpha: 0.1,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: pulseUp
});
};
var highlight = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: step.highlight.x,
y: step.highlight.y,
width: step.highlight.width,
height: step.highlight.height
});
highlight.alpha = 0;
highlight.tint = 0xffff00;
tutorialOverlay.addChild(highlight);
pulseUp();
}
// Create arrow pointing to target
if (step.target) {
tutorialArrow = LK.getAsset('orangeCircle', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80
});
tutorialArrow.tint = 0xff9800;
var targetPos = getTutorialTargetPosition(step.target);
if (targetPos) {
var bounceUp = function bounceUp() {
tween(tutorialArrow, {
y: originalY - 20
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: bounceDown
});
};
var bounceDown = function bounceDown() {
tween(tutorialArrow, {
y: originalY
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: bounceUp
});
};
tutorialArrow.x = targetPos.x;
tutorialArrow.y = targetPos.y - 120;
tutorialOverlay.addChild(tutorialArrow);
// Bouncing animation
var originalY = tutorialArrow.y;
bounceUp();
// Animate arrow sliding in from the side based on target
var startX = tutorialArrow.x;
if (step.target === "nextFruit") {
tutorialArrow.x = 2048 + 100; // Start from right side
} else if (step.target === "score" || step.target === "evolution") {
tutorialArrow.x = -100; // Start from left side
} else {
tutorialArrow.x = 2048 / 2; // Start from center
}
tween(tutorialArrow, {
x: startX
}, {
duration: 600,
easing: tween.bounceOut
});
}
}
}
function getTutorialTargetPosition(target) {
switch (target) {
case "score":
return {
x: scoreTxt.x,
y: 150
};
case "nextFruit":
return {
x: 1700,
y: 120
};
case "evolution":
return {
x: evolutionButton.x,
y: 200
};
case "save":
return {
x: saveMenuButton.x,
y: 200
};
case "music":
return {
x: musicMenuButton.x,
y: 200
};
case "powerups":
return {
x: 2048 / 2,
y: 2732 - 150
};
default:
return null;
}
}
function nextTutorialStep() {
// Clear all tutorial timeouts first
for (var i = 0; i < tutorialTimeouts.length; i++) {
LK.clearTimeout(tutorialTimeouts[i]);
}
tutorialTimeouts = [];
// Clean up current tutorial visuals before moving to next step
if (tutorialVisuals) {
// Stop all tweens on tutorialVisuals and its children recursively
var _stopAllTweensRecursive = function stopAllTweensRecursive(container) {
if (!container) return;
tween.stop(container);
if (container.children && container.children.length > 0) {
for (var i = 0; i < container.children.length; i++) {
if (container.children[i]) {
_stopAllTweensRecursive(container.children[i]);
}
}
}
};
_stopAllTweensRecursive(tutorialVisuals);
// Clear any pending timeouts or intervals that might recreate objects
// Force immediate cleanup by removing from parent first
if (tutorialVisuals.parent) {
tutorialVisuals.parent.removeChild(tutorialVisuals);
}
// Always destroy tutorialVisuals regardless of parent state
tutorialVisuals.destroy();
tutorialVisuals = null;
}
tutorialStep++;
if (tutorialStep >= tutorialSteps.length) {
completeTutorial();
} else {
showTutorialStep();
}
}
function completeTutorial() {
tutorialActive = false;
storage.tutorialCompleted = true;
// Clear all tutorial timeouts
for (var i = 0; i < tutorialTimeouts.length; i++) {
LK.clearTimeout(tutorialTimeouts[i]);
}
tutorialTimeouts = [];
if (tutorialVisuals) {
tween.stop(tutorialVisuals);
tutorialVisuals.destroy();
tutorialVisuals = null;
}
if (tutorialOverlay) {
tutorialOverlay.destroy();
tutorialOverlay = null;
}
gameRunning = true;
fruitsFrozen = false;
}
// Tutorial will start after music selection instead of here
// Add fruit mover button click handler
fruitMoverButton.down = function (x, y, obj) {
if (LK.getScore() >= 125 && fruits.length > 0) {
// Deduct score
LK.setScore(LK.getScore() - 125);
scoreTxt.setText('Score: ' + LK.getScore());
// Activate fruit mover mode
fruitMoverActive = true;
fruitMoverSelectedFruit = null;
// Make all fruits green when fruit mover is used
for (var i = 0; i < fruits.length; i++) {
tween(fruits[i], {
tint: 0x00ff00
}, {
duration: 300,
easing: tween.easeOut
});
}
}
};
// Add shake button click handler
shakeButton.down = function (x, y, obj) {
if (LK.getScore() >= 450) {
// Deduct score
LK.setScore(LK.getScore() - 450);
scoreTxt.setText('Score: ' + LK.getScore());
// Move all fruits to random positions within container bounds
for (var i = 0; i < fruits.length; i++) {
var fruit = fruits[i];
var radius = fruit.getRadius();
var containerLeft = containerX - containerWidth / 2;
var containerRight = containerX + containerWidth / 2;
var containerTop = containerY - containerHeight / 2;
var containerBottom = containerY + containerHeight / 2;
// Calculate valid random position within container bounds
var randomX = containerLeft + radius + Math.random() * (containerRight - containerLeft - 2 * radius);
var randomY = containerTop + radius + Math.random() * (containerBottom - containerTop - 2 * radius);
// Animate fruit to new position with tween
tween(fruit, {
x: randomX,
y: randomY
}, {
duration: 500 + Math.random() * 500,
// Random duration between 500-1000ms
easing: tween.easeOut
});
// Reset velocities to prevent physics issues
fruit.velocityX = 0;
fruit.velocityY = 0;
fruit.angularVelocity = 0;
}
}
};
// Do not spawn a fruit at start; only spawn on click/hold
createNextFruit();
// --- Evolution Button and Menu ---
// Evolution button
var evolutionButton = new Text2('EVOLUTION', {
size: 60,
fill: 0x000000
});
evolutionButton.anchor.set(0.5, 0);
// Place directly under the score display, using LK.gui for vertical stacking
evolutionButton.y = scoreTxt.height + 20;
LK.gui.top.addChild(evolutionButton);
// Evolution menu container (hidden by default)
var evolutionMenu = new Container();
evolutionMenu.visible = false;
// Add evolution menu to the front (highest z-index)
game.addChild(evolutionMenu);
// Semi-transparent background for menu
var menuBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 1400,
height: 1400
});
menuBg.alpha = 0.92;
menuBg.tint = 0xeeeeee;
evolutionMenu.addChild(menuBg);
// Title
var evolutionTitle = new Text2('Fruit Evolution', {
size: 90,
fill: 0x222222,
stroke: 0xffffff,
strokeThickness: 4
});
evolutionTitle.anchor.set(0.5, 0);
evolutionTitle.x = 2048 / 2;
evolutionTitle.y = 2732 / 2 - 650;
evolutionMenu.addChild(evolutionTitle);
// Fruit evolution data
var evoFruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var evoFruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700];
// Draw fruits in a circle
var centerX = 2048 / 2;
var centerY = 2732 / 2 + 80;
var radius = 500;
for (var i = 0; i < evoFruitAssets.length; i++) {
var angle = Math.PI * 2 / evoFruitAssets.length * i - Math.PI / 2;
var fruitAsset = LK.getAsset(evoFruitAssets[i], {
anchorX: 0.5,
anchorY: 0.5
});
// Make all fruits the same size as the strawberry (160x160)
var strawberrySize = 160;
var fruitRadius = strawberrySize / 2;
fruitAsset.width = strawberrySize;
fruitAsset.height = strawberrySize;
fruitAsset.x = centerX + Math.cos(angle) * radius;
fruitAsset.y = centerY + Math.sin(angle) * radius;
// Black out and hide text for undiscovered fruits
if (!discoveredFruits[i]) {
fruitAsset.tint = 0x222222;
fruitAsset.alpha = 0.7;
}
evolutionMenu.addChild(fruitAsset);
// Fruit name label
var nameLabel = new Text2(discoveredFruits[i] ? evoFruitNames[i] : '', {
size: 38,
fill: 0x333333,
stroke: 0xffffff,
strokeThickness: 3
});
nameLabel.anchor.set(0.5, 1);
nameLabel.x = fruitAsset.x;
nameLabel.y = fruitAsset.y - fruitRadius - 10;
evolutionMenu.addChild(nameLabel);
// Draw arrow to next fruit (except last)
if (i < evoFruitAssets.length - 1) {
var nextAngle = Math.PI * 2 / evoFruitAssets.length * (i + 1) - Math.PI / 2;
var arrowX1 = fruitAsset.x + Math.cos(angle) * (fruitRadius + 20);
var arrowY1 = fruitAsset.y + Math.sin(angle) * (fruitRadius + 20);
var arrowX2 = centerX + Math.cos(nextAngle) * (radius - 40);
var arrowY2 = centerY + Math.sin(nextAngle) * (radius - 40);
// Use a small fruit as an arrow "dot"
var arrowDot = LK.getAsset('nextFruit', {
anchorX: 0.5,
anchorY: 0.5,
x: (arrowX1 + arrowX2) / 2,
y: (arrowY1 + arrowY2) / 2,
width: 32,
height: 32
});
arrowDot.tint = 0xaaaaaa;
evolutionMenu.addChild(arrowDot);
}
}
// Show menu on button press
evolutionButton.down = function (x, y, obj) {
// If menu is open, close it
if (evolutionMenu.visible) {
evolutionMenu.visible = false;
gameRunning = true;
fruitsFrozen = false;
return;
}
// Otherwise, update and open the menu
var childIdx = 0;
for (var i = 0; i < evoFruitAssets.length; i++) {
// Fruit asset is first, label is second, then arrow dot (if not last)
var fruitAsset = evolutionMenu.children[childIdx + 2]; // skip bg and title
var nameLabel = evolutionMenu.children[childIdx + 3];
if (!discoveredFruits[i]) {
fruitAsset.tint = 0x222222;
fruitAsset.alpha = 0.7;
nameLabel.setText('');
} else {
fruitAsset.tint = 0xffffff;
fruitAsset.alpha = 1.0;
nameLabel.setText(evoFruitNames[i]);
// Text2 stroke properties are set directly, not through style object
nameLabel.stroke = 0xffffff;
nameLabel.strokeThickness = 3;
}
childIdx += 2;
if (i < evoFruitAssets.length - 1) childIdx++; // skip arrow dot
}
evolutionMenu.visible = true;
// Move evolution menu to front to ensure it's on top of all game elements
game.removeChild(evolutionMenu);
game.addChild(evolutionMenu);
// Optionally, darken background or disable gameplay while menu is open
gameRunning = false;
fruitsFrozen = true;
};
// Music menu button
var musicMenuButton = new Text2('MUSIC', {
size: 60,
fill: 0x000000
});
musicMenuButton.anchor.set(0.5, 0);
musicMenuButton.x = evolutionButton.x + 300;
musicMenuButton.y = evolutionButton.y;
LK.gui.top.addChild(musicMenuButton);
// Save menu button
var saveMenuButton = new Text2('SAVE', {
size: 60,
fill: 0x000000
});
saveMenuButton.anchor.set(0.5, 0);
saveMenuButton.x = evolutionButton.x - 300;
saveMenuButton.y = musicMenuButton.y;
LK.gui.top.addChild(saveMenuButton);
// Music menu container
var musicMenu = new Container();
musicMenu.visible = false;
game.addChild(musicMenu);
// Save menu container
var saveMenu = new Container();
saveMenu.visible = false;
game.addChild(saveMenu);
// Save menu background
var saveMenuBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 1600,
height: 1000
});
saveMenuBg.alpha = 0.95;
saveMenuBg.tint = 0xdddddd;
saveMenu.addChild(saveMenuBg);
// Save menu title
var saveMenuTitle = new Text2('Save & Load Game', {
size: 80,
fill: 0x222222,
stroke: 0xffffff,
strokeThickness: 3
});
saveMenuTitle.anchor.set(0.5, 0);
saveMenuTitle.x = 2048 / 2;
saveMenuTitle.y = 2732 / 2 - 400;
saveMenu.addChild(saveMenuTitle);
// Save game data function
function saveGameData(slotNumber) {
// Save basic game data directly to storage to avoid nested objects
var slotPrefix = 'slot' + slotNumber + '_';
storage[slotPrefix + 'savedGameScore'] = LK.getScore();
storage[slotPrefix + 'savedGameTotalMerges'] = totalMerges;
storage[slotPrefix + 'savedGameDiscoveredFruits'] = discoveredFruits;
storage[slotPrefix + 'savedGameCurrentMusicIndex'] = currentMusicIndex;
storage[slotPrefix + 'savedGameTutorialCompleted'] = storage.tutorialCompleted || false;
storage[slotPrefix + 'savedGameTime'] = Date.now();
// Save fruits data as separate flat arrays to avoid nested objects
var fruitTypes = [];
var fruitXPositions = [];
var fruitYPositions = [];
var fruitIsRainbow = [];
var fruitIsRainFruit = [];
var fruitIsGold = [];
var fruitIsCelestial = [];
for (var i = 0; i < fruits.length; i++) {
fruitTypes.push(fruits[i].type);
fruitXPositions.push(fruits[i].x);
fruitYPositions.push(fruits[i].y);
fruitIsRainbow.push(fruits[i].isRainbow || false);
fruitIsRainFruit.push(fruits[i].isRainFruit || false);
fruitIsGold.push(fruits[i].isGold || false);
fruitIsCelestial.push(fruits[i].isCelestial || false);
}
storage[slotPrefix + 'savedGameFruitTypes'] = fruitTypes;
storage[slotPrefix + 'savedGameFruitXPositions'] = fruitXPositions;
storage[slotPrefix + 'savedGameFruitYPositions'] = fruitYPositions;
storage[slotPrefix + 'savedGameFruitIsRainbow'] = fruitIsRainbow;
storage[slotPrefix + 'savedGameFruitIsRainFruit'] = fruitIsRainFruit;
storage[slotPrefix + 'savedGameFruitIsGold'] = fruitIsGold;
storage[slotPrefix + 'savedGameFruitIsCelestial'] = fruitIsCelestial;
return {
score: storage[slotPrefix + 'savedGameScore'],
totalMerges: storage[slotPrefix + 'savedGameTotalMerges'],
discoveredFruits: storage[slotPrefix + 'savedGameDiscoveredFruits'],
currentMusicIndex: storage[slotPrefix + 'savedGameCurrentMusicIndex'],
tutorialCompleted: storage[slotPrefix + 'savedGameTutorialCompleted']
};
}
// Helper function to check if a save slot has data
function hasSlotData(slotNumber) {
var slotPrefix = 'slot' + slotNumber + '_';
return storage[slotPrefix + 'savedGameScore'] !== undefined;
}
// Load game data function
function loadGameData(slotNumber) {
// Check if we have saved game data for this slot
var slotPrefix = 'slot' + slotNumber + '_';
if (storage[slotPrefix + 'savedGameScore'] === undefined) return false;
// Restore score and counters
LK.setScore(storage[slotPrefix + 'savedGameScore'] || 0);
scoreTxt.setText('Score: ' + LK.getScore());
totalMerges = storage[slotPrefix + 'savedGameTotalMerges'] || 0;
mergeCounterTxt.setText('Merges: ' + totalMerges);
// Restore discovered fruits
if (storage[slotPrefix + 'savedGameDiscoveredFruits']) {
discoveredFruits = storage[slotPrefix + 'savedGameDiscoveredFruits'];
}
// Restore music selection
if (storage[slotPrefix + 'savedGameCurrentMusicIndex'] !== undefined) {
currentMusicIndex = storage[slotPrefix + 'savedGameCurrentMusicIndex'];
}
// Clear existing fruits
for (var i = fruits.length - 1; i >= 0; i--) {
fruits[i].destroy();
fruits.splice(i, 1);
}
// Restore fruits from flat arrays
var fruitTypes = storage[slotPrefix + 'savedGameFruitTypes'] || [];
var fruitXPositions = storage[slotPrefix + 'savedGameFruitXPositions'] || [];
var fruitYPositions = storage[slotPrefix + 'savedGameFruitYPositions'] || [];
var fruitIsRainbow = storage[slotPrefix + 'savedGameFruitIsRainbow'] || [];
var fruitIsRainFruit = storage[slotPrefix + 'savedGameFruitIsRainFruit'] || [];
var fruitIsGold = storage[slotPrefix + 'savedGameFruitIsGold'] || [];
var fruitIsCelestial = storage[slotPrefix + 'savedGameFruitIsCelestial'] || [];
if (fruitTypes.length > 0) {
for (var i = 0; i < fruitTypes.length; i++) {
var newFruit = new Fruit(fruitTypes[i]);
newFruit.x = fruitXPositions[i] || 0;
newFruit.y = fruitYPositions[i] || 0;
newFruit.isRainbow = fruitIsRainbow[i] || false;
newFruit.isRainFruit = fruitIsRainFruit[i] || false;
newFruit.isGold = fruitIsGold[i] || false;
newFruit.isCelestial = fruitIsCelestial[i] || false;
// Restore rainbow visual effects if this fruit is rainbow
if (newFruit.isRainbow) {
newFruit.rainbowTintIndex = 0;
newFruit.rainbowColors = [0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0x0080ff, 0x8000ff];
var fruitGraphics = newFruit.children[0];
if (fruitGraphics) {
fruitGraphics.tint = newFruit.rainbowColors[0];
}
}
// Restore celestial visual effects if this fruit is celestial
if (newFruit.isCelestial) {
var fruitGraphics = newFruit.children[0];
if (fruitGraphics) {
fruitGraphics.tint = 0x8a2be2; // Purple color
}
// Recreate celestial ring using celestial ring asset
newFruit.celestialRing = newFruit.attachAsset('celestialRing', {
anchorX: 0.5,
anchorY: 0.5
});
newFruit.celestialRing.width = newFruit.size + 80;
newFruit.celestialRing.height = newFruit.size + 80;
newFruit.celestialRing.alpha = 0.6;
newFruit.addChildAt(newFruit.celestialRing, 0); // Add behind the fruit
}
// Restore gold visual effects if this fruit is gold
if (newFruit.isGold) {
var fruitGraphics = newFruit.children[0];
if (fruitGraphics) {
fruitGraphics.tint = 0xffd700; // Gold color
}
newFruit.shines = [];
// Recreate shine effects around the fruit
for (var s = 0; s < 3; s++) {
var shine = newFruit.attachAsset('shine', {
anchorX: 0.5,
anchorY: 0.5
});
shine.alpha = 0;
newFruit.shines.push(shine);
}
}
newFruit.velocityX = 0;
newFruit.velocityY = 0;
newFruit.angularVelocity = 0;
fruits.push(newFruit);
game.addChild(newFruit);
}
}
return true;
}
// Create save slots (3 slots)
var saveSlots = [];
for (var slotNum = 1; slotNum <= 3; slotNum++) {
// Save slot button
var saveSlotButton = new Text2('SLOT ' + slotNum, {
size: 50,
fill: 0xffffff
});
saveSlotButton.anchor.set(0.5, 0.5);
saveSlotButton.x = 2048 / 2 - 400 + (slotNum - 1) * 400;
saveSlotButton.y = 2732 / 2 - 150;
saveSlotButton.slotNumber = slotNum;
var saveSlotButtonBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: saveSlotButton.x,
y: saveSlotButton.y,
width: 320,
height: 80
});
saveSlotButtonBg.tint = 0x4CAF50;
saveMenu.addChild(saveSlotButtonBg);
saveMenu.addChild(saveSlotButton);
// Save slot status text
var saveSlotStatus = new Text2(hasSlotData(slotNum) ? 'HAS DATA' : 'EMPTY', {
size: 30,
fill: hasSlotData(slotNum) ? 0x00aa00 : 0xaaaaaa
});
saveSlotStatus.anchor.set(0.5, 0.5);
saveSlotStatus.x = saveSlotButton.x;
saveSlotStatus.y = saveSlotButton.y - 40;
saveMenu.addChild(saveSlotStatus);
// Load slot button
var loadSlotButton = new Text2('LOAD', {
size: 40,
fill: 0xffffff
});
loadSlotButton.anchor.set(0.5, 0.5);
loadSlotButton.x = saveSlotButton.x;
loadSlotButton.y = saveSlotButton.y + 150;
loadSlotButton.slotNumber = slotNum;
var loadSlotButtonBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: loadSlotButton.x,
y: loadSlotButton.y,
width: 260,
height: 70
});
loadSlotButtonBg.tint = hasSlotData(slotNum) ? 0x2196F3 : 0x666666;
saveMenu.addChild(loadSlotButtonBg);
saveMenu.addChild(loadSlotButton);
// Store references for updating
saveSlots.push({
saveButton: saveSlotButton,
saveButtonBg: saveSlotButtonBg,
statusText: saveSlotStatus,
loadButton: loadSlotButton,
loadButtonBg: loadSlotButtonBg,
slotNumber: slotNum
});
// Save button click handler
saveSlotButton.down = function () {
var slotNum = this.slotNumber;
var gameData = saveGameData(slotNum);
// Update slot status
for (var i = 0; i < saveSlots.length; i++) {
if (saveSlots[i].slotNumber === slotNum) {
saveSlots[i].statusText.setText('HAS DATA');
saveSlots[i].statusText.fill = 0x00aa00;
saveSlots[i].loadButtonBg.tint = 0x2196F3;
break;
}
}
// Show confirmation
var confirmText = new Text2('Saved to Slot ' + slotNum + '!', {
size: 40,
fill: 0x00aa00
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = this.x;
confirmText.y = this.y + 140;
confirmText.alpha = 0;
saveMenu.addChild(confirmText);
tween(confirmText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(confirmText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
confirmText.destroy();
}
});
}, 1500);
}
});
};
// Load button click handler
loadSlotButton.down = function () {
var slotNum = this.slotNumber;
var loaded = loadGameData(slotNum);
if (loaded) {
// Show confirmation
var confirmText = new Text2('Loaded Slot ' + slotNum + '!', {
size: 40,
fill: 0x0066aa
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = this.x;
confirmText.y = this.y + 60;
confirmText.alpha = 0;
saveMenu.addChild(confirmText);
tween(confirmText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(confirmText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
confirmText.destroy();
saveMenu.visible = false;
gameRunning = true;
fruitsFrozen = false;
}
});
}, 1500);
}
});
} else {
// Show no save found message
var noSaveText = new Text2('Slot ' + slotNum + ' is empty!', {
size: 40,
fill: 0xaa0000
});
noSaveText.anchor.set(0.5, 0.5);
noSaveText.x = this.x;
noSaveText.y = this.y + 60;
noSaveText.alpha = 0;
saveMenu.addChild(noSaveText);
tween(noSaveText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(noSaveText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
noSaveText.destroy();
}
});
}, 1500);
}
});
}
};
}
// Add tutorial restart button to save menu
var tutorialRestartButton = new Text2('RESTART TUTORIAL', {
size: 50,
fill: 0xffffff
});
tutorialRestartButton.anchor.set(0.5, 0.5);
tutorialRestartButton.x = 2048 / 2 - 300;
tutorialRestartButton.y = 2732 / 2 + 350;
var tutorialRestartBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: tutorialRestartButton.x,
y: tutorialRestartButton.y,
width: 400,
height: 80
});
tutorialRestartBg.tint = 0x2196F3;
saveMenu.addChild(tutorialRestartBg);
saveMenu.addChild(tutorialRestartButton);
tutorialRestartButton.down = function () {
// Close save menu
saveMenu.visible = false;
// Restart tutorial
tutorialActive = true;
tutorialStep = 0;
storage.tutorialCompleted = false;
gameRunning = false;
fruitsFrozen = true;
showTutorialStep();
};
// Close button
var closeSaveMenuButton = new Text2('CLOSE', {
size: 60,
fill: 0xffffff
});
closeSaveMenuButton.anchor.set(0.5, 0.5);
closeSaveMenuButton.x = 2048 / 2 + 300;
closeSaveMenuButton.y = 2732 / 2 + 350;
var closeSaveMenuButtonBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: closeSaveMenuButton.x,
y: closeSaveMenuButton.y,
width: 200,
height: 80
});
closeSaveMenuButtonBg.tint = 0xf44336;
saveMenu.addChild(closeSaveMenuButtonBg);
saveMenu.addChild(closeSaveMenuButton);
closeSaveMenuButton.down = function () {
saveMenu.visible = false;
gameRunning = true;
fruitsFrozen = false;
};
// Show music menu at game start instead of auto-starting music
musicMenu.visible = true;
musicMenuVisible = true;
gameRunning = false;
fruitsFrozen = true;
// Move music menu to front
game.removeChild(musicMenu);
game.addChild(musicMenu);
// Hide music button initially
musicMenuButton.visible = false;
// Hide save button initially
saveMenuButton.visible = false;
// Music menu background
var musicMenuBg = LK.getAsset('container', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 1000,
height: 800
});
musicMenuBg.alpha = 0.95;
musicMenuBg.tint = 0xdddddd;
musicMenu.addChild(musicMenuBg);
// Music menu title
var musicMenuTitle = new Text2('Select Music Track', {
size: 80,
fill: 0x222222,
stroke: 0xffffff,
strokeThickness: 3
});
musicMenuTitle.anchor.set(0.5, 0);
musicMenuTitle.x = 2048 / 2;
musicMenuTitle.y = 2732 / 2 - 300;
musicMenu.addChild(musicMenuTitle);
// Create music selection buttons
var musicButtons = [];
for (var i = 0; i < musicTracks.length; i++) {
var musicButton = new Text2(musicNames[i], {
size: 60,
fill: 0x000000
});
musicButton.anchor.set(0.5, 0.5);
musicButton.x = 2048 / 2;
musicButton.y = 2732 / 2 - 150 + i * 100;
musicButton.musicIndex = i;
// Add click handler for each music button using closure to capture index
(function (index) {
musicButton.down = function (x, y, obj) {
// Update current music selection
currentMusicIndex = index;
storage.selectedMusic = currentMusicIndex;
// Stop current music and play selected track
LK.stopMusic();
LK.playMusic(musicTracks[currentMusicIndex]);
// Close menu
musicMenu.visible = false;
musicMenuVisible = false;
// Show music button now that a song has been picked
musicMenuButton.visible = true;
// Show save button now that a song has been picked
saveMenuButton.visible = true;
// Only start tutorial for new players who haven't completed it
if (!storage.tutorialCompleted) {
gameRunning = false;
fruitsFrozen = true;
LK.setTimeout(function () {
showTutorialStep();
}, 1000);
} else {
// For returning players, start the game immediately
gameRunning = true;
fruitsFrozen = false;
}
};
})(i);
musicButtons.push(musicButton);
musicMenu.addChild(musicButton);
}
// Music menu button click handler
musicMenuButton.down = function (x, y, obj) {
if (musicMenuVisible) {
musicMenu.visible = false;
musicMenuVisible = false;
gameRunning = true;
fruitsFrozen = false;
} else {
musicMenu.visible = true;
musicMenuVisible = true;
// Move music menu to front
game.removeChild(musicMenu);
game.addChild(musicMenu);
gameRunning = false;
fruitsFrozen = true;
}
};
// Save menu button click handler
saveMenuButton.down = function (x, y, obj) {
if (saveMenu.visible) {
saveMenu.visible = false;
gameRunning = true;
fruitsFrozen = false;
} else {
saveMenu.visible = true;
// Move save menu to front
game.removeChild(saveMenu);
game.addChild(saveMenu);
gameRunning = false;
fruitsFrozen = true;
}
};
// Event handlers
game.down = function (x, y, obj) {
if (!gameRunning || currentFruit || saveMenu.visible) {
return;
}
// Handle fruit mover mode
if (fruitMoverActive) {
var _loop = function _loop() {
fruit = fruits[i];
dx = x - fruit.x;
dy = y - fruit.y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= fruit.getRadius()) {
var bobUp = function bobUp() {
tween(nextFruitPreview, {
y: originalY - 15
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: bobDown
});
};
var bobDown = function bobDown() {
tween(nextFruitPreview, {
y: originalY + 15
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: bobUp
});
};
// Fruit clicked - delete it and set as next fruit
fruitMoverSelectedFruit = fruit;
nextFruitType = fruit.type;
// Remove fruit from game
for (j = fruits.length - 1; j >= 0; j--) {
if (fruits[j] === fruit) {
fruits[j].destroy();
fruits.splice(j, 1);
break;
}
}
// Update next fruit preview to show the deleted fruit type
if (nextFruitPreview) {
// Stop any existing tweens before destroying
tween.stop(nextFruitPreview);
nextFruitPreview.destroy();
}
fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
nextFruitPreview = LK.getAsset(fruitAssets[nextFruitType], {
anchorX: 0.5,
anchorY: 0.5
});
nextFruitPreview.x = 1700;
nextFruitPreview.y = 120;
game.addChild(nextFruitPreview);
// Position the label based on fruit size to ensure it's always visible
fruitRadius = fruitSizes[nextFruitType] / 2;
nextFruitLabel.x = nextFruitPreview.x - fruitRadius - 20; // 20px padding from fruit edge
// Add bobbing animation
originalY = nextFruitPreview.y;
bobUp();
// Reset all fruits to normal tint
for (k = 0; k < fruits.length; k++) {
tween(fruits[k], {
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeOut
});
}
// Deactivate fruit mover mode
fruitMoverActive = false;
fruitMoverSelectedFruit = null;
return {
v: void 0
};
}
},
fruit,
dx,
dy,
distance,
j,
fruitAssets,
fruitSizes,
fruitRadius,
originalY,
k,
_ret;
// Check if click is on a fruit
for (var i = 0; i < fruits.length; i++) {
_ret = _loop();
if (_ret) return _ret.v;
}
// If no fruit was clicked, cancel fruit mover mode
fruitMoverActive = false;
for (var m = 0; m < fruits.length; m++) {
tween(fruits[m], {
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeOut
});
}
return;
}
// Only allow spawning if the press is inside the container bounds
var radius = 0;
if (x >= containerX - containerWidth / 2 + radius && x <= containerX + containerWidth / 2 - radius && y >= containerY - containerHeight / 2 + radius && y <= containerY + containerHeight / 2 - radius) {
isDragging = true;
createPreviewFruit(x);
// Music now starts automatically at game load
// Play drop sound when starting to aim
LK.getSound('drop').play();
// Progress tutorial if on the last step (first fruit drop)
if (tutorialActive && tutorialStep === tutorialSteps.length - 1) {
completeTutorial();
}
}
};
game.move = function (x, y, obj) {
if (!gameRunning || !isDragging || saveMenu.visible) {
return;
}
updatePreviewFruit(x);
};
game.up = function (x, y, obj) {
if (!gameRunning || !isDragging || saveMenu.visible) {
return;
}
isDragging = false;
var dropX = previewFruit ? previewFruit.x : x;
destroyPreviewFruit();
dropFruit(dropX);
};
// Main game loop
game.update = function () {
if (!gameRunning) {
return;
}
// Update all fruits
if (!fruitsFrozen) {
for (var i = 0; i < fruits.length; i++) {
fruits[i].update();
}
}
// Check collisions and merges
for (var i = 0; i < fruits.length; i++) {
for (var j = i + 1; j < fruits.length; j++) {
var fruit1 = fruits[i];
var fruit2 = fruits[j];
if (fruit1.merged || fruit2.merged) {
continue;
}
if (checkCollision(fruit1, fruit2)) {
// Mark both fruits as having made contact
fruit1.contactMade = true;
fruit2.contactMade = true;
// Always apply physics first to prevent sticking
resolveFruitCollision(fruit1, fruit2);
// Then check for merge
var currentMerging = fruit1.type === fruit2.type;
if (!fruit1.lastMergeCheck && currentMerging) {
if (mergeFruits(fruit1, fruit2)) {
break; // Break out of inner loop as fruits array changed
}
}
fruit1.lastMergeCheck = currentMerging;
fruit2.lastMergeCheck = currentMerging;
} else {
fruit1.lastMergeCheck = false;
fruit2.lastMergeCheck = false;
}
}
}
// Check game over condition (disabled during fruit rain)
if (!fruitRainActive && checkGameOver() && LK.ticks % 60 === 0) {
// Check every second
gameRunning = false;
LK.showGameOver();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -29,11 +29,11 @@
// Gold mutation - 3% chance for any fruit to be gold
self.isGold = Math.random() < 0.03;
// Celestial mutation - 0.1% chance for any fruit to be celestial (super rare)
self.isCelestial = Math.random() < 0.001;
- var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate'];
- var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700];
- var fruitScores = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190];
+ var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
+ var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
+ var fruitScores = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231];
self.assetName = fruitAssets[type];
self.size = fruitSizes[type];
self.scoreValue = fruitScores[type];
var fruitGraphics = self.attachAsset(self.assetName, {
@@ -273,10 +273,10 @@
/****
* Game Code
****/
-// Attach blue background asset, ensure it's at the back
// Blue background asset (full screen)
+// Attach blue background asset, ensure it's at the back
var blueBg = game.attachAsset('blueBg', {
anchorX: 0,
anchorY: 0,
x: 0,
@@ -306,9 +306,9 @@
// Track which fruits have been discovered by the player
var discoveredFruits = storage.discoveredFruits || [];
// Initialize array if not in storage
if (discoveredFruits.length === 0) {
- for (var i = 0; i < 19; i++) {
+ for (var i = 0; i < 21; i++) {
discoveredFruits[i] = false;
}
}
// Container dimensions and position
@@ -429,9 +429,9 @@
// Save to storage
storage.discoveredFruits = discoveredFruits;
if (newlyDiscovered) {
// Show notification for unlocking new fruit
- var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate'];
+ var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var unlockedName = evoFruitNames[nextFruitType];
var notification = new Text2("You've unlocked " + unlockedName + "!", {
size: 90,
fill: 0x222222
@@ -476,9 +476,9 @@
function createPreviewFruit(x) {
if (previewFruit) {
previewFruit.destroy();
}
- var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate'];
+ var fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
previewFruit = LK.getAsset(fruitAssets[nextFruitType], {
anchorX: 0.5,
anchorY: 0.5
});
@@ -490,9 +490,9 @@
function updatePreviewFruit(x) {
if (!previewFruit) {
return;
}
- var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700];
+ var fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
var radius = fruitSizes[nextFruitType] / 2;
previewFruit.x = Math.max(containerX - containerWidth / 2 + radius, Math.min(x, containerX + containerWidth / 2 - radius));
}
function destroyPreviewFruit() {
@@ -571,19 +571,19 @@
function mergeFruits(fruit1, fruit2) {
if (fruit1.type !== fruit2.type || fruit1.merged || fruit2.merged) {
return false;
}
- if (fruit1.type >= 18) {
+ if (fruit1.type >= 20) {
return false;
- } // Can't merge pomegranate (highest fruit)
+ } // Can't merge cranberry (highest fruit)
// Mark the new fruit type as discovered
var newlyDiscovered = !discoveredFruits[fruit1.type + 1];
discoveredFruits[fruit1.type + 1] = true;
// Save to storage
storage.discoveredFruits = discoveredFruits;
if (newlyDiscovered) {
// Show notification for unlocking new fruit
- var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate'];
+ var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var unlockedName = evoFruitNames[fruit1.type + 1];
var notification = new Text2("You've unlocked " + unlockedName + "!", {
size: 90,
fill: 0x222222
@@ -1986,10 +1986,10 @@
evolutionTitle.x = 2048 / 2;
evolutionTitle.y = 2732 / 2 - 650;
evolutionMenu.addChild(evolutionTitle);
// Fruit evolution data
-var evoFruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate'];
-var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate'];
+var evoFruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
+var evoFruitNames = ['Cherry', 'Strawberry', 'Grape', 'Orange', 'Apple', 'Pear', 'Peach', 'Pineapple', 'Melon', 'Watermelon', 'Lemon', 'Coconut', 'Dragonfruit', 'Kiwi', 'Mango', 'Papaya', 'Durian', 'Blueberry', 'Pomegranate', 'Avocado', 'Cranberry'];
var evoFruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700];
// Draw fruits in a circle
var centerX = 2048 / 2;
var centerY = 2732 / 2 + 80;
@@ -2649,10 +2649,10 @@
// Stop any existing tweens before destroying
tween.stop(nextFruitPreview);
nextFruitPreview.destroy();
}
- fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate'];
- fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700];
+ fruitAssets = ['cherry', 'strawberry', 'grape', 'orange', 'apple', 'pear', 'peach', 'pineapple', 'melon', 'watermelon', 'lemon', 'coconut', 'dragon', 'kiwi', 'mango', 'papaya', 'durian', 'blueberry', 'pomegranate', 'avocado', 'cranberry'];
+ fruitSizes = [120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 520, 560, 600, 640, 580, 620, 660, 380, 700, 720, 340];
nextFruitPreview = LK.getAsset(fruitAssets[nextFruitType], {
anchorX: 0.5,
anchorY: 0.5
});
Apple with cute face. In-Game asset. 2d. High contrast. No shadows
Cherry with cute face. In-Game asset. 2d. High contrast. No shadows
Greyish blue square. In-Game asset. 2d. High contrast. No shadows
Grapes with a cute face. In-Game asset. 2d. High contrast. No shadows
Circle water melon with cute face. In-Game asset. 2d. High contrast. No shadows
Circle cantaloupe with cute face. In-Game asset. 2d. High contrast. No shadows
Pear with cute face. In-Game asset. 2d. High contrast. No shadows
Strawberry with cute face. In-Game asset. 2d. High contrast. No shadows
Peach with cute face. In-Game asset. 2d. High contrast. No shadows
Pineapple with cute face. In-Game asset. 2d. High contrast. No shadows
Dragon fruit with cute face. In-Game asset. 2d. High contrast. No shadows
Lemon with cute face. In-Game asset. 2d. High contrast. No shadows
Coconut with cute face. In-Game asset. 2d. High contrast. No shadows
Kiwi with cute face. In-Game asset. 2d. High contrast. No shadows
Durian with cute face. In-Game asset. 2d. High contrast. No shadows
Mango with cute face. In-Game asset. 2d. High contrast. No shadows
Papaya with cute face. In-Game asset. 2d. High contrast. No shadows
Arrow pointing down. In-Game asset. 2d. High contrast. No shadows
Shine. In-Game asset. 2d. High contrast. No shadows
Purple galaxy. In-Game asset. 2d. High contrast. No shadows
Blueberry with cute face. In-Game asset. 2d. High contrast. No shadows
Open pomegranate with cute face. In-Game asset. 2d. High contrast. No shadows
A cut in half avocado with cute face. In-Game asset. 2d. High contrast. No shadows
Cranberry’s with cute face. In-Game asset. 2d. High contrast. No shadows