Code edit (6 edits merged)
Please save this source code
User prompt
update with: if (self.collecting && !self.tween) { // Create collection tween self.tween = tween(self, { x: self.targetX, y: self.targetY }, { duration: 500, // Half a second easing: tween.quartOut, onUpdate: function(progress) { // Scale down the coin as it moves coinGraphics.scale.set(1 - progress * 0.9); }, onFinish: function() { // Destroy all sparkles attached to the coin game.children.forEach(function (child) { if (child instanceof GoldSparkle && child.coin === self) { child.destroy(); } }); self.destroy(); coinCount++; storage.coins = coinCount; var displayCount = Math.min(coinCount, 999).toString(); if (coinCounter.text !== displayCount) { coinCounter.setText(displayCount); coinIcon.x = -coinCounter.width - 10; } // Check if 100 coins have been collected if (coinCount % 100 === 0) { // Add a heart icon and refill or add a life if (coot.lives < 3) { coot.lives++; heartIcons[coot.lives - 1].alpha = 1; // Restore the heart icon } } } }); } ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
Code edit (9 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Error: Invalid end type for property y: object' in or related to this line: 'tween(self, {' Line Number: 1522 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(self, {' Line Number: 1522 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
add: var ObjectPool = { pools: {}, getPool: function(type) { if (!this.pools[type]) { this.pools[type] = []; } return this.pools[type]; }, get: function(type, Constructor, initParams) { var pool = this.getPool(type); var obj; if (pool.length > 0) { obj = pool.pop(); if (typeof obj.reset === 'function') { obj.reset(initParams); } return obj; } else { return new Constructor(initParams); } }, recycle: function(type, object) { // Don't store null or undefined objects if (!object) return; var pool = this.getPool(type); // Limit pool size to prevent memory issues if (pool.length < 50) { // Clear any references that might cause memory leaks if (typeof object.cleanup === 'function') { object.cleanup(); } pool.push(object); } } };
User prompt
import tween plugin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
update with: coinCount++; storage.coins = coinCount; var displayCount = Math.min(coinCount, 999).toString(); if (coinCounter.text !== displayCount) { coinCounter.setText(displayCount); coinIcon.x = -coinCounter.width - 10; }
User prompt
remove all console logs
User prompt
Make sure the coin icon on the title screen adjusts its x position to align with the coin amount the same as it does in game.
User prompt
The coin counter should display player coins even on the title screen.
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'coinIcon.x = -coinCounter.width - 10')' in or related to this line: 'coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter' Line Number: 1520
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'coinIcon.x = -coinCounter.width - 10')' in or related to this line: 'coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter' Line Number: 1519
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'coinIcon.x = -coinCounter.width - 10')' in or related to this line: 'coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter' Line Number: 1519
User prompt
Make sure the coin counter loads the current saved coins when the game is initialized.
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'coinCounter.setText')' in or related to this line: 'coinCounter.setText(Math.min(coinCount, 999).toString()); // Update coinCounter text' Line Number: 1513
User prompt
Create a save function that keeps track of player coins between sessions. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Import the storage plugin. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Change the bottom text in the instruction screen to read “Jump over the Duck, Dive away from the Eagle/Owl, Dash away from the Fish.” Keep the same formatting.
User prompt
Make it so Eagles only spawn during the day and Owls only spawn at night.
User prompt
Change game speed increase to only happen every 30 seconds.
User prompt
Increase speed of owl moving left to -6
User prompt
Reduce owl dive speed by half.
User prompt
Add a shadow clone animation to owl during dive. Use the Coot powerdash animation as reference and handle appropriately.
/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1", { coins: 0 }); /**** * Classes ****/ // Initialize with default coins value 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 && 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++; storage.coins = coinCount; // Save coin count to storage coinCounter.setText(Math.min(coinCount, 999).toString()); coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter // Check if 100 coins have been collected if (coinCount % 100 === 0) { // Add a heart icon and refill or add a life if (coot.lives < 3) { coot.lives++; heartIcons[coot.lives - 1].alpha = 1; // Restore the heart icon } } 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.powerUpTimers = { 'CoinMagnet': { endTime: 0 }, 'PowerDash': { endTime: 0 }, 'Warning': { endTime: 0 } }; 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(); } // Define state key mapping for power-ups var stateKeyMap = { 'CoinMagnet': 'isMagnetActive', 'PowerDash': 'isPowerDashActive', 'Warning': 'isWarningActive' }; // Check power-up timers for (var powerUpType in self.powerUpTimers) { if (self.powerUpTimers.hasOwnProperty(powerUpType)) { var timer = self.powerUpTimers[powerUpType]; if (Date.now() >= timer.endTime) { var stateKey = stateKeyMap[powerUpType]; if (self[stateKey]) { self[stateKey] = false; // Deactivate the power-up console.log(powerUpType + " power-up deactivated"); } } } } 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: 0xFFFFFF }); 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, 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(); } }; }); var InstructionsButton = Container.expand(function () { var self = Container.call(this); var instructionsButtonGraphics = self.attachAsset('InstructionsButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function () { gameLogo.visible = false; if (gameLogo.playButton) { gameLogo.playButton.visible = false; } if (gameLogo.instructionsButton) { gameLogo.instructionsButton.visible = false; } showInstructions(); }; }); var InstructionsScreen = Container.expand(function () { var self = Container.call(this); var instructionsText = new Text2('Swipe up to jump,\ndown to dive,\nand right to dash!', { size: 80, fill: 0xFFFFFF, align: "center" }); instructionsText.anchor.set(0.5, 0); instructionsText.x = 2048 / 2; instructionsText.y = 2732 * 0.15; self.addChild(instructionsText); // Add power-up icons and explanations var powerUpsInfo = [{ type: 'CoinMagnet', text: 'Coin Magnet: Attracts coins' }, { type: 'Shield', text: 'Shield: Protects from one hit' }, { type: 'PhoenixFeather', text: 'Phoenix Feather: Revive once' }, { type: 'PowerDash', text: 'Power Dash: Dash while jumping or diving' }, { type: 'Warning', text: 'Warning: Alerts of upcoming obstacles' }]; powerUpsInfo.forEach(function (info, index) { var icon = LK.getAsset(info.type, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 300 - 2048 * 0.10, // Move icons further left y: 2732 * 0.30 + index * 200 }); self.addChild(icon); var text = new Text2(info.text, { size: 60, fill: 0xFFFFFF, align: "left" }); text.anchor.set(0, 0.5); text.x = 2048 / 2 - 300 + 2048 * 0.035 - 2048 * 0.07; text.y = icon.y + 20; self.addChild(text); }); var instructionDetails = new Text2('Jump over the Duck,\nDive away from the Eagle/Owl,\nDash away from the Fish.\n100 Coot Coins = 1 heart.', { size: 70, fill: 0xFFFFFF, align: "center" }); instructionDetails.anchor.set(0.5, 0); instructionDetails.x = 2048 / 2; instructionDetails.y = 2732 * 0.66; // Move up by 5% from the original position self.addChild(instructionDetails); var backButton = new Text2('Back', { size: 100, fill: 0xFFFFFF, fontWeight: "bold" }); backButton.anchor.set(0.5, 0.5); backButton.x = 2048 / 2; backButton.y = 2732 * 0.88; // Move back button down by 1.5% self.addChild(backButton); backButton.down = function () { self.menuBackground.destroy(); // Remove the MenuBackground self.destroy(); isTitleScreen = true; gameLogo.visible = true; if (gameLogo.playButton) { gameLogo.playButton.visible = true; } if (gameLogo.instructionsButton) { gameLogo.instructionsButton.visible = true; } }; }); // 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 = 2 * 60 * 60; // 2 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()); } }; }); // Moved Owl logic into Obstacle class 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 } if (type === 'Owl') { self.speedX = -6; // Speed of the owl moving left self.speedY = 0; // Initial vertical speed self.x = 2048 + graphics.width / 2; // Spawn at the top right of the screen self.isDiving = false; // Initialize isDiving state self.hasDived = false; // Initialize hasDived state to false by default } 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 / 2; // Aim slightly higher on the coot self.speedY = (self.targetY - self.y) / (50 / gameSpeed); } } 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); } } else if (type === 'Owl') { if (coot) { if (!self.isDiving && self.x > coot.x) { self.x += self.speedX * gameSpeed; // Move Owl left until it reaches Coot's X position } else { if (!self.hasDived) { self.isDiving = true; // Set isDiving state if (coot.intersects(collisionBlock)) { self.hasDived = true; // Set hasDived state only on intersection with Coot } self.speedX = 0; // Stop left movement if (!coot.isDiving) { self.speedY = (coot.y - self.y) / 40; // Adjust speed to track Coot's Y position at half speed self.y += self.speedY * gameSpeed; // Move Owl towards Coot self.x += (coot.x - self.x) / 20 * gameSpeed; // Move Owl towards Coot's X position } if (self.y >= coot.originalY) { self.isDiving = false; // Remove isDiving state self.speedX = -6; // Set speed to fly away to the left self.speedY = -3; // Add upward movement } else if (self.isDiving) { var shadowClone = new ShadowClone(); shadowClone.x = self.x; shadowClone.y = self.y; game.addChild(shadowClone); } } } // Check if Coot's state requires Owl to fly off if (self.isDiving && (coot.isDiving || coot.isReturning || coot.returnDelay > 0 || coot.intersects(collisionBlock))) { self.isDiving = false; // Remove isDiving state self.speedX = -6; // Set speed to fly away to the left self.speedY = -3; // Add upward movement self.x += self.speedX * gameSpeed; self.y += self.speedY * gameSpeed; // Move Owl upwards as it flies away if (self.x < -self.width / 2) { self.destroy(); // Remove Owl from the game when off-screen } } } } collisionBlock.x = 0; collisionBlock.y = 0; }; }); var OwlWarningIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('OwlIcon', { 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 PhoenixFeatherIcon = Container.expand(function () { var self = Container.call(this); var iconGraphics = self.attachAsset('PhoenixFeatherIcon', { anchorX: 0.5, anchorY: 0.5, alpha: 0.2 // Start dim, not opaque }); self.update = function () { iconGraphics.alpha = coot && coot.hasPhoenixFeather ? 1 : 0.2; // Set alpha based on possession }; }); var PlayButton = Container.expand(function () { var self = Container.call(this); var playButtonGraphics = self.attachAsset('PlayButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function () { // Exit title screen isTitleScreen = false; // Slide out all elements var slideOutInterval = LK.setInterval(function () { gameLogo.x += 50; self.x += 50; if (gameLogo.instructionsButton) { gameLogo.instructionsButton.x += 50; } if (gameLogo.x > 2048 + gameLogo.width / 2) { LK.clearInterval(slideOutInterval); self.destroy(); if (gameLogo.instructionsButton) { gameLogo.instructionsButton.destroy(); } // Start game after animations startGame(); } }, 16); }; }); 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)) { if (type === 'PhoenixFeather' && coot.hasPhoenixFeather || type === 'Shield' && coot.isShielded) { return; // Do not collect if 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) { var powerUpConfig = { 'CoinMagnet': { duration: 15000, state: 'isMagnetActive' }, 'PowerDash': { duration: 30000, state: 'isPowerDashActive' }, 'Warning': { duration: 30000, state: 'isWarningActive' }, 'Shield': { duration: 0, // Shield is instant and doesn't have a duration state: 'isShielded' }, 'PhoenixFeather': { duration: 0, // Phoenix Feather is instant and doesn't have a duration state: 'hasPhoenixFeather' } }; var config = powerUpConfig[type]; var startTime = Date.now(); console.log("Starting activatePowerUp for", type, "State:", coot[config.state]); if (config) { // Removed interval-based state management if (type === 'Shield') { coot.isShielded = true; coot.shieldGraphics = coot.addChild(LK.getAsset('Shield', { anchorX: 0.5, anchorY: 0.5, scaleX: coot.width / 200, // Scale to cover Coot scaleY: coot.height / 204.2, // Scale to cover Coot alpha: 0.5 // Set opacity to 50% })); return; // Exit early as Shield doesn't need a timer } if (type === 'PhoenixFeather') { coot.hasPhoenixFeather = true; return; // Exit early as Phoenix Feather doesn't need a timer } coot[config.state] = true; // Ensure state is set to true coot.powerUpTimers[type].endTime = Date.now() + config.duration; // Set power-up end time var existingPowerUp = powerUpDisplay.activePowerUps.find(function (p) { return p.type === type; }); if (existingPowerUp) { // Calculate remaining time in milliseconds var timeRemaining = existingPowerUp.startTime + existingPowerUp.duration - Date.now(); if (timeRemaining > 0) { config.duration += timeRemaining; // Add remaining time to new duration startTime = Date.now(); // Reset start time to now for accurate duration } LK.clearInterval(existingPowerUp.interval); existingPowerUp.startTime = Date.now(); // Update startTime to reflect new total duration existingPowerUp.duration = config.duration; // Update duration existingPowerUp.interval = createInterval(config, existingPowerUp.startTime); existingPowerUp.timer = config.duration / 1000; // Update visual timer console.log("Ending activatePowerUp for", type, "State:", coot[config.state]); return; // Exit early as we have updated the existing power-up } powerUpDisplay.addPowerUp(type, config.duration / 1000, startTime); // Include startTime for accurate remaining time } } }); 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 existingPowerUp = self.activePowerUps.find(function (p) { return p.type === type; }); if (existingPowerUp) { existingPowerUp.timer += duration; existingPowerUp.lastUpdateTime = Date.now(); existingPowerUp.text.setText(Math.max(0, Math.ceil(existingPowerUp.timer)) + 's'); // Update visual timer return; } var iconAssetMap = { 'CoinMagnet': 'CoinMagnet', 'PowerDash': 'PowerDash', 'Warning': 'Warning', 'Shield': 'Shield', 'PhoenixFeather': 'PhoenixFeather' }; 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: 0xFFFFFF }); text.anchor.set(0.5, 0.5); self.addChild(icon); self.addChild(text); self.activePowerUps.push({ icon: icon, text: text, timer: duration, type: type, lastUpdateTime: Date.now() }); 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(); } }; }); var ShadowClone = Container.expand(function () { var self = Container.call(this); var cloneGraphics = self.attachAsset('Owl', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set initial transparency }); self.fadeRate = 0.05; // Rate at which the clone fades self.update = function () { cloneGraphics.alpha -= self.fadeRate; if (cloneGraphics.alpha <= 0) { 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 * 60 * 60; // 2 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 ****/ // Define createInterval function to fix ReferenceError function createInterval(config, startTime) { return LK.setInterval(function () { var timeRemaining = config.duration - (Date.now() - startTime); if (timeRemaining <= 0) { LK.clearInterval(this); } }, 1000); } function showInstructions() { var menuBackground = LK.getAsset('MenuBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(menuBackground); var instructionsScreen = new InstructionsScreen(); game.addChild(instructionsScreen); instructionsScreen.menuBackground = menuBackground; // Store reference for later removal } function startGame() { gameSpeed = 1.5; // 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); coot.phoenixFeatherIcon = phoenixFeatherIcon; // Store reference in coot // 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; } 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', 'Owl']; var obstacleSpawnChances = { Duck: 1, Eagle: 1, Fish: 1, Owl: 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% Owl: Obstacle.getRandomDelay(2250, 3750) // Add Owl respawn delay }; 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 * 0.4 // Move up by 10% of the screen height }); 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 = 30000; // 30 seconds in milliseconds var maxGameSpeed = 5.0; // Maximum game speed var lastSpeedIncreaseTime = Date.now(); // Track the last time speed was increased var score = 0; var coinCount = storage.coins || 0; // Initialize coinCount from storage var coinCounter = new Text2('0', { size: 150, fill: 0xFFFFFF }); coinCounter.anchor.set(1, 0); // Anchor to the top right corner coinCounter.setText(Math.min(coinCount, 999).toString()); // Update coinCounter text if (coinCounter && coinCounter.width !== undefined) { coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter } 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: 0xFFFFFF }); 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); // Initialize Phoenix Feather icon at the start of the game var phoenixFeatherIcon = new PhoenixFeatherIcon(); // coot.phoenixFeatherIcon will be set after coot initialization phoenixFeatherIcon.x = heartIcons[0].x + heartIcons[0].width / 2 - phoenixFeatherIcon.width / 2; // Center below the leftmost heart icon phoenixFeatherIcon.y = heartIcons[0].y + heartIcons[0].height + 70; // Increase padding below the heart icon LK.gui.topRight.addChild(phoenixFeatherIcon); 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 } if (!gameLogo.playButton && !gameLogo.instructionsButton) { var playButton = new PlayButton(); playButton.x = 2048 / 2; playButton.y = gameLogo.y + gameLogo.height / 2 + 100 + 2732 * 0.06; // Move down by 6% of the screen height game.addChild(playButton); gameLogo.playButton = playButton; var instructionsButton = new InstructionsButton(); instructionsButton.x = 2048 / 2; instructionsButton.y = playButton.y + playButton.height; // Move up by 1% of the screen height game.addChild(instructionsButton); gameLogo.instructionsButton = instructionsButton; } return; // Exit update function to prevent further updates } if (coot) { coot.update(); } phoenixFeatherIcon.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); Obstacle.respawnDelay.Owl = Math.max(Obstacle.respawnDelay.Owl - 500, 1000); } lastSpeedIncreaseTime = Date.now(); } // Define createInterval function to fix ReferenceError // 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.Fish; if (isDay) { totalChance += obstacleSpawnChances.Eagle; } else if (isNight) { totalChance += obstacleSpawnChances.Owl; } var randomChance = Math.random() * totalChance; var cumulativeChance = 0; for (var i = 0; i < obstacleTypes.length; i++) { if (obstacleTypes[i] === 'Eagle' && isDay || obstacleTypes[i] === 'Owl' && isNight || obstacleTypes[i] !== 'Eagle' && obstacleTypes[i] !== 'Owl') { 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, 'Owl': OwlWarningIcon // Add OwlIcon to warning icons }; 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 : currentObstacleType === 'Fish' ? 2732 * 0.85 : 2732 * 0.10; // Owl positioned at 10% from the top 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 && 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); } // Calculate spawn interval based on coin magnet state var baseSpawnRate = 120; // Normal 2-second spawn rate var magnetSpawnRate = 30; // 25% faster (120 * 0.75 = 90) var currentSpawnRate = coot && coot.hasCoinMagnet ? magnetSpawnRate : baseSpawnRate; if (LK.ticks % currentSpawnRate == 0) { var newCoin = new Coin(); newCoin.x = 2048 + newCoin.width / 2; newCoin.y = Math.random() * (2732 * 0.45) + 2732 * 0.35; game.addChild(newCoin); } // Spawn power ups randomly if (LK.ticks % 1080 == 0) { // Every 3 seconds at 60 FPS var powerUpTypes = [{ type: 'Shield', weight: 20 }, { type: 'PowerDash', weight: 25 }, { type: 'CoinMagnet', weight: 25 }, { type: 'Warning', weight: 20 }, { type: 'PhoenixFeather', weight: 10 }]; var totalWeight = powerUpTypes.reduce(function (acc, powerUp) { return acc + powerUp.weight; }, 0); var randomWeight = Math.random() * totalWeight; var cumulativeWeight = 0; var selectedPowerUpType; for (var i = 0; i < powerUpTypes.length; i++) { cumulativeWeight += powerUpTypes[i].weight; if (randomWeight < cumulativeWeight) { selectedPowerUpType = powerUpTypes[i].type; break; } } // Check if Coot already has a shield or Phoenix feather if (selectedPowerUpType === 'Shield' && coot.isShielded || selectedPowerUpType === 'PhoenixFeather' && coot.hasPhoenixFeather) { // Skip spawning this power-up return; } 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) { 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 (!isTitleScreen && 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 && coot.originalY !== undefined && coot.y !== undefined && 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 };
===================================================================
--- original.js
+++ change.js
@@ -1470,9 +1470,9 @@
fill: 0xFFFFFF
});
coinCounter.anchor.set(1, 0); // Anchor to the top right corner
coinCounter.setText(Math.min(coinCount, 999).toString()); // Update coinCounter text
-if (coinCounter) {
+if (coinCounter && coinCounter.width !== undefined) {
coinIcon.x = -coinCounter.width - 10; // Update coin icon position to hug the coin counter
}
var currentObstacle = null;
var warningIcon = null;
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