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