User prompt
böcekleri ortadan kaldır
User prompt
Please fix the bug: 'TypeError: target is not an Object. (evaluating 'key in target')' in or related to this line: 'tween(wormSegments[i], {' Line Number: 734 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Çift tıklandığında daha hızlı gitsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Biraz daha ayrıntı ekle
Code edit (1 edits merged)
Please save this source code
User prompt
Worm Feast: Slither & Devour
Initial prompt
Bana bir solucan yeme simülatör oyunu yap
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, level: 1 }); /**** * Classes ****/ var Food = Container.expand(function (isSpecial) { var self = Container.call(this); self.isSpecial = isSpecial || false; self.value = self.isSpecial ? 3 : 1; var foodGraphics = self.attachAsset(self.isSpecial ? 'food_special' : 'food_normal', { anchorX: 0.5, anchorY: 0.5 }); if (self.isSpecial) { // Add pulsating animation for special food self.pulseDirection = 1; self.pulseMin = 0.85; self.pulseMax = 1.15; self.pulseSpeed = 0.01; } self.update = function () { if (self.isSpecial) { // Pulsating effect if (self.pulseDirection > 0) { foodGraphics.scale.x += self.pulseSpeed; foodGraphics.scale.y += self.pulseSpeed; if (foodGraphics.scale.x >= self.pulseMax) { self.pulseDirection = -1; } } else { foodGraphics.scale.x -= self.pulseSpeed; foodGraphics.scale.y -= self.pulseSpeed; if (foodGraphics.scale.x <= self.pulseMin) { self.pulseDirection = 1; } } } }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'speed'; // speed, invincibility, grow var color; switch (self.type) { case 'speed': color = 0x00BFFF; break; case 'invincibility': color = 0xFFFF00; break; case 'grow': color = 0xFF00FF; break; default: color = 0xFFFFFF; } // Create a shape for the powerup var powerupGraphics = self.attachAsset('powerup_' + self.type, { anchorX: 0.5, anchorY: 0.5 }); // Add pulsating animation self.pulseDirection = 1; self.pulseMin = 0.8; self.pulseMax = 1.2; self.pulseSpeed = 0.02; self.update = function () { // Pulsating effect if (self.pulseDirection > 0) { powerupGraphics.scale.x += self.pulseSpeed; powerupGraphics.scale.y += self.pulseSpeed; if (powerupGraphics.scale.x >= self.pulseMax) { self.pulseDirection = -1; } } else { powerupGraphics.scale.x -= self.pulseSpeed; powerupGraphics.scale.y -= self.pulseSpeed; if (powerupGraphics.scale.x <= self.pulseMin) { self.pulseDirection = 1; } } }; return self; }); var SoilParticle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('soil_particle', { anchorX: 0.5, anchorY: 0.5 }); self.alpha = Math.random() * 0.5 + 0.2; self.lifespan = Math.random() * 30 + 15; self.velocityX = (Math.random() - 0.5) * 2; self.velocityY = (Math.random() - 0.5) * 2; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.lifespan--; if (self.lifespan <= 10) { self.alpha -= 0.1; } }; return self; }); var WormSegment = Container.expand(function (isHead) { var self = Container.call(this); self.isHead = isHead || false; var segmentGraphics = self.attachAsset(self.isHead ? 'worm_head' : 'worm_body', { anchorX: 0.5, anchorY: 0.5 }); // Store previous position for smooth following self.prevX = 0; self.prevY = 0; // Save position to follow self.savePosition = function () { self.prevX = self.x; self.prevY = self.y; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x3E2723 }); /**** * Game Code ****/ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var SEGMENT_SPACING = 30; var STARTING_SEGMENTS = 5; var MAX_SEGMENTS = 50; var MOVE_SPEED = 5; var TURNING_SPEED = 0.1; var SPAWN_FOOD_INTERVAL = 60; var SPAWN_OBSTACLE_INTERVAL = 180; var SPAWN_POWERUP_INTERVAL = 600; var SPECIAL_FOOD_CHANCE = 0.2; var POWERUP_DURATION = 300; // Game variables var wormSegments = []; var foods = []; var obstacles = []; var powerups = []; var soilParticles = []; var targetX = 0; var targetY = 0; var score = 0; var gameLevel = storage.level || 1; var highScore = storage.highScore || 0; var movingToTarget = false; var wormAngle = 0; var foodTimer = 0; var obstacleTimer = 0; var powerupTimer = 0; var powerupActive = false; var powerupType = null; var powerupTimeRemaining = 0; var gameStarted = false; var levelScore = gameLevel * 10; // Create background with soil texture function createBackground() { var backgroundContainer = new Container(); game.addChild(backgroundContainer); var tileSize = 100; for (var x = 0; x < GAME_WIDTH; x += tileSize) { for (var y = 0; y < GAME_HEIGHT; y += tileSize) { var tile = LK.getAsset('background_tile', { anchorX: 0, anchorY: 0, width: tileSize, height: tileSize, alpha: 0.7 + Math.random() * 0.3 }); tile.x = x; tile.y = y; tile.rotation = Math.random() * Math.PI * 2; tile.scale.x = 0.9 + Math.random() * 0.2; tile.scale.y = 0.9 + Math.random() * 0.2; backgroundContainer.addChild(tile); } } } // Initialize worm function createWorm() { // Create head var head = new WormSegment(true); head.x = GAME_WIDTH / 2; head.y = GAME_HEIGHT / 2; game.addChild(head); wormSegments.push(head); // Create initial body segments for (var i = 0; i < STARTING_SEGMENTS; i++) { addWormSegment(); } } // Add new segment to the worm function addWormSegment() { if (wormSegments.length >= MAX_SEGMENTS) { return; } var lastSegment = wormSegments[wormSegments.length - 1]; var newSegment = new WormSegment(false); newSegment.x = lastSegment.x; newSegment.y = lastSegment.y; game.addChild(newSegment); wormSegments.push(newSegment); } // Spawn a food item at a random position function spawnFood() { var isSpecial = Math.random() < SPECIAL_FOOD_CHANCE; var food = new Food(isSpecial); // Position food randomly away from edges food.x = Math.random() * (GAME_WIDTH - 200) + 100; food.y = Math.random() * (GAME_HEIGHT - 200) + 100; // Make sure food doesn't overlap with obstacles for (var i = 0; i < obstacles.length; i++) { if (getDistance(food.x, food.y, obstacles[i].x, obstacles[i].y) < 100) { // Reposition if too close to an obstacle food.x = Math.random() * (GAME_WIDTH - 200) + 100; food.y = Math.random() * (GAME_HEIGHT - 200) + 100; i = -1; // Reset loop to check again } } game.addChild(food); foods.push(food); } // Spawn an obstacle function spawnObstacle() { var obstacle = new Obstacle(); // Position obstacle randomly away from edges and worm head var head = wormSegments[0]; do { obstacle.x = Math.random() * (GAME_WIDTH - 200) + 100; obstacle.y = Math.random() * (GAME_HEIGHT - 200) + 100; } while (getDistance(obstacle.x, obstacle.y, head.x, head.y) < 300); game.addChild(obstacle); obstacles.push(obstacle); } // Spawn a power-up function spawnPowerup() { var types = ['speed', 'invincibility', 'grow']; var randomType = types[Math.floor(Math.random() * types.length)]; var powerup = new PowerUp(randomType); // Position powerup randomly away from edges powerup.x = Math.random() * (GAME_WIDTH - 200) + 100; powerup.y = Math.random() * (GAME_HEIGHT - 200) + 100; // Make sure powerup doesn't overlap with obstacles for (var i = 0; i < obstacles.length; i++) { if (getDistance(powerup.x, powerup.y, obstacles[i].x, obstacles[i].y) < 100) { // Reposition if too close to an obstacle powerup.x = Math.random() * (GAME_WIDTH - 200) + 100; powerup.y = Math.random() * (GAME_HEIGHT - 200) + 100; i = -1; // Reset loop to check again } } game.addChild(powerup); powerups.push(powerup); } // Create soil particles effect function createSoilEffect(x, y, count) { for (var i = 0; i < count; i++) { var particle = new SoilParticle(); particle.x = x; particle.y = y; game.addChild(particle); soilParticles.push(particle); } } // Calculate distance between two points function getDistance(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); } // Activate powerup function activatePowerup(type) { powerupActive = true; powerupType = type; powerupTimeRemaining = POWERUP_DURATION; LK.getSound('powerup').play(); // Apply power-up effects switch (type) { case 'speed': MOVE_SPEED *= 1.75; break; case 'invincibility': // Visual effect for invincibility for (var i = 0; i < wormSegments.length; i++) { tween(wormSegments[i], { alpha: 0.7 }, { duration: 300 }); } break; case 'grow': // Add multiple segments at once for (var j = 0; j < 3; j++) { addWormSegment(); } break; } } // End powerup effect function endPowerupEffect() { switch (powerupType) { case 'speed': MOVE_SPEED = 5; break; case 'invincibility': // Reset visual effect for (var i = 0; i < wormSegments.length; i++) { tween(wormSegments[i], { alpha: 1 }, { duration: 300 }); } break; } powerupActive = false; powerupType = null; } // Setup UI elements function setupUI() { // Score text var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -scoreTxt.width - 20; scoreTxt.y = 20; // Level text var levelTxt = new Text2('Level: ' + gameLevel, { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); LK.gui.topRight.addChild(levelTxt); levelTxt.x = -levelTxt.width - 20; levelTxt.y = 100; // High score text var highScoreTxt = new Text2('Best: ' + highScore, { size: 50, fill: 0xFFD700 }); highScoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(highScoreTxt); highScoreTxt.x = -highScoreTxt.width - 20; highScoreTxt.y = 160; // Next level text var nextLevelTxt = new Text2('Next Level: ' + levelScore, { size: 50, fill: 0x32CD32 }); nextLevelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(nextLevelTxt); nextLevelTxt.y = 20; // Powerup indicator var powerupTxt = new Text2('', { size: 60, fill: 0xFFFF00 }); powerupTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(powerupTxt); powerupTxt.x = 120; // Keep away from the top-left 100x100 px area powerupTxt.y = 20; // Start instructions var instructionsTxt = new Text2('Tap to start\nDrag to move your worm\nEat food to grow', { size: 80, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionsTxt); // Update UI function game.updateUI = function () { scoreTxt.setText('Score: ' + score); scoreTxt.x = -scoreTxt.width - 20; levelTxt.setText('Level: ' + gameLevel); levelTxt.x = -levelTxt.width - 20; highScoreTxt.setText('Best: ' + highScore); highScoreTxt.x = -highScoreTxt.width - 20; nextLevelTxt.setText('Next Level: ' + (levelScore - score)); if (powerupActive) { var timeLeft = Math.ceil(powerupTimeRemaining / 60); powerupTxt.setText(powerupType.toUpperCase() + ': ' + timeLeft + 's'); } else { powerupTxt.setText(''); } if (gameStarted) { instructionsTxt.alpha = 0; } }; } // Initialize game function initGame() { // Reset game state wormSegments = []; foods = []; obstacles = []; powerups = []; soilParticles = []; score = 0; movingToTarget = false; wormAngle = 0; foodTimer = 0; obstacleTimer = 0; powerupTimer = 0; powerupActive = false; powerupType = null; powerupTimeRemaining = 0; levelScore = gameLevel * 10; MOVE_SPEED = 5; // Set background createBackground(); // Create the worm createWorm(); // Initial food for (var i = 0; i < 3; i++) { spawnFood(); } // Initial obstacles based on level for (var j = 0; j < Math.min(gameLevel, 5); j++) { spawnObstacle(); } // Setup UI setupUI(); // Play background music LK.playMusic('bgmusic'); } // Initialize the game initGame(); // Game logic update function game.update = function () { if (!gameStarted) { return; } // Move worm head var head = wormSegments[0]; if (movingToTarget) { // Calculate angle to target var dx = targetX - head.x; var dy = targetY - head.y; var targetAngle = Math.atan2(dy, dx); // Smooth angle change var angleDiff = targetAngle - wormAngle; // Handle angle wrapping if (angleDiff > Math.PI) { angleDiff -= Math.PI * 2; } if (angleDiff < -Math.PI) { angleDiff += Math.PI * 2; } // Apply gradual turning wormAngle += angleDiff * TURNING_SPEED; // Move in the current direction head.savePosition(); head.x += Math.cos(wormAngle) * MOVE_SPEED; head.y += Math.sin(wormAngle) * MOVE_SPEED; // Create soil particles as the worm moves if (LK.ticks % 3 === 0) { createSoilEffect(head.x, head.y, 1); } // Check if close enough to target if (getDistance(head.x, head.y, targetX, targetY) < 10) { movingToTarget = false; } } // Move body segments for (var i = 1; i < wormSegments.length; i++) { var segment = wormSegments[i]; var prevSegment = wormSegments[i - 1]; // Save current position before updating segment.savePosition(); // Calculate direction to previous segment var dx = prevSegment.prevX - segment.x; var dy = prevSegment.prevY - segment.y; var distance = Math.sqrt(dx * dx + dy * dy); // Move towards the previous segment's saved position if (distance > SEGMENT_SPACING) { var moveRatio = (distance - SEGMENT_SPACING) / distance; segment.x += dx * moveRatio; segment.y += dy * moveRatio; } } // Update soil particles for (var p = soilParticles.length - 1; p >= 0; p--) { var particle = soilParticles[p]; particle.update(); if (particle.lifespan <= 0 || particle.alpha <= 0) { particle.destroy(); soilParticles.splice(p, 1); } } // Boundary checking for worm head if (head.x < 0) { head.x = 0; } if (head.x > GAME_WIDTH) { head.x = GAME_WIDTH; } if (head.y < 0) { head.y = 0; } if (head.y > GAME_HEIGHT) { head.y = GAME_HEIGHT; } // Check collisions with food for (var f = foods.length - 1; f >= 0; f--) { var food = foods[f]; food.update(); if (getDistance(head.x, head.y, food.x, food.y) < 40) { // Eat food score += food.value; LK.setScore(score); LK.getSound('eat').play(); // Add segments based on food value for (var s = 0; s < food.value; s++) { addWormSegment(); } // Remove food food.destroy(); foods.splice(f, 1); // Create particle effect createSoilEffect(food.x, food.y, 10); } } // Check collisions with obstacles for (var o = 0; o < obstacles.length; o++) { var obstacle = obstacles[o]; if (getDistance(head.x, head.y, obstacle.x, obstacle.y) < 45) { if (powerupActive && powerupType === 'invincibility') { // Destroy obstacle if invincible createSoilEffect(obstacle.x, obstacle.y, 15); obstacle.destroy(); obstacles.splice(o, 1); o--; continue; } else { // Game over on collision LK.getSound('hit').play(); LK.effects.flashScreen(0xFF0000, 500); // Update high score if (score > highScore) { highScore = score; storage.highScore = highScore; } LK.showGameOver(); return; } } } // Check collisions with powerups for (var pu = powerups.length - 1; pu >= 0; pu--) { var powerup = powerups[pu]; powerup.update(); if (getDistance(head.x, head.y, powerup.x, powerup.y) < 40) { // Collect powerup activatePowerup(powerup.type); // Remove powerup powerup.destroy(); powerups.splice(pu, 1); // Create particle effect createSoilEffect(powerup.x, powerup.y, 15); } } // Spawn new food foodTimer++; if (foodTimer >= SPAWN_FOOD_INTERVAL) { spawnFood(); foodTimer = 0; } // Spawn new obstacles based on level obstacleTimer++; if (obstacleTimer >= SPAWN_OBSTACLE_INTERVAL && obstacles.length < gameLevel + 2) { spawnObstacle(); obstacleTimer = 0; } // Spawn powerups occasionally powerupTimer++; if (powerupTimer >= SPAWN_POWERUP_INTERVAL) { spawnPowerup(); powerupTimer = 0; } // Update powerup duration if (powerupActive) { powerupTimeRemaining--; if (powerupTimeRemaining <= 0) { endPowerupEffect(); } } // Level up check if (score >= levelScore) { // Level up gameLevel++; storage.level = gameLevel; levelScore = gameLevel * 10; // Flash screen green LK.effects.flashScreen(0x00FF00, 500); // Speed increase with level MOVE_SPEED = 5 + gameLevel * 0.25; if (MOVE_SPEED > 10) { MOVE_SPEED = 10; } } // Update UI game.updateUI(); }; // Event handlers game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; return; } targetX = x; targetY = y; movingToTarget = true; }; game.move = function (x, y, obj) { if (gameStarted) { targetX = x; targetY = y; movingToTarget = true; } }; game.up = function (x, y, obj) { // Keep moving to the last target point };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,651 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ level: 1
+});
+
+/****
+* Classes
+****/
+var Food = Container.expand(function (isSpecial) {
+ var self = Container.call(this);
+ self.isSpecial = isSpecial || false;
+ self.value = self.isSpecial ? 3 : 1;
+ var foodGraphics = self.attachAsset(self.isSpecial ? 'food_special' : 'food_normal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ if (self.isSpecial) {
+ // Add pulsating animation for special food
+ self.pulseDirection = 1;
+ self.pulseMin = 0.85;
+ self.pulseMax = 1.15;
+ self.pulseSpeed = 0.01;
+ }
+ self.update = function () {
+ if (self.isSpecial) {
+ // Pulsating effect
+ if (self.pulseDirection > 0) {
+ foodGraphics.scale.x += self.pulseSpeed;
+ foodGraphics.scale.y += self.pulseSpeed;
+ if (foodGraphics.scale.x >= self.pulseMax) {
+ self.pulseDirection = -1;
+ }
+ } else {
+ foodGraphics.scale.x -= self.pulseSpeed;
+ foodGraphics.scale.y -= self.pulseSpeed;
+ if (foodGraphics.scale.x <= self.pulseMin) {
+ self.pulseDirection = 1;
+ }
+ }
+ }
+ };
+ return self;
+});
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var obstacleGraphics = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+var PowerUp = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || 'speed'; // speed, invincibility, grow
+ var color;
+ switch (self.type) {
+ case 'speed':
+ color = 0x00BFFF;
+ break;
+ case 'invincibility':
+ color = 0xFFFF00;
+ break;
+ case 'grow':
+ color = 0xFF00FF;
+ break;
+ default:
+ color = 0xFFFFFF;
+ }
+ // Create a shape for the powerup
+ var powerupGraphics = self.attachAsset('powerup_' + self.type, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Add pulsating animation
+ self.pulseDirection = 1;
+ self.pulseMin = 0.8;
+ self.pulseMax = 1.2;
+ self.pulseSpeed = 0.02;
+ self.update = function () {
+ // Pulsating effect
+ if (self.pulseDirection > 0) {
+ powerupGraphics.scale.x += self.pulseSpeed;
+ powerupGraphics.scale.y += self.pulseSpeed;
+ if (powerupGraphics.scale.x >= self.pulseMax) {
+ self.pulseDirection = -1;
+ }
+ } else {
+ powerupGraphics.scale.x -= self.pulseSpeed;
+ powerupGraphics.scale.y -= self.pulseSpeed;
+ if (powerupGraphics.scale.x <= self.pulseMin) {
+ self.pulseDirection = 1;
+ }
+ }
+ };
+ return self;
+});
+var SoilParticle = Container.expand(function () {
+ var self = Container.call(this);
+ var particleGraphics = self.attachAsset('soil_particle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.alpha = Math.random() * 0.5 + 0.2;
+ self.lifespan = Math.random() * 30 + 15;
+ self.velocityX = (Math.random() - 0.5) * 2;
+ self.velocityY = (Math.random() - 0.5) * 2;
+ self.update = function () {
+ self.x += self.velocityX;
+ self.y += self.velocityY;
+ self.lifespan--;
+ if (self.lifespan <= 10) {
+ self.alpha -= 0.1;
+ }
+ };
+ return self;
+});
+var WormSegment = Container.expand(function (isHead) {
+ var self = Container.call(this);
+ self.isHead = isHead || false;
+ var segmentGraphics = self.attachAsset(self.isHead ? 'worm_head' : 'worm_body', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Store previous position for smooth following
+ self.prevX = 0;
+ self.prevY = 0;
+ // Save position to follow
+ self.savePosition = function () {
+ self.prevX = self.x;
+ self.prevY = self.y;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x3E2723
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var SEGMENT_SPACING = 30;
+var STARTING_SEGMENTS = 5;
+var MAX_SEGMENTS = 50;
+var MOVE_SPEED = 5;
+var TURNING_SPEED = 0.1;
+var SPAWN_FOOD_INTERVAL = 60;
+var SPAWN_OBSTACLE_INTERVAL = 180;
+var SPAWN_POWERUP_INTERVAL = 600;
+var SPECIAL_FOOD_CHANCE = 0.2;
+var POWERUP_DURATION = 300;
+// Game variables
+var wormSegments = [];
+var foods = [];
+var obstacles = [];
+var powerups = [];
+var soilParticles = [];
+var targetX = 0;
+var targetY = 0;
+var score = 0;
+var gameLevel = storage.level || 1;
+var highScore = storage.highScore || 0;
+var movingToTarget = false;
+var wormAngle = 0;
+var foodTimer = 0;
+var obstacleTimer = 0;
+var powerupTimer = 0;
+var powerupActive = false;
+var powerupType = null;
+var powerupTimeRemaining = 0;
+var gameStarted = false;
+var levelScore = gameLevel * 10;
+// Create background with soil texture
+function createBackground() {
+ var backgroundContainer = new Container();
+ game.addChild(backgroundContainer);
+ var tileSize = 100;
+ for (var x = 0; x < GAME_WIDTH; x += tileSize) {
+ for (var y = 0; y < GAME_HEIGHT; y += tileSize) {
+ var tile = LK.getAsset('background_tile', {
+ anchorX: 0,
+ anchorY: 0,
+ width: tileSize,
+ height: tileSize,
+ alpha: 0.7 + Math.random() * 0.3
+ });
+ tile.x = x;
+ tile.y = y;
+ tile.rotation = Math.random() * Math.PI * 2;
+ tile.scale.x = 0.9 + Math.random() * 0.2;
+ tile.scale.y = 0.9 + Math.random() * 0.2;
+ backgroundContainer.addChild(tile);
+ }
+ }
+}
+// Initialize worm
+function createWorm() {
+ // Create head
+ var head = new WormSegment(true);
+ head.x = GAME_WIDTH / 2;
+ head.y = GAME_HEIGHT / 2;
+ game.addChild(head);
+ wormSegments.push(head);
+ // Create initial body segments
+ for (var i = 0; i < STARTING_SEGMENTS; i++) {
+ addWormSegment();
+ }
+}
+// Add new segment to the worm
+function addWormSegment() {
+ if (wormSegments.length >= MAX_SEGMENTS) {
+ return;
+ }
+ var lastSegment = wormSegments[wormSegments.length - 1];
+ var newSegment = new WormSegment(false);
+ newSegment.x = lastSegment.x;
+ newSegment.y = lastSegment.y;
+ game.addChild(newSegment);
+ wormSegments.push(newSegment);
+}
+// Spawn a food item at a random position
+function spawnFood() {
+ var isSpecial = Math.random() < SPECIAL_FOOD_CHANCE;
+ var food = new Food(isSpecial);
+ // Position food randomly away from edges
+ food.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ food.y = Math.random() * (GAME_HEIGHT - 200) + 100;
+ // Make sure food doesn't overlap with obstacles
+ for (var i = 0; i < obstacles.length; i++) {
+ if (getDistance(food.x, food.y, obstacles[i].x, obstacles[i].y) < 100) {
+ // Reposition if too close to an obstacle
+ food.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ food.y = Math.random() * (GAME_HEIGHT - 200) + 100;
+ i = -1; // Reset loop to check again
+ }
+ }
+ game.addChild(food);
+ foods.push(food);
+}
+// Spawn an obstacle
+function spawnObstacle() {
+ var obstacle = new Obstacle();
+ // Position obstacle randomly away from edges and worm head
+ var head = wormSegments[0];
+ do {
+ obstacle.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ obstacle.y = Math.random() * (GAME_HEIGHT - 200) + 100;
+ } while (getDistance(obstacle.x, obstacle.y, head.x, head.y) < 300);
+ game.addChild(obstacle);
+ obstacles.push(obstacle);
+}
+// Spawn a power-up
+function spawnPowerup() {
+ var types = ['speed', 'invincibility', 'grow'];
+ var randomType = types[Math.floor(Math.random() * types.length)];
+ var powerup = new PowerUp(randomType);
+ // Position powerup randomly away from edges
+ powerup.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ powerup.y = Math.random() * (GAME_HEIGHT - 200) + 100;
+ // Make sure powerup doesn't overlap with obstacles
+ for (var i = 0; i < obstacles.length; i++) {
+ if (getDistance(powerup.x, powerup.y, obstacles[i].x, obstacles[i].y) < 100) {
+ // Reposition if too close to an obstacle
+ powerup.x = Math.random() * (GAME_WIDTH - 200) + 100;
+ powerup.y = Math.random() * (GAME_HEIGHT - 200) + 100;
+ i = -1; // Reset loop to check again
+ }
+ }
+ game.addChild(powerup);
+ powerups.push(powerup);
+}
+// Create soil particles effect
+function createSoilEffect(x, y, count) {
+ for (var i = 0; i < count; i++) {
+ var particle = new SoilParticle();
+ particle.x = x;
+ particle.y = y;
+ game.addChild(particle);
+ soilParticles.push(particle);
+ }
+}
+// Calculate distance between two points
+function getDistance(x1, y1, x2, y2) {
+ return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
+}
+// Activate powerup
+function activatePowerup(type) {
+ powerupActive = true;
+ powerupType = type;
+ powerupTimeRemaining = POWERUP_DURATION;
+ LK.getSound('powerup').play();
+ // Apply power-up effects
+ switch (type) {
+ case 'speed':
+ MOVE_SPEED *= 1.75;
+ break;
+ case 'invincibility':
+ // Visual effect for invincibility
+ for (var i = 0; i < wormSegments.length; i++) {
+ tween(wormSegments[i], {
+ alpha: 0.7
+ }, {
+ duration: 300
+ });
+ }
+ break;
+ case 'grow':
+ // Add multiple segments at once
+ for (var j = 0; j < 3; j++) {
+ addWormSegment();
+ }
+ break;
+ }
+}
+// End powerup effect
+function endPowerupEffect() {
+ switch (powerupType) {
+ case 'speed':
+ MOVE_SPEED = 5;
+ break;
+ case 'invincibility':
+ // Reset visual effect
+ for (var i = 0; i < wormSegments.length; i++) {
+ tween(wormSegments[i], {
+ alpha: 1
+ }, {
+ duration: 300
+ });
+ }
+ break;
+ }
+ powerupActive = false;
+ powerupType = null;
+}
+// Setup UI elements
+function setupUI() {
+ // Score text
+ var scoreTxt = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ scoreTxt.anchor.set(0, 0);
+ LK.gui.topRight.addChild(scoreTxt);
+ scoreTxt.x = -scoreTxt.width - 20;
+ scoreTxt.y = 20;
+ // Level text
+ var levelTxt = new Text2('Level: ' + gameLevel, {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ levelTxt.anchor.set(0, 0);
+ LK.gui.topRight.addChild(levelTxt);
+ levelTxt.x = -levelTxt.width - 20;
+ levelTxt.y = 100;
+ // High score text
+ var highScoreTxt = new Text2('Best: ' + highScore, {
+ size: 50,
+ fill: 0xFFD700
+ });
+ highScoreTxt.anchor.set(0, 0);
+ LK.gui.topRight.addChild(highScoreTxt);
+ highScoreTxt.x = -highScoreTxt.width - 20;
+ highScoreTxt.y = 160;
+ // Next level text
+ var nextLevelTxt = new Text2('Next Level: ' + levelScore, {
+ size: 50,
+ fill: 0x32CD32
+ });
+ nextLevelTxt.anchor.set(0.5, 0);
+ LK.gui.top.addChild(nextLevelTxt);
+ nextLevelTxt.y = 20;
+ // Powerup indicator
+ var powerupTxt = new Text2('', {
+ size: 60,
+ fill: 0xFFFF00
+ });
+ powerupTxt.anchor.set(0, 0);
+ LK.gui.topLeft.addChild(powerupTxt);
+ powerupTxt.x = 120; // Keep away from the top-left 100x100 px area
+ powerupTxt.y = 20;
+ // Start instructions
+ var instructionsTxt = new Text2('Tap to start\nDrag to move your worm\nEat food to grow', {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ instructionsTxt.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(instructionsTxt);
+ // Update UI function
+ game.updateUI = function () {
+ scoreTxt.setText('Score: ' + score);
+ scoreTxt.x = -scoreTxt.width - 20;
+ levelTxt.setText('Level: ' + gameLevel);
+ levelTxt.x = -levelTxt.width - 20;
+ highScoreTxt.setText('Best: ' + highScore);
+ highScoreTxt.x = -highScoreTxt.width - 20;
+ nextLevelTxt.setText('Next Level: ' + (levelScore - score));
+ if (powerupActive) {
+ var timeLeft = Math.ceil(powerupTimeRemaining / 60);
+ powerupTxt.setText(powerupType.toUpperCase() + ': ' + timeLeft + 's');
+ } else {
+ powerupTxt.setText('');
+ }
+ if (gameStarted) {
+ instructionsTxt.alpha = 0;
+ }
+ };
+}
+// Initialize game
+function initGame() {
+ // Reset game state
+ wormSegments = [];
+ foods = [];
+ obstacles = [];
+ powerups = [];
+ soilParticles = [];
+ score = 0;
+ movingToTarget = false;
+ wormAngle = 0;
+ foodTimer = 0;
+ obstacleTimer = 0;
+ powerupTimer = 0;
+ powerupActive = false;
+ powerupType = null;
+ powerupTimeRemaining = 0;
+ levelScore = gameLevel * 10;
+ MOVE_SPEED = 5;
+ // Set background
+ createBackground();
+ // Create the worm
+ createWorm();
+ // Initial food
+ for (var i = 0; i < 3; i++) {
+ spawnFood();
+ }
+ // Initial obstacles based on level
+ for (var j = 0; j < Math.min(gameLevel, 5); j++) {
+ spawnObstacle();
+ }
+ // Setup UI
+ setupUI();
+ // Play background music
+ LK.playMusic('bgmusic');
+}
+// Initialize the game
+initGame();
+// Game logic update function
+game.update = function () {
+ if (!gameStarted) {
+ return;
+ }
+ // Move worm head
+ var head = wormSegments[0];
+ if (movingToTarget) {
+ // Calculate angle to target
+ var dx = targetX - head.x;
+ var dy = targetY - head.y;
+ var targetAngle = Math.atan2(dy, dx);
+ // Smooth angle change
+ var angleDiff = targetAngle - wormAngle;
+ // Handle angle wrapping
+ if (angleDiff > Math.PI) {
+ angleDiff -= Math.PI * 2;
+ }
+ if (angleDiff < -Math.PI) {
+ angleDiff += Math.PI * 2;
+ }
+ // Apply gradual turning
+ wormAngle += angleDiff * TURNING_SPEED;
+ // Move in the current direction
+ head.savePosition();
+ head.x += Math.cos(wormAngle) * MOVE_SPEED;
+ head.y += Math.sin(wormAngle) * MOVE_SPEED;
+ // Create soil particles as the worm moves
+ if (LK.ticks % 3 === 0) {
+ createSoilEffect(head.x, head.y, 1);
+ }
+ // Check if close enough to target
+ if (getDistance(head.x, head.y, targetX, targetY) < 10) {
+ movingToTarget = false;
+ }
+ }
+ // Move body segments
+ for (var i = 1; i < wormSegments.length; i++) {
+ var segment = wormSegments[i];
+ var prevSegment = wormSegments[i - 1];
+ // Save current position before updating
+ segment.savePosition();
+ // Calculate direction to previous segment
+ var dx = prevSegment.prevX - segment.x;
+ var dy = prevSegment.prevY - segment.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ // Move towards the previous segment's saved position
+ if (distance > SEGMENT_SPACING) {
+ var moveRatio = (distance - SEGMENT_SPACING) / distance;
+ segment.x += dx * moveRatio;
+ segment.y += dy * moveRatio;
+ }
+ }
+ // Update soil particles
+ for (var p = soilParticles.length - 1; p >= 0; p--) {
+ var particle = soilParticles[p];
+ particle.update();
+ if (particle.lifespan <= 0 || particle.alpha <= 0) {
+ particle.destroy();
+ soilParticles.splice(p, 1);
+ }
+ }
+ // Boundary checking for worm head
+ if (head.x < 0) {
+ head.x = 0;
+ }
+ if (head.x > GAME_WIDTH) {
+ head.x = GAME_WIDTH;
+ }
+ if (head.y < 0) {
+ head.y = 0;
+ }
+ if (head.y > GAME_HEIGHT) {
+ head.y = GAME_HEIGHT;
+ }
+ // Check collisions with food
+ for (var f = foods.length - 1; f >= 0; f--) {
+ var food = foods[f];
+ food.update();
+ if (getDistance(head.x, head.y, food.x, food.y) < 40) {
+ // Eat food
+ score += food.value;
+ LK.setScore(score);
+ LK.getSound('eat').play();
+ // Add segments based on food value
+ for (var s = 0; s < food.value; s++) {
+ addWormSegment();
+ }
+ // Remove food
+ food.destroy();
+ foods.splice(f, 1);
+ // Create particle effect
+ createSoilEffect(food.x, food.y, 10);
+ }
+ }
+ // Check collisions with obstacles
+ for (var o = 0; o < obstacles.length; o++) {
+ var obstacle = obstacles[o];
+ if (getDistance(head.x, head.y, obstacle.x, obstacle.y) < 45) {
+ if (powerupActive && powerupType === 'invincibility') {
+ // Destroy obstacle if invincible
+ createSoilEffect(obstacle.x, obstacle.y, 15);
+ obstacle.destroy();
+ obstacles.splice(o, 1);
+ o--;
+ continue;
+ } else {
+ // Game over on collision
+ LK.getSound('hit').play();
+ LK.effects.flashScreen(0xFF0000, 500);
+ // Update high score
+ if (score > highScore) {
+ highScore = score;
+ storage.highScore = highScore;
+ }
+ LK.showGameOver();
+ return;
+ }
+ }
+ }
+ // Check collisions with powerups
+ for (var pu = powerups.length - 1; pu >= 0; pu--) {
+ var powerup = powerups[pu];
+ powerup.update();
+ if (getDistance(head.x, head.y, powerup.x, powerup.y) < 40) {
+ // Collect powerup
+ activatePowerup(powerup.type);
+ // Remove powerup
+ powerup.destroy();
+ powerups.splice(pu, 1);
+ // Create particle effect
+ createSoilEffect(powerup.x, powerup.y, 15);
+ }
+ }
+ // Spawn new food
+ foodTimer++;
+ if (foodTimer >= SPAWN_FOOD_INTERVAL) {
+ spawnFood();
+ foodTimer = 0;
+ }
+ // Spawn new obstacles based on level
+ obstacleTimer++;
+ if (obstacleTimer >= SPAWN_OBSTACLE_INTERVAL && obstacles.length < gameLevel + 2) {
+ spawnObstacle();
+ obstacleTimer = 0;
+ }
+ // Spawn powerups occasionally
+ powerupTimer++;
+ if (powerupTimer >= SPAWN_POWERUP_INTERVAL) {
+ spawnPowerup();
+ powerupTimer = 0;
+ }
+ // Update powerup duration
+ if (powerupActive) {
+ powerupTimeRemaining--;
+ if (powerupTimeRemaining <= 0) {
+ endPowerupEffect();
+ }
+ }
+ // Level up check
+ if (score >= levelScore) {
+ // Level up
+ gameLevel++;
+ storage.level = gameLevel;
+ levelScore = gameLevel * 10;
+ // Flash screen green
+ LK.effects.flashScreen(0x00FF00, 500);
+ // Speed increase with level
+ MOVE_SPEED = 5 + gameLevel * 0.25;
+ if (MOVE_SPEED > 10) {
+ MOVE_SPEED = 10;
+ }
+ }
+ // Update UI
+ game.updateUI();
+};
+// Event handlers
+game.down = function (x, y, obj) {
+ if (!gameStarted) {
+ gameStarted = true;
+ return;
+ }
+ targetX = x;
+ targetY = y;
+ movingToTarget = true;
+};
+game.move = function (x, y, obj) {
+ if (gameStarted) {
+ targetX = x;
+ targetY = y;
+ movingToTarget = true;
+ }
+};
+game.up = function (x, y, obj) {
+ // Keep moving to the last target point
+};
\ No newline at end of file