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 = -19;
// 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;
});
// Gold: collectible coin between pipes
var Gold = Container.expand(function () {
var self = Container.call(this);
var _gold = self.attachAsset('gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
self.x += self.speed;
};
// For collision detection
self.getBounds = function () {
return {
x: self.x - _gold.width / 2,
y: self.y - _gold.height / 2,
width: _gold.width,
height: _gold.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_top', {
anchorX: 0,
anchorY: 1
});
// Bottom pipe
var bottomPipe = self.attachAsset('pipe_bottom', {
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
****/
// Background landscape and clouds
// Game constants
// Pipes: green boxes, character: yellow ellipse, background: blue
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PIPE_WIDTH = 220;
var PIPE_GAP_MIN = 480;
var PIPE_GAP_MAX = 700;
var PIPE_DISTANCE = 900; // Horizontal distance between pipes
var PIPE_SPEED_START = -7; // Slower initial pipe speed
var PIPE_SPEED_MAX = -28;
var PIPE_FREQ_START = 120; // Pipes appear less frequently at start
var PIPE_FREQ_MIN = 45;
var GRAVITY_START = 1.05; // Slightly lower gravity for even gentler fall
var FLAP_STRENGTH = -22;
// Game variables
var pipes = [];
var golds = [];
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 background landscape (two for seamless looping)
var bgLandscape = LK.getAsset('bg_landscape', {
anchorX: 0,
anchorY: 1,
x: 0,
y: GAME_HEIGHT,
width: GAME_WIDTH,
height: 600
});
var bgLandscape2 = LK.getAsset('bg_landscape', {
anchorX: 0,
anchorY: 1,
x: GAME_WIDTH,
y: GAME_HEIGHT,
width: GAME_WIDTH,
height: 600
});
game.addChild(bgLandscape);
game.addChild(bgLandscape2);
// Add clouds (3 clouds at different positions and scales)
var clouds = [];
for (var i = 0; i < 3; i++) {
var cloud = LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
x: 400 + i * 600,
y: 300 + i * 120,
scaleX: 0.8 + 0.3 * Math.random(),
scaleY: 0.8 + 0.3 * Math.random()
});
game.addChild(cloud);
clouds.push(cloud);
}
// 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);
}
// Remove golds
for (var i = golds.length - 1; i >= 0; i--) {
golds[i].destroy();
golds.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; // Use new slower frequency
pipeSpeed = PIPE_SPEED_START; // Use new slower speed
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;
// Animate clouds (move right to left, loop)
for (var i = 0; i < clouds.length; i++) {
var cloud = clouds[i];
cloud.x -= 0.7 + 0.2 * i;
if (cloud.x < -cloud.width / 2) {
cloud.x = GAME_WIDTH + cloud.width / 2 + Math.random() * 200;
cloud.y = 200 + Math.random() * 400 + i * 100;
}
}
// Animate background landscape to move leftward and loop
bgLandscape.x -= Math.abs(pipeSpeed) * 0.5;
bgLandscape2.x -= Math.abs(pipeSpeed) * 0.5;
// Loop both backgrounds for seamless scrolling
if (bgLandscape.x <= -GAME_WIDTH) {
bgLandscape.x = bgLandscape2.x + GAME_WIDTH;
}
if (bgLandscape2.x <= -GAME_WIDTH) {
bgLandscape2.x = bgLandscape.x + GAME_WIDTH;
}
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;
}
}
// Golds movement and collection
for (var i = golds.length - 1; i >= 0; i--) {
var gold = golds[i];
gold.update();
// Remove gold if off screen
if (gold.x + 50 < 0) {
gold.destroy();
golds.splice(i, 1);
continue;
}
// Collision with character
if (!gold.collected && rectsIntersect(character.getBounds(), gold.getBounds())) {
gold.collected = true;
gold.destroy();
golds.splice(i, 1);
score += 3;
scoreTxt.setText(score);
// Optionally: add a flash or effect here
}
}
// 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);
// Spawn gold in the center of the gap
var gold = new Gold();
gold.x = GAME_WIDTH + PIPE_WIDTH / 2;
gold.y = gapY + gapHeight / 2;
gold.speed = pipeSpeed;
golds.push(gold);
game.addChild(gold);
}
// 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
@@ -36,8 +36,30 @@
};
};
return self;
});
+// Gold: collectible coin between pipes
+var Gold = Container.expand(function () {
+ var self = Container.call(this);
+ var _gold = self.attachAsset('gold', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.collected = false;
+ self.update = function () {
+ self.x += self.speed;
+ };
+ // For collision detection
+ self.getBounds = function () {
+ return {
+ x: self.x - _gold.width / 2,
+ y: self.y - _gold.height / 2,
+ width: _gold.width,
+ height: _gold.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
@@ -107,8 +129,9 @@
var GRAVITY_START = 1.05; // Slightly lower gravity for even gentler fall
var FLAP_STRENGTH = -22;
// Game variables
var pipes = [];
+var golds = [];
var character;
var score = 0;
var scoreTxt;
var lastPipeTick = 0;
@@ -172,8 +195,13 @@
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].destroy();
pipes.splice(i, 1);
}
+ // Remove golds
+ for (var i = golds.length - 1; i >= 0; i--) {
+ golds[i].destroy();
+ golds.splice(i, 1);
+ }
// Reset character
character.x = GAME_WIDTH * 0.35;
character.y = GAME_HEIGHT / 2;
character.velocity = 0;
@@ -306,8 +334,28 @@
}
character.gravity += 0.02;
}
}
+ // Golds movement and collection
+ for (var i = golds.length - 1; i >= 0; i--) {
+ var gold = golds[i];
+ gold.update();
+ // Remove gold if off screen
+ if (gold.x + 50 < 0) {
+ gold.destroy();
+ golds.splice(i, 1);
+ continue;
+ }
+ // Collision with character
+ if (!gold.collected && rectsIntersect(character.getBounds(), gold.getBounds())) {
+ gold.collected = true;
+ gold.destroy();
+ golds.splice(i, 1);
+ score += 3;
+ scoreTxt.setText(score);
+ // Optionally: add a flash or effect here
+ }
+ }
// Pipe spawning
if (LK.ticks - lastPipeTick >= pipeFreq) {
spawnPipePair();
lastPipeTick = LK.ticks;
@@ -330,8 +378,15 @@
pipePair.speed = pipeSpeed;
pipePair.passed = false;
pipes.push(pipePair);
game.addChild(pipePair);
+ // Spawn gold in the center of the gap
+ var gold = new Gold();
+ gold.x = GAME_WIDTH + PIPE_WIDTH / 2;
+ gold.y = gapY + gapHeight / 2;
+ gold.speed = pipeSpeed;
+ golds.push(gold);
+ game.addChild(gold);
}
// Game over logic
function triggerGameOver() {
if (gameOver) return;
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