/**** * Classes ****/ // Define the SmallObstacle class var BigObstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('bigobstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the Coin class var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } // Floating effect self.y += Math.sin(LK.ticks / 20) * 0.5; // Size changing effect self.scale.x = 1 + Math.sin(LK.ticks / 20) * 0.05; self.scale.y = 1 + Math.sin(LK.ticks / 20) * 0.05; }; }); // Define the LaneSeparator class var LaneSeparator = Container.expand(function () { var self = Container.call(this); var separatorGraphics = self.attachAsset('lineobstacle', { anchorX: 0.5, anchorY: 0.0, // Adjust anchor to top width: 15, height: 2732 // Set the height to cover the entire screen height }); separatorGraphics.height = 2732; // Ensure the height covers the entire screen height self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the LeftLaneOutline class var LeftLaneOutline = Container.expand(function () { var self = Container.call(this); var outlineGraphics = self.attachAsset('lineobstacle', { anchorX: 0.5, anchorY: 0.0, width: 15, height: 2732 // Set the height to cover the entire screen height }); outlineGraphics.height = 2732; // Ensure the height covers the entire screen height self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the LeftPlayer class var LeftPlayer = Container.expand(function () { var self = Container.call(this); var leftPlayerGraphics = self.attachAsset('leftplayer', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.update = function () { // Add any specific update logic for LeftPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; if (self && self.x !== undefined) { trail.x = self.x; } else { trail.x = 0; } trail.y = self && self.y !== undefined && self.height !== undefined ? self.y + self.height / 2 : 0; game.addChildAt(trail, game.getChildIndex(self)); } }; }); var LineObstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacleline', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the Obstacle class var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the Particle class var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5, tint: 0xffffff // Apply tint to particle graphics }); self.speed = Math.random() * 5 + 2; // Random speed for each particle self.direction = Math.random() * Math.PI * 2; // Random direction for each particle self.update = function () { self.x += Math.cos(self.direction) * self.speed; // Move the particle in the direction self.y += Math.sin(self.direction) * self.speed; self.alpha -= 0.01; // Fade out the particle if (self.alpha <= 0) { self.destroy(); } }; self.setTint = function (color) { particleGraphics.tint = color; }; }); // Define the Player class var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.shield = null; self.transitionToLane = function (targetX) { self.isMoving = true; self.targetX = targetX; if (self.x < self.targetX) { playerGraphics.rotation = Math.PI / 4; // Rotate player 45 degrees to the direction of movement } else { playerGraphics.rotation = -Math.PI / 4; // Rotate player -45 degrees to the direction of movement } }; self.update = function () { if (self.isInvulnerable) { self.invulnerableTimer--; if (!self.shield) { self.shield = self.addChild(LK.getAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set shield transparency })); // Play powerup sound when shield is activated LK.getSound('powerup').play(); } if (leftPlayer && !leftPlayer.shield) { leftPlayer.shield = leftPlayer.addChild(LK.getAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set shield transparency })); // Play powerup sound when left player's shield is activated LK.getSound('powerup').play(); } if (rightPlayer && !rightPlayer.shield) { rightPlayer.shield = rightPlayer.addChild(LK.getAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set shield transparency })); // Play powerup sound when right player's shield is activated LK.getSound('powerup').play(); } if (self.invulnerableTimer <= 0) { self.isInvulnerable = false; if (self.shield) { self.shield.destroy(); self.shield = null; } if (leftPlayer && leftPlayer.shield) { leftPlayer.shield.destroy(); leftPlayer.shield = null; } if (rightPlayer && rightPlayer.shield) { rightPlayer.shield.destroy(); rightPlayer.shield = null; } } else { // Update countdown text if (self.shieldCountdown) { self.shieldCountdown.setText(Math.ceil(self.invulnerableTimer / 120)); } // Add blinking effect when shield is about to disappear if (self.invulnerableTimer <= 120) { // Last 2 seconds if (LK.ticks % 30 < 15) { // Blink every 0.5 seconds self.shield.alpha = 0.2; } else { self.shield.alpha = 0.5; // Add blinking effect when shield is about to disappear if (self.invulnerableTimer <= 120) { // Last 2 seconds if (LK.ticks % 30 < 15) { // Blink every 0.5 seconds self.shield.alpha = 0.2; } else {} } self.shield.alpha = 0.5; // Add blinking effect when shield is about to disappear if (self.invulnerableTimer <= 120) { // Last 2 seconds if (LK.ticks % 30 < 15) { // Blink every 0.5 seconds self.shield.alpha = 0.2; } else {} } self.shield.alpha = 0.5; } } } } if (self.isMoving) { if (Math.abs(self.x - self.targetX) < self.speed) { self.x = self.targetX; self.isMoving = false; } else { self.x += (self.targetX - self.x) * 0.1; // Smooth movement using linear interpolation playerGraphics.rotation = self.x < self.targetX ? Math.PI / 4 : -Math.PI / 4; // Rotate player 45 degrees to the direction of movement } } else { // Smoothly transition player rotation back to its original position if (playerGraphics.rotation > 0) { playerGraphics.rotation -= 0.1; } else if (playerGraphics.rotation < 0) { playerGraphics.rotation += 0.1; } if (Math.abs(playerGraphics.rotation) < 0.1) { playerGraphics.rotation = 0; // Reset rotation when player is not moving } } if (!self.isJumping && self.visible) { if (self.isMoving && LK.ticks % 1 == 0) { var trail = new Trail(); trail.x = self.x; trail.y = self.y + playerGraphics.height / 2; game.addChild(trail); } else if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.x = self.x; trail.y = self.y + playerGraphics.height / 2; game.addChild(trail); } } if (self.isJumping) { if (self.y > self.jumpPeakY && !self.isFalling) { self.y -= self.jumpSpeed; playerGraphics.scale.x += 0.01; // Increase player size when moving up playerGraphics.scale.y += 0.01; if (self.shield) { self.shield.scale.x += 0.01; // Increase shield size when moving up self.shield.scale.y += 0.01; } } else { self.isFalling = true; self.y += self.jumpSpeed; playerGraphics.scale.x -= 0.01; // Decrease player size when falling down playerGraphics.scale.y -= 0.01; if (self.shield) { self.shield.scale.x -= 0.01; // Decrease shield size when falling down self.shield.scale.y -= 0.01; } if (self.y >= self.jumpStartY) { self.y = self.jumpStartY; self.isJumping = false; self.isFalling = false; playerGraphics.scale.x = 1; // Reset player size when not jumping playerGraphics.scale.y = 1; if (self.shield) { self.shield.scale.x = 1; // Reset shield size when not jumping self.shield.scale.y = 1; } // Destroy the player's shadow shadow.destroy(); } } // Reduce jump duration by 5% every 10 seconds if (LK.ticks % 600 == 0) { self.jumpSpeed *= 1.05; // Increase jump speed by 5% } } // Update shadow rotation to match player rotation if (shadow) { shadow.rotation = playerGraphics.rotation; } // Ensure player is always on top if it is a child of the game if (game.children.includes(self)) { game.setChildIndex(self, game.children.length - 1); } }; self.moveLeft = function () { if (!gameStarted) { for (var i = 0; i < starfield.length; i++) { starfield[i].update(); } return; } if (self.lane > 0 && !self.isMoving && !leftPlayer && !rightPlayer) { self.lane--; self.transitionToLane(lanes[self.lane]); LK.getSound('swipe').play(); LK.getSound('swipe').play(); } }; self.moveRight = function () { if (!gameStarted) { return; } // Prevent player movement when the home screen is up if (self.lane < 2 && !self.isMoving && !leftPlayer && !rightPlayer) { self.lane++; self.transitionToLane(lanes[self.lane]); LK.getSound('swipe').play(); } }; self.jump = function () { if (!self.isMoving && !self.isJumping && !leftPlayer && !rightPlayer) { self.isJumping = true; self.jumpStartY = self.y; self.jumpPeakY = self.y - 250; // Increase jump height self.jumpSpeed = 4; // Create the player's shadow shadow = new Shadow(); shadow.x = self.x; shadow.y = self.y; game.addChild(shadow); // Play jump sound when player jumps LK.getSound('jump').play(); } }; }); // Define the PowerUp class var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the PowerUpCenterLane class var PowerUpCenterLane = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the RightLaneOutline class var RightLaneOutline = Container.expand(function () { var self = Container.call(this); var outlineGraphics = self.attachAsset('lineobstacle', { anchorX: 0.5, anchorY: 0.0, width: 15, height: 2732 // Set the height to cover the entire screen height }); outlineGraphics.height = 2732; // Ensure the height covers the entire screen height self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the RightPlayer class var RightPlayer = Container.expand(function () { var self = Container.call(this); var rightPlayerGraphics = self.attachAsset('rightplayer', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.update = function () { // Add any specific update logic for RightPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; if (self && self.x !== undefined) { trail.x = self.x; } else { trail.x = 0; } trail.y = self && self.y !== undefined && self.height !== undefined ? self.y + self.height / 2 : 0; game.addChildAt(trail, game.getChildIndex(self)); } }; }); //<Assets used in the game will automatically appear here> // Define the Shadow class var Shadow = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, tint: 0x000000 // Set the color to black }); shadowGraphics.alpha = 0.5; // Dim the shadow self.update = function () { // The shadow's size changes based on the player's y position var scale = 1 - (player.y - self.y) / 1000; self.scale.x = scale; self.scale.y = scale; // Update the shadow's position to match the player's position self.x = player.x; // Rotate the shadow to match the player's rotation if (player.playerGraphics) { shadowGraphics.rotation = player.playerGraphics.rotation; } }; }); // Define the LineObstacle class var SmallObstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Define the SmallObstacleCenterCoinSides class var SmallObstacleCenterCoinSides = Container.expand(function () { var self = Container.call(this); var smallObstacle = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); var SmallObstacleMiddlePowerUpLeftCoinRight = Container.expand(function () { var self = Container.call(this); var smallObstacleMiddle = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 // Apply tint #a8ed15 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); var StairedSmallObstacle = Container.expand(function (lane, yOffset) { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, tint: 0xa8ed15 }); self.speed = gameSpeed; self.x = lanes[lane]; self.y = -self.height * 2 + yOffset; self.update = function () { self.y += self.speed; if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.speed = Math.random() * 2 + 1; // Random speed for each star self.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0 self.update = function () { self.y += self.speed; if (self.y > 2732) { self.y = -self.height; self.x = Math.random() * 2048; } }; }); // Function to spawn SmallObstacle in the center and Coins on the sides var TextObstacle = Container.expand(function (customText) { var self = Container.call(this); var textGraphics = new Text2(customText || 'Sample Text', { size: 120, fill: "#ffffff", align: "center", stroke: "#000000", strokeThickness: 10, border: true, borderColor: "#000000", borderWidth: 5 }); textGraphics.anchor.set(0.5, 0.5); self.addChild(textGraphics); self.speed = gameSpeed; self.update = function () { self.y += self.speed; self.hitbox = null; // Ensure TextObstacle does not collide with player if (self.y > 2732 + self.height / 2) { self.destroy(); } }; }); // Function to spawn SmallObstacle // Define the Trail class var Trail = Container.expand(function () { var self = Container.call(this); var trailGraphics = self.attachAsset('trail', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.speed = 5; self.update = function () { self.y += self.speed; self.alpha -= 0.02; // Fade out the trail faster self.scale.x -= 0.02; // Shrink the trail faster self.scale.y -= 0.02; // Shrink the trail faster if (self.y > 2732 || self.alpha <= 0 || self.scale.x <= 0 || self.scale.y <= 0) { self.destroy(); } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x101010 //Init game with even darker grey background }); /**** * Game Code ****/ function fadeOut(target, duration, onComplete) { var fadeStep = 1 / (duration / 16.67); // Assuming 60 FPS, 16.67ms per frame var fadeInterval = LK.setInterval(function () { if (target.alpha > 0) { target.alpha -= fadeStep; if (target.alpha < 0) { target.alpha = 0; } } else { LK.clearInterval(fadeInterval); if (onComplete) { onComplete(); } } }, 16.67); } function spawnStairedSmallObstacles() { var yOffset = 0; for (var i = 0; i < lanes.length; i++) { var lane = i; if (i === 1) { // Ensure the center lane obstacle is always in the same position yOffset = 0; } else { // Randomly choose positive or negative offset for left and right lanes yOffset = (Math.random() < 0.5 ? -1 : 1) * 350; } var stairedObstacle = new StairedSmallObstacle(lane, yOffset); if (!obstacles) { obstacles = []; } obstacles.push(stairedObstacle); game.addChild(stairedObstacle); } } function spawnSmallObstacleMiddlePowerUpLeftCoinRight() { var smallObstacleMiddle = new SmallObstacleMiddlePowerUpLeftCoinRight(); smallObstacleMiddle.x = lanes[1]; // Middle lane smallObstacleMiddle.y = -smallObstacleMiddle.height * 2; smallObstacleMiddle.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(smallObstacleMiddle); game.addChild(smallObstacleMiddle); var powerUpLeft = new PowerUp(); powerUpLeft.x = lanes[0]; // Left lane powerUpLeft.y = -powerUpLeft.height * 2; powerUpLeft.speed = gameSpeed; // Ensure constant speed if (!powerups) { powerups = []; } powerups.push(powerUpLeft); game.addChild(powerUpLeft); var coinRight = new Coin(); coinRight.x = lanes[2]; // Right lane coinRight.y = -coinRight.height * 2; coinRight.speed = gameSpeed; // Ensure constant speed if (!coins) { coins = []; } coins.push(coinRight); game.addChild(coinRight); } // New asset for obstacle line function checkBoundingBoxCollision(obj1, obj2) { var obj1Bounds = obj1.getBounds(); var obj2Bounds = obj2.getBounds(); var forgivenessX = obj1Bounds.width * 0.1; var forgivenessY = obj1Bounds.height * 0.1; return obj1Bounds.x < obj2Bounds.x + obj2Bounds.width - forgivenessX && obj1Bounds.x + obj1Bounds.width > obj2Bounds.x + forgivenessX && obj1Bounds.y < obj2Bounds.y + obj2Bounds.height - forgivenessY && obj1Bounds.y + obj1Bounds.height > obj2Bounds.y + forgivenessY; } // Function to spawn PowerUp in the center lane function spawnPowerUpCenterLane() { var powerUpCenterLane = new PowerUpCenterLane(); powerUpCenterLane.x = lanes[1]; // Center lane powerUpCenterLane.y = -powerUpCenterLane.height * 2; if (!powerups) { powerups = []; } powerups.push(powerUpCenterLane); game.addChild(powerUpCenterLane); } // Create main menu container var mainMenu = new Container(); game.addChildAt(mainMenu, game.children.length); // Play background music on main menu LK.playMusic('backgroundmusic'); // Create title text with background button var titleButton = new Container(); titleButton.update = function () { if (LK.ticks % 120 < 60) { titleButton.scale.x += 0.0001; titleButton.scale.y += 0.0001; } else { titleButton.scale.x -= 0.0001; titleButton.scale.y -= 0.0001; } }; // Removed titleBackground box var titleImage = LK.getAsset('homeTitle', { anchorX: 0.5, anchorY: 0.5 }); titleButton.addChild(titleImage); // Ensure lanes array is properly initialized before accessing its elements if (!lanes || lanes.length < 3) { console.error("Lanes array is not properly initialized."); lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array } titleButton.x = lanes[1]; // Center the title button over the middle lane titleButton.y = 2732 / 4; mainMenu.addChild(titleButton); // Create mode 1 button with background var mode1Button = new Container(); mode1Button.update = function () { if (LK.ticks % 120 < 60) { mode1Button.scale.x += 0.0001; mode1Button.scale.y += 0.0001; } else { mode1Button.scale.x -= 0.0001; mode1Button.scale.y -= 0.0001; } }; // Removed mode1ButtonBackground box var mode1ButtonImage = LK.getAsset('menu1', { anchorX: 0.5, anchorY: 0.5 }); mode1Button.addChild(mode1ButtonImage); mode1Button.x = lanes[1]; // Center the mode 1 button over the middle lane mode1Button.y = 2732 / 2; mainMenu.addChildAt(mode1Button, mainMenu.children.length); // Create mode 2 button with background var mode2Button = new Container(); mode2Button.update = function () { if (LK.ticks % 120 < 60) { mode2Button.scale.x += 0.0001; mode2Button.scale.y += 0.0001; } else { mode2Button.scale.x -= 0.0001; mode2Button.scale.y -= 0.0001; } }; // Removed mode2ButtonBackground box var mode2ButtonImage = LK.getAsset('menu2', { anchorX: 0.5, anchorY: 0.5 }); mode2Button.addChild(mode2ButtonImage); mode2Button.x = lanes[1]; // Center the mode 2 button over the middle lane mode2Button.y = 2732 / 2 + 400; mainMenu.addChildAt(mode2Button, mainMenu.children.length); // Add event listeners for buttons mode1Button.down = function () { LK.getSound('select').play(); startGame('mode1'); }; mode2Button.down = function () { LK.getSound('select').play(); startGame('mode2'); }; // Function to start the game function startGame(mode) { fadeOut(titleButton, 1000, function () { mainMenu.visible = false; }); fadeOut(mode1Button, 1000, function () { scoreTxt.visible = true; // Show score when game starts }); fadeOut(mode2Button, 1000, function () { scoreBackground.visible = true; // Show score background when game starts }); milesTxt.visible = true; // Show miles when game starts milesBackground.visible = true; // Show miles background when game starts // Background music is already playing from the main menu // Hide final score text on game start if (finalScoreTxt) { finalScoreTxt.visible = false; // Hide final score text on game start if (finalScoreTxt) { finalScoreTxt.visible = false; } } if (mode === 'mode1') { // Initialize mode 1 specific elements obstacleSpawnOrder = [{ type: 'TextObstacle', interval: 100, text: 'Swipe LEFT or RIGHT!' }, { type: 'SmallObstacle', interval: 100 }, { type: 'SmallObstacleLeftMiddleCoinRight', interval: 100 }, { type: 'SmallObstacleRightCenterCoinLeft', interval: 100 }, { type: 'TextObstacle', interval: 100, text: 'Swipe UP to JUMP!' }, { type: 'LineObstacle', interval: 100 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'TextObstacle', interval: 100, text: 'Swipe DOWN to SPLIT!' }, { type: 'BigObstacle', interval: 150 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'TextObstacle', interval: 100, text: 'Collect the SHIELD!' }, { type: 'PowerUpCenterLane', interval: 100 }, { type: 'ObstacleLine', interval: 50 }, { type: 'ObstacleLine', interval: 50 }, { type: 'ObstacleLine', interval: 50 }, { type: 'TextObstacle', interval: 100, text: 'You are READY!' }, { type: 'TextObstacle', interval: 100, text: 'Get ORBS for extra score!' }]; } else if (mode === 'mode2') { // Initialize mode 2 specific elements obstacleSpawnOrder = [{ type: 'SmallObstacle', interval: 100 }, { type: 'SmallObstacleLeftMiddleCoinRight', interval: 100 }, { type: 'SmallObstacleRightCenterCoinLeft', interval: 100 }, { type: 'LineObstacle', interval: 100 }, { type: 'SmallObstacleCenterCoinLeftPowerUpRight', interval: 100 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'SmallObstacleCenterCoinSides', interval: 100 }, { type: 'SmallObstacleMiddlePowerUpLeftCoinRight', interval: 100 }, { type: 'StairedSmallObstacles', interval: 100 }, { type: 'BigObstacle', interval: 150 }]; obstacleSpawnOrder = obstacleSpawnOrder.sort(function () { return Math.random() - 0.5; }); } // Start the game var timeout = LK.setTimeout(function () { gameStarted = true; }, 500); } // Function to spawn TextObstacle function spawnTextObstacle(customText) { var textObstacle = new TextObstacle(customText); textObstacle.x = 2048 / 2; // Center the TextObstacle textObstacle.y = -textObstacle.height * 2; if (!obstacles) { obstacles = []; } obstacles.push(textObstacle); game.addChild(textObstacle); } // Function to spawn powerups function spawnPowerUp(lane) { var powerup = new PowerUp(); powerup.lane = lane; powerup.x = lanes[powerup.lane]; powerup.y = -powerup.height * 2; powerups.push(powerup); game.addChild(powerup); } // Initialize gameStarted flag var gameStarted = false; // Initialize array for powerups var powerups = []; // Initialize shadow var shadow; // Initialize lanes var lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Ensure lanes array is properly initialized before accessing its elements if (!lanes || lanes.length < 3) { console.error("Lanes array is not properly initialized."); lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array } // Ensure lanes array is properly initialized before accessing its elements if (!lanes || lanes.length < 3) { console.error("Lanes array is not properly initialized."); lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array } // Initialize starfield // Initialize lane separators var laneSeparators = []; for (var i = 1; i < lanes.length; i++) { var separator = new LaneSeparator(); separator.x = (lanes[i - 1] + lanes[i]) / 2; // Position separator between lanes separator.y = 0; laneSeparators.push(separator); game.addChildAt(separator, 0); // Add lane separators at the bottom of the z axis } // Initialize lane outlines var leftLaneOutline = new LeftLaneOutline(); leftLaneOutline.x = lanes[0] - (lanes[1] - lanes[0]) / 2; // Position left outline to the left of the first lane leftLaneOutline.y = 0; game.addChildAt(leftLaneOutline, 0); // Add left lane outline at the bottom of the z axis var rightLaneOutline = new RightLaneOutline(); rightLaneOutline.x = lanes[2] + (lanes[2] - lanes[1]) / 2; // Position right outline to the right of the last lane rightLaneOutline.y = 0; game.addChildAt(rightLaneOutline, 0); // Add right lane outline at the bottom of the z axis // Initialize player var player = game.addChild(new Player()); player.jumpSpeed = 4; // Initialize jump speed player.hitbox = [player]; player.lane = 1; // Start in the middle lane player.x = lanes[player.lane]; player.y = 2732 - 200 - 350; // Declare left and right players var leftPlayer; var rightPlayer; // Initialize arrays for obstacles and coins var obstacles = []; var coins = []; // Initialize split duration timer var splitDuration = 120; // Duration in frames (2 seconds at 60 FPS) var splitTimer = 0; // Initialize score and final score text var score = 0; var finalScoreTxt = new Text2('Final Score: 0', { size: 100, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); finalScoreTxt.anchor.set(0.5, 0.5); finalScoreTxt.x = 2048 / 2; finalScoreTxt.y = 2732 / 2; finalScoreTxt.visible = false; LK.gui.center.addChild(finalScoreTxt); // Initialize game speed var gameSpeed = 5; // Initialize global spawn interval var globalSpawnInterval = 120; // Default interval in frames (2 seconds at 60 FPS) var spawnIntervalReductionTimer = 0; // Timer to track interval reduction var intervalReductionTimer = 0; // Timer to track interval reduction for obstacle spawn order var scoreTxt = new Text2('0', { size: 50, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); var scoreBackground = LK.getAsset('scoreBackground', { anchorX: 0.5, anchorY: 0.5, x: scoreTxt.x + 550, y: scoreTxt.y + scoreTxt.height / 2 + 200 }); scoreTxt.anchor.set(0.5, 0); scoreTxt.x += 600; scoreTxt.y += 200; scoreTxt.visible = false; // Hide score on main menu scoreBackground.visible = false; // Hide score background on main menu LK.gui.top.addChild(scoreBackground); LK.gui.top.addChild(scoreTxt); // Configuration for defining the order in which obstacles will spawn var obstacleSpawnOrder = [{ type: 'TextObstacle', // New TextObstacle type interval: 100, text: 'Swipe LEFT or RIGHT!' // Custom text for TextObstacle }, { type: 'SmallObstacle', interval: 100 }, { type: 'SmallObstacleLeftMiddleCoinRight', interval: 100 }, { type: 'SmallObstacleRightCenterCoinLeft', interval: 100 }, { type: 'TextObstacle', // New TextObstacle type interval: 100, text: 'Swipe UP to JUMP!' // Custom text for TextObstacle }, { type: 'LineObstacle', interval: 100 }, { type: 'SmallObstacleCenterCoinLeftPowerUpRight', interval: 100 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'TextObstacle', // New TextObstacle type interval: 100, text: 'Swipe DOWN to SPLIT!' // Custom text for TextObstacle }, { type: 'BigObstacle', interval: 100 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'LineObstacle', interval: 100 }, { type: 'SmallObstacleRightCenterCoinLeft', interval: 100 }, { type: 'TextObstacle', // New TextObstacle type interval: 100, text: 'Avoid the Obstacles!' // Custom text for TextObstacle }]; var currentObstacleIndex = 0; var obstacleSpawnTimer = 0; var obstacleSpawnOrderRandom = [{ type: 'SmallObstacle', interval: 100 }, { type: 'SmallObstacleLeftMiddleCoinRight', interval: 100 }, { type: 'SmallObstacleRightCenterCoinLeft', interval: 100 }, { type: 'LineObstacle', interval: 100 }, { type: 'SmallObstacleCenterCoinLeftPowerUpRight', interval: 100 }, { type: 'SmallObstaclesSidesCoinMiddle', interval: 100 }, { type: 'SmallObstacleCenterCoinSides', interval: 100 }, { type: 'StairedSmallObstacles', interval: 100 }, { type: 'BigObstacle', interval: 150 }]; // Initialize queue for predicting next obstacle var obstacleQueue = []; // Function to spawn obstacles function spawnObstacle(lane) { var obstacle; if (lane === undefined) { obstacle = new LineObstacle(); obstacle.x = 2048 / 2; // Center the LineObstacle } else { obstacle = new Obstacle(); obstacle.lane = lane; obstacle.x = lanes[obstacle.lane]; } obstacle.y = -obstacle.height * 2; obstacle.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(obstacle); game.addChild(obstacle); } // Function to spawn BigObstacle with specific rules function spawnBigObstacle() { var bigObstacle = new BigObstacle(); bigObstacle.x = 2048 / 2; // Center the BigObstacle bigObstacle.y = -bigObstacle.height / 2; if (!obstacles) { obstacles = []; } obstacles.push(bigObstacle); game.addChild(bigObstacle); } // Function to spawn coins function spawnCoin(lane) { var coin = new Coin(); coin.lane = lane; coin.x = lanes[coin.lane]; coin.y = -coin.height * 2; coins.push(coin); game.addChild(coin); } // Function to spawn powerups // Handle swipe events for player movement var touchStartX = 0; var touchStartY = 0; game.down = function (x, y, obj) { if (!gameStarted || leftPlayer || rightPlayer) { return; } // Prevent player movement when the home screen is up touchStartX = x; touchStartY = y; }; game.up = function (x, y, obj) { if (!gameStarted) { return; } // Prevent player movement when the home screen is up if (leftPlayer || rightPlayer) { return; // Disable touch screen while player is split } if (Math.abs(y - touchStartY) > Math.abs(x - touchStartX)) { if (y < touchStartY && !leftPlayer && !rightPlayer) { player.jump(); } else if (y > touchStartY && !leftPlayer && !rightPlayer && !player.isJumping && player.lane === 1) { // Animate leftPlayer and rightPlayer to move to the sides var leftTargetX = player.x - 650; var rightTargetX = player.x + 550; var animationDuration = 20; // Duration in frames (0.33 seconds at 60 FPS) if (!leftPlayer) { leftPlayer = new LeftPlayer(); leftPlayer.x = player.x; leftPlayer.y = player.y; game.addChild(leftPlayer); if (!rightPlayer) { rightPlayer = new RightPlayer(); rightPlayer.x = player.x; rightPlayer.y = player.y; game.addChild(rightPlayer); // Play swipe sound when player splits LK.getSound('swipe').play(); player.visible = false; // Hide the original player player.hitbox = [leftPlayer, rightPlayer]; // Move player hitbox to left and right players // Initialize update functions after adding to game if (!leftPlayer) { leftPlayer = new LeftPlayer(); leftPlayer.x = player.x; leftPlayer.y = player.y; game.addChild(leftPlayer); leftPlayer.update = function () { if (animationDuration > 0) { leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration; animationDuration--; } if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; if (leftPlayer && leftPlayer.x !== undefined) { trail.x = leftPlayer.x; } else { trail.x = 0; } trail.y = this.y + (leftPlayer.height ? leftPlayer.height / 2 : 0); game.addChildAt(trail, game.getChildIndex(this)); if (!rightPlayer) { rightPlayer = new RightPlayer(); rightPlayer.x = player.x; rightPlayer.y = player.y; game.addChild(rightPlayer); if (!rightPlayer) { rightPlayer = new RightPlayer(); rightPlayer.x = player.x; rightPlayer.y = player.y; game.addChild(rightPlayer); rightPlayer.update = function () { if (animationDuration > 0) { rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration; animationDuration--; } }; } } ; if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; if (rightPlayer && rightPlayer.x !== undefined) { trail.x = rightPlayer.x; } else { trail.x = 0; } trail.y = this.y + (rightPlayer.height ? rightPlayer.height / 2 : 0); game.addChildAt(trail, game.getChildIndex(this)); // Initialize update functions after adding to game leftPlayer.update = function () { if (animationDuration > 0) { leftPlayer.x += (leftTargetX - leftPlayer.x) * 0.1; // Smooth movement using linear interpolation animationDuration--; titleButton.update = function () { if (LK.ticks % 60 < 30) { titleButton.y += 1; } else {} ; titleButton.y -= 1; }; } }; } ; if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = leftPlayer ? leftPlayer.x : 0; trail.y = leftPlayer && leftPlayer.height ? leftPlayer.y + leftPlayer.height / 2 : 0; game.addChildAt(trail, game.getChildIndex(leftPlayer)); } } ; }; rightPlayer.update = function () { if (animationDuration > 0) { rightPlayer.x += (rightTargetX - rightPlayer.x) * 0.1; // Smooth movement using linear interpolation animationDuration--; } mode1Button.update = function () { if (LK.ticks % 60 < 30) { mode1Button.y += 1; } else { mode1Button.y -= 1; } }; if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = rightPlayer ? rightPlayer.x : 0; trail.y = rightPlayer && rightPlayer.height ? rightPlayer.y + rightPlayer.height / 2 : 0; game.addChildAt(trail, game.getChildIndex(rightPlayer)); } }; } } ; // Initialize update functions after adding to game leftPlayer.update = function () { if (animationDuration > 0) { leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration; animationDuration--; } mode2Button.update = function () { if (LK.ticks % 60 < 30) { mode2Button.y += 1; } else { mode2Button.y -= 1; } }; if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = leftPlayer.x; trail.y = leftPlayer && leftPlayer.y !== undefined ? leftPlayer.y + (leftPlayer.height ? leftPlayer.height / 2 : 0) : 0; game.addChildAt(trail, game.getChildIndex(leftPlayer)); } }; } ; rightPlayer.update = function () { if (animationDuration > 0) { rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration; animationDuration--; } // Add any specific update logic for RightPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = rightPlayer ? rightPlayer.x : 0; trail.y = rightPlayer.y + rightPlayer.height / 2; game.addChildAt(trail, game.getChildIndex(rightPlayer)); } }; // Initialize update functions after adding to game leftPlayer.update = function () { if (animationDuration > 0) { leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration; animationDuration--; } // Add any specific update logic for LeftPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = leftPlayer ? leftPlayer.x : 0; trail.y = leftPlayer && leftPlayer.y !== undefined ? leftPlayer.y + (leftPlayer.height ? leftPlayer.height / 2 : 0) : 0; game.addChildAt(trail, game.getChildIndex(leftPlayer)); } }; rightPlayer.update = function () { if (animationDuration > 0) { rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration; animationDuration--; } // Add any specific update logic for RightPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = rightPlayer.x; trail.y = rightPlayer.y + rightPlayer.height / 2; game.addChildAt(trail, game.getChildIndex(rightPlayer)); } }; } // Start split timer splitTimer = splitDuration; } else { if (x < touchStartX) { player.moveLeft(); } else { player.moveRight(); } } }; // Update game logic game.update = function () { // Update title button if (titleButton.update) { titleButton.update(); } // Update miles traveled milesTraveled += gameSpeed / 30; // Increase the speed at which miles are counted milesTxt.setText(Math.floor(milesTraveled)); // Update mode1 button mode1Button.update(); // Update mode2 button mode2Button.update(); // Update miles traveled milesTraveled += gameSpeed / 30; // Increase the speed at which miles are counted milesTxt.setText(Math.floor(milesTraveled)); if (!gameStarted) { // Update starfield return; } // Update lane separators for (var i = 0; i < laneSeparators.length; i++) { laneSeparators[i].update(); laneSeparators[i].children[0].height = 2732; // Ensure the height covers the entire screen height } // Update player player.update(); // Increase game speed and decrease global spawn interval over time spawnIntervalReductionTimer++; if (spawnIntervalReductionTimer >= 600) { // Every 10 seconds globalSpawnInterval = Math.max(30, globalSpawnInterval * 0.95); // Reduce spawn interval by 5% spawnIntervalReductionTimer = 0; // Reset timer } intervalReductionTimer++; if (intervalReductionTimer >= 600) { for (var i = 0; i < obstacleSpawnOrder.length; i++) { obstacleSpawnOrder[i].interval = Math.max(1, Math.floor(obstacleSpawnOrder[i].interval * 0.95)); } intervalReductionTimer = 0; } if (LK.ticks % 600 == 0) { globalSpawnInterval = Math.max(30, globalSpawnInterval * 0.95); // Reduce spawn interval by 5% every 10 seconds // Increase speed every 10 seconds gameSpeed *= 1.05; // Increase speed by 5% // Decrease global spawn interval to make spawns more frequent globalSpawnInterval = Math.max(30, globalSpawnInterval - 10); // Ensure interval doesn't go below 30 frames (0.5 seconds) } // Update obstacles, coins, and powerups for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].y += gameSpeed; powerups[i].update(); if (player && !player.isJumping && player.hitbox.some(function (hitbox) { return hitbox.intersects(powerups[i]); })) { player.isInvulnerable = true; player.invulnerableTimer = 600; // 10 seconds at 60 FPS if (leftPlayer && leftPlayer.update) { leftPlayer.isInvulnerable = true; leftPlayer.invulnerableTimer = 600; } if (rightPlayer && rightPlayer.update) { rightPlayer.isInvulnerable = true; rightPlayer.invulnerableTimer = 600; } powerups[i].destroy(); powerups.splice(i, 1); } } for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].y += gameSpeed; obstacles[i].update(); if (!player.isJumping && player.hitbox && player.hitbox.some(function (hitbox) { return checkBoundingBoxCollision(hitbox, obstacles[i]) && obstacles[i].hitbox !== null; })) { if (player.isInvulnerable) { // Spawn particles for (var j = 0; j < 50; j++) { var particle = new Particle(); particle.x = obstacles[i].x; particle.y = obstacles[i].y; particle.scale.set(1); // Increase the size of the particles particle.setTint(0xa8ed15); // Set particle color to match obstacle green tint game.addChild(particle); } // Play destroy sound when an obstacle is destroyed by the player with the shield LK.getSound('destroy').play(); obstacles[i].destroy(); obstacles.splice(i, 1); } else { LK.effects.flashScreen(0xffffff, 1000); // Calculate final score var finalScore = Math.floor(milesTraveled) + score * 100; LK.setScore(finalScore); // Display final score var finalScoreTxt = new Text2('Final Score: ' + finalScore, { size: 100, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); finalScoreTxt.anchor.set(0.5, 0.5); finalScoreTxt.x = 2048 / 2; finalScoreTxt.y = 2732 / 2; LK.gui.center.addChild(finalScoreTxt); // Calculate final score var finalScore = Math.floor(milesTraveled) + score * 100; // Display final score if (!finalScoreTxt) { finalScoreTxt = new Text2('Final Score: ' + finalScore, { size: 100, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); finalScoreTxt.anchor.set(0.5, 0.5); finalScoreTxt.x = 2048 / 2; finalScoreTxt.y = 2732 / 2; LK.gui.center.addChild(finalScoreTxt); } else { finalScoreTxt.setText('Final Score: ' + LK.getScore()); finalScoreTxt.visible = true; } // Calculate final score var finalScore = Math.floor(milesTraveled) + score * 100; // Display final score if (!finalScoreTxt) { finalScoreTxt = new Text2('Final Score: ' + finalScore, { size: 100, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); finalScoreTxt.anchor.set(0.5, 0.5); finalScoreTxt.x = 2048 / 2; finalScoreTxt.y = 2732 / 2; LK.gui.center.addChild(finalScoreTxt); } else { finalScoreTxt.setText('Final Score: ' + finalScore); finalScoreTxt.visible = true; } LK.getSound('gameover').play(); // Play gameover sound LK.stopMusic(); // Stop background music // Create a new black asset that covers the whole screen var gameOverCover = LK.getAsset('blackCover', { width: 2048, height: 2732, color: 0x000000, shape: 'box', alpha: 1 }); game.addChildAt(gameOverCover, game.children.length); player.destroy(); scoreTxt.destroy(); scoreBackground.destroy(); milesBackground.destroy(); milesTxt.destroy(); LK.setTimeout(function () { LK.showGameOver(); // Calling this will destroy the 'Game' and reset entire game state. }, 100); // Wait for 1 second (1000ms) before showing game over screen } } } // Handle obstacle spawning based on configuration obstacleSpawnTimer++; if (obstacleSpawnTimer >= obstacleSpawnOrder[currentObstacleIndex].interval) { var obstacleType = obstacleSpawnOrder[currentObstacleIndex].type; if (obstacleType === 'BigObstacle') { spawnBigObstacle(); } else if (obstacleType === 'LineObstacle') { spawnObstacle(); } else if (obstacleType === 'Obstacle') { spawnObstacle(); } else if (obstacleType === 'SmallObstacle') { spawnSmallObstacle(); } else if (obstacleType === 'SmallObstacleLeftMiddleCoinRight') { spawnSmallObstacleLeftMiddleCoinRight(); } else if (obstacleType === 'SmallObstacleRightCenterCoinLeft') { spawnSmallObstacleRightCenterCoinLeft(); } else if (obstacleType === 'SmallObstacleCenterCoinLeftPowerUpRight') { spawnSmallObstacleCenterCoinLeftPowerUpRight(); } else if (obstacleType === 'TextObstacle') { var customText = obstacleSpawnOrder[currentObstacleIndex].text || 'Default Text'; spawnTextObstacle(customText); } else if (obstacleType === 'ObstacleLine') { spawnObstacleLine(); } else if (obstacleType === 'SmallObstaclesSidesCoinMiddle') { spawnSmallObstaclesSidesCoinMiddle(); } else if (obstacleType === 'SmallObstacleCenterCoinSides') { spawnSmallObstacleCenterCoinSides(); } else if (obstacleType === 'SmallObstacleMiddlePowerUpLeftCoinRight') { spawnSmallObstacleMiddlePowerUpLeftCoinRight(); } else if (obstacleType === 'PowerUpCenterLane') { spawnPowerUpCenterLane(); } else if (obstacleType === 'StairedSmallObstacles') { spawnStairedSmallObstacles(); } currentObstacleIndex++; if (currentObstacleIndex >= obstacleSpawnOrder.length) { currentObstacleIndex = 0; if (obstacleSpawnOrder === obstacleSpawnOrderRandom) { obstacleSpawnOrder = obstacleSpawnOrderRandom.sort(function () { return Math.random() - 0.5; }); } else { obstacleSpawnOrder = obstacleSpawnOrderRandom; } } obstacleSpawnTimer = 0; } // Handle split duration and animate back to center if (splitTimer > 0) { splitTimer--; if (LK.ticks % 600 == 0) { splitDuration = Math.max(1, Math.floor(splitDuration * 0.95)); // Reduce split duration by 5% every 10 seconds } if (splitTimer === 0) { // Animate leftPlayer and rightPlayer back to the center var centerX = player.x; var animationDuration = 20; // Duration in frames (0.33 seconds at 60 FPS) // Initialize update functions after adding to game leftPlayer.update = function () { if (animationDuration > 0) { leftPlayer.x += (centerX - leftPlayer.x) * 0.1; // Smooth movement using linear interpolation animationDuration--; } else { leftPlayer.destroy(); leftPlayer = null; player.visible = true; player.hitbox = [player]; // Reset player hitbox to original player // Play swipe sound when player merges back together LK.getSound('swipe').play(); } // Add any specific update logic for LeftPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = leftPlayer ? leftPlayer.x : 0; trail.y = leftPlayer.y + leftPlayer.height / 2; game.addChildAt(trail, game.getChildIndex(leftPlayer)); } }; rightPlayer.update = function () { if (animationDuration > 0) { rightPlayer.x += (centerX - rightPlayer.x) * 0.1; // Smooth movement using linear interpolation animationDuration--; } else { rightPlayer.destroy(); rightPlayer = null; player.visible = true; player.hitbox = [player]; // Reset player hitbox to original player // Play swipe sound when player merges back together LK.getSound('swipe').play(); } // Add any specific update logic for RightPlayer here if (LK.ticks % 4 == 0) { var trail = new Trail(); trail.scale.x = 0.5; trail.scale.y = 0.5; trail.x = rightPlayer ? rightPlayer.x : 0; trail.y = rightPlayer.y + rightPlayer.height / 2; game.addChildAt(trail, game.getChildIndex(rightPlayer)); } }; } } for (var i = coins.length - 1; i >= 0; i--) { coins[i].y += gameSpeed; coins[i].update(); if (player && !player.isJumping && player.hitbox.some(function (hitbox) { return checkBoundingBoxCollision(hitbox, coins[i]); })) { score += 1; scoreTxt.setText(score); // Play bling sound LK.getSound('bling').play(); // Spawn particles for (var j = 0; j < 10; j++) { var particle = new Particle(); particle.x = coins[i].x; particle.y = coins[i].y; particle.setTint(0xffffff); // Set particle color to white game.addChild(particle); } coins[i].destroy(); coins.splice(i, 1); } } for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].y += gameSpeed; powerups[i].update(); if (player && !player.isJumping && player.hitbox.some(function (hitbox) { return checkBoundingBoxCollision(hitbox, powerups[i]); })) { player.isInvulnerable = true; player.invulnerableTimer = 600; // 10 seconds at 60 FPS LK.getSound('powerup').play(); // Play powerup sound LK.getSound('powerup').play(); // Play powerup sound powerups[i].destroy(); powerups.splice(i, 1); } } // Automatic spawning of obstacles, coins, and powerups has been removed }; // Function to spawn SmallObstacle function spawnSmallObstacle() { var smallObstacle = new SmallObstacle(); smallObstacle.x = 2048 / 2; // Center the SmallObstacle smallObstacle.y = -smallObstacle.height * 2; smallObstacle.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(smallObstacle); game.addChild(smallObstacle); } // Function to spawn SmallObstacle on left and middle lanes, and Coin on right lane function spawnSmallObstacleLeftMiddleCoinRight() { var smallObstacleLeft = new SmallObstacle(); var smallObstacleMiddle = new SmallObstacle(); var coinRight = new Coin(); smallObstacleLeft.x = lanes[0]; // Left lane smallObstacleMiddle.x = lanes[1]; // Middle lane coinRight.x = lanes[2]; // Right lane smallObstacleLeft.y = smallObstacleMiddle.y = coinRight.y = -smallObstacleLeft.height * 2; if (!obstacles) { obstacles = []; } if (!coins) { coins = []; } obstacles.push(smallObstacleLeft); obstacles.push(smallObstacleMiddle); coins.push(coinRight); game.addChild(smallObstacleLeft); game.addChild(smallObstacleMiddle); game.addChild(coinRight); // Ensure both obstacles and coin have the same speed var obstacleSpeed = gameSpeed; smallObstacleLeft.speed = smallObstacleMiddle.speed = coinRight.speed = obstacleSpeed; // Attach the obstacles together smallObstacleLeft.update = function () { this.y += this.speed; smallObstacleMiddle.y = this.y; // Move middle obstacle with left obstacle if (this.y > 2732 + this.height / 2) { this.destroy(); smallObstacleMiddle.destroy(); } }; smallObstacleMiddle.update = function () { // Empty update function to prevent individual movement }; } // Function to spawn SmallObstacle on right and center lanes, and Coin on left lane function spawnSmallObstacleRightCenterCoinLeft() { var smallObstacleRight = new SmallObstacle(); var smallObstacleCenter = new SmallObstacle(); var coinLeft = new Coin(); smallObstacleRight.x = lanes[2]; // Right lane smallObstacleCenter.x = lanes[1]; // Center lane coinLeft.x = lanes[0]; // Left lane smallObstacleRight.y = smallObstacleCenter.y = coinLeft.y = -smallObstacleRight.height * 2; if (!obstacles) { obstacles = []; } if (!coins) { coins = []; } obstacles.push(smallObstacleRight); obstacles.push(smallObstacleCenter); coins.push(coinLeft); game.addChild(smallObstacleRight); game.addChild(smallObstacleCenter); game.addChild(coinLeft); // Ensure both obstacles and coin have the same speed var obstacleSpeed = gameSpeed; smallObstacleRight.speed = smallObstacleCenter.speed = coinLeft.speed = obstacleSpeed; // Attach the obstacles together smallObstacleRight.update = function () { this.y += this.speed; smallObstacleCenter.y = this.y; // Move center obstacle with right obstacle if (this.y > 2732 + this.height / 2) { this.destroy(); smallObstacleCenter.destroy(); } }; smallObstacleCenter.update = function () { // Empty update function to prevent individual movement }; } // Function to spawn a line of obstacles function spawnObstacleLine() { for (var i = 0; i < lanes.length; i++) { var obstacle = new Obstacle(); obstacle.x = lanes[i]; obstacle.y = -obstacle.height * 2; if (!obstacles) { obstacles = []; } obstacles.push(obstacle); game.addChild(obstacle); } } function spawnSmallObstacleCenterCoinLeftPowerUpRight() { var smallObstacleCenter = new SmallObstacle(); smallObstacleCenter.x = lanes[1]; // Center lane smallObstacleCenter.y = -smallObstacleCenter.height * 2; smallObstacleCenter.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(smallObstacleCenter); game.addChild(smallObstacleCenter); var coinLeft = new Coin(); coinLeft.x = lanes[0]; // Left lane coinLeft.y = -coinLeft.height * 2; coinLeft.speed = gameSpeed; // Ensure constant speed if (!coins) { coins = []; } coins.push(coinLeft); game.addChild(coinLeft); var powerUpRight = new PowerUp(); powerUpRight.x = lanes[2]; // Right lane powerUpRight.y = -powerUpRight.height * 2; powerUpRight.speed = gameSpeed; // Ensure constant speed if (!powerups) { powerups = []; } powerups.push(powerUpRight); game.addChild(powerUpRight); } // Function to spawn SmallObstacles on the sides and a Coin in the middle function spawnSmallObstaclesSidesCoinMiddle() { var smallObstacleLeft = new SmallObstacle(); smallObstacleLeft.x = lanes[0]; // Left lane smallObstacleLeft.y = -smallObstacleLeft.height * 2; smallObstacleLeft.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(smallObstacleLeft); game.addChild(smallObstacleLeft); var smallObstacleRight = new SmallObstacle(); smallObstacleRight.x = lanes[2]; // Right lane smallObstacleRight.y = -smallObstacleRight.height * 2; smallObstacleRight.speed = gameSpeed; // Ensure constant speed obstacles.push(smallObstacleRight); game.addChild(smallObstacleRight); var coinMiddle = new Coin(); coinMiddle.x = lanes[1]; // Middle lane coinMiddle.y = -coinMiddle.height * 2; coinMiddle.speed = gameSpeed; // Ensure constant speed if (!coins) { coins = []; } coins.push(coinMiddle); game.addChild(coinMiddle); } // Function to spawn SmallObstacle in the center and Coins on the sides function spawnSmallObstacleCenterCoinSides() { var smallObstacleCenter = new SmallObstacleCenterCoinSides(); smallObstacleCenter.x = lanes[1]; // Center lane smallObstacleCenter.y = -smallObstacleCenter.height * 2; smallObstacleCenter.speed = gameSpeed; // Ensure constant speed if (!obstacles) { obstacles = []; } obstacles.push(smallObstacleCenter); game.addChild(smallObstacleCenter); var coinLeft = new Coin(); coinLeft.x = lanes[0]; // Left lane coinLeft.y = -coinLeft.height * 2; coinLeft.speed = gameSpeed; // Ensure constant speed if (!coins) { coins = []; } coins.push(coinLeft); game.addChild(coinLeft); var coinRight = new Coin(); coinRight.x = lanes[2]; // Right lane coinRight.y = -coinRight.height * 2; coinRight.speed = gameSpeed; // Ensure constant speed coins.push(coinRight); game.addChild(coinRight); } var starfield = []; for (var i = 0; i < 25; i++) { var star = new Star(); star.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0 star.x = Math.random() * 2048; star.y = Math.random() * 2732; star.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0 starfield.push(star); game.addChildAt(star, 0); // Add stars at the bottom of the z axis } // Initialize miles traveled var milesTraveled = 0; // Create miles traveled text var milesTxt = new Text2('Miles: 0', { size: 100, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); milesTxt.anchor.set(1, 0); // Anchor to the top-right corner milesTxt.x = 2048; // Position at the top-right corner milesTxt.y = 0; LK.gui.topRight.addChild(milesTxt); // Initialize miles traveled var milesTraveled = 0; // Create miles traveled text var milesTxt = new Text2('0', { size: 50, fill: "#ffffff", stroke: "#000000", strokeThickness: 5, border: true, borderColor: "#000000", borderWidth: 3 }); var milesBackground = LK.getAsset('milesBackground', { anchorX: 0.5, anchorY: 0.5, x: scoreTxt.x - 50, y: scoreTxt.y - 90 }); milesTxt.anchor.set(0.5, 0); milesTxt.x = scoreTxt.x - 10; milesTxt.y = scoreTxt.y - 120; milesTxt.visible = false; // Hide miles on main menu milesBackground.visible = false; // Hide miles background on main menu LK.gui.top.addChild(milesBackground); LK.gui.top.addChild(milesTxt);
/****
* Classes
****/
// Define the SmallObstacle class
var BigObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('bigobstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the Coin class
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
// Floating effect
self.y += Math.sin(LK.ticks / 20) * 0.5;
// Size changing effect
self.scale.x = 1 + Math.sin(LK.ticks / 20) * 0.05;
self.scale.y = 1 + Math.sin(LK.ticks / 20) * 0.05;
};
});
// Define the LaneSeparator class
var LaneSeparator = Container.expand(function () {
var self = Container.call(this);
var separatorGraphics = self.attachAsset('lineobstacle', {
anchorX: 0.5,
anchorY: 0.0,
// Adjust anchor to top
width: 15,
height: 2732 // Set the height to cover the entire screen height
});
separatorGraphics.height = 2732; // Ensure the height covers the entire screen height
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the LeftLaneOutline class
var LeftLaneOutline = Container.expand(function () {
var self = Container.call(this);
var outlineGraphics = self.attachAsset('lineobstacle', {
anchorX: 0.5,
anchorY: 0.0,
width: 15,
height: 2732 // Set the height to cover the entire screen height
});
outlineGraphics.height = 2732; // Ensure the height covers the entire screen height
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the LeftPlayer class
var LeftPlayer = Container.expand(function () {
var self = Container.call(this);
var leftPlayerGraphics = self.attachAsset('leftplayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function () {
// Add any specific update logic for LeftPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
if (self && self.x !== undefined) {
trail.x = self.x;
} else {
trail.x = 0;
}
trail.y = self && self.y !== undefined && self.height !== undefined ? self.y + self.height / 2 : 0;
game.addChildAt(trail, game.getChildIndex(self));
}
};
});
var LineObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacleline', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the Particle class
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xffffff // Apply tint to particle graphics
});
self.speed = Math.random() * 5 + 2; // Random speed for each particle
self.direction = Math.random() * Math.PI * 2; // Random direction for each particle
self.update = function () {
self.x += Math.cos(self.direction) * self.speed; // Move the particle in the direction
self.y += Math.sin(self.direction) * self.speed;
self.alpha -= 0.01; // Fade out the particle
if (self.alpha <= 0) {
self.destroy();
}
};
self.setTint = function (color) {
particleGraphics.tint = color;
};
});
// Define the Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.shield = null;
self.transitionToLane = function (targetX) {
self.isMoving = true;
self.targetX = targetX;
if (self.x < self.targetX) {
playerGraphics.rotation = Math.PI / 4; // Rotate player 45 degrees to the direction of movement
} else {
playerGraphics.rotation = -Math.PI / 4; // Rotate player -45 degrees to the direction of movement
}
};
self.update = function () {
if (self.isInvulnerable) {
self.invulnerableTimer--;
if (!self.shield) {
self.shield = self.addChild(LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5 // Set shield transparency
}));
// Play powerup sound when shield is activated
LK.getSound('powerup').play();
}
if (leftPlayer && !leftPlayer.shield) {
leftPlayer.shield = leftPlayer.addChild(LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5 // Set shield transparency
}));
// Play powerup sound when left player's shield is activated
LK.getSound('powerup').play();
}
if (rightPlayer && !rightPlayer.shield) {
rightPlayer.shield = rightPlayer.addChild(LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5 // Set shield transparency
}));
// Play powerup sound when right player's shield is activated
LK.getSound('powerup').play();
}
if (self.invulnerableTimer <= 0) {
self.isInvulnerable = false;
if (self.shield) {
self.shield.destroy();
self.shield = null;
}
if (leftPlayer && leftPlayer.shield) {
leftPlayer.shield.destroy();
leftPlayer.shield = null;
}
if (rightPlayer && rightPlayer.shield) {
rightPlayer.shield.destroy();
rightPlayer.shield = null;
}
} else {
// Update countdown text
if (self.shieldCountdown) {
self.shieldCountdown.setText(Math.ceil(self.invulnerableTimer / 120));
}
// Add blinking effect when shield is about to disappear
if (self.invulnerableTimer <= 120) {
// Last 2 seconds
if (LK.ticks % 30 < 15) {
// Blink every 0.5 seconds
self.shield.alpha = 0.2;
} else {
self.shield.alpha = 0.5;
// Add blinking effect when shield is about to disappear
if (self.invulnerableTimer <= 120) {
// Last 2 seconds
if (LK.ticks % 30 < 15) {
// Blink every 0.5 seconds
self.shield.alpha = 0.2;
} else {}
}
self.shield.alpha = 0.5;
// Add blinking effect when shield is about to disappear
if (self.invulnerableTimer <= 120) {
// Last 2 seconds
if (LK.ticks % 30 < 15) {
// Blink every 0.5 seconds
self.shield.alpha = 0.2;
} else {}
}
self.shield.alpha = 0.5;
}
}
}
}
if (self.isMoving) {
if (Math.abs(self.x - self.targetX) < self.speed) {
self.x = self.targetX;
self.isMoving = false;
} else {
self.x += (self.targetX - self.x) * 0.1; // Smooth movement using linear interpolation
playerGraphics.rotation = self.x < self.targetX ? Math.PI / 4 : -Math.PI / 4; // Rotate player 45 degrees to the direction of movement
}
} else {
// Smoothly transition player rotation back to its original position
if (playerGraphics.rotation > 0) {
playerGraphics.rotation -= 0.1;
} else if (playerGraphics.rotation < 0) {
playerGraphics.rotation += 0.1;
}
if (Math.abs(playerGraphics.rotation) < 0.1) {
playerGraphics.rotation = 0; // Reset rotation when player is not moving
}
}
if (!self.isJumping && self.visible) {
if (self.isMoving && LK.ticks % 1 == 0) {
var trail = new Trail();
trail.x = self.x;
trail.y = self.y + playerGraphics.height / 2;
game.addChild(trail);
} else if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.x = self.x;
trail.y = self.y + playerGraphics.height / 2;
game.addChild(trail);
}
}
if (self.isJumping) {
if (self.y > self.jumpPeakY && !self.isFalling) {
self.y -= self.jumpSpeed;
playerGraphics.scale.x += 0.01; // Increase player size when moving up
playerGraphics.scale.y += 0.01;
if (self.shield) {
self.shield.scale.x += 0.01; // Increase shield size when moving up
self.shield.scale.y += 0.01;
}
} else {
self.isFalling = true;
self.y += self.jumpSpeed;
playerGraphics.scale.x -= 0.01; // Decrease player size when falling down
playerGraphics.scale.y -= 0.01;
if (self.shield) {
self.shield.scale.x -= 0.01; // Decrease shield size when falling down
self.shield.scale.y -= 0.01;
}
if (self.y >= self.jumpStartY) {
self.y = self.jumpStartY;
self.isJumping = false;
self.isFalling = false;
playerGraphics.scale.x = 1; // Reset player size when not jumping
playerGraphics.scale.y = 1;
if (self.shield) {
self.shield.scale.x = 1; // Reset shield size when not jumping
self.shield.scale.y = 1;
}
// Destroy the player's shadow
shadow.destroy();
}
}
// Reduce jump duration by 5% every 10 seconds
if (LK.ticks % 600 == 0) {
self.jumpSpeed *= 1.05; // Increase jump speed by 5%
}
}
// Update shadow rotation to match player rotation
if (shadow) {
shadow.rotation = playerGraphics.rotation;
}
// Ensure player is always on top if it is a child of the game
if (game.children.includes(self)) {
game.setChildIndex(self, game.children.length - 1);
}
};
self.moveLeft = function () {
if (!gameStarted) {
for (var i = 0; i < starfield.length; i++) {
starfield[i].update();
}
return;
}
if (self.lane > 0 && !self.isMoving && !leftPlayer && !rightPlayer) {
self.lane--;
self.transitionToLane(lanes[self.lane]);
LK.getSound('swipe').play();
LK.getSound('swipe').play();
}
};
self.moveRight = function () {
if (!gameStarted) {
return;
} // Prevent player movement when the home screen is up
if (self.lane < 2 && !self.isMoving && !leftPlayer && !rightPlayer) {
self.lane++;
self.transitionToLane(lanes[self.lane]);
LK.getSound('swipe').play();
}
};
self.jump = function () {
if (!self.isMoving && !self.isJumping && !leftPlayer && !rightPlayer) {
self.isJumping = true;
self.jumpStartY = self.y;
self.jumpPeakY = self.y - 250; // Increase jump height
self.jumpSpeed = 4;
// Create the player's shadow
shadow = new Shadow();
shadow.x = self.x;
shadow.y = self.y;
game.addChild(shadow);
// Play jump sound when player jumps
LK.getSound('jump').play();
}
};
});
// Define the PowerUp class
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the PowerUpCenterLane class
var PowerUpCenterLane = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the RightLaneOutline class
var RightLaneOutline = Container.expand(function () {
var self = Container.call(this);
var outlineGraphics = self.attachAsset('lineobstacle', {
anchorX: 0.5,
anchorY: 0.0,
width: 15,
height: 2732 // Set the height to cover the entire screen height
});
outlineGraphics.height = 2732; // Ensure the height covers the entire screen height
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the RightPlayer class
var RightPlayer = Container.expand(function () {
var self = Container.call(this);
var rightPlayerGraphics = self.attachAsset('rightplayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function () {
// Add any specific update logic for RightPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
if (self && self.x !== undefined) {
trail.x = self.x;
} else {
trail.x = 0;
}
trail.y = self && self.y !== undefined && self.height !== undefined ? self.y + self.height / 2 : 0;
game.addChildAt(trail, game.getChildIndex(self));
}
};
});
//<Assets used in the game will automatically appear here>
// Define the Shadow class
var Shadow = Container.expand(function () {
var self = Container.call(this);
var shadowGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000 // Set the color to black
});
shadowGraphics.alpha = 0.5; // Dim the shadow
self.update = function () {
// The shadow's size changes based on the player's y position
var scale = 1 - (player.y - self.y) / 1000;
self.scale.x = scale;
self.scale.y = scale;
// Update the shadow's position to match the player's position
self.x = player.x;
// Rotate the shadow to match the player's rotation
if (player.playerGraphics) {
shadowGraphics.rotation = player.playerGraphics.rotation;
}
};
});
// Define the LineObstacle class
var SmallObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Define the SmallObstacleCenterCoinSides class
var SmallObstacleCenterCoinSides = Container.expand(function () {
var self = Container.call(this);
var smallObstacle = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
var SmallObstacleMiddlePowerUpLeftCoinRight = Container.expand(function () {
var self = Container.call(this);
var smallObstacleMiddle = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15 // Apply tint #a8ed15
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
var StairedSmallObstacle = Container.expand(function (lane, yOffset) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xa8ed15
});
self.speed = gameSpeed;
self.x = lanes[lane];
self.y = -self.height * 2 + yOffset;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = Math.random() * 2 + 1; // Random speed for each star
self.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0
self.update = function () {
self.y += self.speed;
if (self.y > 2732) {
self.y = -self.height;
self.x = Math.random() * 2048;
}
};
});
// Function to spawn SmallObstacle in the center and Coins on the sides
var TextObstacle = Container.expand(function (customText) {
var self = Container.call(this);
var textGraphics = new Text2(customText || 'Sample Text', {
size: 120,
fill: "#ffffff",
align: "center",
stroke: "#000000",
strokeThickness: 10,
border: true,
borderColor: "#000000",
borderWidth: 5
});
textGraphics.anchor.set(0.5, 0.5);
self.addChild(textGraphics);
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
self.hitbox = null; // Ensure TextObstacle does not collide with player
if (self.y > 2732 + self.height / 2) {
self.destroy();
}
};
});
// Function to spawn SmallObstacle
// Define the Trail class
var Trail = Container.expand(function () {
var self = Container.call(this);
var trailGraphics = self.attachAsset('trail', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.speed = 5;
self.update = function () {
self.y += self.speed;
self.alpha -= 0.02; // Fade out the trail faster
self.scale.x -= 0.02; // Shrink the trail faster
self.scale.y -= 0.02; // Shrink the trail faster
if (self.y > 2732 || self.alpha <= 0 || self.scale.x <= 0 || self.scale.y <= 0) {
self.destroy();
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x101010 //Init game with even darker grey background
});
/****
* Game Code
****/
function fadeOut(target, duration, onComplete) {
var fadeStep = 1 / (duration / 16.67); // Assuming 60 FPS, 16.67ms per frame
var fadeInterval = LK.setInterval(function () {
if (target.alpha > 0) {
target.alpha -= fadeStep;
if (target.alpha < 0) {
target.alpha = 0;
}
} else {
LK.clearInterval(fadeInterval);
if (onComplete) {
onComplete();
}
}
}, 16.67);
}
function spawnStairedSmallObstacles() {
var yOffset = 0;
for (var i = 0; i < lanes.length; i++) {
var lane = i;
if (i === 1) {
// Ensure the center lane obstacle is always in the same position
yOffset = 0;
} else {
// Randomly choose positive or negative offset for left and right lanes
yOffset = (Math.random() < 0.5 ? -1 : 1) * 350;
}
var stairedObstacle = new StairedSmallObstacle(lane, yOffset);
if (!obstacles) {
obstacles = [];
}
obstacles.push(stairedObstacle);
game.addChild(stairedObstacle);
}
}
function spawnSmallObstacleMiddlePowerUpLeftCoinRight() {
var smallObstacleMiddle = new SmallObstacleMiddlePowerUpLeftCoinRight();
smallObstacleMiddle.x = lanes[1]; // Middle lane
smallObstacleMiddle.y = -smallObstacleMiddle.height * 2;
smallObstacleMiddle.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(smallObstacleMiddle);
game.addChild(smallObstacleMiddle);
var powerUpLeft = new PowerUp();
powerUpLeft.x = lanes[0]; // Left lane
powerUpLeft.y = -powerUpLeft.height * 2;
powerUpLeft.speed = gameSpeed; // Ensure constant speed
if (!powerups) {
powerups = [];
}
powerups.push(powerUpLeft);
game.addChild(powerUpLeft);
var coinRight = new Coin();
coinRight.x = lanes[2]; // Right lane
coinRight.y = -coinRight.height * 2;
coinRight.speed = gameSpeed; // Ensure constant speed
if (!coins) {
coins = [];
}
coins.push(coinRight);
game.addChild(coinRight);
}
// New asset for obstacle line
function checkBoundingBoxCollision(obj1, obj2) {
var obj1Bounds = obj1.getBounds();
var obj2Bounds = obj2.getBounds();
var forgivenessX = obj1Bounds.width * 0.1;
var forgivenessY = obj1Bounds.height * 0.1;
return obj1Bounds.x < obj2Bounds.x + obj2Bounds.width - forgivenessX && obj1Bounds.x + obj1Bounds.width > obj2Bounds.x + forgivenessX && obj1Bounds.y < obj2Bounds.y + obj2Bounds.height - forgivenessY && obj1Bounds.y + obj1Bounds.height > obj2Bounds.y + forgivenessY;
}
// Function to spawn PowerUp in the center lane
function spawnPowerUpCenterLane() {
var powerUpCenterLane = new PowerUpCenterLane();
powerUpCenterLane.x = lanes[1]; // Center lane
powerUpCenterLane.y = -powerUpCenterLane.height * 2;
if (!powerups) {
powerups = [];
}
powerups.push(powerUpCenterLane);
game.addChild(powerUpCenterLane);
}
// Create main menu container
var mainMenu = new Container();
game.addChildAt(mainMenu, game.children.length);
// Play background music on main menu
LK.playMusic('backgroundmusic');
// Create title text with background button
var titleButton = new Container();
titleButton.update = function () {
if (LK.ticks % 120 < 60) {
titleButton.scale.x += 0.0001;
titleButton.scale.y += 0.0001;
} else {
titleButton.scale.x -= 0.0001;
titleButton.scale.y -= 0.0001;
}
};
// Removed titleBackground box
var titleImage = LK.getAsset('homeTitle', {
anchorX: 0.5,
anchorY: 0.5
});
titleButton.addChild(titleImage);
// Ensure lanes array is properly initialized before accessing its elements
if (!lanes || lanes.length < 3) {
console.error("Lanes array is not properly initialized.");
lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array
}
titleButton.x = lanes[1]; // Center the title button over the middle lane
titleButton.y = 2732 / 4;
mainMenu.addChild(titleButton);
// Create mode 1 button with background
var mode1Button = new Container();
mode1Button.update = function () {
if (LK.ticks % 120 < 60) {
mode1Button.scale.x += 0.0001;
mode1Button.scale.y += 0.0001;
} else {
mode1Button.scale.x -= 0.0001;
mode1Button.scale.y -= 0.0001;
}
};
// Removed mode1ButtonBackground box
var mode1ButtonImage = LK.getAsset('menu1', {
anchorX: 0.5,
anchorY: 0.5
});
mode1Button.addChild(mode1ButtonImage);
mode1Button.x = lanes[1]; // Center the mode 1 button over the middle lane
mode1Button.y = 2732 / 2;
mainMenu.addChildAt(mode1Button, mainMenu.children.length);
// Create mode 2 button with background
var mode2Button = new Container();
mode2Button.update = function () {
if (LK.ticks % 120 < 60) {
mode2Button.scale.x += 0.0001;
mode2Button.scale.y += 0.0001;
} else {
mode2Button.scale.x -= 0.0001;
mode2Button.scale.y -= 0.0001;
}
};
// Removed mode2ButtonBackground box
var mode2ButtonImage = LK.getAsset('menu2', {
anchorX: 0.5,
anchorY: 0.5
});
mode2Button.addChild(mode2ButtonImage);
mode2Button.x = lanes[1]; // Center the mode 2 button over the middle lane
mode2Button.y = 2732 / 2 + 400;
mainMenu.addChildAt(mode2Button, mainMenu.children.length);
// Add event listeners for buttons
mode1Button.down = function () {
LK.getSound('select').play();
startGame('mode1');
};
mode2Button.down = function () {
LK.getSound('select').play();
startGame('mode2');
};
// Function to start the game
function startGame(mode) {
fadeOut(titleButton, 1000, function () {
mainMenu.visible = false;
});
fadeOut(mode1Button, 1000, function () {
scoreTxt.visible = true; // Show score when game starts
});
fadeOut(mode2Button, 1000, function () {
scoreBackground.visible = true; // Show score background when game starts
});
milesTxt.visible = true; // Show miles when game starts
milesBackground.visible = true; // Show miles background when game starts
// Background music is already playing from the main menu
// Hide final score text on game start
if (finalScoreTxt) {
finalScoreTxt.visible = false;
// Hide final score text on game start
if (finalScoreTxt) {
finalScoreTxt.visible = false;
}
}
if (mode === 'mode1') {
// Initialize mode 1 specific elements
obstacleSpawnOrder = [{
type: 'TextObstacle',
interval: 100,
text: 'Swipe LEFT or RIGHT!'
}, {
type: 'SmallObstacle',
interval: 100
}, {
type: 'SmallObstacleLeftMiddleCoinRight',
interval: 100
}, {
type: 'SmallObstacleRightCenterCoinLeft',
interval: 100
}, {
type: 'TextObstacle',
interval: 100,
text: 'Swipe UP to JUMP!'
}, {
type: 'LineObstacle',
interval: 100
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'TextObstacle',
interval: 100,
text: 'Swipe DOWN to SPLIT!'
}, {
type: 'BigObstacle',
interval: 150
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'TextObstacle',
interval: 100,
text: 'Collect the SHIELD!'
}, {
type: 'PowerUpCenterLane',
interval: 100
}, {
type: 'ObstacleLine',
interval: 50
}, {
type: 'ObstacleLine',
interval: 50
}, {
type: 'ObstacleLine',
interval: 50
}, {
type: 'TextObstacle',
interval: 100,
text: 'You are READY!'
}, {
type: 'TextObstacle',
interval: 100,
text: 'Get ORBS for extra score!'
}];
} else if (mode === 'mode2') {
// Initialize mode 2 specific elements
obstacleSpawnOrder = [{
type: 'SmallObstacle',
interval: 100
}, {
type: 'SmallObstacleLeftMiddleCoinRight',
interval: 100
}, {
type: 'SmallObstacleRightCenterCoinLeft',
interval: 100
}, {
type: 'LineObstacle',
interval: 100
}, {
type: 'SmallObstacleCenterCoinLeftPowerUpRight',
interval: 100
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'SmallObstacleCenterCoinSides',
interval: 100
}, {
type: 'SmallObstacleMiddlePowerUpLeftCoinRight',
interval: 100
}, {
type: 'StairedSmallObstacles',
interval: 100
}, {
type: 'BigObstacle',
interval: 150
}];
obstacleSpawnOrder = obstacleSpawnOrder.sort(function () {
return Math.random() - 0.5;
});
}
// Start the game
var timeout = LK.setTimeout(function () {
gameStarted = true;
}, 500);
}
// Function to spawn TextObstacle
function spawnTextObstacle(customText) {
var textObstacle = new TextObstacle(customText);
textObstacle.x = 2048 / 2; // Center the TextObstacle
textObstacle.y = -textObstacle.height * 2;
if (!obstacles) {
obstacles = [];
}
obstacles.push(textObstacle);
game.addChild(textObstacle);
}
// Function to spawn powerups
function spawnPowerUp(lane) {
var powerup = new PowerUp();
powerup.lane = lane;
powerup.x = lanes[powerup.lane];
powerup.y = -powerup.height * 2;
powerups.push(powerup);
game.addChild(powerup);
}
// Initialize gameStarted flag
var gameStarted = false;
// Initialize array for powerups
var powerups = [];
// Initialize shadow
var shadow;
// Initialize lanes
var lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3];
// Ensure lanes array is properly initialized before accessing its elements
if (!lanes || lanes.length < 3) {
console.error("Lanes array is not properly initialized.");
lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array
}
// Ensure lanes array is properly initialized before accessing its elements
if (!lanes || lanes.length < 3) {
console.error("Lanes array is not properly initialized.");
lanes = [2048 / 4, 2048 / 2, 2048 / 4 * 3]; // Reinitialize lanes array
}
// Initialize starfield
// Initialize lane separators
var laneSeparators = [];
for (var i = 1; i < lanes.length; i++) {
var separator = new LaneSeparator();
separator.x = (lanes[i - 1] + lanes[i]) / 2; // Position separator between lanes
separator.y = 0;
laneSeparators.push(separator);
game.addChildAt(separator, 0); // Add lane separators at the bottom of the z axis
}
// Initialize lane outlines
var leftLaneOutline = new LeftLaneOutline();
leftLaneOutline.x = lanes[0] - (lanes[1] - lanes[0]) / 2; // Position left outline to the left of the first lane
leftLaneOutline.y = 0;
game.addChildAt(leftLaneOutline, 0); // Add left lane outline at the bottom of the z axis
var rightLaneOutline = new RightLaneOutline();
rightLaneOutline.x = lanes[2] + (lanes[2] - lanes[1]) / 2; // Position right outline to the right of the last lane
rightLaneOutline.y = 0;
game.addChildAt(rightLaneOutline, 0); // Add right lane outline at the bottom of the z axis
// Initialize player
var player = game.addChild(new Player());
player.jumpSpeed = 4; // Initialize jump speed
player.hitbox = [player];
player.lane = 1; // Start in the middle lane
player.x = lanes[player.lane];
player.y = 2732 - 200 - 350;
// Declare left and right players
var leftPlayer;
var rightPlayer;
// Initialize arrays for obstacles and coins
var obstacles = [];
var coins = [];
// Initialize split duration timer
var splitDuration = 120; // Duration in frames (2 seconds at 60 FPS)
var splitTimer = 0;
// Initialize score and final score text
var score = 0;
var finalScoreTxt = new Text2('Final Score: 0', {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 2732 / 2;
finalScoreTxt.visible = false;
LK.gui.center.addChild(finalScoreTxt);
// Initialize game speed
var gameSpeed = 5;
// Initialize global spawn interval
var globalSpawnInterval = 120; // Default interval in frames (2 seconds at 60 FPS)
var spawnIntervalReductionTimer = 0; // Timer to track interval reduction
var intervalReductionTimer = 0; // Timer to track interval reduction for obstacle spawn order
var scoreTxt = new Text2('0', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
var scoreBackground = LK.getAsset('scoreBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: scoreTxt.x + 550,
y: scoreTxt.y + scoreTxt.height / 2 + 200
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x += 600;
scoreTxt.y += 200;
scoreTxt.visible = false; // Hide score on main menu
scoreBackground.visible = false; // Hide score background on main menu
LK.gui.top.addChild(scoreBackground);
LK.gui.top.addChild(scoreTxt);
// Configuration for defining the order in which obstacles will spawn
var obstacleSpawnOrder = [{
type: 'TextObstacle',
// New TextObstacle type
interval: 100,
text: 'Swipe LEFT or RIGHT!' // Custom text for TextObstacle
}, {
type: 'SmallObstacle',
interval: 100
}, {
type: 'SmallObstacleLeftMiddleCoinRight',
interval: 100
}, {
type: 'SmallObstacleRightCenterCoinLeft',
interval: 100
}, {
type: 'TextObstacle',
// New TextObstacle type
interval: 100,
text: 'Swipe UP to JUMP!' // Custom text for TextObstacle
}, {
type: 'LineObstacle',
interval: 100
}, {
type: 'SmallObstacleCenterCoinLeftPowerUpRight',
interval: 100
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'TextObstacle',
// New TextObstacle type
interval: 100,
text: 'Swipe DOWN to SPLIT!' // Custom text for TextObstacle
}, {
type: 'BigObstacle',
interval: 100
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'LineObstacle',
interval: 100
}, {
type: 'SmallObstacleRightCenterCoinLeft',
interval: 100
}, {
type: 'TextObstacle',
// New TextObstacle type
interval: 100,
text: 'Avoid the Obstacles!' // Custom text for TextObstacle
}];
var currentObstacleIndex = 0;
var obstacleSpawnTimer = 0;
var obstacleSpawnOrderRandom = [{
type: 'SmallObstacle',
interval: 100
}, {
type: 'SmallObstacleLeftMiddleCoinRight',
interval: 100
}, {
type: 'SmallObstacleRightCenterCoinLeft',
interval: 100
}, {
type: 'LineObstacle',
interval: 100
}, {
type: 'SmallObstacleCenterCoinLeftPowerUpRight',
interval: 100
}, {
type: 'SmallObstaclesSidesCoinMiddle',
interval: 100
}, {
type: 'SmallObstacleCenterCoinSides',
interval: 100
}, {
type: 'StairedSmallObstacles',
interval: 100
}, {
type: 'BigObstacle',
interval: 150
}];
// Initialize queue for predicting next obstacle
var obstacleQueue = [];
// Function to spawn obstacles
function spawnObstacle(lane) {
var obstacle;
if (lane === undefined) {
obstacle = new LineObstacle();
obstacle.x = 2048 / 2; // Center the LineObstacle
} else {
obstacle = new Obstacle();
obstacle.lane = lane;
obstacle.x = lanes[obstacle.lane];
}
obstacle.y = -obstacle.height * 2;
obstacle.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Function to spawn BigObstacle with specific rules
function spawnBigObstacle() {
var bigObstacle = new BigObstacle();
bigObstacle.x = 2048 / 2; // Center the BigObstacle
bigObstacle.y = -bigObstacle.height / 2;
if (!obstacles) {
obstacles = [];
}
obstacles.push(bigObstacle);
game.addChild(bigObstacle);
}
// Function to spawn coins
function spawnCoin(lane) {
var coin = new Coin();
coin.lane = lane;
coin.x = lanes[coin.lane];
coin.y = -coin.height * 2;
coins.push(coin);
game.addChild(coin);
}
// Function to spawn powerups
// Handle swipe events for player movement
var touchStartX = 0;
var touchStartY = 0;
game.down = function (x, y, obj) {
if (!gameStarted || leftPlayer || rightPlayer) {
return;
} // Prevent player movement when the home screen is up
touchStartX = x;
touchStartY = y;
};
game.up = function (x, y, obj) {
if (!gameStarted) {
return;
} // Prevent player movement when the home screen is up
if (leftPlayer || rightPlayer) {
return; // Disable touch screen while player is split
}
if (Math.abs(y - touchStartY) > Math.abs(x - touchStartX)) {
if (y < touchStartY && !leftPlayer && !rightPlayer) {
player.jump();
} else if (y > touchStartY && !leftPlayer && !rightPlayer && !player.isJumping && player.lane === 1) {
// Animate leftPlayer and rightPlayer to move to the sides
var leftTargetX = player.x - 650;
var rightTargetX = player.x + 550;
var animationDuration = 20; // Duration in frames (0.33 seconds at 60 FPS)
if (!leftPlayer) {
leftPlayer = new LeftPlayer();
leftPlayer.x = player.x;
leftPlayer.y = player.y;
game.addChild(leftPlayer);
if (!rightPlayer) {
rightPlayer = new RightPlayer();
rightPlayer.x = player.x;
rightPlayer.y = player.y;
game.addChild(rightPlayer);
// Play swipe sound when player splits
LK.getSound('swipe').play();
player.visible = false; // Hide the original player
player.hitbox = [leftPlayer, rightPlayer]; // Move player hitbox to left and right players
// Initialize update functions after adding to game
if (!leftPlayer) {
leftPlayer = new LeftPlayer();
leftPlayer.x = player.x;
leftPlayer.y = player.y;
game.addChild(leftPlayer);
leftPlayer.update = function () {
if (animationDuration > 0) {
leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration;
animationDuration--;
}
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
if (leftPlayer && leftPlayer.x !== undefined) {
trail.x = leftPlayer.x;
} else {
trail.x = 0;
}
trail.y = this.y + (leftPlayer.height ? leftPlayer.height / 2 : 0);
game.addChildAt(trail, game.getChildIndex(this));
if (!rightPlayer) {
rightPlayer = new RightPlayer();
rightPlayer.x = player.x;
rightPlayer.y = player.y;
game.addChild(rightPlayer);
if (!rightPlayer) {
rightPlayer = new RightPlayer();
rightPlayer.x = player.x;
rightPlayer.y = player.y;
game.addChild(rightPlayer);
rightPlayer.update = function () {
if (animationDuration > 0) {
rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration;
animationDuration--;
}
};
}
}
;
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
if (rightPlayer && rightPlayer.x !== undefined) {
trail.x = rightPlayer.x;
} else {
trail.x = 0;
}
trail.y = this.y + (rightPlayer.height ? rightPlayer.height / 2 : 0);
game.addChildAt(trail, game.getChildIndex(this));
// Initialize update functions after adding to game
leftPlayer.update = function () {
if (animationDuration > 0) {
leftPlayer.x += (leftTargetX - leftPlayer.x) * 0.1; // Smooth movement using linear interpolation
animationDuration--;
titleButton.update = function () {
if (LK.ticks % 60 < 30) {
titleButton.y += 1;
} else {}
;
titleButton.y -= 1;
};
}
};
}
;
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = leftPlayer ? leftPlayer.x : 0;
trail.y = leftPlayer && leftPlayer.height ? leftPlayer.y + leftPlayer.height / 2 : 0;
game.addChildAt(trail, game.getChildIndex(leftPlayer));
}
}
;
};
rightPlayer.update = function () {
if (animationDuration > 0) {
rightPlayer.x += (rightTargetX - rightPlayer.x) * 0.1; // Smooth movement using linear interpolation
animationDuration--;
}
mode1Button.update = function () {
if (LK.ticks % 60 < 30) {
mode1Button.y += 1;
} else {
mode1Button.y -= 1;
}
};
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = rightPlayer ? rightPlayer.x : 0;
trail.y = rightPlayer && rightPlayer.height ? rightPlayer.y + rightPlayer.height / 2 : 0;
game.addChildAt(trail, game.getChildIndex(rightPlayer));
}
};
}
}
;
// Initialize update functions after adding to game
leftPlayer.update = function () {
if (animationDuration > 0) {
leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration;
animationDuration--;
}
mode2Button.update = function () {
if (LK.ticks % 60 < 30) {
mode2Button.y += 1;
} else {
mode2Button.y -= 1;
}
};
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = leftPlayer.x;
trail.y = leftPlayer && leftPlayer.y !== undefined ? leftPlayer.y + (leftPlayer.height ? leftPlayer.height / 2 : 0) : 0;
game.addChildAt(trail, game.getChildIndex(leftPlayer));
}
};
}
;
rightPlayer.update = function () {
if (animationDuration > 0) {
rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration;
animationDuration--;
}
// Add any specific update logic for RightPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = rightPlayer ? rightPlayer.x : 0;
trail.y = rightPlayer.y + rightPlayer.height / 2;
game.addChildAt(trail, game.getChildIndex(rightPlayer));
}
};
// Initialize update functions after adding to game
leftPlayer.update = function () {
if (animationDuration > 0) {
leftPlayer.x += (leftTargetX - leftPlayer.x) / animationDuration;
animationDuration--;
}
// Add any specific update logic for LeftPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = leftPlayer ? leftPlayer.x : 0;
trail.y = leftPlayer && leftPlayer.y !== undefined ? leftPlayer.y + (leftPlayer.height ? leftPlayer.height / 2 : 0) : 0;
game.addChildAt(trail, game.getChildIndex(leftPlayer));
}
};
rightPlayer.update = function () {
if (animationDuration > 0) {
rightPlayer.x += (rightTargetX - rightPlayer.x) / animationDuration;
animationDuration--;
}
// Add any specific update logic for RightPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = rightPlayer.x;
trail.y = rightPlayer.y + rightPlayer.height / 2;
game.addChildAt(trail, game.getChildIndex(rightPlayer));
}
};
}
// Start split timer
splitTimer = splitDuration;
} else {
if (x < touchStartX) {
player.moveLeft();
} else {
player.moveRight();
}
}
};
// Update game logic
game.update = function () {
// Update title button
if (titleButton.update) {
titleButton.update();
}
// Update miles traveled
milesTraveled += gameSpeed / 30; // Increase the speed at which miles are counted
milesTxt.setText(Math.floor(milesTraveled));
// Update mode1 button
mode1Button.update();
// Update mode2 button
mode2Button.update();
// Update miles traveled
milesTraveled += gameSpeed / 30; // Increase the speed at which miles are counted
milesTxt.setText(Math.floor(milesTraveled));
if (!gameStarted) {
// Update starfield
return;
}
// Update lane separators
for (var i = 0; i < laneSeparators.length; i++) {
laneSeparators[i].update();
laneSeparators[i].children[0].height = 2732; // Ensure the height covers the entire screen height
}
// Update player
player.update();
// Increase game speed and decrease global spawn interval over time
spawnIntervalReductionTimer++;
if (spawnIntervalReductionTimer >= 600) {
// Every 10 seconds
globalSpawnInterval = Math.max(30, globalSpawnInterval * 0.95); // Reduce spawn interval by 5%
spawnIntervalReductionTimer = 0; // Reset timer
}
intervalReductionTimer++;
if (intervalReductionTimer >= 600) {
for (var i = 0; i < obstacleSpawnOrder.length; i++) {
obstacleSpawnOrder[i].interval = Math.max(1, Math.floor(obstacleSpawnOrder[i].interval * 0.95));
}
intervalReductionTimer = 0;
}
if (LK.ticks % 600 == 0) {
globalSpawnInterval = Math.max(30, globalSpawnInterval * 0.95); // Reduce spawn interval by 5% every 10 seconds
// Increase speed every 10 seconds
gameSpeed *= 1.05; // Increase speed by 5%
// Decrease global spawn interval to make spawns more frequent
globalSpawnInterval = Math.max(30, globalSpawnInterval - 10); // Ensure interval doesn't go below 30 frames (0.5 seconds)
}
// Update obstacles, coins, and powerups
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].y += gameSpeed;
powerups[i].update();
if (player && !player.isJumping && player.hitbox.some(function (hitbox) {
return hitbox.intersects(powerups[i]);
})) {
player.isInvulnerable = true;
player.invulnerableTimer = 600; // 10 seconds at 60 FPS
if (leftPlayer && leftPlayer.update) {
leftPlayer.isInvulnerable = true;
leftPlayer.invulnerableTimer = 600;
}
if (rightPlayer && rightPlayer.update) {
rightPlayer.isInvulnerable = true;
rightPlayer.invulnerableTimer = 600;
}
powerups[i].destroy();
powerups.splice(i, 1);
}
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].y += gameSpeed;
obstacles[i].update();
if (!player.isJumping && player.hitbox && player.hitbox.some(function (hitbox) {
return checkBoundingBoxCollision(hitbox, obstacles[i]) && obstacles[i].hitbox !== null;
})) {
if (player.isInvulnerable) {
// Spawn particles
for (var j = 0; j < 50; j++) {
var particle = new Particle();
particle.x = obstacles[i].x;
particle.y = obstacles[i].y;
particle.scale.set(1); // Increase the size of the particles
particle.setTint(0xa8ed15); // Set particle color to match obstacle green tint
game.addChild(particle);
}
// Play destroy sound when an obstacle is destroyed by the player with the shield
LK.getSound('destroy').play();
obstacles[i].destroy();
obstacles.splice(i, 1);
} else {
LK.effects.flashScreen(0xffffff, 1000);
// Calculate final score
var finalScore = Math.floor(milesTraveled) + score * 100;
LK.setScore(finalScore);
// Display final score
var finalScoreTxt = new Text2('Final Score: ' + finalScore, {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 2732 / 2;
LK.gui.center.addChild(finalScoreTxt);
// Calculate final score
var finalScore = Math.floor(milesTraveled) + score * 100;
// Display final score
if (!finalScoreTxt) {
finalScoreTxt = new Text2('Final Score: ' + finalScore, {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 2732 / 2;
LK.gui.center.addChild(finalScoreTxt);
} else {
finalScoreTxt.setText('Final Score: ' + LK.getScore());
finalScoreTxt.visible = true;
}
// Calculate final score
var finalScore = Math.floor(milesTraveled) + score * 100;
// Display final score
if (!finalScoreTxt) {
finalScoreTxt = new Text2('Final Score: ' + finalScore, {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
finalScoreTxt.anchor.set(0.5, 0.5);
finalScoreTxt.x = 2048 / 2;
finalScoreTxt.y = 2732 / 2;
LK.gui.center.addChild(finalScoreTxt);
} else {
finalScoreTxt.setText('Final Score: ' + finalScore);
finalScoreTxt.visible = true;
}
LK.getSound('gameover').play(); // Play gameover sound
LK.stopMusic(); // Stop background music
// Create a new black asset that covers the whole screen
var gameOverCover = LK.getAsset('blackCover', {
width: 2048,
height: 2732,
color: 0x000000,
shape: 'box',
alpha: 1
});
game.addChildAt(gameOverCover, game.children.length);
player.destroy();
scoreTxt.destroy();
scoreBackground.destroy();
milesBackground.destroy();
milesTxt.destroy();
LK.setTimeout(function () {
LK.showGameOver(); // Calling this will destroy the 'Game' and reset entire game state.
}, 100); // Wait for 1 second (1000ms) before showing game over screen
}
}
}
// Handle obstacle spawning based on configuration
obstacleSpawnTimer++;
if (obstacleSpawnTimer >= obstacleSpawnOrder[currentObstacleIndex].interval) {
var obstacleType = obstacleSpawnOrder[currentObstacleIndex].type;
if (obstacleType === 'BigObstacle') {
spawnBigObstacle();
} else if (obstacleType === 'LineObstacle') {
spawnObstacle();
} else if (obstacleType === 'Obstacle') {
spawnObstacle();
} else if (obstacleType === 'SmallObstacle') {
spawnSmallObstacle();
} else if (obstacleType === 'SmallObstacleLeftMiddleCoinRight') {
spawnSmallObstacleLeftMiddleCoinRight();
} else if (obstacleType === 'SmallObstacleRightCenterCoinLeft') {
spawnSmallObstacleRightCenterCoinLeft();
} else if (obstacleType === 'SmallObstacleCenterCoinLeftPowerUpRight') {
spawnSmallObstacleCenterCoinLeftPowerUpRight();
} else if (obstacleType === 'TextObstacle') {
var customText = obstacleSpawnOrder[currentObstacleIndex].text || 'Default Text';
spawnTextObstacle(customText);
} else if (obstacleType === 'ObstacleLine') {
spawnObstacleLine();
} else if (obstacleType === 'SmallObstaclesSidesCoinMiddle') {
spawnSmallObstaclesSidesCoinMiddle();
} else if (obstacleType === 'SmallObstacleCenterCoinSides') {
spawnSmallObstacleCenterCoinSides();
} else if (obstacleType === 'SmallObstacleMiddlePowerUpLeftCoinRight') {
spawnSmallObstacleMiddlePowerUpLeftCoinRight();
} else if (obstacleType === 'PowerUpCenterLane') {
spawnPowerUpCenterLane();
} else if (obstacleType === 'StairedSmallObstacles') {
spawnStairedSmallObstacles();
}
currentObstacleIndex++;
if (currentObstacleIndex >= obstacleSpawnOrder.length) {
currentObstacleIndex = 0;
if (obstacleSpawnOrder === obstacleSpawnOrderRandom) {
obstacleSpawnOrder = obstacleSpawnOrderRandom.sort(function () {
return Math.random() - 0.5;
});
} else {
obstacleSpawnOrder = obstacleSpawnOrderRandom;
}
}
obstacleSpawnTimer = 0;
}
// Handle split duration and animate back to center
if (splitTimer > 0) {
splitTimer--;
if (LK.ticks % 600 == 0) {
splitDuration = Math.max(1, Math.floor(splitDuration * 0.95)); // Reduce split duration by 5% every 10 seconds
}
if (splitTimer === 0) {
// Animate leftPlayer and rightPlayer back to the center
var centerX = player.x;
var animationDuration = 20; // Duration in frames (0.33 seconds at 60 FPS)
// Initialize update functions after adding to game
leftPlayer.update = function () {
if (animationDuration > 0) {
leftPlayer.x += (centerX - leftPlayer.x) * 0.1; // Smooth movement using linear interpolation
animationDuration--;
} else {
leftPlayer.destroy();
leftPlayer = null;
player.visible = true;
player.hitbox = [player]; // Reset player hitbox to original player
// Play swipe sound when player merges back together
LK.getSound('swipe').play();
}
// Add any specific update logic for LeftPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = leftPlayer ? leftPlayer.x : 0;
trail.y = leftPlayer.y + leftPlayer.height / 2;
game.addChildAt(trail, game.getChildIndex(leftPlayer));
}
};
rightPlayer.update = function () {
if (animationDuration > 0) {
rightPlayer.x += (centerX - rightPlayer.x) * 0.1; // Smooth movement using linear interpolation
animationDuration--;
} else {
rightPlayer.destroy();
rightPlayer = null;
player.visible = true;
player.hitbox = [player]; // Reset player hitbox to original player
// Play swipe sound when player merges back together
LK.getSound('swipe').play();
}
// Add any specific update logic for RightPlayer here
if (LK.ticks % 4 == 0) {
var trail = new Trail();
trail.scale.x = 0.5;
trail.scale.y = 0.5;
trail.x = rightPlayer ? rightPlayer.x : 0;
trail.y = rightPlayer.y + rightPlayer.height / 2;
game.addChildAt(trail, game.getChildIndex(rightPlayer));
}
};
}
}
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].y += gameSpeed;
coins[i].update();
if (player && !player.isJumping && player.hitbox.some(function (hitbox) {
return checkBoundingBoxCollision(hitbox, coins[i]);
})) {
score += 1;
scoreTxt.setText(score);
// Play bling sound
LK.getSound('bling').play();
// Spawn particles
for (var j = 0; j < 10; j++) {
var particle = new Particle();
particle.x = coins[i].x;
particle.y = coins[i].y;
particle.setTint(0xffffff); // Set particle color to white
game.addChild(particle);
}
coins[i].destroy();
coins.splice(i, 1);
}
}
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].y += gameSpeed;
powerups[i].update();
if (player && !player.isJumping && player.hitbox.some(function (hitbox) {
return checkBoundingBoxCollision(hitbox, powerups[i]);
})) {
player.isInvulnerable = true;
player.invulnerableTimer = 600; // 10 seconds at 60 FPS
LK.getSound('powerup').play(); // Play powerup sound
LK.getSound('powerup').play(); // Play powerup sound
powerups[i].destroy();
powerups.splice(i, 1);
}
}
// Automatic spawning of obstacles, coins, and powerups has been removed
};
// Function to spawn SmallObstacle
function spawnSmallObstacle() {
var smallObstacle = new SmallObstacle();
smallObstacle.x = 2048 / 2; // Center the SmallObstacle
smallObstacle.y = -smallObstacle.height * 2;
smallObstacle.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(smallObstacle);
game.addChild(smallObstacle);
}
// Function to spawn SmallObstacle on left and middle lanes, and Coin on right lane
function spawnSmallObstacleLeftMiddleCoinRight() {
var smallObstacleLeft = new SmallObstacle();
var smallObstacleMiddle = new SmallObstacle();
var coinRight = new Coin();
smallObstacleLeft.x = lanes[0]; // Left lane
smallObstacleMiddle.x = lanes[1]; // Middle lane
coinRight.x = lanes[2]; // Right lane
smallObstacleLeft.y = smallObstacleMiddle.y = coinRight.y = -smallObstacleLeft.height * 2;
if (!obstacles) {
obstacles = [];
}
if (!coins) {
coins = [];
}
obstacles.push(smallObstacleLeft);
obstacles.push(smallObstacleMiddle);
coins.push(coinRight);
game.addChild(smallObstacleLeft);
game.addChild(smallObstacleMiddle);
game.addChild(coinRight);
// Ensure both obstacles and coin have the same speed
var obstacleSpeed = gameSpeed;
smallObstacleLeft.speed = smallObstacleMiddle.speed = coinRight.speed = obstacleSpeed;
// Attach the obstacles together
smallObstacleLeft.update = function () {
this.y += this.speed;
smallObstacleMiddle.y = this.y; // Move middle obstacle with left obstacle
if (this.y > 2732 + this.height / 2) {
this.destroy();
smallObstacleMiddle.destroy();
}
};
smallObstacleMiddle.update = function () {
// Empty update function to prevent individual movement
};
}
// Function to spawn SmallObstacle on right and center lanes, and Coin on left lane
function spawnSmallObstacleRightCenterCoinLeft() {
var smallObstacleRight = new SmallObstacle();
var smallObstacleCenter = new SmallObstacle();
var coinLeft = new Coin();
smallObstacleRight.x = lanes[2]; // Right lane
smallObstacleCenter.x = lanes[1]; // Center lane
coinLeft.x = lanes[0]; // Left lane
smallObstacleRight.y = smallObstacleCenter.y = coinLeft.y = -smallObstacleRight.height * 2;
if (!obstacles) {
obstacles = [];
}
if (!coins) {
coins = [];
}
obstacles.push(smallObstacleRight);
obstacles.push(smallObstacleCenter);
coins.push(coinLeft);
game.addChild(smallObstacleRight);
game.addChild(smallObstacleCenter);
game.addChild(coinLeft);
// Ensure both obstacles and coin have the same speed
var obstacleSpeed = gameSpeed;
smallObstacleRight.speed = smallObstacleCenter.speed = coinLeft.speed = obstacleSpeed;
// Attach the obstacles together
smallObstacleRight.update = function () {
this.y += this.speed;
smallObstacleCenter.y = this.y; // Move center obstacle with right obstacle
if (this.y > 2732 + this.height / 2) {
this.destroy();
smallObstacleCenter.destroy();
}
};
smallObstacleCenter.update = function () {
// Empty update function to prevent individual movement
};
}
// Function to spawn a line of obstacles
function spawnObstacleLine() {
for (var i = 0; i < lanes.length; i++) {
var obstacle = new Obstacle();
obstacle.x = lanes[i];
obstacle.y = -obstacle.height * 2;
if (!obstacles) {
obstacles = [];
}
obstacles.push(obstacle);
game.addChild(obstacle);
}
}
function spawnSmallObstacleCenterCoinLeftPowerUpRight() {
var smallObstacleCenter = new SmallObstacle();
smallObstacleCenter.x = lanes[1]; // Center lane
smallObstacleCenter.y = -smallObstacleCenter.height * 2;
smallObstacleCenter.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(smallObstacleCenter);
game.addChild(smallObstacleCenter);
var coinLeft = new Coin();
coinLeft.x = lanes[0]; // Left lane
coinLeft.y = -coinLeft.height * 2;
coinLeft.speed = gameSpeed; // Ensure constant speed
if (!coins) {
coins = [];
}
coins.push(coinLeft);
game.addChild(coinLeft);
var powerUpRight = new PowerUp();
powerUpRight.x = lanes[2]; // Right lane
powerUpRight.y = -powerUpRight.height * 2;
powerUpRight.speed = gameSpeed; // Ensure constant speed
if (!powerups) {
powerups = [];
}
powerups.push(powerUpRight);
game.addChild(powerUpRight);
}
// Function to spawn SmallObstacles on the sides and a Coin in the middle
function spawnSmallObstaclesSidesCoinMiddle() {
var smallObstacleLeft = new SmallObstacle();
smallObstacleLeft.x = lanes[0]; // Left lane
smallObstacleLeft.y = -smallObstacleLeft.height * 2;
smallObstacleLeft.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(smallObstacleLeft);
game.addChild(smallObstacleLeft);
var smallObstacleRight = new SmallObstacle();
smallObstacleRight.x = lanes[2]; // Right lane
smallObstacleRight.y = -smallObstacleRight.height * 2;
smallObstacleRight.speed = gameSpeed; // Ensure constant speed
obstacles.push(smallObstacleRight);
game.addChild(smallObstacleRight);
var coinMiddle = new Coin();
coinMiddle.x = lanes[1]; // Middle lane
coinMiddle.y = -coinMiddle.height * 2;
coinMiddle.speed = gameSpeed; // Ensure constant speed
if (!coins) {
coins = [];
}
coins.push(coinMiddle);
game.addChild(coinMiddle);
}
// Function to spawn SmallObstacle in the center and Coins on the sides
function spawnSmallObstacleCenterCoinSides() {
var smallObstacleCenter = new SmallObstacleCenterCoinSides();
smallObstacleCenter.x = lanes[1]; // Center lane
smallObstacleCenter.y = -smallObstacleCenter.height * 2;
smallObstacleCenter.speed = gameSpeed; // Ensure constant speed
if (!obstacles) {
obstacles = [];
}
obstacles.push(smallObstacleCenter);
game.addChild(smallObstacleCenter);
var coinLeft = new Coin();
coinLeft.x = lanes[0]; // Left lane
coinLeft.y = -coinLeft.height * 2;
coinLeft.speed = gameSpeed; // Ensure constant speed
if (!coins) {
coins = [];
}
coins.push(coinLeft);
game.addChild(coinLeft);
var coinRight = new Coin();
coinRight.x = lanes[2]; // Right lane
coinRight.y = -coinRight.height * 2;
coinRight.speed = gameSpeed; // Ensure constant speed
coins.push(coinRight);
game.addChild(coinRight);
}
var starfield = [];
for (var i = 0; i < 25; i++) {
var star = new Star();
star.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.scale.set(Math.random() * 1.5 + 0.5); // Random size between 0.5 and 2.0
starfield.push(star);
game.addChildAt(star, 0); // Add stars at the bottom of the z axis
}
// Initialize miles traveled
var milesTraveled = 0;
// Create miles traveled text
var milesTxt = new Text2('Miles: 0', {
size: 100,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
milesTxt.anchor.set(1, 0); // Anchor to the top-right corner
milesTxt.x = 2048; // Position at the top-right corner
milesTxt.y = 0;
LK.gui.topRight.addChild(milesTxt);
// Initialize miles traveled
var milesTraveled = 0;
// Create miles traveled text
var milesTxt = new Text2('0', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 5,
border: true,
borderColor: "#000000",
borderWidth: 3
});
var milesBackground = LK.getAsset('milesBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: scoreTxt.x - 50,
y: scoreTxt.y - 90
});
milesTxt.anchor.set(0.5, 0);
milesTxt.x = scoreTxt.x - 10;
milesTxt.y = scoreTxt.y - 120;
milesTxt.visible = false; // Hide miles on main menu
milesBackground.visible = false; // Hide miles background on main menu
LK.gui.top.addChild(milesBackground);
LK.gui.top.addChild(milesTxt);
cartoon white circle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon light blue circle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon white square. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
black rectangle