User prompt
que cuando somos del mismo tamaño aleatoriamente uno se trague al otro
User prompt
Speed mas al jugador
User prompt
Cancion
User prompt
Has un modo local
User prompt
Que haiga un online local
User prompt
Que haiga modo online
User prompt
Que si tiene el mismo tamaño que no se traspasen
User prompt
Que el fondo sea azul oscuro
User prompt
Que el fondo sea negro completo
User prompt
Que la comida den 5 puntos
User prompt
Que la comida den 1 punto
User prompt
Que el 1 tenga minimo 50 mil puntos
User prompt
Que el primero minimo tenga 300 mil puntos
User prompt
Pero que el nombre del primero sea random cada que inicie
User prompt
Que el primero sea siempre un nombre diferente y que minima cantidad de puntos tenga 23 mil puntos
User prompt
Que el primero tenga de 23 mil puntos a 102 mil puntos
User prompt
Que sin depender del tamaño tenga el mismo speed
User prompt
Que el 1 tenga 23 mil puntos
User prompt
Que cuanto tenga 7000 no se quede congelado
User prompt
Que hasta los 5 mil puntos no aparescan gigantes
User prompt
Please fix the bug: 'mapSize is not defined' in or related to this line: 'food.x = Math.random() * mapSize;' Line Number: 511
User prompt
Que el jugador cresca el mapa creesca con el
User prompt
Has el mapa más grande
User prompt
que no haiga tantisimos gigantes que el más grande tenga 7000 puntos
User prompt
Pero que el jugador aparesca y no se muera al instante
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var AICell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5 }); // self.size is set on spawnAICell for variety self.speed = 2 + Math.random(); self.targetX = Math.random() * 8192; self.targetY = Math.random() * 8192; self.alive = true; self.lastX = self.x; self.lastY = self.y; self.update = function () { if (!self.alive) { return; } // --- AI Hunt Player Logic --- // Only some AI cells hunt the player, and only one at a time var huntingPlayer = false; if (self.huntsPlayer && typeof playerCell !== "undefined" && playerCell !== null) { var pdx = playerCell.x - self.x; var pdy = playerCell.y - self.y; var pdist = Math.sqrt(pdx * pdx + pdy * pdy); // Only hunt if AI is bigger than player by 20% if (self.size > playerCell.size * 1.2) { // Hunt if player is within 2000px (long range) if (pdist < 2000) { // Check if no one is currently hunting or if this AI is the current hunter if (currentHunter === null || currentHunter === self) { self.targetX = playerCell.x; self.targetY = playerCell.y; huntingPlayer = true; currentHunter = self; // Set this AI as the current hunter } } else if (currentHunter === self) { // If this AI was hunting but player moved away, stop hunting currentHunter = null; } } else if (currentHunter === self) { // If this AI was hunting but is no longer big enough, stop hunting currentHunter = null; } } // Move towards target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { // Speed: cells are faster for sizes 50-300, fast until 1000, still fast at 5000, and slow at 20000 var speed; if (self.size > 20000) { speed = 1.2; } else if (self.size > 5000) { speed = 4.5; } else if (self.size > 1000) { speed = 6.0; } else if (self.size > 300) { speed = 7.0; } else if (self.size >= 50) { speed = 9.0; } else { speed = 7.0; } self.x += dx / distance * speed; self.y += dy / distance * speed; } else { // Pick new random target self.targetX = Math.random() * 22000; self.targetY = Math.random() * 22000; } // Keep within bounds if (self.x < self.size / 2) { self.x = self.size / 2; } if (self.x > 22000 - self.size / 2) { self.x = 22000 - self.size / 2; } if (self.y < self.size / 2) { self.y = self.size / 2; } if (self.y > 22000 - self.size / 2) { self.y = 22000 - self.size / 2; } self.lastX = self.x; self.lastY = self.y; }; self.grow = function (amount) { var oldSize = self.size; self.size += amount; var scale = self.size / 50; tween(cellGraphics, { scaleX: scale, scaleY: scale }, { duration: 200, easing: tween.easeOut }); self.speed = Math.max(0.8, 2.5 - (self.size - 50) / 60); }; return self; }); var Food = Container.expand(function () { var self = Container.call(this); var foodGraphics = self.attachAsset('food', { anchorX: 0.5, anchorY: 0.5 }); self.size = 20; self.consumed = false; return self; }); var Papa = Container.expand(function () { var self = Container.call(this); var papaGraphics = self.attachAsset('papa', { anchorX: 0.5, anchorY: 0.5 }); papaGraphics.tint = 0xDEB887; // Burlywood color for potato self.size = 35; self.consumed = false; self.growthValue = 50; // All papas give 50 points return self; }); var PlayerCell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5 }); self.size = 50; self.speed = 3; self.targetX = self.x; self.targetY = self.y; self.grow = function (amount) { var oldSize = self.size; self.size += amount; // Update visual scale var scale = self.size / 50; tween(cellGraphics, { scaleX: scale, scaleY: scale }, { duration: 200, easing: tween.easeOut }); // Reduce speed as size increases self.speed = Math.max(1, 3 - (self.size - 50) / 50); LK.getSound('grow').play(); LK.setScore(Math.floor(self.size)); }; self.update = function () { // Slither.io style drag controls: playerCell.targetX/Y is set by drag logic in game.move // Move towards target position var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { // Speed: player is faster for sizes 50-300, fast until 1000, still fast at 5000, and slow at 20000 var speed; if (self.size > 20000) { speed = 1.2; } else if (self.size > 5000) { speed = 4.5; } else if (self.size > 1000) { speed = 6; } else if (self.size > 300) { speed = 7; } else if (self.size >= 50) { speed = 9.0; } else { speed = 7; } self.x += dx / distance * speed; self.y += dy / distance * speed; } // Keep within bounds if (self.x < self.size / 2) { self.x = self.size / 2; } if (self.x > 22000 - self.size / 2) { self.x = 22000 - self.size / 2; } if (self.y < self.size / 2) { self.y = self.size / 2; } if (self.y > 22000 - self.size / 2) { self.y = 22000 - self.size / 2; } }; return self; }); var PowerFood = Container.expand(function () { var self = Container.call(this); var powerFoodGraphics = self.attachAsset('powerfood', { anchorX: 0.5, anchorY: 0.5 }); powerFoodGraphics.tint = 0xFFD700; // Golden color self.size = 30; self.consumed = false; self.growthValue = 200; // More growth than regular food return self; }); var Predator = Container.expand(function () { var self = Container.call(this); var predatorGraphics = self.attachAsset('predator', { anchorX: 0.5, anchorY: 0.5 }); self.size = 80; self.speed = 4.5; // Much higher base speed for extreme challenge self.targetX = Math.random() * 8192; self.targetY = Math.random() * 8192; self.update = function () { // Move towards target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { // Predators are faster (difficulty up) self.x += dx / distance * 2.1; self.y += dy / distance * 2.1; } else { // Pick new random target self.targetX = Math.random() * 22000; self.targetY = Math.random() * 22000; } // Chase player if close enough if (typeof playerCell !== "undefined" && playerCell !== null) { var playerDx = playerCell.x - self.x; var playerDy = playerCell.y - self.y; var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy); if (playerDistance < 300 && playerCell.size < self.size) { self.x += playerDx / playerDistance * self.speed * 1.5; self.y += playerDy / playerDistance * self.speed * 1.5; } } // Keep within bounds if (self.x < 0) { self.x = 0; } if (self.x > 22000) { self.x = 22000; } if (self.y < 0) { self.y = 0; } if (self.y > 22000) { self.y = 22000; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ var playerCell = null; var foods = []; var powerFoods = []; var papas = []; var predators = []; var aiCells = []; var cellsEaten = 0; var currentHunter = null; // Track which AI cell is currently hunting the player // --- Slither.io-style Start Screen --- var startScreen = new Container(); // Animated background: several moving cells var startBgCells = []; for (var i = 0; i < 12; i++) { var cell = LK.getAsset('cell', { anchorX: 0.5, anchorY: 0.5 }); cell.scaleX = cell.scaleY = 1.2 + Math.random() * 1.8; cell.x = 400 + Math.random() * 1248; cell.y = 600 + Math.random() * 1600; cell.alpha = 0.18 + Math.random() * 0.18; cell._vx = (Math.random() - 0.5) * 1.2; cell._vy = (Math.random() - 0.5) * 1.2; startScreen.addChild(cell); startBgCells.push(cell); } // Main logo/title var titleTxt = new Text2("Célula Survival", { size: 160, fill: "#fff" }); titleTxt.anchor.set(0.5, 0); titleTxt.x = 2048 / 2; titleTxt.y = 320; startScreen.addChild(titleTxt); // Subtitle var subtitleTxt = new Text2("¡Come y sobrevive, evita a los grandes!", { size: 64, fill: "#fff" }); subtitleTxt.anchor.set(0.5, 0); subtitleTxt.x = 2048 / 2; subtitleTxt.y = 520; startScreen.addChild(subtitleTxt); // Name input label var nameLabel = new Text2("Tu nombre:", { size: 64, fill: "#fff" }); nameLabel.anchor.set(0.5, 0); nameLabel.x = 2048 / 2; nameLabel.y = 800; startScreen.addChild(nameLabel); // Simulated name input (tap to edit) var playerName = ""; var nameInput = new Text2("Toca para escribir...", { size: 80, fill: 0xFFFFCC }); nameInput.anchor.set(0.5, 0); nameInput.x = 2048 / 2; nameInput.y = 900; startScreen.addChild(nameInput); // Dice icon for random name var diceIcon = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.1, scaleY: 1.1, x: nameInput.x + 320, y: nameInput.y + 55, color: 0xffffff }); startScreen.addChild(diceIcon); diceIcon.interactive = true; diceIcon.buttonMode = true; // Dice icon click: set random name diceIcon.down = function (x, y, obj) { var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"]; playerName = allNames[Math.floor(Math.random() * allNames.length)]; nameInput.setText(playerName); editingName = false; }; var editingName = false; nameInput.interactive = true; nameInput.buttonMode = true; nameInput.down = function (x, y, obj) { editingName = true; nameInput.setText((playerName.length > 0 ? playerName : "") + "|"); }; // Start button var startBtn = new Text2("JUGAR", { size: 120, fill: 0x00FF99 }); startBtn.anchor.set(0.5, 0.5); startBtn.x = 2048 / 2; startBtn.y = 1200; startBtn.interactive = true; startBtn.buttonMode = true; startScreen.addChild(startBtn); // Credits (bottom) var creditsTxt = new Text2("Inspirado en Slither.io", { size: 40, fill: "#aaa" }); creditsTxt.anchor.set(0.5, 1); creditsTxt.x = 2048 / 2; creditsTxt.y = 2732 - 40; startScreen.addChild(creditsTxt); // Animate background cells startScreen.update = function () { for (var i = 0; i < startBgCells.length; i++) { var c = startBgCells[i]; c.x += c._vx; c.y += c._vy; // Bounce off edges if (c.x < 200 || c.x > 1848) c._vx *= -1; if (c.y < 400 || c.y > 2200) c._vy *= -1; } }; game.update = function (oldUpdate) { return function () { if (startScreen.visible && startScreen.update) startScreen.update(); if (typeof oldUpdate === "function") oldUpdate.apply(this, arguments); }; }(game.update); // Name input tap-to-edit logic game.down = function (x, y, obj) { // If editing name, simulate typing by adding a random letter (since we can't get real keyboard input) if (editingName) { // Simulate: tap = add random letter, long tap = backspace if (playerName.length < 10) { var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var letter = letters[Math.floor(Math.random() * letters.length)]; playerName += letter; } nameInput.setText(playerName + "|"); // If tap on left side, treat as backspace if (x < 2048 / 2 - 200 && playerName.length > 0) { playerName = playerName.substring(0, playerName.length - 1); nameInput.setText(playerName + "|"); } // If tap on right side, finish editing if (x > 2048 / 2 + 200) { editingName = false; nameInput.setText(playerName.length > 0 ? playerName : "Toca para escribir..."); } return; } }; // Start button logic startBtn.down = function (x, y, obj) { if (playerName.length === 0) { playerName = "Tú"; nameInput.setText(playerName); } // Hide start screen and start the game startScreen.visible = false; startScreen.interactive = false; startScreen.children.forEach(function (child) { child.visible = false; }); startGame(); }; game.addChild(startScreen); // --- Main game UI (hidden until start) --- var scoreTxt = new Text2('Size: 50', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Display for #1 (largest cell) score var topScoreTxt = new Text2('', { size: 48, fill: 0xFFD700 }); topScoreTxt.anchor.set(0.5, 0); topScoreTxt.y = 70; // Place below main score, avoid top 100px LK.gui.top.addChild(topScoreTxt); // Create a world container for all game objects (slither.io style) var world = new Container(); game.addChild(world); // --- Game start logic --- function startGame() { // Initialize player cell playerCell = new PlayerCell(); // Try to find a safe spawn location (not near any giant AI or predator) var safe = false; var attempts = 0; while (!safe && attempts < 30) { // Spawn in the center 50% of the map playerCell.x = 5500 + Math.random() * 11000; playerCell.y = 5500 + Math.random() * 11000; safe = true; // Check for nearby giant AI cells (size >= 1000) or predators for (var i = 0; i < aiCells.length; i++) { if (aiCells[i].size >= 1000) { var dx = playerCell.x - aiCells[i].x; var dy = playerCell.y - aiCells[i].y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 1200) { // 1200px buffer from giant AI safe = false; break; } } } if (safe) { for (var i = 0; i < predators.length; i++) { var dx = playerCell.x - predators[i].x; var dy = playerCell.y - predators[i].y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 1200) { // 1200px buffer from predators safe = false; break; } } } attempts++; } // Assign a name to the player cell var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"]; playerCell.randomName = playerName && playerName.length > 0 ? playerName : allNames[Math.floor(Math.random() * allNames.length)]; world.addChild(playerCell); } // Generate initial food function spawnFood() { var food = new Food(); food.x = Math.random() * 22000; food.y = Math.random() * 22000; foods.push(food); world.addChild(food); } function spawnPowerFood() { var powerFood = new PowerFood(); powerFood.x = Math.random() * 22000; powerFood.y = Math.random() * 22000; powerFoods.push(powerFood); world.addChild(powerFood); } function spawnPapa() { var papa = new Papa(); papa.x = Math.random() * 22000; papa.y = Math.random() * 22000; papas.push(papa); world.addChild(papa); } ; // Generate initial predators function spawnPredator() { var predator = new Predator(); predator.x = Math.random() * 22000; predator.y = Math.random() * 22000; // Assign a random name to the predator var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"]; predator.randomName = allNames[Math.floor(Math.random() * allNames.length)]; predators.push(predator); world.addChild(predator); } // Generate AI cells function spawnAICell() { var ai = new AICell(); ai.x = Math.random() * 22000; ai.y = Math.random() * 22000; // Assign random size: 50, 70, 90, 150, or 300 (removed 1000 to reduce large bots) var possibleSizes = [50, 70, 90, 150, 300]; var sizeIdx = Math.floor(Math.random() * possibleSizes.length); ai.size = possibleSizes[sizeIdx]; // Update scale to match new size var scale = ai.size / 50; if (ai.children && ai.children.length > 0) { var cellGraphics = ai.children[0]; cellGraphics.scaleX = scale; cellGraphics.scaleY = scale; } // Assign a random name to this AI cell var aiNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"]; ai.randomName = aiNames[Math.floor(Math.random() * aiNames.length)]; // Only some AI cells will hunt the player // 99% of AI cells will hunt the player (extreme) ai.huntsPlayer = Math.random() < 0.99; // Increase base speed for all AI cells for much more challenge ai.speed += 2.5; aiCells.push(ai); world.addChild(ai); } // Spawn giant AI cells function spawnGiantAICell() { var ai = new AICell(); ai.x = Math.random() * 22000; ai.y = Math.random() * 22000; // Set giant size ai.size = 1000; // Update scale to match new size var scale = ai.size / 50; if (ai.children && ai.children.length > 0) { var cellGraphics = ai.children[0]; cellGraphics.scaleX = scale; cellGraphics.scaleY = scale; } // Assign a random name to this AI cell var aiNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"]; ai.randomName = aiNames[Math.floor(Math.random() * aiNames.length)]; // Giant cells always hunt the player ai.huntsPlayer = true; aiCells.push(ai); world.addChild(ai); } // Spawn initial food, most near the player, some random for (var i = 0; i < 80; i++) { if (i < 60 && playerCell !== null) { // Near player: in a ring 300-900px from player var angle = Math.random() * Math.PI * 2; var dist = 300 + Math.random() * 600; var fx = playerCell.x + Math.cos(angle) * dist; var fy = playerCell.y + Math.sin(angle) * dist; fx = Math.max(20, Math.min(fx, 22000 - 20)); fy = Math.max(20, Math.min(fy, 22000 - 20)); var food = new Food(); food.x = fx; food.y = fy; foods.push(food); world.addChild(food); } else { spawnFood(); } } // Spawn initial power food (less common) for (var i = 0; i < 15; i++) { spawnPowerFood(); } // Spawn initial papas (potato food) for (var i = 0; i < 10; i++) { spawnPapa(); } // Spawn initial predators for (var i = 0; i < 5; i++) { spawnPredator(); } // Spawn initial AI cells for (var i = 0; i < 40; i++) { spawnAICell(); } // Spawn 2-10 giant AI cells var giantCount = 2 + Math.floor(Math.random() * 9); // Random number between 2 and 10 for (var i = 0; i < giantCount; i++) { spawnGiantAICell(); } // Slither.io style swipe/drag controls var dragging = false; var dragTouchId = null; var lastTouchX = null; var lastTouchY = null; var dragStartX = null; var dragStartY = null; var dragPlayerStartX = null; var dragPlayerStartY = null; game.down = function (x, y, obj) { // Start dragging from anywhere except top left 100x100 if (!(x < 100 && y < 100)) { dragging = true; dragTouchId = obj && obj.event && obj.event.identifier !== undefined ? obj.event.identifier : null; dragStartX = x; dragStartY = y; if (playerCell !== null) { dragPlayerStartX = playerCell.x; dragPlayerStartY = playerCell.y; } else { dragPlayerStartX = 0; dragPlayerStartY = 0; } lastTouchX = x; lastTouchY = y; } }; game.move = function (x, y, obj) { if (dragging && (dragTouchId === null || obj && obj.event && obj.event.identifier === dragTouchId)) { lastTouchX = x; lastTouchY = y; // Calculate drag vector relative to drag start var dx = x - dragStartX; var dy = y - dragStartY; // Set a max drag distance for control sensitivity var maxDrag = 400; var dragLen = Math.sqrt(dx * dx + dy * dy); if (dragLen > maxDrag) { dx = dx * maxDrag / dragLen; dy = dy * maxDrag / dragLen; } // Set the target position for the player cell based on drag if (playerCell !== null) { playerCell.targetX = dragPlayerStartX + dx * 8; playerCell.targetY = dragPlayerStartY + dy * 8; } } }; game.up = function (x, y, obj) { if (dragging && (dragTouchId === null || obj && obj.event && obj.event.identifier === dragTouchId)) { dragging = false; dragTouchId = null; lastTouchX = null; lastTouchY = null; dragStartX = null; dragStartY = null; dragPlayerStartX = null; dragPlayerStartY = null; } }; game.update = function () { if (!playerCell) { return; } // Camera logic: center world on playerCell, clamp to map bounds (slither.io style) var viewWidth = 2048; var viewHeight = 2732; var mapSize = 22000; // Calculate zoom based on player size (larger player = zoomed out more) // More zoom out: lower minZoom, faster zoom out curve var baseZoom = 1.0; var minZoom = 0.12; // Allow even more zoom out for very large cells var zoomFactor = baseZoom; if (playerCell.size > 50) { // Zoom out as player gets bigger, more pronounced for very large cells zoomFactor = Math.max(minZoom, baseZoom - (playerCell.size - 50) / 500); } // Smooth zoom transition if (typeof world.lastZoom === "undefined") world.lastZoom = zoomFactor; world.lastZoom += (zoomFactor - world.lastZoom) * 0.1; // Apply zoom to world world.scaleX = world.lastZoom; world.scaleY = world.lastZoom; // Adjust view calculations for zoom var adjustedViewWidth = viewWidth / world.lastZoom; var adjustedViewHeight = viewHeight / world.lastZoom; // Calculate camera target position to center player var camTargetX = playerCell.x - adjustedViewWidth / 2; var camTargetY = playerCell.y - adjustedViewHeight / 2; // Clamp camera to map bounds camTargetX = Math.max(0, Math.min(camTargetX, mapSize - adjustedViewWidth)); camTargetY = Math.max(0, Math.min(camTargetY, mapSize - adjustedViewHeight)); // Smooth camera movement (slither.io style) if (typeof world.lastCamX === "undefined") world.lastCamX = camTargetX; if (typeof world.lastCamY === "undefined") world.lastCamY = camTargetY; world.lastCamX += (camTargetX - world.lastCamX) * 0.15; world.lastCamY += (camTargetY - world.lastCamY) * 0.15; // Move world container world.x = -Math.round(world.lastCamX * world.lastZoom); world.y = -Math.round(world.lastCamY * world.lastZoom); // AI cells update and logic for (var i = aiCells.length - 1; i >= 0; i--) { var ai = aiCells[i]; if (!ai.alive) { continue; } ai.update(); // AI eats food for (var j = foods.length - 1; j >= 0; j--) { var food = foods[j]; if (food.consumed) { continue; } var dx = ai.x - food.x; var dy = ai.y - food.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ai.size / 2 + food.size / 2) { food.consumed = true; food.destroy(); foods.splice(j, 1); ai.grow(600); // AI cells grow even faster from food (extreme) break; } } // AI eats power food for (var j = powerFoods.length - 1; j >= 0; j--) { var powerFood = powerFoods[j]; if (powerFood.consumed) { continue; } var dx = ai.x - powerFood.x; var dy = ai.y - powerFood.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ai.size / 2 + powerFood.size / 2) { powerFood.consumed = true; powerFood.destroy(); powerFoods.splice(j, 1); ai.grow(powerFood.growthValue * 5); // AI cells grow even faster from power food (extreme) break; } } // AI eats papas for (var j = papas.length - 1; j >= 0; j--) { var papa = papas[j]; if (papa.consumed) { continue; } var dx = ai.x - papa.x; var dy = ai.y - papa.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ai.size / 2 + papa.size / 2) { papa.consumed = true; papa.destroy(); papas.splice(j, 1); ai.grow(papa.growthValue * 6); // AI cells grow even faster from papas (extreme) break; } } // AI eats other AI (io style) for (var k = aiCells.length - 1; k >= 0; k--) { if (i === k) { continue; } var other = aiCells[k]; if (!other.alive) { continue; } var dx = ai.x - other.x; var dy = ai.y - other.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ai.size / 2 + other.size / 2) { if (ai.size > other.size * 1.2) { // Clear hunter if the eaten AI was the current hunter if (currentHunter === other) { currentHunter = null; } other.alive = false; other.destroy(); ai.grow(other.size * 2.5); // AI cells grow even faster from eating other AI (extreme) aiCells.splice(k, 1); if (k < i) { i--; } // Adjust index if needed break; } } } // AI can eat player or be eaten by player var dxp = ai.x - playerCell.x; var dyp = ai.y - playerCell.y; var distp = Math.sqrt(dxp * dxp + dyp * dyp); if (distp < ai.size / 2 + playerCell.size / 2) { // Only allow player to be eaten if actually intersecting (touching) the AI cell if (ai.size > playerCell.size * 1.2) { // Player is eaten by a larger AI cell ONLY if touching LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else if (playerCell.size > ai.size * 1.2) { // Player eats smaller AI cell // Clear hunter if the eaten AI was the current hunter if (currentHunter === ai) { currentHunter = null; } ai.alive = false; ai.destroy(); aiCells.splice(i, 1); playerCell.grow(ai.size / 2); cellsEaten++; LK.getSound('eat').play(); scoreTxt.setText('Size: ' + Math.floor(playerCell.size) + ' | Eaten: ' + cellsEaten); break; } } } // Check food collisions for player for (var i = foods.length - 1; i >= 0; i--) { var food = foods[i]; if (food.consumed) { continue; } var dx = playerCell.x - food.x; var dy = playerCell.y - food.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerCell.size / 2 + food.size / 2) { // Consume food food.consumed = true; food.destroy(); foods.splice(i, 1); playerCell.grow(100); // Do not increment cellsEaten for food LK.getSound('eat').play(); // Update score display scoreTxt.setText('Size: ' + Math.floor(playerCell.size)); } } // Check power food collisions for player for (var i = powerFoods.length - 1; i >= 0; i--) { var powerFood = powerFoods[i]; if (powerFood.consumed) { continue; } var dx = playerCell.x - powerFood.x; var dy = playerCell.y - powerFood.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerCell.size / 2 + powerFood.size / 2) { // Consume power food powerFood.consumed = true; powerFood.destroy(); powerFoods.splice(i, 1); playerCell.grow(powerFood.growthValue); // Do not increment cellsEaten for power food LK.getSound('eat').play(); // Update score display scoreTxt.setText('Size: ' + Math.floor(playerCell.size)); } } // Check papa collisions for player for (var i = papas.length - 1; i >= 0; i--) { var papa = papas[i]; if (papa.consumed) { continue; } var dx = playerCell.x - papa.x; var dy = playerCell.y - papa.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerCell.size / 2 + papa.size / 2) { // Consume papa papa.consumed = true; papa.destroy(); papas.splice(i, 1); playerCell.grow(papa.growthValue); // Do not increment cellsEaten for papa LK.getSound('eat').play(); // Update score display scoreTxt.setText('Size: ' + Math.floor(playerCell.size)); } } // Check predator collisions for (var i = 0; i < predators.length; i++) { var predator = predators[i]; var dx = playerCell.x - predator.x; var dy = playerCell.y - predator.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < playerCell.size / 2 + predator.size / 2) { if (predator.size > playerCell.size) { // Game over - eaten by predator LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else if (playerCell.size > predator.size * 1.2) { // Player can eat predator predator.destroy(); predators.splice(i, 1); playerCell.grow(70); cellsEaten++; LK.getSound('eat').play(); scoreTxt.setText('Size: ' + Math.floor(playerCell.size) + ' | Eaten: ' + cellsEaten); // Spawn new predator, and make all predators grow a lot if player is eaten for (var p = 0; p < predators.length; p++) { predators[p].size += 300; // All predators get much bigger (extreme) } spawnPredator(); i--; // Adjust index after removal } } } // Spawn new food periodically, but always near the player if (LK.ticks % 120 == 0 && foods.length < 65) { // Spawn food in a ring 300-700px from player, random angle var angle = Math.random() * Math.PI * 2; var dist = 300 + Math.random() * 400; var fx = playerCell.x + Math.cos(angle) * dist; var fy = playerCell.y + Math.sin(angle) * dist; // Clamp to map bounds fx = Math.max(20, Math.min(fx, 22000 - 20)); fy = Math.max(20, Math.min(fy, 22000 - 20)); var food = new Food(); food.x = fx; food.y = fy; foods.push(food); world.addChild(food); } // Spawn power food less frequently if (LK.ticks % 300 == 0 && powerFoods.length < 20) { // Spawn power food in a ring 400-800px from player, random angle var angle = Math.random() * Math.PI * 2; var dist = 400 + Math.random() * 400; var fx = playerCell.x + Math.cos(angle) * dist; var fy = playerCell.y + Math.sin(angle) * dist; // Clamp to map bounds fx = Math.max(30, Math.min(fx, 22000 - 30)); fy = Math.max(30, Math.min(fy, 22000 - 30)); var powerFood = new PowerFood(); powerFood.x = fx; powerFood.y = fy; powerFoods.push(powerFood); world.addChild(powerFood); } // Spawn papas periodically if (LK.ticks % 200 == 0 && papas.length < 15) { // Spawn papa in a ring 350-600px from player, random angle var angle = Math.random() * Math.PI * 2; var dist = 350 + Math.random() * 250; var fx = playerCell.x + Math.cos(angle) * dist; var fy = playerCell.y + Math.sin(angle) * dist; // Clamp to map bounds fx = Math.max(35, Math.min(fx, 22000 - 35)); fy = Math.max(35, Math.min(fy, 22000 - 35)); var papa = new Papa(); papa.x = fx; papa.y = fy; papas.push(papa); world.addChild(papa); } // Add more predators as player grows (extreme: much more frequent, much higher max, much faster) if (LK.ticks % 40 == 0 && predators.length < 80) { spawnPredator(); } // Add more AI cells as the game progresses (extreme: much more frequent, much higher max, much larger) if (LK.ticks % 20 == 0 && aiCells.length < 120) { spawnAICell(); } // Find the largest cell (player, aiCells, predators) var topCell = playerCell; var topCellType = "Tú"; var topCellSize = playerCell ? playerCell.size : 0; var topCellName = null; // Check AI cells for (var i = 0; i < aiCells.length; i++) { if (aiCells[i].alive && aiCells[i].size > topCellSize) { topCell = aiCells[i]; topCellType = "Bot"; topCellSize = aiCells[i].size; topCellName = aiCells[i].randomName; } } // Check predators for (var i = 0; i < predators.length; i++) { if (predators[i].size > topCellSize) { topCell = predators[i]; topCellType = "Depredador"; topCellSize = predators[i].size; topCellName = null; } } // Show #1 score if (topCell === playerCell) { topScoreTxt.setText("#1: Tú (" + Math.floor(topCellSize) + ")"); } else if (topCellType === "Bot" && topCellName) { topScoreTxt.setText("#1: " + topCellName + " (" + Math.floor(topCellSize) + ")"); } else { topScoreTxt.setText("#1: " + topCellType + " (" + Math.floor(topCellSize) + ")"); } // No win condition: game continues infinitely even if player is #1 };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AICell = Container.expand(function () {
var self = Container.call(this);
var cellGraphics = self.attachAsset('cell', {
anchorX: 0.5,
anchorY: 0.5
});
// self.size is set on spawnAICell for variety
self.speed = 2 + Math.random();
self.targetX = Math.random() * 8192;
self.targetY = Math.random() * 8192;
self.alive = true;
self.lastX = self.x;
self.lastY = self.y;
self.update = function () {
if (!self.alive) {
return;
}
// --- AI Hunt Player Logic ---
// Only some AI cells hunt the player, and only one at a time
var huntingPlayer = false;
if (self.huntsPlayer && typeof playerCell !== "undefined" && playerCell !== null) {
var pdx = playerCell.x - self.x;
var pdy = playerCell.y - self.y;
var pdist = Math.sqrt(pdx * pdx + pdy * pdy);
// Only hunt if AI is bigger than player by 20%
if (self.size > playerCell.size * 1.2) {
// Hunt if player is within 2000px (long range)
if (pdist < 2000) {
// Check if no one is currently hunting or if this AI is the current hunter
if (currentHunter === null || currentHunter === self) {
self.targetX = playerCell.x;
self.targetY = playerCell.y;
huntingPlayer = true;
currentHunter = self; // Set this AI as the current hunter
}
} else if (currentHunter === self) {
// If this AI was hunting but player moved away, stop hunting
currentHunter = null;
}
} else if (currentHunter === self) {
// If this AI was hunting but is no longer big enough, stop hunting
currentHunter = null;
}
}
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Speed: cells are faster for sizes 50-300, fast until 1000, still fast at 5000, and slow at 20000
var speed;
if (self.size > 20000) {
speed = 1.2;
} else if (self.size > 5000) {
speed = 4.5;
} else if (self.size > 1000) {
speed = 6.0;
} else if (self.size > 300) {
speed = 7.0;
} else if (self.size >= 50) {
speed = 9.0;
} else {
speed = 7.0;
}
self.x += dx / distance * speed;
self.y += dy / distance * speed;
} else {
// Pick new random target
self.targetX = Math.random() * 22000;
self.targetY = Math.random() * 22000;
}
// Keep within bounds
if (self.x < self.size / 2) {
self.x = self.size / 2;
}
if (self.x > 22000 - self.size / 2) {
self.x = 22000 - self.size / 2;
}
if (self.y < self.size / 2) {
self.y = self.size / 2;
}
if (self.y > 22000 - self.size / 2) {
self.y = 22000 - self.size / 2;
}
self.lastX = self.x;
self.lastY = self.y;
};
self.grow = function (amount) {
var oldSize = self.size;
self.size += amount;
var scale = self.size / 50;
tween(cellGraphics, {
scaleX: scale,
scaleY: scale
}, {
duration: 200,
easing: tween.easeOut
});
self.speed = Math.max(0.8, 2.5 - (self.size - 50) / 60);
};
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
var foodGraphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.size = 20;
self.consumed = false;
return self;
});
var Papa = Container.expand(function () {
var self = Container.call(this);
var papaGraphics = self.attachAsset('papa', {
anchorX: 0.5,
anchorY: 0.5
});
papaGraphics.tint = 0xDEB887; // Burlywood color for potato
self.size = 35;
self.consumed = false;
self.growthValue = 50; // All papas give 50 points
return self;
});
var PlayerCell = Container.expand(function () {
var self = Container.call(this);
var cellGraphics = self.attachAsset('cell', {
anchorX: 0.5,
anchorY: 0.5
});
self.size = 50;
self.speed = 3;
self.targetX = self.x;
self.targetY = self.y;
self.grow = function (amount) {
var oldSize = self.size;
self.size += amount;
// Update visual scale
var scale = self.size / 50;
tween(cellGraphics, {
scaleX: scale,
scaleY: scale
}, {
duration: 200,
easing: tween.easeOut
});
// Reduce speed as size increases
self.speed = Math.max(1, 3 - (self.size - 50) / 50);
LK.getSound('grow').play();
LK.setScore(Math.floor(self.size));
};
self.update = function () {
// Slither.io style drag controls: playerCell.targetX/Y is set by drag logic in game.move
// Move towards target position
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Speed: player is faster for sizes 50-300, fast until 1000, still fast at 5000, and slow at 20000
var speed;
if (self.size > 20000) {
speed = 1.2;
} else if (self.size > 5000) {
speed = 4.5;
} else if (self.size > 1000) {
speed = 6;
} else if (self.size > 300) {
speed = 7;
} else if (self.size >= 50) {
speed = 9.0;
} else {
speed = 7;
}
self.x += dx / distance * speed;
self.y += dy / distance * speed;
}
// Keep within bounds
if (self.x < self.size / 2) {
self.x = self.size / 2;
}
if (self.x > 22000 - self.size / 2) {
self.x = 22000 - self.size / 2;
}
if (self.y < self.size / 2) {
self.y = self.size / 2;
}
if (self.y > 22000 - self.size / 2) {
self.y = 22000 - self.size / 2;
}
};
return self;
});
var PowerFood = Container.expand(function () {
var self = Container.call(this);
var powerFoodGraphics = self.attachAsset('powerfood', {
anchorX: 0.5,
anchorY: 0.5
});
powerFoodGraphics.tint = 0xFFD700; // Golden color
self.size = 30;
self.consumed = false;
self.growthValue = 200; // More growth than regular food
return self;
});
var Predator = Container.expand(function () {
var self = Container.call(this);
var predatorGraphics = self.attachAsset('predator', {
anchorX: 0.5,
anchorY: 0.5
});
self.size = 80;
self.speed = 4.5; // Much higher base speed for extreme challenge
self.targetX = Math.random() * 8192;
self.targetY = Math.random() * 8192;
self.update = function () {
// Move towards target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Predators are faster (difficulty up)
self.x += dx / distance * 2.1;
self.y += dy / distance * 2.1;
} else {
// Pick new random target
self.targetX = Math.random() * 22000;
self.targetY = Math.random() * 22000;
}
// Chase player if close enough
if (typeof playerCell !== "undefined" && playerCell !== null) {
var playerDx = playerCell.x - self.x;
var playerDy = playerCell.y - self.y;
var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy);
if (playerDistance < 300 && playerCell.size < self.size) {
self.x += playerDx / playerDistance * self.speed * 1.5;
self.y += playerDy / playerDistance * self.speed * 1.5;
}
}
// Keep within bounds
if (self.x < 0) {
self.x = 0;
}
if (self.x > 22000) {
self.x = 22000;
}
if (self.y < 0) {
self.y = 0;
}
if (self.y > 22000) {
self.y = 22000;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var playerCell = null;
var foods = [];
var powerFoods = [];
var papas = [];
var predators = [];
var aiCells = [];
var cellsEaten = 0;
var currentHunter = null; // Track which AI cell is currently hunting the player
// --- Slither.io-style Start Screen ---
var startScreen = new Container();
// Animated background: several moving cells
var startBgCells = [];
for (var i = 0; i < 12; i++) {
var cell = LK.getAsset('cell', {
anchorX: 0.5,
anchorY: 0.5
});
cell.scaleX = cell.scaleY = 1.2 + Math.random() * 1.8;
cell.x = 400 + Math.random() * 1248;
cell.y = 600 + Math.random() * 1600;
cell.alpha = 0.18 + Math.random() * 0.18;
cell._vx = (Math.random() - 0.5) * 1.2;
cell._vy = (Math.random() - 0.5) * 1.2;
startScreen.addChild(cell);
startBgCells.push(cell);
}
// Main logo/title
var titleTxt = new Text2("Célula Survival", {
size: 160,
fill: "#fff"
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = 2048 / 2;
titleTxt.y = 320;
startScreen.addChild(titleTxt);
// Subtitle
var subtitleTxt = new Text2("¡Come y sobrevive, evita a los grandes!", {
size: 64,
fill: "#fff"
});
subtitleTxt.anchor.set(0.5, 0);
subtitleTxt.x = 2048 / 2;
subtitleTxt.y = 520;
startScreen.addChild(subtitleTxt);
// Name input label
var nameLabel = new Text2("Tu nombre:", {
size: 64,
fill: "#fff"
});
nameLabel.anchor.set(0.5, 0);
nameLabel.x = 2048 / 2;
nameLabel.y = 800;
startScreen.addChild(nameLabel);
// Simulated name input (tap to edit)
var playerName = "";
var nameInput = new Text2("Toca para escribir...", {
size: 80,
fill: 0xFFFFCC
});
nameInput.anchor.set(0.5, 0);
nameInput.x = 2048 / 2;
nameInput.y = 900;
startScreen.addChild(nameInput);
// Dice icon for random name
var diceIcon = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1,
x: nameInput.x + 320,
y: nameInput.y + 55,
color: 0xffffff
});
startScreen.addChild(diceIcon);
diceIcon.interactive = true;
diceIcon.buttonMode = true;
// Dice icon click: set random name
diceIcon.down = function (x, y, obj) {
var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"];
playerName = allNames[Math.floor(Math.random() * allNames.length)];
nameInput.setText(playerName);
editingName = false;
};
var editingName = false;
nameInput.interactive = true;
nameInput.buttonMode = true;
nameInput.down = function (x, y, obj) {
editingName = true;
nameInput.setText((playerName.length > 0 ? playerName : "") + "|");
};
// Start button
var startBtn = new Text2("JUGAR", {
size: 120,
fill: 0x00FF99
});
startBtn.anchor.set(0.5, 0.5);
startBtn.x = 2048 / 2;
startBtn.y = 1200;
startBtn.interactive = true;
startBtn.buttonMode = true;
startScreen.addChild(startBtn);
// Credits (bottom)
var creditsTxt = new Text2("Inspirado en Slither.io", {
size: 40,
fill: "#aaa"
});
creditsTxt.anchor.set(0.5, 1);
creditsTxt.x = 2048 / 2;
creditsTxt.y = 2732 - 40;
startScreen.addChild(creditsTxt);
// Animate background cells
startScreen.update = function () {
for (var i = 0; i < startBgCells.length; i++) {
var c = startBgCells[i];
c.x += c._vx;
c.y += c._vy;
// Bounce off edges
if (c.x < 200 || c.x > 1848) c._vx *= -1;
if (c.y < 400 || c.y > 2200) c._vy *= -1;
}
};
game.update = function (oldUpdate) {
return function () {
if (startScreen.visible && startScreen.update) startScreen.update();
if (typeof oldUpdate === "function") oldUpdate.apply(this, arguments);
};
}(game.update);
// Name input tap-to-edit logic
game.down = function (x, y, obj) {
// If editing name, simulate typing by adding a random letter (since we can't get real keyboard input)
if (editingName) {
// Simulate: tap = add random letter, long tap = backspace
if (playerName.length < 10) {
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var letter = letters[Math.floor(Math.random() * letters.length)];
playerName += letter;
}
nameInput.setText(playerName + "|");
// If tap on left side, treat as backspace
if (x < 2048 / 2 - 200 && playerName.length > 0) {
playerName = playerName.substring(0, playerName.length - 1);
nameInput.setText(playerName + "|");
}
// If tap on right side, finish editing
if (x > 2048 / 2 + 200) {
editingName = false;
nameInput.setText(playerName.length > 0 ? playerName : "Toca para escribir...");
}
return;
}
};
// Start button logic
startBtn.down = function (x, y, obj) {
if (playerName.length === 0) {
playerName = "Tú";
nameInput.setText(playerName);
}
// Hide start screen and start the game
startScreen.visible = false;
startScreen.interactive = false;
startScreen.children.forEach(function (child) {
child.visible = false;
});
startGame();
};
game.addChild(startScreen);
// --- Main game UI (hidden until start) ---
var scoreTxt = new Text2('Size: 50', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Display for #1 (largest cell) score
var topScoreTxt = new Text2('', {
size: 48,
fill: 0xFFD700
});
topScoreTxt.anchor.set(0.5, 0);
topScoreTxt.y = 70; // Place below main score, avoid top 100px
LK.gui.top.addChild(topScoreTxt);
// Create a world container for all game objects (slither.io style)
var world = new Container();
game.addChild(world);
// --- Game start logic ---
function startGame() {
// Initialize player cell
playerCell = new PlayerCell();
// Try to find a safe spawn location (not near any giant AI or predator)
var safe = false;
var attempts = 0;
while (!safe && attempts < 30) {
// Spawn in the center 50% of the map
playerCell.x = 5500 + Math.random() * 11000;
playerCell.y = 5500 + Math.random() * 11000;
safe = true;
// Check for nearby giant AI cells (size >= 1000) or predators
for (var i = 0; i < aiCells.length; i++) {
if (aiCells[i].size >= 1000) {
var dx = playerCell.x - aiCells[i].x;
var dy = playerCell.y - aiCells[i].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 1200) {
// 1200px buffer from giant AI
safe = false;
break;
}
}
}
if (safe) {
for (var i = 0; i < predators.length; i++) {
var dx = playerCell.x - predators[i].x;
var dy = playerCell.y - predators[i].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 1200) {
// 1200px buffer from predators
safe = false;
break;
}
}
}
attempts++;
}
// Assign a name to the player cell
var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"];
playerCell.randomName = playerName && playerName.length > 0 ? playerName : allNames[Math.floor(Math.random() * allNames.length)];
world.addChild(playerCell);
}
// Generate initial food
function spawnFood() {
var food = new Food();
food.x = Math.random() * 22000;
food.y = Math.random() * 22000;
foods.push(food);
world.addChild(food);
}
function spawnPowerFood() {
var powerFood = new PowerFood();
powerFood.x = Math.random() * 22000;
powerFood.y = Math.random() * 22000;
powerFoods.push(powerFood);
world.addChild(powerFood);
}
function spawnPapa() {
var papa = new Papa();
papa.x = Math.random() * 22000;
papa.y = Math.random() * 22000;
papas.push(papa);
world.addChild(papa);
}
;
// Generate initial predators
function spawnPredator() {
var predator = new Predator();
predator.x = Math.random() * 22000;
predator.y = Math.random() * 22000;
// Assign a random name to the predator
var allNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"];
predator.randomName = allNames[Math.floor(Math.random() * allNames.length)];
predators.push(predator);
world.addChild(predator);
}
// Generate AI cells
function spawnAICell() {
var ai = new AICell();
ai.x = Math.random() * 22000;
ai.y = Math.random() * 22000;
// Assign random size: 50, 70, 90, 150, or 300 (removed 1000 to reduce large bots)
var possibleSizes = [50, 70, 90, 150, 300];
var sizeIdx = Math.floor(Math.random() * possibleSizes.length);
ai.size = possibleSizes[sizeIdx];
// Update scale to match new size
var scale = ai.size / 50;
if (ai.children && ai.children.length > 0) {
var cellGraphics = ai.children[0];
cellGraphics.scaleX = scale;
cellGraphics.scaleY = scale;
}
// Assign a random name to this AI cell
var aiNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"];
ai.randomName = aiNames[Math.floor(Math.random() * aiNames.length)];
// Only some AI cells will hunt the player
// 99% of AI cells will hunt the player (extreme)
ai.huntsPlayer = Math.random() < 0.99;
// Increase base speed for all AI cells for much more challenge
ai.speed += 2.5;
aiCells.push(ai);
world.addChild(ai);
}
// Spawn giant AI cells
function spawnGiantAICell() {
var ai = new AICell();
ai.x = Math.random() * 22000;
ai.y = Math.random() * 22000;
// Set giant size
ai.size = 1000;
// Update scale to match new size
var scale = ai.size / 50;
if (ai.children && ai.children.length > 0) {
var cellGraphics = ai.children[0];
cellGraphics.scaleX = scale;
cellGraphics.scaleY = scale;
}
// Assign a random name to this AI cell
var aiNames = ["Nano", "Blob", "Zeta", "Mito", "Viru", "Giga", "Beta", "Toxi", "Rex", "Lumo", "Fago", "Proto", "Mega", "Pico", "Tera", "Vivo", "Cello", "Dino", "Mobi", "Rondo"];
ai.randomName = aiNames[Math.floor(Math.random() * aiNames.length)];
// Giant cells always hunt the player
ai.huntsPlayer = true;
aiCells.push(ai);
world.addChild(ai);
}
// Spawn initial food, most near the player, some random
for (var i = 0; i < 80; i++) {
if (i < 60 && playerCell !== null) {
// Near player: in a ring 300-900px from player
var angle = Math.random() * Math.PI * 2;
var dist = 300 + Math.random() * 600;
var fx = playerCell.x + Math.cos(angle) * dist;
var fy = playerCell.y + Math.sin(angle) * dist;
fx = Math.max(20, Math.min(fx, 22000 - 20));
fy = Math.max(20, Math.min(fy, 22000 - 20));
var food = new Food();
food.x = fx;
food.y = fy;
foods.push(food);
world.addChild(food);
} else {
spawnFood();
}
}
// Spawn initial power food (less common)
for (var i = 0; i < 15; i++) {
spawnPowerFood();
}
// Spawn initial papas (potato food)
for (var i = 0; i < 10; i++) {
spawnPapa();
}
// Spawn initial predators
for (var i = 0; i < 5; i++) {
spawnPredator();
}
// Spawn initial AI cells
for (var i = 0; i < 40; i++) {
spawnAICell();
}
// Spawn 2-10 giant AI cells
var giantCount = 2 + Math.floor(Math.random() * 9); // Random number between 2 and 10
for (var i = 0; i < giantCount; i++) {
spawnGiantAICell();
}
// Slither.io style swipe/drag controls
var dragging = false;
var dragTouchId = null;
var lastTouchX = null;
var lastTouchY = null;
var dragStartX = null;
var dragStartY = null;
var dragPlayerStartX = null;
var dragPlayerStartY = null;
game.down = function (x, y, obj) {
// Start dragging from anywhere except top left 100x100
if (!(x < 100 && y < 100)) {
dragging = true;
dragTouchId = obj && obj.event && obj.event.identifier !== undefined ? obj.event.identifier : null;
dragStartX = x;
dragStartY = y;
if (playerCell !== null) {
dragPlayerStartX = playerCell.x;
dragPlayerStartY = playerCell.y;
} else {
dragPlayerStartX = 0;
dragPlayerStartY = 0;
}
lastTouchX = x;
lastTouchY = y;
}
};
game.move = function (x, y, obj) {
if (dragging && (dragTouchId === null || obj && obj.event && obj.event.identifier === dragTouchId)) {
lastTouchX = x;
lastTouchY = y;
// Calculate drag vector relative to drag start
var dx = x - dragStartX;
var dy = y - dragStartY;
// Set a max drag distance for control sensitivity
var maxDrag = 400;
var dragLen = Math.sqrt(dx * dx + dy * dy);
if (dragLen > maxDrag) {
dx = dx * maxDrag / dragLen;
dy = dy * maxDrag / dragLen;
}
// Set the target position for the player cell based on drag
if (playerCell !== null) {
playerCell.targetX = dragPlayerStartX + dx * 8;
playerCell.targetY = dragPlayerStartY + dy * 8;
}
}
};
game.up = function (x, y, obj) {
if (dragging && (dragTouchId === null || obj && obj.event && obj.event.identifier === dragTouchId)) {
dragging = false;
dragTouchId = null;
lastTouchX = null;
lastTouchY = null;
dragStartX = null;
dragStartY = null;
dragPlayerStartX = null;
dragPlayerStartY = null;
}
};
game.update = function () {
if (!playerCell) {
return;
}
// Camera logic: center world on playerCell, clamp to map bounds (slither.io style)
var viewWidth = 2048;
var viewHeight = 2732;
var mapSize = 22000;
// Calculate zoom based on player size (larger player = zoomed out more)
// More zoom out: lower minZoom, faster zoom out curve
var baseZoom = 1.0;
var minZoom = 0.12; // Allow even more zoom out for very large cells
var zoomFactor = baseZoom;
if (playerCell.size > 50) {
// Zoom out as player gets bigger, more pronounced for very large cells
zoomFactor = Math.max(minZoom, baseZoom - (playerCell.size - 50) / 500);
}
// Smooth zoom transition
if (typeof world.lastZoom === "undefined") world.lastZoom = zoomFactor;
world.lastZoom += (zoomFactor - world.lastZoom) * 0.1;
// Apply zoom to world
world.scaleX = world.lastZoom;
world.scaleY = world.lastZoom;
// Adjust view calculations for zoom
var adjustedViewWidth = viewWidth / world.lastZoom;
var adjustedViewHeight = viewHeight / world.lastZoom;
// Calculate camera target position to center player
var camTargetX = playerCell.x - adjustedViewWidth / 2;
var camTargetY = playerCell.y - adjustedViewHeight / 2;
// Clamp camera to map bounds
camTargetX = Math.max(0, Math.min(camTargetX, mapSize - adjustedViewWidth));
camTargetY = Math.max(0, Math.min(camTargetY, mapSize - adjustedViewHeight));
// Smooth camera movement (slither.io style)
if (typeof world.lastCamX === "undefined") world.lastCamX = camTargetX;
if (typeof world.lastCamY === "undefined") world.lastCamY = camTargetY;
world.lastCamX += (camTargetX - world.lastCamX) * 0.15;
world.lastCamY += (camTargetY - world.lastCamY) * 0.15;
// Move world container
world.x = -Math.round(world.lastCamX * world.lastZoom);
world.y = -Math.round(world.lastCamY * world.lastZoom);
// AI cells update and logic
for (var i = aiCells.length - 1; i >= 0; i--) {
var ai = aiCells[i];
if (!ai.alive) {
continue;
}
ai.update();
// AI eats food
for (var j = foods.length - 1; j >= 0; j--) {
var food = foods[j];
if (food.consumed) {
continue;
}
var dx = ai.x - food.x;
var dy = ai.y - food.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ai.size / 2 + food.size / 2) {
food.consumed = true;
food.destroy();
foods.splice(j, 1);
ai.grow(600); // AI cells grow even faster from food (extreme)
break;
}
}
// AI eats power food
for (var j = powerFoods.length - 1; j >= 0; j--) {
var powerFood = powerFoods[j];
if (powerFood.consumed) {
continue;
}
var dx = ai.x - powerFood.x;
var dy = ai.y - powerFood.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ai.size / 2 + powerFood.size / 2) {
powerFood.consumed = true;
powerFood.destroy();
powerFoods.splice(j, 1);
ai.grow(powerFood.growthValue * 5); // AI cells grow even faster from power food (extreme)
break;
}
}
// AI eats papas
for (var j = papas.length - 1; j >= 0; j--) {
var papa = papas[j];
if (papa.consumed) {
continue;
}
var dx = ai.x - papa.x;
var dy = ai.y - papa.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ai.size / 2 + papa.size / 2) {
papa.consumed = true;
papa.destroy();
papas.splice(j, 1);
ai.grow(papa.growthValue * 6); // AI cells grow even faster from papas (extreme)
break;
}
}
// AI eats other AI (io style)
for (var k = aiCells.length - 1; k >= 0; k--) {
if (i === k) {
continue;
}
var other = aiCells[k];
if (!other.alive) {
continue;
}
var dx = ai.x - other.x;
var dy = ai.y - other.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ai.size / 2 + other.size / 2) {
if (ai.size > other.size * 1.2) {
// Clear hunter if the eaten AI was the current hunter
if (currentHunter === other) {
currentHunter = null;
}
other.alive = false;
other.destroy();
ai.grow(other.size * 2.5); // AI cells grow even faster from eating other AI (extreme)
aiCells.splice(k, 1);
if (k < i) {
i--;
} // Adjust index if needed
break;
}
}
}
// AI can eat player or be eaten by player
var dxp = ai.x - playerCell.x;
var dyp = ai.y - playerCell.y;
var distp = Math.sqrt(dxp * dxp + dyp * dyp);
if (distp < ai.size / 2 + playerCell.size / 2) {
// Only allow player to be eaten if actually intersecting (touching) the AI cell
if (ai.size > playerCell.size * 1.2) {
// Player is eaten by a larger AI cell ONLY if touching
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else if (playerCell.size > ai.size * 1.2) {
// Player eats smaller AI cell
// Clear hunter if the eaten AI was the current hunter
if (currentHunter === ai) {
currentHunter = null;
}
ai.alive = false;
ai.destroy();
aiCells.splice(i, 1);
playerCell.grow(ai.size / 2);
cellsEaten++;
LK.getSound('eat').play();
scoreTxt.setText('Size: ' + Math.floor(playerCell.size) + ' | Eaten: ' + cellsEaten);
break;
}
}
}
// Check food collisions for player
for (var i = foods.length - 1; i >= 0; i--) {
var food = foods[i];
if (food.consumed) {
continue;
}
var dx = playerCell.x - food.x;
var dy = playerCell.y - food.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < playerCell.size / 2 + food.size / 2) {
// Consume food
food.consumed = true;
food.destroy();
foods.splice(i, 1);
playerCell.grow(100);
// Do not increment cellsEaten for food
LK.getSound('eat').play();
// Update score display
scoreTxt.setText('Size: ' + Math.floor(playerCell.size));
}
}
// Check power food collisions for player
for (var i = powerFoods.length - 1; i >= 0; i--) {
var powerFood = powerFoods[i];
if (powerFood.consumed) {
continue;
}
var dx = playerCell.x - powerFood.x;
var dy = playerCell.y - powerFood.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < playerCell.size / 2 + powerFood.size / 2) {
// Consume power food
powerFood.consumed = true;
powerFood.destroy();
powerFoods.splice(i, 1);
playerCell.grow(powerFood.growthValue);
// Do not increment cellsEaten for power food
LK.getSound('eat').play();
// Update score display
scoreTxt.setText('Size: ' + Math.floor(playerCell.size));
}
}
// Check papa collisions for player
for (var i = papas.length - 1; i >= 0; i--) {
var papa = papas[i];
if (papa.consumed) {
continue;
}
var dx = playerCell.x - papa.x;
var dy = playerCell.y - papa.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < playerCell.size / 2 + papa.size / 2) {
// Consume papa
papa.consumed = true;
papa.destroy();
papas.splice(i, 1);
playerCell.grow(papa.growthValue);
// Do not increment cellsEaten for papa
LK.getSound('eat').play();
// Update score display
scoreTxt.setText('Size: ' + Math.floor(playerCell.size));
}
}
// Check predator collisions
for (var i = 0; i < predators.length; i++) {
var predator = predators[i];
var dx = playerCell.x - predator.x;
var dy = playerCell.y - predator.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < playerCell.size / 2 + predator.size / 2) {
if (predator.size > playerCell.size) {
// Game over - eaten by predator
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else if (playerCell.size > predator.size * 1.2) {
// Player can eat predator
predator.destroy();
predators.splice(i, 1);
playerCell.grow(70);
cellsEaten++;
LK.getSound('eat').play();
scoreTxt.setText('Size: ' + Math.floor(playerCell.size) + ' | Eaten: ' + cellsEaten);
// Spawn new predator, and make all predators grow a lot if player is eaten
for (var p = 0; p < predators.length; p++) {
predators[p].size += 300; // All predators get much bigger (extreme)
}
spawnPredator();
i--; // Adjust index after removal
}
}
}
// Spawn new food periodically, but always near the player
if (LK.ticks % 120 == 0 && foods.length < 65) {
// Spawn food in a ring 300-700px from player, random angle
var angle = Math.random() * Math.PI * 2;
var dist = 300 + Math.random() * 400;
var fx = playerCell.x + Math.cos(angle) * dist;
var fy = playerCell.y + Math.sin(angle) * dist;
// Clamp to map bounds
fx = Math.max(20, Math.min(fx, 22000 - 20));
fy = Math.max(20, Math.min(fy, 22000 - 20));
var food = new Food();
food.x = fx;
food.y = fy;
foods.push(food);
world.addChild(food);
}
// Spawn power food less frequently
if (LK.ticks % 300 == 0 && powerFoods.length < 20) {
// Spawn power food in a ring 400-800px from player, random angle
var angle = Math.random() * Math.PI * 2;
var dist = 400 + Math.random() * 400;
var fx = playerCell.x + Math.cos(angle) * dist;
var fy = playerCell.y + Math.sin(angle) * dist;
// Clamp to map bounds
fx = Math.max(30, Math.min(fx, 22000 - 30));
fy = Math.max(30, Math.min(fy, 22000 - 30));
var powerFood = new PowerFood();
powerFood.x = fx;
powerFood.y = fy;
powerFoods.push(powerFood);
world.addChild(powerFood);
}
// Spawn papas periodically
if (LK.ticks % 200 == 0 && papas.length < 15) {
// Spawn papa in a ring 350-600px from player, random angle
var angle = Math.random() * Math.PI * 2;
var dist = 350 + Math.random() * 250;
var fx = playerCell.x + Math.cos(angle) * dist;
var fy = playerCell.y + Math.sin(angle) * dist;
// Clamp to map bounds
fx = Math.max(35, Math.min(fx, 22000 - 35));
fy = Math.max(35, Math.min(fy, 22000 - 35));
var papa = new Papa();
papa.x = fx;
papa.y = fy;
papas.push(papa);
world.addChild(papa);
}
// Add more predators as player grows (extreme: much more frequent, much higher max, much faster)
if (LK.ticks % 40 == 0 && predators.length < 80) {
spawnPredator();
}
// Add more AI cells as the game progresses (extreme: much more frequent, much higher max, much larger)
if (LK.ticks % 20 == 0 && aiCells.length < 120) {
spawnAICell();
}
// Find the largest cell (player, aiCells, predators)
var topCell = playerCell;
var topCellType = "Tú";
var topCellSize = playerCell ? playerCell.size : 0;
var topCellName = null;
// Check AI cells
for (var i = 0; i < aiCells.length; i++) {
if (aiCells[i].alive && aiCells[i].size > topCellSize) {
topCell = aiCells[i];
topCellType = "Bot";
topCellSize = aiCells[i].size;
topCellName = aiCells[i].randomName;
}
}
// Check predators
for (var i = 0; i < predators.length; i++) {
if (predators[i].size > topCellSize) {
topCell = predators[i];
topCellType = "Depredador";
topCellSize = predators[i].size;
topCellName = null;
}
}
// Show #1 score
if (topCell === playerCell) {
topScoreTxt.setText("#1: Tú (" + Math.floor(topCellSize) + ")");
} else if (topCellType === "Bot" && topCellName) {
topScoreTxt.setText("#1: " + topCellName + " (" + Math.floor(topCellSize) + ")");
} else {
topScoreTxt.setText("#1: " + topCellType + " (" + Math.floor(topCellSize) + ")");
}
// No win condition: game continues infinitely even if player is #1
};
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Cell Growth" and with the description "Control a growing cell that consumes food particles to increase in size while avoiding larger predators in this survival game.". No text on banner!
Alimento. In-Game asset. 2d. High contrast. No shadows
Celula. In-Game asset. 2d. High contrast. No shadows
Celula de rojos. In-Game asset. 2d. High contrast. No shadows
Pavo pierna. In-Game asset. 2d. High contrast. No shadows
Papa alimento. In-Game asset. 2d. High contrast. No shadows