User prompt
Remove the scale code from fireflytrail
Code edit (1 edits merged)
Please save this source code
User prompt
Have the eagle aim slightly higher on the coot.
User prompt
As the game speed grows, increase eagles downward speed in proportion to compensate and keep the same swoop.
User prompt
When a second power up of the same type is collected, the state relating to that power up needs to be cleared and set again as well.
User prompt
Every time 100 coins is collected add a heart icon and a refill or add a life
User prompt
Change the sun and moon duration to 2 minutes.
User prompt
When a second power up of the same type is collected I think it might be better to just clear and reapply the collection from the start instead of adding to the time. For those power ups with timers.
User prompt
Add a varied chance for random power up to be selected with different weights for each type. Specifically: shield - 20%, powerdash 25%, coin magnet 25%, warning 20%, Phoenix feather 10%
User prompt
Double the time between power ups spawning.
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'coot.phoenixFeatherIcon = phoenixFeatherIcon; // Store reference in coot' Line Number: 1271
User prompt
Please fix the PhoenixFeather icon update system to properly reflect collection state. Specifically: 1. Fix the icon initialization: ```javascript // Start dim, not opaque var iconGraphics = self.attachAsset('PhoenixFeatherIcon', { anchorX: 0.5, anchorY: 0.5, alpha: 0.2 // This is correct }); ``` 2. Ensure the update method is called: - Add update call when collecting the feather - Add update call in game's main update loop - Store icon reference where it can be accessed by both collection and usage code
User prompt
As the game speed gets faster, the duration and the timer of the power ups is not lining up correctly. Please change the duration time calculated using time of day.
User prompt
Something is not working right with power ups when you collect the same power up while it has a timer. The timer is working perfectly but the duration of the power up state does not seem to be updating properly.
User prompt
The Phoenix feather icon visibility state is not being changed when one is acquired. Please fix
User prompt
Set initial game speed to 1.5 and set max game speed to 5
User prompt
Move the phoenix feather icon down more. More padding.
User prompt
Start the Phoenix feather icon as opaque and then set to visible only if collected.
User prompt
A third more
User prompt
Twice as much padding.
User prompt
The Phoenix icon should be directly under the middle of the left heart icon with some padding.
User prompt
Remove the adding of the Phoenix feather icon from the power up class
User prompt
Change the check in the Phoenix feather icon class from checking if the coot is invincible to checking if it has a Phoenix feather.
User prompt
The Phoenix feather icon should be initialized from the beginning of the game.
User prompt
Also make sure the phoenix feather icon updates back to original once the Phoenix event happens
/**** * Classes ****/ var Butterfly = Container.expand(function () { var self = Container.call(this); var butterflyTypes = ['GreenButterfly', 'PinkButterfly', 'YellowButterfly']; var selectedType = butterflyTypes[Math.floor(Math.random() * butterflyTypes.length)]; var butterflyGraphics = self.attachAsset(selectedType, { anchorX: 0.5, anchorY: 0.5 }); // Initialize butterfly properties self.speedX = -2; // Speed of the butterfly moving left self.flitAmplitude = 20; // Amplitude of the flitting motion self.flitFrequency = 0.1; // Frequency of the flitting motion self.startY = Math.random() * (2732 * 0.6) + 2732 * 0.2; // Random Y position within midground tree layer self.update = function () { // Move the butterfly left self.x += self.speedX * gameSpeed; // Apply flitting motion self.y = self.startY + Math.sin(self.x * self.flitFrequency) * self.flitAmplitude; // Simulate wing flapping by adjusting scale var flapScale = 0.2 * Math.sin(LK.ticks * 0.3) + 1; butterflyGraphics.scale.set(flapScale); // Destroy the butterfly if it goes off screen if (self.x < -butterflyGraphics.width / 2) { self.destroy(); } }; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('Coin', { anchorX: 0.5, anchorY: 0.5 }); // Initialize coin properties self.rotationSpeed = 0.05; // Rotation speed for the coin self.speedX = -5; // Speed of the coin moving left self.collecting = false; // Flag to check if the coin is being collected self.targetX = 0; // Target X position for collection animation self.targetY = 0; // Target Y position for collection animation self.update = function () { // Generate GoldSparkle particles if (Math.random() < 0.0525) { var sparkle = new GoldSparkle(); sparkle.x = self.x + (Math.random() * coinGraphics.width - coinGraphics.width / 2); sparkle.y = self.y + (Math.random() * coinGraphics.height - coinGraphics.height / 2); sparkle.coin = self; // Associate sparkle with the coin game.addChild(sparkle); } // Move the coin left self.x += self.speedX * gameSpeed; // Apply spin effect over Y axis coinGraphics.scale.x = Math.sin(self.x * 0.015); if (coot.isMagnetActive && !self.collecting && self.x < 2048 * 0.9) { // Home in on Coot's location self.targetX = coot.x; self.targetY = coot.y; self.collecting = true; } if (self.collecting) { // Animate coin collection self.x += (self.targetX - self.x) * 0.1; self.y += (self.targetY - self.y) * 0.1; coinGraphics.scale.x *= 0.90; coinGraphics.scale.y *= 0.90; // Check if the coin has reached the target position or is small enough if (Math.abs(self.x - self.targetX) < 5 && Math.abs(self.y - self.targetY) < 5 || coinGraphics.scale.x < 0.1 && coinGraphics.scale.y < 0.1) { // Destroy all sparkles attached to the coin game.children.forEach(function (child) { if (child instanceof GoldSparkle && child.coin === self) { child.destroy(); } }); self.destroy(); coinCount++; coinCounter.setText(Math.min(coinCount, 999).toString()); coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter return; } } else if (self.x < -coinGraphics.width / 2) { // Destroy the coin if it goes off screen self.destroy(); } }; }); var CollisionBlock = Container.expand(function () { var self = Container.call(this); var collisionBlockGraphics = self.attachAsset('Collisionblock', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); }); // Assets will be automatically created and loaded by the LK engine based on their usage in the code. // Example assets: 'coot', 'obstacle', 'background' // Class for the main character, the American coot var Coot = Container.expand(function () { var self = Container.call(this); var cootGraphics = self.attachAsset('coot', { anchorX: 0.5, anchorY: 0.5 }); self.originalX = self.x; // Store original X position self.speed = 6.5; self.dashSpeed = 15; self.lives = 3; // Initialize Coot with three lives self.dashDelay = 30; self.isFalling = false; self.isDashing = false; self.fallRotation = 0; // Initialize fall rotation self.dashTimer = 0; self.jumpVelocity = 40; // Increased initial upward velocity for jump self.gravity = 1.0; // Gravity to apply during jump self.jumpHeight = 105; self.isJumping = false; self.isReturning = false; // New state to handle returning to top after diving self.isInvincible = false; // Initialize invincible state self.isShielded = false; // Initialize shielded state self.isMagnetActive = false; // Initialize magnet state self.isWarningActive = false; // Initialize warning state self.isPowerDashActive = false; // Initialize PowerDash state self.hasPhoenixFeather = false; // Initialize Phoenix Feather state self.update = function () { if (self.isJumping) { self.y -= self.jumpVelocity; self.jumpVelocity -= self.gravity; if (self.jumpVelocity <= 0) { self.isJumping = false; self.isFalling = true; self.fallStartY = self.y; self.fallRotation = 0; self.fallSpeed = 5; } } else if (self.isFalling) { handleFalling(); } else if (self.isDiving) { handleDiving(); } else if (self.returnDelay > 0) { handleReturnDelay(); } else if (self.isReturning) { handleReturning(); } function handleFalling() { if (self.lives <= 0) { self.y -= self.fallSpeed; self.fallRotation += 0.05; cootGraphics.rotation = -self.fallRotation; if (self.y <= self.fallStartY - 50) { self.fallSpeed = -10; } if (self.y > 2732) { LK.showGameOver(); } } else { self.y += self.gravity * 10; // Increase gravity effect during fall if (self.y >= self.originalY) { self.y = self.originalY; self.isFalling = false; self.jumpVelocity = 40; self.isJumping = false; } cootGraphics.rotation = 0; } } function handleDiving() { self.y += self.speed * 1.5; cootGraphics.alpha = Math.max(0.5, cootGraphics.alpha - 0.05); cootGraphics.tint = 0x0000ff; if (self.y >= 2732 * 0.90) { self.y = 2732 * 0.90; self.isDiving = false; self.returnDelay = Date.now() + 1000; } } function handleReturnDelay() { if (Date.now() >= self.returnDelay) { self.returnDelay = 0; if (self.y >= 2732 * 0.90) { self.isReturning = true; } } } function handleReturning() { self.y -= self.speed * 1.5; var transitionFactor = 1 - (self.y - self.originalY) / (2732 * 0.90 - self.originalY); cootGraphics.alpha = 0.5 + 0.5 * transitionFactor; var startTint = self.underwaterTint; var endTint = 0xffffff; var r = (startTint >> 16 & 0xff) + ((endTint >> 16 & 0xff) - (startTint >> 16 & 0xff)) * transitionFactor; var g = (startTint >> 8 & 0xff) + ((endTint >> 8 & 0xff) - (startTint >> 8 & 0xff)) * transitionFactor; var b = (startTint & 0xff) + ((endTint & 0xff) - (startTint & 0xff)) * transitionFactor; cootGraphics.tint = (r << 16) + (g << 8) + b; if (self.y <= self.originalY) { self.y = self.originalY; self.isReturning = false; cootGraphics.alpha = 1.0; cootGraphics.tint = 0xffffff; } if (self.isReturning) { self.x += (self.originalX - self.x) * 0.1; } } // Add wobble effect to the coot while running if (!self.isJumping && !self.isDiving && !self.isReturning && !self.isFalling) { cootGraphics.rotation = Math.sin(LK.ticks / 5) * 0.1; // Increase wobble speed by reducing the divisor // Generate 1-2 water splash particles every 60 ticks (1 second) only when not jumping, diving, or falling if (!self.isJumping && !self.isDiving && !self.isFalling && LK.ticks % 60 == 0) { var numParticles = Math.floor(Math.random() * 2) + 1; for (var i = 0; i < numParticles; i++) { var splashLeft = new Splash(); splashLeft.x = self.x - cootGraphics.width / 2; splashLeft.y = self.y + cootGraphics.height / 2; game.addChildAt(splashLeft, game.getChildIndex(foreground1) - 1); var splashRight = new Splash(); splashRight.x = self.x + cootGraphics.width / 2; splashRight.y = self.y + cootGraphics.height / 2; game.addChildAt(splashRight, game.getChildIndex(foreground1) - 1); } } } // Handle dash state if (self.isDashing) { if (self.dashTimer < self.dashDelay) { // Dash forward if (self.x < 2048 * 0.75) { // Stop at 3/4 of screen width self.x += self.dashSpeed * 1.1; } // Create echo trail effect only if PowerDash is active if (self.isPowerDashActive) { var echo = new EchoTrail(); echo.x = self.x; echo.y = self.y; game.addChild(echo); } self.dashTimer++; } else { var returnSpeed = 10; // Fixed return speed self.x += Math.sign(self.originalX - self.x) * Math.min(returnSpeed, Math.abs(self.originalX - self.x)); if (Math.abs(self.x - self.originalX) < returnSpeed) { self.x = self.originalX; self.isDashing = false; self.dashTimer = 0; } } } // Ensure smooth return to original position if falling and returning from a dash if (self.isFalling && self.isReturning) { var returnSpeed = 10; // Fixed return speed self.x += Math.sign(self.originalX - self.x) * Math.min(returnSpeed, Math.abs(self.originalX - self.x)); if (Math.abs(self.x - self.originalX) < returnSpeed) { self.x = self.originalX; self.isReturning = false; } } }; self.isDiving = false; self.isDashing = false; self.dashSpeed = 15; self.dashDelay = 60; self.dashTimer = 0; self.originalX = self.x; self.jump = function () { if (canPerformAction()) { self.isJumping = true; self.originalX = self.x; self.isReturning = false; self.originalY = self.y; } }; self.dash = function () { if (canPerformAction()) { self.isDashing = true; self.originalX = self.x; self.dashTimer = 0; } }; self.dive = function () { if (canPerformAction()) { self.isDiving = true; self.returnDelay = Date.now() + 5000; self.isReturning = false; self.underwaterTint = 0x4444ff; self.originalX = self.x; self.originalY = self.y; self.y += self.speed * 2; generateSplashParticles(2, 4); } }; function canPerformAction() { return !self.isJumping && !self.isDiving && !self.isReturning && !self.isDashing; } function generateSplashParticles(min, max) { var numParticles = Math.floor(Math.random() * (max - min + 1)) + min; for (var i = 0; i < numParticles; i++) { var splash = new Splash(); splash.x = self.x; splash.y = self.y + cootGraphics.height / 2; game.addChildAt(splash, game.getChildIndex(foreground1) - 1); } } }); var DayCountDisplay = Container.expand(function () { var self = Container.call(this); var dayText = new Text2('Day ' + DayCount, { size: 100, fill: "#ffffff" }); dayText.anchor.set(0.5, 0.5); dayText.alpha = 0; // Set alpha to 0 by default self.addChild(dayText); self.show = function () { dayText.setText('Day ' + DayCount); dayText.alpha = 1; LK.setTimeout(function () { dayText.alpha = 0; // Set alpha back to 0 instead of destroying }, 1500); // Set a timer to make the day count display visible for 3 seconds every time the day count increases LK.setTimeout(function () { dayText.alpha = 1; LK.setTimeout(function () { dayText.alpha = 0; }, 1500); }, 1500); }; }); var DuckWarningIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('DuckIcon', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); self.flashInterval = 0; self.update = function () { self.flashInterval++; if (coot.isWarningActive) { if (self.flashInterval % 30 < 15) { iconGraphics.alpha = 0.75; } else { iconGraphics.alpha = 0.5; } } else { iconGraphics.alpha = 0; } }; }); var EagleFeather = Container.expand(function () { var self = Container.call(this); var featherGraphics = self.attachAsset('Eaglefeather', { anchorX: 0.5, anchorY: 0.5 }); // Initialize feather properties self.rotationSpeed = Math.random() * 0.02 - 0.01; // Random rotation speed self.driftX = Math.random() * 2 - 1; // Random sideways drift self.driftY = Math.random() * -1 - 0.5; // Upward drift self.fadeRate = 0.005; // Fade out rate self.update = function () { self.x += self.driftX * gameSpeed; self.y += self.driftY * gameSpeed; featherGraphics.rotation += self.rotationSpeed; featherGraphics.alpha -= self.fadeRate; // Destroy feather when fully faded if (featherGraphics.alpha <= 0) { self.destroy(); } }; }); var EagleWarningIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('EagleIcon', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); self.flashInterval = 0; self.update = function () { self.flashInterval++; if (coot.isWarningActive) { if (self.flashInterval % 30 < 15) { iconGraphics.alpha = 0.75; } else { iconGraphics.alpha = 0.5; } } else { iconGraphics.alpha = 0; } }; }); var EchoTrail = Container.expand(function () { var self = Container.call(this); var echoGraphics = self.attachAsset('coot', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set initial transparency }); self.fadeRate = 0.05; // Rate at which the echo fades self.update = function () { echoGraphics.alpha -= self.fadeRate; if (echoGraphics.alpha <= 0) { self.destroy(); } }; }); var Firefly = Container.expand(function () { var self = Container.call(this); var fireflyGraphics = self.attachAsset('Firefly', { anchorX: 0.5, anchorY: 0.5 }); // Initialize firefly properties self.speedX = Math.random() * 8 - 4; // Further increased random horizontal speed self.speedY = Math.random() * 8 - 4; // Further increased random vertical speed self.fadeRate = 0.005; // Much slower fade rate for slow pulsing self.flickerTimer = Math.random() * 240 + 120; // Random flicker timer between 2 to 4 seconds self.alphaDirection = 1; // Direction of alpha change (1 for fade in, -1 for fade out) self.lifetime = Math.random() * 180 + 180; // Random lifetime between 3 to 5 seconds self.update = function () { // Move the firefly self.x += self.speedX; self.y += self.speedY; // Create trail effect var trail = new FireflyTrail(); trail.x = self.x; trail.y = self.y; game.addChild(trail); // Loop around the screen if (self.x < 0) { self.x = 2048; } if (self.x > 2048) { self.x = 0; } if (self.y < 0) { self.y = 2732; } if (self.y > 2732) { self.y = 0; } // Flicker effect self.flickerTimer--; if (self.flickerTimer <= 0) { fireflyGraphics.alpha = Math.random(); // Random alpha for flicker self.flickerTimer = Math.random() * 60 + 30; // Reset flicker timer } // Fade in and out fireflyGraphics.alpha += self.fadeRate * self.alphaDirection; if (fireflyGraphics.alpha <= 0 || fireflyGraphics.alpha >= 1) { self.alphaDirection *= -1; // Reverse fade direction } // Destroy firefly after its lifetime self.lifetime--; if (self.lifetime <= 0) { self.destroy(); } }; }); var FireflyTrail = Container.expand(function () { var self = Container.call(this); var trailGraphics = LK.getAsset('FireflyTrail', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, alpha: 1 // Initial transparency }); self.fadeRate = 0.02; // Rate at which the trail fades self.update = function () { trailGraphics.alpha -= self.fadeRate; if (trailGraphics.alpha <= 0) { self.destroy(); } }; }); var FishWarningIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('FishIcon', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); self.flashInterval = 0; self.update = function () { self.flashInterval++; if (coot.isWarningActive) { if (self.flashInterval % 30 < 15) { iconGraphics.alpha = 0.75; } else { iconGraphics.alpha = 0.5; } } else { iconGraphics.alpha = 0; } }; }); // Define a single obstacleTypes array as a constant // Class for the foreground var Foreground = Container.expand(function () { var self = Container.call(this); var foregroundGraphics = self.attachAsset('Foreground', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.isFirst = false; // Will be set during initialization self.update = function () { // Only move the first piece if (self.isFirst) { self.x -= self.speed * gameSpeed; // Apply gameSpeed to movement // Move second piece to maintain fixed distance self.other.x = self.x + self.width; // Reset both pieces when first goes off screen if (self.x < -self.width / 1.5) { // Reset earlier - when piece is mostly off screen self.x += self.width; self.other.x = self.x + self.width; } } }; }); var GoldSparkle = Container.expand(function () { var self = Container.call(this); var sparkleGraphics = self.attachAsset('GoldSparkle', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = (Math.random() * 2 - 1) * 0.75; // Reduced horizontal speed by 25% self.speedY = (Math.random() * 2 - 1) * 0.75; // Reduced vertical speed by 25% self.fadeRate = 0.02; // Rate at which the sparkle fades self.update = function () { self.x += self.speedX; self.y += self.speedY; sparkleGraphics.alpha -= self.fadeRate; if (sparkleGraphics.alpha <= 0) { self.destroy(); } }; }); // Class for the midgroundtrees var Midgroundtrees = Container.expand(function () { var self = Container.call(this); var midgroundtreesGraphics = self.attachAsset('Midgroundtrees', { anchorX: 0.5, anchorY: 0.7 }); self.speed = 3; self.update = function () { self.x -= self.speed * gameSpeed; // self.y = coot.y; if (self.x <= -self.width / 2) { self.x += self.width * 2; } }; }); var Moon = Container.expand(function () { var self = Container.call(this); var moonGraphics = self.attachAsset('Moon', { anchorX: 0.5, anchorY: 0.5 }); // Initialize moon properties self.startX = -moonGraphics.width / 2; // Start off-screen to the left self.startY = 2732 * 0.25; // 25% from the top self.endX = 2048 + moonGraphics.width / 2; // End off-screen to the right self.arcHeight = 2732 * 0.1; // Arc height self.duration = 3.75 * 60 * 60; // 3.75 minutes in ticks (assuming 60 FPS) self.ticks = 0; self.update = function () { self.ticks++; var progress = self.ticks / self.duration; self.x = self.startX + (self.endX - self.startX) * progress; self.y = self.startY - Math.sin(progress * Math.PI) * self.arcHeight; // Calculate fade threshold and apply smooth fade based on moon's position var fadeThreshold = 0.8; // Start fade at 80% of moon's journey if (progress >= fadeThreshold) { var fadeProgress = (progress - fadeThreshold) / (1 - fadeThreshold); nightBackground.alpha = 1 - fadeProgress; } // Destroy the moon when it goes off-screen to the right if (self.x > self.endX) { self.destroy(); // Switch to day state isDay = true; isNight = false; DayCount += 1; // Increase day count by 1 dayCountDisplay.show(); // Show day count display // Stop spawning fireflies if (fireflySpawnInterval) { LK.clearInterval(fireflySpawnInterval); fireflySpawnInterval = null; } game.addChild(new Sun()); } }; }); // Class for the Obstacle (Duck, Eagle, and Fish combined) var Obstacle = Container.expand(function (type) { var self = Container.call(this); var graphics; var collisionBlock = self.addChild(new CollisionBlock()); collisionBlock.x = 0; collisionBlock.y = 0; graphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); // Add a Ripple instance to the Duck obstacle if (type === 'Duck') { self.lastRippleTime = Date.now(); var ripple = new Ripple(); ripple.x = 0; // Center the ripple on the Duck ripple.y = graphics.height / 2; // Position the ripple at the bottom of the Duck self.addChildAt(ripple, 0); // Add ripple below the Duck but above the water layer } self.speedX = -6; if (type === 'Fish') { self.isJumping = false; self.pauseTime = 0; graphics.tint = 0x4444ff; graphics.alpha = 0.7; } if (type === 'Fish') { self.speedX = -6; // Back to original fast swimming speed self.jumpSpeed = 0.05; // Slow jump speed control self.isJumping = false; self.isPausing = false; self.pauseTime = 0; self.lastSplashTime = Date.now(); // Add splash timer graphics.tint = 0x4444ff; // Set underwater blue tint initially graphics.alpha = 0.7; // Set underwater opacity initially self.isFalling = false; self.jumpVelocity = 0; self.jumpStartY = self.y; // Store original position self.jumpTime = 0; // Initialize jump time counter self.y = 2732 * 0.90; // Set Fish Y position to the bottom of the Coot's dive } if (type === 'Eagle') { self.lastFeatherTime = Date.now(); self.targetY = coot.isDiving || coot.isReturning ? coot.originalY : coot.y; self.speedY = (self.targetY - self.y) / 100; self.speedX = -8; // Add horizontal speed variable for eagle } self.update = function () { self.x += self.speedX * gameSpeed; if (type === 'Fish') { // Move horizontally self.x += self.speedX; // Generate underwater splash effects if (!self.isJumping && Date.now() - self.lastSplashTime >= 200) { // Generate every 200ms var numSplashes = Math.floor(Math.random() * 2) + 1; // 1-2 splashes for (var i = 0; i < numSplashes; i++) { var splash = new Splash(); splash.x = self.x + (Math.random() * graphics.width - graphics.width / 2); // Random position along fish body splash.y = self.y; splash.tint = 0x4444ff; // Match fish's underwater tint game.addChildAt(splash, game.getChildIndex(self) - 1); } self.lastSplashTime = Date.now(); } // Check if crossing under Coot if (self.x <= coot.x && !self.isJumping) { self.speedX = 0; graphics.alpha = 0; self.pauseTime += 0.02; // Increase pause time by reducing increment rate } // Add this check for when to reappear if (self.pauseTime >= 1 && !self.isJumping) { graphics.alpha = 1; graphics.rotation = Math.PI / 2; // Changed from -Math.PI/2 to rotate the other way self.isJumping = true; self.jumpStartY = self.y; self.jumpTime = 0; } // Handle jumping motion if (self.isJumping) { self.jumpTime += self.jumpSpeed; // Use slower jumpSpeed var jumpHeight = -Math.sin(self.jumpTime) * 864; // Increased by 20% from 720 to 864 self.y = self.jumpStartY + jumpHeight; // Generate bigger splash burst when jumping out if (self.jumpTime < 0.1) { // Only on first frame of jump var burstSplashes = Math.floor(Math.random() * 4) + 6; // 6-9 splashes (increased from 4-6) for (var i = 0; i < burstSplashes; i++) { var splash = new Splash(); splash.x = self.x + (Math.random() * graphics.width - graphics.width / 2); splash.y = self.jumpStartY - Math.random() * 200; // Make splashes go higher game.addChildAt(splash, game.getChildIndex(self) - 1); } } // Change tint based on height above water if (self.y < self.jumpStartY - 50) { graphics.tint = 0xffffff; // Normal color above water graphics.alpha = 1.0; } else { graphics.tint = 0x4444ff; // Blue tint in water graphics.alpha = 0.7; } if (self.jumpTime > Math.PI) { Obstacle.lastDestroyTime = Date.now(); console.log("Fish destroyed after jump at " + Date.now()); currentObstacle = null; // Add this line self.destroy(); } } // Normal destroy check if (self.x <= -self.width / 2) { self.destroy(); Obstacle.lastDestroyTime = Date.now(); } } else if (type === 'Eagle') { self.y += self.speedY; if (Date.now() - self.lastFeatherTime >= 900) { // Feather spawn every 900ms var numFeathers = Math.floor(Math.random() * 2) + 2; // Spawn 2-3 feathers for (var i = 0; i < numFeathers; i++) { var feather = new EagleFeather(); feather.x = self.x + (Math.random() * 20 - 10); // Slight horizontal variation feather.y = self.y + graphics.height / 2; game.addChildAt(feather, game.getChildIndex(self) - 1); } self.lastFeatherTime = Date.now(); } if (self.x <= -self.width / 2) { console.log("Checking for destruction: Eagle at " + self.x); self.destroy(); // Destroy the obstacle when it moves off-screen Obstacle.lastDestroyTime = Date.now(); // Set lastDestroyTime when destroyed console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime); } if (type === 'Eagle') { self.targetY = coot.originalY - coot.height / 4; // Aim slightly lower on the coot self.speedY = (self.targetY - self.y) / 50; } } else if (type === 'Duck') { // Add sinusoidal wave pattern travel for Duck if (type === 'Duck') { self.y += Math.sin(self.x * 0.00625) * 2.7; // Adjusted sinusoidal wave pattern with further reduced frequency and increased amplitude } // Ripple spawn logic if (Date.now() - self.lastRippleTime >= 500) { var ripple = new Ripple(); ripple.x = self.x; ripple.y = self.y + graphics.height / 2; game.addChildAt(ripple, game.getChildIndex(self) - 1); self.lastRippleTime = Date.now(); } // Existing destroy logic if (self.x <= -self.width / 2) { console.log("Checking for destruction: Duck at " + self.x); self.destroy(); Obstacle.lastDestroyTime = Date.now(); console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime); } } collisionBlock.x = 0; collisionBlock.y = 0; }; }); var PhoenixFeatherIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('PhoenixFeatherIcon', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (coot.hasPhoenixFeather) { iconGraphics.alpha = 1; // Full visibility when possessed } else { iconGraphics.alpha = 0.2; // Opaque when not possessed if (!coot.isInvincible) { iconGraphics.alpha = 0.2; // Reset to opaque after Phoenix event } } }; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); var powerUpGraphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); // Initialize power-up properties self.speedX = -5; // Speed of the power-up moving left self.collected = false; // Flag to check if the power-up is collected self.update = function () { // Add pulsating effect var pulseScale = 0.05 * Math.sin(LK.ticks * 0.1) + 1; powerUpGraphics.scale.set(pulseScale); // Add bobbing effect self.y += Math.sin(LK.ticks * 0.05) * 0.5; // Move the power-up left self.x += self.speedX * gameSpeed; // Check for collection by the Coot if (!self.collected && coot.intersects(self) && !(type === 'PhoenixFeather' && coot.hasPhoenixFeather)) { if (type === 'Shield' && coot.isShielded) { return; // Do not collect if shield is already active } self.collected = true; activatePowerUp(type); self.destroy(); } // Destroy the power-up if it goes off screen if (self.x < -powerUpGraphics.width / 2) { self.destroy(); } }; function activatePowerUp(type) { switch (type) { case 'CoinMagnet': // Implement CoinMagnet effect coot.isMagnetActive = true; // Set Coot to magnet state var magnetDuration = 15; LK.setTimeout(function () { coot.isMagnetActive = false; // Deactivate magnet after magnetDuration seconds }, magnetDuration * 1000); var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) { return p.type === 'CoinMagnet'; }); if (existingPowerUp) { existingPowerUp.timer = magnetDuration; // Reset timer to the specified duration coot.isMagnetActive = true; // Refresh power-up state } else { powerUpDisplay.addPowerUp('CoinMagnet', 15); } break; case 'Shield': // Implement Shield effect coot.isShielded = true; // Set Coot to shielded state var shieldGraphics = LK.getAsset('Shield', { anchorX: 0.5, anchorY: 0.5, scaleX: coot.width / 200, // Scale to cover Coot scaleY: coot.height / 197.12, // Scale to cover Coot alpha: 0.5 // Set opacity to 50% }); coot.addChild(shieldGraphics); // Attach shield to Coot coot.shieldGraphics = shieldGraphics; // Store reference to shield graphics // Define handleShieldHit function powerUpDisplay.addPowerUp('Shield', 15); break; case 'PhoenixFeather': // Implement PhoenixFeather effect coot.hasPhoenixFeather = true; // Set Coot to have Phoenix Feather var phoenixFeatherIcon = new PhoenixFeatherIcon(); phoenixFeatherIcon.x = heartIcons[0].x; // Align with the farthest left heart icon phoenixFeatherIcon.y = heartIcons[0].y + heartIcons[0].height + 10; // Position below the heart icon with some padding LK.gui.topRight.addChild(phoenixFeatherIcon); break; case 'PowerDash': // Implement PowerDash effect coot.isPowerDashActive = true; // Set Coot to PowerDash state var powerDashDuration = 30; LK.setTimeout(function () { coot.isPowerDashActive = false; // Deactivate PowerDash after powerDashDuration seconds }, powerDashDuration * 1000); var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) { return p.type === 'PowerDash'; }); if (existingPowerUp) { existingPowerUp.timer = powerDashDuration; // Reset timer to the specified duration coot.isPowerDashActive = true; // Refresh power-up state } else { powerUpDisplay.addPowerUp('PowerDash', 30); } break; case 'Warning': // Implement Warning effect coot.isWarningActive = true; // Set Coot to warning state var warningDuration = 30; LK.setTimeout(function () { coot.isWarningActive = false; // Deactivate warning after warningDuration seconds }, warningDuration * 1000); var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) { return p.type === 'Warning'; }); if (existingPowerUp) { existingPowerUp.timer = 30; // Reset timer coot.isWarningActive = true; // Refresh power-up state } else { powerUpDisplay.addPowerUp('Warning', 30); } break; } } }); var PowerUpDisplay = Container.expand(function () { var self = Container.call(this); self.x = 2048 / 2; // Center horizontally self.y = 2732 * 0.9; // Position at bottom center self.activePowerUps = []; self.update = function () { // Update each power-up display self.activePowerUps.forEach(function (powerUp, index) { powerUp.timer -= (Date.now() - powerUp.lastUpdateTime) / 1000; // Decrease timer based on real time powerUp.lastUpdateTime = Date.now(); // Update the last update time powerUp.text.setText(Math.max(0, Math.ceil(powerUp.timer)) + 's'); // Ensure timer doesn't show negative values // Remove power-up if timer reaches 0 if (powerUp.timer <= 0) { powerUp.icon.destroy(); powerUp.text.destroy(); self.activePowerUps.splice(index, 1); self.repositionPowerUps(); } }); }; self.addPowerUp = function (type, duration) { var iconAssetMap = { 'CoinMagnet': 'CoinMagnet', 'PhoenixFeather': 'PhoenixFeather', 'PowerDash': 'PowerDash', 'Warning': 'Warning' }; if (iconAssetMap[type]) { var icon = LK.getAsset(iconAssetMap[type], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0 }); } else { console.error("Power-up type not found in iconAssetMap: ", type); return; } var text = new Text2(duration + 's', { size: 100, fill: "#ffffff" }); text.anchor.set(0.5, 0.5); self.addChild(icon); self.addChild(text); self.activePowerUps.push({ icon: icon, text: text, timer: duration, type: type, // Store the type of power-up lastUpdateTime: Date.now() // Initialize last update time }); self.repositionPowerUps(); }; self.repositionPowerUps = function () { var totalWidth = self.activePowerUps.reduce(function (acc, powerUp) { return acc + powerUp.icon.width + powerUp.text.width + 40; // 40 is the new spacing }, 0); var startX = -totalWidth / 2; self.activePowerUps.forEach(function (powerUp) { powerUp.icon.x = startX + powerUp.icon.width / 2; powerUp.text.x = powerUp.icon.x + powerUp.icon.width / 2 + 40; // 40 is the new spacing between icon and text startX += powerUp.icon.width + powerUp.text.width + 20; }); }; }); var Ripple = Container.expand(function () { var self = Container.call(this); var rippleGraphics = self.attachAsset('Ripple', { anchorX: 0.5, anchorY: 0.5 }); self.initialScale = 0.05; self.growthRate = 0.02; self.fadeRate = 0.01; self.maxScale = 2.0; rippleGraphics.scaleX = self.initialScale; rippleGraphics.scaleY = self.initialScale; self.update = function () { console.log("Ripple update called"); rippleGraphics.scaleX += self.growthRate; rippleGraphics.scaleY += self.growthRate; rippleGraphics.alpha -= self.fadeRate; console.log("Ripple scale:", rippleGraphics.scaleX, "Ripple alpha:", rippleGraphics.alpha); if (rippleGraphics.scaleX >= self.maxScale || rippleGraphics.alpha <= 0) { console.log("Ripple destroyed"); self.destroy(); } }; }); // Static respawn delay property // Class for the water splash particles var Splash = Container.expand(function () { var self = Container.call(this); var scale = Math.random() * 0.75 + 0.25; var splashGraphics = self.attachAsset('Watersplash', { anchorX: 0.5, anchorY: 0.5, scaleX: scale, scaleY: scale }); self.speedX = Math.random() * 2 - 1; // Random speed in X direction self.speedY = -Math.random() * 5; // Random upward speed in Y direction self.gravity = 0.1; // Gravity to pull the particle down self.update = function () { self.x += self.speedX * gameSpeed; self.y += self.speedY * gameSpeed; self.speedY += self.gravity; // Apply gravity // Add rotation based on the speed of the particle self.rotation += self.speedX / 10; if (self.y > 2732) { // If the particle is below the screen self.destroy(); // Destroy the particle } }; }); var Sun = Container.expand(function () { var self = Container.call(this); var sunGraphics = self.attachAsset('Sun', { anchorX: 0.5, anchorY: 0.5 }); // Initialize sun properties self.startX = -sunGraphics.width / 2; // Start off-screen to the left self.startY = 2732 * 0.25; // 25% from the top self.endX = 2048 + sunGraphics.width / 2; // End off-screen to the right self.arcHeight = 2732 * 0.1; // Arc height self.duration = 2.5 * 60 * 60; // 2.5 minutes in ticks (assuming 60 FPS) self.ticks = 0; self.update = function () { self.ticks++; var progress = self.ticks / self.duration; self.x = self.startX + (self.endX - self.startX) * progress; self.y = self.startY - Math.sin(progress * Math.PI) * self.arcHeight; // Calculate fade threshold and apply smooth fade based on sun's position var fadeThreshold = 0.8; // Start fade at 80% of sun's journey if (progress >= fadeThreshold) { var fadeProgress = (progress - fadeThreshold) / (1 - fadeThreshold); nightBackground.alpha = fadeProgress; } // Destroy the sun when it goes off-screen to the right if (self.x > self.endX) { self.destroy(); // Switch to night state isDay = false; isNight = true; // Start spawning fireflies fireflySpawnInterval = LK.setInterval(function () { var newFirefly = new Firefly(); newFirefly.x = Math.random() * 2048; newFirefly.y = Math.random() * 2732; game.addChild(newFirefly); }, 1000); // Spawn a firefly every second game.addChild(new Moon()); } }; }); // Class for the water var Water = Container.expand(function () { var self = Container.call(this); var waterGraphics = self.attachAsset('Water', { anchorX: 0.5, anchorY: 0.7 }); self.speed = 2; self.update = function () { self.x -= self.speed * gameSpeed; // self.y = midgroundtrees1.y + midgroundtrees1.height / 2; if (self.x <= -self.width / 2) { self.x += self.width * 2; } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ function handleShieldHit() { // Remove shield asset if (coot.shieldGraphics) { coot.shieldGraphics.destroy(); coot.shieldGraphics = null; } coot.isShielded = false; coot.isInvincible = true; // Set Coot to invincible state // Flash effect for invincibility var flashInterval = LK.setInterval(function () { coot.children[0].alpha = coot.children[0].alpha === 1 ? 0.5 : 1; }, 100); LK.setTimeout(function () { LK.clearInterval(flashInterval); coot.children[0].alpha = 1; coot.isInvincible = false; }, 1500); } // Define a single obstacleTypes array as a constant var obstacleTypes = ['Duck', 'Eagle', 'Fish']; var obstacleSpawnChances = { Duck: 1, Eagle: 1, Fish: 1 }; Obstacle.getRandomDelay = function (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; Obstacle.spawnDelay = 6750; // Reduce default spawn delay by 25% to 6.75 seconds Obstacle.respawnDelay = { Eagle: Obstacle.getRandomDelay(2250, 3750), // Reduce Eagle respawn delay by 25% Duck: Obstacle.getRandomDelay(2250, 3750), // Reduce Duck respawn delay by 25% Fish: Obstacle.getRandomDelay(2250, 3750) // Reduce Fish respawn delay by 25% }; Obstacle.lastDestroyTime = Date.now() - 5000; // Initialize to ensure first spawn check passes console.log("Initial lastDestroyTime: " + Obstacle.lastDestroyTime); var background = game.addChild(LK.getAsset('Background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2048 / 2500, scaleY: 2732 / 2500 })); var nightBackground = game.addChild(LK.getAsset('NightBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 2048 / 2500, scaleY: 2732 / 2500, alpha: 0 })); var DayCount = 1; // Global variable to keep track of the number of days, initialized to 1 at game start // Initialize the sun after title screen var sun; var isDay = true; // Initialize day state var isNight = false; // Initialize night state // Initialize the midgroundtrees var midgroundtrees1 = game.addChild(new Midgroundtrees()); midgroundtrees1.x = 2048 / 2; midgroundtrees1.y = 2732 * 0.7; var midgroundtrees2 = game.addChild(new Midgroundtrees()); midgroundtrees2.x = 2048 / 2 + midgroundtrees2.width; midgroundtrees2.y = 2732 * 0.7; // Initialize the water var water1 = game.addChild(new Water()); water1.x = 2048 / 2; water1.y = midgroundtrees1.y + midgroundtrees1.height / 2; var water2 = game.addChild(new Water()); water2.x = 2048 / 2 + water2.width; water2.y = midgroundtrees2.y + midgroundtrees2.height / 2; // Initialize game logo var gameLogo = LK.getAsset('GameIcon', { anchorX: 0.5, anchorY: 0.5, x: -100, // Start off-screen to the left y: 2732 / 2 // Center vertically }); game.addChild(gameLogo); // Initialize game variables var coot; var dragStartY = null; // Initialize dragStartY to null var dragStartX = null; // Initialize dragStartX to null var gameSpeed = 0; // Global variable for game speed, set to 0 during title screen var isTitleScreen = true; // Flag to indicate if the game is in the title screen state var gameActive = false; // Flag to indicate if the game is actively being played var speedIncreaseInterval = 15000; // 15 seconds in milliseconds var maxGameSpeed = 4.0; // Maximum game speed var lastSpeedIncreaseTime = Date.now(); // Track the last time speed was increased var score = 0; var coinCount = 0; // Global variable to keep track of collected coins var currentObstacle = null; var warningIcon = null; // Initialize the foreground var foreground1 = new Foreground(); var foreground2 = new Foreground(); // Removed duplicate addChild calls for foregrounds game.addChild(foreground1); game.addChild(foreground2); foreground1.x = 2048 / 2; foreground1.y = 2732 * 0.9; foreground2.x = foreground1.x + foreground1.width; foreground2.y = 2732 * 0.9; foreground1.isFirst = true; foreground1.other = foreground2; foreground2.other = foreground1; // Validate positioning if (Math.abs(foreground2.x - (foreground1.x + foreground1.width)) > 1) { console.error("Foreground pieces are not correctly positioned!"); } // Add coin counter display var coinCounter = new Text2('0', { size: 150, // Increased size for better visibility fill: "#ffffff" }); coinCounter.anchor.set(1, 0); // Anchor to the top right corner // Add coin asset beside the coin counter var coinIcon = LK.getAsset('Coin', { anchorX: 1, anchorY: 0, x: -coinCounter.width - 10, // Position to the left of the counter with some padding y: 0 }); LK.gui.topRight.addChild(coinIcon); LK.gui.topRight.addChild(coinCounter); // Add heart icons to represent Coot's lives var heartIcons = []; for (var i = 0; i < 3; i++) { // Always create 3 heart icons var heartIcon = LK.getAsset('HeartLife', { anchorX: 0, anchorY: 0, x: -coinCounter.width - 10 - i * 110, y: coinIcon.height + 10 }); LK.gui.topRight.addChild(heartIcon); heartIcons.push(heartIcon); } // Update heart icons based on remaining lives heartIcons.forEach(function (icon, index) { icon.alpha = coot && index < coot.lives ? 1 : 0.2; // Dim the heart if life is lost }); // Initialize PowerUpDisplay after foregrounds are set up var powerUpDisplay = new PowerUpDisplay(); game.addChild(powerUpDisplay); var dayCountDisplay; game.update = function () { if (DayCount > 1 && !dayCountDisplay.visible) { dayCountDisplay.show(); } if (isTitleScreen) { // Only update background, midground trees, water, and foreground during title screen [midgroundtrees1, midgroundtrees2, water1, water2, foreground1, foreground2].forEach(function (element) { element.update(); }); // Animate game logo sliding in from the left if (gameLogo.x < 2048 / 2) { gameLogo.x += 30; // Slide in quickly } else { gameLogo.x = 2048 / 2; // Stop at center } return; // Exit update function to prevent further updates } coot.update(); // Increase game speed every 20 seconds if (!isTitleScreen && Date.now() - lastSpeedIncreaseTime >= speedIncreaseInterval) { if (gameSpeed < maxGameSpeed) { gameSpeed = Math.min(gameSpeed + 0.1, maxGameSpeed); // Decrease respawn delay for all obstacles Obstacle.respawnDelay.Eagle = Math.max(Obstacle.respawnDelay.Eagle - 500, 1000); Obstacle.respawnDelay.Duck = Math.max(Obstacle.respawnDelay.Duck - 500, 1000); Obstacle.respawnDelay.Fish = Math.max(Obstacle.respawnDelay.Fish - 500, 1000); } lastSpeedIncreaseTime = Date.now(); } // Removed the timer counter increment and display logic // Check for collision between the Coot and the Collision Block of the current obstacle if (currentObstacle && coot.intersects(currentObstacle.children[0])) { if (coot.isShielded) { handleShieldHit(); } else if (coot.isInvincible) { // Do nothing, invincible state } else { coot.lives -= 1; if (coot.lives <= 0 && coot.hasPhoenixFeather) { coot.hasPhoenixFeather = false; // Remove Phoenix Feather phoenixFeatherIcon.update(); // Update Phoenix Feather icon coot.lives = 3; // Refill all lives heartIcons.forEach(function (icon) { icon.alpha = 1; // Restore all heart icons }); // Add Phoenix effect coot.isInvincible = true; // Set Coot to invincible state LK.effects.flashScreen(0xff0000, 1000); // Flash screen red for 1 second var phoenix = LK.getAsset('Phoenix', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set initial opacity to 50% }); phoenix.x = 2048 / 2; phoenix.y = 2732 / 2; game.addChild(phoenix); LK.setTimeout(function () { phoenix.destroy(); // Destroy the Phoenix asset coot.isInvincible = false; // Remove invincibility after effect }, 1500); // Wait for 1.5 seconds } else if (coot.lives <= 0) { coot.isFalling = true; coot.fallStartY = coot.y; coot.fallRotation = 0; coot.fallSpeed = 5; heartIcons[0].alpha = 0.2; // Dim the last heart icon to indicate all lives lost } else { coot.isInvincible = true; heartIcons[coot.lives].alpha = 0.2; // Dim the heart icon to indicate a lost life // Flash effect for invincibility LK.effects.flashScreen(0xff0000, 100); // Flash screen red for 100ms var flashInterval = LK.setInterval(function () { coot.children[0].alpha = coot.children[0].alpha === 1 ? 0.5 : 1; }, 100); LK.setTimeout(function () { LK.clearInterval(flashInterval); coot.children[0].alpha = 1; coot.isInvincible = false; }, 1500); } } } // Update PowerUpDisplay powerUpDisplay.update(); // Update the midgroundtrees midgroundtrees1.update(); midgroundtrees2.update(); // Update the water water1.update(); water2.update(); // Update the current obstacle // Check if the current obstacle needs destruction if (currentObstacle && currentObstacle.x < -currentObstacle.width / 2) { currentObstacle.destroy(); Obstacle.lastDestroyTime = Date.now(); console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime); currentObstacle = null; } // Check if it's time to spawn a new obstacle if (gameActive && !currentObstacle) { var timeSinceLastDestroy = Date.now() - Obstacle.lastDestroyTime; if (timeSinceLastDestroy >= Obstacle.spawnDelay - 1000 && !warningIcon) { var totalChance = obstacleSpawnChances.Duck + obstacleSpawnChances.Eagle + obstacleSpawnChances.Fish; var randomChance = Math.random() * totalChance; var cumulativeChance = 0; for (var i = 0; i < obstacleTypes.length; i++) { cumulativeChance += obstacleSpawnChances[obstacleTypes[i]]; if (randomChance < cumulativeChance) { currentObstacleType = obstacleTypes[i]; obstacleSpawnChances[currentObstacleType] = 1; // Reset chance on spawn break; } } var warningIconClassMap = { 'Duck': DuckWarningIcon, 'Eagle': EagleWarningIcon, 'Fish': FishWarningIcon }; warningIcon = game.addChild(new warningIconClassMap[currentObstacleType]()); warningIcon.x = 2048 / 2; warningIcon.y = 2732 / 2; } if (timeSinceLastDestroy >= Obstacle.spawnDelay) { if (warningIcon) { warningIcon.destroy(); warningIcon = null; } console.log("Selected obstacle type: ", currentObstacleType); currentObstacle = game.addChild(new Obstacle(currentObstacleType)); currentObstacle.x = 2048 + currentObstacle.width / 2; // Ensure it starts off-screen currentObstacle.y = currentObstacleType === 'Duck' ? 2732 * 0.80 : currentObstacleType === 'Eagle' ? 2732 * 0.25 : 2732 * 0.85; console.log("Spawned " + currentObstacleType + " at " + Date.now()); // Increase spawn chance for obstacles not selected obstacleTypes.forEach(function (type) { if (type !== currentObstacleType) { obstacleSpawnChances[type] += 0.5; // Increase chance by 0.5 for each non-selected obstacle } }); } } if (currentObstacle) { currentObstacle.update(); } // Check for collision between the Coot and Coins game.children.forEach(function (child) { if (child instanceof Coin && coot.intersects(child) && !child.collecting) { child.collecting = true; child.targetX = 2048 + child.children[0].width; // Target off-screen to the right child.targetY = -child.children[0].height; // Target off-screen to the top } }); // Update the foreground foreground1.update(); foreground2.update(); // Spawn butterflies randomly if (isDay && LK.ticks % 720 == 0) { // Every 3 seconds at 60 FPS var newButterfly = new Butterfly(); newButterfly.x = 2048 + newButterfly.width / 2; // Start off-screen to the right newButterfly.y = Math.random() * (2732 * 0.6) + 2732 * 0.2; // Random Y position within midground tree layer game.addChild(newButterfly); } // Spawn coins randomly if (LK.ticks % 120 == 0) { // Every 2 seconds at 60 FPS var newCoin = new Coin(); newCoin.x = 2048 + newCoin.width / 2; // Start off-screen to the right newCoin.y = Math.random() * (2732 * 0.45) + 2732 * 0.35; // Random Y position between 35% and 80% of the screen height game.addChild(newCoin); } // Spawn power ups randomly if (LK.ticks % 720 == 0) { // Every 3 seconds at 60 FPS var powerUpTypes = ['CoinMagnet', 'Shield', 'PhoenixFeather', 'PowerDash', 'Warning']; var selectedPowerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)]; var newPowerup = new PowerUp(selectedPowerUpType); newPowerup.x = 2048 + newPowerup.width / 2; // Start off-screen to the right newPowerup.y = Math.random() * (2732 * 0.45) + 2732 * 0.35; // Random Y position between 35% and 80% of the screen height game.addChild(newPowerup); } }; // Handle touch events for jumping and diving game.down = function (x, y, obj) { if (isTitleScreen) { // Slide game logo offscreen to the right var slideOutInterval = LK.setInterval(function () { gameLogo.x += 50; // Slide out quickly if (gameLogo.x > 2048 + gameLogo.width / 2) { LK.clearInterval(slideOutInterval); } }, 16); isTitleScreen = false; // Exit title screen state gameSpeed = 1.2; // Set initial game speed gameActive = true; // Set gameActive to true when gameplay starts Obstacle.lastDestroyTime = Date.now(); // Initialize lastDestroyTime when gameplay starts // Initialize Coot when exiting the title screen coot = new Coot(); coot.x = 2048 * 0.20; coot.y = 2732 * 0.75; coot.originalX = coot.x; // Initialize originalX position coot.originalY = coot.y; // Initialize originalY position game.addChildAt(coot, game.getChildIndex(foreground1) - 1); // Initialize heart icons based on Coot's lives heartIcons.forEach(function (icon, index) { icon.alpha = index < coot.lives ? 1 : 0.2; // Dim the heart if life is lost }); // Initialize the day count display after exiting the title screen dayCountDisplay = new DayCountDisplay(); LK.gui.top.addChild(dayCountDisplay); dayCountDisplay.y = 2732 * 0.25; // Move down by 25% of the screen height // Set a timer to show the day count display after 3 seconds of game time LK.setTimeout(function () { dayCountDisplay.show(); }, 1500); // Initialize the sun after exiting the title screen sun = game.addChild(new Sun()); sun.x = sun.startX; sun.y = sun.startY; return; // Exit function to prevent further actions } dragStartY = y; // Record the initial y position when touch starts dragStartX = x; // Record the initial x position when touch starts }; game.move = function (x, y, obj) { if (dragStartY !== null && dragStartX !== null) { if (x - dragStartX > 50) { // Only allow dash during these states if PowerDash is active if (coot.isJumping || coot.isFalling || coot.isDiving || coot.isReturning || coot.returnDelay > 0) { // Check for PowerDash before allowing if (coot.isPowerDashActive) { coot.isDashing = true; } } else { // Normal dash on ground, no PowerDash needed coot.isDashing = true; } dragStartX = null; // Reset dragStartX to prevent repeated dashes } if (y - dragStartY > 50 && coot.y === coot.originalY) { // Check if the drag is downward and significant coot.dive(); dragStartY = null; // Reset dragStartY to prevent repeated dives } else if (dragStartY - y > 50 && coot.y === coot.originalY) { // Check if the drag is upward and significant coot.jump(); dragStartY = null; // Reset dragStartY to prevent repeated jumps } } }; game.up = function (x, y, obj) { dragStartY = null; // Reset dragStartY when touch ends dragStartX = null; // Reset dragStartX when touch ends };
/****
* Classes
****/
var Butterfly = Container.expand(function () {
var self = Container.call(this);
var butterflyTypes = ['GreenButterfly', 'PinkButterfly', 'YellowButterfly'];
var selectedType = butterflyTypes[Math.floor(Math.random() * butterflyTypes.length)];
var butterflyGraphics = self.attachAsset(selectedType, {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize butterfly properties
self.speedX = -2; // Speed of the butterfly moving left
self.flitAmplitude = 20; // Amplitude of the flitting motion
self.flitFrequency = 0.1; // Frequency of the flitting motion
self.startY = Math.random() * (2732 * 0.6) + 2732 * 0.2; // Random Y position within midground tree layer
self.update = function () {
// Move the butterfly left
self.x += self.speedX * gameSpeed;
// Apply flitting motion
self.y = self.startY + Math.sin(self.x * self.flitFrequency) * self.flitAmplitude;
// Simulate wing flapping by adjusting scale
var flapScale = 0.2 * Math.sin(LK.ticks * 0.3) + 1;
butterflyGraphics.scale.set(flapScale);
// Destroy the butterfly if it goes off screen
if (self.x < -butterflyGraphics.width / 2) {
self.destroy();
}
};
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('Coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize coin properties
self.rotationSpeed = 0.05; // Rotation speed for the coin
self.speedX = -5; // Speed of the coin moving left
self.collecting = false; // Flag to check if the coin is being collected
self.targetX = 0; // Target X position for collection animation
self.targetY = 0; // Target Y position for collection animation
self.update = function () {
// Generate GoldSparkle particles
if (Math.random() < 0.0525) {
var sparkle = new GoldSparkle();
sparkle.x = self.x + (Math.random() * coinGraphics.width - coinGraphics.width / 2);
sparkle.y = self.y + (Math.random() * coinGraphics.height - coinGraphics.height / 2);
sparkle.coin = self; // Associate sparkle with the coin
game.addChild(sparkle);
}
// Move the coin left
self.x += self.speedX * gameSpeed;
// Apply spin effect over Y axis
coinGraphics.scale.x = Math.sin(self.x * 0.015);
if (coot.isMagnetActive && !self.collecting && self.x < 2048 * 0.9) {
// Home in on Coot's location
self.targetX = coot.x;
self.targetY = coot.y;
self.collecting = true;
}
if (self.collecting) {
// Animate coin collection
self.x += (self.targetX - self.x) * 0.1;
self.y += (self.targetY - self.y) * 0.1;
coinGraphics.scale.x *= 0.90;
coinGraphics.scale.y *= 0.90;
// Check if the coin has reached the target position or is small enough
if (Math.abs(self.x - self.targetX) < 5 && Math.abs(self.y - self.targetY) < 5 || coinGraphics.scale.x < 0.1 && coinGraphics.scale.y < 0.1) {
// Destroy all sparkles attached to the coin
game.children.forEach(function (child) {
if (child instanceof GoldSparkle && child.coin === self) {
child.destroy();
}
});
self.destroy();
coinCount++;
coinCounter.setText(Math.min(coinCount, 999).toString());
coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter
return;
}
} else if (self.x < -coinGraphics.width / 2) {
// Destroy the coin if it goes off screen
self.destroy();
}
};
});
var CollisionBlock = Container.expand(function () {
var self = Container.call(this);
var collisionBlockGraphics = self.attachAsset('Collisionblock', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
});
// Assets will be automatically created and loaded by the LK engine based on their usage in the code.
// Example assets: 'coot', 'obstacle', 'background'
// Class for the main character, the American coot
var Coot = Container.expand(function () {
var self = Container.call(this);
var cootGraphics = self.attachAsset('coot', {
anchorX: 0.5,
anchorY: 0.5
});
self.originalX = self.x; // Store original X position
self.speed = 6.5;
self.dashSpeed = 15;
self.lives = 3; // Initialize Coot with three lives
self.dashDelay = 30;
self.isFalling = false;
self.isDashing = false;
self.fallRotation = 0; // Initialize fall rotation
self.dashTimer = 0;
self.jumpVelocity = 40; // Increased initial upward velocity for jump
self.gravity = 1.0; // Gravity to apply during jump
self.jumpHeight = 105;
self.isJumping = false;
self.isReturning = false; // New state to handle returning to top after diving
self.isInvincible = false; // Initialize invincible state
self.isShielded = false; // Initialize shielded state
self.isMagnetActive = false; // Initialize magnet state
self.isWarningActive = false; // Initialize warning state
self.isPowerDashActive = false; // Initialize PowerDash state
self.hasPhoenixFeather = false; // Initialize Phoenix Feather state
self.update = function () {
if (self.isJumping) {
self.y -= self.jumpVelocity;
self.jumpVelocity -= self.gravity;
if (self.jumpVelocity <= 0) {
self.isJumping = false;
self.isFalling = true;
self.fallStartY = self.y;
self.fallRotation = 0;
self.fallSpeed = 5;
}
} else if (self.isFalling) {
handleFalling();
} else if (self.isDiving) {
handleDiving();
} else if (self.returnDelay > 0) {
handleReturnDelay();
} else if (self.isReturning) {
handleReturning();
}
function handleFalling() {
if (self.lives <= 0) {
self.y -= self.fallSpeed;
self.fallRotation += 0.05;
cootGraphics.rotation = -self.fallRotation;
if (self.y <= self.fallStartY - 50) {
self.fallSpeed = -10;
}
if (self.y > 2732) {
LK.showGameOver();
}
} else {
self.y += self.gravity * 10; // Increase gravity effect during fall
if (self.y >= self.originalY) {
self.y = self.originalY;
self.isFalling = false;
self.jumpVelocity = 40;
self.isJumping = false;
}
cootGraphics.rotation = 0;
}
}
function handleDiving() {
self.y += self.speed * 1.5;
cootGraphics.alpha = Math.max(0.5, cootGraphics.alpha - 0.05);
cootGraphics.tint = 0x0000ff;
if (self.y >= 2732 * 0.90) {
self.y = 2732 * 0.90;
self.isDiving = false;
self.returnDelay = Date.now() + 1000;
}
}
function handleReturnDelay() {
if (Date.now() >= self.returnDelay) {
self.returnDelay = 0;
if (self.y >= 2732 * 0.90) {
self.isReturning = true;
}
}
}
function handleReturning() {
self.y -= self.speed * 1.5;
var transitionFactor = 1 - (self.y - self.originalY) / (2732 * 0.90 - self.originalY);
cootGraphics.alpha = 0.5 + 0.5 * transitionFactor;
var startTint = self.underwaterTint;
var endTint = 0xffffff;
var r = (startTint >> 16 & 0xff) + ((endTint >> 16 & 0xff) - (startTint >> 16 & 0xff)) * transitionFactor;
var g = (startTint >> 8 & 0xff) + ((endTint >> 8 & 0xff) - (startTint >> 8 & 0xff)) * transitionFactor;
var b = (startTint & 0xff) + ((endTint & 0xff) - (startTint & 0xff)) * transitionFactor;
cootGraphics.tint = (r << 16) + (g << 8) + b;
if (self.y <= self.originalY) {
self.y = self.originalY;
self.isReturning = false;
cootGraphics.alpha = 1.0;
cootGraphics.tint = 0xffffff;
}
if (self.isReturning) {
self.x += (self.originalX - self.x) * 0.1;
}
}
// Add wobble effect to the coot while running
if (!self.isJumping && !self.isDiving && !self.isReturning && !self.isFalling) {
cootGraphics.rotation = Math.sin(LK.ticks / 5) * 0.1; // Increase wobble speed by reducing the divisor
// Generate 1-2 water splash particles every 60 ticks (1 second) only when not jumping, diving, or falling
if (!self.isJumping && !self.isDiving && !self.isFalling && LK.ticks % 60 == 0) {
var numParticles = Math.floor(Math.random() * 2) + 1;
for (var i = 0; i < numParticles; i++) {
var splashLeft = new Splash();
splashLeft.x = self.x - cootGraphics.width / 2;
splashLeft.y = self.y + cootGraphics.height / 2;
game.addChildAt(splashLeft, game.getChildIndex(foreground1) - 1);
var splashRight = new Splash();
splashRight.x = self.x + cootGraphics.width / 2;
splashRight.y = self.y + cootGraphics.height / 2;
game.addChildAt(splashRight, game.getChildIndex(foreground1) - 1);
}
}
}
// Handle dash state
if (self.isDashing) {
if (self.dashTimer < self.dashDelay) {
// Dash forward
if (self.x < 2048 * 0.75) {
// Stop at 3/4 of screen width
self.x += self.dashSpeed * 1.1;
}
// Create echo trail effect only if PowerDash is active
if (self.isPowerDashActive) {
var echo = new EchoTrail();
echo.x = self.x;
echo.y = self.y;
game.addChild(echo);
}
self.dashTimer++;
} else {
var returnSpeed = 10; // Fixed return speed
self.x += Math.sign(self.originalX - self.x) * Math.min(returnSpeed, Math.abs(self.originalX - self.x));
if (Math.abs(self.x - self.originalX) < returnSpeed) {
self.x = self.originalX;
self.isDashing = false;
self.dashTimer = 0;
}
}
}
// Ensure smooth return to original position if falling and returning from a dash
if (self.isFalling && self.isReturning) {
var returnSpeed = 10; // Fixed return speed
self.x += Math.sign(self.originalX - self.x) * Math.min(returnSpeed, Math.abs(self.originalX - self.x));
if (Math.abs(self.x - self.originalX) < returnSpeed) {
self.x = self.originalX;
self.isReturning = false;
}
}
};
self.isDiving = false;
self.isDashing = false;
self.dashSpeed = 15;
self.dashDelay = 60;
self.dashTimer = 0;
self.originalX = self.x;
self.jump = function () {
if (canPerformAction()) {
self.isJumping = true;
self.originalX = self.x;
self.isReturning = false;
self.originalY = self.y;
}
};
self.dash = function () {
if (canPerformAction()) {
self.isDashing = true;
self.originalX = self.x;
self.dashTimer = 0;
}
};
self.dive = function () {
if (canPerformAction()) {
self.isDiving = true;
self.returnDelay = Date.now() + 5000;
self.isReturning = false;
self.underwaterTint = 0x4444ff;
self.originalX = self.x;
self.originalY = self.y;
self.y += self.speed * 2;
generateSplashParticles(2, 4);
}
};
function canPerformAction() {
return !self.isJumping && !self.isDiving && !self.isReturning && !self.isDashing;
}
function generateSplashParticles(min, max) {
var numParticles = Math.floor(Math.random() * (max - min + 1)) + min;
for (var i = 0; i < numParticles; i++) {
var splash = new Splash();
splash.x = self.x;
splash.y = self.y + cootGraphics.height / 2;
game.addChildAt(splash, game.getChildIndex(foreground1) - 1);
}
}
});
var DayCountDisplay = Container.expand(function () {
var self = Container.call(this);
var dayText = new Text2('Day ' + DayCount, {
size: 100,
fill: "#ffffff"
});
dayText.anchor.set(0.5, 0.5);
dayText.alpha = 0; // Set alpha to 0 by default
self.addChild(dayText);
self.show = function () {
dayText.setText('Day ' + DayCount);
dayText.alpha = 1;
LK.setTimeout(function () {
dayText.alpha = 0; // Set alpha back to 0 instead of destroying
}, 1500);
// Set a timer to make the day count display visible for 3 seconds every time the day count increases
LK.setTimeout(function () {
dayText.alpha = 1;
LK.setTimeout(function () {
dayText.alpha = 0;
}, 1500);
}, 1500);
};
});
var DuckWarningIcon = Container.expand(function () {
var self = Container.call(this);
var iconGraphics = self.attachAsset('DuckIcon', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.75
});
self.flashInterval = 0;
self.update = function () {
self.flashInterval++;
if (coot.isWarningActive) {
if (self.flashInterval % 30 < 15) {
iconGraphics.alpha = 0.75;
} else {
iconGraphics.alpha = 0.5;
}
} else {
iconGraphics.alpha = 0;
}
};
});
var EagleFeather = Container.expand(function () {
var self = Container.call(this);
var featherGraphics = self.attachAsset('Eaglefeather', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize feather properties
self.rotationSpeed = Math.random() * 0.02 - 0.01; // Random rotation speed
self.driftX = Math.random() * 2 - 1; // Random sideways drift
self.driftY = Math.random() * -1 - 0.5; // Upward drift
self.fadeRate = 0.005; // Fade out rate
self.update = function () {
self.x += self.driftX * gameSpeed;
self.y += self.driftY * gameSpeed;
featherGraphics.rotation += self.rotationSpeed;
featherGraphics.alpha -= self.fadeRate;
// Destroy feather when fully faded
if (featherGraphics.alpha <= 0) {
self.destroy();
}
};
});
var EagleWarningIcon = Container.expand(function () {
var self = Container.call(this);
var iconGraphics = self.attachAsset('EagleIcon', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.75
});
self.flashInterval = 0;
self.update = function () {
self.flashInterval++;
if (coot.isWarningActive) {
if (self.flashInterval % 30 < 15) {
iconGraphics.alpha = 0.75;
} else {
iconGraphics.alpha = 0.5;
}
} else {
iconGraphics.alpha = 0;
}
};
});
var EchoTrail = Container.expand(function () {
var self = Container.call(this);
var echoGraphics = self.attachAsset('coot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5 // Set initial transparency
});
self.fadeRate = 0.05; // Rate at which the echo fades
self.update = function () {
echoGraphics.alpha -= self.fadeRate;
if (echoGraphics.alpha <= 0) {
self.destroy();
}
};
});
var Firefly = Container.expand(function () {
var self = Container.call(this);
var fireflyGraphics = self.attachAsset('Firefly', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize firefly properties
self.speedX = Math.random() * 8 - 4; // Further increased random horizontal speed
self.speedY = Math.random() * 8 - 4; // Further increased random vertical speed
self.fadeRate = 0.005; // Much slower fade rate for slow pulsing
self.flickerTimer = Math.random() * 240 + 120; // Random flicker timer between 2 to 4 seconds
self.alphaDirection = 1; // Direction of alpha change (1 for fade in, -1 for fade out)
self.lifetime = Math.random() * 180 + 180; // Random lifetime between 3 to 5 seconds
self.update = function () {
// Move the firefly
self.x += self.speedX;
self.y += self.speedY;
// Create trail effect
var trail = new FireflyTrail();
trail.x = self.x;
trail.y = self.y;
game.addChild(trail);
// Loop around the screen
if (self.x < 0) {
self.x = 2048;
}
if (self.x > 2048) {
self.x = 0;
}
if (self.y < 0) {
self.y = 2732;
}
if (self.y > 2732) {
self.y = 0;
}
// Flicker effect
self.flickerTimer--;
if (self.flickerTimer <= 0) {
fireflyGraphics.alpha = Math.random(); // Random alpha for flicker
self.flickerTimer = Math.random() * 60 + 30; // Reset flicker timer
}
// Fade in and out
fireflyGraphics.alpha += self.fadeRate * self.alphaDirection;
if (fireflyGraphics.alpha <= 0 || fireflyGraphics.alpha >= 1) {
self.alphaDirection *= -1; // Reverse fade direction
}
// Destroy firefly after its lifetime
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
};
});
var FireflyTrail = Container.expand(function () {
var self = Container.call(this);
var trailGraphics = LK.getAsset('FireflyTrail', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
alpha: 1 // Initial transparency
});
self.fadeRate = 0.02; // Rate at which the trail fades
self.update = function () {
trailGraphics.alpha -= self.fadeRate;
if (trailGraphics.alpha <= 0) {
self.destroy();
}
};
});
var FishWarningIcon = Container.expand(function () {
var self = Container.call(this);
var iconGraphics = self.attachAsset('FishIcon', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.75
});
self.flashInterval = 0;
self.update = function () {
self.flashInterval++;
if (coot.isWarningActive) {
if (self.flashInterval % 30 < 15) {
iconGraphics.alpha = 0.75;
} else {
iconGraphics.alpha = 0.5;
}
} else {
iconGraphics.alpha = 0;
}
};
});
// Define a single obstacleTypes array as a constant
// Class for the foreground
var Foreground = Container.expand(function () {
var self = Container.call(this);
var foregroundGraphics = self.attachAsset('Foreground', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.isFirst = false; // Will be set during initialization
self.update = function () {
// Only move the first piece
if (self.isFirst) {
self.x -= self.speed * gameSpeed; // Apply gameSpeed to movement
// Move second piece to maintain fixed distance
self.other.x = self.x + self.width;
// Reset both pieces when first goes off screen
if (self.x < -self.width / 1.5) {
// Reset earlier - when piece is mostly off screen
self.x += self.width;
self.other.x = self.x + self.width;
}
}
};
});
var GoldSparkle = Container.expand(function () {
var self = Container.call(this);
var sparkleGraphics = self.attachAsset('GoldSparkle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = (Math.random() * 2 - 1) * 0.75; // Reduced horizontal speed by 25%
self.speedY = (Math.random() * 2 - 1) * 0.75; // Reduced vertical speed by 25%
self.fadeRate = 0.02; // Rate at which the sparkle fades
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
sparkleGraphics.alpha -= self.fadeRate;
if (sparkleGraphics.alpha <= 0) {
self.destroy();
}
};
});
// Class for the midgroundtrees
var Midgroundtrees = Container.expand(function () {
var self = Container.call(this);
var midgroundtreesGraphics = self.attachAsset('Midgroundtrees', {
anchorX: 0.5,
anchorY: 0.7
});
self.speed = 3;
self.update = function () {
self.x -= self.speed * gameSpeed;
// self.y = coot.y;
if (self.x <= -self.width / 2) {
self.x += self.width * 2;
}
};
});
var Moon = Container.expand(function () {
var self = Container.call(this);
var moonGraphics = self.attachAsset('Moon', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize moon properties
self.startX = -moonGraphics.width / 2; // Start off-screen to the left
self.startY = 2732 * 0.25; // 25% from the top
self.endX = 2048 + moonGraphics.width / 2; // End off-screen to the right
self.arcHeight = 2732 * 0.1; // Arc height
self.duration = 3.75 * 60 * 60; // 3.75 minutes in ticks (assuming 60 FPS)
self.ticks = 0;
self.update = function () {
self.ticks++;
var progress = self.ticks / self.duration;
self.x = self.startX + (self.endX - self.startX) * progress;
self.y = self.startY - Math.sin(progress * Math.PI) * self.arcHeight;
// Calculate fade threshold and apply smooth fade based on moon's position
var fadeThreshold = 0.8; // Start fade at 80% of moon's journey
if (progress >= fadeThreshold) {
var fadeProgress = (progress - fadeThreshold) / (1 - fadeThreshold);
nightBackground.alpha = 1 - fadeProgress;
}
// Destroy the moon when it goes off-screen to the right
if (self.x > self.endX) {
self.destroy();
// Switch to day state
isDay = true;
isNight = false;
DayCount += 1; // Increase day count by 1
dayCountDisplay.show(); // Show day count display
// Stop spawning fireflies
if (fireflySpawnInterval) {
LK.clearInterval(fireflySpawnInterval);
fireflySpawnInterval = null;
}
game.addChild(new Sun());
}
};
});
// Class for the Obstacle (Duck, Eagle, and Fish combined)
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
var graphics;
var collisionBlock = self.addChild(new CollisionBlock());
collisionBlock.x = 0;
collisionBlock.y = 0;
graphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
// Add a Ripple instance to the Duck obstacle
if (type === 'Duck') {
self.lastRippleTime = Date.now();
var ripple = new Ripple();
ripple.x = 0; // Center the ripple on the Duck
ripple.y = graphics.height / 2; // Position the ripple at the bottom of the Duck
self.addChildAt(ripple, 0); // Add ripple below the Duck but above the water layer
}
self.speedX = -6;
if (type === 'Fish') {
self.isJumping = false;
self.pauseTime = 0;
graphics.tint = 0x4444ff;
graphics.alpha = 0.7;
}
if (type === 'Fish') {
self.speedX = -6; // Back to original fast swimming speed
self.jumpSpeed = 0.05; // Slow jump speed control
self.isJumping = false;
self.isPausing = false;
self.pauseTime = 0;
self.lastSplashTime = Date.now(); // Add splash timer
graphics.tint = 0x4444ff; // Set underwater blue tint initially
graphics.alpha = 0.7; // Set underwater opacity initially
self.isFalling = false;
self.jumpVelocity = 0;
self.jumpStartY = self.y; // Store original position
self.jumpTime = 0; // Initialize jump time counter
self.y = 2732 * 0.90; // Set Fish Y position to the bottom of the Coot's dive
}
if (type === 'Eagle') {
self.lastFeatherTime = Date.now();
self.targetY = coot.isDiving || coot.isReturning ? coot.originalY : coot.y;
self.speedY = (self.targetY - self.y) / 100;
self.speedX = -8; // Add horizontal speed variable for eagle
}
self.update = function () {
self.x += self.speedX * gameSpeed;
if (type === 'Fish') {
// Move horizontally
self.x += self.speedX;
// Generate underwater splash effects
if (!self.isJumping && Date.now() - self.lastSplashTime >= 200) {
// Generate every 200ms
var numSplashes = Math.floor(Math.random() * 2) + 1; // 1-2 splashes
for (var i = 0; i < numSplashes; i++) {
var splash = new Splash();
splash.x = self.x + (Math.random() * graphics.width - graphics.width / 2); // Random position along fish body
splash.y = self.y;
splash.tint = 0x4444ff; // Match fish's underwater tint
game.addChildAt(splash, game.getChildIndex(self) - 1);
}
self.lastSplashTime = Date.now();
}
// Check if crossing under Coot
if (self.x <= coot.x && !self.isJumping) {
self.speedX = 0;
graphics.alpha = 0;
self.pauseTime += 0.02; // Increase pause time by reducing increment rate
}
// Add this check for when to reappear
if (self.pauseTime >= 1 && !self.isJumping) {
graphics.alpha = 1;
graphics.rotation = Math.PI / 2; // Changed from -Math.PI/2 to rotate the other way
self.isJumping = true;
self.jumpStartY = self.y;
self.jumpTime = 0;
}
// Handle jumping motion
if (self.isJumping) {
self.jumpTime += self.jumpSpeed; // Use slower jumpSpeed
var jumpHeight = -Math.sin(self.jumpTime) * 864; // Increased by 20% from 720 to 864
self.y = self.jumpStartY + jumpHeight;
// Generate bigger splash burst when jumping out
if (self.jumpTime < 0.1) {
// Only on first frame of jump
var burstSplashes = Math.floor(Math.random() * 4) + 6; // 6-9 splashes (increased from 4-6)
for (var i = 0; i < burstSplashes; i++) {
var splash = new Splash();
splash.x = self.x + (Math.random() * graphics.width - graphics.width / 2);
splash.y = self.jumpStartY - Math.random() * 200; // Make splashes go higher
game.addChildAt(splash, game.getChildIndex(self) - 1);
}
}
// Change tint based on height above water
if (self.y < self.jumpStartY - 50) {
graphics.tint = 0xffffff; // Normal color above water
graphics.alpha = 1.0;
} else {
graphics.tint = 0x4444ff; // Blue tint in water
graphics.alpha = 0.7;
}
if (self.jumpTime > Math.PI) {
Obstacle.lastDestroyTime = Date.now();
console.log("Fish destroyed after jump at " + Date.now());
currentObstacle = null; // Add this line
self.destroy();
}
}
// Normal destroy check
if (self.x <= -self.width / 2) {
self.destroy();
Obstacle.lastDestroyTime = Date.now();
}
} else if (type === 'Eagle') {
self.y += self.speedY;
if (Date.now() - self.lastFeatherTime >= 900) {
// Feather spawn every 900ms
var numFeathers = Math.floor(Math.random() * 2) + 2; // Spawn 2-3 feathers
for (var i = 0; i < numFeathers; i++) {
var feather = new EagleFeather();
feather.x = self.x + (Math.random() * 20 - 10); // Slight horizontal variation
feather.y = self.y + graphics.height / 2;
game.addChildAt(feather, game.getChildIndex(self) - 1);
}
self.lastFeatherTime = Date.now();
}
if (self.x <= -self.width / 2) {
console.log("Checking for destruction: Eagle at " + self.x);
self.destroy(); // Destroy the obstacle when it moves off-screen
Obstacle.lastDestroyTime = Date.now(); // Set lastDestroyTime when destroyed
console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime);
}
if (type === 'Eagle') {
self.targetY = coot.originalY - coot.height / 4; // Aim slightly lower on the coot
self.speedY = (self.targetY - self.y) / 50;
}
} else if (type === 'Duck') {
// Add sinusoidal wave pattern travel for Duck
if (type === 'Duck') {
self.y += Math.sin(self.x * 0.00625) * 2.7; // Adjusted sinusoidal wave pattern with further reduced frequency and increased amplitude
}
// Ripple spawn logic
if (Date.now() - self.lastRippleTime >= 500) {
var ripple = new Ripple();
ripple.x = self.x;
ripple.y = self.y + graphics.height / 2;
game.addChildAt(ripple, game.getChildIndex(self) - 1);
self.lastRippleTime = Date.now();
}
// Existing destroy logic
if (self.x <= -self.width / 2) {
console.log("Checking for destruction: Duck at " + self.x);
self.destroy();
Obstacle.lastDestroyTime = Date.now();
console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime);
}
}
collisionBlock.x = 0;
collisionBlock.y = 0;
};
});
var PhoenixFeatherIcon = Container.expand(function () {
var self = Container.call(this);
var iconGraphics = self.attachAsset('PhoenixFeatherIcon', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (coot.hasPhoenixFeather) {
iconGraphics.alpha = 1; // Full visibility when possessed
} else {
iconGraphics.alpha = 0.2; // Opaque when not possessed
if (!coot.isInvincible) {
iconGraphics.alpha = 0.2; // Reset to opaque after Phoenix event
}
}
};
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize power-up properties
self.speedX = -5; // Speed of the power-up moving left
self.collected = false; // Flag to check if the power-up is collected
self.update = function () {
// Add pulsating effect
var pulseScale = 0.05 * Math.sin(LK.ticks * 0.1) + 1;
powerUpGraphics.scale.set(pulseScale);
// Add bobbing effect
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
// Move the power-up left
self.x += self.speedX * gameSpeed;
// Check for collection by the Coot
if (!self.collected && coot.intersects(self) && !(type === 'PhoenixFeather' && coot.hasPhoenixFeather)) {
if (type === 'Shield' && coot.isShielded) {
return; // Do not collect if shield is already active
}
self.collected = true;
activatePowerUp(type);
self.destroy();
}
// Destroy the power-up if it goes off screen
if (self.x < -powerUpGraphics.width / 2) {
self.destroy();
}
};
function activatePowerUp(type) {
switch (type) {
case 'CoinMagnet':
// Implement CoinMagnet effect
coot.isMagnetActive = true; // Set Coot to magnet state
var magnetDuration = 15;
LK.setTimeout(function () {
coot.isMagnetActive = false; // Deactivate magnet after magnetDuration seconds
}, magnetDuration * 1000);
var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) {
return p.type === 'CoinMagnet';
});
if (existingPowerUp) {
existingPowerUp.timer = magnetDuration; // Reset timer to the specified duration
coot.isMagnetActive = true; // Refresh power-up state
} else {
powerUpDisplay.addPowerUp('CoinMagnet', 15);
}
break;
case 'Shield':
// Implement Shield effect
coot.isShielded = true; // Set Coot to shielded state
var shieldGraphics = LK.getAsset('Shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: coot.width / 200,
// Scale to cover Coot
scaleY: coot.height / 197.12,
// Scale to cover Coot
alpha: 0.5 // Set opacity to 50%
});
coot.addChild(shieldGraphics); // Attach shield to Coot
coot.shieldGraphics = shieldGraphics; // Store reference to shield graphics
// Define handleShieldHit function
powerUpDisplay.addPowerUp('Shield', 15);
break;
case 'PhoenixFeather':
// Implement PhoenixFeather effect
coot.hasPhoenixFeather = true; // Set Coot to have Phoenix Feather
var phoenixFeatherIcon = new PhoenixFeatherIcon();
phoenixFeatherIcon.x = heartIcons[0].x; // Align with the farthest left heart icon
phoenixFeatherIcon.y = heartIcons[0].y + heartIcons[0].height + 10; // Position below the heart icon with some padding
LK.gui.topRight.addChild(phoenixFeatherIcon);
break;
case 'PowerDash':
// Implement PowerDash effect
coot.isPowerDashActive = true; // Set Coot to PowerDash state
var powerDashDuration = 30;
LK.setTimeout(function () {
coot.isPowerDashActive = false; // Deactivate PowerDash after powerDashDuration seconds
}, powerDashDuration * 1000);
var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) {
return p.type === 'PowerDash';
});
if (existingPowerUp) {
existingPowerUp.timer = powerDashDuration; // Reset timer to the specified duration
coot.isPowerDashActive = true; // Refresh power-up state
} else {
powerUpDisplay.addPowerUp('PowerDash', 30);
}
break;
case 'Warning':
// Implement Warning effect
coot.isWarningActive = true; // Set Coot to warning state
var warningDuration = 30;
LK.setTimeout(function () {
coot.isWarningActive = false; // Deactivate warning after warningDuration seconds
}, warningDuration * 1000);
var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) {
return p.type === 'Warning';
});
if (existingPowerUp) {
existingPowerUp.timer = 30; // Reset timer
coot.isWarningActive = true; // Refresh power-up state
} else {
powerUpDisplay.addPowerUp('Warning', 30);
}
break;
}
}
});
var PowerUpDisplay = Container.expand(function () {
var self = Container.call(this);
self.x = 2048 / 2; // Center horizontally
self.y = 2732 * 0.9; // Position at bottom center
self.activePowerUps = [];
self.update = function () {
// Update each power-up display
self.activePowerUps.forEach(function (powerUp, index) {
powerUp.timer -= (Date.now() - powerUp.lastUpdateTime) / 1000; // Decrease timer based on real time
powerUp.lastUpdateTime = Date.now(); // Update the last update time
powerUp.text.setText(Math.max(0, Math.ceil(powerUp.timer)) + 's'); // Ensure timer doesn't show negative values
// Remove power-up if timer reaches 0
if (powerUp.timer <= 0) {
powerUp.icon.destroy();
powerUp.text.destroy();
self.activePowerUps.splice(index, 1);
self.repositionPowerUps();
}
});
};
self.addPowerUp = function (type, duration) {
var iconAssetMap = {
'CoinMagnet': 'CoinMagnet',
'PhoenixFeather': 'PhoenixFeather',
'PowerDash': 'PowerDash',
'Warning': 'Warning'
};
if (iconAssetMap[type]) {
var icon = LK.getAsset(iconAssetMap[type], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0
});
} else {
console.error("Power-up type not found in iconAssetMap: ", type);
return;
}
var text = new Text2(duration + 's', {
size: 100,
fill: "#ffffff"
});
text.anchor.set(0.5, 0.5);
self.addChild(icon);
self.addChild(text);
self.activePowerUps.push({
icon: icon,
text: text,
timer: duration,
type: type,
// Store the type of power-up
lastUpdateTime: Date.now() // Initialize last update time
});
self.repositionPowerUps();
};
self.repositionPowerUps = function () {
var totalWidth = self.activePowerUps.reduce(function (acc, powerUp) {
return acc + powerUp.icon.width + powerUp.text.width + 40; // 40 is the new spacing
}, 0);
var startX = -totalWidth / 2;
self.activePowerUps.forEach(function (powerUp) {
powerUp.icon.x = startX + powerUp.icon.width / 2;
powerUp.text.x = powerUp.icon.x + powerUp.icon.width / 2 + 40; // 40 is the new spacing between icon and text
startX += powerUp.icon.width + powerUp.text.width + 20;
});
};
});
var Ripple = Container.expand(function () {
var self = Container.call(this);
var rippleGraphics = self.attachAsset('Ripple', {
anchorX: 0.5,
anchorY: 0.5
});
self.initialScale = 0.05;
self.growthRate = 0.02;
self.fadeRate = 0.01;
self.maxScale = 2.0;
rippleGraphics.scaleX = self.initialScale;
rippleGraphics.scaleY = self.initialScale;
self.update = function () {
console.log("Ripple update called");
rippleGraphics.scaleX += self.growthRate;
rippleGraphics.scaleY += self.growthRate;
rippleGraphics.alpha -= self.fadeRate;
console.log("Ripple scale:", rippleGraphics.scaleX, "Ripple alpha:", rippleGraphics.alpha);
if (rippleGraphics.scaleX >= self.maxScale || rippleGraphics.alpha <= 0) {
console.log("Ripple destroyed");
self.destroy();
}
};
});
// Static respawn delay property
// Class for the water splash particles
var Splash = Container.expand(function () {
var self = Container.call(this);
var scale = Math.random() * 0.75 + 0.25;
var splashGraphics = self.attachAsset('Watersplash', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: scale,
scaleY: scale
});
self.speedX = Math.random() * 2 - 1; // Random speed in X direction
self.speedY = -Math.random() * 5; // Random upward speed in Y direction
self.gravity = 0.1; // Gravity to pull the particle down
self.update = function () {
self.x += self.speedX * gameSpeed;
self.y += self.speedY * gameSpeed;
self.speedY += self.gravity; // Apply gravity
// Add rotation based on the speed of the particle
self.rotation += self.speedX / 10;
if (self.y > 2732) {
// If the particle is below the screen
self.destroy(); // Destroy the particle
}
};
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('Sun', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize sun properties
self.startX = -sunGraphics.width / 2; // Start off-screen to the left
self.startY = 2732 * 0.25; // 25% from the top
self.endX = 2048 + sunGraphics.width / 2; // End off-screen to the right
self.arcHeight = 2732 * 0.1; // Arc height
self.duration = 2.5 * 60 * 60; // 2.5 minutes in ticks (assuming 60 FPS)
self.ticks = 0;
self.update = function () {
self.ticks++;
var progress = self.ticks / self.duration;
self.x = self.startX + (self.endX - self.startX) * progress;
self.y = self.startY - Math.sin(progress * Math.PI) * self.arcHeight;
// Calculate fade threshold and apply smooth fade based on sun's position
var fadeThreshold = 0.8; // Start fade at 80% of sun's journey
if (progress >= fadeThreshold) {
var fadeProgress = (progress - fadeThreshold) / (1 - fadeThreshold);
nightBackground.alpha = fadeProgress;
}
// Destroy the sun when it goes off-screen to the right
if (self.x > self.endX) {
self.destroy();
// Switch to night state
isDay = false;
isNight = true;
// Start spawning fireflies
fireflySpawnInterval = LK.setInterval(function () {
var newFirefly = new Firefly();
newFirefly.x = Math.random() * 2048;
newFirefly.y = Math.random() * 2732;
game.addChild(newFirefly);
}, 1000); // Spawn a firefly every second
game.addChild(new Moon());
}
};
});
// Class for the water
var Water = Container.expand(function () {
var self = Container.call(this);
var waterGraphics = self.attachAsset('Water', {
anchorX: 0.5,
anchorY: 0.7
});
self.speed = 2;
self.update = function () {
self.x -= self.speed * gameSpeed;
// self.y = midgroundtrees1.y + midgroundtrees1.height / 2;
if (self.x <= -self.width / 2) {
self.x += self.width * 2;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
function handleShieldHit() {
// Remove shield asset
if (coot.shieldGraphics) {
coot.shieldGraphics.destroy();
coot.shieldGraphics = null;
}
coot.isShielded = false;
coot.isInvincible = true; // Set Coot to invincible state
// Flash effect for invincibility
var flashInterval = LK.setInterval(function () {
coot.children[0].alpha = coot.children[0].alpha === 1 ? 0.5 : 1;
}, 100);
LK.setTimeout(function () {
LK.clearInterval(flashInterval);
coot.children[0].alpha = 1;
coot.isInvincible = false;
}, 1500);
}
// Define a single obstacleTypes array as a constant
var obstacleTypes = ['Duck', 'Eagle', 'Fish'];
var obstacleSpawnChances = {
Duck: 1,
Eagle: 1,
Fish: 1
};
Obstacle.getRandomDelay = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Obstacle.spawnDelay = 6750; // Reduce default spawn delay by 25% to 6.75 seconds
Obstacle.respawnDelay = {
Eagle: Obstacle.getRandomDelay(2250, 3750),
// Reduce Eagle respawn delay by 25%
Duck: Obstacle.getRandomDelay(2250, 3750),
// Reduce Duck respawn delay by 25%
Fish: Obstacle.getRandomDelay(2250, 3750) // Reduce Fish respawn delay by 25%
};
Obstacle.lastDestroyTime = Date.now() - 5000; // Initialize to ensure first spawn check passes
console.log("Initial lastDestroyTime: " + Obstacle.lastDestroyTime);
var background = game.addChild(LK.getAsset('Background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2048 / 2500,
scaleY: 2732 / 2500
}));
var nightBackground = game.addChild(LK.getAsset('NightBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 2048 / 2500,
scaleY: 2732 / 2500,
alpha: 0
}));
var DayCount = 1; // Global variable to keep track of the number of days, initialized to 1 at game start
// Initialize the sun after title screen
var sun;
var isDay = true; // Initialize day state
var isNight = false; // Initialize night state
// Initialize the midgroundtrees
var midgroundtrees1 = game.addChild(new Midgroundtrees());
midgroundtrees1.x = 2048 / 2;
midgroundtrees1.y = 2732 * 0.7;
var midgroundtrees2 = game.addChild(new Midgroundtrees());
midgroundtrees2.x = 2048 / 2 + midgroundtrees2.width;
midgroundtrees2.y = 2732 * 0.7;
// Initialize the water
var water1 = game.addChild(new Water());
water1.x = 2048 / 2;
water1.y = midgroundtrees1.y + midgroundtrees1.height / 2;
var water2 = game.addChild(new Water());
water2.x = 2048 / 2 + water2.width;
water2.y = midgroundtrees2.y + midgroundtrees2.height / 2;
// Initialize game logo
var gameLogo = LK.getAsset('GameIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
// Start off-screen to the left
y: 2732 / 2 // Center vertically
});
game.addChild(gameLogo);
// Initialize game variables
var coot;
var dragStartY = null; // Initialize dragStartY to null
var dragStartX = null; // Initialize dragStartX to null
var gameSpeed = 0; // Global variable for game speed, set to 0 during title screen
var isTitleScreen = true; // Flag to indicate if the game is in the title screen state
var gameActive = false; // Flag to indicate if the game is actively being played
var speedIncreaseInterval = 15000; // 15 seconds in milliseconds
var maxGameSpeed = 4.0; // Maximum game speed
var lastSpeedIncreaseTime = Date.now(); // Track the last time speed was increased
var score = 0;
var coinCount = 0; // Global variable to keep track of collected coins
var currentObstacle = null;
var warningIcon = null;
// Initialize the foreground
var foreground1 = new Foreground();
var foreground2 = new Foreground();
// Removed duplicate addChild calls for foregrounds
game.addChild(foreground1);
game.addChild(foreground2);
foreground1.x = 2048 / 2;
foreground1.y = 2732 * 0.9;
foreground2.x = foreground1.x + foreground1.width;
foreground2.y = 2732 * 0.9;
foreground1.isFirst = true;
foreground1.other = foreground2;
foreground2.other = foreground1;
// Validate positioning
if (Math.abs(foreground2.x - (foreground1.x + foreground1.width)) > 1) {
console.error("Foreground pieces are not correctly positioned!");
}
// Add coin counter display
var coinCounter = new Text2('0', {
size: 150,
// Increased size for better visibility
fill: "#ffffff"
});
coinCounter.anchor.set(1, 0); // Anchor to the top right corner
// Add coin asset beside the coin counter
var coinIcon = LK.getAsset('Coin', {
anchorX: 1,
anchorY: 0,
x: -coinCounter.width - 10,
// Position to the left of the counter with some padding
y: 0
});
LK.gui.topRight.addChild(coinIcon);
LK.gui.topRight.addChild(coinCounter);
// Add heart icons to represent Coot's lives
var heartIcons = [];
for (var i = 0; i < 3; i++) {
// Always create 3 heart icons
var heartIcon = LK.getAsset('HeartLife', {
anchorX: 0,
anchorY: 0,
x: -coinCounter.width - 10 - i * 110,
y: coinIcon.height + 10
});
LK.gui.topRight.addChild(heartIcon);
heartIcons.push(heartIcon);
}
// Update heart icons based on remaining lives
heartIcons.forEach(function (icon, index) {
icon.alpha = coot && index < coot.lives ? 1 : 0.2; // Dim the heart if life is lost
});
// Initialize PowerUpDisplay after foregrounds are set up
var powerUpDisplay = new PowerUpDisplay();
game.addChild(powerUpDisplay);
var dayCountDisplay;
game.update = function () {
if (DayCount > 1 && !dayCountDisplay.visible) {
dayCountDisplay.show();
}
if (isTitleScreen) {
// Only update background, midground trees, water, and foreground during title screen
[midgroundtrees1, midgroundtrees2, water1, water2, foreground1, foreground2].forEach(function (element) {
element.update();
});
// Animate game logo sliding in from the left
if (gameLogo.x < 2048 / 2) {
gameLogo.x += 30; // Slide in quickly
} else {
gameLogo.x = 2048 / 2; // Stop at center
}
return; // Exit update function to prevent further updates
}
coot.update();
// Increase game speed every 20 seconds
if (!isTitleScreen && Date.now() - lastSpeedIncreaseTime >= speedIncreaseInterval) {
if (gameSpeed < maxGameSpeed) {
gameSpeed = Math.min(gameSpeed + 0.1, maxGameSpeed);
// Decrease respawn delay for all obstacles
Obstacle.respawnDelay.Eagle = Math.max(Obstacle.respawnDelay.Eagle - 500, 1000);
Obstacle.respawnDelay.Duck = Math.max(Obstacle.respawnDelay.Duck - 500, 1000);
Obstacle.respawnDelay.Fish = Math.max(Obstacle.respawnDelay.Fish - 500, 1000);
}
lastSpeedIncreaseTime = Date.now();
}
// Removed the timer counter increment and display logic
// Check for collision between the Coot and the Collision Block of the current obstacle
if (currentObstacle && coot.intersects(currentObstacle.children[0])) {
if (coot.isShielded) {
handleShieldHit();
} else if (coot.isInvincible) {
// Do nothing, invincible state
} else {
coot.lives -= 1;
if (coot.lives <= 0 && coot.hasPhoenixFeather) {
coot.hasPhoenixFeather = false; // Remove Phoenix Feather
phoenixFeatherIcon.update(); // Update Phoenix Feather icon
coot.lives = 3; // Refill all lives
heartIcons.forEach(function (icon) {
icon.alpha = 1; // Restore all heart icons
});
// Add Phoenix effect
coot.isInvincible = true; // Set Coot to invincible state
LK.effects.flashScreen(0xff0000, 1000); // Flash screen red for 1 second
var phoenix = LK.getAsset('Phoenix', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5 // Set initial opacity to 50%
});
phoenix.x = 2048 / 2;
phoenix.y = 2732 / 2;
game.addChild(phoenix);
LK.setTimeout(function () {
phoenix.destroy(); // Destroy the Phoenix asset
coot.isInvincible = false; // Remove invincibility after effect
}, 1500); // Wait for 1.5 seconds
} else if (coot.lives <= 0) {
coot.isFalling = true;
coot.fallStartY = coot.y;
coot.fallRotation = 0;
coot.fallSpeed = 5;
heartIcons[0].alpha = 0.2; // Dim the last heart icon to indicate all lives lost
} else {
coot.isInvincible = true;
heartIcons[coot.lives].alpha = 0.2; // Dim the heart icon to indicate a lost life
// Flash effect for invincibility
LK.effects.flashScreen(0xff0000, 100); // Flash screen red for 100ms
var flashInterval = LK.setInterval(function () {
coot.children[0].alpha = coot.children[0].alpha === 1 ? 0.5 : 1;
}, 100);
LK.setTimeout(function () {
LK.clearInterval(flashInterval);
coot.children[0].alpha = 1;
coot.isInvincible = false;
}, 1500);
}
}
}
// Update PowerUpDisplay
powerUpDisplay.update();
// Update the midgroundtrees
midgroundtrees1.update();
midgroundtrees2.update();
// Update the water
water1.update();
water2.update();
// Update the current obstacle
// Check if the current obstacle needs destruction
if (currentObstacle && currentObstacle.x < -currentObstacle.width / 2) {
currentObstacle.destroy();
Obstacle.lastDestroyTime = Date.now();
console.log("Obstacle destroyed at " + Obstacle.lastDestroyTime);
currentObstacle = null;
}
// Check if it's time to spawn a new obstacle
if (gameActive && !currentObstacle) {
var timeSinceLastDestroy = Date.now() - Obstacle.lastDestroyTime;
if (timeSinceLastDestroy >= Obstacle.spawnDelay - 1000 && !warningIcon) {
var totalChance = obstacleSpawnChances.Duck + obstacleSpawnChances.Eagle + obstacleSpawnChances.Fish;
var randomChance = Math.random() * totalChance;
var cumulativeChance = 0;
for (var i = 0; i < obstacleTypes.length; i++) {
cumulativeChance += obstacleSpawnChances[obstacleTypes[i]];
if (randomChance < cumulativeChance) {
currentObstacleType = obstacleTypes[i];
obstacleSpawnChances[currentObstacleType] = 1; // Reset chance on spawn
break;
}
}
var warningIconClassMap = {
'Duck': DuckWarningIcon,
'Eagle': EagleWarningIcon,
'Fish': FishWarningIcon
};
warningIcon = game.addChild(new warningIconClassMap[currentObstacleType]());
warningIcon.x = 2048 / 2;
warningIcon.y = 2732 / 2;
}
if (timeSinceLastDestroy >= Obstacle.spawnDelay) {
if (warningIcon) {
warningIcon.destroy();
warningIcon = null;
}
console.log("Selected obstacle type: ", currentObstacleType);
currentObstacle = game.addChild(new Obstacle(currentObstacleType));
currentObstacle.x = 2048 + currentObstacle.width / 2; // Ensure it starts off-screen
currentObstacle.y = currentObstacleType === 'Duck' ? 2732 * 0.80 : currentObstacleType === 'Eagle' ? 2732 * 0.25 : 2732 * 0.85;
console.log("Spawned " + currentObstacleType + " at " + Date.now());
// Increase spawn chance for obstacles not selected
obstacleTypes.forEach(function (type) {
if (type !== currentObstacleType) {
obstacleSpawnChances[type] += 0.5; // Increase chance by 0.5 for each non-selected obstacle
}
});
}
}
if (currentObstacle) {
currentObstacle.update();
}
// Check for collision between the Coot and Coins
game.children.forEach(function (child) {
if (child instanceof Coin && coot.intersects(child) && !child.collecting) {
child.collecting = true;
child.targetX = 2048 + child.children[0].width; // Target off-screen to the right
child.targetY = -child.children[0].height; // Target off-screen to the top
}
});
// Update the foreground
foreground1.update();
foreground2.update();
// Spawn butterflies randomly
if (isDay && LK.ticks % 720 == 0) {
// Every 3 seconds at 60 FPS
var newButterfly = new Butterfly();
newButterfly.x = 2048 + newButterfly.width / 2; // Start off-screen to the right
newButterfly.y = Math.random() * (2732 * 0.6) + 2732 * 0.2; // Random Y position within midground tree layer
game.addChild(newButterfly);
}
// Spawn coins randomly
if (LK.ticks % 120 == 0) {
// Every 2 seconds at 60 FPS
var newCoin = new Coin();
newCoin.x = 2048 + newCoin.width / 2; // Start off-screen to the right
newCoin.y = Math.random() * (2732 * 0.45) + 2732 * 0.35; // Random Y position between 35% and 80% of the screen height
game.addChild(newCoin);
}
// Spawn power ups randomly
if (LK.ticks % 720 == 0) {
// Every 3 seconds at 60 FPS
var powerUpTypes = ['CoinMagnet', 'Shield', 'PhoenixFeather', 'PowerDash', 'Warning'];
var selectedPowerUpType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var newPowerup = new PowerUp(selectedPowerUpType);
newPowerup.x = 2048 + newPowerup.width / 2; // Start off-screen to the right
newPowerup.y = Math.random() * (2732 * 0.45) + 2732 * 0.35; // Random Y position between 35% and 80% of the screen height
game.addChild(newPowerup);
}
};
// Handle touch events for jumping and diving
game.down = function (x, y, obj) {
if (isTitleScreen) {
// Slide game logo offscreen to the right
var slideOutInterval = LK.setInterval(function () {
gameLogo.x += 50; // Slide out quickly
if (gameLogo.x > 2048 + gameLogo.width / 2) {
LK.clearInterval(slideOutInterval);
}
}, 16);
isTitleScreen = false; // Exit title screen state
gameSpeed = 1.2; // Set initial game speed
gameActive = true; // Set gameActive to true when gameplay starts
Obstacle.lastDestroyTime = Date.now(); // Initialize lastDestroyTime when gameplay starts
// Initialize Coot when exiting the title screen
coot = new Coot();
coot.x = 2048 * 0.20;
coot.y = 2732 * 0.75;
coot.originalX = coot.x; // Initialize originalX position
coot.originalY = coot.y; // Initialize originalY position
game.addChildAt(coot, game.getChildIndex(foreground1) - 1);
// Initialize heart icons based on Coot's lives
heartIcons.forEach(function (icon, index) {
icon.alpha = index < coot.lives ? 1 : 0.2; // Dim the heart if life is lost
});
// Initialize the day count display after exiting the title screen
dayCountDisplay = new DayCountDisplay();
LK.gui.top.addChild(dayCountDisplay);
dayCountDisplay.y = 2732 * 0.25; // Move down by 25% of the screen height
// Set a timer to show the day count display after 3 seconds of game time
LK.setTimeout(function () {
dayCountDisplay.show();
}, 1500);
// Initialize the sun after exiting the title screen
sun = game.addChild(new Sun());
sun.x = sun.startX;
sun.y = sun.startY;
return; // Exit function to prevent further actions
}
dragStartY = y; // Record the initial y position when touch starts
dragStartX = x; // Record the initial x position when touch starts
};
game.move = function (x, y, obj) {
if (dragStartY !== null && dragStartX !== null) {
if (x - dragStartX > 50) {
// Only allow dash during these states if PowerDash is active
if (coot.isJumping || coot.isFalling || coot.isDiving || coot.isReturning || coot.returnDelay > 0) {
// Check for PowerDash before allowing
if (coot.isPowerDashActive) {
coot.isDashing = true;
}
} else {
// Normal dash on ground, no PowerDash needed
coot.isDashing = true;
}
dragStartX = null; // Reset dragStartX to prevent repeated dashes
}
if (y - dragStartY > 50 && coot.y === coot.originalY) {
// Check if the drag is downward and significant
coot.dive();
dragStartY = null; // Reset dragStartY to prevent repeated dives
} else if (dragStartY - y > 50 && coot.y === coot.originalY) {
// Check if the drag is upward and significant
coot.jump();
dragStartY = null; // Reset dragStartY to prevent repeated jumps
}
}
};
game.up = function (x, y, obj) {
dragStartY = null; // Reset dragStartY when touch ends
dragStartX = null; // Reset dragStartX when touch ends
};
American Coot sprite sheet. Running with wings up.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A beautiful blue sky background. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Grass and reeds foreground layer for endless runner. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
White water bubble. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A mallard floating on the water. Looking left. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A swimming salmon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A single golden coin with the head of an American Coot on it.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
The sun. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Game icon for a video game called “Coot Run”. Show an American Coot with its wings up and its foot big in the foreground. Show the name of the game big in the center with the coots foot underneath.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A moon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A starry sky background image. High resolution. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A fiery Phoenix with wings outspread.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A dark blue rectangle background with rounded edges to place text on top of for a menu.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
An owl with talons extended downwards and wings up. Looking down. Color Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A captain’s hat. Side profile. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A rainbow hat with a propeller on the top. Side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A striped beanie. Side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A white SVG with big bold letters, that says “Start”. A couple black feathers flying off the edge of the word. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A white SVG with big bold letters, that says “How to play”. A couple black feathers flying off the edge of the word. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A sombrero. Side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A knights helmet. Side view. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A horned Viking cap. Side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
An astronauts helmet. Side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A cowboy hat. Full side profile. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
duck
Sound effect
eagle
Sound effect
fishsplash
Sound effect
jumpsound
Sound effect
dashsound
Sound effect
backgroundmusic
Music
coin
Sound effect
powerup
Sound effect
coothurt
Sound effect
owl
Sound effect
phoenix
Sound effect
alert
Sound effect
cootdive
Sound effect
whistle
Sound effect