User prompt
animate gold
User prompt
make gold move a little bit right
User prompt
gold coin is not in the center of the gap
User prompt
add gold between gaps so that player can collect them
User prompt
landscape should also move as we move towards
User prompt
increase the gap between the pipes a little
User prompt
add background landscape and some clouds
User prompt
let's do it
User prompt
make top pipe upside down
User prompt
make to pipe flip horizontally
User prompt
make top pipe flip vertically
User prompt
pipes should be on the same vertical axis
User prompt
but rotated pipes should be stick to the top side of the screen
User prompt
pipes on the top side of the screen should be rotated 180 degrees
User prompt
decrease the gravitiy a little
User prompt
increase the bounce effect a little
User prompt
decrease the bounce effect by half
User prompt
slow down the starting pace, and decrease the gravity force
Code edit (1 edits merged)
Please save this source code
User prompt
Flappy Gap
User prompt
Note that, there shouldn't be any gap between the top pipe and the top screen, there shouldn't be any gap between the bottom pipe and the bottom screen. Player can only move towards the gap between the pipes
Initial prompt
make a flapy bird like game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Character: the player-controlled ellipse var Character = Container.expand(function () { var self = Container.call(this); var _char = self.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }); // Physics self.velocity = 0; self.gravity = 2.2; self.flapStrength = -38; // Flap (jump) self.flap = function () { self.velocity = self.flapStrength; }; // Update position and velocity self.update = function () { self.velocity += self.gravity; self.y += self.velocity; }; // For collision detection self.getBounds = function () { return { x: self.x - _char.width / 2, y: self.y - _char.height / 2, width: _char.width, height: _char.height }; }; return self; }); // PipePair: a pair of pipes (top and bottom) with a gap var PipePair = Container.expand(function () { var self = Container.call(this); // Pipe dimensions var pipeWidth = 220; var pipeHeight = 1200; var gapHeight = 500; // Will be set dynamically // Top pipe var topPipe = self.attachAsset('pipe', { anchorX: 0, anchorY: 1 }); // Bottom pipe var bottomPipe = self.attachAsset('pipe', { anchorX: 0, anchorY: 0 }); // Set pipes' positions based on gapY and gapHeight self.setGap = function (gapY, gapHeight) { // Top pipe: bottom at gapY topPipe.x = 0; topPipe.y = gapY; topPipe.height = gapY; // Bottom pipe: top at gapY+gapHeight bottomPipe.x = 0; bottomPipe.y = gapY + gapHeight; bottomPipe.height = 2732 - (gapY + gapHeight); }; // For collision detection self.getTopPipe = function () { return topPipe; }; self.getBottomPipe = function () { return bottomPipe; }; // Move pipes leftward self.update = function () { self.x += self.speed; }; // Set initial speed self.speed = -12; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4db8ff // Light blue sky }); /**** * Game Code ****/ // Pipes: green boxes, character: yellow ellipse, background: blue // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var PIPE_WIDTH = 220; var PIPE_GAP_MIN = 380; var PIPE_GAP_MAX = 600; var PIPE_DISTANCE = 900; // Horizontal distance between pipes var PIPE_SPEED_START = -12; var PIPE_SPEED_MAX = -28; var PIPE_FREQ_START = 90; // Ticks between pipes var PIPE_FREQ_MIN = 45; var GRAVITY_START = 2.2; var FLAP_STRENGTH = -38; // Game variables var pipes = []; var character; var score = 0; var scoreTxt; var lastPipeTick = 0; var pipeFreq = PIPE_FREQ_START; var pipeSpeed = PIPE_SPEED_START; var gameStarted = false; var gameOver = false; // Add score text to GUI scoreTxt = new Text2('0', { size: 150, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Center score text horizontally, avoid top left 100x100 scoreTxt.x = LK.gui.top.width / 2; scoreTxt.y = 40; // Create character and position character = new Character(); game.addChild(character); character.x = GAME_WIDTH * 0.35; character.y = GAME_HEIGHT / 2; character.gravity = GRAVITY_START; character.flapStrength = FLAP_STRENGTH; // Reset game state function resetGame() { // Remove pipes for (var i = pipes.length - 1; i >= 0; i--) { pipes[i].destroy(); pipes.splice(i, 1); } // Reset character character.x = GAME_WIDTH * 0.35; character.y = GAME_HEIGHT / 2; character.velocity = 0; character.gravity = GRAVITY_START; character.flapStrength = FLAP_STRENGTH; // Reset variables score = 0; scoreTxt.setText(score); lastPipeTick = 0; pipeFreq = PIPE_FREQ_START; pipeSpeed = PIPE_SPEED_START; gameStarted = false; gameOver = false; } // Start game on first tap function startGame() { if (!gameStarted && !gameOver) { gameStarted = true; character.flap(); } } // Flap on tap/click game.down = function (x, y, obj) { if (gameOver) return; if (!gameStarted) { startGame(); } else { character.flap(); } }; // Main update loop game.update = function () { if (gameOver) return; if (!gameStarted) { // Idle animation: bob up and down character.y = GAME_HEIGHT / 2 + Math.sin(LK.ticks / 30) * 30; return; } // Character physics character.update(); // Clamp character to screen if (character.y < character.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }).height / 2) { character.y = character.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }).height / 2; character.velocity = 0; } if (character.y > GAME_HEIGHT - character.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }).height / 2) { character.y = GAME_HEIGHT - character.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }).height / 2; character.velocity = 0; triggerGameOver(); return; } // Pipes movement and collision for (var i = pipes.length - 1; i >= 0; i--) { var pipePair = pipes[i]; pipePair.update(); // Remove pipes off screen if (pipePair.x + PIPE_WIDTH < 0) { pipePair.destroy(); pipes.splice(i, 1); continue; } // Collision detection var charBounds = character.getBounds(); var topPipe = pipePair.getTopPipe(); var bottomPipe = pipePair.getBottomPipe(); // Top pipe collision if (rectsIntersect(charBounds, { x: pipePair.x, y: 0, width: PIPE_WIDTH, height: topPipe.height })) { triggerGameOver(); return; } // Bottom pipe collision if (rectsIntersect(charBounds, { x: pipePair.x, y: bottomPipe.y, width: PIPE_WIDTH, height: bottomPipe.height })) { triggerGameOver(); return; } // Score: when character passes the pipe (center) if (!pipePair.passed && pipePair.x + PIPE_WIDTH / 2 < character.x) { pipePair.passed = true; score += 1; scoreTxt.setText(score); // Increase difficulty if (pipeFreq > PIPE_FREQ_MIN) { pipeFreq -= 2; if (pipeFreq < PIPE_FREQ_MIN) pipeFreq = PIPE_FREQ_MIN; } if (pipeSpeed > PIPE_SPEED_MAX) { pipeSpeed -= 0.5; if (pipeSpeed < PIPE_SPEED_MAX) pipeSpeed = PIPE_SPEED_MAX; } character.gravity += 0.02; } } // Pipe spawning if (LK.ticks - lastPipeTick >= pipeFreq) { spawnPipePair(); lastPipeTick = LK.ticks; } }; // Rectangle intersection helper function rectsIntersect(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; } // Spawn a new pipe pair function spawnPipePair() { var gapHeight = PIPE_GAP_MIN + Math.floor(Math.random() * (PIPE_GAP_MAX - PIPE_GAP_MIN + 1)); var minGapY = 180; var maxGapY = GAME_HEIGHT - gapHeight - 180; var gapY = minGapY + Math.floor(Math.random() * (maxGapY - minGapY + 1)); var pipePair = new PipePair(); pipePair.x = GAME_WIDTH; pipePair.y = 0; pipePair.setGap(gapY, gapHeight); pipePair.speed = pipeSpeed; pipePair.passed = false; pipes.push(pipePair); game.addChild(pipePair); } // Game over logic function triggerGameOver() { if (gameOver) return; gameOver = true; LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } // Reset game on game over LK.on('gameover', function () { resetGame(); }); // Initial game state resetGame();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,294 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Character: the player-controlled ellipse
+var Character = Container.expand(function () {
+ var self = Container.call(this);
+ var _char = self.attachAsset('character', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Physics
+ self.velocity = 0;
+ self.gravity = 2.2;
+ self.flapStrength = -38;
+ // Flap (jump)
+ self.flap = function () {
+ self.velocity = self.flapStrength;
+ };
+ // Update position and velocity
+ self.update = function () {
+ self.velocity += self.gravity;
+ self.y += self.velocity;
+ };
+ // For collision detection
+ self.getBounds = function () {
+ return {
+ x: self.x - _char.width / 2,
+ y: self.y - _char.height / 2,
+ width: _char.width,
+ height: _char.height
+ };
+ };
+ return self;
+});
+// PipePair: a pair of pipes (top and bottom) with a gap
+var PipePair = Container.expand(function () {
+ var self = Container.call(this);
+ // Pipe dimensions
+ var pipeWidth = 220;
+ var pipeHeight = 1200;
+ var gapHeight = 500; // Will be set dynamically
+ // Top pipe
+ var topPipe = self.attachAsset('pipe', {
+ anchorX: 0,
+ anchorY: 1
+ });
+ // Bottom pipe
+ var bottomPipe = self.attachAsset('pipe', {
+ anchorX: 0,
+ anchorY: 0
+ });
+ // Set pipes' positions based on gapY and gapHeight
+ self.setGap = function (gapY, gapHeight) {
+ // Top pipe: bottom at gapY
+ topPipe.x = 0;
+ topPipe.y = gapY;
+ topPipe.height = gapY;
+ // Bottom pipe: top at gapY+gapHeight
+ bottomPipe.x = 0;
+ bottomPipe.y = gapY + gapHeight;
+ bottomPipe.height = 2732 - (gapY + gapHeight);
+ };
+ // For collision detection
+ self.getTopPipe = function () {
+ return topPipe;
+ };
+ self.getBottomPipe = function () {
+ return bottomPipe;
+ };
+ // Move pipes leftward
+ self.update = function () {
+ self.x += self.speed;
+ };
+ // Set initial speed
+ self.speed = -12;
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x4db8ff // Light blue sky
+});
+
+/****
+* Game Code
+****/
+// Pipes: green boxes, character: yellow ellipse, background: blue
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var PIPE_WIDTH = 220;
+var PIPE_GAP_MIN = 380;
+var PIPE_GAP_MAX = 600;
+var PIPE_DISTANCE = 900; // Horizontal distance between pipes
+var PIPE_SPEED_START = -12;
+var PIPE_SPEED_MAX = -28;
+var PIPE_FREQ_START = 90; // Ticks between pipes
+var PIPE_FREQ_MIN = 45;
+var GRAVITY_START = 2.2;
+var FLAP_STRENGTH = -38;
+// Game variables
+var pipes = [];
+var character;
+var score = 0;
+var scoreTxt;
+var lastPipeTick = 0;
+var pipeFreq = PIPE_FREQ_START;
+var pipeSpeed = PIPE_SPEED_START;
+var gameStarted = false;
+var gameOver = false;
+// Add score text to GUI
+scoreTxt = new Text2('0', {
+ size: 150,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Center score text horizontally, avoid top left 100x100
+scoreTxt.x = LK.gui.top.width / 2;
+scoreTxt.y = 40;
+// Create character and position
+character = new Character();
+game.addChild(character);
+character.x = GAME_WIDTH * 0.35;
+character.y = GAME_HEIGHT / 2;
+character.gravity = GRAVITY_START;
+character.flapStrength = FLAP_STRENGTH;
+// Reset game state
+function resetGame() {
+ // Remove pipes
+ for (var i = pipes.length - 1; i >= 0; i--) {
+ pipes[i].destroy();
+ pipes.splice(i, 1);
+ }
+ // Reset character
+ character.x = GAME_WIDTH * 0.35;
+ character.y = GAME_HEIGHT / 2;
+ character.velocity = 0;
+ character.gravity = GRAVITY_START;
+ character.flapStrength = FLAP_STRENGTH;
+ // Reset variables
+ score = 0;
+ scoreTxt.setText(score);
+ lastPipeTick = 0;
+ pipeFreq = PIPE_FREQ_START;
+ pipeSpeed = PIPE_SPEED_START;
+ gameStarted = false;
+ gameOver = false;
+}
+// Start game on first tap
+function startGame() {
+ if (!gameStarted && !gameOver) {
+ gameStarted = true;
+ character.flap();
+ }
+}
+// Flap on tap/click
+game.down = function (x, y, obj) {
+ if (gameOver) return;
+ if (!gameStarted) {
+ startGame();
+ } else {
+ character.flap();
+ }
+};
+// Main update loop
+game.update = function () {
+ if (gameOver) return;
+ if (!gameStarted) {
+ // Idle animation: bob up and down
+ character.y = GAME_HEIGHT / 2 + Math.sin(LK.ticks / 30) * 30;
+ return;
+ }
+ // Character physics
+ character.update();
+ // Clamp character to screen
+ if (character.y < character.attachAsset('character', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).height / 2) {
+ character.y = character.attachAsset('character', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).height / 2;
+ character.velocity = 0;
+ }
+ if (character.y > GAME_HEIGHT - character.attachAsset('character', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).height / 2) {
+ character.y = GAME_HEIGHT - character.attachAsset('character', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }).height / 2;
+ character.velocity = 0;
+ triggerGameOver();
+ return;
+ }
+ // Pipes movement and collision
+ for (var i = pipes.length - 1; i >= 0; i--) {
+ var pipePair = pipes[i];
+ pipePair.update();
+ // Remove pipes off screen
+ if (pipePair.x + PIPE_WIDTH < 0) {
+ pipePair.destroy();
+ pipes.splice(i, 1);
+ continue;
+ }
+ // Collision detection
+ var charBounds = character.getBounds();
+ var topPipe = pipePair.getTopPipe();
+ var bottomPipe = pipePair.getBottomPipe();
+ // Top pipe collision
+ if (rectsIntersect(charBounds, {
+ x: pipePair.x,
+ y: 0,
+ width: PIPE_WIDTH,
+ height: topPipe.height
+ })) {
+ triggerGameOver();
+ return;
+ }
+ // Bottom pipe collision
+ if (rectsIntersect(charBounds, {
+ x: pipePair.x,
+ y: bottomPipe.y,
+ width: PIPE_WIDTH,
+ height: bottomPipe.height
+ })) {
+ triggerGameOver();
+ return;
+ }
+ // Score: when character passes the pipe (center)
+ if (!pipePair.passed && pipePair.x + PIPE_WIDTH / 2 < character.x) {
+ pipePair.passed = true;
+ score += 1;
+ scoreTxt.setText(score);
+ // Increase difficulty
+ if (pipeFreq > PIPE_FREQ_MIN) {
+ pipeFreq -= 2;
+ if (pipeFreq < PIPE_FREQ_MIN) pipeFreq = PIPE_FREQ_MIN;
+ }
+ if (pipeSpeed > PIPE_SPEED_MAX) {
+ pipeSpeed -= 0.5;
+ if (pipeSpeed < PIPE_SPEED_MAX) pipeSpeed = PIPE_SPEED_MAX;
+ }
+ character.gravity += 0.02;
+ }
+ }
+ // Pipe spawning
+ if (LK.ticks - lastPipeTick >= pipeFreq) {
+ spawnPipePair();
+ lastPipeTick = LK.ticks;
+ }
+};
+// Rectangle intersection helper
+function rectsIntersect(a, b) {
+ return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
+}
+// Spawn a new pipe pair
+function spawnPipePair() {
+ var gapHeight = PIPE_GAP_MIN + Math.floor(Math.random() * (PIPE_GAP_MAX - PIPE_GAP_MIN + 1));
+ var minGapY = 180;
+ var maxGapY = GAME_HEIGHT - gapHeight - 180;
+ var gapY = minGapY + Math.floor(Math.random() * (maxGapY - minGapY + 1));
+ var pipePair = new PipePair();
+ pipePair.x = GAME_WIDTH;
+ pipePair.y = 0;
+ pipePair.setGap(gapY, gapHeight);
+ pipePair.speed = pipeSpeed;
+ pipePair.passed = false;
+ pipes.push(pipePair);
+ game.addChild(pipePair);
+}
+// Game over logic
+function triggerGameOver() {
+ if (gameOver) return;
+ gameOver = true;
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+}
+// Reset game on game over
+LK.on('gameover', function () {
+ resetGame();
+});
+// Initial game state
+resetGame();
\ No newline at end of file
give me some alternatives of real flappy bird. In-Game asset. 2d. High contrast. No shadows. Just one image
flappy bird cloud, pixel art. In-Game asset. 2d. High contrast. No shadows
flappy bird ground. In-Game asset. 2d. High contrast. No shadows. pixel art. suitable for looping
flappy bird gold icon. pixel art style. In-Game asset. 2d. High contrast. No shadows
flappy bird power up icon. pixel art style. In-Game asset. 2d. High contrast. No shadows
Restyled