Code edit (12 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Fruit Basket Catch!
Initial prompt
Create a simple and interactive 2D game for children aged 5–10, where the player controls a basket at the bottom of the screen. The player should be able to move the basket left and right using arrow keys on keyboard (or touch/drag if on mobile). Gameplay Mechanics: • From the top of the screen, fruits (like apples, bananas, and strawberries) fall continuously. • Occasionally, rotten fruits or junk items (like rocks or boots) also fall. • The player’s goal is to catch the healthy fruits with the basket and avoid the bad items. Controls: • Use left and right arrow keys for desktop. • Use touch/drag left and right for mobile. Scoring Rules: • Catching a good fruit = +10 points • Catching a rotten fruit or junk = -5 points • Reaching 100 points levels up and increases fruit falling speed. Game Elements: • Add collision detection between the basket and falling objects. • When a good fruit touches the basket, increase score. • When a bad object touches the basket, decrease score. • Add a score counter at the top. Visuals & Audio: • Use colorful, cartoon-style graphics. • Background: blue sky with clouds, rainbow, and trees. • Fun and happy background music. Interface: • Show a “Start Game” screen with a play button. • Show current score on screen during play. • On “Game Over” (e.g. after catching 3 bad objects), show final score and a restart button. Game Title: “Fruit Basket Catch!”
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Basket class
var Basket = Container.expand(function () {
var self = Container.call(this);
var basketAsset = self.attachAsset('basket', {
anchorX: 0.5,
anchorY: 0.5
});
// For a little "catch" animation
self.bump = function () {
tween(self, {
scaleY: 0.85
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleY: 1
}, {
duration: 120,
easing: tween.easeIn
});
}
});
};
return self;
});
// Fruit/Junk falling object
var FallingItem = Container.expand(function () {
var self = Container.call(this);
// type: 'good', 'bad', 'junk'
self.itemType = 'good';
self.scoreValue = 1;
self.speed = 6;
self.assetId = 'fruit_apple';
// Attach asset
var itemAsset = self.attachAsset('fruit_apple', {
anchorX: 0.5,
anchorY: 0.5
});
// Set up item
self.setType = function (type, assetId, scoreValue, speed) {
self.itemType = type;
self.assetId = assetId;
self.scoreValue = scoreValue;
self.speed = speed;
// Remove old asset and attach new one
self.removeChild(itemAsset);
itemAsset = 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: 0x87ceeb // blue sky
});
/****
* Game Code
****/
// Music
// Sounds
// Background elements
// Basket
// Junk (bad)
// Rotten fruit (bad)
// Fruits (good)
// --- Background ---
var bgSky = LK.getAsset('bg_sky', {
x: 0,
y: 0,
anchorX: 0,
anchorY: 0
});
game.addChild(bgSky);
// Rainbow
var bgRainbow = LK.getAsset('bg_rainbow', {
x: 400,
y: 350,
anchorX: 0,
anchorY: 0
});
game.addChild(bgRainbow);
// Clouds
var bgCloud1 = LK.getAsset('bg_cloud', {
x: 200,
y: 200,
anchorX: 0,
anchorY: 0
});
var bgCloud2 = LK.getAsset('bg_cloud', {
x: 1200,
y: 150,
anchorX: 0,
anchorY: 0
});
var bgCloud3 = LK.getAsset('bg_cloud', {
x: 1700,
y: 300,
anchorX: 0,
anchorY: 0
});
game.addChild(bgCloud1);
game.addChild(bgCloud2);
game.addChild(bgCloud3);
// Trees (left/right)
var bgTreeL = LK.getAsset('bg_tree', {
x: 120,
y: 1800,
anchorX: 0.5,
anchorY: 1
});
var bgTrunkL = LK.getAsset('bg_trunk', {
x: 120,
y: 1800,
anchorX: 0.5,
anchorY: 1
});
var bgTreeR = LK.getAsset('bg_tree', {
x: 1928,
y: 1800,
anchorX: 0.5,
anchorY: 1
});
var bgTrunkR = LK.getAsset('bg_trunk', {
x: 1928,
y: 1800,
anchorX: 0.5,
anchorY: 1
});
game.addChild(bgTrunkL);
game.addChild(bgTreeL);
game.addChild(bgTrunkR);
game.addChild(bgTreeR);
// Grass
var bgGrass = LK.getAsset('bg_grass', {
x: 0,
y: 2432,
anchorX: 0,
anchorY: 0
});
game.addChild(bgGrass);
// --- Game Variables ---
var basket = new Basket();
game.addChild(basket);
basket.x = 2048 / 2;
basket.y = 2432 + 150 / 2 - 40; // On grass, above bottom
var fallingItems = [];
var score = 0;
var level = 1;
var badCaught = 0;
var maxBad = 3;
var spawnInterval = 60; // ticks between spawns, will decrease with level
var lastSpawnTick = 0;
// --- GUI ---
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var levelTxt = new Text2('Level 1', {
size: 70,
fill: "#fff"
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 120;
var badTxt = new Text2('Misses: 0/3', {
size: 70,
fill: "#fff"
});
badTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(badTxt);
badTxt.y = 200;
// --- Music ---
LK.playMusic('happy_music');
// --- Fruit/Junk spawn logic ---
var goodFruits = [{
asset: 'fruit_apple',
score: 1
}, {
asset: 'fruit_banana',
score: 1
}, {
asset: 'fruit_orange',
score: 1
}, {
asset: 'fruit_grape',
score: 1
}];
var badItems = [{
asset: 'fruit_rotten',
score: -1,
type: 'bad'
}, {
asset: 'junk_can',
score: -1,
type: 'junk'
}, {
asset: 'junk_bottle',
score: -1,
type: 'junk'
}];
// --- Touch/Drag Controls ---
var dragNode = null;
var dragOffsetX = 0;
// --- Move handler ---
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp basket within screen
var minX = basket.width / 2;
var maxX = 2048 - basket.width / 2;
dragNode.x = Math.max(minX, Math.min(maxX, x - dragOffsetX));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is on basket or near basket
var local = {
x: x,
y: y
};
var dx = Math.abs(local.x - basket.x);
var dy = Math.abs(local.y - basket.y);
if (dx < basket.width / 1.2 && dy < basket.height * 1.5) {
dragNode = basket;
dragOffsetX = x - basket.x;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// --- Helper: spawn a new falling item ---
function spawnFallingItem() {
var isGood = Math.random() < 0.7; // 70% good, 30% bad/junk
var item;
if (isGood) {
var fruit = goodFruits[Math.floor(Math.random() * goodFruits.length)];
item = new FallingItem();
item.setType('good', fruit.asset, fruit.score, 8 + level * 1.2);
} else {
var bad = badItems[Math.floor(Math.random() * badItems.length)];
item = new FallingItem();
item.setType(bad.type, bad.asset, bad.score, 8 + level * 1.2);
}
// Random X, avoid edges
var minX = 80 + item.width / 2;
var maxX = 2048 - 80 - item.width / 2;
item.x = minX + Math.random() * (maxX - minX);
item.y = -item.height / 2;
item.lastY = item.y;
item.lastIntersecting = false;
fallingItems.push(item);
game.addChild(item);
}
// --- Update GUI ---
function updateGUI() {
scoreTxt.setText(score);
levelTxt.setText('Level ' + level);
badTxt.setText('Misses: ' + badCaught + '/' + maxBad);
}
// --- Level up logic ---
function checkLevelUp() {
var nextLevel = 1 + Math.floor(score / 10);
if (nextLevel > level) {
level = nextLevel;
// Make game harder
spawnInterval = Math.max(20, 60 - (level - 1) * 6);
LK.getSound('levelup').play();
// Flash screen for level up
LK.effects.flashScreen(0x00ffcc, 600);
}
}
// --- Main update loop ---
game.update = function () {
// Spawn new items
if (LK.ticks - lastSpawnTick >= spawnInterval) {
spawnFallingItem();
lastSpawnTick = LK.ticks;
}
// Update falling items
for (var i = fallingItems.length - 1; i >= 0; i--) {
var item = fallingItems[i];
item.update();
// Off screen (bottom)
if (item.lastY < 2732 + item.height / 2 && item.y >= 2732 + item.height / 2) {
// Remove item
item.destroy();
fallingItems.splice(i, 1);
continue;
}
// Collision with basket
var intersecting = item.intersects(basket);
if (!item.lastIntersecting && intersecting) {
if (item.itemType === 'good') {
score += item.scoreValue;
LK.getSound('catch_good').play();
basket.bump();
} else {
badCaught += 1;
score = Math.max(0, score + item.scoreValue);
LK.getSound('catch_bad').play();
LK.effects.flashObject(basket, 0xff0000, 400);
}
updateGUI();
checkLevelUp();
item.destroy();
fallingItems.splice(i, 1);
// Game over if too many bad items
if (badCaught >= maxBad) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
continue;
}
item.lastY = item.y;
item.lastIntersecting = intersecting;
}
};
// --- Initial GUI update ---
updateGUI(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,339 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Basket class
+var Basket = Container.expand(function () {
+ var self = Container.call(this);
+ var basketAsset = self.attachAsset('basket', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For a little "catch" animation
+ self.bump = function () {
+ tween(self, {
+ scaleY: 0.85
+ }, {
+ duration: 80,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleY: 1
+ }, {
+ duration: 120,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ return self;
+});
+// Fruit/Junk falling object
+var FallingItem = Container.expand(function () {
+ var self = Container.call(this);
+ // type: 'good', 'bad', 'junk'
+ self.itemType = 'good';
+ self.scoreValue = 1;
+ self.speed = 6;
+ self.assetId = 'fruit_apple';
+ // Attach asset
+ var itemAsset = self.attachAsset('fruit_apple', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Set up item
+ self.setType = function (type, assetId, scoreValue, speed) {
+ self.itemType = type;
+ self.assetId = assetId;
+ self.scoreValue = scoreValue;
+ self.speed = speed;
+ // Remove old asset and attach new one
+ self.removeChild(itemAsset);
+ itemAsset = 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: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87ceeb // blue sky
+});
+
+/****
+* Game Code
+****/
+// Music
+// Sounds
+// Background elements
+// Basket
+// Junk (bad)
+// Rotten fruit (bad)
+// Fruits (good)
+// --- Background ---
+var bgSky = LK.getAsset('bg_sky', {
+ x: 0,
+ y: 0,
+ anchorX: 0,
+ anchorY: 0
+});
+game.addChild(bgSky);
+// Rainbow
+var bgRainbow = LK.getAsset('bg_rainbow', {
+ x: 400,
+ y: 350,
+ anchorX: 0,
+ anchorY: 0
+});
+game.addChild(bgRainbow);
+// Clouds
+var bgCloud1 = LK.getAsset('bg_cloud', {
+ x: 200,
+ y: 200,
+ anchorX: 0,
+ anchorY: 0
+});
+var bgCloud2 = LK.getAsset('bg_cloud', {
+ x: 1200,
+ y: 150,
+ anchorX: 0,
+ anchorY: 0
+});
+var bgCloud3 = LK.getAsset('bg_cloud', {
+ x: 1700,
+ y: 300,
+ anchorX: 0,
+ anchorY: 0
+});
+game.addChild(bgCloud1);
+game.addChild(bgCloud2);
+game.addChild(bgCloud3);
+// Trees (left/right)
+var bgTreeL = LK.getAsset('bg_tree', {
+ x: 120,
+ y: 1800,
+ anchorX: 0.5,
+ anchorY: 1
+});
+var bgTrunkL = LK.getAsset('bg_trunk', {
+ x: 120,
+ y: 1800,
+ anchorX: 0.5,
+ anchorY: 1
+});
+var bgTreeR = LK.getAsset('bg_tree', {
+ x: 1928,
+ y: 1800,
+ anchorX: 0.5,
+ anchorY: 1
+});
+var bgTrunkR = LK.getAsset('bg_trunk', {
+ x: 1928,
+ y: 1800,
+ anchorX: 0.5,
+ anchorY: 1
+});
+game.addChild(bgTrunkL);
+game.addChild(bgTreeL);
+game.addChild(bgTrunkR);
+game.addChild(bgTreeR);
+// Grass
+var bgGrass = LK.getAsset('bg_grass', {
+ x: 0,
+ y: 2432,
+ anchorX: 0,
+ anchorY: 0
+});
+game.addChild(bgGrass);
+// --- Game Variables ---
+var basket = new Basket();
+game.addChild(basket);
+basket.x = 2048 / 2;
+basket.y = 2432 + 150 / 2 - 40; // On grass, above bottom
+var fallingItems = [];
+var score = 0;
+var level = 1;
+var badCaught = 0;
+var maxBad = 3;
+var spawnInterval = 60; // ticks between spawns, will decrease with level
+var lastSpawnTick = 0;
+// --- GUI ---
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var levelTxt = new Text2('Level 1', {
+ size: 70,
+ fill: "#fff"
+});
+levelTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(levelTxt);
+levelTxt.y = 120;
+var badTxt = new Text2('Misses: 0/3', {
+ size: 70,
+ fill: "#fff"
+});
+badTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(badTxt);
+badTxt.y = 200;
+// --- Music ---
+LK.playMusic('happy_music');
+// --- Fruit/Junk spawn logic ---
+var goodFruits = [{
+ asset: 'fruit_apple',
+ score: 1
+}, {
+ asset: 'fruit_banana',
+ score: 1
+}, {
+ asset: 'fruit_orange',
+ score: 1
+}, {
+ asset: 'fruit_grape',
+ score: 1
+}];
+var badItems = [{
+ asset: 'fruit_rotten',
+ score: -1,
+ type: 'bad'
+}, {
+ asset: 'junk_can',
+ score: -1,
+ type: 'junk'
+}, {
+ asset: 'junk_bottle',
+ score: -1,
+ type: 'junk'
+}];
+// --- Touch/Drag Controls ---
+var dragNode = null;
+var dragOffsetX = 0;
+// --- Move handler ---
+function handleMove(x, y, obj) {
+ if (dragNode) {
+ // Clamp basket within screen
+ var minX = basket.width / 2;
+ var maxX = 2048 - basket.width / 2;
+ dragNode.x = Math.max(minX, Math.min(maxX, x - dragOffsetX));
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Only allow drag if touch is on basket or near basket
+ var local = {
+ x: x,
+ y: y
+ };
+ var dx = Math.abs(local.x - basket.x);
+ var dy = Math.abs(local.y - basket.y);
+ if (dx < basket.width / 1.2 && dy < basket.height * 1.5) {
+ dragNode = basket;
+ dragOffsetX = x - basket.x;
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// --- Helper: spawn a new falling item ---
+function spawnFallingItem() {
+ var isGood = Math.random() < 0.7; // 70% good, 30% bad/junk
+ var item;
+ if (isGood) {
+ var fruit = goodFruits[Math.floor(Math.random() * goodFruits.length)];
+ item = new FallingItem();
+ item.setType('good', fruit.asset, fruit.score, 8 + level * 1.2);
+ } else {
+ var bad = badItems[Math.floor(Math.random() * badItems.length)];
+ item = new FallingItem();
+ item.setType(bad.type, bad.asset, bad.score, 8 + level * 1.2);
+ }
+ // Random X, avoid edges
+ var minX = 80 + item.width / 2;
+ var maxX = 2048 - 80 - item.width / 2;
+ item.x = minX + Math.random() * (maxX - minX);
+ item.y = -item.height / 2;
+ item.lastY = item.y;
+ item.lastIntersecting = false;
+ fallingItems.push(item);
+ game.addChild(item);
+}
+// --- Update GUI ---
+function updateGUI() {
+ scoreTxt.setText(score);
+ levelTxt.setText('Level ' + level);
+ badTxt.setText('Misses: ' + badCaught + '/' + maxBad);
+}
+// --- Level up logic ---
+function checkLevelUp() {
+ var nextLevel = 1 + Math.floor(score / 10);
+ if (nextLevel > level) {
+ level = nextLevel;
+ // Make game harder
+ spawnInterval = Math.max(20, 60 - (level - 1) * 6);
+ LK.getSound('levelup').play();
+ // Flash screen for level up
+ LK.effects.flashScreen(0x00ffcc, 600);
+ }
+}
+// --- Main update loop ---
+game.update = function () {
+ // Spawn new items
+ if (LK.ticks - lastSpawnTick >= spawnInterval) {
+ spawnFallingItem();
+ lastSpawnTick = LK.ticks;
+ }
+ // Update falling items
+ for (var i = fallingItems.length - 1; i >= 0; i--) {
+ var item = fallingItems[i];
+ item.update();
+ // Off screen (bottom)
+ if (item.lastY < 2732 + item.height / 2 && item.y >= 2732 + item.height / 2) {
+ // Remove item
+ item.destroy();
+ fallingItems.splice(i, 1);
+ continue;
+ }
+ // Collision with basket
+ var intersecting = item.intersects(basket);
+ if (!item.lastIntersecting && intersecting) {
+ if (item.itemType === 'good') {
+ score += item.scoreValue;
+ LK.getSound('catch_good').play();
+ basket.bump();
+ } else {
+ badCaught += 1;
+ score = Math.max(0, score + item.scoreValue);
+ LK.getSound('catch_bad').play();
+ LK.effects.flashObject(basket, 0xff0000, 400);
+ }
+ updateGUI();
+ checkLevelUp();
+ item.destroy();
+ fallingItems.splice(i, 1);
+ // Game over if too many bad items
+ if (badCaught >= maxBad) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ return;
+ }
+ continue;
+ }
+ item.lastY = item.y;
+ item.lastIntersecting = intersecting;
+ }
+};
+// --- Initial GUI update ---
+updateGUI();
\ No newline at end of file