User prompt
give the bird and control by mouse
User prompt
give the shape and animations also ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Flap or Flop
User prompt
make the game of flap or flop
User prompt
Please continue polishing my design document.
Initial prompt
make the game flap or flop
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetY = 2732 / 2;
self.currentPath = 'center';
self.update = function () {
// Smooth movement towards target position
var diff = self.targetY - self.y;
self.y += diff * 0.1;
// Enhanced floating animation
var floatOffset = Math.sin(LK.ticks * 0.05) * 15;
var currentY = self.y;
self.y = currentY + floatOffset;
// Wing flap simulation with rotation
if (!birdGraphics.isFlapping) {
birdGraphics.rotation = Math.sin(LK.ticks * 0.2) * 0.15;
}
// Scale breathing effect
var breathScale = 1 + Math.sin(LK.ticks * 0.08) * 0.05;
birdGraphics.scaleX = breathScale;
birdGraphics.scaleY = breathScale;
};
self.setPath = function (path) {
self.currentPath = path;
var newTargetY;
if (path === 'left') {
newTargetY = 2732 * 0.3;
} else if (path === 'right') {
newTargetY = 2732 * 0.7;
} else {
newTargetY = 2732 / 2;
}
// Animate bird to new position with bounce effect
tween(self, {
targetY: newTargetY
}, {
duration: 400,
easing: tween.easeOut
});
// Add slight tilt animation based on direction
var targetRotation = 0;
if (path === 'left') {
targetRotation = -0.2;
} else if (path === 'right') {
targetRotation = 0.2;
}
tween(birdGraphics, {
rotation: targetRotation
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(birdGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
});
};
return self;
});
var Obstacle = Container.expand(function (gapSide) {
var self = Container.call(this);
self.gapSide = gapSide || 'both';
self.speed = -gameSpeed;
self.passed = false;
var gapSize = 350;
// Create obstacles based on gap configuration
if (self.gapSide === 'left' || self.gapSide === 'both') {
// Top obstacle for left gap
var topLeft = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 2732 * 0.3 - gapSize / 2
});
// Bottom obstacle for left gap
var bottomLeft = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 2732 * 0.3 + gapSize / 2
});
}
if (self.gapSide === 'right' || self.gapSide === 'both') {
// Top obstacle for right gap
var topRight = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 2732 * 0.7 - gapSize / 2
});
// Bottom obstacle for right gap
var bottomRight = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 2732 * 0.7 + gapSize / 2
});
}
// Add middle obstacle if only one gap
if (self.gapSide === 'left') {
var rightBlock = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 2732 * 0.7,
height: 800
});
}
if (self.gapSide === 'right') {
var leftBlock = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 2732 * 0.3,
height: 800
});
}
// Start obstacles scaled down for entrance animation
self.scaleX = 0.1;
self.scaleY = 0.1;
// Animate entrance
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
self.update = function () {
self.x += self.speed;
};
return self;
});
var PathIndicator = Container.expand(function (side) {
var self = Container.call(this);
var indicator = self.attachAsset('pathIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.side = side;
if (side === 'left') {
self.y = 2732 * 0.3;
} else {
self.y = 2732 * 0.7;
}
// Start pulsing animation
tween(indicator, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.6
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(indicator, {
scaleX: 0.8,
scaleY: 0.8,
alpha: 0.2
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
self.update = function () {
self.x += -gameSpeed;
// Fade out as it moves
if (self.x < 1000) {
indicator.alpha = Math.max(0, indicator.alpha - 0.02);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var bird;
var obstacles = [];
var pathIndicators = [];
var gameSpeed = 8;
var obstacleSpawnTimer = 0;
var obstacleSpawnDelay = 180; // 3 seconds at 60fps
var nextObstacleGap = 'both';
// UI Elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create bird
bird = game.addChild(new Bird());
bird.x = 300;
bird.y = 2732 / 2;
// Touch controls
game.down = function (x, y, obj) {
if (x < 2048 / 2) {
// Left side tapped
bird.setPath('left');
LK.getSound('flap').play();
} else {
// Right side tapped
bird.setPath('right');
LK.getSound('flap').play();
}
// Add flap animation
var birdGraphics = bird.children[0];
birdGraphics.isFlapping = true;
tween(birdGraphics, {
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(birdGraphics, {
scaleY: 1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
birdGraphics.isFlapping = false;
}
});
}
});
};
// Generate random gap configuration
function getRandomGapConfig() {
var configs = ['left', 'right', 'both'];
return configs[Math.floor(Math.random() * configs.length)];
}
// Check collision between bird and obstacles
function checkCollisions() {
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (bird.intersects(obstacle)) {
// Game over
LK.getSound('collision').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
return true;
}
// Check if bird passed obstacle for scoring
if (!obstacle.passed && obstacle.x < bird.x - 100) {
obstacle.passed = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
// Animate score text
tween(scoreTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Increase speed every 5 points
if (LK.getScore() % 5 === 0) {
gameSpeed += 0.5;
obstacleSpawnDelay = Math.max(120, obstacleSpawnDelay - 5);
}
}
}
return false;
}
// Spawn new obstacle
function spawnObstacle() {
var gapConfig = getRandomGapConfig();
var newObstacle = new Obstacle(gapConfig);
newObstacle.x = 2048 + 200;
obstacles.push(newObstacle);
game.addChild(newObstacle);
// Add path indicators
if (gapConfig === 'left' || gapConfig === 'both') {
var leftIndicator = new PathIndicator('left');
leftIndicator.x = 2048 + 100;
pathIndicators.push(leftIndicator);
game.addChild(leftIndicator);
}
if (gapConfig === 'right' || gapConfig === 'both') {
var rightIndicator = new PathIndicator('right');
rightIndicator.x = 2048 + 100;
pathIndicators.push(rightIndicator);
game.addChild(rightIndicator);
}
}
// Main game loop
game.update = function () {
// Spawn obstacles
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnDelay) {
spawnObstacle();
obstacleSpawnTimer = 0;
}
// Update and clean up obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.x < -300) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
// Update and clean up path indicators
for (var j = pathIndicators.length - 1; j >= 0; j--) {
var indicator = pathIndicators[j];
if (indicator.x < -200 || indicator.children[0].alpha <= 0) {
indicator.destroy();
pathIndicators.splice(j, 1);
}
}
// Check for collisions
checkCollisions();
// Keep bird in bounds
if (bird.y < 50) bird.y = 50;
if (bird.y > 2732 - 50) bird.y = 2732 - 50;
}; ===================================================================
--- original.js
+++ change.js
@@ -17,20 +17,59 @@
self.update = function () {
// Smooth movement towards target position
var diff = self.targetY - self.y;
self.y += diff * 0.1;
- // Slight bobbing animation
- birdGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
+ // Enhanced floating animation
+ var floatOffset = Math.sin(LK.ticks * 0.05) * 15;
+ var currentY = self.y;
+ self.y = currentY + floatOffset;
+ // Wing flap simulation with rotation
+ if (!birdGraphics.isFlapping) {
+ birdGraphics.rotation = Math.sin(LK.ticks * 0.2) * 0.15;
+ }
+ // Scale breathing effect
+ var breathScale = 1 + Math.sin(LK.ticks * 0.08) * 0.05;
+ birdGraphics.scaleX = breathScale;
+ birdGraphics.scaleY = breathScale;
};
self.setPath = function (path) {
self.currentPath = path;
+ var newTargetY;
if (path === 'left') {
- self.targetY = 2732 * 0.3;
+ newTargetY = 2732 * 0.3;
} else if (path === 'right') {
- self.targetY = 2732 * 0.7;
+ newTargetY = 2732 * 0.7;
} else {
- self.targetY = 2732 / 2;
+ newTargetY = 2732 / 2;
}
+ // Animate bird to new position with bounce effect
+ tween(self, {
+ targetY: newTargetY
+ }, {
+ duration: 400,
+ easing: tween.easeOut
+ });
+ // Add slight tilt animation based on direction
+ var targetRotation = 0;
+ if (path === 'left') {
+ targetRotation = -0.2;
+ } else if (path === 'right') {
+ targetRotation = 0.2;
+ }
+ tween(birdGraphics, {
+ rotation: targetRotation
+ }, {
+ duration: 200,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(birdGraphics, {
+ rotation: 0
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ });
};
return self;
});
var Obstacle = Container.expand(function (gapSide) {
@@ -90,8 +129,19 @@
y: 2732 * 0.3,
height: 800
});
}
+ // Start obstacles scaled down for entrance animation
+ self.scaleX = 0.1;
+ self.scaleY = 0.1;
+ // Animate entrance
+ tween(self, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.bounceOut
+ });
self.update = function () {
self.x += self.speed;
};
return self;
@@ -108,12 +158,33 @@
self.y = 2732 * 0.3;
} else {
self.y = 2732 * 0.7;
}
+ // Start pulsing animation
+ tween(indicator, {
+ scaleX: 1.2,
+ scaleY: 1.2,
+ alpha: 0.6
+ }, {
+ duration: 500,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ tween(indicator, {
+ scaleX: 0.8,
+ scaleY: 0.8,
+ alpha: 0.2
+ }, {
+ duration: 500,
+ easing: tween.easeInOut
+ });
+ }
+ });
self.update = function () {
self.x += -gameSpeed;
// Fade out as it moves
- indicator.alpha = Math.max(0, indicator.alpha - 0.01);
+ if (self.x < 1000) {
+ indicator.alpha = Math.max(0, indicator.alpha - 0.02);
+ }
};
return self;
});
@@ -156,8 +227,28 @@
// Right side tapped
bird.setPath('right');
LK.getSound('flap').play();
}
+ // Add flap animation
+ var birdGraphics = bird.children[0];
+ birdGraphics.isFlapping = true;
+ tween(birdGraphics, {
+ scaleY: 1.3
+ }, {
+ duration: 100,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(birdGraphics, {
+ scaleY: 1
+ }, {
+ duration: 150,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ birdGraphics.isFlapping = false;
+ }
+ });
+ }
+ });
};
// Generate random gap configuration
function getRandomGapConfig() {
var configs = ['left', 'right', 'both'];
@@ -179,8 +270,25 @@
obstacle.passed = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
+ // Animate score text
+ tween(scoreTxt, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 150,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(scoreTxt, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ }
+ });
// Increase speed every 5 points
if (LK.getScore() % 5 === 0) {
gameSpeed += 0.5;
obstacleSpawnDelay = Math.max(120, obstacleSpawnDelay - 5);