User prompt
Please fix the bug: 'Timeout.tick error: LK.setGameOverText is not a function' in or related to this line: 'LK.setGameOverText('Best: ' + bestScore);' Line Number: 380
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var bestScore = storage.get('flyingChickenBestScore') || 0;' Line Number: 167 โช๐ก Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'storage.getItem is not a function' in or related to this line: 'var bestScore = storage.getItem('flyingChickenBestScore') || 0;' Line Number: 167
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var bestScore = storage.get('flyingChickenBestScore') || 0;' Line Number: 167
User prompt
add top score in game over screen
User prompt
add 8-bit background music
Code edit (1 edits merged)
Please save this source code
User prompt
Flying Chicken
Initial prompt
๐ฑ Game Name: "Flying Chicken" ๐ Concept: The player makes a chicken jump between obstacles. The goal is to go as far as possible. A "tap-to-jump" game that seems easy but requires timing. ๐ฎ Gameplay: Control Mechanics: Just one touch: when you touch the screen, the chicken jumps up, when you release it, it falls down (Flappy Bird style). Obstacles: There are obstacles such as protruding pipes, walls or tractor tires on both sides of the screen (top-bottom or right-left). +1 point is earned for each obstacle passed. Difficulty: The gap between obstacles narrows, moving obstacles may come, environmental factors such as wind/birds may be added.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Chicken class
var Chicken = Container.expand(function () {
var self = Container.call(this);
var chickenSprite = self.attachAsset('chicken', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = chickenSprite.width * 0.5;
self.vy = 0;
self.gravity = 2.2;
self.flapStrength = -38;
self.maxFall = 38;
self.alive = true;
// Flap upward
self.flap = function () {
if (!self.alive) return;
self.vy = self.flapStrength;
LK.getSound('flap').play();
// Animate chicken (slight scale for feedback)
tween.stop(self, {
scaleY: true
});
self.scaleY = 1.0;
tween(self, {
scaleY: 0.8
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
scaleY: 1.0
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
};
// Update position
self.update = function () {
if (!self.alive) return;
self.vy += self.gravity;
if (self.vy > self.maxFall) self.vy = self.maxFall;
self.y += self.vy;
// Rotate chicken based on velocity
var maxAngle = Math.PI / 3;
var minAngle = -Math.PI / 6;
var t = (self.vy + 38) / (self.maxFall + 38);
chickenSprite.rotation = minAngle + (maxAngle - minAngle) * t;
};
// Die
self.die = function () {
self.alive = false;
// Fall fast
self.vy = 18;
// Flash red
LK.effects.flashObject(self, 0xff0000, 400);
};
return self;
});
// PipePair class (top and bottom pipes)
var PipePair = Container.expand(function () {
var self = Container.call(this);
// Top pipe
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1.0
});
var topCap = self.attachAsset('pipecap', {
anchorX: 0.5,
anchorY: 1.0,
y: -topPipe.height
});
// Bottom pipe
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0.0,
y: 0
});
var bottomCap = self.attachAsset('pipecap', {
anchorX: 0.5,
anchorY: 0.0,
y: bottomPipe.height
});
// For collision
self.topPipe = topPipe;
self.bottomPipe = bottomPipe;
// Has the chicken passed this pipe?
self.passed = false;
// Set gap and position
self.setGap = function (gapY, gapHeight) {
// Top pipe: bottom at gapY - gapHeight/2
topPipe.height = Math.max(120, gapY - gapHeight / 2);
topCap.y = -topPipe.height;
// Bottom pipe: top at gapY + gapHeight/2
bottomPipe.y = gapY + gapHeight / 2;
bottomPipe.height = Math.max(120, 2732 - bottomPipe.y - 120);
bottomCap.y = bottomPipe.y + bottomPipe.height;
};
// Move pipes left
self.update = function () {
self.x -= pipeSpeed;
};
// Destroy
self.destroyPair = function () {
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// Sound for hit
// Sound for point
// Sound for flap
// Ground
// Obstacle (pipe cap)
// Obstacle (pipe)
// Chicken (player)
// Game constants
var GROUND_HEIGHT = 120;
var CHICKEN_START_X = 600;
var CHICKEN_START_Y = 1200;
var PIPE_INTERVAL = 1100; // px between pipes
var PIPE_MIN_GAP = 340;
var PIPE_MAX_GAP = 520;
var PIPE_MIN_Y = 420;
var PIPE_MAX_Y = 2732 - GROUND_HEIGHT - 420;
var pipeSpeed = 16;
var pipePairs = [];
var score = 0;
var bestScore = 0;
var gameStarted = false;
var gameOver = false;
var dragNode = null;
var lastPassedPipe = null;
// Score text
var scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFF700
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Best score text (bottom center)
var bestScoreTxt = new Text2('', {
size: 70,
fill: 0xFFFFFF
});
bestScoreTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(bestScoreTxt);
// Ground
var ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - GROUND_HEIGHT
});
game.addChild(ground);
// Chicken
var chicken = new Chicken();
game.addChild(chicken);
chicken.x = CHICKEN_START_X;
chicken.y = CHICKEN_START_Y;
// Helper: reset game state
function resetGame() {
// Remove pipes
for (var i = 0; i < pipePairs.length; i++) {
pipePairs[i].destroyPair();
}
pipePairs = [];
score = 0;
scoreTxt.setText('0');
chicken.x = CHICKEN_START_X;
chicken.y = CHICKEN_START_Y;
chicken.vy = 0;
chicken.alive = true;
chicken.rotation = 0;
gameStarted = false;
gameOver = false;
pipeSpeed = 16;
lastPassedPipe = null;
// Show best score
if (bestScore > 0) {
bestScoreTxt.setText('Best: ' + bestScore);
} else {
bestScoreTxt.setText('');
}
}
// Helper: spawn a new pipe pair
function spawnPipePair() {
// Gap size decreases as score increases
var gapHeight = Math.max(PIPE_MIN_GAP, PIPE_MAX_GAP - score * 8);
// Gap Y position
var gapY = PIPE_MIN_Y + Math.random() * (PIPE_MAX_Y - PIPE_MIN_Y);
var pair = new PipePair();
pair.x = 2048 + 200;
pair.setGap(gapY, gapHeight);
game.addChild(pair);
pipePairs.push(pair);
}
// Helper: check collision between chicken and a pipe
function checkPipeCollision(chicken, pipePair) {
// Chicken bounding circle
var cx = chicken.x;
var cy = chicken.y;
var r = chicken.radius * 0.92;
// Top pipe rect
var tp = pipePair.topPipe;
var tpx = pipePair.x;
var tpy = tp.y + pipePair.y;
var tpw = tp.width;
var tph = tp.height;
// Bottom pipe rect
var bp = pipePair.bottomPipe;
var bpx = pipePair.x;
var bpy = bp.y + pipePair.y;
var bpw = bp.width;
var bph = bp.height;
// Circle-rect collision
function circleRectCollide(cx, cy, r, rx, ry, rw, rh) {
var closestX = Math.max(rx - rw / 2, Math.min(cx, rx + rw / 2));
var closestY = Math.max(ry, Math.min(cy, ry + rh));
var dx = cx - closestX;
var dy = cy - closestY;
return dx * dx + dy * dy < r * r;
}
// Top pipe
if (circleRectCollide(cx, cy, r, tpx, tpy - tph, tpw, tph)) return true;
// Bottom pipe
if (circleRectCollide(cx, cy, r, bpx, bpy, bpw, bph)) return true;
return false;
}
// Helper: check collision with ground or ceiling
function checkGroundCeiling(chicken) {
if (chicken.y + chicken.radius > 2732 - GROUND_HEIGHT) return true;
if (chicken.y - chicken.radius < 0) return true;
return false;
}
// Start game on first tap
function startGame() {
if (gameStarted) return;
resetGame();
gameStarted = true;
// Spawn initial pipes
for (var i = 0; i < 3; i++) {
var pair = new PipePair();
pair.x = 2048 + 600 + i * PIPE_INTERVAL;
var gapHeight = Math.max(PIPE_MIN_GAP, PIPE_MAX_GAP - score * 8);
var gapY = PIPE_MIN_Y + Math.random() * (PIPE_MAX_Y - PIPE_MIN_Y);
pair.setGap(gapY, gapHeight);
game.addChild(pair);
pipePairs.push(pair);
}
}
// Game tap: chicken flaps
game.down = function (x, y, obj) {
if (gameOver) return;
if (!gameStarted) {
startGame();
}
chicken.flap();
dragNode = chicken;
};
// Release: nothing (but required for dragNode)
game.up = function (x, y, obj) {
dragNode = null;
};
// Move: not used for chicken, but required for dragNode
game.move = function (x, y, obj) {
// No drag for chicken, but required for completeness
};
// Main game loop
game.update = function () {
if (!gameStarted) return;
// Chicken update
chicken.update();
// Pipes update
for (var i = pipePairs.length - 1; i >= 0; i--) {
var pair = pipePairs[i];
pair.update();
// Remove pipes off screen
if (pair.x < -300) {
pair.destroyPair();
pipePairs.splice(i, 1);
continue;
}
// Check for passing pipe (score)
if (!pair.passed && pair.x + 110 < chicken.x) {
pair.passed = true;
score += 1;
scoreTxt.setText(score + '');
LK.getSound('point').play();
// Increase speed every 10 points
if (score % 10 === 0) {
pipeSpeed += 1.5;
}
}
}
// Spawn new pipes
if (pipePairs.length === 0 || pipePairs[pipePairs.length - 1].x < 2048 - PIPE_INTERVAL) {
spawnPipePair();
}
// Collision detection
var collided = false;
for (var i = 0; i < pipePairs.length; i++) {
if (checkPipeCollision(chicken, pipePairs[i])) {
collided = true;
break;
}
}
if (checkGroundCeiling(chicken)) {
collided = true;
}
if (collided && chicken.alive) {
chicken.die();
LK.getSound('hit').play();
gameOver = true;
// Update best score
if (score > bestScore) bestScore = score;
// Flash screen
LK.effects.flashScreen(0xff0000, 800);
// Show game over (auto resets)
LK.setTimeout(function () {
LK.showGameOver();
}, 600);
}
};
// On game over, reset state
LK.on('gameover', function () {
resetGame();
});
// On you win (not used, but for completeness)
LK.on('youwin', function () {
resetGame();
});
// Initial state
resetGame(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,353 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Chicken class
+var Chicken = Container.expand(function () {
+ var self = Container.call(this);
+ var chickenSprite = self.attachAsset('chicken', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = chickenSprite.width * 0.5;
+ self.vy = 0;
+ self.gravity = 2.2;
+ self.flapStrength = -38;
+ self.maxFall = 38;
+ self.alive = true;
+ // Flap upward
+ self.flap = function () {
+ if (!self.alive) return;
+ self.vy = self.flapStrength;
+ LK.getSound('flap').play();
+ // Animate chicken (slight scale for feedback)
+ tween.stop(self, {
+ scaleY: true
+ });
+ self.scaleY = 1.0;
+ tween(self, {
+ scaleY: 0.8
+ }, {
+ duration: 80,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleY: 1.0
+ }, {
+ duration: 120,
+ easing: tween.cubicIn
+ });
+ }
+ });
+ };
+ // Update position
+ self.update = function () {
+ if (!self.alive) return;
+ self.vy += self.gravity;
+ if (self.vy > self.maxFall) self.vy = self.maxFall;
+ self.y += self.vy;
+ // Rotate chicken based on velocity
+ var maxAngle = Math.PI / 3;
+ var minAngle = -Math.PI / 6;
+ var t = (self.vy + 38) / (self.maxFall + 38);
+ chickenSprite.rotation = minAngle + (maxAngle - minAngle) * t;
+ };
+ // Die
+ self.die = function () {
+ self.alive = false;
+ // Fall fast
+ self.vy = 18;
+ // Flash red
+ LK.effects.flashObject(self, 0xff0000, 400);
+ };
+ return self;
+});
+// PipePair class (top and bottom pipes)
+var PipePair = Container.expand(function () {
+ var self = Container.call(this);
+ // Top pipe
+ var topPipe = self.attachAsset('pipe', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ var topCap = self.attachAsset('pipecap', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ y: -topPipe.height
+ });
+ // Bottom pipe
+ var bottomPipe = self.attachAsset('pipe', {
+ anchorX: 0.5,
+ anchorY: 0.0,
+ y: 0
+ });
+ var bottomCap = self.attachAsset('pipecap', {
+ anchorX: 0.5,
+ anchorY: 0.0,
+ y: bottomPipe.height
+ });
+ // For collision
+ self.topPipe = topPipe;
+ self.bottomPipe = bottomPipe;
+ // Has the chicken passed this pipe?
+ self.passed = false;
+ // Set gap and position
+ self.setGap = function (gapY, gapHeight) {
+ // Top pipe: bottom at gapY - gapHeight/2
+ topPipe.height = Math.max(120, gapY - gapHeight / 2);
+ topCap.y = -topPipe.height;
+ // Bottom pipe: top at gapY + gapHeight/2
+ bottomPipe.y = gapY + gapHeight / 2;
+ bottomPipe.height = Math.max(120, 2732 - bottomPipe.y - 120);
+ bottomCap.y = bottomPipe.y + bottomPipe.height;
+ };
+ // Move pipes left
+ self.update = function () {
+ self.x -= pipeSpeed;
+ };
+ // Destroy
+ self.destroyPair = function () {
+ self.destroy();
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87ceeb // Sky blue
+});
+
+/****
+* Game Code
+****/
+// Sound for hit
+// Sound for point
+// Sound for flap
+// Ground
+// Obstacle (pipe cap)
+// Obstacle (pipe)
+// Chicken (player)
+// Game constants
+var GROUND_HEIGHT = 120;
+var CHICKEN_START_X = 600;
+var CHICKEN_START_Y = 1200;
+var PIPE_INTERVAL = 1100; // px between pipes
+var PIPE_MIN_GAP = 340;
+var PIPE_MAX_GAP = 520;
+var PIPE_MIN_Y = 420;
+var PIPE_MAX_Y = 2732 - GROUND_HEIGHT - 420;
+var pipeSpeed = 16;
+var pipePairs = [];
+var score = 0;
+var bestScore = 0;
+var gameStarted = false;
+var gameOver = false;
+var dragNode = null;
+var lastPassedPipe = null;
+// Score text
+var scoreTxt = new Text2('0', {
+ size: 180,
+ fill: 0xFFF700
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Best score text (bottom center)
+var bestScoreTxt = new Text2('', {
+ size: 70,
+ fill: 0xFFFFFF
+});
+bestScoreTxt.anchor.set(0.5, 1);
+LK.gui.bottom.addChild(bestScoreTxt);
+// Ground
+var ground = LK.getAsset('ground', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 2732 - GROUND_HEIGHT
+});
+game.addChild(ground);
+// Chicken
+var chicken = new Chicken();
+game.addChild(chicken);
+chicken.x = CHICKEN_START_X;
+chicken.y = CHICKEN_START_Y;
+// Helper: reset game state
+function resetGame() {
+ // Remove pipes
+ for (var i = 0; i < pipePairs.length; i++) {
+ pipePairs[i].destroyPair();
+ }
+ pipePairs = [];
+ score = 0;
+ scoreTxt.setText('0');
+ chicken.x = CHICKEN_START_X;
+ chicken.y = CHICKEN_START_Y;
+ chicken.vy = 0;
+ chicken.alive = true;
+ chicken.rotation = 0;
+ gameStarted = false;
+ gameOver = false;
+ pipeSpeed = 16;
+ lastPassedPipe = null;
+ // Show best score
+ if (bestScore > 0) {
+ bestScoreTxt.setText('Best: ' + bestScore);
+ } else {
+ bestScoreTxt.setText('');
+ }
+}
+// Helper: spawn a new pipe pair
+function spawnPipePair() {
+ // Gap size decreases as score increases
+ var gapHeight = Math.max(PIPE_MIN_GAP, PIPE_MAX_GAP - score * 8);
+ // Gap Y position
+ var gapY = PIPE_MIN_Y + Math.random() * (PIPE_MAX_Y - PIPE_MIN_Y);
+ var pair = new PipePair();
+ pair.x = 2048 + 200;
+ pair.setGap(gapY, gapHeight);
+ game.addChild(pair);
+ pipePairs.push(pair);
+}
+// Helper: check collision between chicken and a pipe
+function checkPipeCollision(chicken, pipePair) {
+ // Chicken bounding circle
+ var cx = chicken.x;
+ var cy = chicken.y;
+ var r = chicken.radius * 0.92;
+ // Top pipe rect
+ var tp = pipePair.topPipe;
+ var tpx = pipePair.x;
+ var tpy = tp.y + pipePair.y;
+ var tpw = tp.width;
+ var tph = tp.height;
+ // Bottom pipe rect
+ var bp = pipePair.bottomPipe;
+ var bpx = pipePair.x;
+ var bpy = bp.y + pipePair.y;
+ var bpw = bp.width;
+ var bph = bp.height;
+ // Circle-rect collision
+ function circleRectCollide(cx, cy, r, rx, ry, rw, rh) {
+ var closestX = Math.max(rx - rw / 2, Math.min(cx, rx + rw / 2));
+ var closestY = Math.max(ry, Math.min(cy, ry + rh));
+ var dx = cx - closestX;
+ var dy = cy - closestY;
+ return dx * dx + dy * dy < r * r;
+ }
+ // Top pipe
+ if (circleRectCollide(cx, cy, r, tpx, tpy - tph, tpw, tph)) return true;
+ // Bottom pipe
+ if (circleRectCollide(cx, cy, r, bpx, bpy, bpw, bph)) return true;
+ return false;
+}
+// Helper: check collision with ground or ceiling
+function checkGroundCeiling(chicken) {
+ if (chicken.y + chicken.radius > 2732 - GROUND_HEIGHT) return true;
+ if (chicken.y - chicken.radius < 0) return true;
+ return false;
+}
+// Start game on first tap
+function startGame() {
+ if (gameStarted) return;
+ resetGame();
+ gameStarted = true;
+ // Spawn initial pipes
+ for (var i = 0; i < 3; i++) {
+ var pair = new PipePair();
+ pair.x = 2048 + 600 + i * PIPE_INTERVAL;
+ var gapHeight = Math.max(PIPE_MIN_GAP, PIPE_MAX_GAP - score * 8);
+ var gapY = PIPE_MIN_Y + Math.random() * (PIPE_MAX_Y - PIPE_MIN_Y);
+ pair.setGap(gapY, gapHeight);
+ game.addChild(pair);
+ pipePairs.push(pair);
+ }
+}
+// Game tap: chicken flaps
+game.down = function (x, y, obj) {
+ if (gameOver) return;
+ if (!gameStarted) {
+ startGame();
+ }
+ chicken.flap();
+ dragNode = chicken;
+};
+// Release: nothing (but required for dragNode)
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Move: not used for chicken, but required for dragNode
+game.move = function (x, y, obj) {
+ // No drag for chicken, but required for completeness
+};
+// Main game loop
+game.update = function () {
+ if (!gameStarted) return;
+ // Chicken update
+ chicken.update();
+ // Pipes update
+ for (var i = pipePairs.length - 1; i >= 0; i--) {
+ var pair = pipePairs[i];
+ pair.update();
+ // Remove pipes off screen
+ if (pair.x < -300) {
+ pair.destroyPair();
+ pipePairs.splice(i, 1);
+ continue;
+ }
+ // Check for passing pipe (score)
+ if (!pair.passed && pair.x + 110 < chicken.x) {
+ pair.passed = true;
+ score += 1;
+ scoreTxt.setText(score + '');
+ LK.getSound('point').play();
+ // Increase speed every 10 points
+ if (score % 10 === 0) {
+ pipeSpeed += 1.5;
+ }
+ }
+ }
+ // Spawn new pipes
+ if (pipePairs.length === 0 || pipePairs[pipePairs.length - 1].x < 2048 - PIPE_INTERVAL) {
+ spawnPipePair();
+ }
+ // Collision detection
+ var collided = false;
+ for (var i = 0; i < pipePairs.length; i++) {
+ if (checkPipeCollision(chicken, pipePairs[i])) {
+ collided = true;
+ break;
+ }
+ }
+ if (checkGroundCeiling(chicken)) {
+ collided = true;
+ }
+ if (collided && chicken.alive) {
+ chicken.die();
+ LK.getSound('hit').play();
+ gameOver = true;
+ // Update best score
+ if (score > bestScore) bestScore = score;
+ // Flash screen
+ LK.effects.flashScreen(0xff0000, 800);
+ // Show game over (auto resets)
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 600);
+ }
+};
+// On game over, reset state
+LK.on('gameover', function () {
+ resetGame();
+});
+// On you win (not used, but for completeness)
+LK.on('youwin', function () {
+ resetGame();
+});
+// Initial state
+resetGame();
\ No newline at end of file