User prompt
- Player can fart every eating lure
User prompt
- Fart is not working properly. Fix this - Remove win condition
User prompt
-Add a fart to player. It trigger when player kill the enemy. - Increase enemy speed - ıNCREASE ENEMY SPAWN RATE -
User prompt
Remove enemy fart mechanic
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'var dx = playerPos.x - self.head.x + (Math.random() - 0.5) * 200;' Line Number: 79
Code edit (1 edits merged)
Please save this source code
User prompt
Snake Minigun Mayhem
Initial prompt
Make me a classic snake game. But add a minigun to this snake. It will be shoot when enemy is nearby. Every time shoot the enemy snake going to fart as flame.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet var Bullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.owner = null; // 'player' or 'enemy' self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Enemy Snake Head var EnemyHead = Container.expand(function () { var self = Container.call(this); var head = self.attachAsset('enemyHead', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Enemy Snake Segment var EnemySegment = Container.expand(function () { var self = Container.call(this); var body = self.attachAsset('enemyBody', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Enemy Snake var EnemySnake = Container.expand(function () { var self = Container.call(this); self.segments = []; self.head = new EnemyHead(); self.addChild(self.head); self.segments.push(self.head); self.length = 4 + Math.floor(Math.random() * 3); self.speed = 7 + Math.random() * 3; self.targetX = 1024 + (Math.random() - 0.5) * 800; self.targetY = 1366 + (Math.random() - 0.5) * 1200; self.lastMoveX = 0; self.lastMoveY = 1; self.alive = true; // Initialize body for (var i = 1; i < self.length; i++) { var seg = new EnemySegment(); seg.x = self.head.x; seg.y = self.head.y + i * 80; self.addChild(seg); self.segments.push(seg); } // Move snake self.moveSnake = function (playerPos) { // Move toward player, but with some randomness var dx = playerPos.x - self.head.x + (Math.random() - 0.5) * 200; var dy = playerPos.y - self.head.y + (Math.random() - 0.5) * 200; var dist = Math.sqrt(dx * dx + dy * dy); var moveX = 0, moveY = 0; if (dist > 10) { moveX = dx / dist; moveY = dy / dist; self.lastMoveX = moveX; self.lastMoveY = moveY; } else { moveX = self.lastMoveX; moveY = self.lastMoveY; } self.head.x += moveX * self.speed; self.head.y += moveY * self.speed; // Move body for (var i = self.segments.length - 1; i > 0; i--) { var prev = self.segments[i - 1]; var seg = self.segments[i]; var pdx = prev.x - seg.x; var pdy = prev.y - seg.y; var pdist = Math.sqrt(pdx * pdx + pdy * pdy); if (pdist > 80) { seg.x += pdx / pdist * Math.min(self.speed, pdist - 80); seg.y += pdy / pdist * Math.min(self.speed, pdist - 80); } } }; // Update self.update = function (playerPos) { if (!self.alive) return; self.moveSnake(playerPos); }; // Get head position self.getHeadPos = function () { return { x: self.head.x, y: self.head.y }; }; // Get direction vector self.getDirection = function () { return { x: self.lastMoveX, y: self.lastMoveY }; }; // Die self.die = function () { self.alive = false; // Fade out for (var i = 0; i < self.segments.length; i++) { tween(self.segments[i], { alpha: 0 }, { duration: 400, easing: tween.linear, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); // Flame Fart Burst var Flame = Container.expand(function () { var self = Container.call(this); var flame = self.attachAsset('flame', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.life = 30; // frames self.update = function () { self.x += self.vx; self.y += self.vy; self.life--; if (self.life <= 0) { self.destroy(); } }; return self; }); // Food var Food = Container.expand(function () { var self = Container.call(this); var food = self.attachAsset('food', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Player Snake var PlayerSnake = Container.expand(function () { var self = Container.call(this); self.segments = []; self.directions = []; self.head = new SnakeHead(); self.addChild(self.head); self.segments.push(self.head); self.length = 5; self.speed = 12; self.targetX = 1024; self.targetY = 1366; self.lastMoveX = 0; self.lastMoveY = -1; self.growPending = 0; self.lastFireTick = 0; // Initialize body for (var i = 1; i < self.length; i++) { var seg = new SnakeSegment(); seg.x = self.head.x; seg.y = self.head.y + i * 80; self.addChild(seg); self.segments.push(seg); } // Move snake self.moveSnake = function () { // Calculate direction to target var dx = self.targetX - self.head.x; var dy = self.targetY - self.head.y; var dist = Math.sqrt(dx * dx + dy * dy); var moveX = 0, moveY = 0; if (dist > 10) { moveX = dx / dist; moveY = dy / dist; self.lastMoveX = moveX; self.lastMoveY = moveY; } else { moveX = self.lastMoveX; moveY = self.lastMoveY; } // Move head self.head.x += moveX * self.speed; self.head.y += moveY * self.speed; // Move body for (var i = self.segments.length - 1; i > 0; i--) { var prev = self.segments[i - 1]; var seg = self.segments[i]; var pdx = prev.x - seg.x; var pdy = prev.y - seg.y; var pdist = Math.sqrt(pdx * pdx + pdy * pdy); if (pdist > 80) { seg.x += pdx / pdist * Math.min(self.speed, pdist - 80); seg.y += pdy / pdist * Math.min(self.speed, pdist - 80); } } }; // Grow snake self.grow = function (n) { self.growPending += n; }; // Update self.update = function () { self.moveSnake(); // Handle growth if (self.growPending > 0) { var last = self.segments[self.segments.length - 1]; var seg = new SnakeSegment(); seg.x = last.x; seg.y = last.y; self.addChild(seg); self.segments.push(seg); self.growPending--; } }; // Get head position self.getHeadPos = function () { return { x: self.head.x, y: self.head.y }; }; // Get direction vector self.getDirection = function () { return { x: self.lastMoveX, y: self.lastMoveY }; }; return self; }); // Player Snake Head var SnakeHead = Container.expand(function () { var self = Container.call(this); var head = self.attachAsset('snakeHead', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Player Snake Segment var SnakeSegment = Container.expand(function () { var self = Container.call(this); var body = self.attachAsset('snakeBody', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Flame fart burst // Bullet // Food // Enemy snake head // Enemy snake body // Snake head (player) // Snake body segment (player) // Game variables var playerSnake; var enemySnakes = []; var foods = []; var bullets = []; var flames = []; var scoreTxt; var dragNode = null; var lastFireTick = 0; var spawnFoodTick = 0; var spawnEnemyTick = 0; var gameArea = { x: 120, y: 120, w: 2048 - 240, h: 2732 - 240 }; // leave margin for UI // Score display scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Initialize player snake playerSnake = new PlayerSnake(); playerSnake.head.x = 1024; playerSnake.head.y = 1800; for (var i = 0; i < playerSnake.segments.length; i++) { playerSnake.segments[i].x = 1024; playerSnake.segments[i].y = 1800 + i * 80; } game.addChild(playerSnake); // Spawn initial food function spawnFood() { var f = new Food(); f.x = gameArea.x + 100 + Math.random() * (gameArea.w - 200); f.y = gameArea.y + 100 + Math.random() * (gameArea.h - 200); foods.push(f); game.addChild(f); } for (var i = 0; i < 8; i++) { spawnFood(); } // Spawn enemy snake function spawnEnemy() { var e = new EnemySnake(); // Spawn at random edge var edge = Math.floor(Math.random() * 4); if (edge === 0) { // top e.head.x = gameArea.x + Math.random() * gameArea.w; e.head.y = gameArea.y - 120; } else if (edge === 1) { // bottom e.head.x = gameArea.x + Math.random() * gameArea.w; e.head.y = gameArea.y + gameArea.h + 120; } else if (edge === 2) { // left e.head.x = gameArea.x - 120; e.head.y = gameArea.y + Math.random() * gameArea.h; } else { // right e.head.x = gameArea.x + gameArea.w + 120; e.head.y = gameArea.y + Math.random() * gameArea.h; } for (var i = 1; i < e.segments.length; i++) { e.segments[i].x = e.head.x; e.segments[i].y = e.head.y + i * 80; } enemySnakes.push(e); game.addChild(e); } for (var i = 0; i < 2; i++) { spawnEnemy(); } // Handle dragging game.down = function (x, y, obj) { dragNode = playerSnake; playerSnake.targetX = x; playerSnake.targetY = y; }; game.move = function (x, y, obj) { if (dragNode) { playerSnake.targetX = x; playerSnake.targetY = y; } }; game.up = function (x, y, obj) { dragNode = null; }; // Helper: check collision between two containers (circle-based) function circlesIntersect(a, b, rA, rB) { var dx = a.x - b.x; var dy = a.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); return dist < (rA + rB) * 0.5; } // Helper: clamp to game area function clampToArea(x, y) { x = Math.max(gameArea.x + 50, Math.min(gameArea.x + gameArea.w - 50, x)); y = Math.max(gameArea.y + 50, Math.min(gameArea.y + gameArea.h - 50, y)); return { x: x, y: y }; } // Main game update game.update = function () { // Update player snake playerSnake.update(); // Clamp player head to area var clamped = clampToArea(playerSnake.head.x, playerSnake.head.y); playerSnake.head.x = clamped.x; playerSnake.head.y = clamped.y; // Update enemy snakes for (var i = enemySnakes.length - 1; i >= 0; i--) { var e = enemySnakes[i]; if (!e.alive) continue; e.update(playerSnake.getHeadPos()); // Clamp enemy head to area var ce = clampToArea(e.head.x, e.head.y); e.head.x = ce.x; e.head.y = ce.y; } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); // Remove if out of bounds if (b.x < gameArea.x - 60 || b.x > gameArea.x + gameArea.w + 60 || b.y < gameArea.y - 60 || b.y > gameArea.y + gameArea.h + 60) { b.destroy(); bullets.splice(i, 1); continue; } // Bullet hits enemy snake if (b.owner === 'player') { for (var j = 0; j < enemySnakes.length; j++) { var e = enemySnakes[j]; if (!e.alive) continue; if (circlesIntersect(b, e.head, 60, 60)) { // Hit! b.destroy(); bullets.splice(i, 1); // Fart burst! spawnFlameBurst(e.head.x, e.head.y, e.getDirection()); // Shorten enemy snake or kill if (e.segments.length > 2) { var seg = e.segments.pop(); seg.destroy(); } else { e.die(); } LK.setScore(LK.getScore() + 5); scoreTxt.setText(LK.getScore()); break; } } } // Bullet hits player (if we add enemy bullets in future) } // Update flames for (var i = flames.length - 1; i >= 0; i--) { var f = flames[i]; f.update(); // Remove if dead if (f.life <= 0) { f.destroy(); flames.splice(i, 1); continue; } // Flame hits player snake head if (circlesIntersect(f, playerSnake.head, 60, 60)) { // Game over LK.effects.flashScreen(0xff3300, 800); LK.showGameOver(); return; } } // Player eats food for (var i = foods.length - 1; i >= 0; i--) { var food = foods[i]; if (circlesIntersect(playerSnake.head, food, 60, 35)) { food.destroy(); foods.splice(i, 1); playerSnake.grow(2); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); // Win condition if (LK.getScore() >= 50) { LK.showYouWin(); return; } } } // Player collides with enemy snake head or body for (var i = 0; i < enemySnakes.length; i++) { var e = enemySnakes[i]; if (!e.alive) continue; // Head to head if (circlesIntersect(playerSnake.head, e.head, 60, 60)) { LK.effects.flashScreen(0xff3300, 800); LK.showGameOver(); return; } // Head to body for (var j = 1; j < e.segments.length; j++) { if (circlesIntersect(playerSnake.head, e.segments[j], 60, 40)) { LK.effects.flashScreen(0xff3300, 800); LK.showGameOver(); return; } } } // Player collides with self (not head) for (var i = 2; i < playerSnake.segments.length; i++) { if (circlesIntersect(playerSnake.head, playerSnake.segments[i], 60, 40)) { LK.effects.flashScreen(0xff3300, 800); LK.showGameOver(); return; } } // Spawn food spawnFoodTick++; if (spawnFoodTick > 40 && foods.length < 12) { spawnFood(); spawnFoodTick = 0; } // Spawn enemy spawnEnemyTick++; if (spawnEnemyTick > 180 && enemySnakes.length < 6) { spawnEnemy(); spawnEnemyTick = 0; } // Minigun: auto-fire at nearest enemy in range if (LK.ticks - lastFireTick > 4) { // ~15 shots/sec var nearest = null; var minDist = 99999; for (var i = 0; i < enemySnakes.length; i++) { var e = enemySnakes[i]; if (!e.alive) continue; var dx = e.head.x - playerSnake.head.x; var dy = e.head.y - playerSnake.head.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 600 && dist < minDist) { minDist = dist; nearest = e; } } if (nearest) { fireBulletAt(playerSnake.head.x, playerSnake.head.y, nearest.head.x, nearest.head.y, 'player'); lastFireTick = LK.ticks; } } }; // Fire bullet from (x0,y0) to (x1,y1) function fireBulletAt(x0, y0, x1, y1, owner) { var b = new Bullet(); b.x = x0; b.y = y0; var dx = x1 - x0; var dy = y1 - y0; var dist = Math.sqrt(dx * dx + dy * dy); var speed = 38; b.vx = dx / dist * speed; b.vy = dy / dist * speed; b.owner = owner; bullets.push(b); game.addChild(b); } // Spawn a flame fart burst at (x,y) in direction dir (object with x,y) function spawnFlameBurst(x, y, dir) { var n = 7; var angle0 = Math.atan2(dir.y, dir.x); for (var i = 0; i < n; i++) { var angle = angle0 + (Math.random() - 0.5) * 1.2; var f = new Flame(); f.x = x; f.y = y; var spd = 18 + Math.random() * 8; f.vx = Math.cos(angle) * spd; f.vy = Math.sin(angle) * spd; flames.push(f); game.addChild(f); // Animate flame fade out tween(f, { alpha: 0 }, { duration: 500, easing: tween.linear }); } } // Center score text scoreTxt.setText(LK.getScore()); scoreTxt.anchor.set(0.5, 0); // No music or sound for MVP
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,587 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Bullet
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bullet = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.owner = null; // 'player' or 'enemy'
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ };
+ return self;
+});
+// Enemy Snake Head
+var EnemyHead = Container.expand(function () {
+ var self = Container.call(this);
+ var head = self.attachAsset('enemyHead', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Enemy Snake Segment
+var EnemySegment = Container.expand(function () {
+ var self = Container.call(this);
+ var body = self.attachAsset('enemyBody', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Enemy Snake
+var EnemySnake = Container.expand(function () {
+ var self = Container.call(this);
+ self.segments = [];
+ self.head = new EnemyHead();
+ self.addChild(self.head);
+ self.segments.push(self.head);
+ self.length = 4 + Math.floor(Math.random() * 3);
+ self.speed = 7 + Math.random() * 3;
+ self.targetX = 1024 + (Math.random() - 0.5) * 800;
+ self.targetY = 1366 + (Math.random() - 0.5) * 1200;
+ self.lastMoveX = 0;
+ self.lastMoveY = 1;
+ self.alive = true;
+ // Initialize body
+ for (var i = 1; i < self.length; i++) {
+ var seg = new EnemySegment();
+ seg.x = self.head.x;
+ seg.y = self.head.y + i * 80;
+ self.addChild(seg);
+ self.segments.push(seg);
+ }
+ // Move snake
+ self.moveSnake = function (playerPos) {
+ // Move toward player, but with some randomness
+ var dx = playerPos.x - self.head.x + (Math.random() - 0.5) * 200;
+ var dy = playerPos.y - self.head.y + (Math.random() - 0.5) * 200;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var moveX = 0,
+ moveY = 0;
+ if (dist > 10) {
+ moveX = dx / dist;
+ moveY = dy / dist;
+ self.lastMoveX = moveX;
+ self.lastMoveY = moveY;
+ } else {
+ moveX = self.lastMoveX;
+ moveY = self.lastMoveY;
+ }
+ self.head.x += moveX * self.speed;
+ self.head.y += moveY * self.speed;
+ // Move body
+ for (var i = self.segments.length - 1; i > 0; i--) {
+ var prev = self.segments[i - 1];
+ var seg = self.segments[i];
+ var pdx = prev.x - seg.x;
+ var pdy = prev.y - seg.y;
+ var pdist = Math.sqrt(pdx * pdx + pdy * pdy);
+ if (pdist > 80) {
+ seg.x += pdx / pdist * Math.min(self.speed, pdist - 80);
+ seg.y += pdy / pdist * Math.min(self.speed, pdist - 80);
+ }
+ }
+ };
+ // Update
+ self.update = function (playerPos) {
+ if (!self.alive) return;
+ self.moveSnake(playerPos);
+ };
+ // Get head position
+ self.getHeadPos = function () {
+ return {
+ x: self.head.x,
+ y: self.head.y
+ };
+ };
+ // Get direction vector
+ self.getDirection = function () {
+ return {
+ x: self.lastMoveX,
+ y: self.lastMoveY
+ };
+ };
+ // Die
+ self.die = function () {
+ self.alive = false;
+ // Fade out
+ for (var i = 0; i < self.segments.length; i++) {
+ tween(self.segments[i], {
+ alpha: 0
+ }, {
+ duration: 400,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ }
+ };
+ return self;
+});
+// Flame Fart Burst
+var Flame = Container.expand(function () {
+ var self = Container.call(this);
+ var flame = self.attachAsset('flame', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.life = 30; // frames
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ self.life--;
+ if (self.life <= 0) {
+ self.destroy();
+ }
+ };
+ return self;
+});
+// Food
+var Food = Container.expand(function () {
+ var self = Container.call(this);
+ var food = self.attachAsset('food', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Player Snake
+var PlayerSnake = Container.expand(function () {
+ var self = Container.call(this);
+ self.segments = [];
+ self.directions = [];
+ self.head = new SnakeHead();
+ self.addChild(self.head);
+ self.segments.push(self.head);
+ self.length = 5;
+ self.speed = 12;
+ self.targetX = 1024;
+ self.targetY = 1366;
+ self.lastMoveX = 0;
+ self.lastMoveY = -1;
+ self.growPending = 0;
+ self.lastFireTick = 0;
+ // Initialize body
+ for (var i = 1; i < self.length; i++) {
+ var seg = new SnakeSegment();
+ seg.x = self.head.x;
+ seg.y = self.head.y + i * 80;
+ self.addChild(seg);
+ self.segments.push(seg);
+ }
+ // Move snake
+ self.moveSnake = function () {
+ // Calculate direction to target
+ var dx = self.targetX - self.head.x;
+ var dy = self.targetY - self.head.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var moveX = 0,
+ moveY = 0;
+ if (dist > 10) {
+ moveX = dx / dist;
+ moveY = dy / dist;
+ self.lastMoveX = moveX;
+ self.lastMoveY = moveY;
+ } else {
+ moveX = self.lastMoveX;
+ moveY = self.lastMoveY;
+ }
+ // Move head
+ self.head.x += moveX * self.speed;
+ self.head.y += moveY * self.speed;
+ // Move body
+ for (var i = self.segments.length - 1; i > 0; i--) {
+ var prev = self.segments[i - 1];
+ var seg = self.segments[i];
+ var pdx = prev.x - seg.x;
+ var pdy = prev.y - seg.y;
+ var pdist = Math.sqrt(pdx * pdx + pdy * pdy);
+ if (pdist > 80) {
+ seg.x += pdx / pdist * Math.min(self.speed, pdist - 80);
+ seg.y += pdy / pdist * Math.min(self.speed, pdist - 80);
+ }
+ }
+ };
+ // Grow snake
+ self.grow = function (n) {
+ self.growPending += n;
+ };
+ // Update
+ self.update = function () {
+ self.moveSnake();
+ // Handle growth
+ if (self.growPending > 0) {
+ var last = self.segments[self.segments.length - 1];
+ var seg = new SnakeSegment();
+ seg.x = last.x;
+ seg.y = last.y;
+ self.addChild(seg);
+ self.segments.push(seg);
+ self.growPending--;
+ }
+ };
+ // Get head position
+ self.getHeadPos = function () {
+ return {
+ x: self.head.x,
+ y: self.head.y
+ };
+ };
+ // Get direction vector
+ self.getDirection = function () {
+ return {
+ x: self.lastMoveX,
+ y: self.lastMoveY
+ };
+ };
+ return self;
+});
+// Player Snake Head
+var SnakeHead = Container.expand(function () {
+ var self = Container.call(this);
+ var head = self.attachAsset('snakeHead', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Player Snake Segment
+var SnakeSegment = Container.expand(function () {
+ var self = Container.call(this);
+ var body = self.attachAsset('snakeBody', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x181818
+});
+
+/****
+* Game Code
+****/
+// Flame fart burst
+// Bullet
+// Food
+// Enemy snake head
+// Enemy snake body
+// Snake head (player)
+// Snake body segment (player)
+// Game variables
+var playerSnake;
+var enemySnakes = [];
+var foods = [];
+var bullets = [];
+var flames = [];
+var scoreTxt;
+var dragNode = null;
+var lastFireTick = 0;
+var spawnFoodTick = 0;
+var spawnEnemyTick = 0;
+var gameArea = {
+ x: 120,
+ y: 120,
+ w: 2048 - 240,
+ h: 2732 - 240
+}; // leave margin for UI
+// Score display
+scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Initialize player snake
+playerSnake = new PlayerSnake();
+playerSnake.head.x = 1024;
+playerSnake.head.y = 1800;
+for (var i = 0; i < playerSnake.segments.length; i++) {
+ playerSnake.segments[i].x = 1024;
+ playerSnake.segments[i].y = 1800 + i * 80;
+}
+game.addChild(playerSnake);
+// Spawn initial food
+function spawnFood() {
+ var f = new Food();
+ f.x = gameArea.x + 100 + Math.random() * (gameArea.w - 200);
+ f.y = gameArea.y + 100 + Math.random() * (gameArea.h - 200);
+ foods.push(f);
+ game.addChild(f);
+}
+for (var i = 0; i < 8; i++) {
+ spawnFood();
+}
+// Spawn enemy snake
+function spawnEnemy() {
+ var e = new EnemySnake();
+ // Spawn at random edge
+ var edge = Math.floor(Math.random() * 4);
+ if (edge === 0) {
+ // top
+ e.head.x = gameArea.x + Math.random() * gameArea.w;
+ e.head.y = gameArea.y - 120;
+ } else if (edge === 1) {
+ // bottom
+ e.head.x = gameArea.x + Math.random() * gameArea.w;
+ e.head.y = gameArea.y + gameArea.h + 120;
+ } else if (edge === 2) {
+ // left
+ e.head.x = gameArea.x - 120;
+ e.head.y = gameArea.y + Math.random() * gameArea.h;
+ } else {
+ // right
+ e.head.x = gameArea.x + gameArea.w + 120;
+ e.head.y = gameArea.y + Math.random() * gameArea.h;
+ }
+ for (var i = 1; i < e.segments.length; i++) {
+ e.segments[i].x = e.head.x;
+ e.segments[i].y = e.head.y + i * 80;
+ }
+ enemySnakes.push(e);
+ game.addChild(e);
+}
+for (var i = 0; i < 2; i++) {
+ spawnEnemy();
+}
+// Handle dragging
+game.down = function (x, y, obj) {
+ dragNode = playerSnake;
+ playerSnake.targetX = x;
+ playerSnake.targetY = y;
+};
+game.move = function (x, y, obj) {
+ if (dragNode) {
+ playerSnake.targetX = x;
+ playerSnake.targetY = y;
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Helper: check collision between two containers (circle-based)
+function circlesIntersect(a, b, rA, rB) {
+ var dx = a.x - b.x;
+ var dy = a.y - b.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ return dist < (rA + rB) * 0.5;
+}
+// Helper: clamp to game area
+function clampToArea(x, y) {
+ x = Math.max(gameArea.x + 50, Math.min(gameArea.x + gameArea.w - 50, x));
+ y = Math.max(gameArea.y + 50, Math.min(gameArea.y + gameArea.h - 50, y));
+ return {
+ x: x,
+ y: y
+ };
+}
+// Main game update
+game.update = function () {
+ // Update player snake
+ playerSnake.update();
+ // Clamp player head to area
+ var clamped = clampToArea(playerSnake.head.x, playerSnake.head.y);
+ playerSnake.head.x = clamped.x;
+ playerSnake.head.y = clamped.y;
+ // Update enemy snakes
+ for (var i = enemySnakes.length - 1; i >= 0; i--) {
+ var e = enemySnakes[i];
+ if (!e.alive) continue;
+ e.update(playerSnake.getHeadPos());
+ // Clamp enemy head to area
+ var ce = clampToArea(e.head.x, e.head.y);
+ e.head.x = ce.x;
+ e.head.y = ce.y;
+ }
+ // Update bullets
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var b = bullets[i];
+ b.update();
+ // Remove if out of bounds
+ if (b.x < gameArea.x - 60 || b.x > gameArea.x + gameArea.w + 60 || b.y < gameArea.y - 60 || b.y > gameArea.y + gameArea.h + 60) {
+ b.destroy();
+ bullets.splice(i, 1);
+ continue;
+ }
+ // Bullet hits enemy snake
+ if (b.owner === 'player') {
+ for (var j = 0; j < enemySnakes.length; j++) {
+ var e = enemySnakes[j];
+ if (!e.alive) continue;
+ if (circlesIntersect(b, e.head, 60, 60)) {
+ // Hit!
+ b.destroy();
+ bullets.splice(i, 1);
+ // Fart burst!
+ spawnFlameBurst(e.head.x, e.head.y, e.getDirection());
+ // Shorten enemy snake or kill
+ if (e.segments.length > 2) {
+ var seg = e.segments.pop();
+ seg.destroy();
+ } else {
+ e.die();
+ }
+ LK.setScore(LK.getScore() + 5);
+ scoreTxt.setText(LK.getScore());
+ break;
+ }
+ }
+ }
+ // Bullet hits player (if we add enemy bullets in future)
+ }
+ // Update flames
+ for (var i = flames.length - 1; i >= 0; i--) {
+ var f = flames[i];
+ f.update();
+ // Remove if dead
+ if (f.life <= 0) {
+ f.destroy();
+ flames.splice(i, 1);
+ continue;
+ }
+ // Flame hits player snake head
+ if (circlesIntersect(f, playerSnake.head, 60, 60)) {
+ // Game over
+ LK.effects.flashScreen(0xff3300, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Player eats food
+ for (var i = foods.length - 1; i >= 0; i--) {
+ var food = foods[i];
+ if (circlesIntersect(playerSnake.head, food, 60, 35)) {
+ food.destroy();
+ foods.splice(i, 1);
+ playerSnake.grow(2);
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ // Win condition
+ if (LK.getScore() >= 50) {
+ LK.showYouWin();
+ return;
+ }
+ }
+ }
+ // Player collides with enemy snake head or body
+ for (var i = 0; i < enemySnakes.length; i++) {
+ var e = enemySnakes[i];
+ if (!e.alive) continue;
+ // Head to head
+ if (circlesIntersect(playerSnake.head, e.head, 60, 60)) {
+ LK.effects.flashScreen(0xff3300, 800);
+ LK.showGameOver();
+ return;
+ }
+ // Head to body
+ for (var j = 1; j < e.segments.length; j++) {
+ if (circlesIntersect(playerSnake.head, e.segments[j], 60, 40)) {
+ LK.effects.flashScreen(0xff3300, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ }
+ // Player collides with self (not head)
+ for (var i = 2; i < playerSnake.segments.length; i++) {
+ if (circlesIntersect(playerSnake.head, playerSnake.segments[i], 60, 40)) {
+ LK.effects.flashScreen(0xff3300, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Spawn food
+ spawnFoodTick++;
+ if (spawnFoodTick > 40 && foods.length < 12) {
+ spawnFood();
+ spawnFoodTick = 0;
+ }
+ // Spawn enemy
+ spawnEnemyTick++;
+ if (spawnEnemyTick > 180 && enemySnakes.length < 6) {
+ spawnEnemy();
+ spawnEnemyTick = 0;
+ }
+ // Minigun: auto-fire at nearest enemy in range
+ if (LK.ticks - lastFireTick > 4) {
+ // ~15 shots/sec
+ var nearest = null;
+ var minDist = 99999;
+ for (var i = 0; i < enemySnakes.length; i++) {
+ var e = enemySnakes[i];
+ if (!e.alive) continue;
+ var dx = e.head.x - playerSnake.head.x;
+ var dy = e.head.y - playerSnake.head.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 600 && dist < minDist) {
+ minDist = dist;
+ nearest = e;
+ }
+ }
+ if (nearest) {
+ fireBulletAt(playerSnake.head.x, playerSnake.head.y, nearest.head.x, nearest.head.y, 'player');
+ lastFireTick = LK.ticks;
+ }
+ }
+};
+// Fire bullet from (x0,y0) to (x1,y1)
+function fireBulletAt(x0, y0, x1, y1, owner) {
+ var b = new Bullet();
+ b.x = x0;
+ b.y = y0;
+ var dx = x1 - x0;
+ var dy = y1 - y0;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ var speed = 38;
+ b.vx = dx / dist * speed;
+ b.vy = dy / dist * speed;
+ b.owner = owner;
+ bullets.push(b);
+ game.addChild(b);
+}
+// Spawn a flame fart burst at (x,y) in direction dir (object with x,y)
+function spawnFlameBurst(x, y, dir) {
+ var n = 7;
+ var angle0 = Math.atan2(dir.y, dir.x);
+ for (var i = 0; i < n; i++) {
+ var angle = angle0 + (Math.random() - 0.5) * 1.2;
+ var f = new Flame();
+ f.x = x;
+ f.y = y;
+ var spd = 18 + Math.random() * 8;
+ f.vx = Math.cos(angle) * spd;
+ f.vy = Math.sin(angle) * spd;
+ flames.push(f);
+ game.addChild(f);
+ // Animate flame fade out
+ tween(f, {
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.linear
+ });
+ }
+}
+// Center score text
+scoreTxt.setText(LK.getScore());
+scoreTxt.anchor.set(0.5, 0);
+// No music or sound for MVP
\ No newline at end of file