/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Coin = Container.expand(function () { var self = Container.call(this); self.frames = [self.attachAsset('coinFrame1', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }), self.attachAsset('coinFrame2', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame3', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame4', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame5', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame6', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame7', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('coinFrame8', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })]; self.currentFrame = 0; self.speed = 10; self.collected = false; self.animationSpeed = 4; self.reset = function (x, y) { self.x = x; self.y = y; self.collected = false; self.alpha = 1; self.currentFrame = 0; for (var i = 0; i < self.frames.length; i++) { self.frames[i].alpha = i === 0 ? 1 : 0; } self.animationTimer = 0; }; self.startAnimation = function () { self.animationTimer = 0; }; self.animate = function () { self.frames[self.currentFrame].alpha = 0; self.currentFrame = (self.currentFrame + 1) % self.frames.length; self.frames[self.currentFrame].alpha = 1; }; self.getBounds = function () { return { left: self.x - 40, right: self.x + 40, top: self.y - 40, bottom: self.y + 40 }; }; self.update = function () { self.animationTimer += 1; if (self.animationTimer >= 6) { self.animate(); self.animationTimer = 0; } if ((!player || !player.isHit && lives >= 0) && !gamePaused) { self.x -= self.speed * globalSpeed; } if (self.x < -100) { var coinIndex = coinManager.coins.indexOf(self); if (coinIndex > -1) { coinManager.coins.splice(coinIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; coinManager.coinPool.push(self); } if (!self.collected && player && player.getBounds && player.canJump && !gamePaused) { var coinBounds = self.getBounds(); var playerBounds = player.getBounds(); if (playerBounds.left < coinBounds.right && playerBounds.right > coinBounds.left && playerBounds.top < coinBounds.bottom && playerBounds.bottom > coinBounds.top) { self.collected = true; LK.getSound('coin').play(); LK.setScore(LK.getScore() + 10); if (scoreText) { scoreText.setText(LK.getScore()); } if (coinCounter) { coinCount++; coinCounter.updateCount(coinCount); } tween(self, { y: self.y - 100, alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { var coinIndex = coinManager.coins.indexOf(self); if (coinIndex > -1) { coinManager.coins.splice(coinIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; coinManager.coinPool.push(self); } }); } } }; self.startAnimation(); return self; }); var CoinCounter = Container.expand(function () { var self = Container.call(this); var coinIcon = self.attachAsset('coinFrame1', { anchorX: 0.5, anchorY: 0.5, x: 220, y: 50, width: 96, height: 96 }); self.hundreds = new Text2('0', { size: 100, fill: 0xFFFFFF }); self.hundreds.anchor.set(0.5); self.hundreds.x = 0; self.hundreds.y = 50; self.addChild(self.hundreds); self.tens = new Text2('0', { size: 100, fill: 0xFFFFFF }); self.tens.anchor.set(0.5); self.tens.x = 60; self.tens.y = 50; self.addChild(self.tens); self.units = new Text2('0', { size: 100, fill: 0xFFFFFF }); self.units.anchor.set(0.5); self.units.x = 120; self.units.y = 50; self.addChild(self.units); self.updateCount = function (count) { count = Math.min(999, Math.max(0, count)); var h = Math.floor(count / 100); var t = Math.floor(count % 100 / 10); var u = count % 10; self.hundreds.setText(h.toString()); self.tens.setText(t.toString()); self.units.setText(u.toString()); }; self.updateCount(0); return self; }); var CoinManager = Container.expand(function () { var self = Container.call(this); self.coins = []; self.coinPool = []; self.spawnInterval = Math.floor(Math.random() * 100) + 50; self.spawnCounter = 0; self.init = function () { self.coins = []; self.coinPool = []; self.spawnInterval = Math.floor(Math.random() * 100) + 50; self.spawnCounter = 0; }; self.resetCoins = function () { for (var i = self.coins.length - 1; i >= 0; i--) { if (self.coins[i].parent) { self.coins[i].parent.removeChild(self.coins[i]); } self.coins[i].visible = false; self.coinPool.push(self.coins[i]); } self.coins = []; self.spawnCounter = 0; }; self.update = function () { if (player && player.isHit || lives < 0 || gamePaused) { return; } // Spawn logic self.spawnCounter++; if (self.coins.length < 10 && self.spawnCounter >= self.spawnInterval) { self.spawnCoin(); self.spawnCounter = 0; } }; self.spawnCoin = function () { var coin; if (self.coinPool.length > 0) { coin = self.coinPool.pop(); coin.visible = true; } else { coin = new Coin(); } coin.x = 2500; var randomHeight = Math.random(); if (randomHeight < 0.33) { coin.y = groundLevel - 100; } else if (randomHeight < 0.66) { coin.y = level1Height - 100; } else { coin.y = level2Height - 100; } if (self.coinPool.indexOf(coin) > -1) { coin.reset(coin.x, coin.y); } self.coins.push(coin); if (!coin.parent) { middlegroundContainer.addChild(coin); } self.spawnInterval = Math.floor(Math.random() * 200) + 100; self.spawnCounter = 0; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.startAnimation = function () { tween(self, { scaleX: 1.15 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 0.9 }, { duration: 200, easing: tween.easeInOut, onFinish: self.startAnimation }); } }); }; self.speed = 15; self.velocityY = 0; self.gravity = 0.7; self.currentPlatform = null; self.reset = function (x, y) { self.x = x; self.y = y; self.velocityY = 0; self.currentPlatform = null; self.passed = false; self.startAnimation(); }; self.update = function () { if (player && player.isHit || lives < 0 || gamePaused) { return; } // Check for water hole collisions and reverse direction if (waterHoleManager && waterHoleManager.waterHoles) { var enemyBounds = self.getBounds(); for (var i = 0; i < waterHoleManager.waterHoles.length; i++) { var waterHole = waterHoleManager.waterHoles[i]; var holeX = waterHole.x; var holeWidth = waterHole.boundingBox.width; // If enemy is close to water hole border, reverse direction if (Math.abs(enemyBounds.right - (holeX - holeWidth / 2)) < 20 || Math.abs(enemyBounds.left - (holeX + holeWidth / 2)) < 20) { self.speed = -self.speed; // Reverse direction break; } } } self.x -= self.speed * globalSpeed; self.x -= self.speed < 0 ? 10 * globalSpeed : 0; if (self.currentPlatform) { var enemyBounds = self.getBounds(); var platformBounds = { left: self.currentPlatform.x - 500, right: self.currentPlatform.x + 500 }; if (enemyBounds.left > platformBounds.right || enemyBounds.right < platformBounds.left) { self.currentPlatform = null; } } if (!self.currentPlatform) { self.velocityY += self.gravity * globalSpeed; self.y += self.velocityY * globalSpeed; } var enemyVisualBottomOffset = 75; if (self.y >= groundLevel - enemyVisualBottomOffset) { self.y = groundLevel - enemyVisualBottomOffset; self.velocityY = 0; self.currentPlatform = null; } if (self.velocityY > 0) { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var enemyBounds = self.getBounds(); var platformBounds = { left: platform.x - 500, right: platform.x + 500, top: platform.y - 50, bottom: platform.y + 50 }; if (enemyBounds.bottom >= platformBounds.top && enemyBounds.bottom - self.velocityY < platformBounds.top && enemyBounds.right > platformBounds.left && enemyBounds.left < platformBounds.right) { self.y = platform.y - 75; self.velocityY = 0; self.currentPlatform = platform; break; } } } if (self.x < -50) { if (self.parent) { self.parent.removeChild(self); } var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } self.visible = false; enemyPool.push(self); } }; self.getBounds = function () { return { left: self.x - 50, right: self.x + 50, top: self.y - 50, bottom: self.y + 50 }; }; self.startAnimation(); return self; }); var LivesCounter = Container.expand(function () { var self = Container.call(this); self.hearts = []; var maxHearts = 3; for (var i = 0; i < maxHearts; i++) { var heart = self.attachAsset('playerRunFrame2', { anchorX: 0.5, anchorY: 0.5, x: i * 70, y: 0, width: 60, height: 60 }); self.hearts.push(heart); } self.updateLives = function (livesCount) { livesCount = Math.min(maxHearts, Math.max(0, livesCount)); for (var i = 0; i < maxHearts; i++) { self.hearts[i].visible = i < livesCount; } }; self.updateLives(3); return self; }); var Mushroom = Container.expand(function () { var self = Container.call(this); var mushroomGraphics = self.attachAsset('mushroom', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.collected = false; self.reset = function (x, y) { self.x = x; self.y = y; self.collected = false; self.alpha = 1; }; self.getBounds = function () { return { left: self.x - 50, right: self.x + 50, top: self.y - 45, bottom: self.y + 45 }; }; self.update = function () { if ((!player || !player.isHit && lives >= 0) && !gamePaused) { self.x -= self.speed * globalSpeed; } if (self.x < -100) { var mushroomIndex = mushroomManager.mushrooms.indexOf(self); if (mushroomIndex > -1) { mushroomManager.mushrooms.splice(mushroomIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; mushroomManager.mushroomPool.push(self); } if (!self.collected && player && player.getBounds && player.canJump && !gamePaused) { var mushroomBounds = self.getBounds(); var playerBounds = player.getBounds(); if (playerBounds.left < mushroomBounds.right && playerBounds.right > mushroomBounds.left && playerBounds.top < mushroomBounds.bottom && playerBounds.bottom > mushroomBounds.top) { self.collected = true; if (player.morphState === 0) { LK.getSound('mushroomEat').play(); player.morphState = 1; player.updateRefScale(); } LK.setScore(LK.getScore() + 100); if (scoreText) { scoreText.setText(LK.getScore()); } tween(self, { y: self.y - 100, alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { var mushroomIndex = mushroomManager.mushrooms.indexOf(self); if (mushroomIndex > -1) { mushroomManager.mushrooms.splice(mushroomIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; mushroomManager.mushroomPool.push(self); } }); } } }; return self; }); var MushroomManager = Container.expand(function () { var self = Container.call(this); self.mushrooms = []; self.mushroomPool = []; self.spawnInterval = Math.floor(Math.random() * 500) + 500; self.spawnCounter = 0; self.init = function () { self.mushrooms = []; self.mushroomPool = []; self.spawnInterval = Math.floor(Math.random() * 500) + 500; self.spawnCounter = 0; }; self.update = function () { if (player && player.isHit || lives < 0 || gamePaused) { return; } // Spawn logic self.spawnCounter++; if (self.mushrooms.length < 2 && self.spawnCounter >= self.spawnInterval) { self.spawnMushroom(); self.spawnCounter = 0; } }; self.spawnMushroom = function () { var mushroom; if (self.mushroomPool.length > 0) { mushroom = self.mushroomPool.pop(); mushroom.visible = true; } else { mushroom = new Mushroom(); } mushroom.x = 2500; // Only spawn on platforms instead of random heights var availablePlatforms = []; for (var p = 0; p < platforms.length; p++) { if (platforms[p].x > 2048 && platforms[p].x < 2800) { availablePlatforms.push(platforms[p]); } } // If we have platforms in the spawn zone, put mushroom on one of them if (availablePlatforms.length > 0) { var randomPlatform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; mushroom.x = randomPlatform.x; // Place at center of platform mushroom.y = randomPlatform.y - 100; // Adjust height to be above platform } else { // Fallback if no platforms are in the spawn zone mushroom.x = 2500; mushroom.y = groundLevel - 100; } if (self.mushroomPool.indexOf(mushroom) > -1) { mushroom.reset(mushroom.x, mushroom.y); } self.mushrooms.push(mushroom); if (!mushroom.parent) { middlegroundContainer.addChild(mushroom); } self.spawnInterval = Math.floor(Math.random() * 500) + 500; self.spawnCounter = 0; }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.passed = false; self.update = function () { if (player && player.isHit || lives < 0 || gamePaused) { return; } self.x -= self.speed * globalSpeed; if (self.x < -500) { if (self.parent) { self.parent.removeChild(self); } var index = platforms.indexOf(self); if (index > -1) { platforms.splice(index, 1); } self.visible = false; platformPool.push(self); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); self.morphState = 0; self.refScaleX = 0.5; self.refScaleY = 0.5; self.resetRun = function () { console.log("Reset run..."); for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].parent) { enemies[i].parent.removeChild(enemies[i]); } enemies[i].visible = false; enemyPool.push(enemies[i]); } enemies = []; // Reset coins using the manager's resetCoins method if (coinManager) { coinManager.resetCoins(); } // Reset mushrooms using the manager if (mushroomManager) { for (var i = mushroomManager.mushrooms.length - 1; i >= 0; i--) { var mushroom = mushroomManager.mushrooms[i]; if (mushroom.parent) { mushroom.parent.removeChild(mushroom); } mushroom.visible = false; mushroomManager.mushroomPool.push(mushroom); } mushroomManager.mushrooms = []; mushroomManager.spawnCounter = 0; } if (waterHoleManager && waterHoleManager.waterHoles) { for (var i = waterHoleManager.waterHoles.length - 1; i >= 0; i--) { var waterHole = waterHoleManager.waterHoles[i]; if (waterHole.parent) { waterHole.parent.removeChild(waterHole); } waterHole.visible = false; waterHoleManager.waterHolePool.push(waterHole); } waterHoleManager.waterHoles = []; waterHoleManager.spawnCounter = 0; } // Reset portals if (portalManager && portalManager.portals) { for (var i = portalManager.portals.length - 1; i >= 0; i--) { var portal = portalManager.portals[i]; if (portal.parent) { portal.parent.removeChild(portal); } portal.visible = false; portalManager.portalPool.push(portal); } portalManager.portals = []; portalManager.spawnCounter = 0; } LK.effects.flashScreen(0xFFFFFF, 600); self.x = 2048 / 6; self.y = groundLevel - 100; self.velocityY = 0; self.isJumping = false; self.currentPlatform = null; self.shadow.alpha = 0.5; console.log("RESET FRAMES!"); self.isDrownAnimPlaying = false; for (var i = 0; i < self.dieFrames.length; i++) { self.dieFrames[i].alpha = 0; } self.morphState = 0; self.scale.x = 0.5; self.scale.y = 0.5; self.updateRefScale(); self.runFrames[self.currentRunFrame].alpha = 1; gamePaused = false; }; self.init = function () { self.updateRefScale(); }; self.updateRefScale = function () { var oldScaleY = self.refScaleY; var visualBottomOffset = self.playerHeight * oldScaleY / 2; if (self.morphState === 0) { self.refScaleX = 0.5; self.refScaleY = 0.5; } else { self.refScaleX = 1.0; self.refScaleY = 1.0; } var newVisualBottomOffset = self.playerHeight * self.refScaleY / 2; if (!self.isJumping) { if (self.currentPlatform) { self.y = self.currentPlatform.y - newVisualBottomOffset; } else { self.y = groundLevel - newVisualBottomOffset; } } tween(self.scale, { x: self.refScaleX, y: self.refScaleY }, { duration: 1000, easing: tween.easeOut }); }; self.shadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, scaleX: 2.0, scaleY: 0.4, tint: 0x000000, y: 200 }); self.runFrames = [self.attachAsset('playerRunFrame1', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }), self.attachAsset('playerRunFrame2', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('playerRunFrame', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })]; self.currentRunFrame = 0; self.speed = 5; self.jumpHeight = 35; self.isJumping = false; self.velocityY = 0; self.isFalling = false; self.currentPlatform = null; self.playerHeight = 400; self.canJump = false; self.isHit = false; self.isDying = false; self.boundingBox = self.attachAsset('boundingBox', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 380, alpha: isDebug ? 0.5 : 0 }); self.hitFrame = self.attachAsset('playerHitFrame1', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.jumpFrame = self.attachAsset('playerJumpFrame', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.getBounds = function () { return { left: self.x - 75, right: self.x + 75, top: self.y - 100, bottom: self.y + 100 }; }; self.update = function () { if (self.isHit || lives < 0) { return; } if (self.isJumping) { var height = Math.min(1, (groundLevel - self.y) / 300); self.shadow.alpha = 0.5 - height * 0.3; self.shadow.scaleX = 2.0 - height; self.shadow.scaleY = 0.5 - height * 0.2; } else { self.shadow.alpha = 0.5; self.shadow.scaleX = 2.0; self.shadow.scaleY = 0.5; } if (self.isJumping) { self.y += self.velocityY * globalSpeed; self.velocityY += 2.0 * globalSpeed; self.isFalling = self.velocityY > 0; self.jumpFrame.alpha = 1; self.runFrames[self.currentRunFrame].alpha = 0; //self.checkWaterHoleCollision(); self.checkPlatformCollision(); var visualBottomOffset = self.playerHeight * self.refScaleY / 2; if (self.y >= groundLevel - visualBottomOffset && !self.currentPlatform) { self.y = groundLevel - visualBottomOffset; self.isJumping = false; self.velocityY = 0; self.jumpFrame.alpha = 0; self.runFrames[self.currentRunFrame].alpha = 1; tween(self, { scaleX: self.refScaleX * 1.2, scaleY: self.refScaleY * 0.8 }, { duration: 100, easing: tween.elasticOut, onFinish: function onFinish() { tween(self, { scaleX: self.refScaleX, scaleY: self.refScaleY }, { duration: 500, easing: tween.elasticOut }); } }); } } else { if (self.currentPlatform) { var platformBounds = { left: self.currentPlatform.x - 500, right: self.currentPlatform.x + 500 }; var playerBounds = self.getBounds(); if (playerBounds.left > platformBounds.right || playerBounds.right < platformBounds.left) { self.isJumping = true; self.velocityY = 0.1; self.isFalling = true; self.currentPlatform = null; self.jumpFrame.alpha = 1; self.runFrames[self.currentRunFrame].alpha = 0; } } if (LK.ticks % 5 === 0 && !self.isDrownAnimPlaying && !self.isDying) { self.runFrames[self.currentRunFrame].alpha = 0; self.currentRunFrame = (self.currentRunFrame + 1) % self.runFrames.length; self.runFrames[self.currentRunFrame].alpha = 1; } } }; self.jump = function () { if (!self.isJumping && !self.isDrownAnimPlaying) { self.isJumping = true; self.velocityY = -self.jumpHeight * 1.5; self.jumpFrame.alpha = 1; LK.getSound('jump').play(); self.currentPlatform = null; } }; self.dieFrames = [self.attachAsset('playerDieFrame1', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('playerDieFrame2', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('playerDieFrame3', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })]; self.die = function () { console.log("Die..."); self.isDying = true; for (var i = 0; i < self.runFrames.length; i++) { self.runFrames[i].alpha = 0; } self.jumpFrame.alpha = 0; self.hitFrame.alpha = 0; self.shadow.alpha = 0; LK.getSound('loose').play(); LK.getSound('loose2').play(); LK.stopMusic(); var currentFrame = 0; function showNextFrame() { if (currentFrame > 0) { self.dieFrames[currentFrame - 1].alpha = 0; } self.dieFrames[currentFrame].alpha = 1; currentFrame++; if (currentFrame < self.dieFrames.length) { LK.setTimeout(showNextFrame, 100); } else { startDeathMovement(); } } function startDeathMovement() { var animLoop = true; var loopFrame = 1; function loopDieFrames() { for (var i = 0; i < self.dieFrames.length; i++) { self.dieFrames[i].alpha = 0; } self.dieFrames[loopFrame].alpha = 1; loopFrame = loopFrame === 1 ? 2 : 1; if (animLoop) { LK.setTimeout(loopDieFrames, 120); } } loopDieFrames(); tween(self, { y: self.y - 1024, x: 768, scaleX: 5, scaleY: 5 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { y: 4000 }, { duration: 1200, easing: tween.easeIn, onFinish: function onFinish() { animLoop = false; } }); } }); } showNextFrame(); }; self.hitPlayer = function () { if (self.isHit) { return; } console.log("Hit..."); self.isHit = true; for (var i = 0; i < self.runFrames.length; i++) { self.runFrames[i].alpha = 0; } self.jumpFrame.alpha = 0; if (self.morphState === 0) { lives--; livesCounter.updateLives(lives); } self.hitFrame.alpha = 1; if (lives <= 0) { self.die(); return; } if (self.morphState === 1) { LK.getSound('hit').play(); self.morphState = 0; self.updateRefScale(); LK.setTimeout(function () { self.hitFrame.alpha = 0; if (self.isJumping) { self.jumpFrame.alpha = 1; } else { self.runFrames[self.currentRunFrame].alpha = 1; } self.isHit = false; }, 330); } else { LK.getSound('hitSmall').play(); LK.setTimeout(function () { self.hitFrame.alpha = 0; if (self.isJumping) { self.jumpFrame.alpha = 1; } else { self.runFrames[self.currentRunFrame].alpha = 1; } self.isHit = false; }, 330); } }; self.drownAnim = function (holeX, callback) { console.log("drownAnim..."); self.jumpFrame.alpha = 0; self.hitFrame.alpha = 0; self.shadow.alpha = 0; self.isDrownAnimPlaying = true; for (var i = 0; i < self.runFrames.length; i++) { self.runFrames[i].alpha = 0; } var loopFrame = 1; function loopDrownFrames() { for (var i = 0; i < self.dieFrames.length; i++) { self.dieFrames[i].alpha = 0; } if (self.isDrownAnimPlaying) { self.dieFrames[loopFrame].alpha = 1; loopFrame = loopFrame === 1 ? 2 : 1; LK.setTimeout(loopDrownFrames, 120); } } loopDrownFrames(); tween(self, { x: holeX, y: 4000 }, { duration: 1500, easing: tween.easeIn, onFinish: function onFinish() { self.isDrownAnimPlaying = false; if (typeof callback === 'function') { callback(); } } }); }; self.drownPlayer = function (holeX, callback) { console.log("drownAnim..."); gamePaused = true; LK.getSound('drown').play(); if (lives > 0) { lives--; livesCounter.updateLives(lives); if (lives <= 0) { player.die(); LK.setTimeout(function () { LK.showGameOver(); }, 4000); } else { self.drownAnim(holeX, function () { if (lives > 0) { self.resetRun(); } if (typeof callback === 'function') { callback(); } }); } } }; self.checkWaterHoleCollision = function () { if (!waterHoleManager || !waterHoleManager.waterHoles) { return true; // No water holes, so platform collision should proceed } var shouldCheckPlatforms = true; for (var j = 0; j < waterHoleManager.waterHoles.length; j++) { var waterHole = waterHoleManager.waterHoles[j]; var distanceToWaterHole = Math.abs(self.x - waterHole.x); console.log("Distance to hole #" + j, distanceToWaterHole); if (distanceToWaterHole <= 400) { shouldCheckPlatforms = true; break; } } return shouldCheckPlatforms; }; self.checkPlatformCollision = function () { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformBounds = { left: platform.x - 500, right: platform.x + 500, top: platform.y - 50, bottom: platform.y + 50 }; var playerBounds = self.getBounds(); var adjustedVelocity = self.velocityY * globalSpeed; if (self.velocityY > 0 && playerBounds.bottom >= platformBounds.top && playerBounds.bottom - adjustedVelocity < platformBounds.top && playerBounds.right > platformBounds.left && playerBounds.left < platformBounds.right) { var visualBottomOffset = self.playerHeight * self.refScaleY / 2; self.y = platform.y - visualBottomOffset; self.velocityY = 0; self.isJumping = false; self.isFalling = false; self.currentPlatform = platform; self.jumpFrame.alpha = 0; self.runFrames[self.currentRunFrame].alpha = 1; tween(self, { scaleX: self.refScaleX * 1.2, scaleY: self.refScaleY * 0.8 }, { duration: 100, easing: tween.elasticOut, onFinish: function onFinish() { tween(self, { scaleX: self.refScaleX, scaleY: self.refScaleY }, { duration: 500, easing: tween.elasticOut }); } }); return true; } } return false; }; self.init(); }); var Portal = Container.expand(function () { var self = Container.call(this); // Main portal graphic var portalGraphics = self.attachAsset('portal', { anchorX: 0.5, anchorY: 0.5 }); // Portal center effect var portalCenter = self.attachAsset('portalCenter', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Portal frame effect var portalFrame = self.attachAsset('portalFrame2', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.speed = 10; self.active = true; self.reset = function (x, y) { self.x = x; self.y = y; self.active = true; self.alpha = 1; self.startAnimation(); }; self.startAnimation = function () { // Temp PORTAIL DISABLED return; // Rotate portal center tween(portalCenter, { rotation: Math.PI * 2 }, { duration: 3000, easing: tween.linear, onFinish: function onFinish() { portalCenter.rotation = 0; if (self.active) { self.startAnimation(); } } }); // Pulse portal frame tween(portalFrame, { alpha: 0.3, scaleX: 0.8, scaleY: 0.8 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { tween(portalFrame, { alpha: 0.7, scaleX: 1.0, scaleY: 1.0 }, { duration: 1500, easing: tween.easeInOut }); } }); }; self.getBounds = function () { return { left: self.x - 125, right: self.x + 125, top: self.y - 200, bottom: self.y + 200 }; }; self.update = function () { // Temp PORTAIL DISABLED return; if ((!player || !player.isHit && lives >= 0) && !gamePaused) { self.x -= self.speed * globalSpeed; } // Check for player collision if (self.active && player && player.getBounds && !player.isHit && lives >= 0 && !gamePaused) { var portalBounds = self.getBounds(); var playerBounds = player.getBounds(); if (playerBounds.left < portalBounds.right && playerBounds.right > portalBounds.left && playerBounds.top < portalBounds.bottom && playerBounds.bottom > portalBounds.top) { self.active = false; // Teleport effect LK.effects.flashScreen(0xFFFFFF, 300); // Move player to a new position (e.g., higher platform) var teleportY = level2Height - 100; // Animate player teleporting tween(player, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { player.x += 400; player.y = teleportY; // Reappear animation tween(player, { alpha: 1, scaleX: player.refScaleX, scaleY: player.refScaleY }, { duration: 300, easing: tween.easeOut }); } }); } } // Remove portal when it's off-screen if (self.x < -150) { if (self.parent) { self.parent.removeChild(self); } self.visible = false; return false; } return true; }; self.startAnimation(); return self; }); var PortalManager = Container.expand(function () { var self = Container.call(this); self.portals = []; self.portalPool = []; self.spawnInterval = Math.floor(Math.random() * 1000) + 1000; self.spawnCounter = 0; self.init = function () { self.portals = []; self.portalPool = []; self.spawnInterval = Math.floor(Math.random() * 1000) + 1000; self.spawnCounter = 0; }; self.update = function () { // Temp PORTAIL DISABLED return; if (player && player.isHit || lives < 0 || gamePaused) { return; } // Spawn logic self.spawnCounter++; if (self.portals.length < 1 && self.spawnCounter >= self.spawnInterval) { self.spawnPortal(); self.spawnCounter = 0; } // Update and remove off-screen portals for (var i = self.portals.length - 1; i >= 0; i--) { var portal = self.portals[i]; var result = portal.x > -150; if (result === false) { if (portal.parent) { portal.parent.removeChild(portal); } self.portals.splice(i, 1); self.portalPool.push(portal); } } }; self.spawnPortal = function () { // Temp PORTAIL DISABLED return; var portal; if (self.portalPool.length > 0) { portal = self.portalPool.pop(); portal.visible = true; } else { portal = new Portal(); } // Only spawn on platforms instead of fixed position var availablePlatforms = []; for (var p = 0; p < platforms.length; p++) { if (platforms[p].x > 2048 && platforms[p].x < 2800) { availablePlatforms.push(platforms[p]); } } // If we have platforms in the spawn zone, put portal on one of them if (availablePlatforms.length > 0) { var randomPlatform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; portal.x = randomPlatform.x; // Place at center of platform portal.y = randomPlatform.y - 200; // Adjust height to be above platform } else { // Fallback if no platforms are in the spawn zone portal.x = 2500; portal.y = groundLevel - 200; } if (self.portalPool.indexOf(portal) > -1) { portal.reset(portal.x, portal.y); } self.portals.push(portal); if (!portal.parent) { middlegroundContainer.addChild(portal); } self.spawnInterval = Math.floor(Math.random() * 1000) + 1000; self.spawnCounter = 0; }; return self; }); var StartButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5, width: 1024, height: 1024 }); self.animate = function () { if (!self.scale) { self.scale = { x: 1, y: 1 }; } tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.easeInOut, onFinish: self.animate }); } }); }; self.startGame = function () { LK.getSound('start').play(); tween(self, { scaleX: 0, scaleY: 0, y: -1000 }, { duration: 900, easing: tween.elasticIn, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } gameStarted = true; enemySpawnCounter = 0; if (player) { player.canJump = true; } } }); }; return self; }); var WaterHole = Container.expand(function () { var self = Container.call(this); self.frames = [self.attachAsset('waterHoleFrame1', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }), self.attachAsset('waterHoleFrame2', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame3', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame4', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame5', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame6', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame7', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }), self.attachAsset('waterHoleFrame8', { anchorX: 0.5, anchorY: 0.5, alpha: 0 })]; self.boundingBox = self.attachAsset('boundingBox', { anchorX: 0.5, anchorY: 0.5, width: 256, height: 1024, alpha: isDebug ? 0.5 : 0 }); self.leftBorder = self.attachAsset('waterHoleBorder', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, x: -230 }); self.leftBorder = self.attachAsset('waterHoleBorder', { anchorX: 0.5, anchorY: 0.5, scaleX: -1.0, x: 230 }); self.currentFrame = 0; self.speed = groundSpeedBase; self.reset = function (x, y) { self.x = x; self.y = y; self.alpha = 1; self.currentFrame = 0; for (var i = 0; i < self.frames.length; i++) { self.frames[i].alpha = i === 0 ? 1 : 0; } self.animationTimer = 0; }; self.startAnimation = function () { self.animationTimer = 0; }; self.animate = function () { self.frames[self.currentFrame].alpha = 0; self.currentFrame = (self.currentFrame + 1) % self.frames.length; self.frames[self.currentFrame].alpha = 1; }; self.update = function () { self.animationTimer += 1; if (self.animationTimer >= 6) { self.animate(); self.animationTimer = 0; } if ((!player || !player.isHit && lives >= 0) && !gamePaused) { self.x -= self.speed * globalSpeed; } }; self.startAnimation(); return self; }); var WaterHoleManager = Container.expand(function () { var self = Container.call(this); self.waterHoles = []; self.waterHolePool = []; self.spawnInterval = 200; self.spawnCounter = 0; self.checkPlayerCollision = function (playerBounds, waterHole) { var holeX = waterHole.x; console.log("Player bounds:", { left: playerBounds.left, right: playerBounds.right, top: playerBounds.top, bottom: playerBounds.bottom }); console.log("Water hole:", { x: holeX, boundingBoxWidth: waterHole.boundingBox.width, groundLevel: groundLevel }); var condition1 = playerBounds.left < holeX + waterHole.boundingBox.width / 2; var condition2 = playerBounds.right > holeX - waterHole.boundingBox.width / 2; var condition3 = playerBounds.bottom > groundLevel - 150; console.log("Collision conditions:", { horizontalOverlap1: condition1, horizontalOverlap2: condition2, belowThreshold: condition3, allConditions: condition1 && condition2 && condition3 }); return condition1 && condition2 && condition3; }; self.init = function () { self.waterHoles = []; self.waterHolePool = []; self.spawnCounter = 0; }; self.spawnWaterHole = function () { var spawnX; var rightmostGround; if (ground && ground2) { if (ground.x > ground2.x) { rightmostGround = ground; } else { rightmostGround = ground2; } var gapStartX = rightmostGround.x; spawnX = gapStartX + 256; } if (!spawnX || spawnX < 2304) { return; } rightmostGround.x += 512; var leftmostGround = ground.x < ground2.x ? ground : ground2; if (self.waterHoles.length > 0 && self.waterHoles[0].x < -150) { leftmostGround.x -= 512; } var waterHole; var wasReused = false; if (self.waterHolePool.length > 0) { waterHole = self.waterHolePool.pop(); waterHole.visible = true; wasReused = true; } else { waterHole = new WaterHole(); } waterHole.x = spawnX; waterHole.y = groundLevel + 512; if (wasReused) { waterHole.reset(waterHole.x, waterHole.y); } self.waterHoles.push(waterHole); if (!waterHole.parent) { middlegroundContainer.addChild(waterHole); } self.spawnInterval = Math.floor(Math.random() * 300) + 200; self.spawnCounter = 0; }; self.update = function () { if (player && player.isHit || lives < 0) { return; } self.spawnCounter++; if (self.waterHoles.length < 3 && self.spawnCounter >= self.spawnInterval) { self.spawnWaterHole(); } for (var i = self.waterHoles.length - 1; i >= 0; i--) { var waterHole = self.waterHoles[i]; if (waterHole.x < -300) { if (waterHole.parent) { waterHole.parent.removeChild(waterHole); } self.waterHoles.splice(i, 1); waterHole.visible = false; self.waterHolePool.push(waterHole); } if (player && player.getBounds) { var distanceToWaterHole = Math.abs(player.x - waterHole.x); console.log("Distance to hole #" + i, distanceToWaterHole); if (distanceToWaterHole < 400) { var playerBounds = player.getBounds(); if (self.checkPlayerCollision(playerBounds, waterHole)) { if (!waterHole.triggered) { waterHole.triggered = true; if (player.canJump) { var currentHole = waterHole; var currentIndex = i; player.drownPlayer(currentHole.x, function () { // Remove the waterhole if (currentHole.parent) { currentHole.parent.removeChild(currentHole); } self.waterHoles.splice(currentIndex, 1); currentHole.visible = false; self.waterHolePool.push(currentHole); // Move the left ground to the right to hide the gap if (ground && ground2) { var leftmostGround = ground.x < ground2.x ? ground : ground2; leftmostGround.x += 512; } }); } else { player.jump(); } } } else { waterHole.triggered = false; } } } } }; self.init(); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ /**** * Global Variables ****/ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) { return t; } var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) { return i; } throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var isDebug = false; var level1Height; var level2Height; var game; var background; var player; var enemies; var enemySpawnInterval; var enemySpawnCounter; var startButton; var coinManager; var mushroomManager; var scoreText; var coinCounter; var coinCount = 0; var lives = 3; var backgroundContainer; var middlegroundContainer; var foregroundContainer; var bgClose; var bgClose2; var bgFar; var bgFar2; var platforms; var ground; var ground2; var groundLevel; var groundSpeedBase = 10; var globalSpeed = 1.0; var gamePaused = false; var waterHoleManager; var portalManager; var gameStarted = false; function backgroundUpdate() { if ((!player || !player.isHit) && lives >= 0 && !gamePaused) { bgClose.x -= 4 * globalSpeed; bgClose2.x -= 4 * globalSpeed; bgFar.x -= 2 * globalSpeed; bgFar2.x -= 2 * globalSpeed; if (bgClose.x <= -bgClose.width) { bgClose.x = bgClose2.x + bgClose2.width; } if (bgClose2.x <= -bgClose2.width) { bgClose2.x = bgClose.x + bgClose.width; } if (bgFar.x <= -bgFar.width) { bgFar.x = bgFar2.x + bgFar2.width; } if (bgFar2.x <= -bgFar2.width) { bgFar2.x = bgFar.x + bgFar.width; } ground.x -= groundSpeedBase * globalSpeed; ground2.x -= groundSpeedBase * globalSpeed; if (ground.x <= -ground.width) { ground.x = ground2.x + ground2.width; } if (ground2.x <= -ground2.width) { ground2.x = ground.x + ground.width; } } } function platformsUpdate() { if (player && player.isHit || lives < 0 || gamePaused) { return; } for (var i = platforms.length - 1; i >= 0; i--) { if (platforms[i].destroyed) { platforms.splice(i, 1); } } if (platforms.length > 0) { var lastPlatform = platforms[platforms.length - 1]; if (lastPlatform.x < 2048 + 500) { spawnPlatform(); } } } game.update = function () { backgroundUpdate(); platformsUpdate(); if (portalManager) { portalManager.update(); } if (enemySpawnCounter !== 9999) { enemySpawnCounter++; if (enemySpawnCounter >= enemySpawnInterval) { var enemy; if (enemyPool.length > 0) { enemy = enemyPool.pop(); enemy.visible = true; } else { enemy = new Enemy(); } enemy.x = 2500; var spawnOnPlatform = Math.random() < 0.5 && platforms.length > 0; if (spawnOnPlatform) { var visiblePlatforms = []; for (var p = 0; p < platforms.length; p++) { if (platforms[p].x > 2200 && platforms[p].x < 2700) { visiblePlatforms.push(platforms[p]); } } if (visiblePlatforms.length > 0) { var randomPlatform = visiblePlatforms[Math.floor(Math.random() * visiblePlatforms.length)]; enemy.y = randomPlatform.y - 150; } else { enemy.y = player.y; } } else { enemy.y = player.y; } if (enemyPool.indexOf(enemy) > -1) { enemy.reset(enemy.x, enemy.y); } enemies.push(enemy); if (!enemy.parent) { middlegroundContainer.addChild(enemy); } enemySpawnInterval = Math.floor(Math.random() * 150) + 50; enemySpawnCounter = 0; } } var playerBounds = player.getBounds(); for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (!enemy.visible) { continue; } var enemyBounds = enemy.getBounds(); if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) { if (player.isFalling && player.velocityY > 0 && playerBounds.bottom > enemyBounds.top && playerBounds.bottom - player.velocityY < enemyBounds.top) { if (enemy.parent) { enemy.parent.removeChild(enemy); } enemies.splice(j, 1); enemy.visible = false; enemyPool.push(enemy); LK.getSound('enemyStomp').play(); player.velocityY = -15; LK.setScore(LK.getScore() + 5); scoreText.setText(LK.getScore()); } else { if (lives < 0) { return; } player.hitPlayer(); LK.effects.flashScreen(0xff0000, 150); if (lives <= 0) { LK.setTimeout(function () { LK.showGameOver(); }, 4000); } else { if (enemy.parent) { enemy.parent.removeChild(enemy); } enemies.splice(j, 1); enemy.visible = false; enemyPool.push(enemy); } } } else if (player.x > enemy.x && !enemy.passed) { enemy.passed = true; LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); } } }; game.down = function (x, y, obj) { if (gameStarted) { player.jump(); } else { startButton.startGame(); } }; function initializeGame() { backgroundContainer = new Container(); middlegroundContainer = new Container(); foregroundContainer = new Container(); game.addChild(backgroundContainer); game.addChild(middlegroundContainer); game.addChild(foregroundContainer); groundLevel = 2732 / 2 + 450; bgFar = LK.getAsset('bgFar', { anchorX: 0, anchorY: 0 }); bgFar.x = 0; bgFar.y = 0; bgFar.width = 2732; backgroundContainer.addChild(bgFar); bgFar2 = LK.getAsset('bgFar', { anchorX: 0, anchorY: 0 }); bgFar2.x = bgFar.width; bgFar2.y = 0; bgFar2.width = 2732; backgroundContainer.addChild(bgFar2); bgClose = LK.getAsset('bgClose', { anchorX: 0, anchorY: 0 }); bgClose.x = 0; bgClose.y = 0; bgClose.width = 2732; backgroundContainer.addChild(bgClose); bgClose2 = LK.getAsset('bgClose', { anchorX: 0, anchorY: 0 }); bgClose2.x = bgClose.width; bgClose2.y = 0; bgClose2.width = 2732; backgroundContainer.addChild(bgClose2); ground = LK.getAsset('ground', { anchorX: 0, anchorY: 0 }); ground.x = 0; ground.y = groundLevel; ground.width = 2048; middlegroundContainer.addChild(ground); ground2 = LK.getAsset('ground', { anchorX: 0, anchorY: 0 }); ground2.x = ground.width; ground2.y = groundLevel; ground2.width = 2048; middlegroundContainer.addChild(ground2); player = new Player(); player.x = 2048 / 6; player.y = groundLevel - 100; foregroundContainer.addChild(player); enemies = []; enemyPool = []; enemySpawnInterval = 100; enemySpawnCounter = 9999; startButton = new StartButton(); startButton.x = 2048 / 2; startButton.y = 2732 / 2; startButton.scale = { x: 0, y: 0 }; foregroundContainer.addChild(startButton); startButton.animate(); startButton.visible = true; player.canJump = false; lives = 3; coinManager = new CoinManager(); middlegroundContainer.addChild(coinManager); mushroomManager = new MushroomManager(); middlegroundContainer.addChild(mushroomManager); platforms = []; level1Height = groundLevel - 450; level2Height = level1Height - 450; for (var i = 0; i < 2; i++) { var platform = new Platform(); if (i === 0) { platform.x = player.x + 800; platform.y = level1Height; } else { platform.x = platforms[i - 1].x + 1200; platform.y = level2Height; } platforms.push(platform); middlegroundContainer.addChild(platform); } scoreText = new Text2('0', { size: 100, fill: 0xFFFFFF }); LK.gui.top.addChild(scoreText); scoreText.x = 2048 / 2; scoreText.y = 0; coinCounter = new CoinCounter(); coinCounter.x = -300; coinCounter.y = 30; LK.gui.topRight.addChild(coinCounter); livesCounter = new LivesCounter(); livesCounter.x = 250; livesCounter.y = 80; LK.gui.topLeft.addChild(livesCounter); livesCounter.updateLives(lives); waterHoleManager = new WaterHoleManager(); middlegroundContainer.addChild(waterHoleManager); // Initialize portal manager portalManager = new PortalManager(); middlegroundContainer.addChild(portalManager); LK.playMusic('bgMusic'); } var platformPool = []; var enemyPool = []; function spawnPlatform() { var platform; if (platformPool.length > 0) { platform = platformPool.pop(); platform.visible = true; } else { platform = new Platform(); } var lastPlatform = platforms[platforms.length - 1]; var lastHeight = lastPlatform.y; if (lastHeight === level1Height) { platform.y = level2Height; platform.x = lastPlatform.x + 1200; } else { platform.y = level1Height; platform.x = lastPlatform.x + 1500; } if (Math.random() < 0.2) { lastPlatform.x += 500; if (platform.parent) { platform.parent.removeChild(platform); } platformPool.push(platform); return; } platforms.push(platform); middlegroundContainer.addChild(platform); } initializeGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
self.frames = [self.attachAsset('coinFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
}), self.attachAsset('coinFrame2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame4', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame5', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame6', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame7', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('coinFrame8', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
})];
self.currentFrame = 0;
self.speed = 10;
self.collected = false;
self.animationSpeed = 4;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.collected = false;
self.alpha = 1;
self.currentFrame = 0;
for (var i = 0; i < self.frames.length; i++) {
self.frames[i].alpha = i === 0 ? 1 : 0;
}
self.animationTimer = 0;
};
self.startAnimation = function () {
self.animationTimer = 0;
};
self.animate = function () {
self.frames[self.currentFrame].alpha = 0;
self.currentFrame = (self.currentFrame + 1) % self.frames.length;
self.frames[self.currentFrame].alpha = 1;
};
self.getBounds = function () {
return {
left: self.x - 40,
right: self.x + 40,
top: self.y - 40,
bottom: self.y + 40
};
};
self.update = function () {
self.animationTimer += 1;
if (self.animationTimer >= 6) {
self.animate();
self.animationTimer = 0;
}
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
if (self.x < -100) {
var coinIndex = coinManager.coins.indexOf(self);
if (coinIndex > -1) {
coinManager.coins.splice(coinIndex, 1);
}
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
coinManager.coinPool.push(self);
}
if (!self.collected && player && player.getBounds && player.canJump && !gamePaused) {
var coinBounds = self.getBounds();
var playerBounds = player.getBounds();
if (playerBounds.left < coinBounds.right && playerBounds.right > coinBounds.left && playerBounds.top < coinBounds.bottom && playerBounds.bottom > coinBounds.top) {
self.collected = true;
LK.getSound('coin').play();
LK.setScore(LK.getScore() + 10);
if (scoreText) {
scoreText.setText(LK.getScore());
}
if (coinCounter) {
coinCount++;
coinCounter.updateCount(coinCount);
}
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
var coinIndex = coinManager.coins.indexOf(self);
if (coinIndex > -1) {
coinManager.coins.splice(coinIndex, 1);
}
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
coinManager.coinPool.push(self);
}
});
}
}
};
self.startAnimation();
return self;
});
var CoinCounter = Container.expand(function () {
var self = Container.call(this);
var coinIcon = self.attachAsset('coinFrame1', {
anchorX: 0.5,
anchorY: 0.5,
x: 220,
y: 50,
width: 96,
height: 96
});
self.hundreds = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
self.hundreds.anchor.set(0.5);
self.hundreds.x = 0;
self.hundreds.y = 50;
self.addChild(self.hundreds);
self.tens = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
self.tens.anchor.set(0.5);
self.tens.x = 60;
self.tens.y = 50;
self.addChild(self.tens);
self.units = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
self.units.anchor.set(0.5);
self.units.x = 120;
self.units.y = 50;
self.addChild(self.units);
self.updateCount = function (count) {
count = Math.min(999, Math.max(0, count));
var h = Math.floor(count / 100);
var t = Math.floor(count % 100 / 10);
var u = count % 10;
self.hundreds.setText(h.toString());
self.tens.setText(t.toString());
self.units.setText(u.toString());
};
self.updateCount(0);
return self;
});
var CoinManager = Container.expand(function () {
var self = Container.call(this);
self.coins = [];
self.coinPool = [];
self.spawnInterval = Math.floor(Math.random() * 100) + 50;
self.spawnCounter = 0;
self.init = function () {
self.coins = [];
self.coinPool = [];
self.spawnInterval = Math.floor(Math.random() * 100) + 50;
self.spawnCounter = 0;
};
self.resetCoins = function () {
for (var i = self.coins.length - 1; i >= 0; i--) {
if (self.coins[i].parent) {
self.coins[i].parent.removeChild(self.coins[i]);
}
self.coins[i].visible = false;
self.coinPool.push(self.coins[i]);
}
self.coins = [];
self.spawnCounter = 0;
};
self.update = function () {
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
// Spawn logic
self.spawnCounter++;
if (self.coins.length < 10 && self.spawnCounter >= self.spawnInterval) {
self.spawnCoin();
self.spawnCounter = 0;
}
};
self.spawnCoin = function () {
var coin;
if (self.coinPool.length > 0) {
coin = self.coinPool.pop();
coin.visible = true;
} else {
coin = new Coin();
}
coin.x = 2500;
var randomHeight = Math.random();
if (randomHeight < 0.33) {
coin.y = groundLevel - 100;
} else if (randomHeight < 0.66) {
coin.y = level1Height - 100;
} else {
coin.y = level2Height - 100;
}
if (self.coinPool.indexOf(coin) > -1) {
coin.reset(coin.x, coin.y);
}
self.coins.push(coin);
if (!coin.parent) {
middlegroundContainer.addChild(coin);
}
self.spawnInterval = Math.floor(Math.random() * 200) + 100;
self.spawnCounter = 0;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.startAnimation = function () {
tween(self, {
scaleX: 1.15
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0.9
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: self.startAnimation
});
}
});
};
self.speed = 15;
self.velocityY = 0;
self.gravity = 0.7;
self.currentPlatform = null;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.velocityY = 0;
self.currentPlatform = null;
self.passed = false;
self.startAnimation();
};
self.update = function () {
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
// Check for water hole collisions and reverse direction
if (waterHoleManager && waterHoleManager.waterHoles) {
var enemyBounds = self.getBounds();
for (var i = 0; i < waterHoleManager.waterHoles.length; i++) {
var waterHole = waterHoleManager.waterHoles[i];
var holeX = waterHole.x;
var holeWidth = waterHole.boundingBox.width;
// If enemy is close to water hole border, reverse direction
if (Math.abs(enemyBounds.right - (holeX - holeWidth / 2)) < 20 || Math.abs(enemyBounds.left - (holeX + holeWidth / 2)) < 20) {
self.speed = -self.speed; // Reverse direction
break;
}
}
}
self.x -= self.speed * globalSpeed;
self.x -= self.speed < 0 ? 10 * globalSpeed : 0;
if (self.currentPlatform) {
var enemyBounds = self.getBounds();
var platformBounds = {
left: self.currentPlatform.x - 500,
right: self.currentPlatform.x + 500
};
if (enemyBounds.left > platformBounds.right || enemyBounds.right < platformBounds.left) {
self.currentPlatform = null;
}
}
if (!self.currentPlatform) {
self.velocityY += self.gravity * globalSpeed;
self.y += self.velocityY * globalSpeed;
}
var enemyVisualBottomOffset = 75;
if (self.y >= groundLevel - enemyVisualBottomOffset) {
self.y = groundLevel - enemyVisualBottomOffset;
self.velocityY = 0;
self.currentPlatform = null;
}
if (self.velocityY > 0) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var enemyBounds = self.getBounds();
var platformBounds = {
left: platform.x - 500,
right: platform.x + 500,
top: platform.y - 50,
bottom: platform.y + 50
};
if (enemyBounds.bottom >= platformBounds.top && enemyBounds.bottom - self.velocityY < platformBounds.top && enemyBounds.right > platformBounds.left && enemyBounds.left < platformBounds.right) {
self.y = platform.y - 75;
self.velocityY = 0;
self.currentPlatform = platform;
break;
}
}
}
if (self.x < -50) {
if (self.parent) {
self.parent.removeChild(self);
}
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
self.visible = false;
enemyPool.push(self);
}
};
self.getBounds = function () {
return {
left: self.x - 50,
right: self.x + 50,
top: self.y - 50,
bottom: self.y + 50
};
};
self.startAnimation();
return self;
});
var LivesCounter = Container.expand(function () {
var self = Container.call(this);
self.hearts = [];
var maxHearts = 3;
for (var i = 0; i < maxHearts; i++) {
var heart = self.attachAsset('playerRunFrame2', {
anchorX: 0.5,
anchorY: 0.5,
x: i * 70,
y: 0,
width: 60,
height: 60
});
self.hearts.push(heart);
}
self.updateLives = function (livesCount) {
livesCount = Math.min(maxHearts, Math.max(0, livesCount));
for (var i = 0; i < maxHearts; i++) {
self.hearts[i].visible = i < livesCount;
}
};
self.updateLives(3);
return self;
});
var Mushroom = Container.expand(function () {
var self = Container.call(this);
var mushroomGraphics = self.attachAsset('mushroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.collected = false;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.collected = false;
self.alpha = 1;
};
self.getBounds = function () {
return {
left: self.x - 50,
right: self.x + 50,
top: self.y - 45,
bottom: self.y + 45
};
};
self.update = function () {
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
if (self.x < -100) {
var mushroomIndex = mushroomManager.mushrooms.indexOf(self);
if (mushroomIndex > -1) {
mushroomManager.mushrooms.splice(mushroomIndex, 1);
}
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
mushroomManager.mushroomPool.push(self);
}
if (!self.collected && player && player.getBounds && player.canJump && !gamePaused) {
var mushroomBounds = self.getBounds();
var playerBounds = player.getBounds();
if (playerBounds.left < mushroomBounds.right && playerBounds.right > mushroomBounds.left && playerBounds.top < mushroomBounds.bottom && playerBounds.bottom > mushroomBounds.top) {
self.collected = true;
if (player.morphState === 0) {
LK.getSound('mushroomEat').play();
player.morphState = 1;
player.updateRefScale();
}
LK.setScore(LK.getScore() + 100);
if (scoreText) {
scoreText.setText(LK.getScore());
}
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
var mushroomIndex = mushroomManager.mushrooms.indexOf(self);
if (mushroomIndex > -1) {
mushroomManager.mushrooms.splice(mushroomIndex, 1);
}
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
mushroomManager.mushroomPool.push(self);
}
});
}
}
};
return self;
});
var MushroomManager = Container.expand(function () {
var self = Container.call(this);
self.mushrooms = [];
self.mushroomPool = [];
self.spawnInterval = Math.floor(Math.random() * 500) + 500;
self.spawnCounter = 0;
self.init = function () {
self.mushrooms = [];
self.mushroomPool = [];
self.spawnInterval = Math.floor(Math.random() * 500) + 500;
self.spawnCounter = 0;
};
self.update = function () {
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
// Spawn logic
self.spawnCounter++;
if (self.mushrooms.length < 2 && self.spawnCounter >= self.spawnInterval) {
self.spawnMushroom();
self.spawnCounter = 0;
}
};
self.spawnMushroom = function () {
var mushroom;
if (self.mushroomPool.length > 0) {
mushroom = self.mushroomPool.pop();
mushroom.visible = true;
} else {
mushroom = new Mushroom();
}
mushroom.x = 2500;
// Only spawn on platforms instead of random heights
var availablePlatforms = [];
for (var p = 0; p < platforms.length; p++) {
if (platforms[p].x > 2048 && platforms[p].x < 2800) {
availablePlatforms.push(platforms[p]);
}
}
// If we have platforms in the spawn zone, put mushroom on one of them
if (availablePlatforms.length > 0) {
var randomPlatform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
mushroom.x = randomPlatform.x; // Place at center of platform
mushroom.y = randomPlatform.y - 100; // Adjust height to be above platform
} else {
// Fallback if no platforms are in the spawn zone
mushroom.x = 2500;
mushroom.y = groundLevel - 100;
}
if (self.mushroomPool.indexOf(mushroom) > -1) {
mushroom.reset(mushroom.x, mushroom.y);
}
self.mushrooms.push(mushroom);
if (!mushroom.parent) {
middlegroundContainer.addChild(mushroom);
}
self.spawnInterval = Math.floor(Math.random() * 500) + 500;
self.spawnCounter = 0;
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.passed = false;
self.update = function () {
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
self.x -= self.speed * globalSpeed;
if (self.x < -500) {
if (self.parent) {
self.parent.removeChild(self);
}
var index = platforms.indexOf(self);
if (index > -1) {
platforms.splice(index, 1);
}
self.visible = false;
platformPool.push(self);
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
self.morphState = 0;
self.refScaleX = 0.5;
self.refScaleY = 0.5;
self.resetRun = function () {
console.log("Reset run...");
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].parent) {
enemies[i].parent.removeChild(enemies[i]);
}
enemies[i].visible = false;
enemyPool.push(enemies[i]);
}
enemies = [];
// Reset coins using the manager's resetCoins method
if (coinManager) {
coinManager.resetCoins();
}
// Reset mushrooms using the manager
if (mushroomManager) {
for (var i = mushroomManager.mushrooms.length - 1; i >= 0; i--) {
var mushroom = mushroomManager.mushrooms[i];
if (mushroom.parent) {
mushroom.parent.removeChild(mushroom);
}
mushroom.visible = false;
mushroomManager.mushroomPool.push(mushroom);
}
mushroomManager.mushrooms = [];
mushroomManager.spawnCounter = 0;
}
if (waterHoleManager && waterHoleManager.waterHoles) {
for (var i = waterHoleManager.waterHoles.length - 1; i >= 0; i--) {
var waterHole = waterHoleManager.waterHoles[i];
if (waterHole.parent) {
waterHole.parent.removeChild(waterHole);
}
waterHole.visible = false;
waterHoleManager.waterHolePool.push(waterHole);
}
waterHoleManager.waterHoles = [];
waterHoleManager.spawnCounter = 0;
}
// Reset portals
if (portalManager && portalManager.portals) {
for (var i = portalManager.portals.length - 1; i >= 0; i--) {
var portal = portalManager.portals[i];
if (portal.parent) {
portal.parent.removeChild(portal);
}
portal.visible = false;
portalManager.portalPool.push(portal);
}
portalManager.portals = [];
portalManager.spawnCounter = 0;
}
LK.effects.flashScreen(0xFFFFFF, 600);
self.x = 2048 / 6;
self.y = groundLevel - 100;
self.velocityY = 0;
self.isJumping = false;
self.currentPlatform = null;
self.shadow.alpha = 0.5;
console.log("RESET FRAMES!");
self.isDrownAnimPlaying = false;
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
self.morphState = 0;
self.scale.x = 0.5;
self.scale.y = 0.5;
self.updateRefScale();
self.runFrames[self.currentRunFrame].alpha = 1;
gamePaused = false;
};
self.init = function () {
self.updateRefScale();
};
self.updateRefScale = function () {
var oldScaleY = self.refScaleY;
var visualBottomOffset = self.playerHeight * oldScaleY / 2;
if (self.morphState === 0) {
self.refScaleX = 0.5;
self.refScaleY = 0.5;
} else {
self.refScaleX = 1.0;
self.refScaleY = 1.0;
}
var newVisualBottomOffset = self.playerHeight * self.refScaleY / 2;
if (!self.isJumping) {
if (self.currentPlatform) {
self.y = self.currentPlatform.y - newVisualBottomOffset;
} else {
self.y = groundLevel - newVisualBottomOffset;
}
}
tween(self.scale, {
x: self.refScaleX,
y: self.refScaleY
}, {
duration: 1000,
easing: tween.easeOut
});
};
self.shadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
scaleX: 2.0,
scaleY: 0.4,
tint: 0x000000,
y: 200
});
self.runFrames = [self.attachAsset('playerRunFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
}), self.attachAsset('playerRunFrame2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('playerRunFrame', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
})];
self.currentRunFrame = 0;
self.speed = 5;
self.jumpHeight = 35;
self.isJumping = false;
self.velocityY = 0;
self.isFalling = false;
self.currentPlatform = null;
self.playerHeight = 400;
self.canJump = false;
self.isHit = false;
self.isDying = false;
self.boundingBox = self.attachAsset('boundingBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 380,
alpha: isDebug ? 0.5 : 0
});
self.hitFrame = self.attachAsset('playerHitFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.jumpFrame = self.attachAsset('playerJumpFrame', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.getBounds = function () {
return {
left: self.x - 75,
right: self.x + 75,
top: self.y - 100,
bottom: self.y + 100
};
};
self.update = function () {
if (self.isHit || lives < 0) {
return;
}
if (self.isJumping) {
var height = Math.min(1, (groundLevel - self.y) / 300);
self.shadow.alpha = 0.5 - height * 0.3;
self.shadow.scaleX = 2.0 - height;
self.shadow.scaleY = 0.5 - height * 0.2;
} else {
self.shadow.alpha = 0.5;
self.shadow.scaleX = 2.0;
self.shadow.scaleY = 0.5;
}
if (self.isJumping) {
self.y += self.velocityY * globalSpeed;
self.velocityY += 2.0 * globalSpeed;
self.isFalling = self.velocityY > 0;
self.jumpFrame.alpha = 1;
self.runFrames[self.currentRunFrame].alpha = 0;
//self.checkWaterHoleCollision();
self.checkPlatformCollision();
var visualBottomOffset = self.playerHeight * self.refScaleY / 2;
if (self.y >= groundLevel - visualBottomOffset && !self.currentPlatform) {
self.y = groundLevel - visualBottomOffset;
self.isJumping = false;
self.velocityY = 0;
self.jumpFrame.alpha = 0;
self.runFrames[self.currentRunFrame].alpha = 1;
tween(self, {
scaleX: self.refScaleX * 1.2,
scaleY: self.refScaleY * 0.8
}, {
duration: 100,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: self.refScaleX,
scaleY: self.refScaleY
}, {
duration: 500,
easing: tween.elasticOut
});
}
});
}
} else {
if (self.currentPlatform) {
var platformBounds = {
left: self.currentPlatform.x - 500,
right: self.currentPlatform.x + 500
};
var playerBounds = self.getBounds();
if (playerBounds.left > platformBounds.right || playerBounds.right < platformBounds.left) {
self.isJumping = true;
self.velocityY = 0.1;
self.isFalling = true;
self.currentPlatform = null;
self.jumpFrame.alpha = 1;
self.runFrames[self.currentRunFrame].alpha = 0;
}
}
if (LK.ticks % 5 === 0 && !self.isDrownAnimPlaying && !self.isDying) {
self.runFrames[self.currentRunFrame].alpha = 0;
self.currentRunFrame = (self.currentRunFrame + 1) % self.runFrames.length;
self.runFrames[self.currentRunFrame].alpha = 1;
}
}
};
self.jump = function () {
if (!self.isJumping && !self.isDrownAnimPlaying) {
self.isJumping = true;
self.velocityY = -self.jumpHeight * 1.5;
self.jumpFrame.alpha = 1;
LK.getSound('jump').play();
self.currentPlatform = null;
}
};
self.dieFrames = [self.attachAsset('playerDieFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('playerDieFrame2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('playerDieFrame3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
})];
self.die = function () {
console.log("Die...");
self.isDying = true;
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
self.jumpFrame.alpha = 0;
self.hitFrame.alpha = 0;
self.shadow.alpha = 0;
LK.getSound('loose').play();
LK.getSound('loose2').play();
LK.stopMusic();
var currentFrame = 0;
function showNextFrame() {
if (currentFrame > 0) {
self.dieFrames[currentFrame - 1].alpha = 0;
}
self.dieFrames[currentFrame].alpha = 1;
currentFrame++;
if (currentFrame < self.dieFrames.length) {
LK.setTimeout(showNextFrame, 100);
} else {
startDeathMovement();
}
}
function startDeathMovement() {
var animLoop = true;
var loopFrame = 1;
function loopDieFrames() {
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
self.dieFrames[loopFrame].alpha = 1;
loopFrame = loopFrame === 1 ? 2 : 1;
if (animLoop) {
LK.setTimeout(loopDieFrames, 120);
}
}
loopDieFrames();
tween(self, {
y: self.y - 1024,
x: 768,
scaleX: 5,
scaleY: 5
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: 4000
}, {
duration: 1200,
easing: tween.easeIn,
onFinish: function onFinish() {
animLoop = false;
}
});
}
});
}
showNextFrame();
};
self.hitPlayer = function () {
if (self.isHit) {
return;
}
console.log("Hit...");
self.isHit = true;
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
self.jumpFrame.alpha = 0;
if (self.morphState === 0) {
lives--;
livesCounter.updateLives(lives);
}
self.hitFrame.alpha = 1;
if (lives <= 0) {
self.die();
return;
}
if (self.morphState === 1) {
LK.getSound('hit').play();
self.morphState = 0;
self.updateRefScale();
LK.setTimeout(function () {
self.hitFrame.alpha = 0;
if (self.isJumping) {
self.jumpFrame.alpha = 1;
} else {
self.runFrames[self.currentRunFrame].alpha = 1;
}
self.isHit = false;
}, 330);
} else {
LK.getSound('hitSmall').play();
LK.setTimeout(function () {
self.hitFrame.alpha = 0;
if (self.isJumping) {
self.jumpFrame.alpha = 1;
} else {
self.runFrames[self.currentRunFrame].alpha = 1;
}
self.isHit = false;
}, 330);
}
};
self.drownAnim = function (holeX, callback) {
console.log("drownAnim...");
self.jumpFrame.alpha = 0;
self.hitFrame.alpha = 0;
self.shadow.alpha = 0;
self.isDrownAnimPlaying = true;
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
var loopFrame = 1;
function loopDrownFrames() {
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
if (self.isDrownAnimPlaying) {
self.dieFrames[loopFrame].alpha = 1;
loopFrame = loopFrame === 1 ? 2 : 1;
LK.setTimeout(loopDrownFrames, 120);
}
}
loopDrownFrames();
tween(self, {
x: holeX,
y: 4000
}, {
duration: 1500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isDrownAnimPlaying = false;
if (typeof callback === 'function') {
callback();
}
}
});
};
self.drownPlayer = function (holeX, callback) {
console.log("drownAnim...");
gamePaused = true;
LK.getSound('drown').play();
if (lives > 0) {
lives--;
livesCounter.updateLives(lives);
if (lives <= 0) {
player.die();
LK.setTimeout(function () {
LK.showGameOver();
}, 4000);
} else {
self.drownAnim(holeX, function () {
if (lives > 0) {
self.resetRun();
}
if (typeof callback === 'function') {
callback();
}
});
}
}
};
self.checkWaterHoleCollision = function () {
if (!waterHoleManager || !waterHoleManager.waterHoles) {
return true; // No water holes, so platform collision should proceed
}
var shouldCheckPlatforms = true;
for (var j = 0; j < waterHoleManager.waterHoles.length; j++) {
var waterHole = waterHoleManager.waterHoles[j];
var distanceToWaterHole = Math.abs(self.x - waterHole.x);
console.log("Distance to hole #" + j, distanceToWaterHole);
if (distanceToWaterHole <= 400) {
shouldCheckPlatforms = true;
break;
}
}
return shouldCheckPlatforms;
};
self.checkPlatformCollision = function () {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformBounds = {
left: platform.x - 500,
right: platform.x + 500,
top: platform.y - 50,
bottom: platform.y + 50
};
var playerBounds = self.getBounds();
var adjustedVelocity = self.velocityY * globalSpeed;
if (self.velocityY > 0 && playerBounds.bottom >= platformBounds.top && playerBounds.bottom - adjustedVelocity < platformBounds.top && playerBounds.right > platformBounds.left && playerBounds.left < platformBounds.right) {
var visualBottomOffset = self.playerHeight * self.refScaleY / 2;
self.y = platform.y - visualBottomOffset;
self.velocityY = 0;
self.isJumping = false;
self.isFalling = false;
self.currentPlatform = platform;
self.jumpFrame.alpha = 0;
self.runFrames[self.currentRunFrame].alpha = 1;
tween(self, {
scaleX: self.refScaleX * 1.2,
scaleY: self.refScaleY * 0.8
}, {
duration: 100,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: self.refScaleX,
scaleY: self.refScaleY
}, {
duration: 500,
easing: tween.elasticOut
});
}
});
return true;
}
}
return false;
};
self.init();
});
var Portal = Container.expand(function () {
var self = Container.call(this);
// Main portal graphic
var portalGraphics = self.attachAsset('portal', {
anchorX: 0.5,
anchorY: 0.5
});
// Portal center effect
var portalCenter = self.attachAsset('portalCenter', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Portal frame effect
var portalFrame = self.attachAsset('portalFrame2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.speed = 10;
self.active = true;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.active = true;
self.alpha = 1;
self.startAnimation();
};
self.startAnimation = function () {
// Temp PORTAIL DISABLED
return;
// Rotate portal center
tween(portalCenter, {
rotation: Math.PI * 2
}, {
duration: 3000,
easing: tween.linear,
onFinish: function onFinish() {
portalCenter.rotation = 0;
if (self.active) {
self.startAnimation();
}
}
});
// Pulse portal frame
tween(portalFrame, {
alpha: 0.3,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(portalFrame, {
alpha: 0.7,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 1500,
easing: tween.easeInOut
});
}
});
};
self.getBounds = function () {
return {
left: self.x - 125,
right: self.x + 125,
top: self.y - 200,
bottom: self.y + 200
};
};
self.update = function () {
// Temp PORTAIL DISABLED
return;
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
// Check for player collision
if (self.active && player && player.getBounds && !player.isHit && lives >= 0 && !gamePaused) {
var portalBounds = self.getBounds();
var playerBounds = player.getBounds();
if (playerBounds.left < portalBounds.right && playerBounds.right > portalBounds.left && playerBounds.top < portalBounds.bottom && playerBounds.bottom > portalBounds.top) {
self.active = false;
// Teleport effect
LK.effects.flashScreen(0xFFFFFF, 300);
// Move player to a new position (e.g., higher platform)
var teleportY = level2Height - 100;
// Animate player teleporting
tween(player, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
player.x += 400;
player.y = teleportY;
// Reappear animation
tween(player, {
alpha: 1,
scaleX: player.refScaleX,
scaleY: player.refScaleY
}, {
duration: 300,
easing: tween.easeOut
});
}
});
}
}
// Remove portal when it's off-screen
if (self.x < -150) {
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
return false;
}
return true;
};
self.startAnimation();
return self;
});
var PortalManager = Container.expand(function () {
var self = Container.call(this);
self.portals = [];
self.portalPool = [];
self.spawnInterval = Math.floor(Math.random() * 1000) + 1000;
self.spawnCounter = 0;
self.init = function () {
self.portals = [];
self.portalPool = [];
self.spawnInterval = Math.floor(Math.random() * 1000) + 1000;
self.spawnCounter = 0;
};
self.update = function () {
// Temp PORTAIL DISABLED
return;
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
// Spawn logic
self.spawnCounter++;
if (self.portals.length < 1 && self.spawnCounter >= self.spawnInterval) {
self.spawnPortal();
self.spawnCounter = 0;
}
// Update and remove off-screen portals
for (var i = self.portals.length - 1; i >= 0; i--) {
var portal = self.portals[i];
var result = portal.x > -150;
if (result === false) {
if (portal.parent) {
portal.parent.removeChild(portal);
}
self.portals.splice(i, 1);
self.portalPool.push(portal);
}
}
};
self.spawnPortal = function () {
// Temp PORTAIL DISABLED
return;
var portal;
if (self.portalPool.length > 0) {
portal = self.portalPool.pop();
portal.visible = true;
} else {
portal = new Portal();
}
// Only spawn on platforms instead of fixed position
var availablePlatforms = [];
for (var p = 0; p < platforms.length; p++) {
if (platforms[p].x > 2048 && platforms[p].x < 2800) {
availablePlatforms.push(platforms[p]);
}
}
// If we have platforms in the spawn zone, put portal on one of them
if (availablePlatforms.length > 0) {
var randomPlatform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
portal.x = randomPlatform.x; // Place at center of platform
portal.y = randomPlatform.y - 200; // Adjust height to be above platform
} else {
// Fallback if no platforms are in the spawn zone
portal.x = 2500;
portal.y = groundLevel - 200;
}
if (self.portalPool.indexOf(portal) > -1) {
portal.reset(portal.x, portal.y);
}
self.portals.push(portal);
if (!portal.parent) {
middlegroundContainer.addChild(portal);
}
self.spawnInterval = Math.floor(Math.random() * 1000) + 1000;
self.spawnCounter = 0;
};
return self;
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 1024,
height: 1024
});
self.animate = function () {
if (!self.scale) {
self.scale = {
x: 1,
y: 1
};
}
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: self.animate
});
}
});
};
self.startGame = function () {
LK.getSound('start').play();
tween(self, {
scaleX: 0,
scaleY: 0,
y: -1000
}, {
duration: 900,
easing: tween.elasticIn,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
gameStarted = true;
enemySpawnCounter = 0;
if (player) {
player.canJump = true;
}
}
});
};
return self;
});
var WaterHole = Container.expand(function () {
var self = Container.call(this);
self.frames = [self.attachAsset('waterHoleFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
}), self.attachAsset('waterHoleFrame2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame4', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame5', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame6', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame7', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
}), self.attachAsset('waterHoleFrame8', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
})];
self.boundingBox = self.attachAsset('boundingBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 256,
height: 1024,
alpha: isDebug ? 0.5 : 0
});
self.leftBorder = self.attachAsset('waterHoleBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
x: -230
});
self.leftBorder = self.attachAsset('waterHoleBorder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1.0,
x: 230
});
self.currentFrame = 0;
self.speed = groundSpeedBase;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.alpha = 1;
self.currentFrame = 0;
for (var i = 0; i < self.frames.length; i++) {
self.frames[i].alpha = i === 0 ? 1 : 0;
}
self.animationTimer = 0;
};
self.startAnimation = function () {
self.animationTimer = 0;
};
self.animate = function () {
self.frames[self.currentFrame].alpha = 0;
self.currentFrame = (self.currentFrame + 1) % self.frames.length;
self.frames[self.currentFrame].alpha = 1;
};
self.update = function () {
self.animationTimer += 1;
if (self.animationTimer >= 6) {
self.animate();
self.animationTimer = 0;
}
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
};
self.startAnimation();
return self;
});
var WaterHoleManager = Container.expand(function () {
var self = Container.call(this);
self.waterHoles = [];
self.waterHolePool = [];
self.spawnInterval = 200;
self.spawnCounter = 0;
self.checkPlayerCollision = function (playerBounds, waterHole) {
var holeX = waterHole.x;
console.log("Player bounds:", {
left: playerBounds.left,
right: playerBounds.right,
top: playerBounds.top,
bottom: playerBounds.bottom
});
console.log("Water hole:", {
x: holeX,
boundingBoxWidth: waterHole.boundingBox.width,
groundLevel: groundLevel
});
var condition1 = playerBounds.left < holeX + waterHole.boundingBox.width / 2;
var condition2 = playerBounds.right > holeX - waterHole.boundingBox.width / 2;
var condition3 = playerBounds.bottom > groundLevel - 150;
console.log("Collision conditions:", {
horizontalOverlap1: condition1,
horizontalOverlap2: condition2,
belowThreshold: condition3,
allConditions: condition1 && condition2 && condition3
});
return condition1 && condition2 && condition3;
};
self.init = function () {
self.waterHoles = [];
self.waterHolePool = [];
self.spawnCounter = 0;
};
self.spawnWaterHole = function () {
var spawnX;
var rightmostGround;
if (ground && ground2) {
if (ground.x > ground2.x) {
rightmostGround = ground;
} else {
rightmostGround = ground2;
}
var gapStartX = rightmostGround.x;
spawnX = gapStartX + 256;
}
if (!spawnX || spawnX < 2304) {
return;
}
rightmostGround.x += 512;
var leftmostGround = ground.x < ground2.x ? ground : ground2;
if (self.waterHoles.length > 0 && self.waterHoles[0].x < -150) {
leftmostGround.x -= 512;
}
var waterHole;
var wasReused = false;
if (self.waterHolePool.length > 0) {
waterHole = self.waterHolePool.pop();
waterHole.visible = true;
wasReused = true;
} else {
waterHole = new WaterHole();
}
waterHole.x = spawnX;
waterHole.y = groundLevel + 512;
if (wasReused) {
waterHole.reset(waterHole.x, waterHole.y);
}
self.waterHoles.push(waterHole);
if (!waterHole.parent) {
middlegroundContainer.addChild(waterHole);
}
self.spawnInterval = Math.floor(Math.random() * 300) + 200;
self.spawnCounter = 0;
};
self.update = function () {
if (player && player.isHit || lives < 0) {
return;
}
self.spawnCounter++;
if (self.waterHoles.length < 3 && self.spawnCounter >= self.spawnInterval) {
self.spawnWaterHole();
}
for (var i = self.waterHoles.length - 1; i >= 0; i--) {
var waterHole = self.waterHoles[i];
if (waterHole.x < -300) {
if (waterHole.parent) {
waterHole.parent.removeChild(waterHole);
}
self.waterHoles.splice(i, 1);
waterHole.visible = false;
self.waterHolePool.push(waterHole);
}
if (player && player.getBounds) {
var distanceToWaterHole = Math.abs(player.x - waterHole.x);
console.log("Distance to hole #" + i, distanceToWaterHole);
if (distanceToWaterHole < 400) {
var playerBounds = player.getBounds();
if (self.checkPlayerCollision(playerBounds, waterHole)) {
if (!waterHole.triggered) {
waterHole.triggered = true;
if (player.canJump) {
var currentHole = waterHole;
var currentIndex = i;
player.drownPlayer(currentHole.x, function () {
// Remove the waterhole
if (currentHole.parent) {
currentHole.parent.removeChild(currentHole);
}
self.waterHoles.splice(currentIndex, 1);
currentHole.visible = false;
self.waterHolePool.push(currentHole);
// Move the left ground to the right to hide the gap
if (ground && ground2) {
var leftmostGround = ground.x < ground2.x ? ground : ground2;
leftmostGround.x += 512;
}
});
} else {
player.jump();
}
}
} else {
waterHole.triggered = false;
}
}
}
}
};
self.init();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
/****
* Global Variables
****/
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) {
return t;
}
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) {
return i;
}
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
var isDebug = false;
var level1Height;
var level2Height;
var game;
var background;
var player;
var enemies;
var enemySpawnInterval;
var enemySpawnCounter;
var startButton;
var coinManager;
var mushroomManager;
var scoreText;
var coinCounter;
var coinCount = 0;
var lives = 3;
var backgroundContainer;
var middlegroundContainer;
var foregroundContainer;
var bgClose;
var bgClose2;
var bgFar;
var bgFar2;
var platforms;
var ground;
var ground2;
var groundLevel;
var groundSpeedBase = 10;
var globalSpeed = 1.0;
var gamePaused = false;
var waterHoleManager;
var portalManager;
var gameStarted = false;
function backgroundUpdate() {
if ((!player || !player.isHit) && lives >= 0 && !gamePaused) {
bgClose.x -= 4 * globalSpeed;
bgClose2.x -= 4 * globalSpeed;
bgFar.x -= 2 * globalSpeed;
bgFar2.x -= 2 * globalSpeed;
if (bgClose.x <= -bgClose.width) {
bgClose.x = bgClose2.x + bgClose2.width;
}
if (bgClose2.x <= -bgClose2.width) {
bgClose2.x = bgClose.x + bgClose.width;
}
if (bgFar.x <= -bgFar.width) {
bgFar.x = bgFar2.x + bgFar2.width;
}
if (bgFar2.x <= -bgFar2.width) {
bgFar2.x = bgFar.x + bgFar.width;
}
ground.x -= groundSpeedBase * globalSpeed;
ground2.x -= groundSpeedBase * globalSpeed;
if (ground.x <= -ground.width) {
ground.x = ground2.x + ground2.width;
}
if (ground2.x <= -ground2.width) {
ground2.x = ground.x + ground.width;
}
}
}
function platformsUpdate() {
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
for (var i = platforms.length - 1; i >= 0; i--) {
if (platforms[i].destroyed) {
platforms.splice(i, 1);
}
}
if (platforms.length > 0) {
var lastPlatform = platforms[platforms.length - 1];
if (lastPlatform.x < 2048 + 500) {
spawnPlatform();
}
}
}
game.update = function () {
backgroundUpdate();
platformsUpdate();
if (portalManager) {
portalManager.update();
}
if (enemySpawnCounter !== 9999) {
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnInterval) {
var enemy;
if (enemyPool.length > 0) {
enemy = enemyPool.pop();
enemy.visible = true;
} else {
enemy = new Enemy();
}
enemy.x = 2500;
var spawnOnPlatform = Math.random() < 0.5 && platforms.length > 0;
if (spawnOnPlatform) {
var visiblePlatforms = [];
for (var p = 0; p < platforms.length; p++) {
if (platforms[p].x > 2200 && platforms[p].x < 2700) {
visiblePlatforms.push(platforms[p]);
}
}
if (visiblePlatforms.length > 0) {
var randomPlatform = visiblePlatforms[Math.floor(Math.random() * visiblePlatforms.length)];
enemy.y = randomPlatform.y - 150;
} else {
enemy.y = player.y;
}
} else {
enemy.y = player.y;
}
if (enemyPool.indexOf(enemy) > -1) {
enemy.reset(enemy.x, enemy.y);
}
enemies.push(enemy);
if (!enemy.parent) {
middlegroundContainer.addChild(enemy);
}
enemySpawnInterval = Math.floor(Math.random() * 150) + 50;
enemySpawnCounter = 0;
}
}
var playerBounds = player.getBounds();
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy.visible) {
continue;
}
var enemyBounds = enemy.getBounds();
if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) {
if (player.isFalling && player.velocityY > 0 && playerBounds.bottom > enemyBounds.top && playerBounds.bottom - player.velocityY < enemyBounds.top) {
if (enemy.parent) {
enemy.parent.removeChild(enemy);
}
enemies.splice(j, 1);
enemy.visible = false;
enemyPool.push(enemy);
LK.getSound('enemyStomp').play();
player.velocityY = -15;
LK.setScore(LK.getScore() + 5);
scoreText.setText(LK.getScore());
} else {
if (lives < 0) {
return;
}
player.hitPlayer();
LK.effects.flashScreen(0xff0000, 150);
if (lives <= 0) {
LK.setTimeout(function () {
LK.showGameOver();
}, 4000);
} else {
if (enemy.parent) {
enemy.parent.removeChild(enemy);
}
enemies.splice(j, 1);
enemy.visible = false;
enemyPool.push(enemy);
}
}
} else if (player.x > enemy.x && !enemy.passed) {
enemy.passed = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
}
}
};
game.down = function (x, y, obj) {
if (gameStarted) {
player.jump();
} else {
startButton.startGame();
}
};
function initializeGame() {
backgroundContainer = new Container();
middlegroundContainer = new Container();
foregroundContainer = new Container();
game.addChild(backgroundContainer);
game.addChild(middlegroundContainer);
game.addChild(foregroundContainer);
groundLevel = 2732 / 2 + 450;
bgFar = LK.getAsset('bgFar', {
anchorX: 0,
anchorY: 0
});
bgFar.x = 0;
bgFar.y = 0;
bgFar.width = 2732;
backgroundContainer.addChild(bgFar);
bgFar2 = LK.getAsset('bgFar', {
anchorX: 0,
anchorY: 0
});
bgFar2.x = bgFar.width;
bgFar2.y = 0;
bgFar2.width = 2732;
backgroundContainer.addChild(bgFar2);
bgClose = LK.getAsset('bgClose', {
anchorX: 0,
anchorY: 0
});
bgClose.x = 0;
bgClose.y = 0;
bgClose.width = 2732;
backgroundContainer.addChild(bgClose);
bgClose2 = LK.getAsset('bgClose', {
anchorX: 0,
anchorY: 0
});
bgClose2.x = bgClose.width;
bgClose2.y = 0;
bgClose2.width = 2732;
backgroundContainer.addChild(bgClose2);
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
ground.y = groundLevel;
ground.width = 2048;
middlegroundContainer.addChild(ground);
ground2 = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground2.x = ground.width;
ground2.y = groundLevel;
ground2.width = 2048;
middlegroundContainer.addChild(ground2);
player = new Player();
player.x = 2048 / 6;
player.y = groundLevel - 100;
foregroundContainer.addChild(player);
enemies = [];
enemyPool = [];
enemySpawnInterval = 100;
enemySpawnCounter = 9999;
startButton = new StartButton();
startButton.x = 2048 / 2;
startButton.y = 2732 / 2;
startButton.scale = {
x: 0,
y: 0
};
foregroundContainer.addChild(startButton);
startButton.animate();
startButton.visible = true;
player.canJump = false;
lives = 3;
coinManager = new CoinManager();
middlegroundContainer.addChild(coinManager);
mushroomManager = new MushroomManager();
middlegroundContainer.addChild(mushroomManager);
platforms = [];
level1Height = groundLevel - 450;
level2Height = level1Height - 450;
for (var i = 0; i < 2; i++) {
var platform = new Platform();
if (i === 0) {
platform.x = player.x + 800;
platform.y = level1Height;
} else {
platform.x = platforms[i - 1].x + 1200;
platform.y = level2Height;
}
platforms.push(platform);
middlegroundContainer.addChild(platform);
}
scoreText = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
LK.gui.top.addChild(scoreText);
scoreText.x = 2048 / 2;
scoreText.y = 0;
coinCounter = new CoinCounter();
coinCounter.x = -300;
coinCounter.y = 30;
LK.gui.topRight.addChild(coinCounter);
livesCounter = new LivesCounter();
livesCounter.x = 250;
livesCounter.y = 80;
LK.gui.topLeft.addChild(livesCounter);
livesCounter.updateLives(lives);
waterHoleManager = new WaterHoleManager();
middlegroundContainer.addChild(waterHoleManager);
// Initialize portal manager
portalManager = new PortalManager();
middlegroundContainer.addChild(portalManager);
LK.playMusic('bgMusic');
}
var platformPool = [];
var enemyPool = [];
function spawnPlatform() {
var platform;
if (platformPool.length > 0) {
platform = platformPool.pop();
platform.visible = true;
} else {
platform = new Platform();
}
var lastPlatform = platforms[platforms.length - 1];
var lastHeight = lastPlatform.y;
if (lastHeight === level1Height) {
platform.y = level2Height;
platform.x = lastPlatform.x + 1200;
} else {
platform.y = level1Height;
platform.x = lastPlatform.x + 1500;
}
if (Math.random() < 0.2) {
lastPlatform.x += 500;
if (platform.parent) {
platform.parent.removeChild(platform);
}
platformPool.push(platform);
return;
}
platforms.push(platform);
middlegroundContainer.addChild(platform);
}
initializeGame();