User prompt
Add background to the game with a new asset
User prompt
Let the bomb take our 3 lives, but let each fruit that falls on the ground take 1 life, and let the fruits go off the screen, put invisible barriers on the sides etc.
User prompt
Fruits are flying again, put a limit on it
Code edit (2 edits merged)
Please save this source code
User prompt
Make the size of the fruits bigger (adjust the collissons well) and make the fruits higher and fall slowly and make the life count visible using assets (3 hearts)
Code edit (4 edits merged)
Please save this source code
User prompt
V The fruits can go higher, the falling speed can be higher and when they hit the bomb they will not die instantly, they will have an explosion effect and then they will die. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Fruits and bombs come from the bottom, increase the rate of coming up
User prompt
Please fix the bug: 'Uncaught TypeError: dynamicAssets[t].push is not a function' in or related to this line: 'var sliceGraphics = self.attachAsset('slice', {' Line Number: 116
Code edit (1 edits merged)
Please save this source code
User prompt
Fruit Slash Frenzy
Initial prompt
Make a fruit ninja game with different fruits etc.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bomb = Container.expand(function () { var self = Container.call(this); self.isSliced = false; var bombGraphics = self.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5 }); // Random movement self.velocityX = (Math.random() - 0.5) * 8; self.velocityY = Math.random() * -20 - 10; self.gravity = 0.5; self.update = function () { if (self.isSliced) { return; } self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; // Limit maximum height - if bomb goes too high, start falling faster if (self.y < 500) { self.velocityY = Math.max(self.velocityY, 2); } // Add invisible barriers on the sides if (self.x < 100) { self.x = 100; self.velocityX = Math.abs(self.velocityX); // Bounce back } if (self.x > 1948) { self.x = 1948; self.velocityX = -Math.abs(self.velocityX); // Bounce back } }; self.slice = function () { if (self.isSliced) { return; } self.isSliced = true; LK.getSound('bomb').play(); // Explosion effect with tween tween(bombGraphics, { scaleX: 3, scaleY: 3, alpha: 0, tint: 0xff0000 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Take all 3 lives when bomb is sliced missedFruits = maxMisses; // Hide all hearts for (var h = 0; h < hearts.length; h++) { hearts[h].alpha = 0.3; } // Flash screen red and end game after explosion LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }); }; return self; }); var Fruit = Container.expand(function (type) { var self = Container.call(this); self.fruitType = type; self.isSliced = false; self.points = 10; // Different point values for different fruits if (type === 'apple') { self.points = 10; } else if (type === 'orange') { self.points = 15; } else if (type === 'banana') { self.points = 20; } else if (type === 'watermelon') { self.points = 30; } else if (type === 'strawberry') { self.points = 25; } var fruitGraphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); // Random rotation and movement self.rotationSpeed = (Math.random() - 0.5) * 0.2; self.velocityX = (Math.random() - 0.5) * 8; self.velocityY = Math.random() * -20 - 10; self.gravity = 0.3; self.update = function () { if (self.isSliced) { return; } self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; self.rotation += self.rotationSpeed; // Limit maximum height - if fruit goes too high, start falling faster if (self.y < 500) { self.velocityY = Math.max(self.velocityY, 2); } // Add invisible barriers on the sides if (self.x < 100) { self.x = 100; self.velocityX = Math.abs(self.velocityX); // Bounce back } if (self.x > 1948) { self.x = 1948; self.velocityX = -Math.abs(self.velocityX); // Bounce back } }; self.slice = function () { if (self.isSliced) { return; } self.isSliced = true; LK.getSound('slice').play(); // Add points and update combo var pointsEarned = self.points * comboMultiplier; LK.setScore(LK.getScore() + pointsEarned); comboCount++; comboMultiplier = Math.min(5, Math.floor(comboCount / 3) + 1); // Visual effect tween(fruitGraphics, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300 }); // Update score display scoreTxt.setText(LK.getScore()); comboTxt.setText('x' + comboMultiplier); }; return self; }); var SliceTrail = Container.expand(function () { var self = Container.call(this); var sliceGraphics = self.attachAsset('slicetrail', { anchorX: 0.5, anchorY: 0.5 }); sliceGraphics.alpha = 0.8; // Fade out over time tween(sliceGraphics, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); } }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Add background var background = game.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); var fruits = []; var bombs = []; var sliceTrails = []; var missedFruits = 0; var maxMisses = 3; var comboCount = 0; var comboMultiplier = 1; var gameSpeed = 1; var lastSliceX = 0; var lastSliceY = 0; var isSlicing = false; // UI Elements var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var comboTxt = new Text2('x1', { size: 60, fill: 0xFFFF00 }); comboTxt.anchor.set(1, 0); LK.gui.topRight.addChild(comboTxt); // Heart lives display var hearts = []; for (var h = 0; h < 3; h++) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); heart.x = 150 + h * 80; // Avoid platform menu, space hearts out heart.y = 80; hearts.push(heart); LK.gui.addChild(heart); } // Spawn timer var spawnTimer = 0; var spawnRate = 45; // frames between spawns (increased rate) // Game input handling game.down = function (x, y, obj) { isSlicing = true; lastSliceX = x; lastSliceY = y; }; game.move = function (x, y, obj) { if (!isSlicing) { return; } // Create slice trail var trail = new SliceTrail(); trail.x = x; trail.y = y; // Calculate angle between last position and current var dx = x - lastSliceX; var dy = y - lastSliceY; var angle = Math.atan2(dy, dx); trail.rotation = angle; game.addChild(trail); sliceTrails.push(trail); // Check for fruit/bomb slicing checkSlicing(lastSliceX, lastSliceY, x, y); lastSliceX = x; lastSliceY = y; }; game.up = function (x, y, obj) { isSlicing = false; // Reset combo if no slicing for a while LK.setTimeout(function () { if (!isSlicing) { comboCount = 0; comboMultiplier = 1; comboTxt.setText('x1'); } }, 1000); }; function checkSlicing(x1, y1, x2, y2) { // Check fruits for (var i = 0; i < fruits.length; i++) { var fruit = fruits[i]; if (fruit.isSliced) { continue; } // Simple line-circle intersection with bigger collision radius var fruitRadius = 100; // Bigger collision for larger fruits if (fruit.fruitType === 'watermelon') { fruitRadius = 200; // Extra large for watermelon } if (lineIntersectsCircle(x1, y1, x2, y2, fruit.x, fruit.y, fruitRadius)) { fruit.slice(); } } // Check bombs for (var i = 0; i < bombs.length; i++) { var bomb = bombs[i]; if (bomb.isSliced) { continue; } if (lineIntersectsCircle(x1, y1, x2, y2, bomb.x, bomb.y, 90)) { bomb.slice(); } } } function lineIntersectsCircle(x1, y1, x2, y2, cx, cy, radius) { var dx = x2 - x1; var dy = y2 - y1; var fx = x1 - cx; var fy = y1 - cy; var a = dx * dx + dy * dy; var b = 2 * (fx * dx + fy * dy); var c = fx * fx + fy * fy - radius * radius; var discriminant = b * b - 4 * a * c; if (discriminant < 0) { return false; } var sqrt = Math.sqrt(discriminant); var t1 = (-b - sqrt) / (2 * a); var t2 = (-b + sqrt) / (2 * a); return t1 >= 0 && t1 <= 1 || t2 >= 0 && t2 <= 1; } function spawnFruit() { var fruitTypes = ['apple', 'orange', 'banana', 'watermelon', 'strawberry']; var randomType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)]; var fruit = new Fruit(randomType); // Spawn from bottom of screen fruit.x = Math.random() * 2048; fruit.y = 2832; // Upward velocity to make fruits fly up much higher fruit.velocityY = Math.random() * -60 - 30; // Initialize lastY for tracking fruit.lastY = fruit.y; fruits.push(fruit); game.addChild(fruit); } function spawnBomb() { var bomb = new Bomb(); // Spawn from bottom of screen bomb.x = Math.random() * 2048; bomb.y = 2832; // Upward velocity to make bombs fly up much higher bomb.velocityY = Math.random() * -50 - 25; bombs.push(bomb); game.addChild(bomb); } game.update = function () { spawnTimer++; // Adjust spawn rate based on score gameSpeed = 1 + LK.getScore() / 1000; var adjustedSpawnRate = Math.max(30, spawnRate / gameSpeed); // Spawn fruits if (spawnTimer >= adjustedSpawnRate) { spawnTimer = 0; if (Math.random() < 0.1) { // 10% chance for bomb spawnBomb(); } else { spawnFruit(); } } // Update and clean up fruits for (var i = fruits.length - 1; i >= 0; i--) { var fruit = fruits[i]; // Check if fruit just hit the ground (transition from above to below ground level) if (fruit.lastY <= 2832 && fruit.y > 2832 && !fruit.isSliced) { missedFruits++; // Hide a heart when life is lost if (missedFruits <= hearts.length) { hearts[hearts.length - missedFruits].alpha = 0.3; // Dim the heart } if (missedFruits >= maxMisses) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } // Update lastY for next frame fruit.lastY = fruit.y; // Remove off-screen or sliced fruits if (fruit.y > 2900 || fruit.isSliced && fruit.alpha <= 0) { fruit.destroy(); fruits.splice(i, 1); } } // Update and clean up bombs for (var i = bombs.length - 1; i >= 0; i--) { var bomb = bombs[i]; // Remove off-screen bombs if (bomb.y > 2900) { bomb.destroy(); bombs.splice(i, 1); } } // Clean up slice trails for (var i = sliceTrails.length - 1; i >= 0; i--) { var trail = sliceTrails[i]; if (trail.alpha <= 0) { sliceTrails.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
self.isSliced = false;
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Random movement
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = Math.random() * -20 - 10;
self.gravity = 0.5;
self.update = function () {
if (self.isSliced) {
return;
}
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
// Limit maximum height - if bomb goes too high, start falling faster
if (self.y < 500) {
self.velocityY = Math.max(self.velocityY, 2);
}
// Add invisible barriers on the sides
if (self.x < 100) {
self.x = 100;
self.velocityX = Math.abs(self.velocityX); // Bounce back
}
if (self.x > 1948) {
self.x = 1948;
self.velocityX = -Math.abs(self.velocityX); // Bounce back
}
};
self.slice = function () {
if (self.isSliced) {
return;
}
self.isSliced = true;
LK.getSound('bomb').play();
// Explosion effect with tween
tween(bombGraphics, {
scaleX: 3,
scaleY: 3,
alpha: 0,
tint: 0xff0000
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Take all 3 lives when bomb is sliced
missedFruits = maxMisses;
// Hide all hearts
for (var h = 0; h < hearts.length; h++) {
hearts[h].alpha = 0.3;
}
// Flash screen red and end game after explosion
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
});
};
return self;
});
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
self.fruitType = type;
self.isSliced = false;
self.points = 10;
// Different point values for different fruits
if (type === 'apple') {
self.points = 10;
} else if (type === 'orange') {
self.points = 15;
} else if (type === 'banana') {
self.points = 20;
} else if (type === 'watermelon') {
self.points = 30;
} else if (type === 'strawberry') {
self.points = 25;
}
var fruitGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
// Random rotation and movement
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.velocityX = (Math.random() - 0.5) * 8;
self.velocityY = Math.random() * -20 - 10;
self.gravity = 0.3;
self.update = function () {
if (self.isSliced) {
return;
}
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityY += self.gravity;
self.rotation += self.rotationSpeed;
// Limit maximum height - if fruit goes too high, start falling faster
if (self.y < 500) {
self.velocityY = Math.max(self.velocityY, 2);
}
// Add invisible barriers on the sides
if (self.x < 100) {
self.x = 100;
self.velocityX = Math.abs(self.velocityX); // Bounce back
}
if (self.x > 1948) {
self.x = 1948;
self.velocityX = -Math.abs(self.velocityX); // Bounce back
}
};
self.slice = function () {
if (self.isSliced) {
return;
}
self.isSliced = true;
LK.getSound('slice').play();
// Add points and update combo
var pointsEarned = self.points * comboMultiplier;
LK.setScore(LK.getScore() + pointsEarned);
comboCount++;
comboMultiplier = Math.min(5, Math.floor(comboCount / 3) + 1);
// Visual effect
tween(fruitGraphics, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300
});
// Update score display
scoreTxt.setText(LK.getScore());
comboTxt.setText('x' + comboMultiplier);
};
return self;
});
var SliceTrail = Container.expand(function () {
var self = Container.call(this);
var sliceGraphics = self.attachAsset('slicetrail', {
anchorX: 0.5,
anchorY: 0.5
});
sliceGraphics.alpha = 0.8;
// Fade out over time
tween(sliceGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Add background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
var fruits = [];
var bombs = [];
var sliceTrails = [];
var missedFruits = 0;
var maxMisses = 3;
var comboCount = 0;
var comboMultiplier = 1;
var gameSpeed = 1;
var lastSliceX = 0;
var lastSliceY = 0;
var isSlicing = false;
// UI Elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('x1', {
size: 60,
fill: 0xFFFF00
});
comboTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(comboTxt);
// Heart lives display
var hearts = [];
for (var h = 0; h < 3; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = 150 + h * 80; // Avoid platform menu, space hearts out
heart.y = 80;
hearts.push(heart);
LK.gui.addChild(heart);
}
// Spawn timer
var spawnTimer = 0;
var spawnRate = 45; // frames between spawns (increased rate)
// Game input handling
game.down = function (x, y, obj) {
isSlicing = true;
lastSliceX = x;
lastSliceY = y;
};
game.move = function (x, y, obj) {
if (!isSlicing) {
return;
}
// Create slice trail
var trail = new SliceTrail();
trail.x = x;
trail.y = y;
// Calculate angle between last position and current
var dx = x - lastSliceX;
var dy = y - lastSliceY;
var angle = Math.atan2(dy, dx);
trail.rotation = angle;
game.addChild(trail);
sliceTrails.push(trail);
// Check for fruit/bomb slicing
checkSlicing(lastSliceX, lastSliceY, x, y);
lastSliceX = x;
lastSliceY = y;
};
game.up = function (x, y, obj) {
isSlicing = false;
// Reset combo if no slicing for a while
LK.setTimeout(function () {
if (!isSlicing) {
comboCount = 0;
comboMultiplier = 1;
comboTxt.setText('x1');
}
}, 1000);
};
function checkSlicing(x1, y1, x2, y2) {
// Check fruits
for (var i = 0; i < fruits.length; i++) {
var fruit = fruits[i];
if (fruit.isSliced) {
continue;
}
// Simple line-circle intersection with bigger collision radius
var fruitRadius = 100; // Bigger collision for larger fruits
if (fruit.fruitType === 'watermelon') {
fruitRadius = 200; // Extra large for watermelon
}
if (lineIntersectsCircle(x1, y1, x2, y2, fruit.x, fruit.y, fruitRadius)) {
fruit.slice();
}
}
// Check bombs
for (var i = 0; i < bombs.length; i++) {
var bomb = bombs[i];
if (bomb.isSliced) {
continue;
}
if (lineIntersectsCircle(x1, y1, x2, y2, bomb.x, bomb.y, 90)) {
bomb.slice();
}
}
}
function lineIntersectsCircle(x1, y1, x2, y2, cx, cy, radius) {
var dx = x2 - x1;
var dy = y2 - y1;
var fx = x1 - cx;
var fy = y1 - cy;
var a = dx * dx + dy * dy;
var b = 2 * (fx * dx + fy * dy);
var c = fx * fx + fy * fy - radius * radius;
var discriminant = b * b - 4 * a * c;
if (discriminant < 0) {
return false;
}
var sqrt = Math.sqrt(discriminant);
var t1 = (-b - sqrt) / (2 * a);
var t2 = (-b + sqrt) / (2 * a);
return t1 >= 0 && t1 <= 1 || t2 >= 0 && t2 <= 1;
}
function spawnFruit() {
var fruitTypes = ['apple', 'orange', 'banana', 'watermelon', 'strawberry'];
var randomType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
var fruit = new Fruit(randomType);
// Spawn from bottom of screen
fruit.x = Math.random() * 2048;
fruit.y = 2832;
// Upward velocity to make fruits fly up much higher
fruit.velocityY = Math.random() * -60 - 30;
// Initialize lastY for tracking
fruit.lastY = fruit.y;
fruits.push(fruit);
game.addChild(fruit);
}
function spawnBomb() {
var bomb = new Bomb();
// Spawn from bottom of screen
bomb.x = Math.random() * 2048;
bomb.y = 2832;
// Upward velocity to make bombs fly up much higher
bomb.velocityY = Math.random() * -50 - 25;
bombs.push(bomb);
game.addChild(bomb);
}
game.update = function () {
spawnTimer++;
// Adjust spawn rate based on score
gameSpeed = 1 + LK.getScore() / 1000;
var adjustedSpawnRate = Math.max(30, spawnRate / gameSpeed);
// Spawn fruits
if (spawnTimer >= adjustedSpawnRate) {
spawnTimer = 0;
if (Math.random() < 0.1) {
// 10% chance for bomb
spawnBomb();
} else {
spawnFruit();
}
}
// Update and clean up fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
// Check if fruit just hit the ground (transition from above to below ground level)
if (fruit.lastY <= 2832 && fruit.y > 2832 && !fruit.isSliced) {
missedFruits++;
// Hide a heart when life is lost
if (missedFruits <= hearts.length) {
hearts[hearts.length - missedFruits].alpha = 0.3; // Dim the heart
}
if (missedFruits >= maxMisses) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
// Update lastY for next frame
fruit.lastY = fruit.y;
// Remove off-screen or sliced fruits
if (fruit.y > 2900 || fruit.isSliced && fruit.alpha <= 0) {
fruit.destroy();
fruits.splice(i, 1);
}
}
// Update and clean up bombs
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
// Remove off-screen bombs
if (bomb.y > 2900) {
bomb.destroy();
bombs.splice(i, 1);
}
}
// Clean up slice trails
for (var i = sliceTrails.length - 1; i >= 0; i--) {
var trail = sliceTrails[i];
if (trail.alpha <= 0) {
sliceTrails.splice(i, 1);
}
}
};