User prompt
Didn’t work
User prompt
Fix this problem
User prompt
Why does closing the shop open the game over
User prompt
Closing the shop should bring you back to the main menu
User prompt
The game shouldn’t start when you open the shop
User prompt
Make it so you don’t die after leaving the shop
User prompt
Make the skins cost less
User prompt
Make the skins different assets
User prompt
The white and orange are still changing
User prompt
It still doesn’t work ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
It didn’t work
User prompt
Make the skins not change the colors white and orange
User prompt
Add a skin shop ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Make a skin shop ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Make a start screen
User prompt
Make the seeds spawn more in the middle
User prompt
Make the walls bigger
User prompt
Make the seeds bigger
User prompt
Even bigger
User prompt
Make the seeds bigger
User prompt
Make the spikes bigger
User prompt
Make the spikes bigger
User prompt
Do it again but make the spike blue
User prompt
Make the walls the same color as the spike ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the bottom and top sides kill you
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { selectedSkin: "default", purchasedSkins: ["default"], coins: 0 }); /**** * Classes ****/ var Bird = Container.expand(function () { var self = Container.call(this); // Bird asset var birdGraphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.5, scaleY: 3.5 }); // Bird physics properties self.velocityY = 0; self.velocityX = 12; // Increased from 8 to 12 for faster horizontal movement self.gravity = 1.0; // Increased from 0.7 to 1.0 for stronger gravity self.flapStrength = -20; // Increased from -15 to -20 for higher jumps self.lastX = 0; self.lastY = 0; self.lastWasIntersecting = false; // Handle tap/click on bird self.down = function (x, y, obj) { self.flap(); }; // Make bird flap wings self.flap = function () { self.velocityY = self.flapStrength; }; // Update bird physics self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Apply gravity self.velocityY += self.gravity; // Update position self.y += self.velocityY; self.x += self.velocityX; // Visual feedback - rotate bird based on velocity var targetRotation = Math.min(Math.max(self.velocityY / 15, -0.5), 0.5); // Make bird face the direction it's flying by flipping the sprite if (self.velocityX > 0) { birdGraphics.scaleX = Math.abs(birdGraphics.scaleX); // Face right birdGraphics.rotation = targetRotation; // Apply rotation normally for right-facing bird } else { birdGraphics.scaleX = -Math.abs(birdGraphics.scaleX); // Face left birdGraphics.rotation = -targetRotation; // Invert rotation for left-facing bird } // Rainbow skin special effect if (storage.selectedSkin === 'rainbow') { var hue = LK.ticks * 2 % 360; var r, g, b; var i = Math.floor(hue / 60) % 6; var f = hue / 60 - Math.floor(hue / 60); var v = 1, s = 1; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); switch (i) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } birdGraphics.tint = (Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255); } }; return self; }); var Seed = Container.expand(function () { var self = Container.call(this); // Seed asset var seedGraphics = self.attachAsset('seed', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.5, scaleY: 3.5 }); // Seed properties self.lastWasIntersecting = false; self.speedX = 0; // Set speed to 0 to stop seeds from moving // Animation effect self.update = function () { // No longer updating x position seedGraphics.rotation += 0.05; // Remove seeds that are off-screen if (self.x < -50) { self.shouldBeRemoved = true; } }; return self; }); var SkinItem = Container.expand(function () { var self = Container.call(this); // Background var background = self.attachAsset('shape', { width: 250, height: 250, color: 0x4682B4, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Bird preview var birdPreview = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2.5, x: 0, y: -30 }); // Price or "Selected" text var priceText = new Text2('', { size: 40, fill: 0xFFFFFF }); priceText.anchor.set(0.5, 0.5); priceText.y = 70; self.addChild(priceText); // Properties self.skinId = ''; self.price = 0; self.isSelected = false; self.isPurchased = false; // Set skin data self.setSkin = function (id, price, selected, purchased) { self.skinId = id; self.price = price; self.isSelected = selected; self.isPurchased = purchased; // Apply skin to preview self.applySkinToBird(birdPreview, id); // Update text if (selected) { priceText.setText('SELECTED'); background.tint = 0x00AA00; } else if (purchased) { priceText.setText('OWNED'); background.tint = 0x4682B4; } else { priceText.setText(price + ' COINS'); background.tint = 0x4682B4; } }; // Apply skin appearance to a bird element self.applySkinToBird = function (birdElement, skinId) { // Reset tint first birdElement.tint = 0xFFFFFF; switch (skinId) { case 'red': birdElement.tint = 0xFF5555; break; case 'blue': birdElement.tint = 0x55AAFF; break; case 'green': birdElement.tint = 0x55FF55; break; case 'gold': birdElement.tint = 0xFFD700; break; case 'rainbow': // Rainbow effect will be handled in update break; // Default skin has no tint } }; // Handle tap/click self.down = function () { if (self.onSelect) { self.onSelect(self.skinId, self.price, self.isPurchased); } }; // Update method for animation effects self.update = function () { // Rainbow effect for rainbow skin if (self.skinId === 'rainbow') { var hue = LK.ticks * 2 % 360; var color = self.hsvToRgb(hue / 360, 1, 1); birdPreview.tint = (color.r << 16) + (color.g << 8) + color.b; } // Slight hover animation if (self.isSelected) { background.scaleX = 1 + Math.sin(LK.ticks / 15) * 0.05; background.scaleY = background.scaleX; } }; // HSV to RGB conversion helper self.hsvToRgb = function (h, s, v) { var r, g, b; var i = Math.floor(h * 6); var f = h * 6 - i; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; }; return self; }); var SkinShop = Container.expand(function () { var self = Container.call(this); // Background panel var panel = self.attachAsset('shape', { width: 1800, height: 2200, color: 0x222233, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Title var titleText = new Text2('SKIN SHOP', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 0; titleText.y = -panel.height / 2 + 80; self.addChild(titleText); // Coins display var coinsText = new Text2('COINS: 0', { size: 80, fill: 0xFFDD00 }); coinsText.anchor.set(0.5, 0); coinsText.x = 0; coinsText.y = -panel.height / 2 + 220; self.addChild(coinsText); // Close button var closeButton = new Container(); var closeButtonBg = closeButton.attachAsset('shape', { width: 80, height: 80, color: 0xFF3333, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); var closeText = new Text2('X', { size: 60, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.x = panel.width / 2 - 80; closeButton.y = -panel.height / 2 + 80; self.addChild(closeButton); // Done button var doneButton = new Container(); var doneButtonBg = doneButton.attachAsset('shape', { width: 400, height: 120, color: 0x44AA44, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); var doneText = new Text2('DONE', { size: 70, fill: 0xFFFFFF }); doneText.anchor.set(0.5, 0.5); doneButton.addChild(doneText); doneButton.x = 0; doneButton.y = panel.height / 2 - 100; self.addChild(doneButton); // Skin items container var skinsContainer = new Container(); self.addChild(skinsContainer); skinsContainer.y = 100; // Status message var statusText = new Text2('', { size: 60, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0.5); statusText.y = 500; self.addChild(statusText); // Skin data var skinData = [{ id: 'default', price: 0 }, { id: 'red', price: 50 }, { id: 'blue', price: 100 }, { id: 'green', price: 150 }, { id: 'gold', price: 300 }, { id: 'rainbow', price: 500 }]; // Skin items var skinItems = []; // Initialize self.init = function () { // Update coins display self.updateCoinsDisplay(); // Create skin items self.createSkinItems(); // Add event handlers closeButton.down = doneButton.down = function () { if (self.onClose) { self.onClose(); } }; return self; }; // Create skin item buttons self.createSkinItems = function () { var itemsPerRow = 3; var itemWidth = 300; var itemHeight = 300; var padding = 50; for (var i = 0; i < skinData.length; i++) { var item = new SkinItem(); var row = Math.floor(i / itemsPerRow); var col = i % itemsPerRow; item.x = (col - 1) * (itemWidth + padding); item.y = row * (itemHeight + padding); // Setup skin var skinId = skinData[i].id; var isSelected = storage.selectedSkin === skinId; var isPurchased = storage.purchasedSkins.indexOf(skinId) !== -1; item.setSkin(skinId, skinData[i].price, isSelected, isPurchased); // Setup on select handler item.onSelect = function (skinId, price, purchased) { self.selectSkin(skinId, price, purchased); }; skinsContainer.addChild(item); skinItems.push(item); } }; // Handle skin selection self.selectSkin = function (skinId, price, purchased) { if (purchased) { // Already purchased, just select it storage.selectedSkin = skinId; // Update all skin items self.updateSkinItems(); // Show status message self.showStatus('Skin selected!', 0x44FF44); } else { // Try to purchase if (storage.coins >= price) { // Enough coins, purchase it storage.coins -= price; if (!storage.purchasedSkins) { storage.purchasedSkins = []; } storage.purchasedSkins.push(skinId); storage.selectedSkin = skinId; // Update coins display self.updateCoinsDisplay(); // Update all skin items self.updateSkinItems(); // Show status message self.showStatus('Skin purchased!', 0x44FF44); } else { // Not enough coins self.showStatus('Not enough coins!', 0xFF4444); } } }; // Update all skin items self.updateSkinItems = function () { for (var i = 0; i < skinItems.length; i++) { var item = skinItems[i]; var skinId = item.skinId; var isSelected = storage.selectedSkin === skinId; var isPurchased = storage.purchasedSkins.indexOf(skinId) !== -1; item.setSkin(skinId, item.price, isSelected, isPurchased); } }; // Update coins display self.updateCoinsDisplay = function () { coinsText.setText('COINS: ' + storage.coins); }; // Show status message with animation self.showStatus = function (message, color) { statusText.setText(message); statusText.style.fill = color || 0xFFFFFF; // Animation statusText.alpha = 0; statusText.scale.set(0.5); tween(statusText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); // Hide after delay LK.clearTimeout(self.statusTimeout); self.statusTimeout = LK.setTimeout(function () { tween(statusText, { alpha: 0 }, { duration: 500, easing: tween.easeIn }); }, 2000); }; // Apply selected skin to a bird self.applySkinToBird = function (birdElement) { // Find the skin item with current selected skin for (var i = 0; i < skinItems.length; i++) { if (skinItems[i].skinId === storage.selectedSkin) { // Apply the skin skinItems[i].applySkinToBird(birdElement, storage.selectedSkin); return; } } }; return self; }); var Spike = Container.expand(function () { var self = Container.call(this); // Create spike shape using a triangle var spikeGraphics = self.attachAsset('shape', { width: 200, height: 200, color: 0x0000FF, // Blue color for spike shape: 'box', anchorX: 0.5, anchorY: 0.5 }); // Rotate to make it look like a spike spikeGraphics.rotation = Math.PI / 4; // 45 degrees self.isStuck = false; self.wall = null; self.lastWasIntersecting = false; // Stick to a wall self.stickTo = function (wall) { self.isStuck = true; self.wall = wall; // Position on wall edge based on wall orientation if (wall.isVertical) { self.x = wall.x + (wall.x < 1024 ? 50 : -50); // Left or right wall - adjusted for wider walls // Keep y position where the collision happened } else { self.y = wall.y + (wall.y < 1366 ? 50 : -50); // Top or bottom wall - adjusted for taller walls // Keep x position where the collision happened } }; self.update = function () { // Nothing to update when stuck if (!self.isStuck) { // If not stuck, spike can move or be collected later self.rotation += 0.05; } }; return self; }); var StartScreen = Container.expand(function () { var self = Container.call(this); // Create title text var titleText = new Text2('BOUNCE BIRD', { size: 150, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 2732 / 3; self.addChild(titleText); // Create start button var startButton = new Container(); var buttonBg = startButton.attachAsset('shape', { width: 500, height: 150, color: 0x4682B4, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); var startText = new Text2('TAP TO START', { size: 80, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startButton.addChild(startText); startButton.x = 2048 / 2; startButton.y = 2732 / 2; self.addChild(startButton); // Create shop button var shopButton = new Container(); var shopButtonBg = shopButton.attachAsset('shape', { width: 400, height: 120, color: 0xFFAA00, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); var shopText = new Text2('SHOP', { size: 70, fill: 0xFFFFFF }); shopText.anchor.set(0.5, 0.5); shopButton.addChild(shopText); shopButton.x = 2048 / 2; shopButton.y = 2732 / 2 + 200; self.addChild(shopButton); // Add coins display var coinsText = new Text2('COINS: ' + storage.coins, { size: 60, fill: 0xFFDD00 }); coinsText.anchor.set(0.5, 0.5); coinsText.x = 2048 / 2; coinsText.y = 2732 / 2 + 320; self.addChild(coinsText); // Shop button tap handler shopButton.down = function () { if (self.onShop) { self.onShop(); } }; // Add a bouncing bird animation var demoBird = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 4, x: 2048 / 2, y: 2732 * 0.7 }); // Make the button pulse self.update = function () { var scale = 1 + Math.sin(LK.ticks / 20) * 0.05; startButton.scale.set(scale); // Make the bird bounce demoBird.y = 2732 * 0.7 + Math.sin(LK.ticks / 15) * 50; demoBird.rotation = Math.sin(LK.ticks / 30) * 0.2; }; // Handle tap event self.down = function (x, y, obj) { // Let individual buttons handle their own events if (obj.target && obj.target.down) { return; } // Default to start game if tap is not on a specific button if (self.onStart) { self.onStart(); } }; return self; }); var Wall = Container.expand(function () { var self = Container.call(this); // Wall properties self.isVertical = true; self.wallGraphics = null; // Initialize with wall type (vertical/horizontal) self.init = function (vertical) { self.isVertical = vertical; if (vertical) { self.wallGraphics = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); } else { self.wallGraphics = self.attachAsset('ceiling', { anchorX: 0.5, anchorY: 0.5 }); } return self; }; return self; }); /**** * Initialize Game ****/ // Change background color to sky blue var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Change background color to sky blue // Assets for Bounce Bird // Import tween plugin game.setBackgroundColor(0x87CEEB); // Game variables var bird; var walls = []; var seeds = []; var spikes = []; var score = 0; var gameWidth = 2048; var gameHeight = 2732; var gameStarted = false; var startScreen; var skinShop; var shopOpen = false; // Create start screen function showStartScreen() { startScreen = new StartScreen(); startScreen.onStart = function () { gameStarted = true; startScreen.destroy(); startScreen = null; startGame(); }; startScreen.onShop = function () { showSkinShop(); }; game.addChild(startScreen); } // Show skin shop function showSkinShop() { if (!skinShop) { skinShop = new SkinShop().init(); skinShop.x = gameWidth / 2; skinShop.y = gameHeight / 2; skinShop.onClose = function () { shopOpen = false; game.removeChild(skinShop); // Update start screen with new coin amount if (startScreen) { startScreen.children.forEach(function (child) { if (child instanceof Text2 && child.text.indexOf('COINS:') === 0) { child.setText('COINS: ' + storage.coins); } }); } // Apply skin to bird if in game if (bird) { skinShop.applySkinToBird(bird.children[0]); } }; } shopOpen = true; game.addChild(skinShop); } // Initialize the actual game function startGame() { createBird(); createWalls(); createScoreDisplay(); } // Create score text var scoreText; function createScoreDisplay() { scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); scoreText.x = 120; // Avoid the top-left 100x100 menu area scoreText.y = 50; } // Create bird function createBird() { bird = new Bird(); bird.x = gameWidth / 4; bird.y = gameHeight / 2; game.addChild(bird); // Apply selected skin to bird if (skinShop) { skinShop.applySkinToBird(bird.children[0]); } else { // Apply skin directly if shop isn't created yet var skinId = storage.selectedSkin || "default"; if (skinId === "default") { bird.children[0].tint = 0xFFFFFF; } else if (skinId === "red") { bird.children[0].tint = 0xFF5555; } else if (skinId === "blue") { bird.children[0].tint = 0x55AAFF; } else if (skinId === "green") { bird.children[0].tint = 0x55FF55; } else if (skinId === "gold") { bird.children[0].tint = 0xFFD700; } } } // Create walls (top, bottom, left, right) function createWalls() { // Top wall (ceiling) var ceiling = new Wall().init(false); ceiling.x = gameWidth / 2; ceiling.y = 40; game.addChild(ceiling); walls.push(ceiling); // Bottom wall (floor) var floor = new Wall().init(false); floor.x = gameWidth / 2; floor.y = gameHeight - 40; game.addChild(floor); walls.push(floor); // Left wall var leftWall = new Wall().init(true); leftWall.x = 40; leftWall.y = gameHeight / 2; game.addChild(leftWall); walls.push(leftWall); // Right wall var rightWall = new Wall().init(true); rightWall.x = gameWidth - 40; rightWall.y = gameHeight / 2; game.addChild(rightWall); walls.push(rightWall); } // Show start screen instead of immediately starting the game showStartScreen(); // Spawn a new seed at a random position function spawnSeed() { var seed = new Seed(); seed.x = gameWidth + 50; seed.y = Math.random() * (gameHeight - 200) + 100; seeds.push(seed); game.addChild(seed); } // Handle click/tap anywhere on screen game.down = function (x, y, obj) { // Don't handle taps if shop is open if (shopOpen) { return; } if (gameStarted && bird) { bird.flap(); } }; // Update function game.update = function () { // Don't process game logic if game hasn't started yet or shop is open if (!gameStarted || shopOpen) { return; } // Seeds now spawn on bounce, not periodically // Update seeds for (var i = seeds.length - 1; i >= 0; i--) { var seed = seeds[i]; // Check for collision with bird var currentIntersecting = bird.intersects(seed); if (!seed.lastWasIntersecting && currentIntersecting) { // Collected seed score++; // Give coins for collecting seeds storage.coins++; scoreText.setText("Score: " + score); LK.setScore(score); LK.getSound('collect').play(); // Remove seed seed.destroy(); seeds.splice(i, 1); } else { seed.lastWasIntersecting = currentIntersecting; // Remove seeds that should be removed if (seed.shouldBeRemoved) { seed.destroy(); seeds.splice(i, 1); } } } // Check for wall collisions for (var i = 0; i < walls.length; i++) { var wall = walls[i]; var currentIntersecting = bird.intersects(wall); if (!bird.lastWasIntersecting && currentIntersecting) { // Check if bird hit ceiling or floor (horizontal walls) if (!wall.isVertical) { // Bird hit ceiling or floor - game over! LK.effects.flashScreen(0xFF0000, 500); LK.showGameOver(); break; } else { // Bird hit a side wall - bounce! LK.getSound('bounce').play(); // Apply bounce physics bird.velocityX *= -1; // Reverse horizontal direction // Push bird away from wall to prevent sticking bird.x += bird.velocityX > 0 ? 5 : -5; // Visual feedback for bounce LK.effects.flashObject(bird, 0xFFFFFF, 200); // Clear old seeds and spikes on bounce for (var j = seeds.length - 1; j >= 0; j--) { seeds[j].destroy(); seeds.splice(j, 1); } // Clear all existing spikes for (var j = spikes.length - 1; j >= 0; j--) { spikes[j].destroy(); spikes.splice(j, 1); } // Reset all wall colors to the original blue color for (var j = 0; j < walls.length; j++) { if (walls[j].isVertical) { tween(walls[j].wallGraphics, { tint: 0x4682b4 }, { duration: 300, easing: tween.easeIn }); } } // Spawn two new seeds on bounce for (var k = 0; k < 2; k++) { var newSeed = new Seed(); // Make seeds spawn more in the middle - use narrower range centered around the middle var middleX = gameWidth / 2; var middleY = gameHeight / 2; var spawnWidth = gameWidth * 0.6; // Use 60% of screen width var spawnHeight = gameHeight * 0.6; // Use 60% of screen height newSeed.x = middleX + (Math.random() - 0.5) * spawnWidth; newSeed.y = middleY + (Math.random() - 0.5) * spawnHeight; seeds.push(newSeed); game.addChild(newSeed); } // Add a spike that sticks to the opposite wall var spike = new Spike(); // Place spike on opposite vertical wall targetWall = wall.x < gameWidth / 2 ? walls[3] : walls[2]; // walls[3] is right wall, walls[2] is left wall spike.x = targetWall.x; spike.y = Math.random() * (gameHeight - 200) + 100; // Random Y position spike.stickTo(targetWall); spikes.push(spike); game.addChild(spike); // Change the target wall color to match the spike color (blue) tween(targetWall.wallGraphics, { tint: 0x0000FF }, { duration: 300, easing: tween.easeOut }); } // Set lastWasIntersecting for the specific wall collision that just happened bird.lastWasIntersecting = true; break; // Exit the loop after handling a collision } } // Reset lastWasIntersecting if not intersecting any wall var intersectingAnyWall = false; for (var i = 0; i < walls.length; i++) { if (bird.intersects(walls[i])) { intersectingAnyWall = true; break; } } if (!intersectingAnyWall) { bird.lastWasIntersecting = false; } // Check for spike collisions for (var i = 0; i < spikes.length; i++) { var spike = spikes[i]; var currentIntersecting = bird.intersects(spike); if (!spike.lastWasIntersecting && currentIntersecting) { // Bird hit a spike - game over! LK.effects.flashScreen(0xFF0000, 500); LK.showGameOver(); break; } spike.lastWasIntersecting = currentIntersecting; } // Check if bird flew off screen (game over condition) if (bird.y < -100 || bird.y > gameHeight + 100 || bird.x < -100 || bird.x > gameWidth + 100) { LK.effects.flashScreen(0xFF0000, 500); LK.showGameOver(); } };
===================================================================
--- original.js
+++ change.js
@@ -1,8 +1,13 @@
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ selectedSkin: "default",
+ purchasedSkins: ["default"],
+ coins: 0
+});
/****
* Classes
****/
@@ -50,8 +55,53 @@
} else {
birdGraphics.scaleX = -Math.abs(birdGraphics.scaleX); // Face left
birdGraphics.rotation = -targetRotation; // Invert rotation for left-facing bird
}
+ // Rainbow skin special effect
+ if (storage.selectedSkin === 'rainbow') {
+ var hue = LK.ticks * 2 % 360;
+ var r, g, b;
+ var i = Math.floor(hue / 60) % 6;
+ var f = hue / 60 - Math.floor(hue / 60);
+ var v = 1,
+ s = 1;
+ var p = v * (1 - s);
+ var q = v * (1 - f * s);
+ var t = v * (1 - (1 - f) * s);
+ switch (i) {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = v;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = v;
+ break;
+ case 5:
+ r = v;
+ g = p;
+ b = q;
+ break;
+ }
+ birdGraphics.tint = (Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255);
+ }
};
return self;
});
var Seed = Container.expand(function () {
@@ -76,8 +126,376 @@
}
};
return self;
});
+var SkinItem = Container.expand(function () {
+ var self = Container.call(this);
+ // Background
+ var background = self.attachAsset('shape', {
+ width: 250,
+ height: 250,
+ color: 0x4682B4,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Bird preview
+ var birdPreview = self.attachAsset('bird', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 2.5,
+ scaleY: 2.5,
+ x: 0,
+ y: -30
+ });
+ // Price or "Selected" text
+ var priceText = new Text2('', {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ priceText.anchor.set(0.5, 0.5);
+ priceText.y = 70;
+ self.addChild(priceText);
+ // Properties
+ self.skinId = '';
+ self.price = 0;
+ self.isSelected = false;
+ self.isPurchased = false;
+ // Set skin data
+ self.setSkin = function (id, price, selected, purchased) {
+ self.skinId = id;
+ self.price = price;
+ self.isSelected = selected;
+ self.isPurchased = purchased;
+ // Apply skin to preview
+ self.applySkinToBird(birdPreview, id);
+ // Update text
+ if (selected) {
+ priceText.setText('SELECTED');
+ background.tint = 0x00AA00;
+ } else if (purchased) {
+ priceText.setText('OWNED');
+ background.tint = 0x4682B4;
+ } else {
+ priceText.setText(price + ' COINS');
+ background.tint = 0x4682B4;
+ }
+ };
+ // Apply skin appearance to a bird element
+ self.applySkinToBird = function (birdElement, skinId) {
+ // Reset tint first
+ birdElement.tint = 0xFFFFFF;
+ switch (skinId) {
+ case 'red':
+ birdElement.tint = 0xFF5555;
+ break;
+ case 'blue':
+ birdElement.tint = 0x55AAFF;
+ break;
+ case 'green':
+ birdElement.tint = 0x55FF55;
+ break;
+ case 'gold':
+ birdElement.tint = 0xFFD700;
+ break;
+ case 'rainbow':
+ // Rainbow effect will be handled in update
+ break;
+ // Default skin has no tint
+ }
+ };
+ // Handle tap/click
+ self.down = function () {
+ if (self.onSelect) {
+ self.onSelect(self.skinId, self.price, self.isPurchased);
+ }
+ };
+ // Update method for animation effects
+ self.update = function () {
+ // Rainbow effect for rainbow skin
+ if (self.skinId === 'rainbow') {
+ var hue = LK.ticks * 2 % 360;
+ var color = self.hsvToRgb(hue / 360, 1, 1);
+ birdPreview.tint = (color.r << 16) + (color.g << 8) + color.b;
+ }
+ // Slight hover animation
+ if (self.isSelected) {
+ background.scaleX = 1 + Math.sin(LK.ticks / 15) * 0.05;
+ background.scaleY = background.scaleX;
+ }
+ };
+ // HSV to RGB conversion helper
+ self.hsvToRgb = function (h, s, v) {
+ var r, g, b;
+ var i = Math.floor(h * 6);
+ var f = h * 6 - i;
+ var p = v * (1 - s);
+ var q = v * (1 - f * s);
+ var t = v * (1 - (1 - f) * s);
+ switch (i % 6) {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = v;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = v;
+ break;
+ case 5:
+ r = v;
+ g = p;
+ b = q;
+ break;
+ }
+ return {
+ r: Math.round(r * 255),
+ g: Math.round(g * 255),
+ b: Math.round(b * 255)
+ };
+ };
+ return self;
+});
+var SkinShop = Container.expand(function () {
+ var self = Container.call(this);
+ // Background panel
+ var panel = self.attachAsset('shape', {
+ width: 1800,
+ height: 2200,
+ color: 0x222233,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Title
+ var titleText = new Text2('SKIN SHOP', {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ titleText.anchor.set(0.5, 0);
+ titleText.x = 0;
+ titleText.y = -panel.height / 2 + 80;
+ self.addChild(titleText);
+ // Coins display
+ var coinsText = new Text2('COINS: 0', {
+ size: 80,
+ fill: 0xFFDD00
+ });
+ coinsText.anchor.set(0.5, 0);
+ coinsText.x = 0;
+ coinsText.y = -panel.height / 2 + 220;
+ self.addChild(coinsText);
+ // Close button
+ var closeButton = new Container();
+ var closeButtonBg = closeButton.attachAsset('shape', {
+ width: 80,
+ height: 80,
+ color: 0xFF3333,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var closeText = new Text2('X', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ closeText.anchor.set(0.5, 0.5);
+ closeButton.addChild(closeText);
+ closeButton.x = panel.width / 2 - 80;
+ closeButton.y = -panel.height / 2 + 80;
+ self.addChild(closeButton);
+ // Done button
+ var doneButton = new Container();
+ var doneButtonBg = doneButton.attachAsset('shape', {
+ width: 400,
+ height: 120,
+ color: 0x44AA44,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var doneText = new Text2('DONE', {
+ size: 70,
+ fill: 0xFFFFFF
+ });
+ doneText.anchor.set(0.5, 0.5);
+ doneButton.addChild(doneText);
+ doneButton.x = 0;
+ doneButton.y = panel.height / 2 - 100;
+ self.addChild(doneButton);
+ // Skin items container
+ var skinsContainer = new Container();
+ self.addChild(skinsContainer);
+ skinsContainer.y = 100;
+ // Status message
+ var statusText = new Text2('', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ statusText.anchor.set(0.5, 0.5);
+ statusText.y = 500;
+ self.addChild(statusText);
+ // Skin data
+ var skinData = [{
+ id: 'default',
+ price: 0
+ }, {
+ id: 'red',
+ price: 50
+ }, {
+ id: 'blue',
+ price: 100
+ }, {
+ id: 'green',
+ price: 150
+ }, {
+ id: 'gold',
+ price: 300
+ }, {
+ id: 'rainbow',
+ price: 500
+ }];
+ // Skin items
+ var skinItems = [];
+ // Initialize
+ self.init = function () {
+ // Update coins display
+ self.updateCoinsDisplay();
+ // Create skin items
+ self.createSkinItems();
+ // Add event handlers
+ closeButton.down = doneButton.down = function () {
+ if (self.onClose) {
+ self.onClose();
+ }
+ };
+ return self;
+ };
+ // Create skin item buttons
+ self.createSkinItems = function () {
+ var itemsPerRow = 3;
+ var itemWidth = 300;
+ var itemHeight = 300;
+ var padding = 50;
+ for (var i = 0; i < skinData.length; i++) {
+ var item = new SkinItem();
+ var row = Math.floor(i / itemsPerRow);
+ var col = i % itemsPerRow;
+ item.x = (col - 1) * (itemWidth + padding);
+ item.y = row * (itemHeight + padding);
+ // Setup skin
+ var skinId = skinData[i].id;
+ var isSelected = storage.selectedSkin === skinId;
+ var isPurchased = storage.purchasedSkins.indexOf(skinId) !== -1;
+ item.setSkin(skinId, skinData[i].price, isSelected, isPurchased);
+ // Setup on select handler
+ item.onSelect = function (skinId, price, purchased) {
+ self.selectSkin(skinId, price, purchased);
+ };
+ skinsContainer.addChild(item);
+ skinItems.push(item);
+ }
+ };
+ // Handle skin selection
+ self.selectSkin = function (skinId, price, purchased) {
+ if (purchased) {
+ // Already purchased, just select it
+ storage.selectedSkin = skinId;
+ // Update all skin items
+ self.updateSkinItems();
+ // Show status message
+ self.showStatus('Skin selected!', 0x44FF44);
+ } else {
+ // Try to purchase
+ if (storage.coins >= price) {
+ // Enough coins, purchase it
+ storage.coins -= price;
+ if (!storage.purchasedSkins) {
+ storage.purchasedSkins = [];
+ }
+ storage.purchasedSkins.push(skinId);
+ storage.selectedSkin = skinId;
+ // Update coins display
+ self.updateCoinsDisplay();
+ // Update all skin items
+ self.updateSkinItems();
+ // Show status message
+ self.showStatus('Skin purchased!', 0x44FF44);
+ } else {
+ // Not enough coins
+ self.showStatus('Not enough coins!', 0xFF4444);
+ }
+ }
+ };
+ // Update all skin items
+ self.updateSkinItems = function () {
+ for (var i = 0; i < skinItems.length; i++) {
+ var item = skinItems[i];
+ var skinId = item.skinId;
+ var isSelected = storage.selectedSkin === skinId;
+ var isPurchased = storage.purchasedSkins.indexOf(skinId) !== -1;
+ item.setSkin(skinId, item.price, isSelected, isPurchased);
+ }
+ };
+ // Update coins display
+ self.updateCoinsDisplay = function () {
+ coinsText.setText('COINS: ' + storage.coins);
+ };
+ // Show status message with animation
+ self.showStatus = function (message, color) {
+ statusText.setText(message);
+ statusText.style.fill = color || 0xFFFFFF;
+ // Animation
+ statusText.alpha = 0;
+ statusText.scale.set(0.5);
+ tween(statusText, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ // Hide after delay
+ LK.clearTimeout(self.statusTimeout);
+ self.statusTimeout = LK.setTimeout(function () {
+ tween(statusText, {
+ alpha: 0
+ }, {
+ duration: 500,
+ easing: tween.easeIn
+ });
+ }, 2000);
+ };
+ // Apply selected skin to a bird
+ self.applySkinToBird = function (birdElement) {
+ // Find the skin item with current selected skin
+ for (var i = 0; i < skinItems.length; i++) {
+ if (skinItems[i].skinId === storage.selectedSkin) {
+ // Apply the skin
+ skinItems[i].applySkinToBird(birdElement, storage.selectedSkin);
+ return;
+ }
+ }
+ };
+ return self;
+});
var Spike = Container.expand(function () {
var self = Container.call(this);
// Create spike shape using a triangle
var spikeGraphics = self.attachAsset('shape', {
@@ -145,8 +563,42 @@
startButton.addChild(startText);
startButton.x = 2048 / 2;
startButton.y = 2732 / 2;
self.addChild(startButton);
+ // Create shop button
+ var shopButton = new Container();
+ var shopButtonBg = shopButton.attachAsset('shape', {
+ width: 400,
+ height: 120,
+ color: 0xFFAA00,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var shopText = new Text2('SHOP', {
+ size: 70,
+ fill: 0xFFFFFF
+ });
+ shopText.anchor.set(0.5, 0.5);
+ shopButton.addChild(shopText);
+ shopButton.x = 2048 / 2;
+ shopButton.y = 2732 / 2 + 200;
+ self.addChild(shopButton);
+ // Add coins display
+ var coinsText = new Text2('COINS: ' + storage.coins, {
+ size: 60,
+ fill: 0xFFDD00
+ });
+ coinsText.anchor.set(0.5, 0.5);
+ coinsText.x = 2048 / 2;
+ coinsText.y = 2732 / 2 + 320;
+ self.addChild(coinsText);
+ // Shop button tap handler
+ shopButton.down = function () {
+ if (self.onShop) {
+ self.onShop();
+ }
+ };
// Add a bouncing bird animation
var demoBird = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5,
@@ -163,9 +615,14 @@
demoBird.y = 2732 * 0.7 + Math.sin(LK.ticks / 15) * 50;
demoBird.rotation = Math.sin(LK.ticks / 30) * 0.2;
};
// Handle tap event
- self.down = function () {
+ self.down = function (x, y, obj) {
+ // Let individual buttons handle their own events
+ if (obj.target && obj.target.down) {
+ return;
+ }
+ // Default to start game if tap is not on a specific button
if (self.onStart) {
self.onStart();
}
};
@@ -219,8 +676,10 @@
var gameWidth = 2048;
var gameHeight = 2732;
var gameStarted = false;
var startScreen;
+var skinShop;
+var shopOpen = false;
// Create start screen
function showStartScreen() {
startScreen = new StartScreen();
startScreen.onStart = function () {
@@ -228,10 +687,39 @@
startScreen.destroy();
startScreen = null;
startGame();
};
+ startScreen.onShop = function () {
+ showSkinShop();
+ };
game.addChild(startScreen);
}
+// Show skin shop
+function showSkinShop() {
+ if (!skinShop) {
+ skinShop = new SkinShop().init();
+ skinShop.x = gameWidth / 2;
+ skinShop.y = gameHeight / 2;
+ skinShop.onClose = function () {
+ shopOpen = false;
+ game.removeChild(skinShop);
+ // Update start screen with new coin amount
+ if (startScreen) {
+ startScreen.children.forEach(function (child) {
+ if (child instanceof Text2 && child.text.indexOf('COINS:') === 0) {
+ child.setText('COINS: ' + storage.coins);
+ }
+ });
+ }
+ // Apply skin to bird if in game
+ if (bird) {
+ skinShop.applySkinToBird(bird.children[0]);
+ }
+ };
+ }
+ shopOpen = true;
+ game.addChild(skinShop);
+}
// Initialize the actual game
function startGame() {
createBird();
createWalls();
@@ -254,8 +742,26 @@
bird = new Bird();
bird.x = gameWidth / 4;
bird.y = gameHeight / 2;
game.addChild(bird);
+ // Apply selected skin to bird
+ if (skinShop) {
+ skinShop.applySkinToBird(bird.children[0]);
+ } else {
+ // Apply skin directly if shop isn't created yet
+ var skinId = storage.selectedSkin || "default";
+ if (skinId === "default") {
+ bird.children[0].tint = 0xFFFFFF;
+ } else if (skinId === "red") {
+ bird.children[0].tint = 0xFF5555;
+ } else if (skinId === "blue") {
+ bird.children[0].tint = 0x55AAFF;
+ } else if (skinId === "green") {
+ bird.children[0].tint = 0x55FF55;
+ } else if (skinId === "gold") {
+ bird.children[0].tint = 0xFFD700;
+ }
+ }
}
// Create walls (top, bottom, left, right)
function createWalls() {
// Top wall (ceiling)
@@ -294,16 +800,20 @@
game.addChild(seed);
}
// Handle click/tap anywhere on screen
game.down = function (x, y, obj) {
+ // Don't handle taps if shop is open
+ if (shopOpen) {
+ return;
+ }
if (gameStarted && bird) {
bird.flap();
}
};
// Update function
game.update = function () {
- // Don't process game logic if game hasn't started yet
- if (!gameStarted) {
+ // Don't process game logic if game hasn't started yet or shop is open
+ if (!gameStarted || shopOpen) {
return;
}
// Seeds now spawn on bounce, not periodically
// Update seeds
@@ -313,8 +823,10 @@
var currentIntersecting = bird.intersects(seed);
if (!seed.lastWasIntersecting && currentIntersecting) {
// Collected seed
score++;
+ // Give coins for collecting seeds
+ storage.coins++;
scoreText.setText("Score: " + score);
LK.setScore(score);
LK.getSound('collect').play();
// Remove seed
Big sunflower seed. In-Game asset. 2d. High contrast. No shadows
Square shaped gold bird. In-Game asset. 2d. High contrast. No shadows
Square shaped green bird facing to the right. In-Game asset. 2d. High contrast. No shadows
Square shaped orange bird facing right
Square shaped red bird facing right. In-Game asset. 2d. High contrast. No shadows
Square shaped rainbow bird facing right. In-Game asset. 2d. High contrast. No shadows