Code edit (1 edits merged)
Please save this source code
User prompt
snake be very fast ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Let the snake's body turn smoothly in one piece, not in multiple pieces. And let the snake's speed increase. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When the snake hits itself, the screen will display the message "You bit yourself" and the restart screen will appear.
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addEventListener')' in or related to this line: 'document.addEventListener('DOMContentLoaded', function () {' Line Number: 12
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (1 edits merged)
Please save this source code
User prompt
restore the game to its previous state
User prompt
Please fix the bug: 'ReferenceError: appleWidth is not defined' in or related to this line: 'return Math.sqrt(dx * dx + dy * dy);' Line Number: 40
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
Code edit (2 edits merged)
Please save this source code
User prompt
The snake's head is not visible
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'getElementById')' in or related to this line: 'var cnv = document.getElementById('gameCanvas'),' Line Number: 11
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game configuration var segmentLength = 40, startingSegments = 10, spawn = { x: 1024, y: 1366 }, snakeSpeed = 8, baseSnakeSpeed = 8, speedIncrement = 0.1, maxApples = 3, appleLife = 300, segmentsPerApple = 2, snakeWidth = 30, appleWidth = 25, cursorSize = 20, snake, target, apples, score, gameState, deathMeans, smoothMovement = true, movementQueue = []; function distance(p1, p2) { var dx = p2.x - p1.x; var dy = p2.y - p1.y; return Math.sqrt(dx * dx + dy * dy); } function lineIntersect(p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) { var s1_x = p1_x - p0_x, s1_y = p1_y - p0_y, s2_x = p3_x - p2_x, s2_y = p3_y - p2_y, s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y), t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y); if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { return true; } return false; } function SGM(angle, x, y) { this.x = x || 0; this.y = y || 0; this.angle = angle || 0; this.parent = null; } ; SGM.prototype.endX = function () { return this.x + Math.cos(this.angle) * segmentLength; }; SGM.prototype.endY = function () { return this.y + Math.sin(this.angle) * segmentLength; }; SGM.prototype.pointAt = function (x, y) { var dx = x - this.x, dy = y - this.y; this.angle = Math.atan2(dy, dx); }; SGM.prototype.target = function (x, y) { this.targetX = x; this.targetY = y; this.arrived = false; this.totalDist = distance({ x: this.endX(), y: this.endY() }, { x: this.targetX, y: this.targetY }); this.currentDist = parseInt(this.totalDist); }; SGM.prototype.gotoTarget = function () { if (!this.arrived) { if (this.targetX > this.x + segmentLength || this.targetX < this.x - segmentLength || this.targetY > this.y + segmentLength || this.targetY < this.y - segmentLength) { this.pointAt(this.targetX, this.targetY); } else { this.arrived = true; } this.currentDist = distance({ x: this.endX(), y: this.endY() }, { x: this.targetX, y: this.targetY }); } // Smooth movement with tweening if (smoothMovement) { var moveSpeed = snakeSpeed * 0.8; // Slightly smoother movement var newX = this.x + (this.endX() - this.x) / moveSpeed; var newY = this.y + (this.endY() - this.y) / moveSpeed; // Use tween for very smooth transitions tween(this, { x: newX, y: newY }, { duration: 50, easing: tween.easeOut }); } else { this.x += (this.endX() - this.x) / snakeSpeed; this.y += (this.endY() - this.y) / snakeSpeed; } if (this.parent) { this.parent.drag(this.x, this.y); } }; SGM.prototype.drag = function (x, y) { this.pointAt(x, y); var newX = x - Math.cos(this.angle) * segmentLength; var newY = y - Math.sin(this.angle) * segmentLength; if (smoothMovement) { // Smooth transition for body segments tween(this, { x: newX, y: newY }, { duration: 80, easing: tween.easeInOut }); } else { this.x = newX; this.y = newY; } if (this.parent) { // Delay the parent drag slightly for smoother chain movement var self = this; LK.setTimeout(function () { self.parent.drag(self.x, self.y); }, 20); } }; SGM.prototype.render = function (context) { context.lineTo(this.endX(), this.endY()); }; function IKR(x, y) { this.ix = x || 0; this.iy = y || 0; this.sgms = []; this.lastArm = null; } ; IKR.prototype.addSeg = function (angle) { var arm = new SGM(angle); if (this.lastArm !== null) { arm.x = this.lastArm.endX(); arm.y = this.lastArm.endY(); arm.parent = this.lastArm; } else { arm.x = this.ix; arm.y = this.iy; } this.sgms.push(arm); this.lastArm = arm; }; IKR.prototype.grow = function () { var tail = this.sgms[0], arm = new SGM(tail.angle); arm.x = tail.x - Math.cos(tail.angle) * segmentLength; arm.y = tail.y - Math.sin(tail.angle) * segmentLength; tail.parent = arm; this.sgms.unshift(arm); }; IKR.prototype.drag = function (x, y) { this.lastArm.drag(x, y); }; function CUR(x, y) { this.x = x; this.y = y; this.rotation = 0; } ; CUR.prototype.render = function (context) { context.save(); context.translate(this.x, this.y); context.rotate(this.rotation); context.beginPath(); context.moveTo(0, -cursorSize); context.lineTo(0, -cursorSize / 2); context.moveTo(0, cursorSize / 2); context.lineTo(0, cursorSize); context.moveTo(-cursorSize, 0); context.lineTo(-cursorSize / 2, 0); context.moveTo(cursorSize / 2, 0); context.lineTo(cursorSize, 0); context.stroke(); context.restore(); this.rotation = (this.rotation + cursorSpin) % 360; }; function Apple(x, y) { this.x = x; this.y = y; this.life = appleLife; this.rotation = 0; } Apple.prototype.update = function () { this.life--; }; Apple.prototype.render = function (context) { context.beginPath(); context.arc(this.x, this.y, appleWidth, 0, Math.PI * 2); context.fill(); if (gameState !== 'dead') { context.save(); context.fillStyle = 'white'; context.font = '8px sans-serif'; context.fillText(this.life, this.x + 10, this.y + 10); context.restore(); CUR.prototype.render.call(this, context); } }; function init() { snake = new IKR(spawn.x, spawn.y); cursor = new CUR(-20, -20); target = new CUR(spawn.x + segmentLength * (startingSegments + 5), spawn.y); apples = []; score = 0; snakeSpeed = baseSnakeSpeed; // Reset speed to base value for (var i = 0; i < startingSegments; i++) { snake.addSeg(); } snake.lastArm.target(target.x, target.y); gameState = 'play'; } init(); // Touch events handled by game object game.down = function (x, y, obj) { switch (gameState) { case 'play': target.x = x; target.y = y; snake.lastArm.target(target.x, target.y); break; case 'dead': init(); break; } }; function badPlacement(apple) { for (var s = 0; s < snake.sgms.length; s++) { var seg = snake.sgms[s]; if (Math.min(distance(apple, { x: seg.endX(), y: seg.endY() }), distance(apple, { x: seg.x, y: seg.y })) < appleWidth * 2) { return true; } } return false; } function addScoreSegments() { for (var i = 0; i < segmentsPerApple; i++) { snake.grow(); } // Increase snake speed progressively snakeSpeed = Math.max(3, snakeSpeed - speedIncrement); } function update() { if (gameState !== 'dead') { snake.lastArm.gotoTarget(); if (snake.lastArm.endX() > 2048 - 50 || snake.lastArm.endX() < 50 || snake.lastArm.endY() > 2732 - 50 || snake.lastArm.endY() < 50) { gameState = 'dead'; deathMeans = 'Hit the wall!'; LK.showGameOver(); return; } for (var s = 0; s < snake.sgms.length - 2; s++) { var seg = snake.sgms[s]; if (lineIntersect(snake.lastArm.x, snake.lastArm.y, snake.lastArm.endX(), snake.lastArm.endY(), seg.x, seg.y, seg.endX(), seg.endY())) { gameState = 'dead'; deathMeans = 'You bit yourself'; LK.showGameOver(); return; } for (var a in apples) { var apple = apples[a]; if (Math.min(distance(apple, { x: seg.endX(), y: seg.endY() }), distance(apple, { x: seg.x, y: seg.y })) < appleWidth * 2) { score += Math.round(apple.life / 2); // half score if absorbed by the tail apples.splice(a, 1); addScoreSegments(); } } } for (var a in apples) { var apple = apples[a]; apple.update(); if (apple.life <= 0) { apples.splice(a, 1); continue; } if (distance(apple, { x: snake.lastArm.endX(), y: snake.lastArm.endY() }) < appleWidth * 2) { score += apple.life; apples.splice(a, 1); addScoreSegments(); } } if (apples.length < maxApples && Math.random() < 0.02) { var offset = appleWidth * 4, apple = new Apple(offset + Math.floor(Math.random() * (2048 - offset * 2)), offset + Math.floor(Math.random() * (2732 - offset * 2))); while (badPlacement(apple)) { apple.x = offset + Math.floor(Math.random() * (2048 - offset * 2)); apple.y = offset + Math.floor(Math.random() * (2732 - offset * 2)); } apples.push(apple); // Create visual apple var appleVisual = LK.getAsset('apple', { width: appleWidth * 2, height: appleWidth * 2, color: 0x00ff00, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); appleVisual.x = apple.x; appleVisual.y = apple.y; game.addChild(appleVisual); appleObjects.push(appleVisual); } } } // LK rendering system - visual elements handled by game objects var snakeSegments = []; var appleObjects = []; var targetObject = null; var scoreText = null; // Initialize visual elements function initVisuals() { // Clear existing visuals for (var i = 0; i < snakeSegments.length; i++) { snakeSegments[i].destroy(); } for (var i = 0; i < appleObjects.length; i++) { appleObjects[i].destroy(); } if (targetObject) targetObject.destroy(); if (scoreText) scoreText.destroy(); snakeSegments = []; appleObjects = []; // Create score text scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); scoreText.x = 120; scoreText.y = 20; // Create target indicator targetObject = LK.getAsset('target', { width: 30, height: 30, color: 0x0000ff, shape: 'ellipse', anchorX: 0.5, anchorY: 0.5 }); game.addChild(targetObject); } // Initialize the game init(); initVisuals(); // LK game update loop game.update = function () { if (gameState === 'play') { update(); // Update score display if (scoreText) { scoreText.setText('Score: ' + score); } // Update target position if (targetObject && !snake.lastArm.arrived) { targetObject.x = target.x; targetObject.y = target.y; targetObject.visible = true; } else if (targetObject) { targetObject.visible = false; } // Update snake visual segments updateSnakeVisuals(); // Update apple visuals updateAppleVisuals(); } }; function updateSnakeVisuals() { // Only update positions if we have existing segments, otherwise recreate if (snakeSegments.length !== snake.sgms.length + 1) { // Clear existing snake segments for (var i = 0; i < snakeSegments.length; i++) { snakeSegments[i].destroy(); } snakeSegments = []; // Create new snake segments for (var s = 0; s < snake.sgms.length; s++) { var seg = snake.sgms[s]; var segmentVisual = LK.getAsset('snakeSegment', { width: snakeWidth, height: segmentLength, color: 0x64ff64, shape: 'box', anchorX: 0.5, anchorY: 0 }); segmentVisual.x = seg.x; segmentVisual.y = seg.y; segmentVisual.rotation = seg.angle + Math.PI / 2; game.addChild(segmentVisual); snakeSegments.push(segmentVisual); } // Create snake head with proper sizing var head = LK.getAsset('snakeHead', { width: 60, height: 60, anchorX: 0.5, anchorY: 0.5 }); head.x = snake.lastArm.endX(); head.y = snake.lastArm.endY(); game.addChild(head); snakeSegments.push(head); } else { // Update existing segments smoothly for (var s = 0; s < snake.sgms.length; s++) { var seg = snake.sgms[s]; var segmentVisual = snakeSegments[s]; // Smooth visual updates with tweening tween(segmentVisual, { x: seg.x, y: seg.y, rotation: seg.angle + Math.PI / 2 }, { duration: 60, easing: tween.easeOut }); } // Update head smoothly var head = snakeSegments[snakeSegments.length - 1]; tween(head, { x: snake.lastArm.endX(), y: snake.lastArm.endY() }, { duration: 60, easing: tween.easeOut }); } } function updateAppleVisuals() { // Remove apples that no longer exist for (var i = appleObjects.length - 1; i >= 0; i--) { var found = false; for (var a = 0; a < apples.length; a++) { if (Math.abs(appleObjects[i].x - apples[a].x) < 5 && Math.abs(appleObjects[i].y - apples[a].y) < 5) { found = true; break; } } if (!found) { appleObjects[i].destroy(); appleObjects.splice(i, 1); } } } ; ;
===================================================================
--- original.js
+++ change.js
@@ -1,5 +1,10 @@
/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
@@ -15,8 +20,10 @@
x: 1024,
y: 1366
},
snakeSpeed = 8,
+ baseSnakeSpeed = 8,
+ speedIncrement = 0.1,
maxApples = 3,
appleLife = 300,
segmentsPerApple = 2,
snakeWidth = 30,
@@ -26,9 +33,11 @@
target,
apples,
score,
gameState,
- deathMeans;
+ deathMeans,
+ smoothMovement = true,
+ movementQueue = [];
function distance(p1, p2) {
var dx = p2.x - p1.x;
var dy = p2.y - p1.y;
return Math.sqrt(dx * dx + dy * dy);
@@ -90,18 +99,52 @@
x: this.targetX,
y: this.targetY
});
}
- this.x += (this.endX() - this.x) / snakeSpeed;
- this.y += (this.endY() - this.y) / snakeSpeed;
- this.parent.drag(this.x, this.y);
+ // Smooth movement with tweening
+ if (smoothMovement) {
+ var moveSpeed = snakeSpeed * 0.8; // Slightly smoother movement
+ var newX = this.x + (this.endX() - this.x) / moveSpeed;
+ var newY = this.y + (this.endY() - this.y) / moveSpeed;
+ // Use tween for very smooth transitions
+ tween(this, {
+ x: newX,
+ y: newY
+ }, {
+ duration: 50,
+ easing: tween.easeOut
+ });
+ } else {
+ this.x += (this.endX() - this.x) / snakeSpeed;
+ this.y += (this.endY() - this.y) / snakeSpeed;
+ }
+ if (this.parent) {
+ this.parent.drag(this.x, this.y);
+ }
};
SGM.prototype.drag = function (x, y) {
this.pointAt(x, y);
- this.x = x - Math.cos(this.angle) * segmentLength;
- this.y = y - Math.sin(this.angle) * segmentLength;
+ var newX = x - Math.cos(this.angle) * segmentLength;
+ var newY = y - Math.sin(this.angle) * segmentLength;
+ if (smoothMovement) {
+ // Smooth transition for body segments
+ tween(this, {
+ x: newX,
+ y: newY
+ }, {
+ duration: 80,
+ easing: tween.easeInOut
+ });
+ } else {
+ this.x = newX;
+ this.y = newY;
+ }
if (this.parent) {
- this.parent.drag(this.x, this.y);
+ // Delay the parent drag slightly for smoother chain movement
+ var self = this;
+ LK.setTimeout(function () {
+ self.parent.drag(self.x, self.y);
+ }, 20);
}
};
SGM.prototype.render = function (context) {
context.lineTo(this.endX(), this.endY());
@@ -187,8 +230,9 @@
cursor = new CUR(-20, -20);
target = new CUR(spawn.x + segmentLength * (startingSegments + 5), spawn.y);
apples = [];
score = 0;
+ snakeSpeed = baseSnakeSpeed; // Reset speed to base value
for (var i = 0; i < startingSegments; i++) {
snake.addSeg();
}
snake.lastArm.target(target.x, target.y);
@@ -226,8 +270,10 @@
function addScoreSegments() {
for (var i = 0; i < segmentsPerApple; i++) {
snake.grow();
}
+ // Increase snake speed progressively
+ snakeSpeed = Math.max(3, snakeSpeed - speedIncrement);
}
function update() {
if (gameState !== 'dead') {
snake.lastArm.gotoTarget();
@@ -363,41 +409,68 @@
updateAppleVisuals();
}
};
function updateSnakeVisuals() {
- // Clear existing snake segments
- for (var i = 0; i < snakeSegments.length; i++) {
- snakeSegments[i].destroy();
- }
- snakeSegments = [];
- // Create new snake segments
- for (var s = 0; s < snake.sgms.length; s++) {
- var seg = snake.sgms[s];
- var segmentVisual = LK.getAsset('snakeSegment', {
- width: snakeWidth,
- height: segmentLength,
- color: 0x64ff64,
- shape: 'box',
+ // Only update positions if we have existing segments, otherwise recreate
+ if (snakeSegments.length !== snake.sgms.length + 1) {
+ // Clear existing snake segments
+ for (var i = 0; i < snakeSegments.length; i++) {
+ snakeSegments[i].destroy();
+ }
+ snakeSegments = [];
+ // Create new snake segments
+ for (var s = 0; s < snake.sgms.length; s++) {
+ var seg = snake.sgms[s];
+ var segmentVisual = LK.getAsset('snakeSegment', {
+ width: snakeWidth,
+ height: segmentLength,
+ color: 0x64ff64,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0
+ });
+ segmentVisual.x = seg.x;
+ segmentVisual.y = seg.y;
+ segmentVisual.rotation = seg.angle + Math.PI / 2;
+ game.addChild(segmentVisual);
+ snakeSegments.push(segmentVisual);
+ }
+ // Create snake head with proper sizing
+ var head = LK.getAsset('snakeHead', {
+ width: 60,
+ height: 60,
anchorX: 0.5,
- anchorY: 0
+ anchorY: 0.5
});
- segmentVisual.x = seg.x;
- segmentVisual.y = seg.y;
- segmentVisual.rotation = seg.angle + Math.PI / 2;
- game.addChild(segmentVisual);
- snakeSegments.push(segmentVisual);
+ head.x = snake.lastArm.endX();
+ head.y = snake.lastArm.endY();
+ game.addChild(head);
+ snakeSegments.push(head);
+ } else {
+ // Update existing segments smoothly
+ for (var s = 0; s < snake.sgms.length; s++) {
+ var seg = snake.sgms[s];
+ var segmentVisual = snakeSegments[s];
+ // Smooth visual updates with tweening
+ tween(segmentVisual, {
+ x: seg.x,
+ y: seg.y,
+ rotation: seg.angle + Math.PI / 2
+ }, {
+ duration: 60,
+ easing: tween.easeOut
+ });
+ }
+ // Update head smoothly
+ var head = snakeSegments[snakeSegments.length - 1];
+ tween(head, {
+ x: snake.lastArm.endX(),
+ y: snake.lastArm.endY()
+ }, {
+ duration: 60,
+ easing: tween.easeOut
+ });
}
- // Create snake head with proper sizing
- var head = LK.getAsset('snakeHead', {
- width: 60,
- height: 60,
- anchorX: 0.5,
- anchorY: 0.5
- });
- head.x = snake.lastArm.endX();
- head.y = snake.lastArm.endY();
- game.addChild(head);
- snakeSegments.push(head);
}
function updateAppleVisuals() {
// Remove apples that no longer exist
for (var i = appleObjects.length - 1; i >= 0; i--) {