User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'bird')' in or related to this line: 'var decor = cosmeticsDecor[type];' Line Number: 575
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'bird')' in or related to this line: 'var decor = cosmeticsDecor[type];' Line Number: 575
User prompt
In the cosmetics menu, visually emphasize the selected character. Add a gentle bounce animation to the selected character’s frame, making it float slightly upward in a loop. Additionally, decorate the selected frame: - If the selected character is the bird, animate tiny hearts or sparkling stars gently floating around the frame. - If the selected character is the dragon, animate small glowing sparks or embers flickering around the frame. Ensure the effects are subtle, pastel-themed, and consistent with the game’s cute and retro pixel art style. The visual indicators should not interfere with the clarity of the character inside the frame.
User prompt
The volume icons are visible in the cosmetics menu after changing them, but they shouldn't be visible there. They should still change, but they should be visible when you get to the main menu.
User prompt
Volume buttons can never appear in the cosmetics menu.
User prompt
If "playerSquare" is pressed in the Cosmetics menu, the volume icons in the main menu will be replaced with"volumeOn" and "volumeOff".
User prompt
If player clicks on playerDragon in the Cosmetics menu, the volume icons in the main menu will be replaced with "volumeOffDragon" and "volumeOnDragon".
User prompt
I have to press it multiple times to get the sound icons to match the correct theme.
User prompt
If the theme is dragon, "volumeOnDragon" or "volumeOffDragon" assets will appear in the main menu.
User prompt
If the theme is dragon, the sound icons should also be dragons, but that's not the case. If the theme is bird, it will be normal sound icons, if the theme is dragon, it will be dragon sound icons.
User prompt
If the theme is bird, there are dragon sounds, if it is dragon, there are bird sounds. That's wrong.
User prompt
I added "volumeOnDragon" and "volumeOfDragon" to the assets for the dragon theme. If the theme is dragon, they will be the volume icons.
User prompt
The volume icon's appearance and clickability do not align.
User prompt
When in the cosmetics menu, the play button is not visible, but it still functions and can be clicked, its function must be deactivated.
User prompt
The Cosmetics button should not be clickable while in the cosmetics menu.
User prompt
When you click on the cosmetics button while in the cosmetics menu, the game starts, and there should be no function while it is there.
User prompt
The pipes should be behind the ground, that's how it should look.
User prompt
When the character is falling, he looks down. When he is jumping, he looks up, but after changing the character, this feature stops working.
User prompt
After changing the character from the Cosmetics menu, the character's physics do not work.
User prompt
If the theme is dragons, then the character's lost version should also be a dragon.
User prompt
The best score doesn't changes.
Code edit (1 edits merged)
Please save this source code
User prompt
Make pipes wider
User prompt
If the theme is dragon, the pipes should also match the dragon theme.
User prompt
If the theme is dragon, the pipes should also match the dragon theme.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // PipePair: Represents a pair of pipes (top and bottom) with a gap for the player to pass through var PipePair = Container.expand(function () { var self = Container.call(this); // Constants for pipe dimensions var pipeWidth = 400; // Increased from 220 to 400 for wider pipes var minGap = 700; var maxGap = 1000; var minY = 350; var maxY = 2732 - 350 - minGap; // Randomize gap position var gapSize = minGap + Math.floor(Math.random() * (maxGap - minGap)); var gapY = minY + Math.floor(Math.random() * (maxY - minY)); // Determine pipe asset names based on global theme flag var pipeTopAsset = 'pipeTop'; var pipeBottomAsset = 'pipeBottom'; if (typeof window !== "undefined" && window.__FRVR_PIPES_THEME === "dragon") { pipeTopAsset = 'pipeTopDragon'; pipeBottomAsset = 'pipeBottomDragon'; } // Top pipe var topPipeHeight = gapY; var topPipe = self.attachAsset(pipeTopAsset, { width: pipeWidth, height: topPipeHeight, color: 0x4ec04e, shape: 'box', anchorX: 0, anchorY: 0 }); topPipe.x = 0; topPipe.y = 0; // Bottom pipe var bottomPipeHeight = 2732 - (gapY + gapSize); var bottomPipe = self.attachAsset(pipeBottomAsset, { width: pipeWidth, height: bottomPipeHeight, color: 0x4ec04e, shape: 'box', anchorX: 0, anchorY: 0 }); bottomPipe.x = 0; bottomPipe.y = gapY + gapSize; // Used for collision detection self.topPipe = topPipe; self.bottomPipe = bottomPipe; // Used to check if player has passed this pipe self.passed = false; // Set initial position (off the right edge) self.x = 2048; self.y = 0; // Pipe speed (will be set from outside) self.speed = -8; // Update method called every tick self.update = function () { self.x += self.speed; }; // Helper for collision with player self.intersectsPlayer = function (player) { // Check collision with top pipe if (player.intersects(topPipe)) { return true; } // Check collision with bottom pipe if (player.intersects(bottomPipe)) { return true; } return false; }; return self; }); // Player: The square character controlled by the player var Player = Container.expand(function () { var self = Container.call(this); // Attach square asset var square = self.attachAsset('playerSquare', { width: 200, height: 200, color: 0xffd700, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Physics properties self.vy = 0; // vertical velocity self.gravity = 1.1; self.jumpStrength = -22; // For rotation effect (optional, can be improved later) self.maxAngle = Math.PI / 6; self.minAngle = -Math.PI / 3; // Always keep a reference to the main asset for rotation self._mainAsset = square; // Update method called every tick self.update = function () { self.vy += self.gravity; self.y += self.vy; // Clamp rotation based on velocity var angle = self.vy / 40; if (angle > self.maxAngle) { angle = self.maxAngle; } if (angle < self.minAngle) { angle = self.minAngle; } // Always rotate the main asset (square, dragon, etc) if (self._mainAsset) { self._mainAsset.rotation = angle; } }; // Jump method self.jump = function () { self.vy = self.jumpStrength; }; // Reset method self.reset = function () { self.vy = 0; self.y = 2732 / 2; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Sky blue }); /**** * Game Code ****/ // Game constants // Tween plugin for smooth animations (not strictly needed for MVP, but included for future use) var GROUND_HEIGHT = 350; // Volume button state and asset var volumeOnButton = null; var volumeOffButton = null; var isVolumeOn = true; // Helper to get correct volume asset names based on theme function getVolumeAssetNames() { var theme = "bird"; if (typeof selectedCharacter !== "undefined") { theme = selectedCharacter; } else if (typeof window !== "undefined" && window.__FRVR_PIPES_THEME === "dragon") { theme = "dragon"; } if (theme === "dragon") { return { on: "volumeOnDragon", off: "volumeOffDragon" }; } return { on: "volumeOn", off: "volumeOff" }; } // Always play background music when the game starts if (!window.__FRVR_MUTED) { LK.playMusic('muzik'); } // Hide the pause button in the top left if it exists if (LK.pauseButton) { LK.pauseButton.visible = false; } var PIPE_INTERVAL = 110; // frames between pipes var PIPE_SPEED_START = -8; var PIPE_SPEED_INC = -0.2; var PIPE_SPEED_MAX = -22; // Game state variables var pipes = []; var player = null; var ground = null; // scoreTxt and bestScoreTxt removed (no longer used) var score = 0; var bestScore = 0; var ticksSinceLastPipe = 0; var pipeSpeed = PIPE_SPEED_START; var gameStarted = false; var gameOver = false; // Load best score from storage at game start if (typeof storage.flappyBest !== "undefined" && !isNaN(storage.flappyBest)) { bestScore = storage.flappyBest; } else { bestScore = 0; } // Add background image (behind everything) var background = LK.getAsset('background', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); background.x = 0; background.y = 0; game.addChild(background); // Add a container for pipes so we can control their display order var pipesContainer = new Container(); game.addChild(pipesContainer); // Add ground (visual only, for collision) ground = LK.getAsset('ground', { width: 2048, height: GROUND_HEIGHT, color: 0x8b5a2b, shape: 'box', anchorX: 0, anchorY: 0 }); ground.x = 0; ground.y = 2732 - GROUND_HEIGHT; game.addChild(ground); // Add player player = new Player(); player.x = 600; player.y = 2732 / 2; player.visible = false; // Hide player at first game.addChild(player); // Add play and cosmetics buttons (in front of background, before game starts) var playButton = LK.getAsset('playButton', { width: 1000, height: 440, anchorX: 0.5, anchorY: 0.5, x: 1024, y: 600 }); var cosmeticsButton = LK.getAsset('cosmeticsButton', { width: 1340, height: 440, anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1100 }); game.addChild(playButton); game.addChild(cosmeticsButton); // Cosmetics menu state var cosmeticsMenuActive = false; // Cosmetics menu assets (created once, shown/hidden as needed) var cosmeticsTitle = LK.getAsset('cosmeticsButton', { width: 1340, height: 440, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 440 }); cosmeticsTitle.visible = false; game.addChild(cosmeticsTitle); // Character frames var frameY = 1366; // vertical center var frameSpacing = 300; var birdFrame = LK.getAsset('birdFrame', { width: 840, height: 960, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - frameSpacing - 150, y: frameY }); birdFrame.visible = false; game.addChild(birdFrame); // Bird character sprite (centered in birdFrame) var birdSprite = LK.getAsset('playerSquare', { width: 520, // fits well inside 840x960 frame, leaves margin for decorations height: 490, // maintain aspect ratio (original 1000x945.31) anchorX: 0.5, anchorY: 0.5, x: birdFrame.x, y: birdFrame.y }); birdSprite.visible = false; game.addChild(birdSprite); var dragonFrame = LK.getAsset('dragonFrame', { width: 920, height: 1150, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + frameSpacing + 150, y: frameY }); dragonFrame.visible = false; game.addChild(dragonFrame); // Dragon character sprite (centered in dragonFrame) var dragonSprite = LK.getAsset('playerDragon', { width: 600, // fits well inside 920x1150 frame, leaves margin for decorations height: 610, // maintain aspect ratio (original 1000x1019.92) anchorX: 0.5, anchorY: 0.5, x: dragonFrame.x, y: dragonFrame.y }); dragonSprite.visible = false; game.addChild(dragonSprite); // BACK button, centered below frames, same vertical distance as title above var backBtnY = frameY + (frameY - cosmeticsTitle.y); var backButton = LK.getAsset('backButton', { width: 1000, height: 531.25, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: backBtnY }); backButton.visible = false; game.addChild(backButton); // Add volume buttons (positioned under cosmetics button, matching cosmetics button width) var cosmeticsBtnWidth = 1340; var cosmeticsBtnHeight = 440; var volumeBtnWidth = cosmeticsBtnWidth * 0.25; // make volume buttons bigger var volumeBtnHeightOn = volumeBtnWidth * 0.77; // keep aspect ratio similar to original var volumeBtnHeightOff = volumeBtnWidth * 0.98; // keep aspect ratio similar to original var volumeBtnX = 2048 / 2; var volumeBtnY = 1100 + cosmeticsBtnHeight / 2 + 60 + volumeBtnHeightOn / 2; // 60px gap below cosmetics var volumeAssets = getVolumeAssetNames(); volumeOnButton = LK.getAsset(volumeAssets.on, { width: volumeBtnWidth, height: volumeBtnHeightOn, anchorX: 0.5, anchorY: 0.5, x: volumeBtnX, y: volumeBtnY }); volumeOffButton = LK.getAsset(volumeAssets.off, { width: volumeBtnWidth, height: volumeBtnHeightOff, anchorX: 0.5, anchorY: 0.5, x: volumeBtnX, y: volumeBtnY }); // Show correct volume icons in main menu based on theme if (typeof selectedCharacter !== "undefined" && selectedCharacter === "dragon" || typeof window !== "undefined" && window.__FRVR_PIPES_THEME === "dragon") { volumeOnButton.visible = isVolumeOn; volumeOffButton.visible = !isVolumeOn; } else { volumeOnButton.visible = isVolumeOn; volumeOffButton.visible = !isVolumeOn; } game.addChild(volumeOnButton); game.addChild(volumeOffButton); // (score text removed) // (best score text removed) // --- High Score Display (main menu) --- var highScoreGroup = new Container(); // Make the high score icon and digits EVEN bigger // Position: to the left under the cosmetics button, now stack vertically var highScoreIconScale = 2.5; // scale up the icon even more // Centered horizontally with cosmetics button, below it var highScoreIconX = 725; var highScoreIconY = 1875; var highScoreIcon = LK.getAsset('highScore', { width: volumeBtnWidth * 0.7 * highScoreIconScale, height: 54.3 * (volumeBtnWidth * 0.7 * highScoreIconScale / 100), anchorX: 0.5, anchorY: 0.5, x: highScoreIconX + volumeBtnWidth * 0.7 * highScoreIconScale / 2, y: highScoreIconY }); highScoreGroup.addChild(highScoreIcon); // Helper to clear and set numeric assets for high score function setHighScoreDigits(n) { // Remove previous digits for (var i = highScoreGroup.children.length - 1; i >= 1; i--) { highScoreGroup.removeChild(highScoreGroup.children[i]); } var digits = String(n).split(''); var digitWidth = volumeBtnWidth * 0.32 * 2.2; // scale up digits even more var digitSpacing = digitWidth * 0.12; // more spacing for bigger digits // Center digits horizontally under the icon var totalDigitsWidth = digits.length * digitWidth + (digits.length - 1) * digitSpacing; var startX = highScoreIcon.x - totalDigitsWidth / 2; var digitY = highScoreIcon.y + highScoreIcon.height / 2 + digitWidth / 2 + 20; // 20px gap below icon for (var i = 0; i < digits.length; i++) { var digitAsset = LK.getAsset(digits[i], { width: digitWidth, height: LK.getAsset(digits[i], { width: 100, height: 100 }).height * (digitWidth / 100), anchorX: 0, anchorY: 0.5, x: startX + i * (digitWidth + digitSpacing), y: digitY }); highScoreGroup.addChild(digitAsset); } } // Set initial best score setHighScoreDigits(bestScore); // Add to game game.addChild(highScoreGroup); // Show only in main menu highScoreGroup.visible = !gameStarted && !gameOver; // Update high score display on game over var _oldOnGameOver = game.onGameOver; game.onGameOver = function () { if (score > bestScore) { bestScore = score; setHighScoreDigits(bestScore); } else { setHighScoreDigits(bestScore); } highScoreGroup.visible = true; if (_oldOnGameOver) { _oldOnGameOver(); } }; // Hide high score display when game starts var _oldStartGame = startGame; startGame = function startGame() { highScoreGroup.visible = false; _oldStartGame(); }; // Helper: Start the game function startGame() { // Reset state for (var i = pipes.length - 1; i >= 0; i--) { pipes[i].destroy(); pipes.splice(i, 1); } // Always use the selected character's player, background, and ground if (typeof swappableAssets !== "undefined") { player = swappableAssets.player; background = swappableAssets.background; ground = swappableAssets.ground; } player.x = 600; player.y = 2732 / 2; player.vy = 0; player.visible = true; // Show player when game starts score = 0; // scoreTxt.setText(score); // removed, no score text pipeSpeed = PIPE_SPEED_START; ticksSinceLastPipe = 0; gameStarted = true; gameOver = false; // Play music if not muted if (!window.__FRVR_MUTED) { LK.playMusic('muzik'); } } // Helper: End the game function endGame() { gameOver = true; gameStarted = false; // Swap player asset to 'playerDead' or 'playerDragonDead' depending on theme if (typeof swappableAssets !== "undefined") { player = swappableAssets.player; background = swappableAssets.background; ground = swappableAssets.ground; } if (player && player.children && player.children.length > 0) { // Remove all children to ensure no old sprite remains while (player.children.length > 0) { player.removeChild(player.children[0]); } var deadAsset; // Use correct dead sprite for selected character or theme if (typeof selectedCharacter !== "undefined" && selectedCharacter === "dragon" || typeof window !== "undefined" && window.__FRVR_PIPES_THEME === "dragon") { deadAsset = player.attachAsset('playerDragonDead', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); } else { deadAsset = player.attachAsset('playerDead', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); } // Center dead asset deadAsset.x = 0; deadAsset.y = 0; deadAsset.rotation = 0; } // Flash screen red LK.effects.flashScreen(0xff0000, 800); // Save best score if (score > bestScore) { bestScore = score; storage.flappyBest = bestScore; } // Show game over popup (handled by LK) LK.showGameOver(); // Show dead player sprite and keep it visible after death player.visible = true; } // Helper: Player jump function playerJump() { if (!gameStarted) { startGame(); } if (!gameOver) { player.jump(); } } // Touch/click to jump or handle play/cosmetics button game.down = function (x, y, obj) { // Prevent jump if touch is in top left 100x100 (menu area) if (x < 100 && y < 100) { return; } // If game hasn't started, check if playButton or cosmeticsButton was pressed if (!gameStarted && !gameOver) { // Check volumeOnButton (use correct bounds for anchorX: 0.5) if (volumeOnButton && volumeOnButton.visible && x >= volumeOnButton.x - volumeOnButton.width / 2 && x <= volumeOnButton.x + volumeOnButton.width / 2 && y >= volumeOnButton.y - volumeOnButton.height / 2 && y <= volumeOnButton.y + volumeOnButton.height / 2) { // Mute all sounds isVolumeOn = false; volumeOnButton.visible = false; volumeOffButton.visible = true; // Set a global mute flag; all sound/music play calls should check this flag window.__FRVR_MUTED = true; LK.stopMusic(); return; } // Check volumeOffButton (use correct bounds for anchorX: 0.5) if (volumeOffButton && volumeOffButton.visible && x >= volumeOffButton.x - volumeOffButton.width / 2 && x <= volumeOffButton.x + volumeOffButton.width / 2 && y >= volumeOffButton.y - volumeOffButton.height / 2 && y <= volumeOffButton.y + volumeOffButton.height / 2) { // Unmute all sounds isVolumeOn = true; volumeOnButton.visible = true; volumeOffButton.visible = false; // Unset the global mute flag; all sound/music play calls should check this flag window.__FRVR_MUTED = false; LK.playMusic('muzik'); return; } // Check playButton if (!cosmeticsMenuActive && playButton && x >= playButton.x - playButton.width / 2 && x <= playButton.x + playButton.width / 2 && y >= playButton.y - playButton.height / 2 && y <= playButton.y + playButton.height / 2) { // Start game, hide buttons playButton.visible = false; cosmeticsButton.visible = false; if (volumeOnButton) { volumeOnButton.visible = false; } if (volumeOffButton) { volumeOffButton.visible = false; } startGame(); return; } // Check cosmeticsButton (open cosmetics menu) if (cosmeticsButton && x >= cosmeticsButton.x - cosmeticsButton.width / 2 && x <= cosmeticsButton.x + cosmeticsButton.width / 2 && y >= cosmeticsButton.y - cosmeticsButton.height / 2 && y <= cosmeticsButton.y + cosmeticsButton.height / 2) { // Helper to swap character theme var setCharacterTheme = function setCharacterTheme(theme) { // Always allow switching, even if same as current selectedCharacter = theme; // Remove old assets if (swappableAssets.background && swappableAssets.background.parent) { swappableAssets.background.parent.removeChild(swappableAssets.background); } if (swappableAssets.ground && swappableAssets.ground.parent) { swappableAssets.ground.parent.removeChild(swappableAssets.ground); } if (swappableAssets.player && swappableAssets.player.parent) { swappableAssets.player.parent.removeChild(swappableAssets.player); } // Swap volume button assets for theme var volumeAssets = getVolumeAssetNames(); var oldOnButton = volumeOnButton; var oldOffButton = volumeOffButton; var volumeBtnWidth = cosmeticsBtnWidth * 0.25; var volumeBtnHeightOn = volumeBtnWidth * 0.77; var volumeBtnHeightOff = volumeBtnWidth * 0.98; var volumeBtnX = 2048 / 2; var volumeBtnY = 1100 + cosmeticsBtnHeight / 2 + 60 + volumeBtnHeightOn / 2; // Remove old volume buttons before creating new ones to avoid stacking if (oldOnButton && oldOnButton.parent) oldOnButton.parent.removeChild(oldOnButton); if (oldOffButton && oldOffButton.parent) oldOffButton.parent.removeChild(oldOffButton); volumeOnButton = LK.getAsset(volumeAssets.on, { width: volumeBtnWidth, height: volumeBtnHeightOn, anchorX: 0.5, anchorY: 0.5, x: volumeBtnX, y: volumeBtnY }); volumeOffButton = LK.getAsset(volumeAssets.off, { width: volumeBtnWidth, height: volumeBtnHeightOff, anchorX: 0.5, anchorY: 0.5, x: volumeBtnX, y: volumeBtnY }); volumeOnButton.visible = isVolumeOn; volumeOffButton.visible = !isVolumeOn; game.addChild(volumeOnButton); game.addChild(volumeOffButton); // Add new assets if (theme === "dragon") { // Background swappableAssets.background = LK.getAsset('backgroundDragon', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); swappableAssets.background.x = 0; swappableAssets.background.y = 0; game.addChildAt(swappableAssets.background, 0); // Ground swappableAssets.ground = LK.getAsset('groundDragon', { width: 2048, height: GROUND_HEIGHT, anchorX: 0, anchorY: 0 }); swappableAssets.ground.x = 0; swappableAssets.ground.y = 2732 - GROUND_HEIGHT; game.addChild(swappableAssets.ground); // Ensure pipesContainer is above background and below ground if (pipesContainer && pipesContainer.parent) { pipesContainer.parent.removeChild(pipesContainer); } game.addChildAt(pipesContainer, game.children.indexOf(swappableAssets.ground)); // Player swappableAssets.player = new Player(); // Swap asset inside Player to dragon if (swappableAssets.player.children.length > 0) { var oldAsset = swappableAssets.player.children[0]; var dragonAsset = swappableAssets.player.attachAsset('playerDragon', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); dragonAsset.x = oldAsset.x; dragonAsset.y = oldAsset.y; dragonAsset.rotation = oldAsset.rotation; swappableAssets.player.removeChild(oldAsset); // Ensure reference to the new asset for rotation swappableAssets.player._mainAsset = dragonAsset; } else { // If no children, set _mainAsset to the new dragon asset swappableAssets.player._mainAsset = swappableAssets.player.children[0]; } swappableAssets.player.x = 600; swappableAssets.player.y = 2732 / 2; swappableAssets.player.visible = false; game.addChild(swappableAssets.player); // Set global flag for dragon pipes window.__FRVR_PIPES_THEME = "dragon"; } else { // Bird theme (default) swappableAssets.background = LK.getAsset('background', { width: 2048, height: 2732, anchorX: 0, anchorY: 0 }); swappableAssets.background.x = 0; swappableAssets.background.y = 0; game.addChildAt(swappableAssets.background, 0); swappableAssets.ground = LK.getAsset('ground', { width: 2048, height: GROUND_HEIGHT, anchorX: 0, anchorY: 0 }); swappableAssets.ground.x = 0; swappableAssets.ground.y = 2732 - GROUND_HEIGHT; game.addChild(swappableAssets.ground); // Ensure pipesContainer is above background and below ground if (pipesContainer && pipesContainer.parent) { pipesContainer.parent.removeChild(pipesContainer); } game.addChildAt(pipesContainer, game.children.indexOf(swappableAssets.ground)); swappableAssets.player = new Player(); // Swap asset inside Player to bird if (swappableAssets.player.children.length > 0) { var oldAsset = swappableAssets.player.children[0]; var birdAsset = swappableAssets.player.attachAsset('playerSquare', { width: 200, height: 200, anchorX: 0.5, anchorY: 0.5 }); birdAsset.x = oldAsset.x; birdAsset.y = oldAsset.y; birdAsset.rotation = oldAsset.rotation; swappableAssets.player.removeChild(oldAsset); // Ensure reference to the new asset for rotation swappableAssets.player._mainAsset = birdAsset; } else { // If no children, set _mainAsset to the new bird asset swappableAssets.player._mainAsset = swappableAssets.player.children[0]; } swappableAssets.player.x = 600; swappableAssets.player.y = 2732 / 2; swappableAssets.player.visible = false; game.addChild(swappableAssets.player); // Set global flag for bird pipes window.__FRVR_PIPES_THEME = "bird"; } // Update global references background = swappableAssets.background; ground = swappableAssets.ground; player = swappableAssets.player; }; // Hide main menu assets playButton.visible = false; cosmeticsButton.visible = false; if (volumeOnButton) { volumeOnButton.visible = false; } if (volumeOffButton) { volumeOffButton.visible = false; } highScoreGroup.visible = false; // Show cosmetics menu assets cosmeticsTitle.visible = true; birdFrame.visible = true; dragonFrame.visible = true; backButton.visible = true; birdSprite.visible = true; dragonSprite.visible = true; cosmeticsMenuActive = true; // Track which character is selected: "bird" or "dragon" if (typeof selectedCharacter === "undefined") { var selectedCharacter = "bird"; } // Save references to swappable assets for easy replacement if (typeof swappableAssets === "undefined") { var swappableAssets = { background: background, ground: ground, player: player }; } game._cosmeticsMenuDownHandler = function (x, y) { // Bird card if (birdFrame.visible && x >= birdFrame.x - birdFrame.width / 2 && x <= birdFrame.x + birdFrame.width / 2 && y >= birdFrame.y - birdFrame.height / 2 && y <= birdFrame.y + birdFrame.height / 2) { setCharacterTheme("bird"); return; } // Dragon card if (dragonFrame.visible && x >= dragonFrame.x - dragonFrame.width / 2 && x <= dragonFrame.x + dragonFrame.width / 2 && y >= dragonFrame.y - dragonFrame.height / 2 && y <= dragonFrame.y + dragonFrame.height / 2) { setCharacterTheme("dragon"); return; } }; return; } // Handle BACK button in cosmetics menu if (cosmeticsMenuActive) { // First, check if a character card was clicked if (typeof game._cosmeticsMenuDownHandler === "function") { game._cosmeticsMenuDownHandler(x, y); } // Then, check for BACK button if (backButton && backButton.visible && x >= backButton.x - backButton.width / 2 && x <= backButton.x + backButton.width / 2 && y >= backButton.y - backButton.height / 2 && y <= backButton.y + backButton.height / 2) { // Hide cosmetics menu assets cosmeticsTitle.visible = false; birdFrame.visible = false; dragonFrame.visible = false; backButton.visible = false; birdSprite.visible = false; dragonSprite.visible = false; cosmeticsMenuActive = false; // Show main menu assets playButton.visible = true; cosmeticsButton.visible = true; if (isVolumeOn) { volumeOnButton.visible = true; volumeOffButton.visible = false; } else { volumeOnButton.visible = false; volumeOffButton.visible = true; } highScoreGroup.visible = true; return; } // Block jump if not started return; } // Block jump if not started return; } playerJump(); }; // Main update loop game.update = function () { if (!gameStarted || gameOver) { // Idle animation: player slowly falls, pipes don't move player.update(); // Clamp player to not fall below ground if (player.y + 100 > 2732 - GROUND_HEIGHT) { player.y = 2732 - GROUND_HEIGHT - 100; player.vy = 0.0; } return; } // Always use the selected character's player, background, and ground if (typeof swappableAssets !== "undefined") { player = swappableAssets.player; background = swappableAssets.background; ground = swappableAssets.ground; } // Update player player.update(); // Clamp player to not fall below ground if (player.y + 100 > 2732 - GROUND_HEIGHT) { player.y = 2732 - GROUND_HEIGHT - 100; endGame(); return; } // Clamp player to not go above screen if (player.y - 100 < 0) { player.y = 100; player.vy = 0; } // Spawn pipes ticksSinceLastPipe++; if (ticksSinceLastPipe >= PIPE_INTERVAL) { ticksSinceLastPipe = 0; var pipe = new PipePair(); pipe.speed = pipeSpeed; pipes.push(pipe); pipesContainer.addChild(pipe); } // Update pipes for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; pipe.speed = pipeSpeed; pipe.update(); // Check for collision if (pipe.intersectsPlayer(player)) { endGame(); return; } // Check if player passed the pipe (score) if (!pipe.passed && pipe.x + 400 < player.x - 100) { // 400 matches new pipeWidth pipe.passed = true; score++; // scoreTxt.setText(score); // removed, no score text // Increase speed every 5 points, up to max if (score % 5 === 0 && pipeSpeed > PIPE_SPEED_MAX) { pipeSpeed += PIPE_SPEED_INC; } } // Remove pipes that are off screen if (pipe.x + 400 < -100) { // 400 matches new pipeWidth pipe.destroy(); pipes.splice(i, 1); } } }; // Idle animation: gently bob player up and down before game starts var idleDir = 1; var idleTicks = 0; game.idleInterval = LK.setInterval(function () { if (!gameStarted && !gameOver) { idleTicks++; if (idleTicks % 30 === 0) { idleDir *= -1; } if (typeof swappableAssets !== "undefined") { player = swappableAssets.player; background = swappableAssets.background; ground = swappableAssets.ground; } player.y += idleDir * 2; } }, 16); // Reset game on game over (handled by LK, but for safety) game.onGameOver = function () { gameStarted = false; gameOver = true; if (playButton) { playButton.visible = true; } if (cosmeticsButton) { cosmeticsButton.visible = true; } if (volumeOnButton && volumeOffButton) { if (isVolumeOn) { volumeOnButton.visible = true; volumeOffButton.visible = false; } else { volumeOnButton.visible = false; volumeOffButton.visible = true; } } }; // Reset game on you win (not used, but for completeness) game.onYouWin = function () { gameStarted = false; gameOver = true; if (playButton) { playButton.visible = true; } if (cosmeticsButton) { cosmeticsButton.visible = true; } if (typeof swappableAssets !== "undefined") { player = swappableAssets.player; background = swappableAssets.background; ground = swappableAssets.ground; } if (player) { // Show dead player sprite and keep it visible after you win player.visible = true; } if (volumeOnButton && volumeOffButton) { if (isVolumeOn) { volumeOnButton.visible = true; volumeOffButton.visible = false; } else { volumeOnButton.visible = false; volumeOffButton.visible = true; } } };
===================================================================
--- original.js
+++ change.js
@@ -579,8 +579,11 @@
var volumeBtnHeightOn = volumeBtnWidth * 0.77;
var volumeBtnHeightOff = volumeBtnWidth * 0.98;
var volumeBtnX = 2048 / 2;
var volumeBtnY = 1100 + cosmeticsBtnHeight / 2 + 60 + volumeBtnHeightOn / 2;
+ // Remove old volume buttons before creating new ones to avoid stacking
+ if (oldOnButton && oldOnButton.parent) oldOnButton.parent.removeChild(oldOnButton);
+ if (oldOffButton && oldOffButton.parent) oldOffButton.parent.removeChild(oldOffButton);
volumeOnButton = LK.getAsset(volumeAssets.on, {
width: volumeBtnWidth,
height: volumeBtnHeightOn,
anchorX: 0.5,
@@ -599,10 +602,8 @@
volumeOnButton.visible = isVolumeOn;
volumeOffButton.visible = !isVolumeOn;
game.addChild(volumeOnButton);
game.addChild(volumeOffButton);
- if (oldOnButton && oldOnButton.parent) oldOnButton.parent.removeChild(oldOnButton);
- if (oldOffButton && oldOffButton.parent) oldOffButton.parent.removeChild(oldOffButton);
// Add new assets
if (theme === "dragon") {
// Background
swappableAssets.background = LK.getAsset('backgroundDragon', {
A flat, horizontal ground layer made of bright green grass on top and brown soil underneath, designed in pixel art style. The grass is slightly jagged at the top to suggest texture, and the soil has subtle pixel shading with small rocks and dirt patches. The image should be side-view and seamless, suitable for a 2D side-scrolling game like Flappy Bird, with tiny pixel flowers or varied shades of green for extra detail.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. seamless. ground texture. retro style
A pixel art green pipe bottom section from a side view, designed for a 2D side-scrolling game like Flappy Bird. The pipe is vertically stretched and has a bright green, smooth surface with subtle shading to show depth. The pipe should be closed at the bottom and open at the top, and it should look metallic and cartoonish, consistent with a retro game style.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. retro style. bright colors
A unique pixel art bird character designed for a 2D side-scrolling game. The bird has a round, compact body and large expressive eyes. Its feathers are colorful, with shades of turquoise and orange, and it has small flapping wings. It has a slightly cartoonish look, with a tiny beak and simple outlines. The bird is seen from the side and appears mid-flight, with its wings lifted. The overall design is cute and distinct from Flappy Bird, but still fits in a retro-style arcade game.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. game character. cute. retro style. colorful
A pixel art version of the same bird character shown in a defeated state, designed for a 2D side-scrolling game. The bird appears to be falling downward or lying upside down, with closed or X-shaped eyes and limp wings. Its beak might be slightly open, and its posture should suggest that it is unconscious or dead. The overall style should remain cute and cartoonish, fitting the retro pixel art theme, but clearly indicate that the bird is no longer alive.
A pixel art baby dragon character designed for a 2D side-scrolling game, viewed from the side. The dragon has small wings, a chubby body, and a cute cartoonish face. It has small horns, a short tail, and colorful scales—shades of purple and teal. The dragon is in a flying pose, flapping its wings. Its eyes are big and expressive, and it has tiny fangs showing. The overall design is playful and fantasy-inspired, while still fitting a retro arcade pixel style.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. game character. baby dragon. cute. fantasy. retro style
A pixel art version of the baby dragon character shown in a defeated state, designed for a 2D side-scrolling game. The dragon appears to be falling or lying on its back, with X-shaped eyes or closed eyelids. Its wings are limp and slightly spread, the tail droops, and its mouth is slightly open with a small tongue sticking out. The overall design remains cute and fantasy-inspired, with a cartoonish touch, but clearly shows the dragon is no longer active or alive. The colors and features should match the flying version for consistency.
A small and cute pixel art icon representing sound on, designed for a 2D game UI. The icon shows a colorful, rounded speaker with smiling face and small animated sound waves coming out in bright pastel colors like yellow and light blue. The design is chibi and cartoonish, with soft outlines and playful details. It fits the style of a fun, colorful retro arcade game.. In-Game asset. 2d. High contrast. No shadows. pixel art. cute. ui icon. colorful. retro style. chibi. cartoonish
A small and cute pixel art icon representing sound off, designed for a 2D game UI. The icon shows the same round speaker, but now with a sad or sleepy face and a small red X or mute symbol on it. The sound waves are gone or faded out. The color palette is still colorful, using soft reds and purples. The style is playful, chibi, and pixel art, fitting a cute arcade game interface.
remove the dragon and ground
get only ground
only take "PLAY" button
only take "COSMETICS" button
A flat pixel art button for a 2D retro-style game UI. The button is rectangular with rounded corners and minimal shading. It features the word "BACK" written in large, centered pixel font. The button color should be a clear pastel blue-grey, leaning more towards light blue than grey. The design is clean and simple, with no extra icons, borders, or decorations—just a cozy retro button.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d game ui. flat design. pastel colors. soft light blue. clean. simple. rounded corners. large pixel font. minimal
A decorative pixel art character card frame for a 2D retro-style game, themed around a cute bird world. The card is rectangular with rounded corners and has a pastel-colored background. Each corner includes soft, themed details: A cloud and sun in the top-left, A feather or flying bird in the top-right, Grass or flowers in the bottom-left, A cracked egg in the bottom-right. The center area is left empty for a character sprite to be added later. The overall design is cozy, cute, colorful, and flat—fitting the aesthetic of a peaceful, playful bird-themed game world. Style tags: pixel art, retro, bird theme, character card, cozy, pastel colors, cloud, feather, egg, grass, flowers, soft design, minimal, 2D UI, flat, cute. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. bird theme. character card. cozy. pastel colors. cloud. feather. egg. grass. flowers. soft design. minimal. 2d ui. flat. cute
A pixel art text label for a retro 2D game main menu displaying "HIGH SCORE" in bold uppercase letters. The text is centered, large enough to be easily readable, and uses a pastel light green color. The style is simple, flat, and fits the cozy retro pixel art theme of the game. The text label is static and not interactive.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. text label. pastel green. bold uppercase letters. clear font. minimal. flat design. non-interactive
A pixel art number "5" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A pixel art number "3" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A pixel art number "2" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A pixel art number "1" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A pixel art number "0" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A pixel art number "7" designed for a cozy, cute retro 2D game UI with a bird theme. The number is rendered in soft pastel light green tones to harmonize with the gentle and sweet aesthetic of the game. It has a clean, simple, and rounded pixel style with no harsh edges, fitting perfectly within the pixel art UI style. The number is bold and easily readable at small sizes.. In-Game asset. 2d. High contrast. No shadows. pixel art. retro. 2d ui. number. pastel light green. simple. rounded edges. bold. cute. minimal
A square pixel art character selection frame inspired by a cute baby dragon. The frame includes fantasy elements like tiny dragon horns on the top corners, small claws at the bottom, and subtle flame or smoke decorations curling around the edges. The background inside the frame should have a soft and decorative texture, matching the baby dragon theme, using soft red, orange, and golden tones. The character will be placed on top of this frame later, so leave the center visually calm and not too detailed. The frame should be viewed from the front and designed for a 2D game UI.. In-Game asset. 2d. High contrast. No shadows. pixel art. front view. fantasy. cute. retro. pastel colors. ui element
A single vertical top pipe for a 2D pixel art side-scrolling game with classic Flappy Bird hitbox. The pipe is designed with a dragon theme using red, orange, and gold tones. The pipe surface features subtle dragon scale textures and glowing ember details. Around the opening at the top, there is a stylized flame motif to give a mystical fantasy feel. The pipe is viewed from the side with a clear silhouette suitable for gameplay. The style is cute, retro, and fits a pixel art fantasy game.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. retro. fantasy. dragon theme. red. orange. gold. cute. mystical
A small pixel art dragon head viewed from the side, mouth slightly open as if letting out a small roar. Glowing embers or a little flame is coming out of its mouth to symbolize that sound is on. The style is cute and retro, matching a fantasy-themed 2D game UI icon.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. cute. fantasy. retro. flame. icon. dragon
A small pixel art dragon head viewed from the side, mouth closed with a small puff of smoke or a speech bubble with a cross to symbolize that sound is off. The expression is calm and cute. Designed as a fantasy-themed icon for a retro-style 2D game UI.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. cute. fantasy. retro. dragon. mute. icon
A horizontally-oriented pixel art score frame designed for a cute 2D retro game. The frame is meant to be placed at the top center of the screen during gameplay. It has a soft pastel green or cream background with a rounded rectangular shape. The inside of the frame is filled with a solid light color (not transparent), ready for number assets to be placed on top. The border is subtle and cute, with minimal decorative details like tiny sparkles or stars to match the playful and colorful retro game aesthetic.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. cute. pastel colors. soft edges. retro ui. video game hud. minimal
A horizontally-oriented pixel art score frame designed for a fantasy-themed 2D retro game featuring a baby dragon. The frame is intended to be placed at the top center of the screen during gameplay. It has a rounded rectangular shape with a rich dark red or deep gold background and mystical decorative accents. The inside of the frame is filled with a solid warm color (not transparent) to allow number assets to be placed on top. Small fantasy elements like tiny dragon scales, curved horns, or red lantern motifs can appear on the corners or edges to match the baby dragon theme. The overall look is mystical, cute, and fits a traditional Eastern-inspired fantasy aesthetic.. In-Game asset. 2d. High contrast. No shadows. pixel art. side view. fantasy. retro game. dragon theme. eastern style. cute. rich colors. mystical