/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Track if continue has been used in current session var Bird = Container.expand(function () { var self = Container.call(this); var birdGraphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = 0; self.gravity = 0.8; self.flapStrength = -12; self.maxFallSpeed = 15; self.rotation = 0; self.flap = function () { self.velocity = self.flapStrength; LK.getSound('flap').play(); // Animate bird flap tween(birdGraphics, { rotation: -0.3 }, { duration: 150 }); tween(birdGraphics, { rotation: 0 }, { duration: 150, onFinish: function onFinish() { if (self.velocity > 0) { tween(birdGraphics, { rotation: 0.3 }, { duration: 200 }); } } }); }; self.update = function () { // Don't update bird physics if game hasn't started if (!gameStarted) { return; } // Apply gravity self.velocity += self.gravity; if (self.velocity > self.maxFallSpeed) { self.velocity = self.maxFallSpeed; } // Update position self.y += self.velocity; // Update rotation based on velocity with falling effect var targetRotation = Math.min(Math.max(self.velocity * 0.05, -0.5), 0.8); // Add dramatic falling effect when bird is falling fast if (self.velocity > 8) { // Create falling spin effect tween(birdGraphics, { rotation: targetRotation + Math.PI * 2 }, { duration: 800, easing: tween.easeIn }); // Add slight scale effect during fall tween(birdGraphics, { scaleX: 0.9, scaleY: 1.1 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(birdGraphics, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } else { // Normal rotation for regular movement birdGraphics.rotation = targetRotation; } }; return self; }); var Chicken = Container.expand(function () { var self = Container.call(this); var chickenGraphics = self.attachAsset('chicken', { anchorX: 0.5, anchorY: 1 }); self.speed = -4; self.baseY = 0; self.pecking = false; self.update = function () { self.x += self.speed; // Chicken walking animation - quick and jerky movements var walkCycle = LK.ticks * 0.25; // Fast walking // Quick head bobbing motion self.y = self.baseY + Math.sin(walkCycle) * 1; // Head jerking motion characteristic of chickens chickenGraphics.x = Math.sin(walkCycle * 0.8) * 0.5; // Periodic pecking animation if (LK.ticks % 120 === 0) { self.pecking = !self.pecking; } // Quick stepping animation every 10 frames for rapid chicken steps if (LK.ticks % 10 === 0) { var stepDirection = Math.floor(LK.ticks / 10) % 2 * 2 - 1; tween(chickenGraphics, { scaleY: 0.95, scaleX: 1.05, y: stepDirection * 0.3, rotation: stepDirection * 0.05 }, { duration: 50, easing: tween.easeOut, onFinish: function onFinish() { tween(chickenGraphics, { scaleY: 1, scaleX: 1, y: 0, rotation: 0 }, { duration: 50, easing: tween.easeIn }); } }); } // Enhanced pecking motion when pecking if (self.pecking) { chickenGraphics.y = Math.sin(LK.ticks * 0.3) * 2; } }; return self; }); // Cloud class removed var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -4; self.collected = false; self.rotationSpeed = 0.1; self.update = function () { self.x += self.speed; // Rotate coin for visual appeal coinGraphics.rotation += self.rotationSpeed; // Gentle floating animation coinGraphics.y = Math.sin(LK.ticks * 0.05) * 3; }; return self; }); var Cow = Container.expand(function () { var self = Container.call(this); var cowGraphics = self.attachAsset('cow', { anchorX: 0.5, anchorY: 1 }); self.speed = -4; // Add some black spots for cow appearance self.baseY = 0; self.update = function () { self.x += self.speed; // Proper walking animation with realistic bobbing var walkCycle = LK.ticks * 0.15; // Walking speed // Vertical bobbing motion - more pronounced and realistic self.y = self.baseY + Math.sin(walkCycle) * 2; // Subtle horizontal body sway cowGraphics.x = Math.sin(walkCycle * 0.5) * 1; // Body tilt during walking cowGraphics.rotation = Math.sin(walkCycle) * 0.05; // Step-based animation every 20 frames for more frequent steps if (LK.ticks % 20 === 0) { // Alternating leg movement effect var stepDirection = Math.floor(LK.ticks / 20) % 2 * 2 - 1; // -1 or 1 // Step effect with body compression and extension tween(cowGraphics, { scaleY: 0.95, scaleX: 1.05, y: stepDirection * 1 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(cowGraphics, { scaleY: 1, scaleX: 1, y: 0 }, { duration: 100, easing: tween.easeIn }); } }); } }; return self; }); var Farm = Container.expand(function () { var self = Container.call(this); var farmGraphics = self.attachAsset('farmGround', { anchorX: 0, anchorY: 0 }); self.speed = -4; self.update = function () { self.x += self.speed; }; return self; }); var Pig = Container.expand(function () { var self = Container.call(this); var pigGraphics = self.attachAsset('pig', { anchorX: 0.5, anchorY: 1 }); self.speed = -4; self.baseY = 0; self.update = function () { self.x += self.speed; // Pig walking animation - heavier and slower var walkCycle = LK.ticks * 0.12; // Slower walking // Heavy bobbing motion self.y = self.baseY + Math.sin(walkCycle) * 1.2; // Wide body sway for heavier appearance pigGraphics.x = Math.sin(walkCycle * 0.3) * 1.5; // Heavy stepping animation every 25 frames if (LK.ticks % 25 === 0) { var stepDirection = Math.floor(LK.ticks / 25) % 2 * 2 - 1; tween(pigGraphics, { scaleY: 0.92, scaleX: 1.08, y: stepDirection * 0.8 }, { duration: 125, easing: tween.easeOut, onFinish: function onFinish() { tween(pigGraphics, { scaleY: 1, scaleX: 1, y: 0 }, { duration: 125, easing: tween.easeIn }); } }); } }; return self; }); var Pipe = Container.expand(function () { var self = Container.call(this); self.speed = -4; self.passed = false; self.gapSize = 450; // Create top pipe self.topPipe = self.attachAsset('pipe', { anchorX: 0.5, anchorY: 1 }); // Create top pipe segment (Mario-style cap) self.topPipeSegment = self.attachAsset('pipeSegment', { anchorX: 0.5, anchorY: 1 }); // Create bottom pipe self.bottomPipe = self.attachAsset('pipe', { anchorX: 0.5, anchorY: 0 }); // Create bottom pipe segment (Mario-style cap) self.bottomPipeSegment = self.attachAsset('pipeSegment', { anchorX: 0.5, anchorY: 0 }); self.setGapPosition = function (gapY) { self.topPipe.y = gapY - self.gapSize / 2; self.bottomPipe.y = gapY + self.gapSize / 2; // Position the Mario-style pipe segments self.topPipeSegment.y = gapY - self.gapSize / 2; self.bottomPipeSegment.y = gapY + self.gapSize / 2; }; self.update = function () { self.x += self.speed; }; return self; }); var Sheep = Container.expand(function () { var self = Container.call(this); var sheepGraphics = self.attachAsset('sheep', { anchorX: 0.5, anchorY: 1 }); self.speed = -4; self.baseY = 0; self.update = function () { self.x += self.speed; // Sheep walking animation - lighter and bouncier than cows var walkCycle = LK.ticks * 0.18; // Slightly faster walking // Bouncy vertical movement self.y = self.baseY + Math.sin(walkCycle) * 1.5; // Gentle body sway sheepGraphics.x = Math.sin(walkCycle * 0.4) * 0.8; // Light stepping animation every 15 frames for quicker steps if (LK.ticks % 15 === 0) { var stepDirection = Math.floor(LK.ticks / 15) % 2 * 2 - 1; tween(sheepGraphics, { scaleY: 0.98, scaleX: 1.02, y: stepDirection * 0.5 }, { duration: 75, easing: tween.easeOut, onFinish: function onFinish() { tween(sheepGraphics, { scaleY: 1, scaleX: 1, y: 0 }, { duration: 75, easing: tween.easeIn }); } }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4a90e2 }); /**** * Game Code ****/ // Game variables // Cloud asset removed // Sky gradient assets removed var continueUsed = false; var bird; var pipes = []; var ground; var gameStarted = false; var gameSpeed = 4; var pipeSpawnTimer = 0; var pipeSpawnInterval = 180; // frames between pipe spawns var lastPipeScore = 0; var coins = []; var coinSpawnTimer = 0; var coinSpawnInterval = 200; // frames between coin spawns - slightly after pipes // Cloud spawning removed var farms = []; var farmSpawnTimer = 0; var farmSpawnInterval = 400; // frames between farm spawns var animals = []; var animalSpawnTimer = 0; var animalSpawnInterval = 150; // frames between animal spawns // Sky gradient layers removed // Health system variables var maxHealth = 3; var currentHealth = 3; var healthBar; var healthBarBg; // UI elements var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var instructionTxt = new Text2('Tap to Flap!', { size: 60, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionTxt); // Days counter display var daysTxt = new Text2('Days: 0', { size: 50, fill: 0xFFFFFF }); daysTxt.anchor.set(0, 0); daysTxt.x = 20; daysTxt.y = 70; LK.gui.topLeft.addChild(daysTxt); // Start menu UI elements var showStartMenu = true; var titleTxt = new Text2('Mutili Bird', { size: 120, fill: 0xFFD700 }); titleTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(titleTxt); var startButtonTxt = new Text2('TAP TO START', { size: 80, fill: 0x00FF00 }); startButtonTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(startButtonTxt); // Position menu elements titleTxt.y = -200; startButtonTxt.y = 100; // Add pulsing animation to start button tween(startButtonTxt, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(startButtonTxt, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut }); } }); // Set interval for continuous button pulsing var buttonPulseTimer = LK.setInterval(function () { if (showStartMenu) { tween(startButtonTxt, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(startButtonTxt, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut }); } }); } }, 1600); // Create health bar healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0 }); healthBarBg.x = 150; healthBarBg.y = 20; LK.gui.topLeft.addChild(healthBarBg); healthBar = LK.getAsset('healthBarFill', { anchorX: 0, anchorY: 0 }); healthBar.x = 150; healthBar.y = 20; LK.gui.topLeft.addChild(healthBar); // Create bird bird = game.addChild(new Bird()); bird.x = 400; bird.y = 1366; // Center of screen height // Initialize health system currentHealth = maxHealth; updateHealthBar(); // Hide game UI initially scoreTxt.alpha = 0; instructionTxt.alpha = 0; healthBarBg.alpha = 0; healthBar.alpha = 0; daysTxt.alpha = 0; // Create ground ground = game.addChild(LK.getAsset('ground', { anchorX: 0, anchorY: 0 })); ground.x = 0; ground.y = 2732 - 100; // Bottom of screen // Game state tracking var lastBirdY = bird.y; var lastGroundCollision = false; var lastCeilingCollision = false; function spawnPipe() { var pipe = new Pipe(); pipe.x = 2048 + 60; // Start off-screen right // Random gap position (avoiding too high or too low) var minGapY = 300; var maxGapY = ground.y - 300; var gapY = minGapY + Math.random() * (maxGapY - minGapY); pipe.setGapPosition(gapY); pipe.speed = -gameSpeed; // Add entrance animation - pipes grow from small to normal size pipe.scaleX = 0.3; pipe.scaleY = 0.3; tween(pipe, { scaleX: 1, scaleY: 1 }, { duration: 400, easing: tween.easeOut }); pipes.push(pipe); game.addChild(pipe); } function spawnCoin() { // Only spawn coin if there's a recent pipe to place it with if (pipes.length > 0) { var latestPipe = pipes[pipes.length - 1]; var coin = new Coin(); // Place coin slightly ahead of the pipe gap coin.x = latestPipe.x + 150; // Position coin in the gap area // Place coin in the center of the pipe gap var gapCenterY = (latestPipe.topPipe.y + latestPipe.bottomPipe.y) / 2; coin.y = gapCenterY; coin.speed = -gameSpeed; // Add sparkle entrance effect - coin appears with bounce coin.scaleX = 0; coin.scaleY = 0; tween(coin, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(coin, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.easeIn }); } }); coins.push(coin); game.addChild(coin); } } // Cloud spawning function removed function spawnFarm() { var farm = new Farm(); farm.x = 2048; farm.y = ground.y - 200; // Position above ground farm.speed = -gameSpeed; farms.push(farm); game.addChild(farm); } function spawnAnimal() { if (farms.length > 0) { var randomFarm = farms[Math.floor(Math.random() * farms.length)]; var animalTypes = [Cow, Sheep, Pig, Chicken]; var AnimalClass = animalTypes[Math.floor(Math.random() * animalTypes.length)]; var animal = new AnimalClass(); animal.x = randomFarm.x + Math.random() * 1500; // Random position on farm animal.baseY = randomFarm.y; animal.y = animal.baseY; animal.speed = -gameSpeed; animals.push(animal); game.addChild(animal); } } function updateHealthBar() { var healthPercent = currentHealth / maxHealth; healthBar.width = 300 * healthPercent; // Change color based on health if (healthPercent > 0.6) { healthBar.tint = 0x00ff00; // Green } else if (healthPercent > 0.3) { healthBar.tint = 0xffff00; // Yellow } else { healthBar.tint = 0xff0000; // Red } // Flash effect when damaged tween(healthBar, { alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(healthBar, { alpha: 1 }, { duration: 100 }); } }); } function takeDamage() { currentHealth--; updateHealthBar(); if (currentHealth <= 0) { LK.getSound('hit').play(); // Add dramatic screen shake before game over var originalX = game.x; var originalY = game.y; tween(game, { x: originalX + 20, y: originalY + 10 }, { duration: 50, onFinish: function onFinish() { tween(game, { x: originalX - 15, y: originalY - 8 }, { duration: 50, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: 100, onFinish: function onFinish() { showCustomGameOver(); } }); } }); } }); return true; // Game over } LK.getSound('hit').play(); // Add screen shake effect for damage feedback var originalX = game.x; var originalY = game.y; tween(game, { x: originalX + 10, y: originalY + 5 }, { duration: 60, onFinish: function onFinish() { tween(game, { x: originalX - 8, y: originalY - 4 }, { duration: 60, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: 80 }); } }); } }); // Flash bird red when damaged tween(bird, { tint: 0xff0000 }, { duration: 200, onFinish: function onFinish() { tween(bird, { tint: 0xffffff }, { duration: 200 }); } }); return false; // Continue game } function checkCollisions() { // Check ground collision var currentGroundCollision = bird.y + 22 >= ground.y; // bird half-height if (!lastGroundCollision && currentGroundCollision) { LK.getSound('hit').play(); showCustomGameOver(); return; } lastGroundCollision = currentGroundCollision; // Check heaven win condition - when bird reaches very top var heavenThreshold = -50; // Above the screen if (bird.y <= heavenThreshold) { // Flash screen with heavenly light effect tween(game, { tint: 0xffffff }, { duration: 500, onFinish: function onFinish() { tween(game, { tint: 0xffffff }, { duration: 500, onFinish: function onFinish() { LK.showYouWin(); // Show win screen } }); } }); return; } // Check ceiling collision (but not heaven) var currentCeilingCollision = bird.y - 22 <= 0 && bird.y > heavenThreshold; if (!lastCeilingCollision && currentCeilingCollision) { LK.getSound('hit').play(); showCustomGameOver(); return; } lastCeilingCollision = currentCeilingCollision; // Check pipe collisions and scoring for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; // Check if bird passed through pipe (scoring) if (!pipe.passed && bird.x > pipe.x + 60) { pipe.passed = true; // Check if this is a milestone (every 10 pipes) var pipesPassed = 0; for (var p = 0; p < pipes.length; p++) { if (pipes[p].passed) { pipesPassed++; } } // Add bonus points for every 10 pipes passed if (pipesPassed > 0 && pipesPassed % 10 === 0) { LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); // Special visual effect for bonus score tween(scoreTxt, { scaleX: 1.5, scaleY: 1.5, tint: 0xFFD700 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 300, easing: tween.easeIn }); } }); } LK.getSound('score').play(); // Increase difficulty every 5 pipes if (LK.getScore() % 5 === 0) { gameSpeed += 0.5; } } // Check collision with pipes var birdLeft = bird.x - 30; var birdRight = bird.x + 30; var birdTop = bird.y - 22; var birdBottom = bird.y + 22; var pipeLeft = pipe.x - 60; var pipeRight = pipe.x + 60; if (birdRight > pipeLeft && birdLeft < pipeRight) { // Bird is horizontally aligned with pipe var topPipeBottom = pipe.topPipe.y; var bottomPipeTop = pipe.bottomPipe.y; if (birdTop < topPipeBottom || birdBottom > bottomPipeTop) { // Check if this pipe already caused damage if (!pipe.damageCaused) { pipe.damageCaused = true; if (takeDamage()) { return; // Game over } } } } } // Check coin collection for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; if (!coin.collected && bird.intersects(coin)) { coin.collected = true; LK.setScore(LK.getScore() + 1); // Coins worth 1 point scoreTxt.setText(LK.getScore()); LK.getSound('coin').play(); // Add score text animation for feedback tween(scoreTxt, { scaleX: 1.3, scaleY: 1.3 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1, scaleY: 1 }, { duration: 150, easing: tween.easeIn }); } }); // Visual effect - make coin disappear with scaling tween(coin, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, onFinish: function onFinish() { coin.destroy(); } }); coins.splice(j, 1); } } } // Custom game over UI variables var gameOverScreen = null; var restartButton = null; var continueButton = null; var gameOverTitleTxt = null; var showingGameOver = false; function showCustomGameOver() { if (showingGameOver) return; showingGameOver = true; gameStarted = false; // Create game over overlay gameOverScreen = new Container(); // Semi-transparent background var overlay = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0 }); overlay.width = 2048; overlay.height = 2732; overlay.alpha = 0.8; overlay.tint = 0x000000; gameOverScreen.addChild(overlay); // Game Over title gameOverTitleTxt = new Text2('GAME OVER', { size: 100, fill: 0xFF0000 }); gameOverTitleTxt.anchor.set(0.5, 0.5); gameOverTitleTxt.x = 1024; gameOverTitleTxt.y = 800; gameOverScreen.addChild(gameOverTitleTxt); // Restart button restartButton = new Text2('RESTART', { size: 80, fill: 0x00FF00 }); restartButton.anchor.set(0.5, 0.5); restartButton.x = 1024; restartButton.y = 1200; gameOverScreen.addChild(restartButton); // Continue button (only show if not used yet) if (!continueUsed) { continueButton = new Text2('CONTINUE (2 LIVES)', { size: 60, fill: 0xFFD700 }); continueButton.anchor.set(0.5, 0.5); continueButton.x = 1024; continueButton.y = 1400; gameOverScreen.addChild(continueButton); } game.addChild(gameOverScreen); // Add pulsing animation to buttons tween(restartButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 600, easing: tween.easeInOut }); if (continueButton) { tween(continueButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 800, easing: tween.easeInOut }); } } function restartGame() { // Reset game state gameStarted = false; showingGameOver = false; continueUsed = false; currentHealth = maxHealth; gameSpeed = 4; LK.setScore(0); scoreTxt.setText('0'); updateHealthBar(); // Clear all game objects for (var i = pipes.length - 1; i >= 0; i--) { pipes[i].destroy(); } pipes = []; for (var j = coins.length - 1; j >= 0; j--) { coins[j].destroy(); } coins = []; for (var k = animals.length - 1; k >= 0; k--) { animals[k].destroy(); } animals = []; for (var l = farms.length - 1; l >= 0; l--) { farms[l].destroy(); } farms = []; // Reset bird position bird.x = 400; bird.y = 1366; bird.velocity = 0; // Reset timers pipeSpawnTimer = 0; coinSpawnTimer = 0; farmSpawnTimer = 0; animalSpawnTimer = 0; // Remove game over screen if (gameOverScreen) { gameOverScreen.destroy(); gameOverScreen = null; } // Show start menu again showStartMenu = true; titleTxt.alpha = 1; titleTxt.y = -200; startButtonTxt.alpha = 1; startButtonTxt.y = 100; // Hide game UI scoreTxt.alpha = 0; instructionTxt.alpha = 0; healthBarBg.alpha = 0; healthBar.alpha = 0; daysTxt.alpha = 0; } function continueGame() { if (continueUsed) return; continueUsed = true; showingGameOver = false; gameStarted = true; // Give 2 lives (set health to 2) currentHealth = 2; updateHealthBar(); // Reset bird position to safe spot bird.x = 400; bird.y = 1366; bird.velocity = 0; // Remove game over screen if (gameOverScreen) { gameOverScreen.destroy(); gameOverScreen = null; } // Continue with current score and game state } // Touch controls game.down = function (x, y, obj) { // Handle game over screen touches if (showingGameOver) { // Use the x, y coordinates directly from the touch event // Check restart button if (restartButton && x >= restartButton.x - 150 && x <= restartButton.x + 150 && y >= restartButton.y - 50 && y <= restartButton.y + 50) { restartGame(); return; } // Check continue button (if available) if (continueButton && !continueUsed && x >= continueButton.x - 200 && x <= continueButton.x + 200 && y >= continueButton.y - 40 && y <= continueButton.y + 40) { continueGame(); return; } return; } if (showStartMenu) { // Start the game from menu showStartMenu = false; gameStarted = true; // Update days counter var currentDate = new Date().toDateString(); var lastPlayDate = storage.lastPlayDate || ''; var daysPlayed = storage.daysPlayed || 0; if (lastPlayDate !== currentDate) { daysPlayed++; storage.daysPlayed = daysPlayed; storage.lastPlayDate = currentDate; } daysTxt.setText('Days: ' + daysPlayed); // Smooth fade out menu elements tween(titleTxt, { alpha: 0, y: titleTxt.y - 100 }, { duration: 500, easing: tween.easeIn }); tween(startButtonTxt, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, easing: tween.easeIn }); // Smooth fade in game UI tween(scoreTxt, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); tween(instructionTxt, { alpha: 1 }, { duration: 1000, easing: tween.easeOut }); tween(healthBarBg, { alpha: 1 }, { duration: 600, easing: tween.easeOut }); tween(healthBar, { alpha: 1 }, { duration: 600, easing: tween.easeOut }); tween(daysTxt, { alpha: 1 }, { duration: 600, easing: tween.easeOut }); // Start background music try { LK.playMusic('bgmusic', { loop: true, volume: 0.5 }); } catch (e) { console.log('Music playback failed:', e); } // Hide instruction after a delay with smooth fade tween(instructionTxt, { alpha: 0 }, { duration: 2000, easing: tween.easeInOut }); bird.flap(); } else if (!gameStarted) { gameStarted = true; tween(instructionTxt, { alpha: 0 }, { duration: 500, easing: tween.easeOut }); bird.flap(); } else { bird.flap(); } }; // Main game loop game.update = function () { if (!gameStarted) { return; } // Update bird lastBirdY = bird.y; // Spawn pipes pipeSpawnTimer++; if (pipeSpawnTimer >= pipeSpawnInterval) { spawnPipe(); pipeSpawnTimer = 0; } // Spawn coins - spawn a coin shortly after each pipe coinSpawnTimer++; if (coinSpawnTimer >= coinSpawnInterval) { spawnCoin(); coinSpawnTimer = 0; } // Cloud spawning logic removed // Spawn farms farmSpawnTimer++; if (farmSpawnTimer >= farmSpawnInterval) { spawnFarm(); farmSpawnTimer = 0; } // Spawn animals on existing farms animalSpawnTimer++; if (animalSpawnTimer >= animalSpawnInterval) { spawnAnimal(); animalSpawnTimer = 0; } // Update pipes and remove off-screen ones for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; pipe.speed = -gameSpeed; if (pipe.x < -120) { pipe.destroy(); pipes.splice(i, 1); } } // Update coins and remove off-screen ones for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; coin.speed = -gameSpeed; if (coin.x < -40) { coin.destroy(); coins.splice(j, 1); } } // Cloud update logic removed // Update farms and remove off-screen ones for (var l = farms.length - 1; l >= 0; l--) { var farm = farms[l]; farm.speed = -gameSpeed; if (farm.x < -2048) { farm.destroy(); farms.splice(l, 1); } } // Update animals and remove off-screen ones for (var m = animals.length - 1; m >= 0; m--) { var animal = animals[m]; animal.speed = -gameSpeed; if (animal.x < -100) { animal.destroy(); animals.splice(m, 1); } } // Check all collisions checkCollisions(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Track if continue has been used in current session
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = 0;
self.gravity = 0.8;
self.flapStrength = -12;
self.maxFallSpeed = 15;
self.rotation = 0;
self.flap = function () {
self.velocity = self.flapStrength;
LK.getSound('flap').play();
// Animate bird flap
tween(birdGraphics, {
rotation: -0.3
}, {
duration: 150
});
tween(birdGraphics, {
rotation: 0
}, {
duration: 150,
onFinish: function onFinish() {
if (self.velocity > 0) {
tween(birdGraphics, {
rotation: 0.3
}, {
duration: 200
});
}
}
});
};
self.update = function () {
// Don't update bird physics if game hasn't started
if (!gameStarted) {
return;
}
// Apply gravity
self.velocity += self.gravity;
if (self.velocity > self.maxFallSpeed) {
self.velocity = self.maxFallSpeed;
}
// Update position
self.y += self.velocity;
// Update rotation based on velocity with falling effect
var targetRotation = Math.min(Math.max(self.velocity * 0.05, -0.5), 0.8);
// Add dramatic falling effect when bird is falling fast
if (self.velocity > 8) {
// Create falling spin effect
tween(birdGraphics, {
rotation: targetRotation + Math.PI * 2
}, {
duration: 800,
easing: tween.easeIn
});
// Add slight scale effect during fall
tween(birdGraphics, {
scaleX: 0.9,
scaleY: 1.1
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(birdGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
} else {
// Normal rotation for regular movement
birdGraphics.rotation = targetRotation;
}
};
return self;
});
var Chicken = Container.expand(function () {
var self = Container.call(this);
var chickenGraphics = self.attachAsset('chicken', {
anchorX: 0.5,
anchorY: 1
});
self.speed = -4;
self.baseY = 0;
self.pecking = false;
self.update = function () {
self.x += self.speed;
// Chicken walking animation - quick and jerky movements
var walkCycle = LK.ticks * 0.25; // Fast walking
// Quick head bobbing motion
self.y = self.baseY + Math.sin(walkCycle) * 1;
// Head jerking motion characteristic of chickens
chickenGraphics.x = Math.sin(walkCycle * 0.8) * 0.5;
// Periodic pecking animation
if (LK.ticks % 120 === 0) {
self.pecking = !self.pecking;
}
// Quick stepping animation every 10 frames for rapid chicken steps
if (LK.ticks % 10 === 0) {
var stepDirection = Math.floor(LK.ticks / 10) % 2 * 2 - 1;
tween(chickenGraphics, {
scaleY: 0.95,
scaleX: 1.05,
y: stepDirection * 0.3,
rotation: stepDirection * 0.05
}, {
duration: 50,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(chickenGraphics, {
scaleY: 1,
scaleX: 1,
y: 0,
rotation: 0
}, {
duration: 50,
easing: tween.easeIn
});
}
});
}
// Enhanced pecking motion when pecking
if (self.pecking) {
chickenGraphics.y = Math.sin(LK.ticks * 0.3) * 2;
}
};
return self;
});
// Cloud class removed
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.collected = false;
self.rotationSpeed = 0.1;
self.update = function () {
self.x += self.speed;
// Rotate coin for visual appeal
coinGraphics.rotation += self.rotationSpeed;
// Gentle floating animation
coinGraphics.y = Math.sin(LK.ticks * 0.05) * 3;
};
return self;
});
var Cow = Container.expand(function () {
var self = Container.call(this);
var cowGraphics = self.attachAsset('cow', {
anchorX: 0.5,
anchorY: 1
});
self.speed = -4;
// Add some black spots for cow appearance
self.baseY = 0;
self.update = function () {
self.x += self.speed;
// Proper walking animation with realistic bobbing
var walkCycle = LK.ticks * 0.15; // Walking speed
// Vertical bobbing motion - more pronounced and realistic
self.y = self.baseY + Math.sin(walkCycle) * 2;
// Subtle horizontal body sway
cowGraphics.x = Math.sin(walkCycle * 0.5) * 1;
// Body tilt during walking
cowGraphics.rotation = Math.sin(walkCycle) * 0.05;
// Step-based animation every 20 frames for more frequent steps
if (LK.ticks % 20 === 0) {
// Alternating leg movement effect
var stepDirection = Math.floor(LK.ticks / 20) % 2 * 2 - 1; // -1 or 1
// Step effect with body compression and extension
tween(cowGraphics, {
scaleY: 0.95,
scaleX: 1.05,
y: stepDirection * 1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(cowGraphics, {
scaleY: 1,
scaleX: 1,
y: 0
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
};
return self;
});
var Farm = Container.expand(function () {
var self = Container.call(this);
var farmGraphics = self.attachAsset('farmGround', {
anchorX: 0,
anchorY: 0
});
self.speed = -4;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Pig = Container.expand(function () {
var self = Container.call(this);
var pigGraphics = self.attachAsset('pig', {
anchorX: 0.5,
anchorY: 1
});
self.speed = -4;
self.baseY = 0;
self.update = function () {
self.x += self.speed;
// Pig walking animation - heavier and slower
var walkCycle = LK.ticks * 0.12; // Slower walking
// Heavy bobbing motion
self.y = self.baseY + Math.sin(walkCycle) * 1.2;
// Wide body sway for heavier appearance
pigGraphics.x = Math.sin(walkCycle * 0.3) * 1.5;
// Heavy stepping animation every 25 frames
if (LK.ticks % 25 === 0) {
var stepDirection = Math.floor(LK.ticks / 25) % 2 * 2 - 1;
tween(pigGraphics, {
scaleY: 0.92,
scaleX: 1.08,
y: stepDirection * 0.8
}, {
duration: 125,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(pigGraphics, {
scaleY: 1,
scaleX: 1,
y: 0
}, {
duration: 125,
easing: tween.easeIn
});
}
});
}
};
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
self.speed = -4;
self.passed = false;
self.gapSize = 450;
// Create top pipe
self.topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1
});
// Create top pipe segment (Mario-style cap)
self.topPipeSegment = self.attachAsset('pipeSegment', {
anchorX: 0.5,
anchorY: 1
});
// Create bottom pipe
self.bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0
});
// Create bottom pipe segment (Mario-style cap)
self.bottomPipeSegment = self.attachAsset('pipeSegment', {
anchorX: 0.5,
anchorY: 0
});
self.setGapPosition = function (gapY) {
self.topPipe.y = gapY - self.gapSize / 2;
self.bottomPipe.y = gapY + self.gapSize / 2;
// Position the Mario-style pipe segments
self.topPipeSegment.y = gapY - self.gapSize / 2;
self.bottomPipeSegment.y = gapY + self.gapSize / 2;
};
self.update = function () {
self.x += self.speed;
};
return self;
});
var Sheep = Container.expand(function () {
var self = Container.call(this);
var sheepGraphics = self.attachAsset('sheep', {
anchorX: 0.5,
anchorY: 1
});
self.speed = -4;
self.baseY = 0;
self.update = function () {
self.x += self.speed;
// Sheep walking animation - lighter and bouncier than cows
var walkCycle = LK.ticks * 0.18; // Slightly faster walking
// Bouncy vertical movement
self.y = self.baseY + Math.sin(walkCycle) * 1.5;
// Gentle body sway
sheepGraphics.x = Math.sin(walkCycle * 0.4) * 0.8;
// Light stepping animation every 15 frames for quicker steps
if (LK.ticks % 15 === 0) {
var stepDirection = Math.floor(LK.ticks / 15) % 2 * 2 - 1;
tween(sheepGraphics, {
scaleY: 0.98,
scaleX: 1.02,
y: stepDirection * 0.5
}, {
duration: 75,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(sheepGraphics, {
scaleY: 1,
scaleX: 1,
y: 0
}, {
duration: 75,
easing: tween.easeIn
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4a90e2
});
/****
* Game Code
****/
// Game variables
// Cloud asset removed
// Sky gradient assets removed
var continueUsed = false;
var bird;
var pipes = [];
var ground;
var gameStarted = false;
var gameSpeed = 4;
var pipeSpawnTimer = 0;
var pipeSpawnInterval = 180; // frames between pipe spawns
var lastPipeScore = 0;
var coins = [];
var coinSpawnTimer = 0;
var coinSpawnInterval = 200; // frames between coin spawns - slightly after pipes
// Cloud spawning removed
var farms = [];
var farmSpawnTimer = 0;
var farmSpawnInterval = 400; // frames between farm spawns
var animals = [];
var animalSpawnTimer = 0;
var animalSpawnInterval = 150; // frames between animal spawns
// Sky gradient layers removed
// Health system variables
var maxHealth = 3;
var currentHealth = 3;
var healthBar;
var healthBarBg;
// UI elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionTxt = new Text2('Tap to Flap!', {
size: 60,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionTxt);
// Days counter display
var daysTxt = new Text2('Days: 0', {
size: 50,
fill: 0xFFFFFF
});
daysTxt.anchor.set(0, 0);
daysTxt.x = 20;
daysTxt.y = 70;
LK.gui.topLeft.addChild(daysTxt);
// Start menu UI elements
var showStartMenu = true;
var titleTxt = new Text2('Mutili Bird', {
size: 120,
fill: 0xFFD700
});
titleTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(titleTxt);
var startButtonTxt = new Text2('TAP TO START', {
size: 80,
fill: 0x00FF00
});
startButtonTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startButtonTxt);
// Position menu elements
titleTxt.y = -200;
startButtonTxt.y = 100;
// Add pulsing animation to start button
tween(startButtonTxt, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButtonTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
// Set interval for continuous button pulsing
var buttonPulseTimer = LK.setInterval(function () {
if (showStartMenu) {
tween(startButtonTxt, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(startButtonTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut
});
}
});
}
}, 1600);
// Create health bar
healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
healthBarBg.x = 150;
healthBarBg.y = 20;
LK.gui.topLeft.addChild(healthBarBg);
healthBar = LK.getAsset('healthBarFill', {
anchorX: 0,
anchorY: 0
});
healthBar.x = 150;
healthBar.y = 20;
LK.gui.topLeft.addChild(healthBar);
// Create bird
bird = game.addChild(new Bird());
bird.x = 400;
bird.y = 1366; // Center of screen height
// Initialize health system
currentHealth = maxHealth;
updateHealthBar();
// Hide game UI initially
scoreTxt.alpha = 0;
instructionTxt.alpha = 0;
healthBarBg.alpha = 0;
healthBar.alpha = 0;
daysTxt.alpha = 0;
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
}));
ground.x = 0;
ground.y = 2732 - 100; // Bottom of screen
// Game state tracking
var lastBirdY = bird.y;
var lastGroundCollision = false;
var lastCeilingCollision = false;
function spawnPipe() {
var pipe = new Pipe();
pipe.x = 2048 + 60; // Start off-screen right
// Random gap position (avoiding too high or too low)
var minGapY = 300;
var maxGapY = ground.y - 300;
var gapY = minGapY + Math.random() * (maxGapY - minGapY);
pipe.setGapPosition(gapY);
pipe.speed = -gameSpeed;
// Add entrance animation - pipes grow from small to normal size
pipe.scaleX = 0.3;
pipe.scaleY = 0.3;
tween(pipe, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
pipes.push(pipe);
game.addChild(pipe);
}
function spawnCoin() {
// Only spawn coin if there's a recent pipe to place it with
if (pipes.length > 0) {
var latestPipe = pipes[pipes.length - 1];
var coin = new Coin();
// Place coin slightly ahead of the pipe gap
coin.x = latestPipe.x + 150; // Position coin in the gap area
// Place coin in the center of the pipe gap
var gapCenterY = (latestPipe.topPipe.y + latestPipe.bottomPipe.y) / 2;
coin.y = gapCenterY;
coin.speed = -gameSpeed;
// Add sparkle entrance effect - coin appears with bounce
coin.scaleX = 0;
coin.scaleY = 0;
tween(coin, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(coin, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
coins.push(coin);
game.addChild(coin);
}
}
// Cloud spawning function removed
function spawnFarm() {
var farm = new Farm();
farm.x = 2048;
farm.y = ground.y - 200; // Position above ground
farm.speed = -gameSpeed;
farms.push(farm);
game.addChild(farm);
}
function spawnAnimal() {
if (farms.length > 0) {
var randomFarm = farms[Math.floor(Math.random() * farms.length)];
var animalTypes = [Cow, Sheep, Pig, Chicken];
var AnimalClass = animalTypes[Math.floor(Math.random() * animalTypes.length)];
var animal = new AnimalClass();
animal.x = randomFarm.x + Math.random() * 1500; // Random position on farm
animal.baseY = randomFarm.y;
animal.y = animal.baseY;
animal.speed = -gameSpeed;
animals.push(animal);
game.addChild(animal);
}
}
function updateHealthBar() {
var healthPercent = currentHealth / maxHealth;
healthBar.width = 300 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBar.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBar.tint = 0xffff00; // Yellow
} else {
healthBar.tint = 0xff0000; // Red
}
// Flash effect when damaged
tween(healthBar, {
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(healthBar, {
alpha: 1
}, {
duration: 100
});
}
});
}
function takeDamage() {
currentHealth--;
updateHealthBar();
if (currentHealth <= 0) {
LK.getSound('hit').play();
// Add dramatic screen shake before game over
var originalX = game.x;
var originalY = game.y;
tween(game, {
x: originalX + 20,
y: originalY + 10
}, {
duration: 50,
onFinish: function onFinish() {
tween(game, {
x: originalX - 15,
y: originalY - 8
}, {
duration: 50,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: 100,
onFinish: function onFinish() {
showCustomGameOver();
}
});
}
});
}
});
return true; // Game over
}
LK.getSound('hit').play();
// Add screen shake effect for damage feedback
var originalX = game.x;
var originalY = game.y;
tween(game, {
x: originalX + 10,
y: originalY + 5
}, {
duration: 60,
onFinish: function onFinish() {
tween(game, {
x: originalX - 8,
y: originalY - 4
}, {
duration: 60,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: 80
});
}
});
}
});
// Flash bird red when damaged
tween(bird, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(bird, {
tint: 0xffffff
}, {
duration: 200
});
}
});
return false; // Continue game
}
function checkCollisions() {
// Check ground collision
var currentGroundCollision = bird.y + 22 >= ground.y; // bird half-height
if (!lastGroundCollision && currentGroundCollision) {
LK.getSound('hit').play();
showCustomGameOver();
return;
}
lastGroundCollision = currentGroundCollision;
// Check heaven win condition - when bird reaches very top
var heavenThreshold = -50; // Above the screen
if (bird.y <= heavenThreshold) {
// Flash screen with heavenly light effect
tween(game, {
tint: 0xffffff
}, {
duration: 500,
onFinish: function onFinish() {
tween(game, {
tint: 0xffffff
}, {
duration: 500,
onFinish: function onFinish() {
LK.showYouWin(); // Show win screen
}
});
}
});
return;
}
// Check ceiling collision (but not heaven)
var currentCeilingCollision = bird.y - 22 <= 0 && bird.y > heavenThreshold;
if (!lastCeilingCollision && currentCeilingCollision) {
LK.getSound('hit').play();
showCustomGameOver();
return;
}
lastCeilingCollision = currentCeilingCollision;
// Check pipe collisions and scoring
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
// Check if bird passed through pipe (scoring)
if (!pipe.passed && bird.x > pipe.x + 60) {
pipe.passed = true;
// Check if this is a milestone (every 10 pipes)
var pipesPassed = 0;
for (var p = 0; p < pipes.length; p++) {
if (pipes[p].passed) {
pipesPassed++;
}
}
// Add bonus points for every 10 pipes passed
if (pipesPassed > 0 && pipesPassed % 10 === 0) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
// Special visual effect for bonus score
tween(scoreTxt, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
LK.getSound('score').play();
// Increase difficulty every 5 pipes
if (LK.getScore() % 5 === 0) {
gameSpeed += 0.5;
}
}
// Check collision with pipes
var birdLeft = bird.x - 30;
var birdRight = bird.x + 30;
var birdTop = bird.y - 22;
var birdBottom = bird.y + 22;
var pipeLeft = pipe.x - 60;
var pipeRight = pipe.x + 60;
if (birdRight > pipeLeft && birdLeft < pipeRight) {
// Bird is horizontally aligned with pipe
var topPipeBottom = pipe.topPipe.y;
var bottomPipeTop = pipe.bottomPipe.y;
if (birdTop < topPipeBottom || birdBottom > bottomPipeTop) {
// Check if this pipe already caused damage
if (!pipe.damageCaused) {
pipe.damageCaused = true;
if (takeDamage()) {
return; // Game over
}
}
}
}
}
// Check coin collection
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
if (!coin.collected && bird.intersects(coin)) {
coin.collected = true;
LK.setScore(LK.getScore() + 1); // Coins worth 1 point
scoreTxt.setText(LK.getScore());
LK.getSound('coin').play();
// Add score text animation for feedback
tween(scoreTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Visual effect - make coin disappear with scaling
tween(coin, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(j, 1);
}
}
}
// Custom game over UI variables
var gameOverScreen = null;
var restartButton = null;
var continueButton = null;
var gameOverTitleTxt = null;
var showingGameOver = false;
function showCustomGameOver() {
if (showingGameOver) return;
showingGameOver = true;
gameStarted = false;
// Create game over overlay
gameOverScreen = new Container();
// Semi-transparent background
var overlay = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0
});
overlay.width = 2048;
overlay.height = 2732;
overlay.alpha = 0.8;
overlay.tint = 0x000000;
gameOverScreen.addChild(overlay);
// Game Over title
gameOverTitleTxt = new Text2('GAME OVER', {
size: 100,
fill: 0xFF0000
});
gameOverTitleTxt.anchor.set(0.5, 0.5);
gameOverTitleTxt.x = 1024;
gameOverTitleTxt.y = 800;
gameOverScreen.addChild(gameOverTitleTxt);
// Restart button
restartButton = new Text2('RESTART', {
size: 80,
fill: 0x00FF00
});
restartButton.anchor.set(0.5, 0.5);
restartButton.x = 1024;
restartButton.y = 1200;
gameOverScreen.addChild(restartButton);
// Continue button (only show if not used yet)
if (!continueUsed) {
continueButton = new Text2('CONTINUE (2 LIVES)', {
size: 60,
fill: 0xFFD700
});
continueButton.anchor.set(0.5, 0.5);
continueButton.x = 1024;
continueButton.y = 1400;
gameOverScreen.addChild(continueButton);
}
game.addChild(gameOverScreen);
// Add pulsing animation to buttons
tween(restartButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 600,
easing: tween.easeInOut
});
if (continueButton) {
tween(continueButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 800,
easing: tween.easeInOut
});
}
}
function restartGame() {
// Reset game state
gameStarted = false;
showingGameOver = false;
continueUsed = false;
currentHealth = maxHealth;
gameSpeed = 4;
LK.setScore(0);
scoreTxt.setText('0');
updateHealthBar();
// Clear all game objects
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].destroy();
}
pipes = [];
for (var j = coins.length - 1; j >= 0; j--) {
coins[j].destroy();
}
coins = [];
for (var k = animals.length - 1; k >= 0; k--) {
animals[k].destroy();
}
animals = [];
for (var l = farms.length - 1; l >= 0; l--) {
farms[l].destroy();
}
farms = [];
// Reset bird position
bird.x = 400;
bird.y = 1366;
bird.velocity = 0;
// Reset timers
pipeSpawnTimer = 0;
coinSpawnTimer = 0;
farmSpawnTimer = 0;
animalSpawnTimer = 0;
// Remove game over screen
if (gameOverScreen) {
gameOverScreen.destroy();
gameOverScreen = null;
}
// Show start menu again
showStartMenu = true;
titleTxt.alpha = 1;
titleTxt.y = -200;
startButtonTxt.alpha = 1;
startButtonTxt.y = 100;
// Hide game UI
scoreTxt.alpha = 0;
instructionTxt.alpha = 0;
healthBarBg.alpha = 0;
healthBar.alpha = 0;
daysTxt.alpha = 0;
}
function continueGame() {
if (continueUsed) return;
continueUsed = true;
showingGameOver = false;
gameStarted = true;
// Give 2 lives (set health to 2)
currentHealth = 2;
updateHealthBar();
// Reset bird position to safe spot
bird.x = 400;
bird.y = 1366;
bird.velocity = 0;
// Remove game over screen
if (gameOverScreen) {
gameOverScreen.destroy();
gameOverScreen = null;
}
// Continue with current score and game state
}
// Touch controls
game.down = function (x, y, obj) {
// Handle game over screen touches
if (showingGameOver) {
// Use the x, y coordinates directly from the touch event
// Check restart button
if (restartButton && x >= restartButton.x - 150 && x <= restartButton.x + 150 && y >= restartButton.y - 50 && y <= restartButton.y + 50) {
restartGame();
return;
}
// Check continue button (if available)
if (continueButton && !continueUsed && x >= continueButton.x - 200 && x <= continueButton.x + 200 && y >= continueButton.y - 40 && y <= continueButton.y + 40) {
continueGame();
return;
}
return;
}
if (showStartMenu) {
// Start the game from menu
showStartMenu = false;
gameStarted = true;
// Update days counter
var currentDate = new Date().toDateString();
var lastPlayDate = storage.lastPlayDate || '';
var daysPlayed = storage.daysPlayed || 0;
if (lastPlayDate !== currentDate) {
daysPlayed++;
storage.daysPlayed = daysPlayed;
storage.lastPlayDate = currentDate;
}
daysTxt.setText('Days: ' + daysPlayed);
// Smooth fade out menu elements
tween(titleTxt, {
alpha: 0,
y: titleTxt.y - 100
}, {
duration: 500,
easing: tween.easeIn
});
tween(startButtonTxt, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 300,
easing: tween.easeIn
});
// Smooth fade in game UI
tween(scoreTxt, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
tween(instructionTxt, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeOut
});
tween(healthBarBg, {
alpha: 1
}, {
duration: 600,
easing: tween.easeOut
});
tween(healthBar, {
alpha: 1
}, {
duration: 600,
easing: tween.easeOut
});
tween(daysTxt, {
alpha: 1
}, {
duration: 600,
easing: tween.easeOut
});
// Start background music
try {
LK.playMusic('bgmusic', {
loop: true,
volume: 0.5
});
} catch (e) {
console.log('Music playback failed:', e);
}
// Hide instruction after a delay with smooth fade
tween(instructionTxt, {
alpha: 0
}, {
duration: 2000,
easing: tween.easeInOut
});
bird.flap();
} else if (!gameStarted) {
gameStarted = true;
tween(instructionTxt, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
bird.flap();
} else {
bird.flap();
}
};
// Main game loop
game.update = function () {
if (!gameStarted) {
return;
}
// Update bird
lastBirdY = bird.y;
// Spawn pipes
pipeSpawnTimer++;
if (pipeSpawnTimer >= pipeSpawnInterval) {
spawnPipe();
pipeSpawnTimer = 0;
}
// Spawn coins - spawn a coin shortly after each pipe
coinSpawnTimer++;
if (coinSpawnTimer >= coinSpawnInterval) {
spawnCoin();
coinSpawnTimer = 0;
}
// Cloud spawning logic removed
// Spawn farms
farmSpawnTimer++;
if (farmSpawnTimer >= farmSpawnInterval) {
spawnFarm();
farmSpawnTimer = 0;
}
// Spawn animals on existing farms
animalSpawnTimer++;
if (animalSpawnTimer >= animalSpawnInterval) {
spawnAnimal();
animalSpawnTimer = 0;
}
// Update pipes and remove off-screen ones
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
pipe.speed = -gameSpeed;
if (pipe.x < -120) {
pipe.destroy();
pipes.splice(i, 1);
}
}
// Update coins and remove off-screen ones
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.speed = -gameSpeed;
if (coin.x < -40) {
coin.destroy();
coins.splice(j, 1);
}
}
// Cloud update logic removed
// Update farms and remove off-screen ones
for (var l = farms.length - 1; l >= 0; l--) {
var farm = farms[l];
farm.speed = -gameSpeed;
if (farm.x < -2048) {
farm.destroy();
farms.splice(l, 1);
}
}
// Update animals and remove off-screen ones
for (var m = animals.length - 1; m >= 0; m--) {
var animal = animals[m];
animal.speed = -gameSpeed;
if (animal.x < -100) {
animal.destroy();
animals.splice(m, 1);
}
}
// Check all collisions
checkCollisions();
};
Kuş. In-Game asset. 2d. High contrast. No shadows
İnek. In-Game asset. 2d. High contrast. No shadows
Koyun. In-Game asset. 2d. High contrast. No shadows
Domuz. In-Game asset. 2d. High contrast. No shadows
Tavuk. In-Game asset. 2d. High contrast. No shadows
Toprak. In-Game asset. 2d. High contrast. No shadows