/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bird class
var Bird = Container.expand(function () {
var self = Container.call(this);
// Attach a yellow ellipse as the bird
var birdAsset = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Bird physics
self.velocityY = 0;
self.gravity = 1.2; // Gravity per frame
self.flapStrength = -28; // Negative for upward movement
// Bird size for collision
self.radius = birdAsset.width * 0.45;
// Flap method
self.flap = function () {
self.velocityY = self.flapStrength;
// Animate a quick upward tilt
tween(self, {
rotation: -0.3
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
// Return to downward tilt
tween(self, {
rotation: 0.4
}, {
duration: 300,
easing: tween.cubicIn
});
}
});
};
// Update method
self.update = function () {
self.velocityY += self.gravity;
self.y += self.velocityY;
// Clamp rotation based on velocity
if (self.velocityY > 0) {
self.rotation = 0.4;
} else if (self.velocityY < 0) {
self.rotation = -0.3;
}
};
return self;
});
// PipePair class (top and bottom pipes)
var PipePair = Container.expand(function () {
var self = Container.call(this);
// Pipe config
self.pipeWidth = 220;
self.gapHeight = 520;
self.speed = 12;
// Randomize gap position
var minGapY = 400;
var maxGapY = 2732 - 400 - self.gapHeight;
self.gapY = minGapY + Math.floor(Math.random() * (maxGapY - minGapY));
// Top pipe
var topPipe = self.attachAsset('pipe', {
anchorX: 0,
anchorY: 1,
width: self.pipeWidth,
height: self.gapY,
color: 0x3bb54a,
shape: 'box',
x: 0,
y: self.gapY
});
// Bottom pipe
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0,
anchorY: 0,
width: self.pipeWidth,
height: 2732 - (self.gapY + self.gapHeight),
color: 0x3bb54a,
shape: 'box',
x: 0,
y: self.gapY + self.gapHeight
});
// For collision
self.topPipe = topPipe;
self.bottomPipe = bottomPipe;
// Scoring flag
self.passed = false;
// Update method
self.update = function () {
self.x -= self.speed;
};
// Collision check with bird
self.collidesWith = function (bird) {
// Bird bounding box
var bx = bird.x;
var by = bird.y;
var br = bird.radius;
// Top pipe rect
var tx = self.x;
var ty = 0;
var tw = self.pipeWidth;
var th = self.gapY;
// Bottom pipe rect
var bx2 = self.x;
var by2 = self.gapY + self.gapHeight;
var bw2 = self.pipeWidth;
var bh2 = 2732 - by2;
// Circle-rectangle collision
function circleRectCollide(cx, cy, cr, rx, ry, rw, rh) {
var closestX = Math.max(rx, Math.min(cx, rx + rw));
var closestY = Math.max(ry, Math.min(cy, ry + rh));
var dx = cx - closestX;
var dy = cy - closestY;
return dx * dx + dy * dy < cr * cr;
}
if (circleRectCollide(bx, by, br, tx, ty, tw, th)) return true;
if (circleRectCollide(bx, by, br, bx2, by2, bw2, bh2)) return true;
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue
});
/****
* Game Code
****/
// Game constants
var BIRD_START_X = 600;
var BIRD_START_Y = 1200;
var PIPE_INTERVAL = 90; // Frames between pipes
var GROUND_HEIGHT = 180;
// Create bird asset (ellipse)
// Create pipe asset (box)
// Ground asset (for collision)
// Score text
var scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Bird instance
var bird = new Bird();
game.addChild(bird);
bird.x = BIRD_START_X;
bird.y = BIRD_START_Y;
// Ground instance
var ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - GROUND_HEIGHT
});
game.addChild(ground);
// Pipes array
var pipes = [];
// Game state
var gameStarted = false;
var gameOver = false;
var frameCount = 0;
// For tap/flap
game.down = function (x, y, obj) {
if (gameOver) return;
if (!gameStarted) {
gameStarted = true;
}
bird.flap();
};
// Main update loop
game.update = function () {
if (gameOver) return;
if (gameStarted) {
bird.update();
// Add new pipes
if (frameCount % PIPE_INTERVAL === 0) {
var pipePair = new PipePair();
pipePair.x = 2048;
game.addChild(pipePair);
pipes.push(pipePair);
}
// Update pipes and check for collisions
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
pipe.update();
// Collision
if (pipe.collidesWith(bird)) {
endGame();
return;
}
// Score: when bird passes the pipe
if (!pipe.passed && pipe.x + pipe.pipeWidth < bird.x) {
pipe.passed = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
}
// Remove off-screen pipes
if (pipe.x + pipe.pipeWidth < 0) {
pipe.destroy();
pipes.splice(i, 1);
}
}
// Ground collision
if (bird.y + bird.radius > 2732 - GROUND_HEIGHT) {
bird.y = 2732 - GROUND_HEIGHT - bird.radius;
endGame();
return;
}
// Ceiling clamp
if (bird.y - bird.radius < 0) {
bird.y = bird.radius;
bird.velocityY = 0;
}
frameCount++;
} else {
// Idle bird bobbing
bird.y = BIRD_START_Y + Math.sin(LK.ticks / 20) * 30;
}
};
// End game function
function endGame() {
if (gameOver) return;
gameOver = true;
// Flash red
LK.effects.flashScreen(0xff0000, 600);
// Show game over popup
LK.showGameOver();
}
// Reset on game restart
game.on('destroy', function () {
// Clean up
for (var i = 0; i < pipes.length; i++) {
pipes[i].destroy();
}
pipes = [];
gameStarted = false;
gameOver = false;
frameCount = 0;
LK.setScore(0);
scoreTxt.setText('0');
bird.x = BIRD_START_X;
bird.y = BIRD_START_Y;
bird.velocityY = 0;
bird.rotation = 0;
}); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,256 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Bird class
+var Bird = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach a yellow ellipse as the bird
+ var birdAsset = self.attachAsset('bird', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Bird physics
+ self.velocityY = 0;
+ self.gravity = 1.2; // Gravity per frame
+ self.flapStrength = -28; // Negative for upward movement
+ // Bird size for collision
+ self.radius = birdAsset.width * 0.45;
+ // Flap method
+ self.flap = function () {
+ self.velocityY = self.flapStrength;
+ // Animate a quick upward tilt
+ tween(self, {
+ rotation: -0.3
+ }, {
+ duration: 80,
+ easing: tween.cubicOut,
+ onFinish: function onFinish() {
+ // Return to downward tilt
+ tween(self, {
+ rotation: 0.4
+ }, {
+ duration: 300,
+ easing: tween.cubicIn
+ });
+ }
+ });
+ };
+ // Update method
+ self.update = function () {
+ self.velocityY += self.gravity;
+ self.y += self.velocityY;
+ // Clamp rotation based on velocity
+ if (self.velocityY > 0) {
+ self.rotation = 0.4;
+ } else if (self.velocityY < 0) {
+ self.rotation = -0.3;
+ }
+ };
+ return self;
+});
+// PipePair class (top and bottom pipes)
+var PipePair = Container.expand(function () {
+ var self = Container.call(this);
+ // Pipe config
+ self.pipeWidth = 220;
+ self.gapHeight = 520;
+ self.speed = 12;
+ // Randomize gap position
+ var minGapY = 400;
+ var maxGapY = 2732 - 400 - self.gapHeight;
+ self.gapY = minGapY + Math.floor(Math.random() * (maxGapY - minGapY));
+ // Top pipe
+ var topPipe = self.attachAsset('pipe', {
+ anchorX: 0,
+ anchorY: 1,
+ width: self.pipeWidth,
+ height: self.gapY,
+ color: 0x3bb54a,
+ shape: 'box',
+ x: 0,
+ y: self.gapY
+ });
+ // Bottom pipe
+ var bottomPipe = self.attachAsset('pipe', {
+ anchorX: 0,
+ anchorY: 0,
+ width: self.pipeWidth,
+ height: 2732 - (self.gapY + self.gapHeight),
+ color: 0x3bb54a,
+ shape: 'box',
+ x: 0,
+ y: self.gapY + self.gapHeight
+ });
+ // For collision
+ self.topPipe = topPipe;
+ self.bottomPipe = bottomPipe;
+ // Scoring flag
+ self.passed = false;
+ // Update method
+ self.update = function () {
+ self.x -= self.speed;
+ };
+ // Collision check with bird
+ self.collidesWith = function (bird) {
+ // Bird bounding box
+ var bx = bird.x;
+ var by = bird.y;
+ var br = bird.radius;
+ // Top pipe rect
+ var tx = self.x;
+ var ty = 0;
+ var tw = self.pipeWidth;
+ var th = self.gapY;
+ // Bottom pipe rect
+ var bx2 = self.x;
+ var by2 = self.gapY + self.gapHeight;
+ var bw2 = self.pipeWidth;
+ var bh2 = 2732 - by2;
+ // Circle-rectangle collision
+ function circleRectCollide(cx, cy, cr, rx, ry, rw, rh) {
+ var closestX = Math.max(rx, Math.min(cx, rx + rw));
+ var closestY = Math.max(ry, Math.min(cy, ry + rh));
+ var dx = cx - closestX;
+ var dy = cy - closestY;
+ return dx * dx + dy * dy < cr * cr;
+ }
+ if (circleRectCollide(bx, by, br, tx, ty, tw, th)) return true;
+ if (circleRectCollide(bx, by, br, bx2, by2, bw2, bh2)) return true;
+ return false;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x87ceeb // Sky blue
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var BIRD_START_X = 600;
+var BIRD_START_Y = 1200;
+var PIPE_INTERVAL = 90; // Frames between pipes
+var GROUND_HEIGHT = 180;
+// Create bird asset (ellipse)
+// Create pipe asset (box)
+// Ground asset (for collision)
+// Score text
+var scoreTxt = new Text2('0', {
+ size: 180,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Bird instance
+var bird = new Bird();
+game.addChild(bird);
+bird.x = BIRD_START_X;
+bird.y = BIRD_START_Y;
+// Ground instance
+var ground = LK.getAsset('ground', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 2732 - GROUND_HEIGHT
+});
+game.addChild(ground);
+// Pipes array
+var pipes = [];
+// Game state
+var gameStarted = false;
+var gameOver = false;
+var frameCount = 0;
+// For tap/flap
+game.down = function (x, y, obj) {
+ if (gameOver) return;
+ if (!gameStarted) {
+ gameStarted = true;
+ }
+ bird.flap();
+};
+// Main update loop
+game.update = function () {
+ if (gameOver) return;
+ if (gameStarted) {
+ bird.update();
+ // Add new pipes
+ if (frameCount % PIPE_INTERVAL === 0) {
+ var pipePair = new PipePair();
+ pipePair.x = 2048;
+ game.addChild(pipePair);
+ pipes.push(pipePair);
+ }
+ // Update pipes and check for collisions
+ for (var i = pipes.length - 1; i >= 0; i--) {
+ var pipe = pipes[i];
+ pipe.update();
+ // Collision
+ if (pipe.collidesWith(bird)) {
+ endGame();
+ return;
+ }
+ // Score: when bird passes the pipe
+ if (!pipe.passed && pipe.x + pipe.pipeWidth < bird.x) {
+ pipe.passed = true;
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ }
+ // Remove off-screen pipes
+ if (pipe.x + pipe.pipeWidth < 0) {
+ pipe.destroy();
+ pipes.splice(i, 1);
+ }
+ }
+ // Ground collision
+ if (bird.y + bird.radius > 2732 - GROUND_HEIGHT) {
+ bird.y = 2732 - GROUND_HEIGHT - bird.radius;
+ endGame();
+ return;
+ }
+ // Ceiling clamp
+ if (bird.y - bird.radius < 0) {
+ bird.y = bird.radius;
+ bird.velocityY = 0;
+ }
+ frameCount++;
+ } else {
+ // Idle bird bobbing
+ bird.y = BIRD_START_Y + Math.sin(LK.ticks / 20) * 30;
+ }
+};
+// End game function
+function endGame() {
+ if (gameOver) return;
+ gameOver = true;
+ // Flash red
+ LK.effects.flashScreen(0xff0000, 600);
+ // Show game over popup
+ LK.showGameOver();
+}
+// Reset on game restart
+game.on('destroy', function () {
+ // Clean up
+ for (var i = 0; i < pipes.length; i++) {
+ pipes[i].destroy();
+ }
+ pipes = [];
+ gameStarted = false;
+ gameOver = false;
+ frameCount = 0;
+ LK.setScore(0);
+ scoreTxt.setText('0');
+ bird.x = BIRD_START_X;
+ bird.y = BIRD_START_Y;
+ bird.velocityY = 0;
+ bird.rotation = 0;
});
\ No newline at end of file