/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Basket class var Basket = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('basket', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Fruit class var Fruit = Container.expand(function () { var self = Container.call(this); // Fruit types: apple, banana, orange, grape, golden, bomb self.type = 'apple'; // default, will be set on creation self.speed = 6; // will be set on creation self.points = 1; // will be set on creation // Attach asset based on type self.setType = function (type) { self.type = type; if (self.asset) { self.removeChild(self.asset); } var assetId = ''; if (type === 'apple') assetId = 'fruit_apple';else if (type === 'banana') assetId = 'fruit_banana';else if (type === 'orange') assetId = 'fruit_orange';else if (type === 'grape') assetId = 'fruit_grape';else if (type === 'golden') assetId = 'fruit_golden';else if (type === 'bomb') assetId = 'bomb'; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ // Music // Sound effects // Basket // Bomb // Fruits // Game variables var basket = null; var fruits = []; var score = 0; var scoreTxt = null; var dragNode = null; var lastBasketX = 0; var gameSpeed = 1; var spawnInterval = 60; // ticks between spawns var ticksSinceLastSpawn = 0; var gameOver = false; // Only bombs will fall! var fruitTypes = [{ type: 'bomb', weight: 1, points: 0, speed: 13 }]; // Helper: always pick bomb function pickRandomFruitType() { return fruitTypes[0]; } // Helper: spawn a fruit as a meteor from left or right edge, moving diagonally function spawnFruit() { var fruitInfo = pickRandomFruitType(); var fruit = new Fruit(); fruit.setType(fruitInfo.type); fruit.points = fruitInfo.points; fruit.speed = fruitInfo.speed * gameSpeed; // Decide spawn side: 0 = left, 1 = right var side = Math.random() < 0.5 ? 0 : 1; // Spawn from higher up: Y between -200 and 400 var minY = -200; var maxY = 400; fruit.y = minY + Math.random() * (maxY - minY); // Set start and end X for diagonal movement var marginX = 80; if (side === 0) { // Spawn from left edge, move right fruit.x = -100; fruit.targetX = 2048 + 100; } else { // Spawn from right edge, move left fruit.x = 2048 + 100; fruit.targetX = -100; } // Save start/end for update fruit.startX = fruit.x; fruit.startY = fruit.y; fruit.endX = fruit.targetX; // Calculate how many frames it will take to cross the screen var dx = fruit.targetX - fruit.x; var dy = 2732 + 200 - fruit.y; // go off bottom var dist = Math.sqrt(dx * dx + dy * dy); fruit.framesToCross = dist / fruit.speed; fruit.frameCount = 0; // Override update for diagonal movement fruit.update = function () { this.frameCount++; var t = this.frameCount / this.framesToCross; if (t > 1) t = 1; // Linear interpolation this.x = this.startX + (this.endX - this.startX) * t; this.y = this.startY + (2732 + 200 - this.startY) * t; }; fruits.push(fruit); game.addChild(fruit); } // Score text scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Basket basket = new Basket(); basket.x = 1024; basket.y = 2732 - 120; game.addChild(basket); // Move handler for dragging basket function handleMove(x, y, obj) { if (dragNode) { // Clamp basket inside screen var halfW = basket.asset.width / 2; var minX = halfW; var maxX = 2048 - halfW; dragNode.x = Math.max(minX, Math.min(maxX, x)); } } game.move = handleMove; // Down handler: start dragging if touch is on basket or near bottom game.down = function (x, y, obj) { // Only allow drag if touch is near basket (bottom 400px) if (y > 2732 - 400) { dragNode = basket; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { dragNode = null; }; // Update function game.update = function () { if (gameOver) return; // Increase game speed as time passes (bombs get faster over time) if (!game.startTick) game.startTick = LK.ticks; var elapsedSeconds = (LK.ticks - game.startTick) / 60; gameSpeed = 1 + Math.min(1.5, elapsedSeconds * 0.07); // up to 2.5x after ~21s // Spawn fruits ticksSinceLastSpawn++; var interval = Math.max(18, Math.floor(spawnInterval / gameSpeed)); if (ticksSinceLastSpawn >= interval) { spawnFruit(); ticksSinceLastSpawn = 0; } // Update fruits for (var i = fruits.length - 1; i >= 0; i--) { var fruit = fruits[i]; fruit.update(); // Check for collision with basket if (fruit.intersects(basket)) { if (fruit.type === 'bomb') { // Bomb caught: game over LK.getSound('bomb').play(); LK.effects.flashScreen(0xff0000, 800); gameOver = true; LK.showGameOver(); return; } else { // Fruit caught if (fruit.type === 'golden') { LK.getSound('golden').play(); LK.effects.flashObject(basket, 0xffe700, 600); } else { LK.getSound('catch').play(); LK.effects.flashObject(basket, 0xffffff, 200); } score += fruit.points; LK.setScore(score); scoreTxt.setText(score); // Remove fruit fruit.destroy(); fruits.splice(i, 1); continue; } } // Missed fruit (not bomb): if it goes off screen (bottom or left/right) if (fruit.y > 2732 + 120 || fruit.x < -150 || fruit.x > 2048 + 150) { if (fruit.type !== 'bomb') { // Missed a fruit: game over LK.effects.flashScreen(0xff0000, 800); gameOver = true; LK.showGameOver(); return; } else { // Bomb missed: just remove fruit.destroy(); fruits.splice(i, 1); continue; } } } }; // Play background music LK.playMusic('bgmusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Basket class
var Basket = Container.expand(function () {
var self = Container.call(this);
self.asset = self.attachAsset('basket', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Fruit class
var Fruit = Container.expand(function () {
var self = Container.call(this);
// Fruit types: apple, banana, orange, grape, golden, bomb
self.type = 'apple'; // default, will be set on creation
self.speed = 6; // will be set on creation
self.points = 1; // will be set on creation
// Attach asset based on type
self.setType = function (type) {
self.type = type;
if (self.asset) {
self.removeChild(self.asset);
}
var assetId = '';
if (type === 'apple') assetId = 'fruit_apple';else if (type === 'banana') assetId = 'fruit_banana';else if (type === 'orange') assetId = 'fruit_orange';else if (type === 'grape') assetId = 'fruit_grape';else if (type === 'golden') assetId = 'fruit_golden';else if (type === 'bomb') assetId = 'bomb';
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Music
// Sound effects
// Basket
// Bomb
// Fruits
// Game variables
var basket = null;
var fruits = [];
var score = 0;
var scoreTxt = null;
var dragNode = null;
var lastBasketX = 0;
var gameSpeed = 1;
var spawnInterval = 60; // ticks between spawns
var ticksSinceLastSpawn = 0;
var gameOver = false;
// Only bombs will fall!
var fruitTypes = [{
type: 'bomb',
weight: 1,
points: 0,
speed: 13
}];
// Helper: always pick bomb
function pickRandomFruitType() {
return fruitTypes[0];
}
// Helper: spawn a fruit as a meteor from left or right edge, moving diagonally
function spawnFruit() {
var fruitInfo = pickRandomFruitType();
var fruit = new Fruit();
fruit.setType(fruitInfo.type);
fruit.points = fruitInfo.points;
fruit.speed = fruitInfo.speed * gameSpeed;
// Decide spawn side: 0 = left, 1 = right
var side = Math.random() < 0.5 ? 0 : 1;
// Spawn from higher up: Y between -200 and 400
var minY = -200;
var maxY = 400;
fruit.y = minY + Math.random() * (maxY - minY);
// Set start and end X for diagonal movement
var marginX = 80;
if (side === 0) {
// Spawn from left edge, move right
fruit.x = -100;
fruit.targetX = 2048 + 100;
} else {
// Spawn from right edge, move left
fruit.x = 2048 + 100;
fruit.targetX = -100;
}
// Save start/end for update
fruit.startX = fruit.x;
fruit.startY = fruit.y;
fruit.endX = fruit.targetX;
// Calculate how many frames it will take to cross the screen
var dx = fruit.targetX - fruit.x;
var dy = 2732 + 200 - fruit.y; // go off bottom
var dist = Math.sqrt(dx * dx + dy * dy);
fruit.framesToCross = dist / fruit.speed;
fruit.frameCount = 0;
// Override update for diagonal movement
fruit.update = function () {
this.frameCount++;
var t = this.frameCount / this.framesToCross;
if (t > 1) t = 1;
// Linear interpolation
this.x = this.startX + (this.endX - this.startX) * t;
this.y = this.startY + (2732 + 200 - this.startY) * t;
};
fruits.push(fruit);
game.addChild(fruit);
}
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Basket
basket = new Basket();
basket.x = 1024;
basket.y = 2732 - 120;
game.addChild(basket);
// Move handler for dragging basket
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp basket inside screen
var halfW = basket.asset.width / 2;
var minX = halfW;
var maxX = 2048 - halfW;
dragNode.x = Math.max(minX, Math.min(maxX, x));
}
}
game.move = handleMove;
// Down handler: start dragging if touch is on basket or near bottom
game.down = function (x, y, obj) {
// Only allow drag if touch is near basket (bottom 400px)
if (y > 2732 - 400) {
dragNode = basket;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Update function
game.update = function () {
if (gameOver) return;
// Increase game speed as time passes (bombs get faster over time)
if (!game.startTick) game.startTick = LK.ticks;
var elapsedSeconds = (LK.ticks - game.startTick) / 60;
gameSpeed = 1 + Math.min(1.5, elapsedSeconds * 0.07); // up to 2.5x after ~21s
// Spawn fruits
ticksSinceLastSpawn++;
var interval = Math.max(18, Math.floor(spawnInterval / gameSpeed));
if (ticksSinceLastSpawn >= interval) {
spawnFruit();
ticksSinceLastSpawn = 0;
}
// Update fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
fruit.update();
// Check for collision with basket
if (fruit.intersects(basket)) {
if (fruit.type === 'bomb') {
// Bomb caught: game over
LK.getSound('bomb').play();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
} else {
// Fruit caught
if (fruit.type === 'golden') {
LK.getSound('golden').play();
LK.effects.flashObject(basket, 0xffe700, 600);
} else {
LK.getSound('catch').play();
LK.effects.flashObject(basket, 0xffffff, 200);
}
score += fruit.points;
LK.setScore(score);
scoreTxt.setText(score);
// Remove fruit
fruit.destroy();
fruits.splice(i, 1);
continue;
}
}
// Missed fruit (not bomb): if it goes off screen (bottom or left/right)
if (fruit.y > 2732 + 120 || fruit.x < -150 || fruit.x > 2048 + 150) {
if (fruit.type !== 'bomb') {
// Missed a fruit: game over
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
} else {
// Bomb missed: just remove
fruit.destroy();
fruits.splice(i, 1);
continue;
}
}
}
};
// Play background music
LK.playMusic('bgmusic');