/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Blade = Container.expand(function () {
var self = Container.call(this);
var bladeGraphics = self.attachAsset('blade', {
anchorX: 0.5,
anchorY: 0.5
});
bladeGraphics.alpha = 0; // Invisible until used
var trail = new Trail();
game.addChild(trail);
var active = false;
var lastX = 0;
var lastY = 0;
var velocity = 0;
self.activate = function (x, y) {
active = true;
self.x = x;
self.y = y;
lastX = x;
lastY = y;
bladeGraphics.alpha = 1;
};
self.deactivate = function () {
active = false;
bladeGraphics.alpha = 0;
trail.clear();
};
self.move = function (x, y) {
if (!active) return;
// Calculate angle based on movement direction
var dx = x - lastX;
var dy = y - lastY;
if (dx !== 0 || dy !== 0) {
self.rotation = Math.atan2(dy, dx) + Math.PI / 2;
// Calculate velocity for hit detection
velocity = Math.sqrt(dx * dx + dy * dy);
// Update blade position
self.x = x;
self.y = y;
// Add point to trail
trail.addPoint(x, y);
lastX = x;
lastY = y;
}
};
self.isActive = function () {
return active;
};
self.getVelocity = function () {
return velocity;
};
self.update = function () {
if (active) {
// Gradually decrease velocity when not moving
velocity *= 0.95;
}
trail.update();
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bombGraphics.width / 2;
self.velocity = {
x: Math.random() * 6 - 3,
y: 1 + Math.random() * 1.5
};
self.gravity = 0.06;
self.rotationSpeed = Math.random() * 0.1 - 0.05;
self.sliced = false;
self.update = function () {
if (self.sliced) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove bomb if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.slice = function () {
if (self.sliced) return false;
self.sliced = true;
// Create explosion
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8
});
game.addChild(explosion);
// Fade out explosion
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Fade out bomb
tween(bombGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('explode').play();
return true;
};
return self;
});
var Fruit = Container.expand(function () {
var self = Container.call(this);
var type = Math.floor(Math.random() * 3);
var colors = [0x00FF00, 0xFF8800, 0xFF0088]; // green, orange, pink
var fruitGraphics = self.attachAsset('fruit', {
anchorX: 0.5,
anchorY: 0.5
});
fruitGraphics.tint = colors[type];
self.radius = fruitGraphics.width / 2;
self.velocity = {
x: Math.random() * 6 - 3,
y: 1 + Math.random() * 1.5
};
self.gravity = 0.06;
self.rotationSpeed = Math.random() * 0.1 - 0.05;
self.sliced = false;
self.value = 1;
self.update = function () {
if (self.sliced) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove fruit if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.slice = function () {
if (self.sliced) return false;
self.sliced = true;
// Create juice splat
var splat = LK.getAsset('splat', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
});
splat.tint = fruitGraphics.tint;
splat.alpha = 0.7;
game.addChild(splat);
// Fade out splat
tween(splat, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
onFinish: function onFinish() {
splat.destroy();
}
});
// Create blood effect
for (var i = 0; i < 15; i++) {
var blood = LK.getAsset('blood', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.9
});
// Random blood color variation
blood.tint = 0xcc0000 - Math.floor(Math.random() * 0x330000);
game.addChild(blood);
// Randomize blood particle velocity and direction
var angle = Math.random() * Math.PI * 2;
var speed = 3 + Math.random() * 7;
var endX = self.x + Math.cos(angle) * speed * 20;
var endY = self.y + Math.sin(angle) * speed * 20;
// Animate blood particles
tween(blood, {
x: endX,
y: endY,
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 300 + Math.random() * 500,
easing: tween.easeOut,
onFinish: function () {
var b = blood;
return function () {
b.destroy();
};
}()
});
}
// Fade out fruit
tween(fruitGraphics, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('slice').play();
return true;
};
return self;
});
var PowerIndicator = Container.expand(function () {
var self = Container.call(this);
// Create container for power icon
var iconContainer = new Container();
self.addChild(iconContainer);
// Background for the power icon
var background = LK.getAsset('superPower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
iconContainer.addChild(background);
// Add glow effect
var glow = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6,
scaleX: 1.2,
scaleY: 1.2
});
iconContainer.addChild(glow);
// Move glow behind other elements by removing and adding it first
iconContainer.removeChild(glow);
iconContainer.addChildAt(glow, 0);
// Text instruction
var instructionText = new Text2("Press E to use", {
size: 30,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = background.height / 2 + 10;
self.addChild(instructionText);
// Make the power indicator invisible initially
self.visible = false;
// Animate the glow
tween(glow, {
alpha: 0.3,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 1000,
easing: tween.sineInOut,
loop: true,
yoyo: true
});
// Show the power indicator
self.show = function () {
self.visible = true;
self.scale.set(0);
// Animate appearance
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.backOut
});
};
// Hide the power indicator
self.hide = function () {
tween(self, {
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.backIn,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
var SuperPower = Container.expand(function () {
var self = Container.call(this);
var powerGraphics = self.attachAsset('superPower', {
anchorX: 0.5,
anchorY: 0.5
});
// Add glow effect around superpower
var glow = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
});
self.addChild(glow);
self.radius = powerGraphics.width / 2;
self.velocity = {
x: Math.random() * 4 - 2,
y: 2.5 + Math.random() * 1.5
};
self.gravity = 0.08;
self.rotationSpeed = Math.random() * 0.05 - 0.025;
self.collected = false;
// Animate the glow effect
tween(glow, {
alpha: 0.3,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.sineInOut,
loop: true,
yoyo: true
});
self.update = function () {
if (self.collected) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.collect = function () {
if (self.collected) return false;
self.collected = true;
// Create collection effect
for (var i = 0; i < 20; i++) {
var particle = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8,
scaleX: 0.2,
scaleY: 0.2
});
game.addChild(particle);
// Animate particles
var angle = Math.random() * Math.PI * 2;
var speed = 2 + Math.random() * 5;
var endX = self.x + Math.cos(angle) * speed * 20;
var endY = self.y + Math.sin(angle) * speed * 20;
tween(particle, {
x: endX,
y: endY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500 + Math.random() * 500,
easing: tween.easeOut,
onFinish: function () {
var p = particle;
return function () {
p.destroy();
};
}()
});
}
// Fade out power item
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return true;
};
return self;
});
var Trail = Container.expand(function () {
var self = Container.call(this);
var particles = [];
var lastPosition = null;
var activeTicks = 0;
var maxTicks = 10;
self.addPoint = function (x, y) {
activeTicks = maxTicks;
if (lastPosition) {
// Calculate distance between last point and new point
var dx = x - lastPosition.x;
var dy = y - lastPosition.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Add trail particles along the path
var numParticles = Math.min(Math.floor(distance / 10), 10);
for (var i = 0; i < numParticles; i++) {
var ratio = i / numParticles;
var px = lastPosition.x + dx * ratio;
var py = lastPosition.y + dy * ratio;
var particle = LK.getAsset('trail', {
anchorX: 0.5,
anchorY: 0.5,
x: px,
y: py,
alpha: 0.8
});
game.addChild(particle);
particles.push(particle);
// Animate particle fade out
tween(particle, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
onFinish: function () {
var p = particle;
return function () {
p.destroy();
var index = particles.indexOf(p);
if (index > -1) {
particles.splice(index, 1);
}
};
}()
});
}
}
lastPosition = {
x: x,
y: y
};
};
self.update = function () {
activeTicks--;
if (activeTicks <= 0) {
lastPosition = null;
}
};
self.clear = function () {
for (var i = 0; i < particles.length; i++) {
particles[i].destroy();
}
particles = [];
lastPosition = null;
activeTicks = 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Create background that covers the entire screen
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Game configuration
var spawnInterval = 1000; // ms between fruit spawns
var minSpawnInterval = 400; // Fastest spawn rate
var difficultyIncreaseRate = 50; // ms to decrease from spawn interval per wave
var bombProbability = 0.2; // Chance of spawning a bomb instead of fruit
var maxBombProbability = 0.3; // Maximum bomb probability
var comboTimeWindow = 300; // ms window for combo detection
var waveSize = 5; // Number of items per wave
var itemsInCurrentWave = 0;
var waveCount = 1;
var gameActive = false;
// Game objects
var fruits = [];
var bombs = [];
var superPowers = [];
var blade = new Blade();
var comboCounter = 0;
var comboTimeout = null;
var lastSliceTime = 0;
var superPowerActive = false;
var superPowerTimer = null;
var superPowerProbability = 0.05; // 5% chance to spawn super power
var powerCollected = false;
var powerIndicator = new PowerIndicator();
var keyboardEnabled = true;
// GUI Elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('', {
size: 100,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(comboTxt);
comboTxt.alpha = 0;
// Create hint text
var hintTxt = new Text2('Swipe to slice fruits!\nAvoid bombs!', {
size: 80,
fill: 0xFFFFFF
});
hintTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(hintTxt);
// Initialize game
game.addChild(blade);
// Add power indicator to top left (with some margin to avoid menu icon)
powerIndicator.x = 150;
powerIndicator.y = 150;
game.addChild(powerIndicator);
// Start spawning after a short delay
LK.setTimeout(function () {
gameActive = true;
spawnWave();
hintTxt.alpha = 0;
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
}, 1500);
// Spawn a wave of fruits/bombs
function spawnWave() {
if (!gameActive) return;
itemsInCurrentWave = 0;
// Spawn wave items with delay between each
var itemInterval = LK.setInterval(function () {
if (!gameActive) {
LK.clearInterval(itemInterval);
return;
}
spawnItem();
itemsInCurrentWave++;
if (itemsInCurrentWave >= waveSize) {
LK.clearInterval(itemInterval);
// Schedule next wave
LK.setTimeout(function () {
if (gameActive) {
waveCount++;
// Increase difficulty
spawnInterval = Math.max(minSpawnInterval, spawnInterval - difficultyIncreaseRate);
bombProbability = Math.min(maxBombProbability, bombProbability + 0.01);
spawnWave();
}
}, spawnInterval * 2);
}
}, spawnInterval / 2);
}
// Spawn a single fruit or bomb
function spawnItem() {
if (!gameActive) return;
var isSuperPower = Math.random() < superPowerProbability;
var isBomb = !isSuperPower && Math.random() < bombProbability;
var item;
if (isSuperPower) {
item = new SuperPower();
superPowers.push(item);
} else if (isBomb) {
item = new Bomb();
bombs.push(item);
} else {
item = new Fruit();
fruits.push(item);
}
// Position at top of screen with random x
item.x = Math.random() * (2048 - 200) + 100;
item.y = -item.radius;
game.addChild(item);
}
// Handle combo system
function handleCombo() {
// Clear existing combo timeout
if (comboTimeout !== null) {
LK.clearTimeout(comboTimeout);
}
comboCounter++;
// Display combo text if combo > 1
if (comboCounter > 1) {
var comboText = comboCounter + "x Combo!";
comboTxt.setText(comboText);
comboTxt.alpha = 1;
// Add combo bonus points
LK.setScore(LK.getScore() + comboCounter);
scoreTxt.setText(LK.getScore());
// Play combo sound if combo >= 3
if (comboCounter >= 3) {
LK.getSound('combo').play();
}
// Animate combo text
tween.stop(comboTxt);
comboTxt.scale.set(1.5);
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
}
// Set timeout to reset combo
comboTimeout = LK.setTimeout(function () {
comboCounter = 0;
tween(comboTxt, {
alpha: 0
}, {
duration: 300
});
}, comboTimeWindow);
}
// Check for slices
function checkSlices(x, y) {
if (!blade.isActive() || blade.getVelocity() < 3) return;
var sliced = false;
// Check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
var dx = fruit.x - x;
var dy = fruit.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < fruit.radius + 30) {
if (fruit.slice()) {
fruits.splice(i, 1);
LK.setScore(LK.getScore() + (superPowerActive ? 2 : 1)); // Double points during super power
scoreTxt.setText(LK.getScore());
// Handle combo system
var now = Date.now();
if (now - lastSliceTime < comboTimeWindow) {
handleCombo();
} else {
comboCounter = 0;
}
lastSliceTime = now;
sliced = true;
}
}
}
// Check bombs
for (var j = bombs.length - 1; j >= 0; j--) {
var bomb = bombs[j];
var bdx = bomb.x - x;
var bdy = bomb.y - y;
var bdistance = Math.sqrt(bdx * bdx + bdy * bdy);
if (bdistance < bomb.radius + 30) {
if (superPowerActive) {
// During super power, bombs are treated as fruits
if (bomb.slice()) {
bombs.splice(j, 1);
LK.setScore(LK.getScore() + 5); // Bonus points for "defusing" bombs
scoreTxt.setText(LK.getScore());
sliced = true;
}
} else if (bomb.slice()) {
bombs.splice(j, 1);
// Game over when bomb is sliced
gameActive = false;
// Flash screen red
LK.effects.flashScreen(0xff0000, 1000);
// Show game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
}
}
}
// Check super powers
for (var k = superPowers.length - 1; k >= 0; k--) {
var power = superPowers[k];
var pdx = power.x - x;
var pdy = power.y - y;
var pdistance = Math.sqrt(pdx * pdx + pdy * pdy);
if (pdistance < power.radius + 30) {
if (power.collect()) {
superPowers.splice(k, 1);
// Activate super power immediately when collected
activateSuperPower();
sliced = true;
}
}
}
return sliced;
}
// Activate super power mode
function activateSuperPower() {
// Clear existing super power timer if active
if (superPowerTimer !== null) {
LK.clearTimeout(superPowerTimer);
}
superPowerActive = true;
// Hide power indicator if it's visible
if (powerIndicator.visible) {
powerIndicator.hide();
}
// Flash screen blue for super power activation
LK.effects.flashScreen(0x00ffff, 500);
// Make blade bigger and blue during super power
blade.children[0].tint = 0x00ffff;
blade.children[0].scale.set(1.5);
// Show super power mode text
var superPowerTxt = new Text2("SUPER POWER!", {
size: 120,
fill: 0x00FFFF
});
superPowerTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(superPowerTxt);
// Animate super power text
tween(superPowerTxt, {
alpha: 0,
scaleX: 2,
scaleY: 2,
y: LK.gui.center.y - 200
}, {
duration: 1000,
onFinish: function onFinish() {
superPowerTxt.destroy();
}
});
// Set timeout to end super power
superPowerTimer = LK.setTimeout(function () {
superPowerActive = false;
powerCollected = false;
blade.children[0].tint = 0xFFFFFF;
blade.children[0].scale.set(1);
}, 10000); // 10 seconds of super power
}
// Game update loop
game.update = function () {
if (!gameActive) return;
// Update blade
blade.update();
// Update fruits
for (var i = fruits.length - 1; i >= 0; i--) {
fruits[i].update();
}
// Update bombs
for (var j = bombs.length - 1; j >= 0; j--) {
bombs[j].update();
}
// Update super powers
for (var k = superPowers.length - 1; k >= 0; k--) {
superPowers[k].update();
}
// If blade is active, check for collisions
if (blade.isActive()) {
checkSlices(blade.x, blade.y);
}
};
// Touch/mouse event handlers
game.down = function (x, y, obj) {
blade.activate(x, y);
};
game.move = function (x, y, obj) {
blade.move(x, y);
};
game.up = function (x, y, obj) {
blade.deactivate();
};
// Add keyboard listener for E key
LK.on('keydown', function (e) {
// Check if E key is pressed (key code 69) and super power is collected
if (e.keyCode === 69 && powerCollected && !superPowerActive && keyboardEnabled && gameActive) {
powerCollected = false;
powerIndicator.hide();
activateSuperPower();
}
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Blade = Container.expand(function () {
var self = Container.call(this);
var bladeGraphics = self.attachAsset('blade', {
anchorX: 0.5,
anchorY: 0.5
});
bladeGraphics.alpha = 0; // Invisible until used
var trail = new Trail();
game.addChild(trail);
var active = false;
var lastX = 0;
var lastY = 0;
var velocity = 0;
self.activate = function (x, y) {
active = true;
self.x = x;
self.y = y;
lastX = x;
lastY = y;
bladeGraphics.alpha = 1;
};
self.deactivate = function () {
active = false;
bladeGraphics.alpha = 0;
trail.clear();
};
self.move = function (x, y) {
if (!active) return;
// Calculate angle based on movement direction
var dx = x - lastX;
var dy = y - lastY;
if (dx !== 0 || dy !== 0) {
self.rotation = Math.atan2(dy, dx) + Math.PI / 2;
// Calculate velocity for hit detection
velocity = Math.sqrt(dx * dx + dy * dy);
// Update blade position
self.x = x;
self.y = y;
// Add point to trail
trail.addPoint(x, y);
lastX = x;
lastY = y;
}
};
self.isActive = function () {
return active;
};
self.getVelocity = function () {
return velocity;
};
self.update = function () {
if (active) {
// Gradually decrease velocity when not moving
velocity *= 0.95;
}
trail.update();
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bombGraphics.width / 2;
self.velocity = {
x: Math.random() * 6 - 3,
y: 1 + Math.random() * 1.5
};
self.gravity = 0.06;
self.rotationSpeed = Math.random() * 0.1 - 0.05;
self.sliced = false;
self.update = function () {
if (self.sliced) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove bomb if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.slice = function () {
if (self.sliced) return false;
self.sliced = true;
// Create explosion
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8
});
game.addChild(explosion);
// Fade out explosion
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Fade out bomb
tween(bombGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('explode').play();
return true;
};
return self;
});
var Fruit = Container.expand(function () {
var self = Container.call(this);
var type = Math.floor(Math.random() * 3);
var colors = [0x00FF00, 0xFF8800, 0xFF0088]; // green, orange, pink
var fruitGraphics = self.attachAsset('fruit', {
anchorX: 0.5,
anchorY: 0.5
});
fruitGraphics.tint = colors[type];
self.radius = fruitGraphics.width / 2;
self.velocity = {
x: Math.random() * 6 - 3,
y: 1 + Math.random() * 1.5
};
self.gravity = 0.06;
self.rotationSpeed = Math.random() * 0.1 - 0.05;
self.sliced = false;
self.value = 1;
self.update = function () {
if (self.sliced) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove fruit if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.slice = function () {
if (self.sliced) return false;
self.sliced = true;
// Create juice splat
var splat = LK.getAsset('splat', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
});
splat.tint = fruitGraphics.tint;
splat.alpha = 0.7;
game.addChild(splat);
// Fade out splat
tween(splat, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
onFinish: function onFinish() {
splat.destroy();
}
});
// Create blood effect
for (var i = 0; i < 15; i++) {
var blood = LK.getAsset('blood', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.9
});
// Random blood color variation
blood.tint = 0xcc0000 - Math.floor(Math.random() * 0x330000);
game.addChild(blood);
// Randomize blood particle velocity and direction
var angle = Math.random() * Math.PI * 2;
var speed = 3 + Math.random() * 7;
var endX = self.x + Math.cos(angle) * speed * 20;
var endY = self.y + Math.sin(angle) * speed * 20;
// Animate blood particles
tween(blood, {
x: endX,
y: endY,
alpha: 0,
scaleX: 0.3,
scaleY: 0.3
}, {
duration: 300 + Math.random() * 500,
easing: tween.easeOut,
onFinish: function () {
var b = blood;
return function () {
b.destroy();
};
}()
});
}
// Fade out fruit
tween(fruitGraphics, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('slice').play();
return true;
};
return self;
});
var PowerIndicator = Container.expand(function () {
var self = Container.call(this);
// Create container for power icon
var iconContainer = new Container();
self.addChild(iconContainer);
// Background for the power icon
var background = LK.getAsset('superPower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
iconContainer.addChild(background);
// Add glow effect
var glow = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6,
scaleX: 1.2,
scaleY: 1.2
});
iconContainer.addChild(glow);
// Move glow behind other elements by removing and adding it first
iconContainer.removeChild(glow);
iconContainer.addChildAt(glow, 0);
// Text instruction
var instructionText = new Text2("Press E to use", {
size: 30,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = background.height / 2 + 10;
self.addChild(instructionText);
// Make the power indicator invisible initially
self.visible = false;
// Animate the glow
tween(glow, {
alpha: 0.3,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 1000,
easing: tween.sineInOut,
loop: true,
yoyo: true
});
// Show the power indicator
self.show = function () {
self.visible = true;
self.scale.set(0);
// Animate appearance
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.backOut
});
};
// Hide the power indicator
self.hide = function () {
tween(self, {
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.backIn,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
var SuperPower = Container.expand(function () {
var self = Container.call(this);
var powerGraphics = self.attachAsset('superPower', {
anchorX: 0.5,
anchorY: 0.5
});
// Add glow effect around superpower
var glow = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
});
self.addChild(glow);
self.radius = powerGraphics.width / 2;
self.velocity = {
x: Math.random() * 4 - 2,
y: 2.5 + Math.random() * 1.5
};
self.gravity = 0.08;
self.rotationSpeed = Math.random() * 0.05 - 0.025;
self.collected = false;
// Animate the glow effect
tween(glow, {
alpha: 0.3,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.sineInOut,
loop: true,
yoyo: true
});
self.update = function () {
if (self.collected) return;
self.x += self.velocity.x;
self.y += self.velocity.y;
self.velocity.y += self.gravity;
self.rotation += self.rotationSpeed;
// Remove if it falls below screen
if (self.y > 2732 + self.radius) {
self.destroy();
}
};
self.collect = function () {
if (self.collected) return false;
self.collected = true;
// Create collection effect
for (var i = 0; i < 20; i++) {
var particle = LK.getAsset('superPowerGlow', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8,
scaleX: 0.2,
scaleY: 0.2
});
game.addChild(particle);
// Animate particles
var angle = Math.random() * Math.PI * 2;
var speed = 2 + Math.random() * 5;
var endX = self.x + Math.cos(angle) * speed * 20;
var endY = self.y + Math.sin(angle) * speed * 20;
tween(particle, {
x: endX,
y: endY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500 + Math.random() * 500,
easing: tween.easeOut,
onFinish: function () {
var p = particle;
return function () {
p.destroy();
};
}()
});
}
// Fade out power item
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return true;
};
return self;
});
var Trail = Container.expand(function () {
var self = Container.call(this);
var particles = [];
var lastPosition = null;
var activeTicks = 0;
var maxTicks = 10;
self.addPoint = function (x, y) {
activeTicks = maxTicks;
if (lastPosition) {
// Calculate distance between last point and new point
var dx = x - lastPosition.x;
var dy = y - lastPosition.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Add trail particles along the path
var numParticles = Math.min(Math.floor(distance / 10), 10);
for (var i = 0; i < numParticles; i++) {
var ratio = i / numParticles;
var px = lastPosition.x + dx * ratio;
var py = lastPosition.y + dy * ratio;
var particle = LK.getAsset('trail', {
anchorX: 0.5,
anchorY: 0.5,
x: px,
y: py,
alpha: 0.8
});
game.addChild(particle);
particles.push(particle);
// Animate particle fade out
tween(particle, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
onFinish: function () {
var p = particle;
return function () {
p.destroy();
var index = particles.indexOf(p);
if (index > -1) {
particles.splice(index, 1);
}
};
}()
});
}
}
lastPosition = {
x: x,
y: y
};
};
self.update = function () {
activeTicks--;
if (activeTicks <= 0) {
lastPosition = null;
}
};
self.clear = function () {
for (var i = 0; i < particles.length; i++) {
particles[i].destroy();
}
particles = [];
lastPosition = null;
activeTicks = 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Create background that covers the entire screen
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Game configuration
var spawnInterval = 1000; // ms between fruit spawns
var minSpawnInterval = 400; // Fastest spawn rate
var difficultyIncreaseRate = 50; // ms to decrease from spawn interval per wave
var bombProbability = 0.2; // Chance of spawning a bomb instead of fruit
var maxBombProbability = 0.3; // Maximum bomb probability
var comboTimeWindow = 300; // ms window for combo detection
var waveSize = 5; // Number of items per wave
var itemsInCurrentWave = 0;
var waveCount = 1;
var gameActive = false;
// Game objects
var fruits = [];
var bombs = [];
var superPowers = [];
var blade = new Blade();
var comboCounter = 0;
var comboTimeout = null;
var lastSliceTime = 0;
var superPowerActive = false;
var superPowerTimer = null;
var superPowerProbability = 0.05; // 5% chance to spawn super power
var powerCollected = false;
var powerIndicator = new PowerIndicator();
var keyboardEnabled = true;
// GUI Elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('', {
size: 100,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(comboTxt);
comboTxt.alpha = 0;
// Create hint text
var hintTxt = new Text2('Swipe to slice fruits!\nAvoid bombs!', {
size: 80,
fill: 0xFFFFFF
});
hintTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(hintTxt);
// Initialize game
game.addChild(blade);
// Add power indicator to top left (with some margin to avoid menu icon)
powerIndicator.x = 150;
powerIndicator.y = 150;
game.addChild(powerIndicator);
// Start spawning after a short delay
LK.setTimeout(function () {
gameActive = true;
spawnWave();
hintTxt.alpha = 0;
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
}, 1500);
// Spawn a wave of fruits/bombs
function spawnWave() {
if (!gameActive) return;
itemsInCurrentWave = 0;
// Spawn wave items with delay between each
var itemInterval = LK.setInterval(function () {
if (!gameActive) {
LK.clearInterval(itemInterval);
return;
}
spawnItem();
itemsInCurrentWave++;
if (itemsInCurrentWave >= waveSize) {
LK.clearInterval(itemInterval);
// Schedule next wave
LK.setTimeout(function () {
if (gameActive) {
waveCount++;
// Increase difficulty
spawnInterval = Math.max(minSpawnInterval, spawnInterval - difficultyIncreaseRate);
bombProbability = Math.min(maxBombProbability, bombProbability + 0.01);
spawnWave();
}
}, spawnInterval * 2);
}
}, spawnInterval / 2);
}
// Spawn a single fruit or bomb
function spawnItem() {
if (!gameActive) return;
var isSuperPower = Math.random() < superPowerProbability;
var isBomb = !isSuperPower && Math.random() < bombProbability;
var item;
if (isSuperPower) {
item = new SuperPower();
superPowers.push(item);
} else if (isBomb) {
item = new Bomb();
bombs.push(item);
} else {
item = new Fruit();
fruits.push(item);
}
// Position at top of screen with random x
item.x = Math.random() * (2048 - 200) + 100;
item.y = -item.radius;
game.addChild(item);
}
// Handle combo system
function handleCombo() {
// Clear existing combo timeout
if (comboTimeout !== null) {
LK.clearTimeout(comboTimeout);
}
comboCounter++;
// Display combo text if combo > 1
if (comboCounter > 1) {
var comboText = comboCounter + "x Combo!";
comboTxt.setText(comboText);
comboTxt.alpha = 1;
// Add combo bonus points
LK.setScore(LK.getScore() + comboCounter);
scoreTxt.setText(LK.getScore());
// Play combo sound if combo >= 3
if (comboCounter >= 3) {
LK.getSound('combo').play();
}
// Animate combo text
tween.stop(comboTxt);
comboTxt.scale.set(1.5);
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
}
// Set timeout to reset combo
comboTimeout = LK.setTimeout(function () {
comboCounter = 0;
tween(comboTxt, {
alpha: 0
}, {
duration: 300
});
}, comboTimeWindow);
}
// Check for slices
function checkSlices(x, y) {
if (!blade.isActive() || blade.getVelocity() < 3) return;
var sliced = false;
// Check fruits
for (var i = fruits.length - 1; i >= 0; i--) {
var fruit = fruits[i];
var dx = fruit.x - x;
var dy = fruit.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < fruit.radius + 30) {
if (fruit.slice()) {
fruits.splice(i, 1);
LK.setScore(LK.getScore() + (superPowerActive ? 2 : 1)); // Double points during super power
scoreTxt.setText(LK.getScore());
// Handle combo system
var now = Date.now();
if (now - lastSliceTime < comboTimeWindow) {
handleCombo();
} else {
comboCounter = 0;
}
lastSliceTime = now;
sliced = true;
}
}
}
// Check bombs
for (var j = bombs.length - 1; j >= 0; j--) {
var bomb = bombs[j];
var bdx = bomb.x - x;
var bdy = bomb.y - y;
var bdistance = Math.sqrt(bdx * bdx + bdy * bdy);
if (bdistance < bomb.radius + 30) {
if (superPowerActive) {
// During super power, bombs are treated as fruits
if (bomb.slice()) {
bombs.splice(j, 1);
LK.setScore(LK.getScore() + 5); // Bonus points for "defusing" bombs
scoreTxt.setText(LK.getScore());
sliced = true;
}
} else if (bomb.slice()) {
bombs.splice(j, 1);
// Game over when bomb is sliced
gameActive = false;
// Flash screen red
LK.effects.flashScreen(0xff0000, 1000);
// Show game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
}
}
}
// Check super powers
for (var k = superPowers.length - 1; k >= 0; k--) {
var power = superPowers[k];
var pdx = power.x - x;
var pdy = power.y - y;
var pdistance = Math.sqrt(pdx * pdx + pdy * pdy);
if (pdistance < power.radius + 30) {
if (power.collect()) {
superPowers.splice(k, 1);
// Activate super power immediately when collected
activateSuperPower();
sliced = true;
}
}
}
return sliced;
}
// Activate super power mode
function activateSuperPower() {
// Clear existing super power timer if active
if (superPowerTimer !== null) {
LK.clearTimeout(superPowerTimer);
}
superPowerActive = true;
// Hide power indicator if it's visible
if (powerIndicator.visible) {
powerIndicator.hide();
}
// Flash screen blue for super power activation
LK.effects.flashScreen(0x00ffff, 500);
// Make blade bigger and blue during super power
blade.children[0].tint = 0x00ffff;
blade.children[0].scale.set(1.5);
// Show super power mode text
var superPowerTxt = new Text2("SUPER POWER!", {
size: 120,
fill: 0x00FFFF
});
superPowerTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(superPowerTxt);
// Animate super power text
tween(superPowerTxt, {
alpha: 0,
scaleX: 2,
scaleY: 2,
y: LK.gui.center.y - 200
}, {
duration: 1000,
onFinish: function onFinish() {
superPowerTxt.destroy();
}
});
// Set timeout to end super power
superPowerTimer = LK.setTimeout(function () {
superPowerActive = false;
powerCollected = false;
blade.children[0].tint = 0xFFFFFF;
blade.children[0].scale.set(1);
}, 10000); // 10 seconds of super power
}
// Game update loop
game.update = function () {
if (!gameActive) return;
// Update blade
blade.update();
// Update fruits
for (var i = fruits.length - 1; i >= 0; i--) {
fruits[i].update();
}
// Update bombs
for (var j = bombs.length - 1; j >= 0; j--) {
bombs[j].update();
}
// Update super powers
for (var k = superPowers.length - 1; k >= 0; k--) {
superPowers[k].update();
}
// If blade is active, check for collisions
if (blade.isActive()) {
checkSlices(blade.x, blade.y);
}
};
// Touch/mouse event handlers
game.down = function (x, y, obj) {
blade.activate(x, y);
};
game.move = function (x, y, obj) {
blade.move(x, y);
};
game.up = function (x, y, obj) {
blade.deactivate();
};
// Add keyboard listener for E key
LK.on('keydown', function (e) {
// Check if E key is pressed (key code 69) and super power is collected
if (e.keyCode === 69 && powerCollected && !superPowerActive && keyboardEnabled && gameActive) {
powerCollected = false;
powerIndicator.hide();
activateSuperPower();
}
});
A Katana City. In-Game asset. 2d. High contrast. No shadows
A Katana 2D. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A 2D Watermelon. In-Game asset. 2d. High contrast. No shadows
A 2D Banana. In-Game asset. 2d. High contrast. No shadows
A Bomb 2D. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A Super Blue Laser Ball 2D. In-Game asset. 2d. High contrast. No shadows
A Fire and Freeze Super Power 2D. In-Game asset. 2d. High contrast. No shadows