/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
leaderboard: []
});
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
self.sliced = false;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.isBomb = true;
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.sliced) {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += 0.03;
}
};
return self;
});
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'apple';
self.sliced = false;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
// Set points based on fruit type
switch (self.type) {
case 'apple':
self.points = 1;
break;
case 'orange':
self.points = 2;
break;
case 'watermelon':
self.points = 3;
break;
case 'golden_fruit':
self.points = 10;
break;
default:
self.points = 1;
}
var fruitGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.sliced) {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += 0.02;
}
};
return self;
});
var FruitParticle = Container.expand(function (color) {
var self = Container.call(this);
var particleGraphics = self.attachAsset('fruit_particle', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.tint = color || 0xff0000;
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = (Math.random() - 0.5) * 8 - 3;
self.gravity = 0.2;
self.life = 60;
self.update = function () {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.life--;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
var SliceEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('slice_effect', {
anchorX: 0.5,
anchorY: 0.5
});
// Auto-fade and destroy
tween(effectGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
var fruits = [];
var bombs = [];
var sliceEffects = [];
var fruitParticles = [];
var lives = 3;
var comboMultiplier = 1;
var spawnTimer = 0;
var difficultyLevel = 1;
var lastSliceTime = 0;
var isSlicing = false;
var slicePoints = [];
var gameStarted = true;
var playerNickname = 'Player';
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardScores = storage.leaderboardScores || [];
var leaderboardEntries = [];
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var livesTxt = new Text2('Lives: 3', {
size: 50,
fill: 0xFF4444
});
livesTxt.anchor.set(0, 0);
livesTxt.x = 150;
livesTxt.y = 50;
LK.gui.topLeft.addChild(livesTxt);
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFFF44
});
comboTxt.anchor.set(0.5, 0.5);
comboTxt.x = 1024;
comboTxt.y = 400;
LK.gui.center.addChild(comboTxt);
// Game UI is visible from start
scoreTxt.visible = true;
livesTxt.visible = true;
comboTxt.visible = true;
// Initialize leaderboard entries (but keep them hidden for now)
for (var i = 0; i < 10; i++) {
var entry = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
entry.anchor.set(0.5, 0);
entry.x = 1024;
entry.y = 200 + i * 50;
entry.visible = false; // Hidden by default
leaderboardEntries.push(entry);
LK.gui.center.addChild(entry);
}
function updateLeaderboard() {
// Create combined array for sorting
var combined = [];
for (var i = 0; i < leaderboardNames.length; i++) {
combined.push({
name: leaderboardNames[i],
score: leaderboardScores[i]
});
}
combined.sort(function (a, b) {
return b.score - a.score;
});
combined = combined.slice(0, 10); // Keep top 10
// Split back into separate arrays
leaderboardNames = [];
leaderboardScores = [];
for (var i = 0; i < combined.length; i++) {
leaderboardNames.push(combined[i].name);
leaderboardScores.push(combined[i].score);
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardScores = leaderboardScores;
for (var i = 0; i < leaderboardEntries.length; i++) {
if (i < leaderboardNames.length) {
leaderboardEntries[i].setText(i + 1 + '. ' + leaderboardNames[i] + ' - ' + leaderboardScores[i]);
} else {
leaderboardEntries[i].setText('');
}
}
}
function addToLeaderboard(name, score) {
leaderboardNames.push(name);
leaderboardScores.push(score);
updateLeaderboard();
}
function spawnFruit() {
var fruitTypes = ['apple', 'orange', 'watermelon'];
var selectedType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
// 5% chance for golden fruit
if (Math.random() < 0.05) {
selectedType = 'golden_fruit';
}
var fruit = new Fruit(selectedType);
fruit.x = Math.random() * 1800 + 124; // Random X position
fruit.y = 2732 + 100; // Start below screen
// Arc trajectory
fruit.velocityX = (Math.random() - 0.5) * 8;
fruit.velocityY = -(Math.random() * 12 + 25); // Reduced upward velocity
fruits.push(fruit);
game.addChild(fruit);
}
function spawnBomb() {
var bomb = new Bomb();
bomb.x = Math.random() * 1800 + 124;
bomb.y = 2732 + 100;
bomb.velocityX = (Math.random() - 0.5) * 6;
bomb.velocityY = -(Math.random() * 10 + 20);
bombs.push(bomb);
game.addChild(bomb);
}
function createSliceEffect(x, y, fruitType) {
var effect = new SliceEffect();
effect.x = x;
effect.y = y;
sliceEffects.push(effect);
game.addChild(effect);
// Create colored particles based on fruit type
var particleColor = 0xff0000; // Default red
switch (fruitType) {
case 'apple':
particleColor = 0xff0000; // Red
break;
case 'orange':
particleColor = 0xffa500; // Orange
break;
case 'watermelon':
particleColor = 0x00ff00; // Green
break;
case 'golden_fruit':
particleColor = 0xffd700; // Gold
break;
}
// Spawn multiple particles
for (var p = 0; p < 6; p++) {
var particle = new FruitParticle(particleColor);
particle.x = x + (Math.random() - 0.5) * 40;
particle.y = y + (Math.random() - 0.5) * 40;
fruitParticles.push(particle);
game.addChild(particle);
}
}
function checkSlice(x, y) {
var slicedCount = 0;
// Check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
if (!fruit.sliced) {
var distance = Math.sqrt((fruit.x - x) * (fruit.x - x) + (fruit.y - y) * (fruit.y - y));
if (distance < 80) {
fruit.sliced = true;
slicedCount++;
// Add score with combo multiplier
var points = fruit.points * comboMultiplier;
LK.setScore(LK.getScore() + points);
// Create slice effect with fruit type for colored particles
createSliceEffect(fruit.x, fruit.y, fruit.type);
// Remove fruit
fruit.destroy();
fruits.splice(i, 1);
// Play slice sound
LK.getSound('slice').play();
}
}
}
// Check bombs
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
if (!bomb.sliced) {
var distance = Math.sqrt((bomb.x - x) * (bomb.x - x) + (bomb.y - y) * (bomb.y - y));
if (distance < 80) {
bomb.sliced = true;
// Game over on bomb hit
addToLeaderboard(playerNickname, LK.getScore());
LK.getSound('bomb_hit').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
return slicedCount;
}
function updateCombo(slicedCount) {
if (slicedCount > 1) {
comboMultiplier = slicedCount;
comboTxt.setText('COMBO x' + comboMultiplier + '!');
// Flash combo text
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200
});
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
// Reset combo text after delay
LK.setTimeout(function () {
comboTxt.setText('');
}, 1500);
} else if (slicedCount === 1) {
comboMultiplier = 1;
}
}
game.down = function (x, y, obj) {
isSlicing = true;
slicePoints = [{
x: x,
y: y
}];
lastSliceTime = LK.ticks;
var slicedCount = checkSlice(x, y);
if (slicedCount > 0) {
updateCombo(slicedCount);
}
};
game.move = function (x, y, obj) {
if (isSlicing) {
slicePoints.push({
x: x,
y: y
});
// Create slice effect at cursor position
var cursorEffect = new SliceEffect();
cursorEffect.x = x;
cursorEffect.y = y;
sliceEffects.push(cursorEffect);
game.addChild(cursorEffect);
// Check slice along the path
var slicedCount = checkSlice(x, y);
if (slicedCount > 0) {
updateCombo(slicedCount);
}
}
};
game.up = function (x, y, obj) {
isSlicing = false;
slicePoints = [];
// Reset combo multiplier after a short delay
LK.setTimeout(function () {
comboMultiplier = 1;
}, 500);
};
game.update = function () {
spawnTimer++;
// Increase difficulty over time
difficultyLevel = Math.floor(LK.getScore() / 50) + 1;
var spawnRate = Math.max(60 - difficultyLevel * 5, 30);
// Spawn fruits
if (spawnTimer % spawnRate === 0) {
spawnFruit();
}
// Spawn bombs (more frequently)
if (spawnTimer % (spawnRate * 2) === 0 && Math.random() < 0.5) {
spawnBomb();
}
// Update and check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
// Check if fruit fell off screen (missed)
if (fruit.y > 2832 && !fruit.sliced) {
lives--;
livesTxt.setText('Lives: ' + lives);
if (lives <= 0) {
addToLeaderboard(playerNickname, LK.getScore());
LK.getSound('fruit_miss').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
fruit.destroy();
fruits.splice(i, 1);
LK.getSound('fruit_miss').play();
}
// Remove fruits that are completely off screen
else if (fruit.y > 2900 || fruit.x < -200 || fruit.x > 2248) {
fruit.destroy();
fruits.splice(i, 1);
}
}
// Update and cleanup bombs
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
if (bomb.y > 2900 || bomb.x < -200 || bomb.x > 2248) {
bomb.destroy();
bombs.splice(i, 1);
}
}
// Cleanup expired particles
for (var i = fruitParticles.length - 1; i >= 0; i--) {
var particle = fruitParticles[i];
if (particle.life <= 0) {
particle.destroy();
fruitParticles.splice(i, 1);
}
}
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
leaderboard: []
});
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
self.sliced = false;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.isBomb = true;
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.sliced) {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += 0.03;
}
};
return self;
});
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'apple';
self.sliced = false;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
// Set points based on fruit type
switch (self.type) {
case 'apple':
self.points = 1;
break;
case 'orange':
self.points = 2;
break;
case 'watermelon':
self.points = 3;
break;
case 'golden_fruit':
self.points = 10;
break;
default:
self.points = 1;
}
var fruitGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!self.sliced) {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += 0.02;
}
};
return self;
});
var FruitParticle = Container.expand(function (color) {
var self = Container.call(this);
var particleGraphics = self.attachAsset('fruit_particle', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.tint = color || 0xff0000;
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = (Math.random() - 0.5) * 8 - 3;
self.gravity = 0.2;
self.life = 60;
self.update = function () {
self.velocityY += self.gravity;
self.x += self.velocityX;
self.y += self.velocityY;
self.life--;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
var SliceEffect = Container.expand(function () {
var self = Container.call(this);
var effectGraphics = self.attachAsset('slice_effect', {
anchorX: 0.5,
anchorY: 0.5
});
// Auto-fade and destroy
tween(effectGraphics, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
var fruits = [];
var bombs = [];
var sliceEffects = [];
var fruitParticles = [];
var lives = 3;
var comboMultiplier = 1;
var spawnTimer = 0;
var difficultyLevel = 1;
var lastSliceTime = 0;
var isSlicing = false;
var slicePoints = [];
var gameStarted = true;
var playerNickname = 'Player';
var leaderboardNames = storage.leaderboardNames || [];
var leaderboardScores = storage.leaderboardScores || [];
var leaderboardEntries = [];
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var livesTxt = new Text2('Lives: 3', {
size: 50,
fill: 0xFF4444
});
livesTxt.anchor.set(0, 0);
livesTxt.x = 150;
livesTxt.y = 50;
LK.gui.topLeft.addChild(livesTxt);
var comboTxt = new Text2('', {
size: 80,
fill: 0xFFFF44
});
comboTxt.anchor.set(0.5, 0.5);
comboTxt.x = 1024;
comboTxt.y = 400;
LK.gui.center.addChild(comboTxt);
// Game UI is visible from start
scoreTxt.visible = true;
livesTxt.visible = true;
comboTxt.visible = true;
// Initialize leaderboard entries (but keep them hidden for now)
for (var i = 0; i < 10; i++) {
var entry = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
entry.anchor.set(0.5, 0);
entry.x = 1024;
entry.y = 200 + i * 50;
entry.visible = false; // Hidden by default
leaderboardEntries.push(entry);
LK.gui.center.addChild(entry);
}
function updateLeaderboard() {
// Create combined array for sorting
var combined = [];
for (var i = 0; i < leaderboardNames.length; i++) {
combined.push({
name: leaderboardNames[i],
score: leaderboardScores[i]
});
}
combined.sort(function (a, b) {
return b.score - a.score;
});
combined = combined.slice(0, 10); // Keep top 10
// Split back into separate arrays
leaderboardNames = [];
leaderboardScores = [];
for (var i = 0; i < combined.length; i++) {
leaderboardNames.push(combined[i].name);
leaderboardScores.push(combined[i].score);
}
storage.leaderboardNames = leaderboardNames;
storage.leaderboardScores = leaderboardScores;
for (var i = 0; i < leaderboardEntries.length; i++) {
if (i < leaderboardNames.length) {
leaderboardEntries[i].setText(i + 1 + '. ' + leaderboardNames[i] + ' - ' + leaderboardScores[i]);
} else {
leaderboardEntries[i].setText('');
}
}
}
function addToLeaderboard(name, score) {
leaderboardNames.push(name);
leaderboardScores.push(score);
updateLeaderboard();
}
function spawnFruit() {
var fruitTypes = ['apple', 'orange', 'watermelon'];
var selectedType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
// 5% chance for golden fruit
if (Math.random() < 0.05) {
selectedType = 'golden_fruit';
}
var fruit = new Fruit(selectedType);
fruit.x = Math.random() * 1800 + 124; // Random X position
fruit.y = 2732 + 100; // Start below screen
// Arc trajectory
fruit.velocityX = (Math.random() - 0.5) * 8;
fruit.velocityY = -(Math.random() * 12 + 25); // Reduced upward velocity
fruits.push(fruit);
game.addChild(fruit);
}
function spawnBomb() {
var bomb = new Bomb();
bomb.x = Math.random() * 1800 + 124;
bomb.y = 2732 + 100;
bomb.velocityX = (Math.random() - 0.5) * 6;
bomb.velocityY = -(Math.random() * 10 + 20);
bombs.push(bomb);
game.addChild(bomb);
}
function createSliceEffect(x, y, fruitType) {
var effect = new SliceEffect();
effect.x = x;
effect.y = y;
sliceEffects.push(effect);
game.addChild(effect);
// Create colored particles based on fruit type
var particleColor = 0xff0000; // Default red
switch (fruitType) {
case 'apple':
particleColor = 0xff0000; // Red
break;
case 'orange':
particleColor = 0xffa500; // Orange
break;
case 'watermelon':
particleColor = 0x00ff00; // Green
break;
case 'golden_fruit':
particleColor = 0xffd700; // Gold
break;
}
// Spawn multiple particles
for (var p = 0; p < 6; p++) {
var particle = new FruitParticle(particleColor);
particle.x = x + (Math.random() - 0.5) * 40;
particle.y = y + (Math.random() - 0.5) * 40;
fruitParticles.push(particle);
game.addChild(particle);
}
}
function checkSlice(x, y) {
var slicedCount = 0;
// Check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
if (!fruit.sliced) {
var distance = Math.sqrt((fruit.x - x) * (fruit.x - x) + (fruit.y - y) * (fruit.y - y));
if (distance < 80) {
fruit.sliced = true;
slicedCount++;
// Add score with combo multiplier
var points = fruit.points * comboMultiplier;
LK.setScore(LK.getScore() + points);
// Create slice effect with fruit type for colored particles
createSliceEffect(fruit.x, fruit.y, fruit.type);
// Remove fruit
fruit.destroy();
fruits.splice(i, 1);
// Play slice sound
LK.getSound('slice').play();
}
}
}
// Check bombs
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
if (!bomb.sliced) {
var distance = Math.sqrt((bomb.x - x) * (bomb.x - x) + (bomb.y - y) * (bomb.y - y));
if (distance < 80) {
bomb.sliced = true;
// Game over on bomb hit
addToLeaderboard(playerNickname, LK.getScore());
LK.getSound('bomb_hit').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
return slicedCount;
}
function updateCombo(slicedCount) {
if (slicedCount > 1) {
comboMultiplier = slicedCount;
comboTxt.setText('COMBO x' + comboMultiplier + '!');
// Flash combo text
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200
});
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
// Reset combo text after delay
LK.setTimeout(function () {
comboTxt.setText('');
}, 1500);
} else if (slicedCount === 1) {
comboMultiplier = 1;
}
}
game.down = function (x, y, obj) {
isSlicing = true;
slicePoints = [{
x: x,
y: y
}];
lastSliceTime = LK.ticks;
var slicedCount = checkSlice(x, y);
if (slicedCount > 0) {
updateCombo(slicedCount);
}
};
game.move = function (x, y, obj) {
if (isSlicing) {
slicePoints.push({
x: x,
y: y
});
// Create slice effect at cursor position
var cursorEffect = new SliceEffect();
cursorEffect.x = x;
cursorEffect.y = y;
sliceEffects.push(cursorEffect);
game.addChild(cursorEffect);
// Check slice along the path
var slicedCount = checkSlice(x, y);
if (slicedCount > 0) {
updateCombo(slicedCount);
}
}
};
game.up = function (x, y, obj) {
isSlicing = false;
slicePoints = [];
// Reset combo multiplier after a short delay
LK.setTimeout(function () {
comboMultiplier = 1;
}, 500);
};
game.update = function () {
spawnTimer++;
// Increase difficulty over time
difficultyLevel = Math.floor(LK.getScore() / 50) + 1;
var spawnRate = Math.max(60 - difficultyLevel * 5, 30);
// Spawn fruits
if (spawnTimer % spawnRate === 0) {
spawnFruit();
}
// Spawn bombs (more frequently)
if (spawnTimer % (spawnRate * 2) === 0 && Math.random() < 0.5) {
spawnBomb();
}
// Update and check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
// Check if fruit fell off screen (missed)
if (fruit.y > 2832 && !fruit.sliced) {
lives--;
livesTxt.setText('Lives: ' + lives);
if (lives <= 0) {
addToLeaderboard(playerNickname, LK.getScore());
LK.getSound('fruit_miss').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
fruit.destroy();
fruits.splice(i, 1);
LK.getSound('fruit_miss').play();
}
// Remove fruits that are completely off screen
else if (fruit.y > 2900 || fruit.x < -200 || fruit.x > 2248) {
fruit.destroy();
fruits.splice(i, 1);
}
}
// Update and cleanup bombs
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
if (bomb.y > 2900 || bomb.x < -200 || bomb.x > 2248) {
bomb.destroy();
bombs.splice(i, 1);
}
}
// Cleanup expired particles
for (var i = fruitParticles.length - 1; i >= 0; i--) {
var particle = fruitParticles[i];
if (particle.life <= 0) {
particle.destroy();
fruitParticles.splice(i, 1);
}
}
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
};