User prompt
Make the Bird Game controls easier
User prompt
No the breaks between the pipe next to the next time
User prompt
Make the Gaps between the pipes bigger
User prompt
Make the Bird Stativ in the start screen so its not falling down
User prompt
Make the Bird moving slower. Add an start screen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ok
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: OBSTACLE_WIDTH' in or related to this line: 'if (obstacle.x + OBSTACLE_WIDTH / 2 < 0) {' Line Number: 239
User prompt
Fix Bugs of the pipes
Code edit (1 edits merged)
Please save this source code
User prompt
Trippy Flap Odyssey
Initial prompt
Ich hätte gern ein Flappy Bird Game im LSD Style mit wilden Animationen und krassen Farben.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bird class representing the player character
var Bird = Container.expand(function () {
var self = Container.call(this);
// Constants for physics
var GRAVITY = 1.5;
var FLAP_STRENGTH = -25; // Negative value for upward movement
var MAX_ROTATION = Math.PI / 4; // Max tilt angle (45 degrees)
var MIN_ROTATION = -Math.PI / 6; // Min tilt angle (-30 degrees)
// Bird's vertical velocity
self.velocityY = 0;
// Attach the bird graphic asset
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Public method for flapping
self.flap = function () {
self.velocityY = FLAP_STRENGTH;
LK.getSound('flapSound').play(); // Play flap sound
// Optional: Add a quick visual feedback tween on flap
tween.stop(birdGraphics); // Stop previous scale tweens
birdGraphics.scale.set(1.1, 1.1);
tween(birdGraphics.scale, {
x: 1,
y: 1
}, {
duration: 100
});
};
// Update method called every frame by the engine
self.update = function () {
// Apply gravity
self.velocityY += GRAVITY;
self.y += self.velocityY;
// Clamp position to screen bounds (leaving some margin)
if (self.y < birdGraphics.height / 2) {
self.y = birdGraphics.height / 2;
self.velocityY = 0; // Stop moving up if hitting the ceiling
}
// Note: Ground collision is handled in the main game update loop
// Apply rotation based on velocity
var targetRotation = 0;
if (self.velocityY < 0) {
// Moving up
targetRotation = MIN_ROTATION; // Tilt slightly up
} else if (self.velocityY > 10) {
// Moving down fast
// Gradually tilt down based on velocity, capped at MAX_ROTATION
targetRotation = Math.min(MAX_ROTATION, self.velocityY / 50 * MAX_ROTATION);
}
// Smoothly rotate towards the target rotation
birdGraphics.rotation += (targetRotation - birdGraphics.rotation) * 0.1;
};
return self;
});
// ObstaclePair class representing a top and bottom obstacle
var ObstaclePair = Container.expand(function () {
var self = Container.call(this);
// Constants for obstacles
var GAP_HEIGHT = 550; // Space between top and bottom obstacles
var OBSTACLE_WIDTH = 200; // Keep consistent with asset init
// Create top and bottom obstacles
self.topObstacle = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0 // Anchor at the bottom-center
});
self.bottomObstacle = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0 // Anchor at the top-center
});
// Property to track if score has been awarded for this pair
self.scored = false;
// Method to set the position and gap
self.setup = function (xPos, gapCenterY) {
self.x = xPos;
// Position obstacles relative to the container's position
self.topObstacle.y = gapCenterY - GAP_HEIGHT / 2;
self.bottomObstacle.y = gapCenterY + GAP_HEIGHT / 2;
// Randomize color for psychedelic effect
var randomColor = Math.random() * 0xFFFFFF;
self.topObstacle.tint = randomColor;
self.bottomObstacle.tint = randomColor;
};
// Method to check collision with the bird
self.collidesWith = function (bird) {
// Simple Axis-Aligned Bounding Box (AABB) collision check
// Need to convert bird position to obstacle's local coordinates or vice-versa,
// but since obstacles are direct children of the game, and assuming bird is too,
// their global positions can be used if their parents are the same (the game).
// Let's adjust for anchors and check bounds.
// Get global bounds (requires helper or direct calculation)
// Simplified check assuming bird is small compared to gap
var birdRadius = bird.children[0].width / 2; // Approximate bird radius
var birdGlobalPos = bird.getGlobalPosition ? bird.getGlobalPosition() : {
x: bird.x,
y: bird.y
}; // Use global pos if available, else local
// Check collision with top obstacle
// Get global position of obstacle parts if possible, otherwise calculate based on parent
var topObsGlobalPos = self.toGlobal(self.topObstacle.position);
var bottomObsGlobalPos = self.toGlobal(self.bottomObstacle.position);
var topRect = {
x: topObsGlobalPos.x - self.topObstacle.width / 2,
y: topObsGlobalPos.y - self.topObstacle.height,
// Anchor Y is 1.0
width: self.topObstacle.width,
height: self.topObstacle.height
};
var bottomRect = {
x: bottomObsGlobalPos.x - self.bottomObstacle.width / 2,
y: bottomObsGlobalPos.y,
// Anchor Y is 0.0
width: self.bottomObstacle.width,
height: self.bottomObstacle.height
};
var birdRect = {
x: birdGlobalPos.x - birdRadius,
y: birdGlobalPos.y - birdRadius,
width: birdRadius * 2,
height: birdRadius * 2
};
// Check overlap
function checkOverlap(rectA, rectB) {
return rectA.x < rectB.x + rectB.width && rectA.x + rectA.width > rectB.x && rectA.y < rectB.y + rectB.height && rectA.y + rectA.height > rectB.y;
}
if (checkOverlap(birdRect, topRect) || checkOverlap(birdRect, bottomRect)) {
return true;
}
return false;
};
// Update method for movement
self.update = function (speed) {
self.x -= speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a001a // Start with a dark purple background
});
/****
* Game Code
****/
// Include the tween plugin for animations and effects
// Sound for collision (optional)
// Sound for passing obstacle (optional)
// Sound for flapping (optional, but good practice)
// Obstacle asset (will be tinted/resized later)
// Bird asset
// Define assets for the game. These will be created automatically by the engine.
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var OBSTACLE_SPEED = 8;
var OBSTACLE_SPAWN_RATE = 120; // Ticks between spawns (approx 2 seconds at 60fps)
var OBSTACLE_START_X = GAME_WIDTH + 150; // Start spawning off-screen right
var OBSTACLE_MIN_Y = 600; // Min center Y for the gap
var OBSTACLE_MAX_Y = GAME_HEIGHT - 600; // Max center Y for the gap
// Game variables
var bird;
var obstacles = [];
var spawnTimer = 0;
var isGameOver = false;
var backgroundChangeTimer = 0;
var backgroundTween = null; // To manage background color tween
// Score display
var scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Position score text slightly down from the top center, avoiding top-left corner
scoreTxt.y = 100;
// Initialize bird
bird = new Bird();
bird.x = GAME_WIDTH / 4; // Start position
bird.y = GAME_HEIGHT / 2;
game.addChild(bird);
// Handle player input (flap)
game.down = function (x, y, obj) {
if (!isGameOver) {
bird.flap();
}
};
// Function to spawn a new obstacle pair
function spawnObstacle() {
var newObstacle = new ObstaclePair();
var gapCenterY = Math.random() * (OBSTACLE_MAX_Y - OBSTACLE_MIN_Y) + OBSTACLE_MIN_Y;
newObstacle.setup(OBSTACLE_START_X, gapCenterY);
obstacles.push(newObstacle);
game.addChild(newObstacle);
}
// Function for psychedelic background effect
function changeBackgroundColor() {
if (backgroundTween) {
tween.stop(game); // Stop existing background tween if any
}
var nextColor = Math.random() * 0xFFFFFF;
backgroundTween = tween(game, {
backgroundColor: nextColor
}, {
duration: 1000,
// Transition over 1 second
easing: tween.easeInOut,
// Smooth transition
onFinish: function onFinish() {
backgroundTween = null;
} // Clear the tween reference on finish
});
}
// Game update loop
game.update = function () {
if (isGameOver) {
return;
} // Stop updates if game over
// Update bird
bird.update(); // Calls bird's internal update for physics
// Check ground collision
if (bird.y >= GAME_HEIGHT - bird.children[0].height / 2) {
LK.getSound('hitSound').play();
LK.effects.flashScreen(0xFF0000, 300); // Flash red on hit
isGameOver = true;
LK.showGameOver();
return; // Stop further processing this frame
}
// Update obstacles
spawnTimer++;
if (spawnTimer >= OBSTACLE_SPAWN_RATE) {
spawnObstacle();
spawnTimer = 0;
}
// Move and check obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update(OBSTACLE_SPEED); // Move obstacle left
// Check for collision with bird
if (obstacle.collidesWith(bird)) {
LK.getSound('hitSound').play();
LK.effects.flashObject(bird, 0xFF0000, 300); // Flash bird red
isGameOver = true;
LK.showGameOver();
return; // Stop further processing this frame
}
// Check for scoring
if (!obstacle.scored && obstacle.x + obstacle.topObstacle.width / 2 < bird.x) {
obstacle.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('scoreSound').play();
// Optional: Flash score text or screen briefly on score
LK.effects.flashObject(scoreTxt, 0x00FF00, 150);
}
// Remove obstacles that are off-screen left
if (obstacle.x < -obstacle.topObstacle.width) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
// Psychedelic background effect timer
backgroundChangeTimer++;
if (backgroundChangeTimer >= 60) {
// Change color every second (approx)
changeBackgroundColor();
backgroundChangeTimer = 0;
}
// Optional: Add more psychedelic effects like slight world rotation or scaling via tween?
// Example: Pulsating effect on obstacles (use with caution for performance)
obstacles.forEach(function (obs) {
var pulseScale = 1 + Math.sin(LK.ticks * 0.1) * 0.02; // Gentle pulse
obs.topObstacle.scale.y = pulseScale;
obs.bottomObstacle.scale.y = pulseScale;
});
};
// Start the first background color change
changeBackgroundColor(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,288 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Bird class representing the player character
+var Bird = Container.expand(function () {
+ var self = Container.call(this);
+ // Constants for physics
+ var GRAVITY = 1.5;
+ var FLAP_STRENGTH = -25; // Negative value for upward movement
+ var MAX_ROTATION = Math.PI / 4; // Max tilt angle (45 degrees)
+ var MIN_ROTATION = -Math.PI / 6; // Min tilt angle (-30 degrees)
+ // Bird's vertical velocity
+ self.velocityY = 0;
+ // Attach the bird graphic asset
+ var birdGraphics = self.attachAsset('bird', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Public method for flapping
+ self.flap = function () {
+ self.velocityY = FLAP_STRENGTH;
+ LK.getSound('flapSound').play(); // Play flap sound
+ // Optional: Add a quick visual feedback tween on flap
+ tween.stop(birdGraphics); // Stop previous scale tweens
+ birdGraphics.scale.set(1.1, 1.1);
+ tween(birdGraphics.scale, {
+ x: 1,
+ y: 1
+ }, {
+ duration: 100
+ });
+ };
+ // Update method called every frame by the engine
+ self.update = function () {
+ // Apply gravity
+ self.velocityY += GRAVITY;
+ self.y += self.velocityY;
+ // Clamp position to screen bounds (leaving some margin)
+ if (self.y < birdGraphics.height / 2) {
+ self.y = birdGraphics.height / 2;
+ self.velocityY = 0; // Stop moving up if hitting the ceiling
+ }
+ // Note: Ground collision is handled in the main game update loop
+ // Apply rotation based on velocity
+ var targetRotation = 0;
+ if (self.velocityY < 0) {
+ // Moving up
+ targetRotation = MIN_ROTATION; // Tilt slightly up
+ } else if (self.velocityY > 10) {
+ // Moving down fast
+ // Gradually tilt down based on velocity, capped at MAX_ROTATION
+ targetRotation = Math.min(MAX_ROTATION, self.velocityY / 50 * MAX_ROTATION);
+ }
+ // Smoothly rotate towards the target rotation
+ birdGraphics.rotation += (targetRotation - birdGraphics.rotation) * 0.1;
+ };
+ return self;
+});
+// ObstaclePair class representing a top and bottom obstacle
+var ObstaclePair = Container.expand(function () {
+ var self = Container.call(this);
+ // Constants for obstacles
+ var GAP_HEIGHT = 550; // Space between top and bottom obstacles
+ var OBSTACLE_WIDTH = 200; // Keep consistent with asset init
+ // Create top and bottom obstacles
+ self.topObstacle = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 1.0 // Anchor at the bottom-center
+ });
+ self.bottomObstacle = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.0 // Anchor at the top-center
+ });
+ // Property to track if score has been awarded for this pair
+ self.scored = false;
+ // Method to set the position and gap
+ self.setup = function (xPos, gapCenterY) {
+ self.x = xPos;
+ // Position obstacles relative to the container's position
+ self.topObstacle.y = gapCenterY - GAP_HEIGHT / 2;
+ self.bottomObstacle.y = gapCenterY + GAP_HEIGHT / 2;
+ // Randomize color for psychedelic effect
+ var randomColor = Math.random() * 0xFFFFFF;
+ self.topObstacle.tint = randomColor;
+ self.bottomObstacle.tint = randomColor;
+ };
+ // Method to check collision with the bird
+ self.collidesWith = function (bird) {
+ // Simple Axis-Aligned Bounding Box (AABB) collision check
+ // Need to convert bird position to obstacle's local coordinates or vice-versa,
+ // but since obstacles are direct children of the game, and assuming bird is too,
+ // their global positions can be used if their parents are the same (the game).
+ // Let's adjust for anchors and check bounds.
+ // Get global bounds (requires helper or direct calculation)
+ // Simplified check assuming bird is small compared to gap
+ var birdRadius = bird.children[0].width / 2; // Approximate bird radius
+ var birdGlobalPos = bird.getGlobalPosition ? bird.getGlobalPosition() : {
+ x: bird.x,
+ y: bird.y
+ }; // Use global pos if available, else local
+ // Check collision with top obstacle
+ // Get global position of obstacle parts if possible, otherwise calculate based on parent
+ var topObsGlobalPos = self.toGlobal(self.topObstacle.position);
+ var bottomObsGlobalPos = self.toGlobal(self.bottomObstacle.position);
+ var topRect = {
+ x: topObsGlobalPos.x - self.topObstacle.width / 2,
+ y: topObsGlobalPos.y - self.topObstacle.height,
+ // Anchor Y is 1.0
+ width: self.topObstacle.width,
+ height: self.topObstacle.height
+ };
+ var bottomRect = {
+ x: bottomObsGlobalPos.x - self.bottomObstacle.width / 2,
+ y: bottomObsGlobalPos.y,
+ // Anchor Y is 0.0
+ width: self.bottomObstacle.width,
+ height: self.bottomObstacle.height
+ };
+ var birdRect = {
+ x: birdGlobalPos.x - birdRadius,
+ y: birdGlobalPos.y - birdRadius,
+ width: birdRadius * 2,
+ height: birdRadius * 2
+ };
+ // Check overlap
+ function checkOverlap(rectA, rectB) {
+ return rectA.x < rectB.x + rectB.width && rectA.x + rectA.width > rectB.x && rectA.y < rectB.y + rectB.height && rectA.y + rectA.height > rectB.y;
+ }
+ if (checkOverlap(birdRect, topRect) || checkOverlap(birdRect, bottomRect)) {
+ return true;
+ }
+ return false;
+ };
+ // Update method for movement
+ self.update = function (speed) {
+ self.x -= speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1a001a // Start with a dark purple background
+});
+
+/****
+* Game Code
+****/
+// Include the tween plugin for animations and effects
+// Sound for collision (optional)
+// Sound for passing obstacle (optional)
+// Sound for flapping (optional, but good practice)
+// Obstacle asset (will be tinted/resized later)
+// Bird asset
+// Define assets for the game. These will be created automatically by the engine.
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var OBSTACLE_SPEED = 8;
+var OBSTACLE_SPAWN_RATE = 120; // Ticks between spawns (approx 2 seconds at 60fps)
+var OBSTACLE_START_X = GAME_WIDTH + 150; // Start spawning off-screen right
+var OBSTACLE_MIN_Y = 600; // Min center Y for the gap
+var OBSTACLE_MAX_Y = GAME_HEIGHT - 600; // Max center Y for the gap
+// Game variables
+var bird;
+var obstacles = [];
+var spawnTimer = 0;
+var isGameOver = false;
+var backgroundChangeTimer = 0;
+var backgroundTween = null; // To manage background color tween
+// Score display
+var scoreTxt = new Text2('0', {
+ size: 180,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Position score text slightly down from the top center, avoiding top-left corner
+scoreTxt.y = 100;
+// Initialize bird
+bird = new Bird();
+bird.x = GAME_WIDTH / 4; // Start position
+bird.y = GAME_HEIGHT / 2;
+game.addChild(bird);
+// Handle player input (flap)
+game.down = function (x, y, obj) {
+ if (!isGameOver) {
+ bird.flap();
+ }
+};
+// Function to spawn a new obstacle pair
+function spawnObstacle() {
+ var newObstacle = new ObstaclePair();
+ var gapCenterY = Math.random() * (OBSTACLE_MAX_Y - OBSTACLE_MIN_Y) + OBSTACLE_MIN_Y;
+ newObstacle.setup(OBSTACLE_START_X, gapCenterY);
+ obstacles.push(newObstacle);
+ game.addChild(newObstacle);
+}
+// Function for psychedelic background effect
+function changeBackgroundColor() {
+ if (backgroundTween) {
+ tween.stop(game); // Stop existing background tween if any
+ }
+ var nextColor = Math.random() * 0xFFFFFF;
+ backgroundTween = tween(game, {
+ backgroundColor: nextColor
+ }, {
+ duration: 1000,
+ // Transition over 1 second
+ easing: tween.easeInOut,
+ // Smooth transition
+ onFinish: function onFinish() {
+ backgroundTween = null;
+ } // Clear the tween reference on finish
+ });
+}
+// Game update loop
+game.update = function () {
+ if (isGameOver) {
+ return;
+ } // Stop updates if game over
+ // Update bird
+ bird.update(); // Calls bird's internal update for physics
+ // Check ground collision
+ if (bird.y >= GAME_HEIGHT - bird.children[0].height / 2) {
+ LK.getSound('hitSound').play();
+ LK.effects.flashScreen(0xFF0000, 300); // Flash red on hit
+ isGameOver = true;
+ LK.showGameOver();
+ return; // Stop further processing this frame
+ }
+ // Update obstacles
+ spawnTimer++;
+ if (spawnTimer >= OBSTACLE_SPAWN_RATE) {
+ spawnObstacle();
+ spawnTimer = 0;
+ }
+ // Move and check obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obstacle = obstacles[i];
+ obstacle.update(OBSTACLE_SPEED); // Move obstacle left
+ // Check for collision with bird
+ if (obstacle.collidesWith(bird)) {
+ LK.getSound('hitSound').play();
+ LK.effects.flashObject(bird, 0xFF0000, 300); // Flash bird red
+ isGameOver = true;
+ LK.showGameOver();
+ return; // Stop further processing this frame
+ }
+ // Check for scoring
+ if (!obstacle.scored && obstacle.x + obstacle.topObstacle.width / 2 < bird.x) {
+ obstacle.scored = true;
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ LK.getSound('scoreSound').play();
+ // Optional: Flash score text or screen briefly on score
+ LK.effects.flashObject(scoreTxt, 0x00FF00, 150);
+ }
+ // Remove obstacles that are off-screen left
+ if (obstacle.x < -obstacle.topObstacle.width) {
+ obstacle.destroy();
+ obstacles.splice(i, 1);
+ }
+ }
+ // Psychedelic background effect timer
+ backgroundChangeTimer++;
+ if (backgroundChangeTimer >= 60) {
+ // Change color every second (approx)
+ changeBackgroundColor();
+ backgroundChangeTimer = 0;
+ }
+ // Optional: Add more psychedelic effects like slight world rotation or scaling via tween?
+ // Example: Pulsating effect on obstacles (use with caution for performance)
+ obstacles.forEach(function (obs) {
+ var pulseScale = 1 + Math.sin(LK.ticks * 0.1) * 0.02; // Gentle pulse
+ obs.topObstacle.scale.y = pulseScale;
+ obs.bottomObstacle.scale.y = pulseScale;
+ });
+};
+// Start the first background color change
+changeBackgroundColor();
\ No newline at end of file