User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'head.lastDir')' in or related to this line: 'if (head.lastDir === undefined) {' Line Number: 449
User prompt
If you make a sharp turn, it kills you
User prompt
Make the head spawn normally from the body
User prompt
Now it want move and it keeps killing me because the obstacles pawn on the snake
User prompt
Make the head spawn on the body
User prompt
Remove speed poweup
User prompt
Make the head spawn away from the body
User prompt
More content
User prompt
Move the head to be away from the body (not close)
User prompt
Mive the head foward
User prompt
Remove the blue food
User prompt
Make the head further away from the body
User prompt
Make the head further away from the body
User prompt
Don’t make the obstacles move
Code edit (1 edits merged)
Please save this source code
User prompt
Snake Evolution
Initial prompt
Snake game (with new content)
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Food var Food = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('food', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Obstacle (static) var Obstacle = Container.expand(function () { var self = Container.call(this); self.asset = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Obstacles are static: no velocity, no update needed return self; }); // PowerUp var PowerUp = Container.expand(function () { var self = Container.call(this); self.type = 'speed'; // or 'invincible' self.asset = null; self.setType = function (type) { if (self.asset) self.removeChild(self.asset); self.type = type; if (type === 'speed') { self.asset = self.attachAsset('powerupSpeed', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'invincible') { self.asset = self.attachAsset('powerupInvincible', { anchorX: 0.5, anchorY: 0.5 }); } }; self.setType('speed'); return self; }); // Snake Segment (body or head) var SnakeSegment = Container.expand(function () { var self = Container.call(this); self.isHead = false; self.asset = null; self.setType = function (type) { if (self.asset) self.removeChild(self.asset); if (type === 'head') { self.asset = self.attachAsset('snakeHead', { anchorX: 0.5, anchorY: 0.5 }); self.isHead = true; } else { self.asset = self.attachAsset('snakeBody', { anchorX: 0.5, anchorY: 0.5 }); self.isHead = false; } }; self.setType('body'); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Music // Sounds // Obstacles // Power-ups // Food // Snake head and body // --- Game constants --- var SNAKE_INIT_LENGTH = 5; var SNAKE_INIT_SPEED = 16; // pixels per tick var SNAKE_MIN_SPEED = 8; var SNAKE_MAX_SPEED = 40; var SNAKE_TURN_ANGLE = Math.PI / 18; // 10 degrees per input var FOOD_SCORE = 10; var POWERUP_SCORE = 25; var POWERUP_DURATION = 300; // ticks (5 seconds) var OBSTACLE_COUNT = 3; var OBSTACLE_SPEED = 6; // --- Game state --- var snake = []; var snakeDir = 0; // in radians, 0 = right var snakeNextDir = 0; var snakeSpeed = SNAKE_INIT_SPEED; var snakeGrow = 0; var food = null; var powerup = null; var powerupActive = false; var powerupType = null; var powerupTimer = 0; var obstacles = []; var score = 0; var isInvincible = false; var lastTouch = null; var dragStart = null; var dragAngle = null; var dragActive = false; var gameOver = false; // --- GUI --- var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // --- Helper functions --- function randomPos(margin) { margin = margin || 150; var x = margin + Math.random() * (2048 - 2 * margin); var y = margin + Math.random() * (2732 - 2 * margin); return { x: x, y: y }; } function dist2(a, b) { var dx = a.x - b.x, dy = a.y - b.y; return dx * dx + dy * dy; } function angleBetween(a, b) { return Math.atan2(b.y - a.y, b.x - a.x); } function wrapPos(pos) { // Not used, but could be for wrap-around if (pos.x < 0) pos.x += 2048; if (pos.x > 2048) pos.x -= 2048; if (pos.y < 0) pos.y += 2732; if (pos.y > 2732) pos.y -= 2732; } function spawnFood() { if (food) food.destroy(); food = new Food(); var pos = randomPos(200); food.x = pos.x; food.y = pos.y; game.addChild(food); } function spawnPowerUp() { if (powerup) powerup.destroy(); powerup = new PowerUp(); var pos = randomPos(200); var t = Math.random() < 0.5 ? 'speed' : 'invincible'; powerup.setType(t); powerup.x = pos.x; powerup.y = pos.y; game.addChild(powerup); } function spawnObstacles() { for (var i = 0; i < obstacles.length; ++i) { obstacles[i].destroy(); } obstacles = []; for (var i = 0; i < OBSTACLE_COUNT; ++i) { var obs = new Obstacle(); var pos = randomPos(300); obs.x = pos.x; obs.y = pos.y; // Obstacles are static, no velocity needed obstacles.push(obs); game.addChild(obs); } } function resetSnake() { for (var i = 0; i < snake.length; ++i) { snake[i].destroy(); } snake = []; var startX = 2048 / 2, startY = 2732 / 2; for (var i = 0; i < SNAKE_INIT_LENGTH; ++i) { var seg = new SnakeSegment(); if (i === 0) seg.setType('head');else seg.setType('body'); // Make the head further away from the first body segment if (i === 0) { seg.x = startX + snakeSpeed * 2; // Move head further forward seg.y = startY; } else if (i === 1) { seg.x = startX - snakeSpeed * 2; // Further increase initial gap between head and first body segment seg.y = startY; } else { seg.x = startX - i * snakeSpeed - snakeSpeed; // Maintain increased spacing for the rest seg.y = startY; } game.addChild(seg); snake.push(seg); } snakeDir = 0; snakeNextDir = 0; snakeSpeed = SNAKE_INIT_SPEED; snakeGrow = 0; isInvincible = false; powerupActive = false; powerupType = null; powerupTimer = 0; } function updateScore(val) { score = val; scoreTxt.setText(score); LK.setScore(score); } function activatePowerUp(type) { powerupActive = true; powerupType = type; powerupTimer = POWERUP_DURATION; if (type === 'speed') { snakeSpeed = Math.min(SNAKE_MAX_SPEED, SNAKE_INIT_SPEED * 2); } else if (type === 'invincible') { isInvincible = true; // Flash snake for (var i = 0; i < snake.length; ++i) { LK.effects.flashObject(snake[i], 0xf1c40f, 500); } } } function deactivatePowerUp() { powerupActive = false; powerupType = null; powerupTimer = 0; snakeSpeed = SNAKE_INIT_SPEED; isInvincible = false; } function endGame() { if (gameOver) return; gameOver = true; LK.effects.flashScreen(0xff0000, 1000); LK.getSound('hit').play(); LK.showGameOver(); } // --- Input handling (touch/drag to steer) --- game.down = function (x, y, obj) { // Only allow drag from outside top left 100x100 if (x < 100 && y < 100) return; dragStart = { x: x, y: y }; dragAngle = null; dragActive = true; }; game.move = function (x, y, obj) { if (!dragActive) return; if (!dragStart) return; // Calculate angle from snake head to drag point var head = snake[0]; var dx = x - head.x; var dy = y - head.y; if (dx * dx + dy * dy < 100) return; // Ignore tiny drags var angle = Math.atan2(dy, dx); snakeNextDir = angle; dragAngle = angle; }; game.up = function (x, y, obj) { dragActive = false; dragStart = null; dragAngle = null; }; // --- Main game update loop --- game.update = function () { if (gameOver) return; // Power-up timer if (powerupActive) { powerupTimer--; if (powerupTimer <= 0) { deactivatePowerUp(); } } // Obstacles are static, no update needed // Snake direction: smooth turn toward nextDir var d = snakeNextDir - snakeDir; while (d > Math.PI) d -= 2 * Math.PI; while (d < -Math.PI) d += 2 * Math.PI; if (Math.abs(d) > 0.01) { var turn = Math.sign(d) * Math.min(Math.abs(d), SNAKE_TURN_ANGLE); snakeDir += turn; } // Move snake head var head = snake[0]; var prevPos = { x: head.x, y: head.y }; head.x += Math.cos(snakeDir) * snakeSpeed; head.y += Math.sin(snakeDir) * snakeSpeed; // Clamp to bounds (leave 100px margin for UI) head.x = Math.max(100 + head.asset.width / 2, Math.min(2048 - 100 - head.asset.width / 2, head.x)); head.y = Math.max(100 + head.asset.height / 2, Math.min(2732 - 100 - head.asset.height / 2, head.y)); // Move body segments to follow for (var i = 1; i < snake.length; ++i) { var seg = snake[i]; var target = snake[i - 1]; var dx = target.x - seg.x; var dy = target.y - seg.y; var dist = Math.sqrt(dx * dx + dy * dy); var desired = snakeSpeed * 0.9; if (dist > desired) { var move = (dist - desired) * 0.5; seg.x += dx / dist * move; seg.y += dy / dist * move; } } // Grow snake if needed if (snakeGrow > 0) { var tail = snake[snake.length - 1]; var newSeg = new SnakeSegment(); newSeg.setType('body'); newSeg.x = tail.x; newSeg.y = tail.y; game.addChild(newSeg); snake.push(newSeg); snakeGrow--; } // Check collision with food if (food && head.intersects(food)) { LK.getSound('eat').play(); updateScore(score + FOOD_SCORE); snakeGrow += 2; food.destroy(); food = null; spawnFood(); // Chance to spawn powerup if (!powerup && Math.random() < 0.2) { spawnPowerUp(); } } // Check collision with powerup if (powerup && head.intersects(powerup)) { LK.getSound('powerup').play(); updateScore(score + POWERUP_SCORE); activatePowerUp(powerup.type); powerup.destroy(); powerup = null; } // Check collision with obstacles for (var i = 0; i < obstacles.length; ++i) { if (head.intersects(obstacles[i])) { if (!isInvincible) { endGame(); return; } else { // Flash obstacle and destroy it LK.effects.flashObject(obstacles[i], 0xffffff, 300); obstacles[i].destroy(); obstacles.splice(i, 1); i--; } } } // Check collision with self (skip first 4 segments for leniency) if (!isInvincible) { for (var i = 4; i < snake.length; ++i) { if (head.intersects(snake[i])) { endGame(); return; } } } // Evolving obstacles: every 30 seconds, add a new one (max 8) if (LK.ticks % (60 * 30) === 0 && obstacles.length < 8) { var obs = new Obstacle(); var pos = randomPos(300); obs.x = pos.x; obs.y = pos.y; // Obstacles are static, no velocity needed obstacles.push(obs); game.addChild(obs); } }; // --- Game start/reset --- function startGame() { gameOver = false; updateScore(0); resetSnake(); spawnFood(); if (powerup) { powerup.destroy(); powerup = null; } spawnObstacles(); deactivatePowerUp(); LK.playMusic('snakebg', { fade: { start: 0, end: 1, duration: 1000 } }); } startGame(); // --- Game over/win handling is automatic by LK --- // --- Music is started on game start ---
===================================================================
--- original.js
+++ change.js
@@ -195,15 +195,15 @@
var seg = new SnakeSegment();
if (i === 0) seg.setType('head');else seg.setType('body');
// Make the head further away from the first body segment
if (i === 0) {
- seg.x = startX;
+ seg.x = startX + snakeSpeed * 2; // Move head further forward
seg.y = startY;
} else if (i === 1) {
- seg.x = startX - snakeSpeed * 4; // Further increase initial gap between head and first body segment
+ seg.x = startX - snakeSpeed * 2; // Further increase initial gap between head and first body segment
seg.y = startY;
} else {
- seg.x = startX - i * snakeSpeed - snakeSpeed * 3; // Maintain increased spacing for the rest
+ seg.x = startX - i * snakeSpeed - snakeSpeed; // Maintain increased spacing for the rest
seg.y = startY;
}
game.addChild(seg);
snake.push(seg);