/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { coins: 0, ownedSkins: ["Pencil"], currentSkin: "Pencil", hardcoreMode: false }); /**** * Classes ****/ var Fruit = Container.expand(function () { var self = Container.call(this); // Define fruit properties var fruitProperties = { 'Watermelon': { points: 1, speed: 15, scale: 6, rarity: 0.15 }, 'Orange': { points: 2, speed: 20, scale: 5, rarity: 0.2 }, 'Apple': { points: 2, speed: 20, scale: 5, rarity: 0.2 }, 'Banana': { points: 2, speed: 20, scale: 5, rarity: 0.15 }, 'pineapple': { points: 3, speed: 22, scale: 4.5, rarity: 0.1 }, 'sleeve': { points: 3, speed: 22, scale: 4.5, rarity: 0.1 }, 'Grapes': { points: 4, speed: 25, scale: 4, rarity: 0.05 }, 'Cherry': { points: 5, speed: 30, scale: 3, rarity: 0.05 } }; // Calculate weighted random selection var weightedSelection = function weightedSelection() { var rand = Math.random(); var cumulative = 0; for (var fruit in fruitProperties) { cumulative += fruitProperties[fruit].rarity; if (rand < cumulative) { return fruit; } } return 'Apple'; // Default fallback }; // Select fruit based on rarity var randomFruit = weightedSelection(); self.fruitType = randomFruit; self.pointValue = fruitProperties[randomFruit].points; // Attach the selected fruit image asset to the container var fruitGraphics = self.attachAsset(randomFruit, { anchorX: 0.5, anchorY: 0.5, scaleX: fruitProperties[randomFruit].scale, // Scale fruit based on type scaleY: fruitProperties[randomFruit].scale // Scale fruit based on type }); // Add value indicator for high-value fruits if (self.pointValue >= 3) { var glow = self.attachAsset('Light', { anchorX: 0.5, anchorY: 0.5, scaleX: fruitProperties[randomFruit].scale * 1.2, scaleY: fruitProperties[randomFruit].scale * 1.2, alpha: 0.3, tint: self.pointValue >= 4 ? 0xFFD700 : 0xC0C0C0 }); glow.zIndex = -1; } // Set initial position of the fruit in the middle of the screen self.x = 1024; // Center horizontally self.y = 1366; // Center vertically // Add update method to move the fruit left and right self.update = function () { // Move fruit left and right if (self.x <= 0 || self.x >= 2048) { self.speed = -self.speed; // Reverse direction when hitting screen edges } self.x += self.speed; // Dodge behavior in hardcore mode if (storage.hardcoreMode && !self.isDodging && pencil && pencil.isThrown) { // Check if pencil is getting close (within 400 pixels vertically) if (Math.abs(pencil.y - self.y) < 400 && pencil.y < self.y) { // 10% chance to dodge if (Math.random() < 0.1) { self.isDodging = true; // Calculate dodge direction based on pencil position var dodgeDirection = pencil.x < self.x ? 1 : -1; // Increase speed temporarily for dodge self.dodgeSpeed = self.speed; self.speed = Math.abs(self.speed) * 3 * dodgeDirection; // Reset dodge after a short time LK.setTimeout(function () { if (self && !self.destroyed) { self.speed = self.dodgeSpeed; self.isDodging = false; } }, 500); } } } }; // Set speed based on fruit type and hardcore mode var baseSpeed = fruitProperties[randomFruit].speed; if (storage.hardcoreMode) { // In hardcore mode, fruits are 2x faster baseSpeed *= 2; } self.speed = Math.random() < 0.5 ? baseSpeed : -baseSpeed; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); // Create small circular particle var particle = self.attachAsset('Light', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: Math.random() * 0xffffff }); // Random velocity self.vx = (Math.random() - 0.5) * 20; self.vy = (Math.random() - 0.5) * 20; self.gravity = 0.5; self.update = function () { self.x += self.vx; self.y += self.vy; self.vy += self.gravity; self.alpha -= 0.02; if (self.alpha <= 0) { self.shouldDestroy = true; } }; return self; }); var Pencil = Container.expand(function () { var self = Container.call(this); // Attach the pencil image asset to the container using selected skin var pencilGraphics = self.attachAsset(storage.currentSkin, { anchorX: 0.5, anchorY: 0.5 }); // Set initial position of the pencil self.x = 1024; // Center horizontally self.y = 0; // Position at the top of the screen // Add update method to move the pencil left and right self.update = function () { // Move pencil left and right if (self.x <= 0 || self.x >= 2048) { self.speed = -self.speed; // Reverse direction when hitting screen edges } self.x += self.speed; }; // In hardcore mode, pencil moves faster making it harder to aim self.speed = storage.hardcoreMode ? 25 : 15; // Initial speed of the pencil self.isThrown = false; // Track if pencil has been thrown // Add glow effect when pencil is ready var glow = self.attachAsset('Light', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, alpha: 0.3, tint: 0x00ff00 }); // Store reference to glow for later removal self.glow = glow; // Create manual pulsing animation since tween doesn't support loop/yoyo var pulseDirection = 1; var pulseUpdate = function pulseUpdate() { if (!self.isThrown && self.glow) { glow.alpha += 0.006 * pulseDirection; glow.scaleX += 0.01 * pulseDirection; glow.scaleY += 0.01 * pulseDirection; if (glow.alpha >= 0.6 || glow.alpha <= 0.3) { pulseDirection = -pulseDirection; } } }; // Store update function for removal self.pulseUpdate = pulseUpdate; // Add to pencil's update var originalUpdate = self.update; self.update = function () { originalUpdate.call(self); pulseUpdate(); }; }); var Settings = Container.expand(function () { var self = Container.call(this); // Settings background var bg = self.attachAsset('Bg_shop', { anchorX: 0.5, anchorY: 0.5, scaleX: 15, scaleY: 20, tint: 0x333333, alpha: 0.95 }); // Settings title var title = new Text2('SETTINGS', { size: 180, fill: 0xFFFFFF }); title.anchor.set(0.5, 0.5); title.x = 0; title.y = -600; self.addChild(title); // Close button var closeBtn = new Text2('X', { size: 150, fill: 0xFF0000 }); closeBtn.anchor.set(0.5, 0.5); closeBtn.x = 600; closeBtn.y = -600; self.addChild(closeBtn); closeBtn.interactive = true; closeBtn.down = function () { self.close(); }; // Hardcore mode toggle var hardcoreLabel = new Text2('Hardcore Mode', { size: 100, fill: 0xFFFFFF }); hardcoreLabel.anchor.set(0, 0.5); hardcoreLabel.x = -400; hardcoreLabel.y = -200; self.addChild(hardcoreLabel); // Toggle button var toggleBtn = new Text2(storage.hardcoreMode ? 'ON' : 'OFF', { size: 100, fill: storage.hardcoreMode ? 0x00FF00 : 0xFF0000 }); toggleBtn.anchor.set(0.5, 0.5); toggleBtn.x = 300; toggleBtn.y = -200; self.addChild(toggleBtn); toggleBtn.interactive = true; toggleBtn.down = function () { if (!storage.hardcoreMode) { // Show confirmation dialog self.showConfirmation(); } else { // Turn off hardcore mode storage.hardcoreMode = false; toggleBtn.setText('OFF'); toggleBtn.fill = 0xFF0000; } }; // Hardcore mode description var description = new Text2('Makes fruits much faster\nand harder to hit!', { size: 60, fill: 0xAAAAAA }); description.anchor.set(0.5, 0.5); description.x = 0; description.y = 0; self.addChild(description); self.showConfirmation = function () { // Create confirmation overlay var confirmOverlay = new Container(); var confirmBg = confirmOverlay.attachAsset('Bg_shop', { anchorX: 0.5, anchorY: 0.5, scaleX: 12, scaleY: 10, tint: 0x222222, alpha: 0.98 }); // Shocked emoji var emoji = confirmOverlay.attachAsset('Emoji_shocked', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, y: -200 }); // Confirmation text var confirmText = new Text2('Are you sure?', { size: 120, fill: 0xFFFFFF }); confirmText.anchor.set(0.5, 0.5); confirmText.y = 0; confirmOverlay.addChild(confirmText); // Yes button var yesBtn = new Text2('YES', { size: 100, fill: 0x00FF00 }); yesBtn.anchor.set(0.5, 0.5); yesBtn.x = -200; yesBtn.y = 200; confirmOverlay.addChild(yesBtn); yesBtn.interactive = true; yesBtn.down = function () { // Enable hardcore mode storage.hardcoreMode = true; toggleBtn.setText('ON'); toggleBtn.fill = 0x00FF00; confirmOverlay.destroy(); // Play alert sound LK.getSound('Alert').play(); }; // No button var noBtn = new Text2('NO', { size: 100, fill: 0xFF0000 }); noBtn.anchor.set(0.5, 0.5); noBtn.x = 200; noBtn.y = 200; confirmOverlay.addChild(noBtn); noBtn.interactive = true; noBtn.down = function () { confirmOverlay.destroy(); }; self.addChild(confirmOverlay); }; self.close = function () { self.parent.destroy(); settingsContainer = null; }; return self; }); var Shop = Container.expand(function () { var self = Container.call(this); // Shop background var bg = self.attachAsset('Bg_shop', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 20, tint: 0x222222, alpha: 0.95 }); // Shop title var title = new Text2('SHOP', { size: 200, fill: 0xFFFFFF }); title.anchor.set(0.5, 0.5); title.x = 0; title.y = -800; self.addChild(title); // Coins display self.coinsText = new Text2('Coins: ' + storage.coins, { size: 120, fill: 0xFFD700 }); self.coinsText.anchor.set(0.5, 0.5); self.coinsText.x = 0; self.coinsText.y = -600; self.addChild(self.coinsText); // Close button var closeBtn = new Text2('X', { size: 150, fill: 0xFF0000 }); closeBtn.anchor.set(0.5, 0.5); closeBtn.x = 800; closeBtn.y = -800; self.addChild(closeBtn); // Make close button interactive closeBtn.interactive = true; closeBtn.down = function () { self.close(); }; // Skin items var skins = [{ id: 'Pencil', name: 'Classic', price: 0 }, { id: 'Pencil_skin1', name: 'Pencil Picnic Mat', price: 50 }, { id: 'Pencil_skin2', name: 'Golden Pencil', price: 100 }, { id: 'Pencil_skin3', name: 'Wax Pencil', price: 150 }, { id: 'Pencil_skin4', name: 'Remote Control Pencil', price: 200 }, { id: 'Pencil_skin5', name: 'Pencil Case', price: 500 }]; // Create skin items skins.forEach(function (skin, index) { var yPos = -400 + index * 200; // Skin preview var skinPreview = self.attachAsset(skin.id, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.15, scaleY: 0.15, x: -600, y: yPos }); // Skin name var skinName = new Text2(skin.name, { size: 80, fill: 0xFFFFFF }); skinName.anchor.set(0, 0.5); skinName.x = -400; skinName.y = yPos; self.addChild(skinName); // Check if owned var isOwned = storage.ownedSkins.indexOf(skin.id) !== -1; var isSelected = storage.currentSkin === skin.id; if (isOwned) { // Select button var selectBtn = new Text2(isSelected ? 'SELECTED' : 'SELECT', { size: 60, fill: isSelected ? 0x00FF00 : 0xFFFFFF }); selectBtn.anchor.set(0.5, 0.5); selectBtn.x = 400; selectBtn.y = yPos; self.addChild(selectBtn); if (!isSelected) { selectBtn.interactive = true; selectBtn.down = function () { storage.currentSkin = skin.id; var shopParent = self.parent; shopParent.destroy(); shopContainer = new Container(); shopContainer.x = 1024; shopContainer.y = 1366; var newShop = new Shop(); shopContainer.addChild(newShop); game.addChild(shopContainer); }; } } else { // Buy button var buyBtn = new Text2('BUY: ' + skin.price, { size: 60, fill: storage.coins >= skin.price ? 0xFFD700 : 0x666666 }); buyBtn.anchor.set(0.5, 0.5); buyBtn.x = 400; buyBtn.y = yPos; self.addChild(buyBtn); if (storage.coins >= skin.price) { buyBtn.interactive = true; buyBtn.down = function () { storage.coins -= skin.price; storage.ownedSkins.push(skin.id); var shopParent = self.parent; shopParent.destroy(); shopContainer = new Container(); shopContainer.x = 1024; shopContainer.y = 1366; var newShop = new Shop(); shopContainer.addChild(newShop); game.addChild(shopContainer); }; } } }); self.close = function () { self.parent.destroy(); shopContainer = null; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var bg = LK.getAsset('Bg', { anchorX: 0.5, anchorY: 0.5, scaleX: 2048 / 100, // Scale to fit the screen width scaleY: 2732 / 100, // Scale to fit the screen height // Scale to fit 720p height x: 2048 / 2, // Center horizontally y: 2732 / 2 // Center vertically }); game.addChild(bg); var pencil = game.addChild(new Pencil()); var fruit = game.addChild(new Fruit()); // Initialize score display var scoreTxt = new Text2('0', { size: 150, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Add combo multiplier display var comboMultiplier = 1; var comboTxt = new Text2('', { size: 100, fill: 0xFFFF00 }); comboTxt.anchor.set(0.5, 0); comboTxt.y = 160; LK.gui.top.addChild(comboTxt); // Add coins display var coinsContainer = new Container(); var coinIcon = coinsContainer.attachAsset('Coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, x: -50, y: 0 }); var coinsText = new Text2(storage.coins.toString(), { size: 80, fill: 0xFFD700 }); coinsText.anchor.set(0, 0.5); coinsText.x = 0; coinsContainer.addChild(coinsText); LK.gui.topRight.addChild(coinsContainer); coinsContainer.y = 50; coinsContainer.x = -150; // Add shop button var shopBtn = LK.getAsset('Shop_button', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); LK.gui.topRight.addChild(shopBtn); shopBtn.x = -80; shopBtn.y = 150; shopBtn.interactive = true; shopBtn.down = function () { if (!shopContainer) { shopContainer = new Container(); shopContainer.x = 1024; shopContainer.y = 1366; var shop = new Shop(); shopContainer.addChild(shop); game.addChild(shopContainer); } }; var shopContainer = null; // Add settings button var settingsBtn = LK.getAsset('settings', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); LK.gui.topRight.addChild(settingsBtn); settingsBtn.x = -80; settingsBtn.y = 260; settingsBtn.interactive = true; settingsBtn.down = function () { if (!settingsContainer) { settingsContainer = new Container(); settingsContainer.x = 1024; settingsContainer.y = 1366; var settings = new Settings(); settingsContainer.addChild(settings); game.addChild(settingsContainer); } }; var settingsContainer = null; fruit.lastWasIntersecting = false; // Add event listener for screen touch to throw the pencil down game.down = function (x, y, obj) { if (!pencil) return; // Don't allow throwing if pencil doesn't exist pencil.isThrown = true; // Remove glow effect if (pencil.glow) { pencil.glow.destroy(); pencil.glow = null; } // In hardcore mode, pencil falls faster making it harder to time hits pencil.speed = storage.hardcoreMode ? 35 : 20; // Set a downward speed for the pencil pencil.update = function () { // Move pencil down only pencil.y += pencil.speed; }; // Background music removed - level up sound was too repetitive }; // Ensure the game updates the pencil's position every tick game.update = function () { if (pencil) { pencil.update(); } fruit.update(); // Check if the pencil has missed the target (e.g., gone off-screen) if (pencil && pencil.y > 2732) { // Reset combo multiplier comboMultiplier = 1; comboTxt.setText(''); // Trigger game over if the pencil misses the target LK.showGameOver(); } else if (pencil && fruit.lastWasIntersecting === false && pencil.intersects(fruit)) { // Create particle explosion var particles = []; for (var i = 0; i < 15; i++) { var particle = new Particle(); particle.x = fruit.x; particle.y = fruit.y; particles.push(particle); game.addChild(particle); } // Update particles in a separate loop LK.setInterval(function () { for (var j = particles.length - 1; j >= 0; j--) { var p = particles[j]; p.update(); if (p.shouldDestroy) { p.destroy(); particles.splice(j, 1); } } if (particles.length === 0) { LK.clearInterval(this); } }, 16); // Destroy the pencil after it touches a fruit pencil.destroy(); pencil = null; // Play hit sound LK.getSound('Hit').play(); // Darken the screen var darkOverlay = LK.getAsset('Bg', { anchorX: 0.5, anchorY: 0.5, scaleX: 2048 / 100, scaleY: 2732 / 100, x: 2048 / 2, y: 2732 / 2, tint: 0x000000, alpha: 0.5 }); game.addChild(darkOverlay); // Remove dark overlay after a short duration LK.setTimeout(function () { darkOverlay.destroy(); }, 1000); // Update combo multiplier comboMultiplier = Math.min(comboMultiplier + 1, 10); comboTxt.setText('x' + comboMultiplier); // Flash combo text tween(comboTxt, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); // Update score with multiplier and fruit value var points = fruit.pointValue * comboMultiplier; LK.setScore(LK.getScore() + points); scoreTxt.setText(LK.getScore()); // Award coins (1 coin per 10 points) var coinsEarned = Math.floor(points / 10); if (coinsEarned > 0) { storage.coins += coinsEarned; coinsText.setText(storage.coins.toString()); // Show coins earned animation var coinsTxt = new Text2('+' + coinsEarned + ' coin' + (coinsEarned > 1 ? 's' : ''), { size: 80, fill: 0xFFD700 }); coinsTxt.anchor.set(0.5, 0.5); coinsTxt.x = fruit.x; coinsTxt.y = fruit.y - 100; game.addChild(coinsTxt); // Animate coins text tween(coinsTxt, { y: fruit.y - 250, alpha: 0 }, { duration: 1500, onFinish: function onFinish() { coinsTxt.destroy(); } }); } // Show points earned var pointsTxt = new Text2('+' + points, { size: 120, fill: fruit.pointValue >= 4 ? 0xFFD700 : fruit.pointValue >= 3 ? 0xC0C0C0 : 0xFFFFFF }); pointsTxt.anchor.set(0.5, 0.5); pointsTxt.x = fruit.x; pointsTxt.y = fruit.y; game.addChild(pointsTxt); // Animate points text tween(pointsTxt, { y: fruit.y - 200, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { pointsTxt.destroy(); } }); // Check if 10 fruits have been destroyed if (LK.getScore() % 10 === 0) { // Remove level up sound as it's repetitive // Screen shake effect var originalX = game.x; var originalY = game.y; var shakeIntensity = 20; var shakeDuration = 500; var shakeStart = Date.now(); var shakeInterval = LK.setInterval(function () { var elapsed = Date.now() - shakeStart; if (elapsed < shakeDuration) { var factor = 1 - elapsed / shakeDuration; game.x = originalX + (Math.random() - 0.5) * shakeIntensity * factor; game.y = originalY + (Math.random() - 0.5) * shakeIntensity * factor; } else { game.x = originalX; game.y = originalY; LK.clearInterval(shakeInterval); } }, 16); // Increase fruit speed for a dash effect fruit.speed *= 2; // Reset fruit speed after a short duration LK.setTimeout(function () { fruit.speed /= 2; }, 1000); // Darken the screen var darkOverlay = LK.getAsset('Bg', { anchorX: 0.5, anchorY: 0.5, scaleX: 2048 / 100, scaleY: 2732 / 100, x: 2048 / 2, y: 2732 / 2, tint: 0x000000, alpha: 0.8 }); game.addChild(darkOverlay); // Add light effect to the fruit var light = LK.getAsset('Light', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 10, x: fruit.x, y: fruit.y }); game.addChild(light); // Animate light effect tween(light, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { light.destroy(); } }); // Remove dark overlay after a short duration LK.setTimeout(function () { darkOverlay.destroy(); }, 1000); } // Create a new pencil pencil = game.addChild(new Pencil()); // Bounce animation on fruit hit tween(fruit, { scaleX: 6, scaleY: 6 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { tween(fruit, { scaleX: 5, scaleY: 5 }, { duration: 300, easing: tween.bounceIn, onFinish: function onFinish() { // Create a new fruit fruit.destroy(); fruit = game.addChild(new Fruit()); // Show fruit name var fruitNameTxt = new Text2(fruit.fruitType, { size: 80, fill: 0xFFFFFF }); fruitNameTxt.anchor.set(0.5, 0.5); fruitNameTxt.x = fruit.x; fruitNameTxt.y = fruit.y - 150; fruitNameTxt.alpha = 0; game.addChild(fruitNameTxt); // Animate fruit name tween(fruitNameTxt, { alpha: 1 }, { duration: 300, onFinish: function onFinish() { tween(fruitNameTxt, { alpha: 0 }, { duration: 300, delay: 500, onFinish: function onFinish() { fruitNameTxt.destroy(); } }); } }); // Add light effect to the fruit var light = LK.getAsset('Light', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 10, x: fruit.x, y: fruit.y }); game.addChild(light); // Animate light effect tween(light, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { light.destroy(); } }); } }); } }); } fruit.lastWasIntersecting = pencil ? pencil.intersects(fruit) : false; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
coins: 0,
ownedSkins: ["Pencil"],
currentSkin: "Pencil",
hardcoreMode: false
});
/****
* Classes
****/
var Fruit = Container.expand(function () {
var self = Container.call(this);
// Define fruit properties
var fruitProperties = {
'Watermelon': {
points: 1,
speed: 15,
scale: 6,
rarity: 0.15
},
'Orange': {
points: 2,
speed: 20,
scale: 5,
rarity: 0.2
},
'Apple': {
points: 2,
speed: 20,
scale: 5,
rarity: 0.2
},
'Banana': {
points: 2,
speed: 20,
scale: 5,
rarity: 0.15
},
'pineapple': {
points: 3,
speed: 22,
scale: 4.5,
rarity: 0.1
},
'sleeve': {
points: 3,
speed: 22,
scale: 4.5,
rarity: 0.1
},
'Grapes': {
points: 4,
speed: 25,
scale: 4,
rarity: 0.05
},
'Cherry': {
points: 5,
speed: 30,
scale: 3,
rarity: 0.05
}
};
// Calculate weighted random selection
var weightedSelection = function weightedSelection() {
var rand = Math.random();
var cumulative = 0;
for (var fruit in fruitProperties) {
cumulative += fruitProperties[fruit].rarity;
if (rand < cumulative) {
return fruit;
}
}
return 'Apple'; // Default fallback
};
// Select fruit based on rarity
var randomFruit = weightedSelection();
self.fruitType = randomFruit;
self.pointValue = fruitProperties[randomFruit].points;
// Attach the selected fruit image asset to the container
var fruitGraphics = self.attachAsset(randomFruit, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: fruitProperties[randomFruit].scale,
// Scale fruit based on type
scaleY: fruitProperties[randomFruit].scale // Scale fruit based on type
});
// Add value indicator for high-value fruits
if (self.pointValue >= 3) {
var glow = self.attachAsset('Light', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: fruitProperties[randomFruit].scale * 1.2,
scaleY: fruitProperties[randomFruit].scale * 1.2,
alpha: 0.3,
tint: self.pointValue >= 4 ? 0xFFD700 : 0xC0C0C0
});
glow.zIndex = -1;
}
// Set initial position of the fruit in the middle of the screen
self.x = 1024; // Center horizontally
self.y = 1366; // Center vertically
// Add update method to move the fruit left and right
self.update = function () {
// Move fruit left and right
if (self.x <= 0 || self.x >= 2048) {
self.speed = -self.speed; // Reverse direction when hitting screen edges
}
self.x += self.speed;
// Dodge behavior in hardcore mode
if (storage.hardcoreMode && !self.isDodging && pencil && pencil.isThrown) {
// Check if pencil is getting close (within 400 pixels vertically)
if (Math.abs(pencil.y - self.y) < 400 && pencil.y < self.y) {
// 10% chance to dodge
if (Math.random() < 0.1) {
self.isDodging = true;
// Calculate dodge direction based on pencil position
var dodgeDirection = pencil.x < self.x ? 1 : -1;
// Increase speed temporarily for dodge
self.dodgeSpeed = self.speed;
self.speed = Math.abs(self.speed) * 3 * dodgeDirection;
// Reset dodge after a short time
LK.setTimeout(function () {
if (self && !self.destroyed) {
self.speed = self.dodgeSpeed;
self.isDodging = false;
}
}, 500);
}
}
}
};
// Set speed based on fruit type and hardcore mode
var baseSpeed = fruitProperties[randomFruit].speed;
if (storage.hardcoreMode) {
// In hardcore mode, fruits are 2x faster
baseSpeed *= 2;
}
self.speed = Math.random() < 0.5 ? baseSpeed : -baseSpeed;
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
// Create small circular particle
var particle = self.attachAsset('Light', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: Math.random() * 0xffffff
});
// Random velocity
self.vx = (Math.random() - 0.5) * 20;
self.vy = (Math.random() - 0.5) * 20;
self.gravity = 0.5;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.vy += self.gravity;
self.alpha -= 0.02;
if (self.alpha <= 0) {
self.shouldDestroy = true;
}
};
return self;
});
var Pencil = Container.expand(function () {
var self = Container.call(this);
// Attach the pencil image asset to the container using selected skin
var pencilGraphics = self.attachAsset(storage.currentSkin, {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position of the pencil
self.x = 1024; // Center horizontally
self.y = 0; // Position at the top of the screen
// Add update method to move the pencil left and right
self.update = function () {
// Move pencil left and right
if (self.x <= 0 || self.x >= 2048) {
self.speed = -self.speed; // Reverse direction when hitting screen edges
}
self.x += self.speed;
};
// In hardcore mode, pencil moves faster making it harder to aim
self.speed = storage.hardcoreMode ? 25 : 15; // Initial speed of the pencil
self.isThrown = false; // Track if pencil has been thrown
// Add glow effect when pencil is ready
var glow = self.attachAsset('Light', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
alpha: 0.3,
tint: 0x00ff00
});
// Store reference to glow for later removal
self.glow = glow;
// Create manual pulsing animation since tween doesn't support loop/yoyo
var pulseDirection = 1;
var pulseUpdate = function pulseUpdate() {
if (!self.isThrown && self.glow) {
glow.alpha += 0.006 * pulseDirection;
glow.scaleX += 0.01 * pulseDirection;
glow.scaleY += 0.01 * pulseDirection;
if (glow.alpha >= 0.6 || glow.alpha <= 0.3) {
pulseDirection = -pulseDirection;
}
}
};
// Store update function for removal
self.pulseUpdate = pulseUpdate;
// Add to pencil's update
var originalUpdate = self.update;
self.update = function () {
originalUpdate.call(self);
pulseUpdate();
};
});
var Settings = Container.expand(function () {
var self = Container.call(this);
// Settings background
var bg = self.attachAsset('Bg_shop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 15,
scaleY: 20,
tint: 0x333333,
alpha: 0.95
});
// Settings title
var title = new Text2('SETTINGS', {
size: 180,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0.5);
title.x = 0;
title.y = -600;
self.addChild(title);
// Close button
var closeBtn = new Text2('X', {
size: 150,
fill: 0xFF0000
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 600;
closeBtn.y = -600;
self.addChild(closeBtn);
closeBtn.interactive = true;
closeBtn.down = function () {
self.close();
};
// Hardcore mode toggle
var hardcoreLabel = new Text2('Hardcore Mode', {
size: 100,
fill: 0xFFFFFF
});
hardcoreLabel.anchor.set(0, 0.5);
hardcoreLabel.x = -400;
hardcoreLabel.y = -200;
self.addChild(hardcoreLabel);
// Toggle button
var toggleBtn = new Text2(storage.hardcoreMode ? 'ON' : 'OFF', {
size: 100,
fill: storage.hardcoreMode ? 0x00FF00 : 0xFF0000
});
toggleBtn.anchor.set(0.5, 0.5);
toggleBtn.x = 300;
toggleBtn.y = -200;
self.addChild(toggleBtn);
toggleBtn.interactive = true;
toggleBtn.down = function () {
if (!storage.hardcoreMode) {
// Show confirmation dialog
self.showConfirmation();
} else {
// Turn off hardcore mode
storage.hardcoreMode = false;
toggleBtn.setText('OFF');
toggleBtn.fill = 0xFF0000;
}
};
// Hardcore mode description
var description = new Text2('Makes fruits much faster\nand harder to hit!', {
size: 60,
fill: 0xAAAAAA
});
description.anchor.set(0.5, 0.5);
description.x = 0;
description.y = 0;
self.addChild(description);
self.showConfirmation = function () {
// Create confirmation overlay
var confirmOverlay = new Container();
var confirmBg = confirmOverlay.attachAsset('Bg_shop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 12,
scaleY: 10,
tint: 0x222222,
alpha: 0.98
});
// Shocked emoji
var emoji = confirmOverlay.attachAsset('Emoji_shocked', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
y: -200
});
// Confirmation text
var confirmText = new Text2('Are you sure?', {
size: 120,
fill: 0xFFFFFF
});
confirmText.anchor.set(0.5, 0.5);
confirmText.y = 0;
confirmOverlay.addChild(confirmText);
// Yes button
var yesBtn = new Text2('YES', {
size: 100,
fill: 0x00FF00
});
yesBtn.anchor.set(0.5, 0.5);
yesBtn.x = -200;
yesBtn.y = 200;
confirmOverlay.addChild(yesBtn);
yesBtn.interactive = true;
yesBtn.down = function () {
// Enable hardcore mode
storage.hardcoreMode = true;
toggleBtn.setText('ON');
toggleBtn.fill = 0x00FF00;
confirmOverlay.destroy();
// Play alert sound
LK.getSound('Alert').play();
};
// No button
var noBtn = new Text2('NO', {
size: 100,
fill: 0xFF0000
});
noBtn.anchor.set(0.5, 0.5);
noBtn.x = 200;
noBtn.y = 200;
confirmOverlay.addChild(noBtn);
noBtn.interactive = true;
noBtn.down = function () {
confirmOverlay.destroy();
};
self.addChild(confirmOverlay);
};
self.close = function () {
self.parent.destroy();
settingsContainer = null;
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
// Shop background
var bg = self.attachAsset('Bg_shop', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 20,
tint: 0x222222,
alpha: 0.95
});
// Shop title
var title = new Text2('SHOP', {
size: 200,
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0.5);
title.x = 0;
title.y = -800;
self.addChild(title);
// Coins display
self.coinsText = new Text2('Coins: ' + storage.coins, {
size: 120,
fill: 0xFFD700
});
self.coinsText.anchor.set(0.5, 0.5);
self.coinsText.x = 0;
self.coinsText.y = -600;
self.addChild(self.coinsText);
// Close button
var closeBtn = new Text2('X', {
size: 150,
fill: 0xFF0000
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 800;
closeBtn.y = -800;
self.addChild(closeBtn);
// Make close button interactive
closeBtn.interactive = true;
closeBtn.down = function () {
self.close();
};
// Skin items
var skins = [{
id: 'Pencil',
name: 'Classic',
price: 0
}, {
id: 'Pencil_skin1',
name: 'Pencil Picnic Mat',
price: 50
}, {
id: 'Pencil_skin2',
name: 'Golden Pencil',
price: 100
}, {
id: 'Pencil_skin3',
name: 'Wax Pencil',
price: 150
}, {
id: 'Pencil_skin4',
name: 'Remote Control Pencil',
price: 200
}, {
id: 'Pencil_skin5',
name: 'Pencil Case',
price: 500
}];
// Create skin items
skins.forEach(function (skin, index) {
var yPos = -400 + index * 200;
// Skin preview
var skinPreview = self.attachAsset(skin.id, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.15,
scaleY: 0.15,
x: -600,
y: yPos
});
// Skin name
var skinName = new Text2(skin.name, {
size: 80,
fill: 0xFFFFFF
});
skinName.anchor.set(0, 0.5);
skinName.x = -400;
skinName.y = yPos;
self.addChild(skinName);
// Check if owned
var isOwned = storage.ownedSkins.indexOf(skin.id) !== -1;
var isSelected = storage.currentSkin === skin.id;
if (isOwned) {
// Select button
var selectBtn = new Text2(isSelected ? 'SELECTED' : 'SELECT', {
size: 60,
fill: isSelected ? 0x00FF00 : 0xFFFFFF
});
selectBtn.anchor.set(0.5, 0.5);
selectBtn.x = 400;
selectBtn.y = yPos;
self.addChild(selectBtn);
if (!isSelected) {
selectBtn.interactive = true;
selectBtn.down = function () {
storage.currentSkin = skin.id;
var shopParent = self.parent;
shopParent.destroy();
shopContainer = new Container();
shopContainer.x = 1024;
shopContainer.y = 1366;
var newShop = new Shop();
shopContainer.addChild(newShop);
game.addChild(shopContainer);
};
}
} else {
// Buy button
var buyBtn = new Text2('BUY: ' + skin.price, {
size: 60,
fill: storage.coins >= skin.price ? 0xFFD700 : 0x666666
});
buyBtn.anchor.set(0.5, 0.5);
buyBtn.x = 400;
buyBtn.y = yPos;
self.addChild(buyBtn);
if (storage.coins >= skin.price) {
buyBtn.interactive = true;
buyBtn.down = function () {
storage.coins -= skin.price;
storage.ownedSkins.push(skin.id);
var shopParent = self.parent;
shopParent.destroy();
shopContainer = new Container();
shopContainer.x = 1024;
shopContainer.y = 1366;
var newShop = new Shop();
shopContainer.addChild(newShop);
game.addChild(shopContainer);
};
}
}
});
self.close = function () {
self.parent.destroy();
shopContainer = null;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var bg = LK.getAsset('Bg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
// Scale to fit the screen width
scaleY: 2732 / 100,
// Scale to fit the screen height
// Scale to fit 720p height
x: 2048 / 2,
// Center horizontally
y: 2732 / 2 // Center vertically
});
game.addChild(bg);
var pencil = game.addChild(new Pencil());
var fruit = game.addChild(new Fruit());
// Initialize score display
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Add combo multiplier display
var comboMultiplier = 1;
var comboTxt = new Text2('', {
size: 100,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 160;
LK.gui.top.addChild(comboTxt);
// Add coins display
var coinsContainer = new Container();
var coinIcon = coinsContainer.attachAsset('Coin', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
x: -50,
y: 0
});
var coinsText = new Text2(storage.coins.toString(), {
size: 80,
fill: 0xFFD700
});
coinsText.anchor.set(0, 0.5);
coinsText.x = 0;
coinsContainer.addChild(coinsText);
LK.gui.topRight.addChild(coinsContainer);
coinsContainer.y = 50;
coinsContainer.x = -150;
// Add shop button
var shopBtn = LK.getAsset('Shop_button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
LK.gui.topRight.addChild(shopBtn);
shopBtn.x = -80;
shopBtn.y = 150;
shopBtn.interactive = true;
shopBtn.down = function () {
if (!shopContainer) {
shopContainer = new Container();
shopContainer.x = 1024;
shopContainer.y = 1366;
var shop = new Shop();
shopContainer.addChild(shop);
game.addChild(shopContainer);
}
};
var shopContainer = null;
// Add settings button
var settingsBtn = LK.getAsset('settings', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
LK.gui.topRight.addChild(settingsBtn);
settingsBtn.x = -80;
settingsBtn.y = 260;
settingsBtn.interactive = true;
settingsBtn.down = function () {
if (!settingsContainer) {
settingsContainer = new Container();
settingsContainer.x = 1024;
settingsContainer.y = 1366;
var settings = new Settings();
settingsContainer.addChild(settings);
game.addChild(settingsContainer);
}
};
var settingsContainer = null;
fruit.lastWasIntersecting = false;
// Add event listener for screen touch to throw the pencil down
game.down = function (x, y, obj) {
if (!pencil) return; // Don't allow throwing if pencil doesn't exist
pencil.isThrown = true;
// Remove glow effect
if (pencil.glow) {
pencil.glow.destroy();
pencil.glow = null;
}
// In hardcore mode, pencil falls faster making it harder to time hits
pencil.speed = storage.hardcoreMode ? 35 : 20; // Set a downward speed for the pencil
pencil.update = function () {
// Move pencil down only
pencil.y += pencil.speed;
};
// Background music removed - level up sound was too repetitive
};
// Ensure the game updates the pencil's position every tick
game.update = function () {
if (pencil) {
pencil.update();
}
fruit.update();
// Check if the pencil has missed the target (e.g., gone off-screen)
if (pencil && pencil.y > 2732) {
// Reset combo multiplier
comboMultiplier = 1;
comboTxt.setText('');
// Trigger game over if the pencil misses the target
LK.showGameOver();
} else if (pencil && fruit.lastWasIntersecting === false && pencil.intersects(fruit)) {
// Create particle explosion
var particles = [];
for (var i = 0; i < 15; i++) {
var particle = new Particle();
particle.x = fruit.x;
particle.y = fruit.y;
particles.push(particle);
game.addChild(particle);
}
// Update particles in a separate loop
LK.setInterval(function () {
for (var j = particles.length - 1; j >= 0; j--) {
var p = particles[j];
p.update();
if (p.shouldDestroy) {
p.destroy();
particles.splice(j, 1);
}
}
if (particles.length === 0) {
LK.clearInterval(this);
}
}, 16);
// Destroy the pencil after it touches a fruit
pencil.destroy();
pencil = null;
// Play hit sound
LK.getSound('Hit').play();
// Darken the screen
var darkOverlay = LK.getAsset('Bg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
scaleY: 2732 / 100,
x: 2048 / 2,
y: 2732 / 2,
tint: 0x000000,
alpha: 0.5
});
game.addChild(darkOverlay);
// Remove dark overlay after a short duration
LK.setTimeout(function () {
darkOverlay.destroy();
}, 1000);
// Update combo multiplier
comboMultiplier = Math.min(comboMultiplier + 1, 10);
comboTxt.setText('x' + comboMultiplier);
// Flash combo text
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
// Update score with multiplier and fruit value
var points = fruit.pointValue * comboMultiplier;
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
// Award coins (1 coin per 10 points)
var coinsEarned = Math.floor(points / 10);
if (coinsEarned > 0) {
storage.coins += coinsEarned;
coinsText.setText(storage.coins.toString());
// Show coins earned animation
var coinsTxt = new Text2('+' + coinsEarned + ' coin' + (coinsEarned > 1 ? 's' : ''), {
size: 80,
fill: 0xFFD700
});
coinsTxt.anchor.set(0.5, 0.5);
coinsTxt.x = fruit.x;
coinsTxt.y = fruit.y - 100;
game.addChild(coinsTxt);
// Animate coins text
tween(coinsTxt, {
y: fruit.y - 250,
alpha: 0
}, {
duration: 1500,
onFinish: function onFinish() {
coinsTxt.destroy();
}
});
}
// Show points earned
var pointsTxt = new Text2('+' + points, {
size: 120,
fill: fruit.pointValue >= 4 ? 0xFFD700 : fruit.pointValue >= 3 ? 0xC0C0C0 : 0xFFFFFF
});
pointsTxt.anchor.set(0.5, 0.5);
pointsTxt.x = fruit.x;
pointsTxt.y = fruit.y;
game.addChild(pointsTxt);
// Animate points text
tween(pointsTxt, {
y: fruit.y - 200,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
pointsTxt.destroy();
}
});
// Check if 10 fruits have been destroyed
if (LK.getScore() % 10 === 0) {
// Remove level up sound as it's repetitive
// Screen shake effect
var originalX = game.x;
var originalY = game.y;
var shakeIntensity = 20;
var shakeDuration = 500;
var shakeStart = Date.now();
var shakeInterval = LK.setInterval(function () {
var elapsed = Date.now() - shakeStart;
if (elapsed < shakeDuration) {
var factor = 1 - elapsed / shakeDuration;
game.x = originalX + (Math.random() - 0.5) * shakeIntensity * factor;
game.y = originalY + (Math.random() - 0.5) * shakeIntensity * factor;
} else {
game.x = originalX;
game.y = originalY;
LK.clearInterval(shakeInterval);
}
}, 16);
// Increase fruit speed for a dash effect
fruit.speed *= 2;
// Reset fruit speed after a short duration
LK.setTimeout(function () {
fruit.speed /= 2;
}, 1000);
// Darken the screen
var darkOverlay = LK.getAsset('Bg', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2048 / 100,
scaleY: 2732 / 100,
x: 2048 / 2,
y: 2732 / 2,
tint: 0x000000,
alpha: 0.8
});
game.addChild(darkOverlay);
// Add light effect to the fruit
var light = LK.getAsset('Light', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 10,
x: fruit.x,
y: fruit.y
});
game.addChild(light);
// Animate light effect
tween(light, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
light.destroy();
}
});
// Remove dark overlay after a short duration
LK.setTimeout(function () {
darkOverlay.destroy();
}, 1000);
}
// Create a new pencil
pencil = game.addChild(new Pencil());
// Bounce animation on fruit hit
tween(fruit, {
scaleX: 6,
scaleY: 6
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(fruit, {
scaleX: 5,
scaleY: 5
}, {
duration: 300,
easing: tween.bounceIn,
onFinish: function onFinish() {
// Create a new fruit
fruit.destroy();
fruit = game.addChild(new Fruit());
// Show fruit name
var fruitNameTxt = new Text2(fruit.fruitType, {
size: 80,
fill: 0xFFFFFF
});
fruitNameTxt.anchor.set(0.5, 0.5);
fruitNameTxt.x = fruit.x;
fruitNameTxt.y = fruit.y - 150;
fruitNameTxt.alpha = 0;
game.addChild(fruitNameTxt);
// Animate fruit name
tween(fruitNameTxt, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
tween(fruitNameTxt, {
alpha: 0
}, {
duration: 300,
delay: 500,
onFinish: function onFinish() {
fruitNameTxt.destroy();
}
});
}
});
// Add light effect to the fruit
var light = LK.getAsset('Light', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10,
scaleY: 10,
x: fruit.x,
y: fruit.y
});
game.addChild(light);
// Animate light effect
tween(light, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
light.destroy();
}
});
}
});
}
});
}
fruit.lastWasIntersecting = pencil ? pencil.intersects(fruit) : false;
};
Pencil. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
picnic bg. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
heart icon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
mango fruit with eye and mouth animation.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Banana with eye and mouth animation.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
picnic bg in a night sky. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Watermelon with eye and mouth animation. In-Game asset. 2d. High contrast. No shadows
Orange with eye and mouth animation. In-Game asset. 2d. High contrast. No shadows
Shop icon. In-Game asset. 2d. High contrast. No shadows
Coin icon. In-Game asset. 2d. High contrast. No shadows
Emoji_shocked. In-Game asset. 2d. High contrast. No shadows
Settings icon. In-Game asset. 2d. High contrast. No shadows