User prompt
Arka plan siyah olsun
User prompt
Oyunda karakter ten daha büyük düşmanlar her zaman olsun
User prompt
Dikene çarptığında bir sefer parçalansın ve diken yok olsun. Parça sayısı 3 4 parça olsun
User prompt
Oyuna diken ekle. Karakter dikenden küçükken altına saklansın dikenden büyük olunca dokunduğunda küçük parçalara ayrılsın
User prompt
Bunları yap
User prompt
Oyuncu parmağını çekince karakter yavaşlamasın
User prompt
Oyuncu gıda yedikçe büyüsün
User prompt
Ekrandan parmağı çekince oyuncu harekete devam etsin
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'x')' in or related to this line: 'stage.x = 1024 - camX;' Line Number: 369
User prompt
Ekran oyuncuyu takip etsin
User prompt
Oyundaki sınırları genişlet
User prompt
Oyuncu hücresinin hareketini parmakla kaydırma hareketi ile yönlendir
User prompt
Düşmanları yüzde 70 yavaşlat
User prompt
Oyundaki karakterler çok daha yavaş olsun
Code edit (1 edits merged)
Please save this source code
User prompt
Cell Eater: Agar.io Clone
Initial prompt
Agar io tarzı bir oyun yapmak istiyorum
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Enemy Cell Class var EnemyCell = Container.expand(function () { var self = Container.call(this); var cell = self.attachAsset('enemyCell', { anchorX: 0.5, anchorY: 0.5 }); self.radius = cell.width / 2; self.lastX = self.x; self.lastY = self.y; self.lastRadius = self.radius; self.setSize = function (diameter) { cell.width = diameter; cell.height = diameter; self.radius = diameter / 2; }; // AI movement target self.targetX = self.x; self.targetY = self.y; self.speed = (3 + 40 / (self.radius + 40)) * 0.3; // 70% slower movement for enemies self.update = function () { // Move towards target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); self.lastX = self.x; self.lastY = self.y; self.lastRadius = self.radius; if (dist > self.speed) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } else { self.x = self.targetX; self.y = self.targetY; } }; return self; }); // Food Cell Class var FoodCell = Container.expand(function () { var self = Container.call(this); var cell = self.attachAsset('foodCell', { anchorX: 0.5, anchorY: 0.5 }); self.radius = cell.width / 2; self.setSize = function (diameter) { cell.width = diameter; cell.height = diameter; self.radius = diameter / 2; }; return self; }); // Player Cell Class var PlayerCell = Container.expand(function () { var self = Container.call(this); var cell = self.attachAsset('playerCell', { anchorX: 0.5, anchorY: 0.5 }); self.radius = cell.width / 2; self.lastX = self.x; self.lastY = self.y; self.lastRadius = self.radius; self.setSize = function (diameter) { cell.width = diameter; cell.height = diameter; self.radius = diameter / 2; }; // For smooth movement self.targetX = self.x; self.targetY = self.y; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.lastRadius = self.radius; // Drag direction control: move in drag direction if dragging var speed = 4 + 40 / (self.radius + 40); // Slower movement for player, larger cells move slower if (typeof dragDirX !== "undefined" && (dragDirX !== 0 || dragDirY !== 0)) { // Move in drag direction self.x += dragDirX * speed; self.y += dragDirY * speed; } }; return self; }); // Spike Cell Class var SpikeCell = Container.expand(function () { var self = Container.call(this); var cell = self.attachAsset('spikeCell', { anchorX: 0.5, anchorY: 0.5 }); self.radius = cell.width / 2; self.setSize = function (diameter) { cell.width = diameter; cell.height = diameter; self.radius = diameter / 2; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Food cell: yellow ellipse // Enemy cell: blue ellipse // Player cell: green ellipse // Arena size (expanded for a much larger play area) var ARENA_WIDTH = 4096; var ARENA_HEIGHT = 5464; // Player cell var player = new PlayerCell(); player.setSize(180); player.x = ARENA_WIDTH / 2; player.y = ARENA_HEIGHT / 2; game.addChild(player); // Arrays for enemies and food var enemies = []; var foods = []; var spikes = []; // Score display var score = 0; var scoreTxt = new Text2('Score: 0', { size: 90, fill: 0x222222 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: spawn food at random position function spawnFood() { var food = new FoodCell(); var size = 60 + Math.floor(Math.random() * 40); food.setSize(size); food.x = 100 + Math.random() * (ARENA_WIDTH - 200); food.y = 200 + Math.random() * (ARENA_HEIGHT - 400); foods.push(food); game.addChild(food); } // Helper: spawn enemy at random position and size function spawnEnemy() { var enemy = new EnemyCell(); var size = 120 + Math.floor(Math.random() * 120); enemy.setSize(size); // Avoid spawning too close to player var safe = false; while (!safe) { enemy.x = 100 + Math.random() * (ARENA_WIDTH - 200); enemy.y = 200 + Math.random() * (ARENA_HEIGHT - 400); var dx = enemy.x - player.x; var dy = enemy.y - player.y; if (Math.sqrt(dx * dx + dy * dy) > 400) safe = true; } // Set initial AI target enemy.targetX = enemy.x; enemy.targetY = enemy.y; enemies.push(enemy); game.addChild(enemy); } // Helper: spawn spike at random position function spawnSpike() { var spike = new SpikeCell(); var size = 140 + Math.floor(Math.random() * 40); spike.setSize(size); // Avoid spawning too close to player var safe = false; while (!safe) { spike.x = 100 + Math.random() * (ARENA_WIDTH - 200); spike.y = 200 + Math.random() * (ARENA_HEIGHT - 400); var dx = spike.x - player.x; var dy = spike.y - player.y; if (Math.sqrt(dx * dx + dy * dy) > 500) safe = true; } spikes.push(spike); game.addChild(spike); } // Initial spawn for (var i = 0; i < 18; i++) spawnFood(); for (var i = 0; i < 7; i++) spawnEnemy(); for (var i = 0; i < 5; i++) spawnSpike(); // Drag-to-move: swipe direction controls player movement var dragging = false; var dragStartX = 0; var dragStartY = 0; var dragLastX = 0; var dragLastY = 0; var dragDirX = 0; var dragDirY = 0; function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } game.down = function (x, y, obj) { dragging = true; dragStartX = x; dragStartY = y; dragLastX = x; dragLastY = y; dragDirX = 0; dragDirY = 0; }; game.move = function (x, y, obj) { if (dragging) { // Calculate drag direction vector dragDirX = x - dragStartX; dragDirY = y - dragStartY; dragLastX = x; dragLastY = y; // Normalize direction for smooth control var len = Math.sqrt(dragDirX * dragDirX + dragDirY * dragDirY); if (len > 20) { // Only if drag is significant dragDirX /= len; dragDirY /= len; } else { dragDirX = 0; dragDirY = 0; } } }; game.up = function (x, y, obj) { dragging = false; // Do not reset dragDirX/dragDirY here; keep last direction for inertia }; // Main update loop game.update = function () { // Update player player.update(); // Only update and check collisions for enemies and foods near the camera view for performance var camX = clamp(player.x, 1024, ARENA_WIDTH - 1024); var camY = clamp(player.y, 1366, ARENA_HEIGHT - 1366); var camLeft = camX - 1200, camRight = camX + 1200, camTop = camY - 1600, camBottom = camY + 1600; // Update enemies (only those near camera) for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Only update if near camera if (enemy.x > camLeft - 400 && enemy.x < camRight + 400 && enemy.y > camTop - 400 && enemy.y < camBottom + 400) { // AI: If player is smaller, chase; if bigger, flee; else random walk var dx = player.x - enemy.x; var dy = player.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); if (enemy.radius > player.radius * 1.15) { // Enemy is bigger: chase player if not too close to border if (dist < 900) { // Move towards player enemy.targetX = clamp(player.x, enemy.radius, ARENA_WIDTH - enemy.radius); enemy.targetY = clamp(player.y, enemy.radius, ARENA_HEIGHT - enemy.radius); } else { // Random walk if (LK.ticks % 120 === 0) { enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200); enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400); } } } else if (enemy.radius < player.radius * 0.85) { // Enemy is smaller: flee from player if (dist < 700) { var angle = Math.atan2(dy, dx) + Math.PI; // Opposite direction var fleeDist = 300; enemy.targetX = clamp(enemy.x + Math.cos(angle) * fleeDist, enemy.radius, ARENA_WIDTH - enemy.radius); enemy.targetY = clamp(enemy.y + Math.sin(angle) * fleeDist, enemy.radius, ARENA_HEIGHT - enemy.radius); } else { // Random walk if (LK.ticks % 120 === 0) { enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200); enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400); } } } else { // Similar size: random walk if (LK.ticks % 120 === 0) { enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200); enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400); } } enemy.update(); } } // --- Collision: Player and spike interaction --- var playerHidingUnderSpike = false; for (var i = 0; i < spikes.length; i++) { var spike = spikes[i]; // Only check if spike is near player/camera if (spike.x > camLeft - 300 && spike.x < camRight + 300 && spike.y > camTop - 300 && spike.y < camBottom + 300) { var dx = player.x - spike.x; var dy = player.y - spike.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.radius + spike.radius * 0.7) { if (player.radius < spike.radius * 0.95) { // Player is small: hide under spike (draw under, no effect) playerHidingUnderSpike = true; // Move player visually under spike (z-order handled by addChild order, so do nothing) } else { // Player is big: split into 3-4 pieces and destroy spike (only once per spike) var splitCount = 3 + Math.floor(Math.random() * 2); // 3 or 4 for (var s = 0; s < splitCount; s++) { var food = new FoodCell(); var size = 60 + Math.floor(Math.random() * 30); food.setSize(size); var angle = Math.random() * Math.PI * 2; var distF = 60 + Math.random() * 40; food.x = player.x + Math.cos(angle) * distF; food.y = player.y + Math.sin(angle) * distF; foods.push(food); game.addChild(food); } // Shrink player drastically player.setSize(Math.max(120, player.radius * 0.4)); LK.effects.flashObject(player, 0x888888, 800); // Destroy spike and remove from array spike.destroy(); spikes.splice(i, 1); break; // Only trigger once per frame } } } } // --- Collision: Player eats food (only foods near player/camera) --- for (var i = foods.length - 1; i >= 0; i--) { var food = foods[i]; // Only check if food is near player/camera if (food.x > camLeft - 200 && food.x < camRight + 200 && food.y > camTop - 200 && food.y < camBottom + 200) { var dx = player.x - food.x; var dy = player.y - food.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.radius + food.radius * 0.7) { // Eat food: grow player by a fixed amount var growAmount = Math.max(12, food.radius * 0.6); var newDiameter = player.radius * 2 + growAmount; newDiameter = Math.min(newDiameter, 600); // Cap max size player.setSize(newDiameter); // Score score += 1; scoreTxt.setText('Score: ' + score); // Remove food food.destroy(); foods.splice(i, 1); // Spawn new food spawnFood(); } } } // --- Collision: Enemy eats food (only if both are near camera) --- for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; if (enemy.x > camLeft - 400 && enemy.x < camRight + 400 && enemy.y > camTop - 400 && enemy.y < camBottom + 400) { for (var i = foods.length - 1; i >= 0; i--) { var food = foods[i]; if (food.x > camLeft - 200 && food.x < camRight + 200 && food.y > camTop - 200 && food.y < camBottom + 200) { var dx = enemy.x - food.x; var dy = enemy.y - food.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < enemy.radius + food.radius * 0.7) { // Enemy eats food var newSize = Math.min(enemy.radius * 2 + 12, 400); enemy.setSize(newSize); food.destroy(); foods.splice(i, 1); spawnFood(); } } } } } // --- Collision: Player eats enemy or is eaten --- for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var dx = player.x - enemy.x; var dy = player.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.radius + enemy.radius * 0.7) { if (player.radius > enemy.radius * 1.15) { // Player eats enemy var newSize = Math.min(player.radius * 2 + enemy.radius * 2 * 0.7, 700); player.setSize(newSize); score += 5; scoreTxt.setText('Score: ' + score); enemy.destroy(); enemies.splice(i, 1); // After removing, ensure at least one enemy is always bigger than the player var hasBigger = false; for (var j = 0; j < enemies.length; j++) { if (enemies[j].radius > player.radius * 1.15) { hasBigger = true; break; } } if (!hasBigger) { // Spawn a new enemy that is always bigger than the player var bigEnemy = new EnemyCell(); var bigSize = Math.max(player.radius * 1.25, 220 + Math.random() * 80); bigEnemy.setSize(bigSize); // Place far from player var safe = false; while (!safe) { bigEnemy.x = 100 + Math.random() * (ARENA_WIDTH - 200); bigEnemy.y = 200 + Math.random() * (ARENA_HEIGHT - 400); var dx2 = bigEnemy.x - player.x; var dy2 = bigEnemy.y - player.y; if (Math.sqrt(dx2 * dx2 + dy2 * dy2) > 600) safe = true; } bigEnemy.targetX = bigEnemy.x; bigEnemy.targetY = bigEnemy.y; enemies.push(bigEnemy); game.addChild(bigEnemy); } else { spawnEnemy(); } } else if (enemy.radius > player.radius * 1.15) { // Player is eaten LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } } // --- Enemy eats enemy --- for (var i = enemies.length - 1; i >= 0; i--) { var enemyA = enemies[i]; for (var j = enemies.length - 1; j >= 0; j--) { if (i === j) continue; var enemyB = enemies[j]; var dx = enemyA.x - enemyB.x; var dy = enemyA.y - enemyB.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < enemyA.radius + enemyB.radius * 0.7) { if (enemyA.radius > enemyB.radius * 1.15) { // A eats B var newSize = Math.min(enemyA.radius * 2 + enemyB.radius * 2 * 0.5, 500); enemyA.setSize(newSize); enemyB.destroy(); enemies.splice(j, 1); spawnEnemy(); if (j < i) i--; // Adjust index if needed } } } } // Clamp player inside arena player.x = clamp(player.x, player.radius, ARENA_WIDTH - player.radius); player.y = clamp(player.y, player.radius, ARENA_HEIGHT - player.radius); // Clamp enemies inside arena for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; enemy.x = clamp(enemy.x, enemy.radius, ARENA_WIDTH - enemy.radius); enemy.y = clamp(enemy.y, enemy.radius, ARENA_HEIGHT - enemy.radius); } // Camera follow: center the visible area on the player // LK.stage is the root container for all game objects // The visible area is 2048x2732 (game resolution) var camX = clamp(player.x, 1024, ARENA_WIDTH - 1024); var camY = clamp(player.y, 1366, ARENA_HEIGHT - 1366); game.x = 1024 - camX; game.y = 1366 - camY; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Cell Class
var EnemyCell = Container.expand(function () {
var self = Container.call(this);
var cell = self.attachAsset('enemyCell', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = cell.width / 2;
self.lastX = self.x;
self.lastY = self.y;
self.lastRadius = self.radius;
self.setSize = function (diameter) {
cell.width = diameter;
cell.height = diameter;
self.radius = diameter / 2;
};
// AI movement target
self.targetX = self.x;
self.targetY = self.y;
self.speed = (3 + 40 / (self.radius + 40)) * 0.3; // 70% slower movement for enemies
self.update = function () {
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
self.lastX = self.x;
self.lastY = self.y;
self.lastRadius = self.radius;
if (dist > self.speed) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
} else {
self.x = self.targetX;
self.y = self.targetY;
}
};
return self;
});
// Food Cell Class
var FoodCell = Container.expand(function () {
var self = Container.call(this);
var cell = self.attachAsset('foodCell', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = cell.width / 2;
self.setSize = function (diameter) {
cell.width = diameter;
cell.height = diameter;
self.radius = diameter / 2;
};
return self;
});
// Player Cell Class
var PlayerCell = Container.expand(function () {
var self = Container.call(this);
var cell = self.attachAsset('playerCell', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = cell.width / 2;
self.lastX = self.x;
self.lastY = self.y;
self.lastRadius = self.radius;
self.setSize = function (diameter) {
cell.width = diameter;
cell.height = diameter;
self.radius = diameter / 2;
};
// For smooth movement
self.targetX = self.x;
self.targetY = self.y;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.lastRadius = self.radius;
// Drag direction control: move in drag direction if dragging
var speed = 4 + 40 / (self.radius + 40); // Slower movement for player, larger cells move slower
if (typeof dragDirX !== "undefined" && (dragDirX !== 0 || dragDirY !== 0)) {
// Move in drag direction
self.x += dragDirX * speed;
self.y += dragDirY * speed;
}
};
return self;
});
// Spike Cell Class
var SpikeCell = Container.expand(function () {
var self = Container.call(this);
var cell = self.attachAsset('spikeCell', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = cell.width / 2;
self.setSize = function (diameter) {
cell.width = diameter;
cell.height = diameter;
self.radius = diameter / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Food cell: yellow ellipse
// Enemy cell: blue ellipse
// Player cell: green ellipse
// Arena size (expanded for a much larger play area)
var ARENA_WIDTH = 4096;
var ARENA_HEIGHT = 5464;
// Player cell
var player = new PlayerCell();
player.setSize(180);
player.x = ARENA_WIDTH / 2;
player.y = ARENA_HEIGHT / 2;
game.addChild(player);
// Arrays for enemies and food
var enemies = [];
var foods = [];
var spikes = [];
// Score display
var score = 0;
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: 0x222222
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn food at random position
function spawnFood() {
var food = new FoodCell();
var size = 60 + Math.floor(Math.random() * 40);
food.setSize(size);
food.x = 100 + Math.random() * (ARENA_WIDTH - 200);
food.y = 200 + Math.random() * (ARENA_HEIGHT - 400);
foods.push(food);
game.addChild(food);
}
// Helper: spawn enemy at random position and size
function spawnEnemy() {
var enemy = new EnemyCell();
var size = 120 + Math.floor(Math.random() * 120);
enemy.setSize(size);
// Avoid spawning too close to player
var safe = false;
while (!safe) {
enemy.x = 100 + Math.random() * (ARENA_WIDTH - 200);
enemy.y = 200 + Math.random() * (ARENA_HEIGHT - 400);
var dx = enemy.x - player.x;
var dy = enemy.y - player.y;
if (Math.sqrt(dx * dx + dy * dy) > 400) safe = true;
}
// Set initial AI target
enemy.targetX = enemy.x;
enemy.targetY = enemy.y;
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: spawn spike at random position
function spawnSpike() {
var spike = new SpikeCell();
var size = 140 + Math.floor(Math.random() * 40);
spike.setSize(size);
// Avoid spawning too close to player
var safe = false;
while (!safe) {
spike.x = 100 + Math.random() * (ARENA_WIDTH - 200);
spike.y = 200 + Math.random() * (ARENA_HEIGHT - 400);
var dx = spike.x - player.x;
var dy = spike.y - player.y;
if (Math.sqrt(dx * dx + dy * dy) > 500) safe = true;
}
spikes.push(spike);
game.addChild(spike);
}
// Initial spawn
for (var i = 0; i < 18; i++) spawnFood();
for (var i = 0; i < 7; i++) spawnEnemy();
for (var i = 0; i < 5; i++) spawnSpike();
// Drag-to-move: swipe direction controls player movement
var dragging = false;
var dragStartX = 0;
var dragStartY = 0;
var dragLastX = 0;
var dragLastY = 0;
var dragDirX = 0;
var dragDirY = 0;
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
game.down = function (x, y, obj) {
dragging = true;
dragStartX = x;
dragStartY = y;
dragLastX = x;
dragLastY = y;
dragDirX = 0;
dragDirY = 0;
};
game.move = function (x, y, obj) {
if (dragging) {
// Calculate drag direction vector
dragDirX = x - dragStartX;
dragDirY = y - dragStartY;
dragLastX = x;
dragLastY = y;
// Normalize direction for smooth control
var len = Math.sqrt(dragDirX * dragDirX + dragDirY * dragDirY);
if (len > 20) {
// Only if drag is significant
dragDirX /= len;
dragDirY /= len;
} else {
dragDirX = 0;
dragDirY = 0;
}
}
};
game.up = function (x, y, obj) {
dragging = false;
// Do not reset dragDirX/dragDirY here; keep last direction for inertia
};
// Main update loop
game.update = function () {
// Update player
player.update();
// Only update and check collisions for enemies and foods near the camera view for performance
var camX = clamp(player.x, 1024, ARENA_WIDTH - 1024);
var camY = clamp(player.y, 1366, ARENA_HEIGHT - 1366);
var camLeft = camX - 1200,
camRight = camX + 1200,
camTop = camY - 1600,
camBottom = camY + 1600;
// Update enemies (only those near camera)
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
// Only update if near camera
if (enemy.x > camLeft - 400 && enemy.x < camRight + 400 && enemy.y > camTop - 400 && enemy.y < camBottom + 400) {
// AI: If player is smaller, chase; if bigger, flee; else random walk
var dx = player.x - enemy.x;
var dy = player.y - enemy.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (enemy.radius > player.radius * 1.15) {
// Enemy is bigger: chase player if not too close to border
if (dist < 900) {
// Move towards player
enemy.targetX = clamp(player.x, enemy.radius, ARENA_WIDTH - enemy.radius);
enemy.targetY = clamp(player.y, enemy.radius, ARENA_HEIGHT - enemy.radius);
} else {
// Random walk
if (LK.ticks % 120 === 0) {
enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200);
enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400);
}
}
} else if (enemy.radius < player.radius * 0.85) {
// Enemy is smaller: flee from player
if (dist < 700) {
var angle = Math.atan2(dy, dx) + Math.PI; // Opposite direction
var fleeDist = 300;
enemy.targetX = clamp(enemy.x + Math.cos(angle) * fleeDist, enemy.radius, ARENA_WIDTH - enemy.radius);
enemy.targetY = clamp(enemy.y + Math.sin(angle) * fleeDist, enemy.radius, ARENA_HEIGHT - enemy.radius);
} else {
// Random walk
if (LK.ticks % 120 === 0) {
enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200);
enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400);
}
}
} else {
// Similar size: random walk
if (LK.ticks % 120 === 0) {
enemy.targetX = 100 + Math.random() * (ARENA_WIDTH - 200);
enemy.targetY = 200 + Math.random() * (ARENA_HEIGHT - 400);
}
}
enemy.update();
}
}
// --- Collision: Player and spike interaction ---
var playerHidingUnderSpike = false;
for (var i = 0; i < spikes.length; i++) {
var spike = spikes[i];
// Only check if spike is near player/camera
if (spike.x > camLeft - 300 && spike.x < camRight + 300 && spike.y > camTop - 300 && spike.y < camBottom + 300) {
var dx = player.x - spike.x;
var dy = player.y - spike.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < player.radius + spike.radius * 0.7) {
if (player.radius < spike.radius * 0.95) {
// Player is small: hide under spike (draw under, no effect)
playerHidingUnderSpike = true;
// Move player visually under spike (z-order handled by addChild order, so do nothing)
} else {
// Player is big: split into 3-4 pieces and destroy spike (only once per spike)
var splitCount = 3 + Math.floor(Math.random() * 2); // 3 or 4
for (var s = 0; s < splitCount; s++) {
var food = new FoodCell();
var size = 60 + Math.floor(Math.random() * 30);
food.setSize(size);
var angle = Math.random() * Math.PI * 2;
var distF = 60 + Math.random() * 40;
food.x = player.x + Math.cos(angle) * distF;
food.y = player.y + Math.sin(angle) * distF;
foods.push(food);
game.addChild(food);
}
// Shrink player drastically
player.setSize(Math.max(120, player.radius * 0.4));
LK.effects.flashObject(player, 0x888888, 800);
// Destroy spike and remove from array
spike.destroy();
spikes.splice(i, 1);
break; // Only trigger once per frame
}
}
}
}
// --- Collision: Player eats food (only foods near player/camera) ---
for (var i = foods.length - 1; i >= 0; i--) {
var food = foods[i];
// Only check if food is near player/camera
if (food.x > camLeft - 200 && food.x < camRight + 200 && food.y > camTop - 200 && food.y < camBottom + 200) {
var dx = player.x - food.x;
var dy = player.y - food.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < player.radius + food.radius * 0.7) {
// Eat food: grow player by a fixed amount
var growAmount = Math.max(12, food.radius * 0.6);
var newDiameter = player.radius * 2 + growAmount;
newDiameter = Math.min(newDiameter, 600); // Cap max size
player.setSize(newDiameter);
// Score
score += 1;
scoreTxt.setText('Score: ' + score);
// Remove food
food.destroy();
foods.splice(i, 1);
// Spawn new food
spawnFood();
}
}
}
// --- Collision: Enemy eats food (only if both are near camera) ---
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
if (enemy.x > camLeft - 400 && enemy.x < camRight + 400 && enemy.y > camTop - 400 && enemy.y < camBottom + 400) {
for (var i = foods.length - 1; i >= 0; i--) {
var food = foods[i];
if (food.x > camLeft - 200 && food.x < camRight + 200 && food.y > camTop - 200 && food.y < camBottom + 200) {
var dx = enemy.x - food.x;
var dy = enemy.y - food.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < enemy.radius + food.radius * 0.7) {
// Enemy eats food
var newSize = Math.min(enemy.radius * 2 + 12, 400);
enemy.setSize(newSize);
food.destroy();
foods.splice(i, 1);
spawnFood();
}
}
}
}
}
// --- Collision: Player eats enemy or is eaten ---
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var dx = player.x - enemy.x;
var dy = player.y - enemy.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < player.radius + enemy.radius * 0.7) {
if (player.radius > enemy.radius * 1.15) {
// Player eats enemy
var newSize = Math.min(player.radius * 2 + enemy.radius * 2 * 0.7, 700);
player.setSize(newSize);
score += 5;
scoreTxt.setText('Score: ' + score);
enemy.destroy();
enemies.splice(i, 1);
// After removing, ensure at least one enemy is always bigger than the player
var hasBigger = false;
for (var j = 0; j < enemies.length; j++) {
if (enemies[j].radius > player.radius * 1.15) {
hasBigger = true;
break;
}
}
if (!hasBigger) {
// Spawn a new enemy that is always bigger than the player
var bigEnemy = new EnemyCell();
var bigSize = Math.max(player.radius * 1.25, 220 + Math.random() * 80);
bigEnemy.setSize(bigSize);
// Place far from player
var safe = false;
while (!safe) {
bigEnemy.x = 100 + Math.random() * (ARENA_WIDTH - 200);
bigEnemy.y = 200 + Math.random() * (ARENA_HEIGHT - 400);
var dx2 = bigEnemy.x - player.x;
var dy2 = bigEnemy.y - player.y;
if (Math.sqrt(dx2 * dx2 + dy2 * dy2) > 600) safe = true;
}
bigEnemy.targetX = bigEnemy.x;
bigEnemy.targetY = bigEnemy.y;
enemies.push(bigEnemy);
game.addChild(bigEnemy);
} else {
spawnEnemy();
}
} else if (enemy.radius > player.radius * 1.15) {
// Player is eaten
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// --- Enemy eats enemy ---
for (var i = enemies.length - 1; i >= 0; i--) {
var enemyA = enemies[i];
for (var j = enemies.length - 1; j >= 0; j--) {
if (i === j) continue;
var enemyB = enemies[j];
var dx = enemyA.x - enemyB.x;
var dy = enemyA.y - enemyB.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < enemyA.radius + enemyB.radius * 0.7) {
if (enemyA.radius > enemyB.radius * 1.15) {
// A eats B
var newSize = Math.min(enemyA.radius * 2 + enemyB.radius * 2 * 0.5, 500);
enemyA.setSize(newSize);
enemyB.destroy();
enemies.splice(j, 1);
spawnEnemy();
if (j < i) i--; // Adjust index if needed
}
}
}
}
// Clamp player inside arena
player.x = clamp(player.x, player.radius, ARENA_WIDTH - player.radius);
player.y = clamp(player.y, player.radius, ARENA_HEIGHT - player.radius);
// Clamp enemies inside arena
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
enemy.x = clamp(enemy.x, enemy.radius, ARENA_WIDTH - enemy.radius);
enemy.y = clamp(enemy.y, enemy.radius, ARENA_HEIGHT - enemy.radius);
}
// Camera follow: center the visible area on the player
// LK.stage is the root container for all game objects
// The visible area is 2048x2732 (game resolution)
var camX = clamp(player.x, 1024, ARENA_WIDTH - 1024);
var camY = clamp(player.y, 1366, ARENA_HEIGHT - 1366);
game.x = 1024 - camX;
game.y = 1366 - camY;
};