/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Enemy class (for both pumpkin and watermelon) var Enemy = Container.expand(function () { var self = Container.call(this); // Randomly choose pumpkin or watermelon var isPumpkin = Math.random() < 0.5; var assetId = isPumpkin ? 'pumpkin' : 'watermelon'; var enemySprite = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.type = assetId; // Enemy speed increases as score increases (base speed + random, plus score scaling) var score = typeof LK.getScore === "function" ? LK.getScore() : 0; self.speed = 3 + Math.random() * 2 + Math.floor(score / 10) * 0.7; self.update = function () { // Dynamically update speed based on current score var score = typeof LK.getScore === "function" ? LK.getScore() : 0; self.speed = 3 + Math.random() * 2 + Math.floor(score / 10) * 0.7; // Move towards base (center) var dx = base.x - self.x; var dy = base.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } }; return self; }); // Hero class var Hero = Container.expand(function () { var self = Container.call(this); var heroSprite = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); // For possible future effects self.flash = function () { LK.effects.flashObject(self, 0xffffff, 200); }; return self; }); // HeroBullet class var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = -30; // Default up self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Start screen and high score table are handled automatically by LK engine // Center positions var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var CENTER_X = GAME_WIDTH / 2; var CENTER_Y = GAME_HEIGHT / 2; // Add Turkmen carpet pixel art background (full screen, behind everything) var carpetBg = LK.getAsset('carpetBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: GAME_WIDTH, height: GAME_HEIGHT }); game.addChild(carpetBg); // Add base (defense point) var base = LK.getAsset('base', { anchorX: 0.5, anchorY: 0.5, x: CENTER_X, y: CENTER_Y }); game.addChild(base); // Add hero var hero = new Hero(); hero.x = CENTER_X; hero.y = CENTER_Y + 700; game.addChild(hero); // Score display var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Arrays to track bullets and enemies var heroBullets = []; var enemies = []; // Dragging logic var dragNode = null; // Cursor for showing target position var cursor = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7, x: CENTER_X, y: CENTER_Y }); cursor.alpha = 0.5; game.addChild(cursor); // For intersection detection var lastBaseIntersecting = false; // Fire control var canShoot = true; var shootCooldown = 18; // frames between shots // Enemy spawn control var enemySpawnTimer = 0; var enemySpawnInterval = 120; // frames (was 60, now slower spawn) // Play music LK.playMusic('fruitBattleMusic'); // Move handler for dragging hero function handleMove(x, y, obj) { if (dragNode === hero) { // Clamp hero inside game area (with margin) var margin = 80; var minX = margin; var maxX = GAME_WIDTH - margin; var minY = margin; var maxY = GAME_HEIGHT - margin; // Move hero towards target position, but only a fraction per frame for slower movement var moveSpeed = 32; // Lower = slower, higher = faster var targetX = Math.max(minX, Math.min(maxX, x)); var targetY = Math.max(minY, Math.min(maxY, y)); var dx = targetX - hero.x; var dy = targetY - hero.y; var dist = Math.sqrt(dx * dx + dy * dy); // Add random move chance (wobble) var moveChance = 0.85; // 85% chance to move per frame if (Math.random() < moveChance) { if (dist > moveSpeed) { hero.x += dx / dist * moveSpeed; hero.y += dy / dist * moveSpeed; } else { hero.x = targetX; hero.y = targetY; } } // Always update cursor to current pointer/touch position (clamped to game area) var margin = 80; var minX = margin; var maxX = GAME_WIDTH - margin; var minY = margin; var maxY = GAME_HEIGHT - margin; var cursorX = Math.max(minX, Math.min(maxX, x)); var cursorY = Math.max(minY, Math.min(maxY, y)); cursor.x = cursorX; cursor.y = cursorY; } } game.move = handleMove; game.down = function (x, y, obj) { // Allow drag from anywhere dragNode = hero; }; game.up = function (x, y, obj) { dragNode = null; }; // Fire bullet function in any direction function fireBullet(targetX, targetY) { if (!canShoot) return; // Default: shoot up if no target var tx = typeof targetX === "number" ? targetX : hero.x; var ty = typeof targetY === "number" ? targetY : hero.y - 200; var dx = tx - hero.x; var dy = ty - hero.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) dist = 1; var bullet = new HeroBullet(); bullet.x = hero.x; bullet.y = hero.y; // Set velocity for bullet bullet.vx = dx / dist * 40; bullet.vy = dy / dist * 40; bullet.lastY = bullet.y; bullet.lastIntersecting = false; heroBullets.push(bullet); game.addChild(bullet); canShoot = false; LK.getSound('shoot').play(); } // Touch anywhere to shoot in that direction game.tap = function (x, y, obj) { fireBullet(x, y); }; // Main update loop game.update = function () { // Shooting cooldown if (!canShoot) { shootCooldown--; if (shootCooldown <= 0) { canShoot = true; shootCooldown = 18; } } // Fire bullet automatically if dragging if (dragNode === hero && canShoot) { fireBullet(); } // Update hero bullets for (var i = heroBullets.length - 1; i >= 0; i--) { var bullet = heroBullets[i]; bullet.update(); // Remove if off screen (any direction) if (bullet.x < -bullet.width || bullet.x > GAME_WIDTH + bullet.width || bullet.y < -bullet.height || bullet.y > GAME_HEIGHT + bullet.height) { bullet.destroy(); heroBullets.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; var isIntersecting = bullet.intersects(enemy); if (!bullet.lastIntersecting && isIntersecting) { // Destroy both LK.getSound('fruitPop').play(); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); bullet.destroy(); heroBullets.splice(i, 1); enemy.destroy(); enemies.splice(j, 1); break; } bullet.lastIntersecting = isIntersecting; } } // Update enemies for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; enemy.update(); // Check collision with base var baseIntersecting = enemy.intersects(base); if (!lastBaseIntersecting && baseIntersecting) { // Game over LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } lastBaseIntersecting = baseIntersecting; // Check collision with hero if (enemy.intersects(hero)) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } // Spawn enemies enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnInterval) { enemySpawnTimer = 0; // Spawn at random edge var edge = Math.floor(Math.random() * 4); var spawnX, spawnY; var margin = 100; if (edge === 0) { // Top spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin); spawnY = -80; } else if (edge === 1) { // Bottom spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin); spawnY = GAME_HEIGHT + 80; } else if (edge === 2) { // Left spawnX = -80; spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin); } else { // Right spawnX = GAME_WIDTH + 80; spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin); } var enemy = new Enemy(); enemy.x = spawnX; enemy.y = spawnY; enemies.push(enemy); game.addChild(enemy); } // Win condition: survive and destroy 30 fruits if (LK.getScore() >= 30) { LK.showYouWin(); } // --- Extra teardrop spawn logic --- if (typeof lastTeardropScore === "undefined") { lastTeardropScore = 0; } if (typeof lastHeroBulletScore === "undefined") { lastHeroBulletScore = 0; } var currentScore = LK.getScore(); if (currentScore > 0 && currentScore % 10 === 0 && lastTeardropScore !== currentScore) { // Spawn an extra teardrop (enemy) at a random edge var edge = Math.floor(Math.random() * 4); var spawnX, spawnY; var margin = 100; if (edge === 0) { // Top spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin); spawnY = -80; } else if (edge === 1) { // Bottom spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin); spawnY = GAME_HEIGHT + 80; } else if (edge === 2) { // Left spawnX = -80; spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin); } else { // Right spawnX = GAME_WIDTH + 80; spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin); } var extraEnemy = new Enemy(); extraEnemy.x = spawnX; extraEnemy.y = spawnY; enemies.push(extraEnemy); game.addChild(extraEnemy); lastTeardropScore = currentScore; } // --- Extra hero bullet spawn logic --- if (currentScore > 0 && currentScore % 10 === 0 && lastHeroBulletScore !== currentScore) { // Spawn a hero bullet straight up from hero's current position var bonusBullet = new HeroBullet(); bonusBullet.x = hero.x; bonusBullet.y = hero.y; bonusBullet.vx = 0; bonusBullet.vy = -40; bonusBullet.lastY = bonusBullet.y; bonusBullet.lastIntersecting = false; heroBullets.push(bonusBullet); game.addChild(bonusBullet); lastHeroBulletScore = currentScore; } }; // Set initial score LK.setScore(0); scoreTxt.setText('0'); ; // Start screen and high score table are handled automatically by LK engine
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy class (for both pumpkin and watermelon)
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Randomly choose pumpkin or watermelon
var isPumpkin = Math.random() < 0.5;
var assetId = isPumpkin ? 'pumpkin' : 'watermelon';
var enemySprite = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = assetId;
// Enemy speed increases as score increases (base speed + random, plus score scaling)
var score = typeof LK.getScore === "function" ? LK.getScore() : 0;
self.speed = 3 + Math.random() * 2 + Math.floor(score / 10) * 0.7;
self.update = function () {
// Dynamically update speed based on current score
var score = typeof LK.getScore === "function" ? LK.getScore() : 0;
self.speed = 3 + Math.random() * 2 + Math.floor(score / 10) * 0.7;
// Move towards base (center)
var dx = base.x - self.x;
var dy = base.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
};
return self;
});
// Hero class
var Hero = Container.expand(function () {
var self = Container.call(this);
var heroSprite = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
// For possible future effects
self.flash = function () {
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
// HeroBullet class
var HeroBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('heroBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = -30; // Default up
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Start screen and high score table are handled automatically by LK engine
// Center positions
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var CENTER_X = GAME_WIDTH / 2;
var CENTER_Y = GAME_HEIGHT / 2;
// Add Turkmen carpet pixel art background (full screen, behind everything)
var carpetBg = LK.getAsset('carpetBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: GAME_WIDTH,
height: GAME_HEIGHT
});
game.addChild(carpetBg);
// Add base (defense point)
var base = LK.getAsset('base', {
anchorX: 0.5,
anchorY: 0.5,
x: CENTER_X,
y: CENTER_Y
});
game.addChild(base);
// Add hero
var hero = new Hero();
hero.x = CENTER_X;
hero.y = CENTER_Y + 700;
game.addChild(hero);
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Arrays to track bullets and enemies
var heroBullets = [];
var enemies = [];
// Dragging logic
var dragNode = null;
// Cursor for showing target position
var cursor = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7,
x: CENTER_X,
y: CENTER_Y
});
cursor.alpha = 0.5;
game.addChild(cursor);
// For intersection detection
var lastBaseIntersecting = false;
// Fire control
var canShoot = true;
var shootCooldown = 18; // frames between shots
// Enemy spawn control
var enemySpawnTimer = 0;
var enemySpawnInterval = 120; // frames (was 60, now slower spawn)
// Play music
LK.playMusic('fruitBattleMusic');
// Move handler for dragging hero
function handleMove(x, y, obj) {
if (dragNode === hero) {
// Clamp hero inside game area (with margin)
var margin = 80;
var minX = margin;
var maxX = GAME_WIDTH - margin;
var minY = margin;
var maxY = GAME_HEIGHT - margin;
// Move hero towards target position, but only a fraction per frame for slower movement
var moveSpeed = 32; // Lower = slower, higher = faster
var targetX = Math.max(minX, Math.min(maxX, x));
var targetY = Math.max(minY, Math.min(maxY, y));
var dx = targetX - hero.x;
var dy = targetY - hero.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Add random move chance (wobble)
var moveChance = 0.85; // 85% chance to move per frame
if (Math.random() < moveChance) {
if (dist > moveSpeed) {
hero.x += dx / dist * moveSpeed;
hero.y += dy / dist * moveSpeed;
} else {
hero.x = targetX;
hero.y = targetY;
}
}
// Always update cursor to current pointer/touch position (clamped to game area)
var margin = 80;
var minX = margin;
var maxX = GAME_WIDTH - margin;
var minY = margin;
var maxY = GAME_HEIGHT - margin;
var cursorX = Math.max(minX, Math.min(maxX, x));
var cursorY = Math.max(minY, Math.min(maxY, y));
cursor.x = cursorX;
cursor.y = cursorY;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Allow drag from anywhere
dragNode = hero;
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Fire bullet function in any direction
function fireBullet(targetX, targetY) {
if (!canShoot) return;
// Default: shoot up if no target
var tx = typeof targetX === "number" ? targetX : hero.x;
var ty = typeof targetY === "number" ? targetY : hero.y - 200;
var dx = tx - hero.x;
var dy = ty - hero.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) dist = 1;
var bullet = new HeroBullet();
bullet.x = hero.x;
bullet.y = hero.y;
// Set velocity for bullet
bullet.vx = dx / dist * 40;
bullet.vy = dy / dist * 40;
bullet.lastY = bullet.y;
bullet.lastIntersecting = false;
heroBullets.push(bullet);
game.addChild(bullet);
canShoot = false;
LK.getSound('shoot').play();
}
// Touch anywhere to shoot in that direction
game.tap = function (x, y, obj) {
fireBullet(x, y);
};
// Main update loop
game.update = function () {
// Shooting cooldown
if (!canShoot) {
shootCooldown--;
if (shootCooldown <= 0) {
canShoot = true;
shootCooldown = 18;
}
}
// Fire bullet automatically if dragging
if (dragNode === hero && canShoot) {
fireBullet();
}
// Update hero bullets
for (var i = heroBullets.length - 1; i >= 0; i--) {
var bullet = heroBullets[i];
bullet.update();
// Remove if off screen (any direction)
if (bullet.x < -bullet.width || bullet.x > GAME_WIDTH + bullet.width || bullet.y < -bullet.height || bullet.y > GAME_HEIGHT + bullet.height) {
bullet.destroy();
heroBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
var isIntersecting = bullet.intersects(enemy);
if (!bullet.lastIntersecting && isIntersecting) {
// Destroy both
LK.getSound('fruitPop').play();
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
bullet.destroy();
heroBullets.splice(i, 1);
enemy.destroy();
enemies.splice(j, 1);
break;
}
bullet.lastIntersecting = isIntersecting;
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
enemy.update();
// Check collision with base
var baseIntersecting = enemy.intersects(base);
if (!lastBaseIntersecting && baseIntersecting) {
// Game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
lastBaseIntersecting = baseIntersecting;
// Check collision with hero
if (enemy.intersects(hero)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Spawn enemies
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnInterval) {
enemySpawnTimer = 0;
// Spawn at random edge
var edge = Math.floor(Math.random() * 4);
var spawnX, spawnY;
var margin = 100;
if (edge === 0) {
// Top
spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin);
spawnY = -80;
} else if (edge === 1) {
// Bottom
spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin);
spawnY = GAME_HEIGHT + 80;
} else if (edge === 2) {
// Left
spawnX = -80;
spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
} else {
// Right
spawnX = GAME_WIDTH + 80;
spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
}
var enemy = new Enemy();
enemy.x = spawnX;
enemy.y = spawnY;
enemies.push(enemy);
game.addChild(enemy);
}
// Win condition: survive and destroy 30 fruits
if (LK.getScore() >= 30) {
LK.showYouWin();
}
// --- Extra teardrop spawn logic ---
if (typeof lastTeardropScore === "undefined") {
lastTeardropScore = 0;
}
if (typeof lastHeroBulletScore === "undefined") {
lastHeroBulletScore = 0;
}
var currentScore = LK.getScore();
if (currentScore > 0 && currentScore % 10 === 0 && lastTeardropScore !== currentScore) {
// Spawn an extra teardrop (enemy) at a random edge
var edge = Math.floor(Math.random() * 4);
var spawnX, spawnY;
var margin = 100;
if (edge === 0) {
// Top
spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin);
spawnY = -80;
} else if (edge === 1) {
// Bottom
spawnX = margin + Math.random() * (GAME_WIDTH - 2 * margin);
spawnY = GAME_HEIGHT + 80;
} else if (edge === 2) {
// Left
spawnX = -80;
spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
} else {
// Right
spawnX = GAME_WIDTH + 80;
spawnY = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
}
var extraEnemy = new Enemy();
extraEnemy.x = spawnX;
extraEnemy.y = spawnY;
enemies.push(extraEnemy);
game.addChild(extraEnemy);
lastTeardropScore = currentScore;
}
// --- Extra hero bullet spawn logic ---
if (currentScore > 0 && currentScore % 10 === 0 && lastHeroBulletScore !== currentScore) {
// Spawn a hero bullet straight up from hero's current position
var bonusBullet = new HeroBullet();
bonusBullet.x = hero.x;
bonusBullet.y = hero.y;
bonusBullet.vx = 0;
bonusBullet.vy = -40;
bonusBullet.lastY = bonusBullet.y;
bonusBullet.lastIntersecting = false;
heroBullets.push(bonusBullet);
game.addChild(bonusBullet);
lastHeroBulletScore = currentScore;
}
};
// Set initial score
LK.setScore(0);
scoreTxt.setText('0');
;
// Start screen and high score table are handled automatically by LK engine
Add a face this character and cut the background
Create pixel art clown with no background. In-Game asset. 2d. High contrast. No shadows
Create teardrop with pixel art. In-Game asset. 2d. High contrast. No shadows
Add face on it
Add angry face on it
Create carpet from Iran with pixel art. In-Game asset. 2d. High contrast. No shadows
Create Arrow with silly face pixel art. In-Game asset. 2d. High contrast. No shadows