/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { musicVolume: 1 }); /**** * Classes ****/ var ControlButton = Container.expand(function (type) { var self = Container.call(this); self.buttonType = type; self.isPressed = false; var buttonGraphics; if (type === 'jump') { buttonGraphics = self.attachAsset('jumpButton', { anchorX: 0.5, anchorY: 0.5 }); } else if (type === 'run') { buttonGraphics = self.attachAsset('runButton', { anchorX: 0.5, anchorY: 0.5 }); } else { buttonGraphics = self.attachAsset(type === 'left' ? 'leftButton' : 'rightButton', { anchorX: 0.5, anchorY: 0.5 }); } // Add larger transparent hitbox for easier touch detection var hitboxSize = 240; // Larger than visual button (180px) var hitbox = LK.getAsset('jumpButton', { anchorX: 0.5, anchorY: 0.5, width: hitboxSize, height: hitboxSize, alpha: 0 // Invisible }); self.addChild(hitbox); self.down = function (x, y, obj) { self.isPressed = true; // Scale down and change alpha for press effect tween(buttonGraphics, { scaleX: 0.85, scaleY: 0.85, alpha: 0.7 }, { duration: 100, easing: tween.easeOut }); }; self.up = function (x, y, obj) { self.isPressed = false; // Scale back up and restore alpha for release effect tween(buttonGraphics, { scaleX: 1.0, scaleY: 1.0, alpha: 1.0 }, { duration: 150, easing: tween.easeOut }); }; // Add idle floating animation self.animationTimer = Math.random() * 100; // Random start offset self.update = function () { if (!self.isPressed) { // Gentle floating animation when not pressed self.animationTimer += 0.05; var floatOffset = Math.sin(self.animationTimer) * 3; buttonGraphics.y = floatOffset; // Subtle breathing scale effect var breathingScale = 1.0 + Math.sin(self.animationTimer * 2) * 0.02; if (!buttonGraphics._tweening) { buttonGraphics.scaleX = breathingScale; buttonGraphics.scaleY = breathingScale; } } }; return self; }); var MenuButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 }); // Add menu icon (three lines) var line1 = new Text2('—', { size: 24, fill: 0xFFFFFF }); line1.anchor.set(0.5, 0.5); line1.y = -15; self.addChild(line1); var line2 = new Text2('—', { size: 24, fill: 0xFFFFFF }); line2.anchor.set(0.5, 0.5); self.addChild(line2); var line3 = new Text2('—', { size: 24, fill: 0xFFFFFF }); line3.anchor.set(0.5, 0.5); line3.y = 15; self.addChild(line3); self.down = function (x, y, obj) { // Scale down for press effect tween(buttonGraphics, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); // Show menu showMenu(); }; self.up = function (x, y, obj) { // Scale back up tween(buttonGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut }); }; return self; }); var MenuOverlay = Container.expand(function () { var self = Container.call(this); // Semi-transparent background var background = LK.getAsset('menuOverlay', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.8 }); background.interactive = true; self.addChild(background); // Menu panel var menuPanel = self.attachAsset('menuOverlay', { anchorX: 0.5, anchorY: 0.5 }); // Menu title var titleText = new Text2('MENU', { size: 60, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -300; self.addChild(titleText); // Restart Level button var restartButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); restartButton.y = -150; restartButton.interactive = true; var restartText = new Text2('RESTART LEVEL', { size: 36, fill: 0xFFFFFF }); restartText.anchor.set(0.5, 0.5); restartButton.addChild(restartText); restartButton.down = function () { tween(restartButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; restartButton.up = function () { tween(restartButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Show final score before restart LK.setScore(gamePoints); // Reset points for new game gamePoints = 0; pointsText.setText('Points: 0'); // Reset power usage flags superJumpUsed = false; slowFallModeUsed = false; // Restart current level createLevel(currentLevel); applyDifficultyModifiers(currentLevel); player.x = 400; // Platform 1 x position player.y = 2350; // Just above platform 1 player.velocityX = 0; player.velocityY = 0; player.powerUpActive = false; player.slowFallActive = false; player.jumpPower = player.baseJumpPower; player.gravity = player.baseGravity; hideMenu(); } }); }; // Music Volume Controls var volumeText = new Text2('MUSIC VOLUME', { size: 32, fill: 0xFFFFFF }); volumeText.anchor.set(0.5, 0.5); volumeText.y = -100; self.addChild(volumeText); var volumeDisplayText = new Text2(Math.round(musicVolume * 100) + '%', { size: 28, fill: 0xf39c12 }); volumeDisplayText.anchor.set(0.5, 0.5); volumeDisplayText.y = -60; self.addChild(volumeDisplayText); // Volume Down Button var volumeDownButton = self.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 })); volumeDownButton.x = -100; volumeDownButton.y = -20; volumeDownButton.interactive = true; var volumeDownText = new Text2('−', { size: 40, fill: 0xFFFFFF }); volumeDownText.anchor.set(0.5, 0.5); volumeDownButton.addChild(volumeDownText); volumeDownButton.down = function () { tween(volumeDownButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); }; volumeDownButton.up = function () { tween(volumeDownButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { decreaseMusicVolume(); volumeDisplayText.setText(Math.round(musicVolume * 100) + '%'); } }); }; // Volume Up Button var volumeUpButton = self.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 })); volumeUpButton.x = 100; volumeUpButton.y = -20; volumeUpButton.interactive = true; var volumeUpText = new Text2('+', { size: 40, fill: 0xFFFFFF }); volumeUpText.anchor.set(0.5, 0.5); volumeUpButton.addChild(volumeUpText); volumeUpButton.down = function () { tween(volumeUpButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); }; volumeUpButton.up = function () { tween(volumeUpButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { increaseMusicVolume(); volumeDisplayText.setText(Math.round(musicVolume * 100) + '%'); } }); }; // Sky Color Controls var skyColorText = new Text2('SKY COLOR', { size: 32, fill: 0xFFFFFF }); skyColorText.anchor.set(0.5, 0.5); skyColorText.y = 40; self.addChild(skyColorText); // Previous Sky Color Button var skyPrevButton = self.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 })); skyPrevButton.x = -100; skyPrevButton.y = 80; skyPrevButton.interactive = true; var skyPrevText = new Text2('←', { size: 40, fill: 0xFFFFFF }); skyPrevText.anchor.set(0.5, 0.5); skyPrevButton.addChild(skyPrevText); skyPrevButton.down = function () { tween(skyPrevButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); }; skyPrevButton.up = function () { tween(skyPrevButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { var prevIndex = currentSkyColorIndex - 1; if (prevIndex < 0) { prevIndex = skyColors.length - 1; } changeSkyColor(prevIndex); } }); }; // Next Sky Color Button var skyNextButton = self.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 })); skyNextButton.x = 100; skyNextButton.y = 80; skyNextButton.interactive = true; var skyNextText = new Text2('→', { size: 40, fill: 0xFFFFFF }); skyNextText.anchor.set(0.5, 0.5); skyNextButton.addChild(skyNextText); skyNextButton.down = function () { tween(skyNextButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); }; skyNextButton.up = function () { tween(skyNextButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { cycleSkyColor(); } }); }; // Random Sky Color Button var skyRandomButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); skyRandomButton.y = 140; skyRandomButton.interactive = true; var skyRandomText = new Text2('RANDOM SKY', { size: 28, fill: 0xFFFFFF }); skyRandomText.anchor.set(0.5, 0.5); skyRandomButton.addChild(skyRandomText); skyRandomButton.down = function () { tween(skyRandomButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; skyRandomButton.up = function () { tween(skyRandomButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { var randomIndex = getRandomSkyColor(); changeSkyColor(randomIndex); } }); }; // Cycle Sky Colors Button var cycleSkyButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); cycleSkyButton.y = 200; cycleSkyButton.interactive = true; var cycleSkyText = new Text2('CYCLE SKY COLORS', { size: 28, fill: 0xFFFFFF }); cycleSkyText.anchor.set(0.5, 0.5); cycleSkyButton.addChild(cycleSkyText); cycleSkyButton.down = function () { tween(cycleSkyButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; cycleSkyButton.up = function () { tween(cycleSkyButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Start automatic sky color cycling startSkyCycling(); } }); }; // Close button var closeButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); closeButton.y = 260; closeButton.interactive = true; var closeText = new Text2('CLOSE', { size: 36, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.down = function () { tween(closeButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; closeButton.up = function () { tween(closeButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { hideMenu(); } }); }; // Background click to close background.down = function () { hideMenu(); }; return self; }); var Platform = Container.expand(function (width, height, number) { var self = Container.call(this); self.platformWidth = width || 300; self.platformHeight = height || 40; self.platformNumber = number || 0; var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5, scaleX: self.platformWidth / 300, scaleY: self.platformHeight / 40 }); // Add number text if platform has a number if (self.platformNumber > 0) { var numberText = new Text2(self.platformNumber.toString(), { size: 30, fill: 0x000000 }); numberText.anchor.set(0.5, 0.5); self.addChild(numberText); } return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1.0 }); self.velocityX = 0; self.velocityY = 0; self.speed = 12; self.runSpeed = 20; self.isRunning = false; self.jumpPower = 30; self.baseJumpPower = 30; self.powerUpJumpPower = 45; self.powerUpActive = false; self.powerUpTimer = 0; self.slowFallActive = false; self.slowFallTimer = 0; self.gravity = 0.8; self.baseGravity = 0.8; self.slowFallGravity = 0.25; self.onGround = false; self.canDoubleJump = false; self.hasDoubleJumped = false; self.parachute = null; self.boots = null; self.maxFallSpeed = 15; // Animation states self.animationState = 'idle'; // 'idle', 'falling', 'jumping' self.lastOnGround = true; self.animationTimer = 0; self.moveLeft = function () { self.velocityX = self.isRunning ? -self.runSpeed : -self.speed; }; self.moveRight = function () { self.velocityX = self.isRunning ? self.runSpeed : self.speed; }; self.setRunning = function (running) { self.isRunning = running; }; self.jump = function () { if (self.onGround) { self.velocityY = -self.jumpPower; self.onGround = false; self.canDoubleJump = true; self.hasDoubleJumped = false; // Play voice sound when jumping LK.getSound('Voz').play(); } else if (self.canDoubleJump && !self.hasDoubleJumped) { // Double jump self.velocityY = -self.jumpPower * 0.9; // Slightly weaker than first jump self.hasDoubleJumped = true; self.canDoubleJump = false; // Play voice sound when double jumping LK.getSound('Voz').play(); // Flash player purple to show double jump LK.effects.flashObject(self, 0x9b59b6, 200); } }; self.stopHorizontalMovement = function () { self.velocityX = 0; }; self.collectPowerUp = function () { self.powerUpActive = true; self.powerUpTimer = 300; // 5 seconds at 60fps self.jumpPower = self.powerUpJumpPower; // Flash player green to show power-up is active LK.effects.flashObject(self, 0x00ff00, 300); // Create boots visual effect self.boots = LK.getAsset('boots', { anchorX: 0.5, anchorY: 1.0, alpha: 0 }); self.addChild(self.boots); self.boots.x = 0; self.boots.y = 0; // Position at player's feet // Animate boots appearing tween(self.boots, { alpha: 1.0, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.easeOut }); }; self.collectSlowFallPowerUp = function () { self.slowFallActive = true; self.slowFallTimer = 300; // 5 seconds at 60fps self.gravity = self.slowFallGravity; // Flash player blue to show slow fall is active LK.effects.flashObject(self, 0x3498db, 300); // Add gentle blue tint while active tween(playerGraphics, { tint: 0xadd8e6 }, { duration: 300, easing: tween.easeOut }); // Create parachute self.parachute = LK.getAsset('parachute', { anchorX: 0.5, anchorY: 1.0, alpha: 0 }); self.addChild(self.parachute); self.parachute.x = 0; self.parachute.y = -200; // Position above player // Animate parachute appearing tween(self.parachute, { alpha: 0.8, y: -180 }, { duration: 500, easing: tween.easeOut }); }; self.update = function () { // Apply gravity self.velocityY += self.gravity; // Limit fall speed if (self.velocityY > self.maxFallSpeed) { self.velocityY = self.maxFallSpeed; } // Update position self.x += self.velocityX; self.y += self.velocityY; // Flip sprite based on movement direction if (self.velocityX > 0) { // Moving right - face right (normal) playerGraphics.scaleX = Math.abs(playerGraphics.scaleX); } else if (self.velocityX < 0) { // Moving left - face left (flipped) playerGraphics.scaleX = -Math.abs(playerGraphics.scaleX); } // Update animation timer self.animationTimer += 0.1; // Determine animation state var newAnimationState = 'idle'; if (!self.onGround && self.velocityY < -5) { newAnimationState = 'jumping'; } else if (!self.onGround && self.velocityY > 5) { newAnimationState = 'falling'; } else if (self.onGround && self.velocityX !== 0) { newAnimationState = 'walking'; } else if (self.onGround) { newAnimationState = 'idle'; } // Apply animations based on state transitions if (self.animationState !== newAnimationState) { // State changed, apply new animation if (newAnimationState === 'jumping') { // Jump animation - stretch upward tween(playerGraphics, { scaleY: 1.3, scaleX: 0.8, rotation: self.velocityX > 0 ? 0.1 : self.velocityX < 0 ? -0.1 : 0 }, { duration: 200, easing: tween.easeOut }); } else if (newAnimationState === 'falling') { // Fall animation - compress and tilt tween(playerGraphics, { scaleY: 0.7, scaleX: 1.2, rotation: self.velocityX > 0 ? 0.2 : self.velocityX < 0 ? -0.2 : 0 }, { duration: 300, easing: tween.easeOut }); } else if (newAnimationState === 'idle' && !self.lastOnGround && self.onGround) { // Landing animation - squash and recover tween(playerGraphics, { scaleY: 0.6, scaleX: 1.4, rotation: 0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(playerGraphics, { scaleY: 1.0, scaleX: 1.0, rotation: 0 }, { duration: 200, easing: tween.easeOut }); } }); } else if (newAnimationState === 'walking') { // Walking animation - return to normal scale for bouncing tween(playerGraphics, { scaleY: 1.0, scaleX: 1.0, rotation: 0 }, { duration: 200, easing: tween.easeOut }); } else if (newAnimationState === 'idle') { // Return to idle animation tween(playerGraphics, { scaleY: 1.0, scaleX: 1.0, rotation: 0 }, { duration: 300, easing: tween.easeOut }); } } // Continuous animations based on state if (newAnimationState === 'idle' && self.onGround) { // Gentle breathing effect var breathingScale = 1.0 + Math.sin(self.animationTimer * 2) * 0.02; if (!playerGraphics._tweening) { // Only apply if not currently tweening playerGraphics.scaleY = breathingScale; } } else if (newAnimationState === 'walking' && self.onGround) { // Walking animation - bouncing effect (slower) var walkingBounce = 1.0 + Math.sin(self.animationTimer * 4) * 0.15; var walkingTilt = Math.sin(self.animationTimer * 4) * 0.05; if (!playerGraphics._tweening) { // Only apply if not currently tweening playerGraphics.scaleY = walkingBounce; playerGraphics.rotation = walkingTilt * (self.velocityX > 0 ? 1 : -1); } } // Update states for next frame self.animationState = newAnimationState; self.lastOnGround = self.onGround; // Keep player within screen bounds horizontally if (self.x < 90) { self.x = 90; } if (self.x > 1958) { self.x = 1958; } // Handle power-up timer if (self.powerUpActive) { self.powerUpTimer--; if (self.powerUpTimer <= 0) { self.powerUpActive = false; self.jumpPower = self.baseJumpPower; // Flash player red to show power-up expired LK.effects.flashObject(self, 0xff0000, 200); // Remove boots with animation if (self.boots) { tween(self.boots, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { if (self.boots) { self.removeChild(self.boots); self.boots = null; } } }); } } } // Handle slow fall timer if (self.slowFallActive) { self.slowFallTimer--; // Animate parachute swaying if (self.parachute) { var swayAmount = Math.sin(self.animationTimer * 3) * 15; self.parachute.x = swayAmount; self.parachute.rotation = Math.sin(self.animationTimer * 2) * 0.1; } if (self.slowFallTimer <= 0) { self.slowFallActive = false; self.gravity = self.baseGravity; // Flash player red to show slow fall expired and remove tint LK.effects.flashObject(self, 0xff0000, 200); tween(playerGraphics, { tint: 0xffffff }, { duration: 300, easing: tween.easeOut }); // Remove parachute with animation if (self.parachute) { tween(self.parachute, { alpha: 0, y: -220 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { if (self.parachute) { self.removeChild(self.parachute); self.parachute = null; } } }); } } } // Reset double jump when landing if (self.onGround && !self.lastOnGround) { self.canDoubleJump = false; self.hasDoubleJumped = false; } // Reset onGround flag self.onGround = false; }; return self; }); var PowerMenuOverlay = Container.expand(function () { var self = Container.call(this); // Semi-transparent background var background = LK.getAsset('menuOverlay', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.8 }); background.interactive = true; self.addChild(background); // Menu panel var menuPanel = self.attachAsset('menuOverlay', { anchorX: 0.5, anchorY: 0.5 }); // Menu title var titleText = new Text2('POWER MENU', { size: 60, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -300; self.addChild(titleText); // Super Jump Button var superJumpButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); superJumpButton.y = -150; superJumpButton.interactive = true; var superJumpText = new Text2('SUPER JUMP', { size: 36, fill: 0xFFFFFF }); superJumpText.anchor.set(0.5, 0.5); superJumpButton.addChild(superJumpText); superJumpButton.down = function () { tween(superJumpButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; superJumpButton.up = function () { tween(superJumpButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Check if super jump has already been used if (!superJumpUsed) { // Activate super jump mode activateSuperJumpMode(); superJumpUsed = true; // Update button appearance to show it's used superJumpText.setText('USED'); superJumpButton.alpha = 0.5; superJumpButton.interactive = false; } hidePowerMenu(); } }); }; // Slow Fall Button var slowFallButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); slowFallButton.y = -50; slowFallButton.interactive = true; var slowFallButtonText = new Text2('SLOW FALL MODE', { size: 36, fill: 0xFFFFFF }); slowFallButtonText.anchor.set(0.5, 0.5); slowFallButton.addChild(slowFallButtonText); slowFallButton.down = function () { tween(slowFallButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; slowFallButton.up = function () { tween(slowFallButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { // Check if slow fall mode has already been used if (!slowFallModeUsed) { // Activate slow fall mode activateSlowFallMode(); slowFallModeUsed = true; // Update button appearance to show it's used slowFallButtonText.setText('USED'); slowFallButton.alpha = 0.5; slowFallButton.interactive = false; } hidePowerMenu(); } }); }; // Close button var closeButton = self.addChild(LK.getAsset('menuButtonBg', { anchorX: 0.5, anchorY: 0.5 })); closeButton.y = 50; closeButton.interactive = true; var closeText = new Text2('CLOSE', { size: 36, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.down = function () { tween(closeButton, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; closeButton.up = function () { tween(closeButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { hidePowerMenu(); } }); }; // Background click to close background.down = function () { hidePowerMenu(); }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.collected = false; var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); // Add visual indicator (star symbol) var starText = new Text2('★', { size: 30, fill: 0xFFFFFF }); starText.anchor.set(0.5, 0.5); self.addChild(starText); // Floating animation self.floatOffset = 0; self.update = function () { // Create floating effect self.floatOffset += 0.1; powerupGraphics.y = Math.sin(self.floatOffset) * 10; starText.y = Math.sin(self.floatOffset) * 10; // Rotate the star starText.rotation += 0.05; }; return self; }); var SlowFallPowerUp = Container.expand(function () { var self = Container.call(this); self.collected = false; var powerupGraphics = self.attachAsset('slowfallpowerup', { anchorX: 0.5, anchorY: 0.5 }); // Tint it blue to distinguish from jump power-up powerupGraphics.tint = 0x3498db; // Add visual indicator (feather symbol) var featherText = new Text2('🪶', { size: 30, fill: 0xFFFFFF }); featherText.anchor.set(0.5, 0.5); self.addChild(featherText); // Floating animation with slower movement self.floatOffset = 0; self.update = function () { // Create gentle floating effect self.floatOffset += 0.05; var floatY = Math.sin(self.floatOffset) * 15; powerupGraphics.y = floatY; featherText.y = floatY; // Gentle rotation featherText.rotation += 0.02; // Subtle pulsing effect using tween if (LK.ticks % 120 === 0) { tween(powerupGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.easeInOut }); tween(powerupGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeInOut }); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb }); /**** * Game Code ****/ var currentLevel = 1; var menuOverlay = null; var isMenuOpen = false; var powerMenuOverlay = null; var isPowerMenuOpen = false; var superJumpUsed = false; var slowFallModeUsed = false; var powerMenuOpened = false; var musicVolume = storage.musicVolume || 1.0; var gamePoints = 0; var highScore = storage.highScore || 0; // Sky color system var skyColors = [0x87ceeb, // Sky blue (default) 0xff6b6b, // Sunset red 0x4ecdc4, // Turquoise 0x45b7d1, // Ocean blue 0xf9ca24, // Golden yellow 0x6c5ce7, // Purple 0xa29bfe, // Light purple 0xfd79a8, // Pink 0x00b894, // Emerald 0xe17055 // Orange ]; var currentSkyColorIndex = 0; var skyTransitionActive = false; var skyCyclingActive = false; var skyCyclingTimer = null; function increaseMusicVolume() { musicVolume = Math.min(1.0, musicVolume + 0.1); storage.musicVolume = musicVolume; LK.stopMusic(); LK.playMusic('Musica', { fade: { start: 0, end: musicVolume, duration: 300 } }); } function decreaseMusicVolume() { musicVolume = Math.max(0.0, musicVolume - 0.1); storage.musicVolume = musicVolume; if (musicVolume === 0) { LK.stopMusic(); } else { LK.stopMusic(); LK.playMusic('Musica', { fade: { start: 0, end: musicVolume, duration: 300 } }); } } function changeSkyColor(newColorIndex) { if (skyTransitionActive) { return; } if (newColorIndex < 0 || newColorIndex >= skyColors.length) { return; } skyTransitionActive = true; currentSkyColorIndex = newColorIndex; // Create smooth color transition using tween var startColor = game.backgroundColor; var endColor = skyColors[newColorIndex]; // Animate background color change var colorTransition = { r: startColor >> 16 & 0xFF, g: startColor >> 8 & 0xFF, b: startColor & 0xFF }; var targetColor = { r: endColor >> 16 & 0xFF, g: endColor >> 8 & 0xFF, b: endColor & 0xFF }; tween(colorTransition, targetColor, { duration: 2000, easing: tween.easeInOut, onUpdate: function onUpdate() { var r = Math.round(colorTransition.r); var g = Math.round(colorTransition.g); var b = Math.round(colorTransition.b); var newColor = r << 16 | g << 8 | b; game.setBackgroundColor(newColor); }, onFinish: function onFinish() { skyTransitionActive = false; game.setBackgroundColor(endColor); } }); } function getRandomSkyColor() { var randomIndex; do { randomIndex = Math.floor(Math.random() * skyColors.length); } while (randomIndex === currentSkyColorIndex); return randomIndex; } function cycleSkyColor() { var nextIndex = (currentSkyColorIndex + 1) % skyColors.length; changeSkyColor(nextIndex); } function startSkyCycling() { if (skyCyclingActive) { // Stop cycling if already active stopSkyCycling(); return; } skyCyclingActive = true; // Change sky color every 2 seconds function cycleNext() { if (skyCyclingActive) { var nextIndex = (currentSkyColorIndex + 1) % skyColors.length; changeSkyColor(nextIndex); skyCyclingTimer = LK.setTimeout(cycleNext, 3000); // 3 seconds between changes } } // Start first cycle skyCyclingTimer = LK.setTimeout(cycleNext, 1000); // 1 second delay before first change } function stopSkyCycling() { skyCyclingActive = false; if (skyCyclingTimer) { LK.clearTimeout(skyCyclingTimer); skyCyclingTimer = null; } } function showPowerMenu() { if (isPowerMenuOpen || powerMenuOpened) { return; } powerMenuOpened = true; isPowerMenuOpen = true; powerMenuOverlay = LK.gui.center.addChild(new PowerMenuOverlay()); // Animate menu appearing powerMenuOverlay.alpha = 0; powerMenuOverlay.scaleX = 0.8; powerMenuOverlay.scaleY = 0.8; tween(powerMenuOverlay, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeOut }); } function hidePowerMenu() { if (!isPowerMenuOpen || !powerMenuOverlay) { return; } tween(powerMenuOverlay, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { if (powerMenuOverlay) { powerMenuOverlay.destroy(); powerMenuOverlay = null; } isPowerMenuOpen = false; } }); } function activateSuperJumpMode() { // Give player super jump for 10 seconds player.jumpPower = player.powerUpJumpPower * 1.5; // Even stronger than normal power-up player.powerUpActive = true; player.powerUpTimer = 600; // 10 seconds at 60fps // Flash player golden to show super jump mode LK.effects.flashObject(player, 0xFFD700, 500); // Create special golden boots visual effect if (player.boots) { player.removeChild(player.boots); } player.boots = LK.getAsset('boots', { anchorX: 0.5, anchorY: 1.0, alpha: 0, tint: 0xFFD700 }); player.addChild(player.boots); player.boots.x = 0; player.boots.y = 0; // Animate boots appearing tween(player.boots, { alpha: 1.0, scaleX: 1.4, scaleY: 1.4 }, { duration: 300, easing: tween.easeOut }); } function activateSlowFallMode() { // Give player slow fall for 10 seconds player.gravity = player.slowFallGravity * 0.5; // Even slower than normal slow fall player.slowFallActive = true; player.slowFallTimer = 600; // 10 seconds at 60fps // Flash player blue to show slow fall mode LK.effects.flashObject(player, 0x3498db, 500); // Create special enhanced parachute if (player.parachute) { player.removeChild(player.parachute); } player.parachute = LK.getAsset('parachute', { anchorX: 0.5, anchorY: 1.0, alpha: 0, tint: 0x3498db }); player.addChild(player.parachute); player.parachute.x = 0; player.parachute.y = -200; // Animate parachute appearing tween(player.parachute, { alpha: 0.9, y: -180, scaleX: 1.3, scaleY: 1.3 }, { duration: 500, easing: tween.easeOut }); } function showMenu() { if (isMenuOpen) { return; } isMenuOpen = true; menuOverlay = LK.gui.center.addChild(new MenuOverlay()); // Animate menu appearing menuOverlay.alpha = 0; menuOverlay.scaleX = 0.8; menuOverlay.scaleY = 0.8; tween(menuOverlay, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeOut }); } function hideMenu() { if (!isMenuOpen || !menuOverlay) { return; } // Stop sky cycling when menu closes stopSkyCycling(); tween(menuOverlay, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { if (menuOverlay) { menuOverlay.destroy(); menuOverlay = null; } isMenuOpen = false; } }); } var player = game.addChild(new Player()); player.x = 400; // Platform 1 x position player.y = 2350; // Just above platform 1 var platforms = []; var powerUps = []; var slowFallPowerUps = []; var ground = game.addChild(LK.getAsset('ground', { anchorX: 0.5, anchorY: 1.0, scaleY: 1.7 // Extend ground 70% more downward })); ground.x = 1024; ground.y = 2732; // Create platforms with numbers 1-15 var platformData = [{ x: 400, y: 2400, width: 200, number: 1 }, { x: 800, y: 2200, width: 250, number: 2 }, { x: 1200, y: 2000, width: 200, number: 3 }, { x: 600, y: 1800, width: 300, number: 4 }, { x: 1400, y: 1600, width: 200, number: 5 }, { x: 300, y: 1400, width: 250, number: 6 }, { x: 1000, y: 1200, width: 300, number: 7 }, { x: 1600, y: 1000, width: 200, number: 8 }, { x: 400, y: 800, width: 250, number: 9 }, { x: 1200, y: 600, width: 200, number: 10 }, { x: 800, y: 400, width: 300, number: 11 }, { x: 500, y: 200, width: 180, number: 12 }, { x: 1400, y: 100, width: 220, number: 13 }, { x: 200, y: -100, width: 250, number: 14 }, { x: 1000, y: -300, width: 200, number: 15 }]; function createLevel(levelNumber) { // Clear existing platforms for (var i = platforms.length - 1; i >= 0; i--) { platforms[i].destroy(); } platforms = []; // Clear existing power-ups for (var i = powerUps.length - 1; i >= 0; i--) { powerUps[i].destroy(); } powerUps = []; // Clear existing slow fall power-ups for (var i = slowFallPowerUps.length - 1; i >= 0; i--) { slowFallPowerUps[i].destroy(); } slowFallPowerUps = []; // Enhanced difficulty scaling for levels after 5 var isHardMode = levelNumber > 5; var difficultyMultiplier = isHardMode ? levelNumber - 5 : 0; // Platform sizing - much smaller after level 5 var basePlatformWidth = isHardMode ? Math.max(120, 200 - difficultyMultiplier * 15) : Math.max(150, 250 - (levelNumber - 1) * 10); var platformHeight = isHardMode ? Math.max(25, 40 - difficultyMultiplier * 2) : 40; // Vertical spacing - increased gaps after level 5 var baseY = 2400; var yStep = isHardMode ? Math.min(280, 200 + difficultyMultiplier * 15) : 200; // Generate new platform layout for each level var _loop = function _loop() { platformNumber = i + 1; // Calculate platform width with additional randomness for hard mode var platformWidth = basePlatformWidth; if (isHardMode && platformNumber > 1 && platformNumber < 15) { // Add random variation to platform sizes (±20 pixels) platformWidth += (Math.random() - 0.5) * 40; platformWidth = Math.max(100, Math.min(platformWidth, 200)); // Clamp between 100-200 } platform = game.addChild(new Platform(platformWidth, platformHeight, platformNumber)); // Positioning logic - more challenging after level 5 var minX, maxX, randomX; if (isHardMode) { // Hard mode: More precise positioning requirements minX = 150 + platformWidth / 2; maxX = 1898 - platformWidth / 2; // Create more challenging horizontal gaps between platforms if (i > 0) { var lastPlatform = platforms[platforms.length - 1]; var minGap = 200 + difficultyMultiplier * 20; // Minimum gap increases with difficulty var maxGap = 400 + difficultyMultiplier * 30; // Maximum gap increases with difficulty // Try to place platform at challenging but reachable distance var preferredDistance = minGap + Math.random() * (maxGap - minGap); var direction = Math.random() > 0.5 ? 1 : -1; // Random direction randomX = lastPlatform.x + direction * preferredDistance; randomX = Math.max(minX, Math.min(maxX, randomX)); // Keep within bounds } else { randomX = minX + Math.random() * (maxX - minX); } } else { // Normal mode: Original positioning minX = 200; maxX = 1848; randomX = minX + Math.random() * (maxX - minX); } platform.x = randomX; platform.y = baseY - i * yStep; platforms.push(platform); // Make the last platform (platform 15) shine with golden glow if (platformNumber === 15) { // Golden color // Create pulsing glow effect var _createPulsingGlow = function createPulsingGlow() { tween(platform.children[0], { alpha: 0.6, scaleX: platform.children[0].scaleX * 1.1, scaleY: platform.children[0].scaleY * 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(platform.children[0], { alpha: 1.0, scaleX: platform.children[0].scaleX / 1.1, scaleY: platform.children[0].scaleY / 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: _createPulsingGlow // Loop the animation }); } }); }; // Start the pulsing animation with a delay to make it more noticeable // Add sparkling effect with tint changes var createSparkleEffect = function createSparkleEffect() { var sparkleColors = [0xFFD700, 0xFFF700, 0xFFFF00, 0xFFD700]; // Golden to bright yellow var currentColorIndex = 0; function nextSparkle() { currentColorIndex = (currentColorIndex + 1) % sparkleColors.length; tween(platform.children[0], { tint: sparkleColors[currentColorIndex] }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { LK.setTimeout(nextSparkle, Math.random() * 800 + 400); // Random delay between sparkles } }); } nextSparkle(); }; // Start sparkling effect // Add golden tint to make it special platform.children[0].tint = 0xFFD700; LK.setTimeout(function () { _createPulsingGlow(); }, 500); LK.setTimeout(function () { createSparkleEffect(); }, 1000); } // Spawn power-up randomly - reduced chance in hard mode var powerUpChance = isHardMode ? Math.max(0.02, 0.07 - difficultyMultiplier * 0.01) : 0.07; if (Math.random() < powerUpChance && platformNumber !== 1 && platformNumber !== 15) { powerUp = game.addChild(new PowerUp()); powerUp.x = platform.x; powerUp.y = platform.y - 60; // Position above platform powerUps.push(powerUp); } // Spawn slow fall power-up randomly - reduced chance in hard mode var slowFallChance = isHardMode ? Math.max(0.02, 0.07 - difficultyMultiplier * 0.01) : 0.07; if (Math.random() < slowFallChance && platformNumber !== 1 && platformNumber !== 15) { slowFallPowerUp = game.addChild(new SlowFallPowerUp()); slowFallPowerUp.x = platform.x + 50; // Offset slightly to avoid overlap slowFallPowerUp.y = platform.y - 60; // Position above platform slowFallPowerUps.push(slowFallPowerUp); } }, platformNumber, platform, minX, maxX, randomX, powerUp, slowFallPowerUp; for (var i = 0; i < 15; i++) { _loop(); } } // Apply difficulty modifiers to player stats for hard mode function applyDifficultyModifiers(levelNumber) { var isHardMode = levelNumber > 5; if (isHardMode) { var difficultyMultiplier = levelNumber - 5; // Increase gravity slightly (making falls faster and jumps shorter) player.baseGravity = Math.min(1.2, 0.8 + difficultyMultiplier * 0.05); player.gravity = player.slowFallActive ? player.slowFallGravity : player.baseGravity; // Reduce jump power slightly (making precise jumping harder) player.baseJumpPower = Math.max(25, 30 - difficultyMultiplier * 0.8); player.powerUpJumpPower = Math.max(38, 45 - difficultyMultiplier * 1.0); player.jumpPower = player.powerUpActive ? player.powerUpJumpPower : player.baseJumpPower; // Reduce movement speed slightly for more precise control requirements player.speed = Math.max(8, 12 - difficultyMultiplier * 0.5); player.runSpeed = Math.max(14, 20 - difficultyMultiplier * 0.8); } else { // Reset to normal values for easier levels player.baseGravity = 0.8; player.gravity = player.slowFallActive ? player.slowFallGravity : player.baseGravity; player.baseJumpPower = 30; player.powerUpJumpPower = 45; player.jumpPower = player.powerUpActive ? player.powerUpJumpPower : player.baseJumpPower; player.speed = 12; player.runSpeed = 20; } } // Create initial level createLevel(currentLevel); applyDifficultyModifiers(currentLevel); // Control buttons var leftButton = LK.gui.bottomLeft.addChild(new ControlButton('left')); leftButton.x = 110; leftButton.y = -110; var rightButton = LK.gui.bottomLeft.addChild(new ControlButton('right')); rightButton.x = 310; rightButton.y = -110; var runButton = LK.gui.bottomLeft.addChild(new ControlButton('run')); runButton.x = 510; runButton.y = -110; var jumpButton = LK.gui.bottomRight.addChild(new ControlButton('jump')); jumpButton.x = -110; jumpButton.y = -110; // Control button labels var leftLabel = new Text2('←', { size: 60, fill: 0xFFFFFF }); leftLabel.anchor.set(0.5, 0.5); leftButton.addChild(leftLabel); var rightLabel = new Text2('→', { size: 60, fill: 0xFFFFFF }); rightLabel.anchor.set(0.5, 0.5); rightButton.addChild(rightLabel); var runLabel = new Text2('RUN', { size: 30, fill: 0xFFFFFF }); runLabel.anchor.set(0.5, 0.5); runButton.addChild(runLabel); var jumpLabel = new Text2('↑', { size: 60, fill: 0xFFFFFF }); jumpLabel.anchor.set(0.5, 0.5); jumpButton.addChild(jumpLabel); // Menu button in top-right corner var menuButton = LK.gui.topRight.addChild(new MenuButton()); menuButton.x = -120; // Position away from right edge menuButton.y = 120; // Position below top menu area // Power menu button var powerMenuButton = LK.gui.bottomRight.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5 })); powerMenuButton.x = -220; powerMenuButton.y = -220; powerMenuButton.interactive = true; // Add power icon (lightning bolt) var powerIcon = new Text2('⚡', { size: 40, fill: 0xFFD700 }); powerIcon.anchor.set(0.5, 0.5); powerMenuButton.addChild(powerIcon); powerMenuButton.down = function () { tween(powerMenuButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.easeOut }); }; powerMenuButton.up = function () { tween(powerMenuButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { showPowerMenu(); } }); }; // Level display var levelText = new Text2('Level ' + currentLevel, { size: 80, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 120; // Position below the top menu // Power-up status display var powerUpText = new Text2('', { size: 40, fill: 0xf39c12 }); powerUpText.anchor.set(0.5, 0); LK.gui.top.addChild(powerUpText); powerUpText.y = 200; // Slow fall status display var slowFallText = new Text2('', { size: 40, fill: 0x3498db }); slowFallText.anchor.set(0.5, 0); LK.gui.top.addChild(slowFallText); slowFallText.y = 250; // Points display var pointsText = new Text2('Points: 0', { size: 50, fill: 0xFFFFFF }); pointsText.anchor.set(0.5, 0); LK.gui.top.addChild(pointsText); pointsText.y = 300; // High score display var highScoreText = new Text2('Best: ' + highScore, { size: 35, fill: 0xf39c12 }); highScoreText.anchor.set(0.5, 0); LK.gui.top.addChild(highScoreText); highScoreText.y = 360; function checkCollisions() { var playerBottom = player.y; var playerTop = player.y - 180; var playerLeft = player.x - 90; var playerRight = player.x + 90; // Check ground collision if (playerBottom >= ground.y - 50) { if (player.velocityY > 0) { player.y = ground.y - 50; player.velocityY = 0; player.onGround = true; } } // Check platform collisions for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformLeft = platform.x - platform.platformWidth / 2; var platformRight = platform.x + platform.platformWidth / 2; var platformTop = platform.y - platform.platformHeight / 2; var platformBottom = platform.y + platform.platformHeight / 2; // Check if player is horizontally aligned with platform if (playerRight > platformLeft && playerLeft < platformRight) { // Check if player is falling onto platform from above if (player.velocityY > 0 && playerBottom >= platformTop && playerTop < platformTop) { player.y = platformTop; player.velocityY = 0; player.onGround = true; } } } // Check power-up collisions for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; if (!powerUp.collected) { var powerUpLeft = powerUp.x - 20; var powerUpRight = powerUp.x + 20; var powerUpTop = powerUp.y - 20; var powerUpBottom = powerUp.y + 20; // Check if player intersects with power-up if (playerRight > powerUpLeft && playerLeft < powerUpRight && playerBottom > powerUpTop && playerTop < powerUpBottom) { powerUp.collected = true; player.collectPowerUp(); // Add 10 points for collecting power-up gamePoints += 10; pointsText.setText('Points: ' + gamePoints); // Check for new high score if (gamePoints > highScore) { highScore = gamePoints; storage.highScore = highScore; highScoreText.setText('Best: ' + highScore); // Flash screen gold for new high score LK.effects.flashScreen(0xFFD700, 300); } powerUp.destroy(); powerUps.splice(i, 1); } } } // Check slow fall power-up collisions for (var i = slowFallPowerUps.length - 1; i >= 0; i--) { var slowFallPowerUp = slowFallPowerUps[i]; if (!slowFallPowerUp.collected) { var slowFallLeft = slowFallPowerUp.x - 20; var slowFallRight = slowFallPowerUp.x + 20; var slowFallTop = slowFallPowerUp.y - 20; var slowFallBottom = slowFallPowerUp.y + 20; // Check if player intersects with slow fall power-up (slime) if (playerRight > slowFallLeft && playerLeft < slowFallRight && playerBottom > slowFallTop && playerTop < slowFallBottom) { slowFallPowerUp.collected = true; // Play slime sound effect LK.getSound('Voz').play(); // Player character sound and animation when touching slime // Create bouncy squash animation for player tween(player.children[0], { scaleX: 1.4, scaleY: 0.7, rotation: Math.random() * 0.3 - 0.15 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(player.children[0], { scaleX: 0.9, scaleY: 1.3, rotation: Math.random() * 0.2 - 0.1 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(player.children[0], { scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 180, easing: tween.easeOut }); } }); } }); // Create slime bounce animation tween(slowFallPowerUp.children[0], { scaleX: 1.5, scaleY: 0.8, rotation: Math.random() * 0.4 - 0.2 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(slowFallPowerUp.children[0], { scaleX: 0.8, scaleY: 1.4, rotation: Math.random() * 0.3 - 0.15 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(slowFallPowerUp.children[0], { scaleX: 1.0, scaleY: 1.0, rotation: 0, alpha: 0 }, { duration: 200, easing: tween.easeInOut }); } }); } }); // Add jiggle animation to the feather text tween(slowFallPowerUp.children[1], { scaleX: 1.3, scaleY: 1.3, rotation: Math.random() * 0.5 - 0.25 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(slowFallPowerUp.children[1], { scaleX: 0.9, scaleY: 0.9, rotation: Math.random() * 0.3 - 0.15 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(slowFallPowerUp.children[1], { scaleX: 1.0, scaleY: 1.0, rotation: 0, alpha: 0 }, { duration: 150, easing: tween.easeInOut }); } }); } }); player.collectSlowFallPowerUp(); // Add 10 points for collecting slow fall power-up gamePoints += 10; pointsText.setText('Points: ' + gamePoints); // Check for new high score if (gamePoints > highScore) { highScore = gamePoints; storage.highScore = highScore; highScoreText.setText('Best: ' + highScore); // Flash screen gold for new high score LK.effects.flashScreen(0xFFD700, 300); } // Destroy slime after animation completes LK.setTimeout(function () { slowFallPowerUp.destroy(); slowFallPowerUps.splice(slowFallPowerUps.indexOf(slowFallPowerUp), 1); }, 500); } } } } game.update = function () { // Check collisions first to set onGround flag checkCollisions(); // Handle input player.setRunning(runButton.isPressed); if (leftButton.isPressed) { player.moveLeft(); } else if (rightButton.isPressed) { player.moveRight(); } else { player.stopHorizontalMovement(); } if (jumpButton.isPressed) { player.jump(); } // Update power-up display if (player.powerUpActive) { var secondsLeft = Math.ceil(player.powerUpTimer / 60); powerUpText.setText('★ Super Jump: ' + secondsLeft + 's'); } else { powerUpText.setText(''); } // Update slow fall display if (player.slowFallActive) { var secondsLeft = Math.ceil(player.slowFallTimer / 60); slowFallText.setText('🪶 Slow Fall: ' + secondsLeft + 's'); } else { slowFallText.setText(''); } // Camera follows player var targetY = -player.y + 1366; // Center player vertically on screen game.y = targetY; // Check if player reached platform 15 var platform15 = null; for (var i = 0; i < platforms.length; i++) { if (platforms[i].platformNumber === 15) { platform15 = platforms[i]; break; } } if (platform15) { var playerBottom = player.y; var playerLeft = player.x - 90; var playerRight = player.x + 90; var platform15Left = platform15.x - platform15.platformWidth / 2; var platform15Right = platform15.x + platform15.platformWidth / 2; var platform15Top = platform15.y - platform15.platformHeight / 2; // Check if player is on platform 15 if (playerRight > platform15Left && playerLeft < platform15Right && playerBottom >= platform15Top && playerBottom <= platform15Top + 50) { // Player reached platform 15 - advance to next level // Add 20 points for completing a level gamePoints += 20; pointsText.setText('Points: ' + gamePoints); // Check for new high score if (gamePoints > highScore) { highScore = gamePoints; storage.highScore = highScore; highScoreText.setText('Best: ' + highScore); // Flash screen gold for new high score LK.effects.flashScreen(0xFFD700, 300); } currentLevel++; if (currentLevel > 10) { // Update final score before showing you win LK.setScore(gamePoints); // After 10 levels, show you win LK.showYouWin(); } else { // Reset power usage flags for new level superJumpUsed = false; slowFallModeUsed = false; // Create next level createLevel(currentLevel); applyDifficultyModifiers(currentLevel); levelText.setText('Level ' + currentLevel); // Reset player position for new level player.x = 400; // Platform 1 x position player.y = 2350; // Just above platform 1 player.velocityX = 0; player.velocityY = 0; // Change sky color every few levels for visual variety if (currentLevel % 3 === 0) { var randomSkyIndex = getRandomSkyColor(); changeSkyColor(randomSkyIndex); } // Flash screen green to indicate level completion LK.effects.flashScreen(0x00ff00, 500); } } } // Check if player fell off screen if (player.y > 2800) { // Set final score and show game over LK.setScore(gamePoints); LK.showGameOver(); } }; // Play background music with saved volume if (musicVolume > 0) { LK.playMusic('Musica', { fade: { start: 0, end: musicVolume, duration: 500 } }); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
musicVolume: 1
});
/****
* Classes
****/
var ControlButton = Container.expand(function (type) {
var self = Container.call(this);
self.buttonType = type;
self.isPressed = false;
var buttonGraphics;
if (type === 'jump') {
buttonGraphics = self.attachAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (type === 'run') {
buttonGraphics = self.attachAsset('runButton', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
buttonGraphics = self.attachAsset(type === 'left' ? 'leftButton' : 'rightButton', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Add larger transparent hitbox for easier touch detection
var hitboxSize = 240; // Larger than visual button (180px)
var hitbox = LK.getAsset('jumpButton', {
anchorX: 0.5,
anchorY: 0.5,
width: hitboxSize,
height: hitboxSize,
alpha: 0 // Invisible
});
self.addChild(hitbox);
self.down = function (x, y, obj) {
self.isPressed = true;
// Scale down and change alpha for press effect
tween(buttonGraphics, {
scaleX: 0.85,
scaleY: 0.85,
alpha: 0.7
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
self.isPressed = false;
// Scale back up and restore alpha for release effect
tween(buttonGraphics, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 1.0
}, {
duration: 150,
easing: tween.easeOut
});
};
// Add idle floating animation
self.animationTimer = Math.random() * 100; // Random start offset
self.update = function () {
if (!self.isPressed) {
// Gentle floating animation when not pressed
self.animationTimer += 0.05;
var floatOffset = Math.sin(self.animationTimer) * 3;
buttonGraphics.y = floatOffset;
// Subtle breathing scale effect
var breathingScale = 1.0 + Math.sin(self.animationTimer * 2) * 0.02;
if (!buttonGraphics._tweening) {
buttonGraphics.scaleX = breathingScale;
buttonGraphics.scaleY = breathingScale;
}
}
};
return self;
});
var MenuButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Add menu icon (three lines)
var line1 = new Text2('—', {
size: 24,
fill: 0xFFFFFF
});
line1.anchor.set(0.5, 0.5);
line1.y = -15;
self.addChild(line1);
var line2 = new Text2('—', {
size: 24,
fill: 0xFFFFFF
});
line2.anchor.set(0.5, 0.5);
self.addChild(line2);
var line3 = new Text2('—', {
size: 24,
fill: 0xFFFFFF
});
line3.anchor.set(0.5, 0.5);
line3.y = 15;
self.addChild(line3);
self.down = function (x, y, obj) {
// Scale down for press effect
tween(buttonGraphics, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Show menu
showMenu();
};
self.up = function (x, y, obj) {
// Scale back up
tween(buttonGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut
});
};
return self;
});
var MenuOverlay = Container.expand(function () {
var self = Container.call(this);
// Semi-transparent background
var background = LK.getAsset('menuOverlay', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 0.8
});
background.interactive = true;
self.addChild(background);
// Menu panel
var menuPanel = self.attachAsset('menuOverlay', {
anchorX: 0.5,
anchorY: 0.5
});
// Menu title
var titleText = new Text2('MENU', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Restart Level button
var restartButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
restartButton.y = -150;
restartButton.interactive = true;
var restartText = new Text2('RESTART LEVEL', {
size: 36,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartButton.addChild(restartText);
restartButton.down = function () {
tween(restartButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
restartButton.up = function () {
tween(restartButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show final score before restart
LK.setScore(gamePoints);
// Reset points for new game
gamePoints = 0;
pointsText.setText('Points: 0');
// Reset power usage flags
superJumpUsed = false;
slowFallModeUsed = false;
// Restart current level
createLevel(currentLevel);
applyDifficultyModifiers(currentLevel);
player.x = 400; // Platform 1 x position
player.y = 2350; // Just above platform 1
player.velocityX = 0;
player.velocityY = 0;
player.powerUpActive = false;
player.slowFallActive = false;
player.jumpPower = player.baseJumpPower;
player.gravity = player.baseGravity;
hideMenu();
}
});
};
// Music Volume Controls
var volumeText = new Text2('MUSIC VOLUME', {
size: 32,
fill: 0xFFFFFF
});
volumeText.anchor.set(0.5, 0.5);
volumeText.y = -100;
self.addChild(volumeText);
var volumeDisplayText = new Text2(Math.round(musicVolume * 100) + '%', {
size: 28,
fill: 0xf39c12
});
volumeDisplayText.anchor.set(0.5, 0.5);
volumeDisplayText.y = -60;
self.addChild(volumeDisplayText);
// Volume Down Button
var volumeDownButton = self.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
}));
volumeDownButton.x = -100;
volumeDownButton.y = -20;
volumeDownButton.interactive = true;
var volumeDownText = new Text2('−', {
size: 40,
fill: 0xFFFFFF
});
volumeDownText.anchor.set(0.5, 0.5);
volumeDownButton.addChild(volumeDownText);
volumeDownButton.down = function () {
tween(volumeDownButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
volumeDownButton.up = function () {
tween(volumeDownButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
decreaseMusicVolume();
volumeDisplayText.setText(Math.round(musicVolume * 100) + '%');
}
});
};
// Volume Up Button
var volumeUpButton = self.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
}));
volumeUpButton.x = 100;
volumeUpButton.y = -20;
volumeUpButton.interactive = true;
var volumeUpText = new Text2('+', {
size: 40,
fill: 0xFFFFFF
});
volumeUpText.anchor.set(0.5, 0.5);
volumeUpButton.addChild(volumeUpText);
volumeUpButton.down = function () {
tween(volumeUpButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
volumeUpButton.up = function () {
tween(volumeUpButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
increaseMusicVolume();
volumeDisplayText.setText(Math.round(musicVolume * 100) + '%');
}
});
};
// Sky Color Controls
var skyColorText = new Text2('SKY COLOR', {
size: 32,
fill: 0xFFFFFF
});
skyColorText.anchor.set(0.5, 0.5);
skyColorText.y = 40;
self.addChild(skyColorText);
// Previous Sky Color Button
var skyPrevButton = self.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
}));
skyPrevButton.x = -100;
skyPrevButton.y = 80;
skyPrevButton.interactive = true;
var skyPrevText = new Text2('←', {
size: 40,
fill: 0xFFFFFF
});
skyPrevText.anchor.set(0.5, 0.5);
skyPrevButton.addChild(skyPrevText);
skyPrevButton.down = function () {
tween(skyPrevButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
skyPrevButton.up = function () {
tween(skyPrevButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
var prevIndex = currentSkyColorIndex - 1;
if (prevIndex < 0) {
prevIndex = skyColors.length - 1;
}
changeSkyColor(prevIndex);
}
});
};
// Next Sky Color Button
var skyNextButton = self.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
}));
skyNextButton.x = 100;
skyNextButton.y = 80;
skyNextButton.interactive = true;
var skyNextText = new Text2('→', {
size: 40,
fill: 0xFFFFFF
});
skyNextText.anchor.set(0.5, 0.5);
skyNextButton.addChild(skyNextText);
skyNextButton.down = function () {
tween(skyNextButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
skyNextButton.up = function () {
tween(skyNextButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
cycleSkyColor();
}
});
};
// Random Sky Color Button
var skyRandomButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
skyRandomButton.y = 140;
skyRandomButton.interactive = true;
var skyRandomText = new Text2('RANDOM SKY', {
size: 28,
fill: 0xFFFFFF
});
skyRandomText.anchor.set(0.5, 0.5);
skyRandomButton.addChild(skyRandomText);
skyRandomButton.down = function () {
tween(skyRandomButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
skyRandomButton.up = function () {
tween(skyRandomButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
var randomIndex = getRandomSkyColor();
changeSkyColor(randomIndex);
}
});
};
// Cycle Sky Colors Button
var cycleSkyButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
cycleSkyButton.y = 200;
cycleSkyButton.interactive = true;
var cycleSkyText = new Text2('CYCLE SKY COLORS', {
size: 28,
fill: 0xFFFFFF
});
cycleSkyText.anchor.set(0.5, 0.5);
cycleSkyButton.addChild(cycleSkyText);
cycleSkyButton.down = function () {
tween(cycleSkyButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
cycleSkyButton.up = function () {
tween(cycleSkyButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Start automatic sky color cycling
startSkyCycling();
}
});
};
// Close button
var closeButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.y = 260;
closeButton.interactive = true;
var closeText = new Text2('CLOSE', {
size: 36,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.down = function () {
tween(closeButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
closeButton.up = function () {
tween(closeButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
hideMenu();
}
});
};
// Background click to close
background.down = function () {
hideMenu();
};
return self;
});
var Platform = Container.expand(function (width, height, number) {
var self = Container.call(this);
self.platformWidth = width || 300;
self.platformHeight = height || 40;
self.platformNumber = number || 0;
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.platformWidth / 300,
scaleY: self.platformHeight / 40
});
// Add number text if platform has a number
if (self.platformNumber > 0) {
var numberText = new Text2(self.platformNumber.toString(), {
size: 30,
fill: 0x000000
});
numberText.anchor.set(0.5, 0.5);
self.addChild(numberText);
}
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
self.velocityX = 0;
self.velocityY = 0;
self.speed = 12;
self.runSpeed = 20;
self.isRunning = false;
self.jumpPower = 30;
self.baseJumpPower = 30;
self.powerUpJumpPower = 45;
self.powerUpActive = false;
self.powerUpTimer = 0;
self.slowFallActive = false;
self.slowFallTimer = 0;
self.gravity = 0.8;
self.baseGravity = 0.8;
self.slowFallGravity = 0.25;
self.onGround = false;
self.canDoubleJump = false;
self.hasDoubleJumped = false;
self.parachute = null;
self.boots = null;
self.maxFallSpeed = 15;
// Animation states
self.animationState = 'idle'; // 'idle', 'falling', 'jumping'
self.lastOnGround = true;
self.animationTimer = 0;
self.moveLeft = function () {
self.velocityX = self.isRunning ? -self.runSpeed : -self.speed;
};
self.moveRight = function () {
self.velocityX = self.isRunning ? self.runSpeed : self.speed;
};
self.setRunning = function (running) {
self.isRunning = running;
};
self.jump = function () {
if (self.onGround) {
self.velocityY = -self.jumpPower;
self.onGround = false;
self.canDoubleJump = true;
self.hasDoubleJumped = false;
// Play voice sound when jumping
LK.getSound('Voz').play();
} else if (self.canDoubleJump && !self.hasDoubleJumped) {
// Double jump
self.velocityY = -self.jumpPower * 0.9; // Slightly weaker than first jump
self.hasDoubleJumped = true;
self.canDoubleJump = false;
// Play voice sound when double jumping
LK.getSound('Voz').play();
// Flash player purple to show double jump
LK.effects.flashObject(self, 0x9b59b6, 200);
}
};
self.stopHorizontalMovement = function () {
self.velocityX = 0;
};
self.collectPowerUp = function () {
self.powerUpActive = true;
self.powerUpTimer = 300; // 5 seconds at 60fps
self.jumpPower = self.powerUpJumpPower;
// Flash player green to show power-up is active
LK.effects.flashObject(self, 0x00ff00, 300);
// Create boots visual effect
self.boots = LK.getAsset('boots', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
self.addChild(self.boots);
self.boots.x = 0;
self.boots.y = 0; // Position at player's feet
// Animate boots appearing
tween(self.boots, {
alpha: 1.0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut
});
};
self.collectSlowFallPowerUp = function () {
self.slowFallActive = true;
self.slowFallTimer = 300; // 5 seconds at 60fps
self.gravity = self.slowFallGravity;
// Flash player blue to show slow fall is active
LK.effects.flashObject(self, 0x3498db, 300);
// Add gentle blue tint while active
tween(playerGraphics, {
tint: 0xadd8e6
}, {
duration: 300,
easing: tween.easeOut
});
// Create parachute
self.parachute = LK.getAsset('parachute', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
self.addChild(self.parachute);
self.parachute.x = 0;
self.parachute.y = -200; // Position above player
// Animate parachute appearing
tween(self.parachute, {
alpha: 0.8,
y: -180
}, {
duration: 500,
easing: tween.easeOut
});
};
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Limit fall speed
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Flip sprite based on movement direction
if (self.velocityX > 0) {
// Moving right - face right (normal)
playerGraphics.scaleX = Math.abs(playerGraphics.scaleX);
} else if (self.velocityX < 0) {
// Moving left - face left (flipped)
playerGraphics.scaleX = -Math.abs(playerGraphics.scaleX);
}
// Update animation timer
self.animationTimer += 0.1;
// Determine animation state
var newAnimationState = 'idle';
if (!self.onGround && self.velocityY < -5) {
newAnimationState = 'jumping';
} else if (!self.onGround && self.velocityY > 5) {
newAnimationState = 'falling';
} else if (self.onGround && self.velocityX !== 0) {
newAnimationState = 'walking';
} else if (self.onGround) {
newAnimationState = 'idle';
}
// Apply animations based on state transitions
if (self.animationState !== newAnimationState) {
// State changed, apply new animation
if (newAnimationState === 'jumping') {
// Jump animation - stretch upward
tween(playerGraphics, {
scaleY: 1.3,
scaleX: 0.8,
rotation: self.velocityX > 0 ? 0.1 : self.velocityX < 0 ? -0.1 : 0
}, {
duration: 200,
easing: tween.easeOut
});
} else if (newAnimationState === 'falling') {
// Fall animation - compress and tilt
tween(playerGraphics, {
scaleY: 0.7,
scaleX: 1.2,
rotation: self.velocityX > 0 ? 0.2 : self.velocityX < 0 ? -0.2 : 0
}, {
duration: 300,
easing: tween.easeOut
});
} else if (newAnimationState === 'idle' && !self.lastOnGround && self.onGround) {
// Landing animation - squash and recover
tween(playerGraphics, {
scaleY: 0.6,
scaleX: 1.4,
rotation: 0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playerGraphics, {
scaleY: 1.0,
scaleX: 1.0,
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
} else if (newAnimationState === 'walking') {
// Walking animation - return to normal scale for bouncing
tween(playerGraphics, {
scaleY: 1.0,
scaleX: 1.0,
rotation: 0
}, {
duration: 200,
easing: tween.easeOut
});
} else if (newAnimationState === 'idle') {
// Return to idle animation
tween(playerGraphics, {
scaleY: 1.0,
scaleX: 1.0,
rotation: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Continuous animations based on state
if (newAnimationState === 'idle' && self.onGround) {
// Gentle breathing effect
var breathingScale = 1.0 + Math.sin(self.animationTimer * 2) * 0.02;
if (!playerGraphics._tweening) {
// Only apply if not currently tweening
playerGraphics.scaleY = breathingScale;
}
} else if (newAnimationState === 'walking' && self.onGround) {
// Walking animation - bouncing effect (slower)
var walkingBounce = 1.0 + Math.sin(self.animationTimer * 4) * 0.15;
var walkingTilt = Math.sin(self.animationTimer * 4) * 0.05;
if (!playerGraphics._tweening) {
// Only apply if not currently tweening
playerGraphics.scaleY = walkingBounce;
playerGraphics.rotation = walkingTilt * (self.velocityX > 0 ? 1 : -1);
}
}
// Update states for next frame
self.animationState = newAnimationState;
self.lastOnGround = self.onGround;
// Keep player within screen bounds horizontally
if (self.x < 90) {
self.x = 90;
}
if (self.x > 1958) {
self.x = 1958;
}
// Handle power-up timer
if (self.powerUpActive) {
self.powerUpTimer--;
if (self.powerUpTimer <= 0) {
self.powerUpActive = false;
self.jumpPower = self.baseJumpPower;
// Flash player red to show power-up expired
LK.effects.flashObject(self, 0xff0000, 200);
// Remove boots with animation
if (self.boots) {
tween(self.boots, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (self.boots) {
self.removeChild(self.boots);
self.boots = null;
}
}
});
}
}
}
// Handle slow fall timer
if (self.slowFallActive) {
self.slowFallTimer--;
// Animate parachute swaying
if (self.parachute) {
var swayAmount = Math.sin(self.animationTimer * 3) * 15;
self.parachute.x = swayAmount;
self.parachute.rotation = Math.sin(self.animationTimer * 2) * 0.1;
}
if (self.slowFallTimer <= 0) {
self.slowFallActive = false;
self.gravity = self.baseGravity;
// Flash player red to show slow fall expired and remove tint
LK.effects.flashObject(self, 0xff0000, 200);
tween(playerGraphics, {
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeOut
});
// Remove parachute with animation
if (self.parachute) {
tween(self.parachute, {
alpha: 0,
y: -220
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
if (self.parachute) {
self.removeChild(self.parachute);
self.parachute = null;
}
}
});
}
}
}
// Reset double jump when landing
if (self.onGround && !self.lastOnGround) {
self.canDoubleJump = false;
self.hasDoubleJumped = false;
}
// Reset onGround flag
self.onGround = false;
};
return self;
});
var PowerMenuOverlay = Container.expand(function () {
var self = Container.call(this);
// Semi-transparent background
var background = LK.getAsset('menuOverlay', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 0.8
});
background.interactive = true;
self.addChild(background);
// Menu panel
var menuPanel = self.attachAsset('menuOverlay', {
anchorX: 0.5,
anchorY: 0.5
});
// Menu title
var titleText = new Text2('POWER MENU', {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
self.addChild(titleText);
// Super Jump Button
var superJumpButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
superJumpButton.y = -150;
superJumpButton.interactive = true;
var superJumpText = new Text2('SUPER JUMP', {
size: 36,
fill: 0xFFFFFF
});
superJumpText.anchor.set(0.5, 0.5);
superJumpButton.addChild(superJumpText);
superJumpButton.down = function () {
tween(superJumpButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
superJumpButton.up = function () {
tween(superJumpButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Check if super jump has already been used
if (!superJumpUsed) {
// Activate super jump mode
activateSuperJumpMode();
superJumpUsed = true;
// Update button appearance to show it's used
superJumpText.setText('USED');
superJumpButton.alpha = 0.5;
superJumpButton.interactive = false;
}
hidePowerMenu();
}
});
};
// Slow Fall Button
var slowFallButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
slowFallButton.y = -50;
slowFallButton.interactive = true;
var slowFallButtonText = new Text2('SLOW FALL MODE', {
size: 36,
fill: 0xFFFFFF
});
slowFallButtonText.anchor.set(0.5, 0.5);
slowFallButton.addChild(slowFallButtonText);
slowFallButton.down = function () {
tween(slowFallButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
slowFallButton.up = function () {
tween(slowFallButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Check if slow fall mode has already been used
if (!slowFallModeUsed) {
// Activate slow fall mode
activateSlowFallMode();
slowFallModeUsed = true;
// Update button appearance to show it's used
slowFallButtonText.setText('USED');
slowFallButton.alpha = 0.5;
slowFallButton.interactive = false;
}
hidePowerMenu();
}
});
};
// Close button
var closeButton = self.addChild(LK.getAsset('menuButtonBg', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.y = 50;
closeButton.interactive = true;
var closeText = new Text2('CLOSE', {
size: 36,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.down = function () {
tween(closeButton, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
closeButton.up = function () {
tween(closeButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
hidePowerMenu();
}
});
};
// Background click to close
background.down = function () {
hidePowerMenu();
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.collected = false;
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Add visual indicator (star symbol)
var starText = new Text2('★', {
size: 30,
fill: 0xFFFFFF
});
starText.anchor.set(0.5, 0.5);
self.addChild(starText);
// Floating animation
self.floatOffset = 0;
self.update = function () {
// Create floating effect
self.floatOffset += 0.1;
powerupGraphics.y = Math.sin(self.floatOffset) * 10;
starText.y = Math.sin(self.floatOffset) * 10;
// Rotate the star
starText.rotation += 0.05;
};
return self;
});
var SlowFallPowerUp = Container.expand(function () {
var self = Container.call(this);
self.collected = false;
var powerupGraphics = self.attachAsset('slowfallpowerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint it blue to distinguish from jump power-up
powerupGraphics.tint = 0x3498db;
// Add visual indicator (feather symbol)
var featherText = new Text2('🪶', {
size: 30,
fill: 0xFFFFFF
});
featherText.anchor.set(0.5, 0.5);
self.addChild(featherText);
// Floating animation with slower movement
self.floatOffset = 0;
self.update = function () {
// Create gentle floating effect
self.floatOffset += 0.05;
var floatY = Math.sin(self.floatOffset) * 15;
powerupGraphics.y = floatY;
featherText.y = floatY;
// Gentle rotation
featherText.rotation += 0.02;
// Subtle pulsing effect using tween
if (LK.ticks % 120 === 0) {
tween(powerupGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.easeInOut
});
tween(powerupGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 600,
easing: tween.easeInOut
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
var currentLevel = 1;
var menuOverlay = null;
var isMenuOpen = false;
var powerMenuOverlay = null;
var isPowerMenuOpen = false;
var superJumpUsed = false;
var slowFallModeUsed = false;
var powerMenuOpened = false;
var musicVolume = storage.musicVolume || 1.0;
var gamePoints = 0;
var highScore = storage.highScore || 0;
// Sky color system
var skyColors = [0x87ceeb,
// Sky blue (default)
0xff6b6b,
// Sunset red
0x4ecdc4,
// Turquoise
0x45b7d1,
// Ocean blue
0xf9ca24,
// Golden yellow
0x6c5ce7,
// Purple
0xa29bfe,
// Light purple
0xfd79a8,
// Pink
0x00b894,
// Emerald
0xe17055 // Orange
];
var currentSkyColorIndex = 0;
var skyTransitionActive = false;
var skyCyclingActive = false;
var skyCyclingTimer = null;
function increaseMusicVolume() {
musicVolume = Math.min(1.0, musicVolume + 0.1);
storage.musicVolume = musicVolume;
LK.stopMusic();
LK.playMusic('Musica', {
fade: {
start: 0,
end: musicVolume,
duration: 300
}
});
}
function decreaseMusicVolume() {
musicVolume = Math.max(0.0, musicVolume - 0.1);
storage.musicVolume = musicVolume;
if (musicVolume === 0) {
LK.stopMusic();
} else {
LK.stopMusic();
LK.playMusic('Musica', {
fade: {
start: 0,
end: musicVolume,
duration: 300
}
});
}
}
function changeSkyColor(newColorIndex) {
if (skyTransitionActive) {
return;
}
if (newColorIndex < 0 || newColorIndex >= skyColors.length) {
return;
}
skyTransitionActive = true;
currentSkyColorIndex = newColorIndex;
// Create smooth color transition using tween
var startColor = game.backgroundColor;
var endColor = skyColors[newColorIndex];
// Animate background color change
var colorTransition = {
r: startColor >> 16 & 0xFF,
g: startColor >> 8 & 0xFF,
b: startColor & 0xFF
};
var targetColor = {
r: endColor >> 16 & 0xFF,
g: endColor >> 8 & 0xFF,
b: endColor & 0xFF
};
tween(colorTransition, targetColor, {
duration: 2000,
easing: tween.easeInOut,
onUpdate: function onUpdate() {
var r = Math.round(colorTransition.r);
var g = Math.round(colorTransition.g);
var b = Math.round(colorTransition.b);
var newColor = r << 16 | g << 8 | b;
game.setBackgroundColor(newColor);
},
onFinish: function onFinish() {
skyTransitionActive = false;
game.setBackgroundColor(endColor);
}
});
}
function getRandomSkyColor() {
var randomIndex;
do {
randomIndex = Math.floor(Math.random() * skyColors.length);
} while (randomIndex === currentSkyColorIndex);
return randomIndex;
}
function cycleSkyColor() {
var nextIndex = (currentSkyColorIndex + 1) % skyColors.length;
changeSkyColor(nextIndex);
}
function startSkyCycling() {
if (skyCyclingActive) {
// Stop cycling if already active
stopSkyCycling();
return;
}
skyCyclingActive = true;
// Change sky color every 2 seconds
function cycleNext() {
if (skyCyclingActive) {
var nextIndex = (currentSkyColorIndex + 1) % skyColors.length;
changeSkyColor(nextIndex);
skyCyclingTimer = LK.setTimeout(cycleNext, 3000); // 3 seconds between changes
}
}
// Start first cycle
skyCyclingTimer = LK.setTimeout(cycleNext, 1000); // 1 second delay before first change
}
function stopSkyCycling() {
skyCyclingActive = false;
if (skyCyclingTimer) {
LK.clearTimeout(skyCyclingTimer);
skyCyclingTimer = null;
}
}
function showPowerMenu() {
if (isPowerMenuOpen || powerMenuOpened) {
return;
}
powerMenuOpened = true;
isPowerMenuOpen = true;
powerMenuOverlay = LK.gui.center.addChild(new PowerMenuOverlay());
// Animate menu appearing
powerMenuOverlay.alpha = 0;
powerMenuOverlay.scaleX = 0.8;
powerMenuOverlay.scaleY = 0.8;
tween(powerMenuOverlay, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
}
function hidePowerMenu() {
if (!isPowerMenuOpen || !powerMenuOverlay) {
return;
}
tween(powerMenuOverlay, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (powerMenuOverlay) {
powerMenuOverlay.destroy();
powerMenuOverlay = null;
}
isPowerMenuOpen = false;
}
});
}
function activateSuperJumpMode() {
// Give player super jump for 10 seconds
player.jumpPower = player.powerUpJumpPower * 1.5; // Even stronger than normal power-up
player.powerUpActive = true;
player.powerUpTimer = 600; // 10 seconds at 60fps
// Flash player golden to show super jump mode
LK.effects.flashObject(player, 0xFFD700, 500);
// Create special golden boots visual effect
if (player.boots) {
player.removeChild(player.boots);
}
player.boots = LK.getAsset('boots', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0,
tint: 0xFFD700
});
player.addChild(player.boots);
player.boots.x = 0;
player.boots.y = 0;
// Animate boots appearing
tween(player.boots, {
alpha: 1.0,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 300,
easing: tween.easeOut
});
}
function activateSlowFallMode() {
// Give player slow fall for 10 seconds
player.gravity = player.slowFallGravity * 0.5; // Even slower than normal slow fall
player.slowFallActive = true;
player.slowFallTimer = 600; // 10 seconds at 60fps
// Flash player blue to show slow fall mode
LK.effects.flashObject(player, 0x3498db, 500);
// Create special enhanced parachute
if (player.parachute) {
player.removeChild(player.parachute);
}
player.parachute = LK.getAsset('parachute', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0,
tint: 0x3498db
});
player.addChild(player.parachute);
player.parachute.x = 0;
player.parachute.y = -200;
// Animate parachute appearing
tween(player.parachute, {
alpha: 0.9,
y: -180,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 500,
easing: tween.easeOut
});
}
function showMenu() {
if (isMenuOpen) {
return;
}
isMenuOpen = true;
menuOverlay = LK.gui.center.addChild(new MenuOverlay());
// Animate menu appearing
menuOverlay.alpha = 0;
menuOverlay.scaleX = 0.8;
menuOverlay.scaleY = 0.8;
tween(menuOverlay, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
}
function hideMenu() {
if (!isMenuOpen || !menuOverlay) {
return;
}
// Stop sky cycling when menu closes
stopSkyCycling();
tween(menuOverlay, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
if (menuOverlay) {
menuOverlay.destroy();
menuOverlay = null;
}
isMenuOpen = false;
}
});
}
var player = game.addChild(new Player());
player.x = 400; // Platform 1 x position
player.y = 2350; // Just above platform 1
var platforms = [];
var powerUps = [];
var slowFallPowerUps = [];
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1.0,
scaleY: 1.7 // Extend ground 70% more downward
}));
ground.x = 1024;
ground.y = 2732;
// Create platforms with numbers 1-15
var platformData = [{
x: 400,
y: 2400,
width: 200,
number: 1
}, {
x: 800,
y: 2200,
width: 250,
number: 2
}, {
x: 1200,
y: 2000,
width: 200,
number: 3
}, {
x: 600,
y: 1800,
width: 300,
number: 4
}, {
x: 1400,
y: 1600,
width: 200,
number: 5
}, {
x: 300,
y: 1400,
width: 250,
number: 6
}, {
x: 1000,
y: 1200,
width: 300,
number: 7
}, {
x: 1600,
y: 1000,
width: 200,
number: 8
}, {
x: 400,
y: 800,
width: 250,
number: 9
}, {
x: 1200,
y: 600,
width: 200,
number: 10
}, {
x: 800,
y: 400,
width: 300,
number: 11
}, {
x: 500,
y: 200,
width: 180,
number: 12
}, {
x: 1400,
y: 100,
width: 220,
number: 13
}, {
x: 200,
y: -100,
width: 250,
number: 14
}, {
x: 1000,
y: -300,
width: 200,
number: 15
}];
function createLevel(levelNumber) {
// Clear existing platforms
for (var i = platforms.length - 1; i >= 0; i--) {
platforms[i].destroy();
}
platforms = [];
// Clear existing power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].destroy();
}
powerUps = [];
// Clear existing slow fall power-ups
for (var i = slowFallPowerUps.length - 1; i >= 0; i--) {
slowFallPowerUps[i].destroy();
}
slowFallPowerUps = [];
// Enhanced difficulty scaling for levels after 5
var isHardMode = levelNumber > 5;
var difficultyMultiplier = isHardMode ? levelNumber - 5 : 0;
// Platform sizing - much smaller after level 5
var basePlatformWidth = isHardMode ? Math.max(120, 200 - difficultyMultiplier * 15) : Math.max(150, 250 - (levelNumber - 1) * 10);
var platformHeight = isHardMode ? Math.max(25, 40 - difficultyMultiplier * 2) : 40;
// Vertical spacing - increased gaps after level 5
var baseY = 2400;
var yStep = isHardMode ? Math.min(280, 200 + difficultyMultiplier * 15) : 200;
// Generate new platform layout for each level
var _loop = function _loop() {
platformNumber = i + 1;
// Calculate platform width with additional randomness for hard mode
var platformWidth = basePlatformWidth;
if (isHardMode && platformNumber > 1 && platformNumber < 15) {
// Add random variation to platform sizes (±20 pixels)
platformWidth += (Math.random() - 0.5) * 40;
platformWidth = Math.max(100, Math.min(platformWidth, 200)); // Clamp between 100-200
}
platform = game.addChild(new Platform(platformWidth, platformHeight, platformNumber));
// Positioning logic - more challenging after level 5
var minX, maxX, randomX;
if (isHardMode) {
// Hard mode: More precise positioning requirements
minX = 150 + platformWidth / 2;
maxX = 1898 - platformWidth / 2;
// Create more challenging horizontal gaps between platforms
if (i > 0) {
var lastPlatform = platforms[platforms.length - 1];
var minGap = 200 + difficultyMultiplier * 20; // Minimum gap increases with difficulty
var maxGap = 400 + difficultyMultiplier * 30; // Maximum gap increases with difficulty
// Try to place platform at challenging but reachable distance
var preferredDistance = minGap + Math.random() * (maxGap - minGap);
var direction = Math.random() > 0.5 ? 1 : -1; // Random direction
randomX = lastPlatform.x + direction * preferredDistance;
randomX = Math.max(minX, Math.min(maxX, randomX)); // Keep within bounds
} else {
randomX = minX + Math.random() * (maxX - minX);
}
} else {
// Normal mode: Original positioning
minX = 200;
maxX = 1848;
randomX = minX + Math.random() * (maxX - minX);
}
platform.x = randomX;
platform.y = baseY - i * yStep;
platforms.push(platform);
// Make the last platform (platform 15) shine with golden glow
if (platformNumber === 15) {
// Golden color
// Create pulsing glow effect
var _createPulsingGlow = function createPulsingGlow() {
tween(platform.children[0], {
alpha: 0.6,
scaleX: platform.children[0].scaleX * 1.1,
scaleY: platform.children[0].scaleY * 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(platform.children[0], {
alpha: 1.0,
scaleX: platform.children[0].scaleX / 1.1,
scaleY: platform.children[0].scaleY / 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: _createPulsingGlow // Loop the animation
});
}
});
}; // Start the pulsing animation with a delay to make it more noticeable
// Add sparkling effect with tint changes
var createSparkleEffect = function createSparkleEffect() {
var sparkleColors = [0xFFD700, 0xFFF700, 0xFFFF00, 0xFFD700]; // Golden to bright yellow
var currentColorIndex = 0;
function nextSparkle() {
currentColorIndex = (currentColorIndex + 1) % sparkleColors.length;
tween(platform.children[0], {
tint: sparkleColors[currentColorIndex]
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(nextSparkle, Math.random() * 800 + 400); // Random delay between sparkles
}
});
}
nextSparkle();
}; // Start sparkling effect
// Add golden tint to make it special
platform.children[0].tint = 0xFFD700;
LK.setTimeout(function () {
_createPulsingGlow();
}, 500);
LK.setTimeout(function () {
createSparkleEffect();
}, 1000);
}
// Spawn power-up randomly - reduced chance in hard mode
var powerUpChance = isHardMode ? Math.max(0.02, 0.07 - difficultyMultiplier * 0.01) : 0.07;
if (Math.random() < powerUpChance && platformNumber !== 1 && platformNumber !== 15) {
powerUp = game.addChild(new PowerUp());
powerUp.x = platform.x;
powerUp.y = platform.y - 60; // Position above platform
powerUps.push(powerUp);
}
// Spawn slow fall power-up randomly - reduced chance in hard mode
var slowFallChance = isHardMode ? Math.max(0.02, 0.07 - difficultyMultiplier * 0.01) : 0.07;
if (Math.random() < slowFallChance && platformNumber !== 1 && platformNumber !== 15) {
slowFallPowerUp = game.addChild(new SlowFallPowerUp());
slowFallPowerUp.x = platform.x + 50; // Offset slightly to avoid overlap
slowFallPowerUp.y = platform.y - 60; // Position above platform
slowFallPowerUps.push(slowFallPowerUp);
}
},
platformNumber,
platform,
minX,
maxX,
randomX,
powerUp,
slowFallPowerUp;
for (var i = 0; i < 15; i++) {
_loop();
}
}
// Apply difficulty modifiers to player stats for hard mode
function applyDifficultyModifiers(levelNumber) {
var isHardMode = levelNumber > 5;
if (isHardMode) {
var difficultyMultiplier = levelNumber - 5;
// Increase gravity slightly (making falls faster and jumps shorter)
player.baseGravity = Math.min(1.2, 0.8 + difficultyMultiplier * 0.05);
player.gravity = player.slowFallActive ? player.slowFallGravity : player.baseGravity;
// Reduce jump power slightly (making precise jumping harder)
player.baseJumpPower = Math.max(25, 30 - difficultyMultiplier * 0.8);
player.powerUpJumpPower = Math.max(38, 45 - difficultyMultiplier * 1.0);
player.jumpPower = player.powerUpActive ? player.powerUpJumpPower : player.baseJumpPower;
// Reduce movement speed slightly for more precise control requirements
player.speed = Math.max(8, 12 - difficultyMultiplier * 0.5);
player.runSpeed = Math.max(14, 20 - difficultyMultiplier * 0.8);
} else {
// Reset to normal values for easier levels
player.baseGravity = 0.8;
player.gravity = player.slowFallActive ? player.slowFallGravity : player.baseGravity;
player.baseJumpPower = 30;
player.powerUpJumpPower = 45;
player.jumpPower = player.powerUpActive ? player.powerUpJumpPower : player.baseJumpPower;
player.speed = 12;
player.runSpeed = 20;
}
}
// Create initial level
createLevel(currentLevel);
applyDifficultyModifiers(currentLevel);
// Control buttons
var leftButton = LK.gui.bottomLeft.addChild(new ControlButton('left'));
leftButton.x = 110;
leftButton.y = -110;
var rightButton = LK.gui.bottomLeft.addChild(new ControlButton('right'));
rightButton.x = 310;
rightButton.y = -110;
var runButton = LK.gui.bottomLeft.addChild(new ControlButton('run'));
runButton.x = 510;
runButton.y = -110;
var jumpButton = LK.gui.bottomRight.addChild(new ControlButton('jump'));
jumpButton.x = -110;
jumpButton.y = -110;
// Control button labels
var leftLabel = new Text2('←', {
size: 60,
fill: 0xFFFFFF
});
leftLabel.anchor.set(0.5, 0.5);
leftButton.addChild(leftLabel);
var rightLabel = new Text2('→', {
size: 60,
fill: 0xFFFFFF
});
rightLabel.anchor.set(0.5, 0.5);
rightButton.addChild(rightLabel);
var runLabel = new Text2('RUN', {
size: 30,
fill: 0xFFFFFF
});
runLabel.anchor.set(0.5, 0.5);
runButton.addChild(runLabel);
var jumpLabel = new Text2('↑', {
size: 60,
fill: 0xFFFFFF
});
jumpLabel.anchor.set(0.5, 0.5);
jumpButton.addChild(jumpLabel);
// Menu button in top-right corner
var menuButton = LK.gui.topRight.addChild(new MenuButton());
menuButton.x = -120; // Position away from right edge
menuButton.y = 120; // Position below top menu area
// Power menu button
var powerMenuButton = LK.gui.bottomRight.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5
}));
powerMenuButton.x = -220;
powerMenuButton.y = -220;
powerMenuButton.interactive = true;
// Add power icon (lightning bolt)
var powerIcon = new Text2('⚡', {
size: 40,
fill: 0xFFD700
});
powerIcon.anchor.set(0.5, 0.5);
powerMenuButton.addChild(powerIcon);
powerMenuButton.down = function () {
tween(powerMenuButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
powerMenuButton.up = function () {
tween(powerMenuButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
showPowerMenu();
}
});
};
// Level display
var levelText = new Text2('Level ' + currentLevel, {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 120; // Position below the top menu
// Power-up status display
var powerUpText = new Text2('', {
size: 40,
fill: 0xf39c12
});
powerUpText.anchor.set(0.5, 0);
LK.gui.top.addChild(powerUpText);
powerUpText.y = 200;
// Slow fall status display
var slowFallText = new Text2('', {
size: 40,
fill: 0x3498db
});
slowFallText.anchor.set(0.5, 0);
LK.gui.top.addChild(slowFallText);
slowFallText.y = 250;
// Points display
var pointsText = new Text2('Points: 0', {
size: 50,
fill: 0xFFFFFF
});
pointsText.anchor.set(0.5, 0);
LK.gui.top.addChild(pointsText);
pointsText.y = 300;
// High score display
var highScoreText = new Text2('Best: ' + highScore, {
size: 35,
fill: 0xf39c12
});
highScoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(highScoreText);
highScoreText.y = 360;
function checkCollisions() {
var playerBottom = player.y;
var playerTop = player.y - 180;
var playerLeft = player.x - 90;
var playerRight = player.x + 90;
// Check ground collision
if (playerBottom >= ground.y - 50) {
if (player.velocityY > 0) {
player.y = ground.y - 50;
player.velocityY = 0;
player.onGround = true;
}
}
// Check platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformLeft = platform.x - platform.platformWidth / 2;
var platformRight = platform.x + platform.platformWidth / 2;
var platformTop = platform.y - platform.platformHeight / 2;
var platformBottom = platform.y + platform.platformHeight / 2;
// Check if player is horizontally aligned with platform
if (playerRight > platformLeft && playerLeft < platformRight) {
// Check if player is falling onto platform from above
if (player.velocityY > 0 && playerBottom >= platformTop && playerTop < platformTop) {
player.y = platformTop;
player.velocityY = 0;
player.onGround = true;
}
}
}
// Check power-up collisions
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (!powerUp.collected) {
var powerUpLeft = powerUp.x - 20;
var powerUpRight = powerUp.x + 20;
var powerUpTop = powerUp.y - 20;
var powerUpBottom = powerUp.y + 20;
// Check if player intersects with power-up
if (playerRight > powerUpLeft && playerLeft < powerUpRight && playerBottom > powerUpTop && playerTop < powerUpBottom) {
powerUp.collected = true;
player.collectPowerUp();
// Add 10 points for collecting power-up
gamePoints += 10;
pointsText.setText('Points: ' + gamePoints);
// Check for new high score
if (gamePoints > highScore) {
highScore = gamePoints;
storage.highScore = highScore;
highScoreText.setText('Best: ' + highScore);
// Flash screen gold for new high score
LK.effects.flashScreen(0xFFD700, 300);
}
powerUp.destroy();
powerUps.splice(i, 1);
}
}
}
// Check slow fall power-up collisions
for (var i = slowFallPowerUps.length - 1; i >= 0; i--) {
var slowFallPowerUp = slowFallPowerUps[i];
if (!slowFallPowerUp.collected) {
var slowFallLeft = slowFallPowerUp.x - 20;
var slowFallRight = slowFallPowerUp.x + 20;
var slowFallTop = slowFallPowerUp.y - 20;
var slowFallBottom = slowFallPowerUp.y + 20;
// Check if player intersects with slow fall power-up (slime)
if (playerRight > slowFallLeft && playerLeft < slowFallRight && playerBottom > slowFallTop && playerTop < slowFallBottom) {
slowFallPowerUp.collected = true;
// Play slime sound effect
LK.getSound('Voz').play();
// Player character sound and animation when touching slime
// Create bouncy squash animation for player
tween(player.children[0], {
scaleX: 1.4,
scaleY: 0.7,
rotation: Math.random() * 0.3 - 0.15
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player.children[0], {
scaleX: 0.9,
scaleY: 1.3,
rotation: Math.random() * 0.2 - 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player.children[0], {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 180,
easing: tween.easeOut
});
}
});
}
});
// Create slime bounce animation
tween(slowFallPowerUp.children[0], {
scaleX: 1.5,
scaleY: 0.8,
rotation: Math.random() * 0.4 - 0.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slowFallPowerUp.children[0], {
scaleX: 0.8,
scaleY: 1.4,
rotation: Math.random() * 0.3 - 0.15
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slowFallPowerUp.children[0], {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0,
alpha: 0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
// Add jiggle animation to the feather text
tween(slowFallPowerUp.children[1], {
scaleX: 1.3,
scaleY: 1.3,
rotation: Math.random() * 0.5 - 0.25
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slowFallPowerUp.children[1], {
scaleX: 0.9,
scaleY: 0.9,
rotation: Math.random() * 0.3 - 0.15
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(slowFallPowerUp.children[1], {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0,
alpha: 0
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
}
});
player.collectSlowFallPowerUp();
// Add 10 points for collecting slow fall power-up
gamePoints += 10;
pointsText.setText('Points: ' + gamePoints);
// Check for new high score
if (gamePoints > highScore) {
highScore = gamePoints;
storage.highScore = highScore;
highScoreText.setText('Best: ' + highScore);
// Flash screen gold for new high score
LK.effects.flashScreen(0xFFD700, 300);
}
// Destroy slime after animation completes
LK.setTimeout(function () {
slowFallPowerUp.destroy();
slowFallPowerUps.splice(slowFallPowerUps.indexOf(slowFallPowerUp), 1);
}, 500);
}
}
}
}
game.update = function () {
// Check collisions first to set onGround flag
checkCollisions();
// Handle input
player.setRunning(runButton.isPressed);
if (leftButton.isPressed) {
player.moveLeft();
} else if (rightButton.isPressed) {
player.moveRight();
} else {
player.stopHorizontalMovement();
}
if (jumpButton.isPressed) {
player.jump();
}
// Update power-up display
if (player.powerUpActive) {
var secondsLeft = Math.ceil(player.powerUpTimer / 60);
powerUpText.setText('★ Super Jump: ' + secondsLeft + 's');
} else {
powerUpText.setText('');
}
// Update slow fall display
if (player.slowFallActive) {
var secondsLeft = Math.ceil(player.slowFallTimer / 60);
slowFallText.setText('🪶 Slow Fall: ' + secondsLeft + 's');
} else {
slowFallText.setText('');
}
// Camera follows player
var targetY = -player.y + 1366; // Center player vertically on screen
game.y = targetY;
// Check if player reached platform 15
var platform15 = null;
for (var i = 0; i < platforms.length; i++) {
if (platforms[i].platformNumber === 15) {
platform15 = platforms[i];
break;
}
}
if (platform15) {
var playerBottom = player.y;
var playerLeft = player.x - 90;
var playerRight = player.x + 90;
var platform15Left = platform15.x - platform15.platformWidth / 2;
var platform15Right = platform15.x + platform15.platformWidth / 2;
var platform15Top = platform15.y - platform15.platformHeight / 2;
// Check if player is on platform 15
if (playerRight > platform15Left && playerLeft < platform15Right && playerBottom >= platform15Top && playerBottom <= platform15Top + 50) {
// Player reached platform 15 - advance to next level
// Add 20 points for completing a level
gamePoints += 20;
pointsText.setText('Points: ' + gamePoints);
// Check for new high score
if (gamePoints > highScore) {
highScore = gamePoints;
storage.highScore = highScore;
highScoreText.setText('Best: ' + highScore);
// Flash screen gold for new high score
LK.effects.flashScreen(0xFFD700, 300);
}
currentLevel++;
if (currentLevel > 10) {
// Update final score before showing you win
LK.setScore(gamePoints);
// After 10 levels, show you win
LK.showYouWin();
} else {
// Reset power usage flags for new level
superJumpUsed = false;
slowFallModeUsed = false;
// Create next level
createLevel(currentLevel);
applyDifficultyModifiers(currentLevel);
levelText.setText('Level ' + currentLevel);
// Reset player position for new level
player.x = 400; // Platform 1 x position
player.y = 2350; // Just above platform 1
player.velocityX = 0;
player.velocityY = 0;
// Change sky color every few levels for visual variety
if (currentLevel % 3 === 0) {
var randomSkyIndex = getRandomSkyColor();
changeSkyColor(randomSkyIndex);
}
// Flash screen green to indicate level completion
LK.effects.flashScreen(0x00ff00, 500);
}
}
}
// Check if player fell off screen
if (player.y > 2800) {
// Set final score and show game over
LK.setScore(gamePoints);
LK.showGameOver();
}
};
// Play background music with saved volume
if (musicVolume > 0) {
LK.playMusic('Musica', {
fade: {
start: 0,
end: musicVolume,
duration: 500
}
});
}
Poder de saltó. In-Game asset. 2d. High contrast. No shadows
Slow fall. In-Game asset. 2d. High contrast. No shadows
Paracaídas. In-Game asset. 2d. High contrast. No shadows
Flecha hacia la derecha. In-Game asset. 2d. High contrast. No shadows
Botas de super salto. In-Game asset. 2d. High contrast. No shadows
Cubo de slime con cara feliz. In-Game asset. 2d. High contrast. No shadows