/**** * 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