Code edit (3 edits merged)
Please save this source code
User prompt
pass a callback to drownAnim to act when anim is finished
User prompt
in drownAnim, instead of `var animLoop = true;` use a public property like self.isDrownAnimPlaying
User prompt
Now Mushrooms should only spawn on the middle of platforms
Code edit (1 edits merged)
Please save this source code
User prompt
when Clearing water holes, move back the left most ground to hide the gap left by the removed water hole
User prompt
extract all the code of drown anim end into a resetRun() function
User prompt
at end of drownAnim, remove all current coins, monsters and waterHoles to start again on a fresh screen
Code edit (1 edits merged)
Please save this source code
User prompt
When drownAnim end restore player correctly : - add a wite flash - hide playerDieFrame1 and 2 - restore player at its base position and in running state
User prompt
hide die frames when resatoring player
User prompt
in drownAnim, after player is out of screen replace it at initial position if lives > 0 and unpause game movments
User prompt
in drownPlayer() pause all movements (backgrounds, coins, monsters...) ; use a global var for that;
User prompt
in drownAnim() ,animate player drown by alterning between 'playerDieFrame2' and 'playerDieFrame3' and make player fall vertically until going out of screen bottom ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
in drownPlayer() call new empty function drownAnim() and remove playerHit() call
Code edit (1 edits merged)
Please save this source code
User prompt
fix WaterHoleManager.checkPlayerCollision() because playerBounds is in format: { left: self.x - 75, right: self.x + 75, top: self.y - 100, bottom: self.y + 100 } not x,y,w,h
Code edit (1 edits merged)
Please save this source code
User prompt
add logs to checkPlayerCollision because it doesn't work
User prompt
extract `playerBounds.x - playerBounds.width / 2 < holeX + waterHole.boundingBox.width / 2 && playerBounds.x + playerBounds.width / 2 > holeX - waterHole.boundingBox.width / 2 && playerBounds.y + playerBounds.height / 2 > groundLevel - 150` in a dedicated function
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
dans WaterHoleManager, quand player touche l'eau, appeler une nouvelle fonction player.drownPlayer() qui contiendra ``` if (lives > 0) { // Lose a life lives--; // Update lives counter livesCounter.updateLives(lives); // Player hit animation or die if no lives left if (lives <= 0) { player.die(); // Show game over after animation LK.setTimeout(function () { LK.showGameOver(); }, 4000); } else { player.hitPlayer(); } } ```
User prompt
if faut corriger ``` return { left: self.x - 75, right: self.x + 75, top: self.y - 100, bottom: self.y + 100 }; ``` pour utiliser le dimesions de self.boundingBox au lieu de valeurs fixes
/**** * 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 = coins.indexOf(self); if (coinIndex > -1) { coins.splice(coinIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; 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 = coins.indexOf(self); if (coinIndex > -1) { coins.splice(coinIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; 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 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; } self.x -= self.speed * globalSpeed; 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 = mushrooms.indexOf(self); if (mushroomIndex > -1) { mushrooms.splice(mushroomIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; 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 = mushrooms.indexOf(self); if (mushroomIndex > -1) { mushrooms.splice(mushroomIndex, 1); } if (self.parent) { self.parent.removeChild(self); } self.visible = false; mushroomPool.push(self); } }); } } }; 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 () { 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 = []; for (var i = coins.length - 1; i >= 0; i--) { if (coins[i].parent) { coins[i].parent.removeChild(coins[i]); } coins[i].visible = false; coinPool.push(coins[i]); } coins = []; 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; } 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; for (var i = 0; i < self.dieFrames.length; i++) { self.dieFrames[i].alpha = 0; } 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.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.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.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.canJump) { 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 () { 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, 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; } 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 () { 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; var animLoop = true; var loopFrame = 1; function loopDrownFrames() { 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(loopDrownFrames, 120); } } loopDrownFrames(); tween(self, { y: 4000 }, { duration: 1500, easing: tween.easeIn, onFinish: function onFinish() { animLoop = false; if (lives > 0) { self.resetRun(); } } }); }; self.drownPlayer = function () { gamePaused = true; self.drownAnim(); if (lives > 0) { lives--; livesCounter.updateLives(lives); if (lives <= 0) { player.die(); LK.setTimeout(function () { LK.showGameOver(); }, 4000); } } }; 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 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.down = function (x, y, obj) { LK.getSound('start').play(); tween(self, { scale: 0.9 }, { duration: 100, easing: tween.easeOut }); }; self.up = function (x, y, obj) { tween(self, { scale: 0, alpha: 0 }, { duration: 300, easing: tween.elasticIn, onFinish: function onFinish() { if (self.parent) { self.parent.removeChild(self); } 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 playerBounds = player.getBounds(); if (self.checkPlayerCollision(playerBounds, waterHole)) { if (!waterHole.triggered) { waterHole.triggered = true; if (player.canJump) { player.drownPlayer(); } 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 = true; var level1Height; var level2Height; var game; var background; var player; var enemies; var enemySpawnInterval; var enemySpawnCounter; var startButton; var coins = []; var coinPool = []; var mushrooms = []; var mushroomPool = []; var mushroomSpawnInterval = 500; 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; 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 (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()); } } if (coins.length < 10 && LK.ticks % Math.floor(Math.random() * 100 + 50) === 0) { var coin; if (coinPool.length > 0) { coin = 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 (coinPool.indexOf(coin) > -1) { coin.reset(coin.x, coin.y); } coins.push(coin); if (!coin.parent) { middlegroundContainer.addChild(coin); } } if (mushrooms.length < 2 && LK.ticks % mushroomSpawnInterval === 0) { var mushroom; if (mushroomPool.length > 0) { mushroom = mushroomPool.pop(); mushroom.visible = true; } else { mushroom = new Mushroom(); } mushroom.x = 2500; var randomMushroomHeight = Math.random(); if (randomMushroomHeight < 0.33) { mushroom.y = groundLevel - 100; } else if (randomMushroomHeight < 0.66) { mushroom.y = level1Height - 100; } else { mushroom.y = level2Height - 100; } if (mushroomPool.indexOf(mushroom) > -1) { mushroom.reset(mushroom.x, mushroom.y); } mushrooms.push(mushroom); if (!mushroom.parent) { middlegroundContainer.addChild(mushroom); } mushroomSpawnInterval = Math.floor(Math.random() * 500) + 500; } }; game.down = function (x, y, obj) { player.jump(); }; 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; coins = []; coinPool = []; mushrooms = []; mushroomPool = []; 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); 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();
===================================================================
--- original.js
+++ change.js
@@ -5,20 +5,18 @@
/****
* Classes
****/
-// Define a class for coins with 8-frame animation
var Coin = Container.expand(function () {
var self = Container.call(this);
- // Create and attach all 8 coin frames
self.frames = [self.attachAsset('coinFrame1', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 1 // First frame visible initially
+ alpha: 1
}), self.attachAsset('coinFrame2', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 0 // Hidden initially
+ alpha: 0
}), self.attachAsset('coinFrame3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
@@ -43,36 +41,28 @@
anchorY: 0.5,
alpha: 0
})];
self.currentFrame = 0;
- self.speed = 10; // Horizontal movement speed
+ self.speed = 10;
self.collected = false;
- self.animationSpeed = 4; // Frames to wait before changing animation frame
- // Method to reset coin for reuse from pool
+ self.animationSpeed = 4;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.collected = false;
self.alpha = 1;
- // Reset animation state
self.currentFrame = 0;
- // Show first frame, hide others
for (var i = 0; i < self.frames.length; i++) {
self.frames[i].alpha = i === 0 ? 1 : 0;
}
self.animationTimer = 0;
};
- // Initialize animation
self.startAnimation = function () {
- // No need to call animate directly, it will be called via update
self.animationTimer = 0;
};
self.animate = function () {
- // Hide current frame
self.frames[self.currentFrame].alpha = 0;
- // Move to next frame
self.currentFrame = (self.currentFrame + 1) % self.frames.length;
- // Show next frame
self.frames[self.currentFrame].alpha = 1;
};
self.getBounds = function () {
return {
@@ -82,66 +72,52 @@
bottom: self.y + 40
};
};
self.update = function () {
- // Handle animation timing with frame counter
self.animationTimer += 1;
if (self.animationTimer >= 6) {
- // 6 frames ≈ 100ms at 60fps
self.animate();
self.animationTimer = 0;
}
- // Move coin from right to left only if player is not hit, lives >= 0, and game is not paused
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
- // Remove coin when it goes off-screen
if (self.x < -100) {
- // Remove from coins array before returning to pool
var coinIndex = coins.indexOf(self);
if (coinIndex > -1) {
coins.splice(coinIndex, 1);
}
- // Return to pool instead of destroying
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
coinPool.push(self);
}
- // Check if player collected the coin (intersection with player)
- // Only allow collection if player can jump (start button was pressed)
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;
- // Play coin sound when collected
LK.getSound('coin').play();
- // Increment score immediately
LK.setScore(LK.getScore() + 10);
if (scoreText) {
scoreText.setText(LK.getScore());
}
- // Update coin counter immediately - increment coins by 1 (independent from score)
if (coinCounter) {
- coinCount++; // Increment coin count
+ coinCount++;
coinCounter.updateCount(coinCount);
}
- // Coin collection animation
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
- // Remove from coins array before returning to pool
var coinIndex = coins.indexOf(self);
if (coinIndex > -1) {
coins.splice(coinIndex, 1);
}
- // Return to pool instead of destroying
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
@@ -150,25 +126,21 @@
});
}
}
};
- // Start the animation when created
self.startAnimation();
return self;
});
-// Define a class for the coin counter display
var CoinCounter = Container.expand(function () {
var self = Container.call(this);
- // Create and attach coin icon
var coinIcon = self.attachAsset('coinFrame1', {
anchorX: 0.5,
anchorY: 0.5,
x: 220,
y: 50,
width: 96,
height: 96
});
- // Create 3-digit display (hundreds, tens, units)
self.hundreds = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
@@ -191,35 +163,27 @@
self.units.anchor.set(0.5);
self.units.x = 120;
self.units.y = 50;
self.addChild(self.units);
- // Method to update the counter display
self.updateCount = function (count) {
- // Ensure count is between 0-999
count = Math.min(999, Math.max(0, count));
- // Calculate digits
var h = Math.floor(count / 100);
var t = Math.floor(count % 100 / 10);
var u = count % 10;
- // Update text display
self.hundreds.setText(h.toString());
self.tens.setText(t.toString());
self.units.setText(u.toString());
};
- // Initialize with 0
self.updateCount(0);
return self;
});
-// Define a class for enemies
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
- // Add pulsing animation
self.startAnimation = function () {
- // Create a subtle x-axis pulse animation with faster timing
tween(self, {
scaleX: 1.15
}, {
duration: 200,
@@ -234,54 +198,45 @@
});
}
});
};
- self.speed = 15; // Plus rapide que le sol (10) pour qu'ils avancent vers la gauche
+ self.speed = 15;
self.velocityY = 0;
- self.gravity = 0.7; // Même gravité que le joueur
- self.currentPlatform = null; // Plateforme actuelle sur laquelle l'ennemi se trouve
- // Reset method to reuse enemy
+ 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;
- // Start the animation when enemy is reset
self.startAnimation();
};
self.update = function () {
- // Only move if player is not hit, lives >= 0, and game is not paused
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
self.x -= self.speed * globalSpeed;
- // Vérifier si l'ennemi est toujours sur sa plateforme actuelle
if (self.currentPlatform) {
var enemyBounds = self.getBounds();
var platformBounds = {
left: self.currentPlatform.x - 500,
right: self.currentPlatform.x + 500
};
- // Si l'ennemi sort de la plateforme, il commence à tomber
if (enemyBounds.left > platformBounds.right || enemyBounds.right < platformBounds.left) {
self.currentPlatform = null;
}
}
- // Appliquer la gravité si l'ennemi n'est pas sur une plateforme
if (!self.currentPlatform) {
self.velocityY += self.gravity * globalSpeed;
self.y += self.velocityY * globalSpeed;
}
- // Vérifier collision avec le sol
- // Adjust Y position to account for enemy's height (anchor is 0.5), similar to player offset
- var enemyVisualBottomOffset = 75; // Half of enemy height (150 / 2)
+ var enemyVisualBottomOffset = 75;
if (self.y >= groundLevel - enemyVisualBottomOffset) {
- self.y = groundLevel - enemyVisualBottomOffset; // Set enemy bottom to ground level
+ self.y = groundLevel - enemyVisualBottomOffset;
self.velocityY = 0;
- self.currentPlatform = null; // L'ennemi est sur le sol, pas sur une plateforme
+ self.currentPlatform = null;
}
- // Vérifier collision avec les plateformes seulement si l'ennemi tombe
if (self.velocityY > 0) {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var enemyBounds = self.getBounds();
@@ -290,28 +245,24 @@
right: platform.x + 500,
top: platform.y - 50,
bottom: platform.y + 50
};
- // Si l'ennemi atterrit sur une plateforme
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; // Mémoriser la plateforme actuelle
+ self.currentPlatform = platform;
break;
}
}
}
if (self.x < -50) {
- // Instead of destroying, return to pool
if (self.parent) {
self.parent.removeChild(self);
}
- // Remove from enemies array
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
}
- // Add to pool for reuse
self.visible = false;
enemyPool.push(self);
}
};
@@ -322,57 +273,43 @@
top: self.y - 50,
bottom: self.y + 50
};
};
- // Start animation when enemy is created
self.startAnimation();
return self;
});
-// Define a class for lives counter display
var LivesCounter = Container.expand(function () {
var self = Container.call(this);
- // Create heart icons for lives
self.hearts = [];
- // Number of heart icons to create
var maxHearts = 3;
- // Create heart icons using coin assets (since we don't have heart assets)
for (var i = 0; i < maxHearts; i++) {
var heart = self.attachAsset('playerRunFrame2', {
anchorX: 0.5,
anchorY: 0.5,
x: i * 70,
- // Space hearts horizontally
y: 0,
width: 60,
height: 60
});
self.hearts.push(heart);
}
- // Method to update lives display
self.updateLives = function (livesCount) {
- // Ensure lives count is between 0-3
livesCount = Math.min(maxHearts, Math.max(0, livesCount));
- // Show or hide hearts based on current lives
for (var i = 0; i < maxHearts; i++) {
self.hearts[i].visible = i < livesCount;
}
};
- // Initialize with 3 lives
self.updateLives(3);
return self;
});
-// Define StartButton class
-// Define Mushroom class for power-up
var Mushroom = Container.expand(function () {
var self = Container.call(this);
- // Create and attach mushroom asset
var mushroomGraphics = self.attachAsset('mushroom', {
anchorX: 0.5,
anchorY: 0.5
});
- self.speed = 10; // Same speed as platforms
+ self.speed = 10;
self.collected = false;
- // Method to reset mushroom for reuse from pool
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.collected = false;
@@ -386,58 +323,47 @@
bottom: self.y + 45
};
};
self.update = function () {
- // Move mushroom from right to left only if player is not hit, lives >= 0, and game is not paused
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
- // Remove mushroom when it goes off-screen
if (self.x < -100) {
- // Remove from mushrooms array before returning to pool
var mushroomIndex = mushrooms.indexOf(self);
if (mushroomIndex > -1) {
mushrooms.splice(mushroomIndex, 1);
}
- // Return to pool instead of destroying
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
mushroomPool.push(self);
}
- // Check if player collected the mushroom
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;
- // Change player morph state if currently in DEFAULT state
if (player.morphState === 0) {
- // Play mushroom eat sound when player is in DEFAULT state
LK.getSound('mushroomEat').play();
player.morphState = 1;
player.updateRefScale();
}
- // Add 100 points
LK.setScore(LK.getScore() + 100);
if (scoreText) {
scoreText.setText(LK.getScore());
}
- // Collection animation
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
- // Remove from mushrooms array before returning to pool
var mushroomIndex = mushrooms.indexOf(self);
if (mushroomIndex > -1) {
mushrooms.splice(mushroomIndex, 1);
}
- // Return to pool instead of destroying
if (self.parent) {
self.parent.removeChild(self);
}
self.visible = false;
@@ -448,9 +374,8 @@
}
};
return self;
});
-// Define a class for platforms
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
@@ -458,61 +383,48 @@
});
self.speed = 10;
self.passed = false;
self.update = function () {
- // Only move if player is not hit, lives >= 0, and game is not paused
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
self.x -= self.speed * globalSpeed;
if (self.x < -500) {
- // Instead of destroying, remove from parent and add to pool
if (self.parent) {
self.parent.removeChild(self);
}
- // Remove from platforms array
var index = platforms.indexOf(self);
if (index > -1) {
platforms.splice(index, 1);
}
- // Add to pool for reuse
self.visible = false;
platformPool.push(self);
}
};
return self;
});
-// Define a class for the player character
var Player = Container.expand(function () {
var self = Container.call(this);
- // Add morphState property to track player state
- // 0 - DEFAULT, 1 - BIG, 2 - FIRE
self.morphState = 0;
- // Add reference scale properties
self.refScaleX = 0.5;
self.refScaleY = 0.5;
- // Function to reset player when respawning
self.resetRun = function () {
- // Remove all current enemies, coins, and water holes to start fresh
- // Clear enemies
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 = [];
- // Clear coins
for (var i = coins.length - 1; i >= 0; i--) {
if (coins[i].parent) {
coins[i].parent.removeChild(coins[i]);
}
coins[i].visible = false;
coinPool.push(coins[i]);
}
coins = [];
- // Clear water holes
if (waterHoleManager && waterHoleManager.waterHoles) {
for (var i = waterHoleManager.waterHoles.length - 1; i >= 0; i--) {
var waterHole = waterHoleManager.waterHoles[i];
if (waterHole.parent) {
@@ -523,75 +435,58 @@
}
waterHoleManager.waterHoles = [];
waterHoleManager.spawnCounter = 0;
}
- // Add white screen flash when restoring player
LK.effects.flashScreen(0xFFFFFF, 600);
- // Reset player position to initial state
- self.x = 2048 / 6; // Same as initial position in initializeGame
+ self.x = 2048 / 6;
self.y = groundLevel - 100;
self.velocityY = 0;
self.isJumping = false;
self.currentPlatform = null;
- // Reset visual state
self.shadow.alpha = 0.5;
- // Hide all die frames
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
- // Show running frame
self.runFrames[self.currentRunFrame].alpha = 1;
- // Unpause game movements
gamePaused = false;
};
- // Initialize player with appropriate scale based on morphState
self.init = function () {
self.updateRefScale();
};
- // Update player reference scale based on morphState
self.updateRefScale = function () {
- // Set player scale based on morphState
- // Store current scale before updating
var oldScaleY = self.refScaleY;
- // Calculate current offset from ground
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;
}
- // Calculate new offset for the updated scale
var newVisualBottomOffset = self.playerHeight * self.refScaleY / 2;
- // Adjust player position based on current position
if (!self.isJumping) {
if (self.currentPlatform) {
- // Adjust position on platform
self.y = self.currentPlatform.y - newVisualBottomOffset;
} else {
- // Adjust position on ground
self.y = groundLevel - newVisualBottomOffset;
}
}
tween(self.scale, {
x: self.refScaleX,
y: self.refScaleY
}, {
duration: 1000,
- // Animation duration in milliseconds
easing: tween.easeOut
});
};
- // Add shadow beneath player
self.shadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
scaleX: 2.0,
scaleY: 0.4,
tint: 0x000000,
- y: 200 // Position shadow below player
+ y: 200
});
self.runFrames = [self.attachAsset('playerRunFrame1', {
anchorX: 0.5,
anchorY: 0.5,
@@ -606,17 +501,16 @@
alpha: 0
})];
self.currentRunFrame = 0;
self.speed = 5;
- self.jumpHeight = 35; // Réduire légèrement la hauteur de saut
+ self.jumpHeight = 35;
self.isJumping = false;
self.velocityY = 0;
self.isFalling = false;
self.currentPlatform = null;
- self.playerHeight = 400; // Hauteur du sprite du joueur
- self.canJump = false; // Flag to control if player can jump (only after start button is clicked)
- self.isHit = false; // Track if player is in hit state
- // Add bounding box for collision detection visualization
+ self.playerHeight = 400;
+ self.canJump = false;
+ self.isHit = false;
self.boundingBox = self.attachAsset('boundingBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
@@ -625,14 +519,14 @@
});
self.hitFrame = self.attachAsset('playerHitFrame1', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 0 // Hidden initially
+ alpha: 0
});
self.jumpFrame = self.attachAsset('playerJumpFrame', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 0 // Hide the jump frame by setting alpha to 0
+ alpha: 0
});
self.getBounds = function () {
return {
left: self.x - 75,
@@ -641,44 +535,35 @@
bottom: self.y + 100
};
};
self.update = function () {
- // If player is in hit state or lives are less than zero, don't process movement
if (self.isHit || lives < 0) {
return;
}
- // Update shadow position based on player's height from the ground
if (self.isJumping) {
- // Reduce shadow opacity based on height and make it smaller when jumping
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 {
- // Reset shadow when on ground
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; // Increase gravity for faster fall without changing jump height
+ self.velocityY += 2.0 * globalSpeed;
self.isFalling = self.velocityY > 0;
- self.jumpFrame.alpha = 1; // While jumping, switch to the jump frame
- self.runFrames[self.currentRunFrame].alpha = 0; // Hide the player asset when jumping
- // Check for platform collision
+ self.jumpFrame.alpha = 1;
+ self.runFrames[self.currentRunFrame].alpha = 0;
self.checkPlatformCollision();
- // Check for ground collision
- // Use visual bottom offset for correct ground alignment based on scale
var visualBottomOffset = self.playerHeight * self.refScaleY / 2;
if (self.y >= groundLevel - visualBottomOffset && !self.currentPlatform) {
- // Ground level - adjust y based on current scale
self.y = groundLevel - visualBottomOffset;
self.isJumping = false;
self.velocityY = 0;
- self.jumpFrame.alpha = 0; // When not jumping, switch back to the normal frame
- self.runFrames[self.currentRunFrame].alpha = 1; // Show the player asset when not jumping
- // Add a bounce effect relative to refScale
+ self.jumpFrame.alpha = 0;
+ self.runFrames[self.currentRunFrame].alpha = 1;
tween(self, {
scaleX: self.refScaleX * 1.2,
scaleY: self.refScaleY * 0.8
}, {
@@ -695,45 +580,39 @@
}
});
}
} else {
- // Check if player is still on the platform
if (self.currentPlatform) {
var platformBounds = {
left: self.currentPlatform.x - 500,
right: self.currentPlatform.x + 500
};
var playerBounds = self.getBounds();
- // If player is no longer on the platform, start falling
if (playerBounds.left > platformBounds.right || playerBounds.right < platformBounds.left) {
self.isJumping = true;
- self.velocityY = 0.1; // Start with a small downward velocity
+ self.velocityY = 0.1;
self.isFalling = true;
self.currentPlatform = null;
self.jumpFrame.alpha = 1;
self.runFrames[self.currentRunFrame].alpha = 0;
}
}
- // Handle running animation
if (LK.ticks % 5 === 0) {
- // Fine-tuned interval for balanced and natural pace
- // Adjusted interval for balanced pace
- self.runFrames[self.currentRunFrame].alpha = 0; // Hide current frame
- self.currentRunFrame = (self.currentRunFrame + 1) % self.runFrames.length; // Switch to next frame
- self.runFrames[self.currentRunFrame].alpha = 1; // Show next frame
+ 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.canJump) {
self.isJumping = true;
- self.velocityY = -self.jumpHeight * 1.5; // Increase initial jump velocity for a faster jump
- self.jumpFrame.alpha = 1; // Make jump frame visible
- LK.getSound('jump').play(); // Play jump sound
+ self.velocityY = -self.jumpHeight * 1.5;
+ self.jumpFrame.alpha = 1;
+ LK.getSound('jump').play();
self.currentPlatform = null;
}
};
- // Add die animation frames
self.dieFrames = [self.attachAsset('playerDieFrame1', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
@@ -746,208 +625,151 @@
anchorY: 0.5,
alpha: 0
})];
self.die = function () {
- // Hide all other frames
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
self.jumpFrame.alpha = 0;
self.hitFrame.alpha = 0;
- // Hide shadow during die animation
self.shadow.alpha = 0;
- // Play loose sound when die animation starts
LK.getSound('loose').play();
LK.getSound('loose2').play();
- // Stop background music
LK.stopMusic();
- // Play die animation sequence
var currentFrame = 0;
function showNextFrame() {
- // Hide previous frame if exists
if (currentFrame > 0) {
self.dieFrames[currentFrame - 1].alpha = 0;
}
- // Show current frame
self.dieFrames[currentFrame].alpha = 1;
currentFrame++;
- // After last frame, start movement animation
if (currentFrame < self.dieFrames.length) {
LK.setTimeout(showNextFrame, 100);
} else {
- // After last frame, start movement animation
startDeathMovement();
}
}
- // Start death movement animation
function startDeathMovement() {
- // Start looping animation between frames 2 and 3
var animLoop = true;
- var loopFrame = 1; // Start with frame 2 (index 1)
+ var loopFrame = 1;
function loopDieFrames() {
- // Hide all frames
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
- // Show current frame
self.dieFrames[loopFrame].alpha = 1;
- // Toggle between frames 2 and 3 (index 1 and 2)
loopFrame = loopFrame === 1 ? 2 : 1;
- // Continue loop if animation is active
if (animLoop) {
LK.setTimeout(loopDieFrames, 120);
}
}
- // Start the loop animation
loopDieFrames();
- // First tween: move player up to y=512 with bounce effect and scale up to 4x
tween(self, {
y: self.y - 1024,
scaleX: 5,
scaleY: 5
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
- // Second tween: move player down out of screen
tween(self, {
- y: 4000 // Beyond screen bottom
+ y: 4000
}, {
duration: 1200,
easing: tween.easeIn,
onFinish: function onFinish() {
- // Stop the animation loop when player is off screen
animLoop = false;
}
});
}
});
}
- // Start animation
showNextFrame();
};
self.hitPlayer = function () {
if (self.isHit) {
return;
- } // Already in hit state
- // Set hit state
+ }
self.isHit = true;
- // Hide all other frames
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
self.jumpFrame.alpha = 0;
if (self.morphState === 0) {
- // Player touched enemy from side or bottom - lose a life
lives--;
- // Update lives counter
livesCounter.updateLives(lives);
}
- // Show hit frame
self.hitFrame.alpha = 1;
if (lives <= 0) {
- // Call die animation instead of returning
self.die();
return;
}
- // Check if player is in BIG state (morphState 1)
if (self.morphState === 1) {
- // Play hit sound
LK.getSound('hit').play();
- // Transform player back to DEFAULT state instead of losing a life
self.morphState = 0;
self.updateRefScale();
- // Set a timeout to reset player after hit animation
LK.setTimeout(function () {
- // Hide hit frame
self.hitFrame.alpha = 0;
- // Show appropriate frame based on state
if (self.isJumping) {
self.jumpFrame.alpha = 1;
} else {
self.runFrames[self.currentRunFrame].alpha = 1;
}
- // Reset hit state
self.isHit = false;
}, 330);
} else {
- // Normal hit behavior for DEFAULT state
- // Play hit sound
LK.getSound('hitSmall').play();
- // Set a timeout to reset player after 600ms
LK.setTimeout(function () {
- // Hide hit frame
self.hitFrame.alpha = 0;
- // Show appropriate frame based on state
if (self.isJumping) {
self.jumpFrame.alpha = 1;
} else {
self.runFrames[self.currentRunFrame].alpha = 1;
}
- // Reset hit state
self.isHit = false;
}, 330);
}
};
- // Method to handle drowning in water holes
self.drownAnim = function () {
- // Hide all other frames
for (var i = 0; i < self.runFrames.length; i++) {
self.runFrames[i].alpha = 0;
}
self.jumpFrame.alpha = 0;
self.hitFrame.alpha = 0;
- // Hide shadow during drowning animation
self.shadow.alpha = 0;
- // Start alternating between frames 2 and 3
var animLoop = true;
- var loopFrame = 1; // Start with frame 2 (index 1)
+ var loopFrame = 1;
function loopDrownFrames() {
- // Hide all frames
for (var i = 0; i < self.dieFrames.length; i++) {
self.dieFrames[i].alpha = 0;
}
- // Show current frame
self.dieFrames[loopFrame].alpha = 1;
- // Toggle between frames 2 and 3 (index 1 and 2)
loopFrame = loopFrame === 1 ? 2 : 1;
- // Continue loop if animation is active
if (animLoop) {
LK.setTimeout(loopDrownFrames, 120);
}
}
- // After last frame, start movement animation
loopDrownFrames();
- // Fall vertically to bottom of screen
tween(self, {
- y: 4000 // Beyond screen bottom
+ y: 4000
}, {
duration: 1500,
easing: tween.easeIn,
onFinish: function onFinish() {
- // Stop the animation loop when player is off screen
animLoop = false;
- // Check if player has lives remaining
if (lives > 0) {
- // Call resetRun function to reset game state
self.resetRun();
}
}
});
};
self.drownPlayer = function () {
- // Pause all game movements
gamePaused = true;
self.drownAnim();
if (lives > 0) {
- // Lose a life
lives--;
- // Update lives counter
livesCounter.updateLives(lives);
- // Player hit animation or die if no lives left
if (lives <= 0) {
player.die();
- // Show game over after animation
LK.setTimeout(function () {
LK.showGameOver();
}, 4000);
}
@@ -962,23 +784,18 @@
top: platform.y - 50,
bottom: platform.y + 50
};
var playerBounds = self.getBounds();
- // Check if player is above the platform and falling
- // Adjust collision detection for high globalSpeed values
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) {
- // Land on the platform
- // Adjust player Y based on current scale to ensure visual bottom aligns with platform top
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;
- // Add a bounce effect relative to refScale
tween(self, {
scaleX: self.refScaleX * 1.2,
scaleY: self.refScaleY * 0.8
}, {
@@ -1002,18 +819,15 @@
self.init();
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
- // Create and attach start button asset
var buttonGraphics = self.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 1024,
height: 1024
});
- // Add pulsing animation effect
self.animate = function () {
- // Initialize scale object if it doesn't exist
if (!self.scale) {
self.scale = {
x: 1,
y: 1
@@ -1036,58 +850,47 @@
});
}
});
};
- // Handle button press
self.down = function (x, y, obj) {
- // Play sound effect when button is pressed
LK.getSound('start').play();
- // Trigger button pressed animation
tween(self, {
scale: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
- // Handle button release
self.up = function (x, y, obj) {
- // Play start sound when button is clicked
- // Hide the button with a scale animation
tween(self, {
scale: 0,
alpha: 0
}, {
duration: 300,
easing: tween.elasticIn,
onFinish: function onFinish() {
- // Remove button after animation
if (self.parent) {
self.parent.removeChild(self);
}
- // Start enemy spawning
enemySpawnCounter = 0;
- // Allow player to jump now
if (player) {
player.canJump = true;
}
}
});
};
return self;
});
-// Define a class for water hole with 8-frame animation
var WaterHole = Container.expand(function () {
var self = Container.call(this);
- // Create and attach all 8 water hole frames
self.frames = [self.attachAsset('waterHoleFrame1', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 1 // First frame visible initially
+ alpha: 1
}), self.attachAsset('waterHoleFrame2', {
anchorX: 0.5,
anchorY: 0.5,
- alpha: 0 // Hidden initially
+ alpha: 0
}), self.attachAsset('waterHoleFrame3', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
@@ -1111,9 +914,8 @@
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
})];
- // Add bounding box for collision detection visualization
self.boundingBox = self.attachAsset('boundingBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 256,
@@ -1132,64 +934,48 @@
scaleX: -1.0,
x: 230
});
self.currentFrame = 0;
- self.speed = groundSpeedBase; // Use base ground speed for synchronization
- // Method to reset water hole for reuse
+ self.speed = groundSpeedBase;
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.alpha = 1;
- // Reset animation state
self.currentFrame = 0;
- // Show first frame, hide others
for (var i = 0; i < self.frames.length; i++) {
self.frames[i].alpha = i === 0 ? 1 : 0;
}
self.animationTimer = 0;
};
- // Initialize animation
self.startAnimation = function () {
- // No need to call animate directly, it will be called via update
self.animationTimer = 0;
};
self.animate = function () {
- // Hide current frame
self.frames[self.currentFrame].alpha = 0;
- // Move to next frame
self.currentFrame = (self.currentFrame + 1) % self.frames.length;
- // Show next frame
self.frames[self.currentFrame].alpha = 1;
};
self.update = function () {
- // Handle animation timing with frame counter
self.animationTimer += 1;
if (self.animationTimer >= 6) {
- // 6 frames ≈ 100ms at 60fps
self.animate();
self.animationTimer = 0;
}
- // Move water hole from right to left only if player is not hit, lives >= 0, and game is not paused
if ((!player || !player.isHit && lives >= 0) && !gamePaused) {
self.x -= self.speed * globalSpeed;
}
};
- // Start the animation when created
self.startAnimation();
return self;
});
-// Define WaterHoleManager class to handle water hole spawning and pooling
var WaterHoleManager = Container.expand(function () {
var self = Container.call(this);
- // Properties to manage water holes
- self.waterHoles = []; // Active water holes
- self.waterHolePool = []; // Pool for reuse
- self.spawnInterval = 200; // Base spawn interval
- self.spawnCounter = 0; // Counter for spawn timing
- // Function to check if player is colliding with water hole
+ self.waterHoles = [];
+ self.waterHolePool = [];
+ self.spawnInterval = 200;
+ self.spawnCounter = 0;
self.checkPlayerCollision = function (playerBounds, waterHole) {
var holeX = waterHole.x;
- // Log player and water hole positions and dimensions
console.log("Player bounds:", {
left: playerBounds.left,
right: playerBounds.right,
top: playerBounds.top,
@@ -1199,9 +985,8 @@
x: holeX,
boundingBoxWidth: waterHole.boundingBox.width,
groundLevel: groundLevel
});
- // Log individual collision conditions
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:", {
@@ -1209,136 +994,98 @@
horizontalOverlap2: condition2,
belowThreshold: condition3,
allConditions: condition1 && condition2 && condition3
});
- // Simple AABB collision check using player's boundingBox in the right format
return condition1 && condition2 && condition3;
};
- // Initialize the manager
self.init = function () {
self.waterHoles = [];
self.waterHolePool = [];
self.spawnCounter = 0;
};
- // Spawn a new water hole
self.spawnWaterHole = function () {
- // Determine the spawn position based on the rightmost ground piece
var spawnX;
var rightmostGround;
if (ground && ground2) {
if (ground.x > ground2.x) {
rightmostGround = ground;
} else {
rightmostGround = ground2;
}
- // Calculate the X position for the water hole: the start of the rightmost ground piece + half the gap width
- var gapStartX = rightmostGround.x; // Position before offset
- spawnX = gapStartX + 256; // Center of the 512 gap
+ var gapStartX = rightmostGround.x;
+ spawnX = gapStartX + 256;
}
if (!spawnX || spawnX < 2304) {
return;
}
- // Apply 512px offset to the rightmost ground piece AFTER calculating spawnX
rightmostGround.x += 512;
- // Find the leftmost ground piece and move it back to fill the gap when a water hole is removed
var leftmostGround = ground.x < ground2.x ? ground : ground2;
- // Move the leftmost ground piece to cover the gap that will be left by the removed water hole
if (self.waterHoles.length > 0 && self.waterHoles[0].x < -150) {
leftmostGround.x -= 512;
}
var waterHole;
- // Try to reuse from pool first
var wasReused = false;
if (self.waterHolePool.length > 0) {
waterHole = self.waterHolePool.pop();
waterHole.visible = true;
wasReused = true;
} else {
waterHole = new WaterHole();
}
- // Position water hole
waterHole.x = spawnX;
- // Position water hole vertically. Its visual top should align with groundLevel.
- // Anchor is 0.5, 0.5 and height is 1024. Center should be at groundLevel + 512.
waterHole.y = groundLevel + 512;
- // If water hole was reused from pool, reset its state
if (wasReused) {
waterHole.reset(waterHole.x, waterHole.y);
- } //{ax} // Keep original comment ID for context
- // Add to tracking array and game container
+ }
self.waterHoles.push(waterHole);
- // Only add to container if not already a child
if (!waterHole.parent) {
middlegroundContainer.addChild(waterHole);
}
- // Note: The ground offset logic is now integrated above, before positioning the water hole.
- // The block below is no longer needed here. //{aC} // Keep original comment ID for context
- // Randomize next spawn interval
self.spawnInterval = Math.floor(Math.random() * 300) + 200;
self.spawnCounter = 0;
};
- // Update all water holes
self.update = function () {
- // Don't spawn if player is hit or game over
if (player && player.isHit || lives < 0) {
return;
}
- // Increment spawn counter
self.spawnCounter++;
- // Check if it's time to spawn a new water hole
if (self.waterHoles.length < 3 && self.spawnCounter >= self.spawnInterval) {
self.spawnWaterHole();
}
- // Process all active water holes
for (var i = self.waterHoles.length - 1; i >= 0; i--) {
var waterHole = self.waterHoles[i];
- // Check if water hole is off-screen
if (waterHole.x < -300) {
- // Return to pool
if (waterHole.parent) {
waterHole.parent.removeChild(waterHole);
}
self.waterHoles.splice(i, 1);
waterHole.visible = false;
self.waterHolePool.push(waterHole);
}
- // Check collision with player
if (player && player.getBounds) {
var playerBounds = player.getBounds();
- // Use the extracted collision check function
if (self.checkPlayerCollision(playerBounds, waterHole)) {
- // Only trigger once
if (!waterHole.triggered) {
waterHole.triggered = true;
- // If player can jump (game started), handle deadly water
if (player.canJump) {
- // Player dies in water
player.drownPlayer();
} else {
- // Game not started yet - make player jump over waterhole
player.jump();
- // player.isJumping = true;
- // player.velocityY = -player.jumpHeight * 1.5;
- // player.jumpFrame.alpha = 1; // Make jump frame visible
- // LK.getSound('jump').play(); // Play jump sound
- // player.currentPlatform = null;
}
}
} else {
waterHole.triggered = false;
}
}
}
};
- // Initialize the manager
self.init();
return self;
});
/****
* Initialize Game
****/
-// Initialize game
var game = new LK.Game({
backgroundColor: 0x000000
});
@@ -1381,27 +1128,27 @@
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
-var isDebug = true; // Global debug flag
+var isDebug = true;
var level1Height;
var level2Height;
var game;
var background;
var player;
var enemies;
var enemySpawnInterval;
var enemySpawnCounter;
-var startButton; // Variable for start button
-var coins = []; // Initialize an empty array for tracking active coins
-var coinPool = []; // Initialize coin pool for reusing instances
-var mushrooms = []; // Initialize array for tracking active mushrooms
-var mushroomPool = []; // Initialize mushroom pool for reusing instances
-var mushroomSpawnInterval = 500; // Control how often mushrooms spawn
+var startButton;
+var coins = [];
+var coinPool = [];
+var mushrooms = [];
+var mushroomPool = [];
+var mushroomSpawnInterval = 500;
var scoreText;
var coinCounter;
-var coinCount = 0; // Add global coin count variable
-var lives = 3; // Add global lives counter
+var coinCount = 0;
+var lives = 3;
var backgroundContainer;
var middlegroundContainer;
var foregroundContainer;
var bgClose;
@@ -1411,22 +1158,18 @@
var platforms;
var ground;
var ground2;
var groundLevel;
-var groundSpeedBase = 10; // Base speed for ground elements
-var globalSpeed = 1.0; // Control the overall game speed (1.0 = normal)
-var gamePaused = false; // Global variable to track if game is paused
-var waterHoleManager; // Manager for water holes
-// Function to handle background updates
+var groundSpeedBase = 10;
+var globalSpeed = 1.0;
+var gamePaused = false;
+var waterHoleManager;
function backgroundUpdate() {
- // Only move backgrounds if player is not hit, lives >= 0, and game is not paused
if ((!player || !player.isHit) && lives >= 0 && !gamePaused) {
- // Parallax scrolling
- bgClose.x -= 4 * globalSpeed; // Increase speed for close background
- bgClose2.x -= 4 * globalSpeed; // Move the duplicate at the same speed
- bgFar.x -= 2 * globalSpeed; // Increase speed for far background
- bgFar2.x -= 2 * globalSpeed; // Move the duplicate at the same speed
- // Repeat backgrounds infinitely
+ 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) {
@@ -1437,141 +1180,106 @@
}
if (bgFar2.x <= -bgFar2.width) {
bgFar2.x = bgFar.x + bgFar.width;
}
- // Scroll ground
- ground.x -= groundSpeedBase * globalSpeed; // Use base ground speed
- ground2.x -= groundSpeedBase * globalSpeed; // Use base ground speed
+ 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 to handle platform updates
function platformsUpdate() {
- // Only process platforms if player is not hit, lives >= 0, and game is not paused
if (player && player.isHit || lives < 0 || gamePaused) {
return;
}
- // Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
- // Ne pas appeler update() car il est déjà appelé automatiquement par le moteur
- // platforms[i].update();
- // Remove platforms that are destroyed
if (platforms[i].destroyed) {
platforms.splice(i, 1);
}
}
- // Check if we need to spawn a new platform
if (platforms.length > 0) {
var lastPlatform = platforms[platforms.length - 1];
if (lastPlatform.x < 2048 + 500) {
- // Spawn a new platform
spawnPlatform();
}
}
}
-// Handle game updates
game.update = function () {
- // Call background update function
backgroundUpdate();
- // Call platform update function
platformsUpdate();
- // Spawn enemies only after start button is clicked (when enemySpawnCounter is not 9999)
if (enemySpawnCounter !== 9999) {
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnInterval) {
var enemy;
- // Try to reuse an enemy from the pool
if (enemyPool.length > 0) {
enemy = enemyPool.pop();
enemy.visible = true;
} else {
enemy = new Enemy();
}
- enemy.x = 2500; // Plus loin à droite que 2048
- // Décider si l'ennemi apparaît sur le sol ou sur une plateforme
+ enemy.x = 2500;
var spawnOnPlatform = Math.random() < 0.5 && platforms.length > 0;
if (spawnOnPlatform) {
- // Trouver une plateforme visible à l'écran ou proche de l'écran
var visiblePlatforms = [];
for (var p = 0; p < platforms.length; p++) {
if (platforms[p].x > 2200 && platforms[p].x < 2700) {
visiblePlatforms.push(platforms[p]);
}
}
- // S'il y a des plateformes visibles, placer l'ennemi sur l'une d'elles
if (visiblePlatforms.length > 0) {
var randomPlatform = visiblePlatforms[Math.floor(Math.random() * visiblePlatforms.length)];
- // Placer l'ennemi sur la plateforme en utilisant la même logique que pour le joueur
enemy.y = randomPlatform.y - 150;
} else {
- // Sinon, placer l'ennemi sur le sol (même position Y que le joueur au repos)
enemy.y = player.y;
}
} else {
- // Placer l'ennemi sur le sol (même position Y que le joueur au repos)
enemy.y = player.y;
}
- // If enemy was from pool, use reset method
if (enemyPool.indexOf(enemy) > -1) {
enemy.reset(enemy.x, enemy.y);
}
enemies.push(enemy);
- // Only add to container if not already a child
if (!enemy.parent) {
middlegroundContainer.addChild(enemy);
}
- // Randomize the spawn interval for the next enemy
enemySpawnInterval = Math.floor(Math.random() * 150) + 50;
enemySpawnCounter = 0;
}
}
- // Check collisions with enemies
- var playerBounds = player.getBounds(); // Calculate once per frame
+ var playerBounds = player.getBounds();
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy.visible) {
continue;
- } // Skip invisible enemies (in pool)
+ }
var enemyBounds = enemy.getBounds();
- // Check if player intersects with enemy
if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) {
- // Check if player is falling on top of the enemy
if (player.isFalling && player.velocityY > 0 && playerBounds.bottom > enemyBounds.top && playerBounds.bottom - player.velocityY < enemyBounds.top) {
- // Player jumped on enemy - return to pool
if (enemy.parent) {
enemy.parent.removeChild(enemy);
}
enemies.splice(j, 1);
enemy.visible = false;
enemyPool.push(enemy);
- // Play enemy stomp sound
LK.getSound('enemyStomp').play();
- // Give player a small bounce after killing enemy
player.velocityY = -15;
- // Increment score when killing enemy
LK.setScore(LK.getScore() + 5);
scoreText.setText(LK.getScore());
} else {
if (lives < 0) {
return;
}
- // Trigger player hit state
player.hitPlayer();
- // Flash screen to indicate damage
LK.effects.flashScreen(0xff0000, 150);
- // If no more lives, show game over after a short delay
if (lives <= 0) {
- // Wait 1 second before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 4000);
} else {
- // Remove enemy that caused damage
if (enemy.parent) {
enemy.parent.removeChild(enemy);
}
enemies.splice(j, 1);
@@ -1579,266 +1287,204 @@
enemyPool.push(enemy);
}
}
} else if (player.x > enemy.x && !enemy.passed) {
- // Player passed enemy without touching it
enemy.passed = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
}
}
- // Use coins array to track how many active coins we have
- // Spawn coins with random timing, but limit the maximum number
if (coins.length < 10 && LK.ticks % Math.floor(Math.random() * 100 + 50) === 0) {
var coin;
- // Try to reuse a coin from the pool
if (coinPool.length > 0) {
coin = coinPool.pop();
coin.visible = true;
} else {
coin = new Coin();
}
- coin.x = 2500; // Start off-screen to the right
- // Randomly position the coin at one of three heights
+ coin.x = 2500;
var randomHeight = Math.random();
if (randomHeight < 0.33) {
- // On ground level
coin.y = groundLevel - 100;
} else if (randomHeight < 0.66) {
- // On level 1
coin.y = level1Height - 100;
} else {
- // On level 2
coin.y = level2Height - 100;
}
- // If coin was from pool, use reset method
if (coinPool.indexOf(coin) > -1) {
coin.reset(coin.x, coin.y);
}
- // Add coin to both the coins array and the middle ground
coins.push(coin);
- // Only add to container if not already a child
if (!coin.parent) {
middlegroundContainer.addChild(coin);
}
}
- // Spawn mushrooms occasionally (much less frequently than coins)
if (mushrooms.length < 2 && LK.ticks % mushroomSpawnInterval === 0) {
var mushroom;
- // Try to reuse a mushroom from the pool
if (mushroomPool.length > 0) {
mushroom = mushroomPool.pop();
mushroom.visible = true;
} else {
mushroom = new Mushroom();
}
- mushroom.x = 2500; // Start off-screen to the right
- // Randomly position the mushroom at one of three heights
+ mushroom.x = 2500;
var randomMushroomHeight = Math.random();
if (randomMushroomHeight < 0.33) {
- // On ground level
mushroom.y = groundLevel - 100;
} else if (randomMushroomHeight < 0.66) {
- // On level 1
mushroom.y = level1Height - 100;
} else {
- // On level 2
mushroom.y = level2Height - 100;
}
- // If mushroom was from pool, use reset method
if (mushroomPool.indexOf(mushroom) > -1) {
mushroom.reset(mushroom.x, mushroom.y);
}
- // Add mushroom to both the mushrooms array and the middle ground
mushrooms.push(mushroom);
- // Only add to container if not already a child
if (!mushroom.parent) {
middlegroundContainer.addChild(mushroom);
}
- // Reset spawn interval to a random value between 500 and 1000
mushroomSpawnInterval = Math.floor(Math.random() * 500) + 500;
}
};
-// Handle player jump
game.down = function (x, y, obj) {
player.jump();
};
function initializeGame() {
- // Initialize containers
backgroundContainer = new Container();
middlegroundContainer = new Container();
foregroundContainer = new Container();
- // Add containers to game in proper order
game.addChild(backgroundContainer);
game.addChild(middlegroundContainer);
game.addChild(foregroundContainer);
- // Define fixed platform heights for two levels
- groundLevel = 2732 / 2 + 450; // Descendre le niveau du sol de 450 pixels
- // Add background
+ groundLevel = 2732 / 2 + 450;
bgFar = LK.getAsset('bgFar', {
anchorX: 0,
anchorY: 0
});
bgFar.x = 0;
bgFar.y = 0;
bgFar.width = 2732;
backgroundContainer.addChild(bgFar);
- // Add second background for infinite scrolling
bgFar2 = LK.getAsset('bgFar', {
anchorX: 0,
anchorY: 0
});
bgFar2.x = bgFar.width;
bgFar2.y = 0;
bgFar2.width = 2732;
backgroundContainer.addChild(bgFar2);
- // Initialize parallax backgrounds
bgClose = LK.getAsset('bgClose', {
anchorX: 0,
anchorY: 0
});
bgClose.x = 0;
bgClose.y = 0;
- bgClose.width = 2732; // Set correct width to match the actual image width
+ bgClose.width = 2732;
backgroundContainer.addChild(bgClose);
- // Create a duplicate of bgClose for seamless scrolling
bgClose2 = LK.getAsset('bgClose', {
anchorX: 0,
anchorY: 0
});
bgClose2.x = bgClose.width;
bgClose2.y = 0;
bgClose2.width = 2732;
backgroundContainer.addChild(bgClose2);
- // Add ground that scrolls
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
- ground.y = groundLevel; // Placer le haut du sol exactement au niveau du sol
+ ground.y = groundLevel;
ground.width = 2048;
middlegroundContainer.addChild(ground);
- // Add second ground piece for infinite scrolling
ground2 = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground2.x = ground.width;
- ground2.y = groundLevel; // Placer le haut du sol exactement au niveau du sol
+ ground2.y = groundLevel;
ground2.width = 2048;
middlegroundContainer.addChild(ground2);
- // Initialize player
player = new Player();
- player.x = 2048 / 6; // Adjust the player's initial position to be more to the left
- player.y = groundLevel - 100; // Mario légèrement au-dessus du sol
+ player.x = 2048 / 6;
+ player.y = groundLevel - 100;
foregroundContainer.addChild(player);
- // Initialize enemies
enemies = [];
- enemyPool = []; // Reset enemy pool on game init
+ enemyPool = [];
enemySpawnInterval = 100;
- enemySpawnCounter = 9999; // Set to a large value so enemies won't spawn until start button is pressed
- // Create and add start button
+ enemySpawnCounter = 9999;
startButton = new StartButton();
- startButton.x = 2048 / 2; // Center horizontally
- startButton.y = 2732 / 2; // Center vertically
+ startButton.x = 2048 / 2;
+ startButton.y = 2732 / 2;
startButton.scale = {
x: 0,
y: 0
- }; // Initialize scale properly as an object
+ };
foregroundContainer.addChild(startButton);
- startButton.animate(); // Start the pulsing animation
- // Make sure the start button is visible
+ startButton.animate();
startButton.visible = true;
- // Initialize player with jumping disabled until start button is clicked
player.canJump = false;
- // Reset lives counter
lives = 3;
- // Clear the global coins array and coin pool
coins = [];
coinPool = [];
- // Clear mushrooms array and pool
mushrooms = [];
mushroomPool = [];
- // Initialize platforms
platforms = [];
- level1Height = groundLevel - 450; // Niveau 1 à 450 pixels au-dessus du sol
- level2Height = level1Height - 450; // Niveau 2 à 450 pixels au-dessus du niveau 1
- // Create initial 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; // Start the first platform further away
- platform.y = level1Height; // Première plateforme toujours au niveau 1
+ platform.x = player.x + 800;
+ platform.y = level1Height;
} else {
- // Deuxième plateforme au niveau 2, mais plus proche horizontalement
- platform.x = platforms[i - 1].x + 1200; // Plus espacé
+ platform.x = platforms[i - 1].x + 1200;
platform.y = level2Height;
}
platforms.push(platform);
middlegroundContainer.addChild(platform);
}
- // Create a new Text2 object to display the score
scoreText = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
- // Add the score text to the game GUI at the top center of the screen
LK.gui.top.addChild(scoreText);
scoreText.x = 2048 / 2;
scoreText.y = 0;
- // Create the coin counter and add it to the GUI
coinCounter = new CoinCounter();
- // Position coin counter properly in the top right corner
- // Note: GUI coordinates work differently than game coordinates
- coinCounter.x = -300; // Negative X moves it left from the right edge
- coinCounter.y = 30; // Some space from the top
+ coinCounter.x = -300;
+ coinCounter.y = 30;
LK.gui.topRight.addChild(coinCounter);
- // Create the lives counter and add it to the GUI
livesCounter = new LivesCounter();
- // Position lives counter in the top left corner with offset
- livesCounter.x = 250; // Offset from left edge
- livesCounter.y = 80; // Some space from the top
+ livesCounter.x = 250;
+ livesCounter.y = 80;
LK.gui.topLeft.addChild(livesCounter);
- // Initialize lives counter
livesCounter.updateLives(lives);
- // Create and initialize water hole manager
waterHoleManager = new WaterHoleManager();
middlegroundContainer.addChild(waterHoleManager);
- // Play background music
LK.playMusic('bgMusic');
}
-// Platform object pool
var platformPool = [];
-// Enemy object pool
var enemyPool = [];
-// Function to spawn a new platform
function spawnPlatform() {
var platform;
- // Try to reuse a platform from the pool
if (platformPool.length > 0) {
platform = platformPool.pop();
platform.visible = true;
} else {
platform = new Platform();
}
var lastPlatform = platforms[platforms.length - 1];
var lastHeight = lastPlatform.y;
- // Déterminer la hauteur de la nouvelle plateforme
if (lastHeight === level1Height) {
- // Si la dernière plateforme était au niveau 1, la nouvelle sera au niveau 2
platform.y = level2Height;
- platform.x = lastPlatform.x + 1200; // Plus espacé
+ platform.x = lastPlatform.x + 1200;
} else {
- // Si la dernière plateforme était au niveau 2, la nouvelle sera au niveau 1
platform.y = level1Height;
- platform.x = lastPlatform.x + 1500; // Encore plus espacé après une plateforme de niveau 2
+ platform.x = lastPlatform.x + 1500;
}
- // Ajouter une chance de ne pas générer de plateforme (20%)
if (Math.random() < 0.2) {
- // Si on décide de ne pas générer cette plateforme, on augmente la distance pour la prochaine
lastPlatform.x += 500;
- // Return platform to pool if we decided not to use it
if (platform.parent) {
platform.parent.removeChild(platform);
}
platformPool.push(platform);
@@ -1846,6 +1492,5 @@
}
platforms.push(platform);
middlegroundContainer.addChild(platform);
}
-// Call initializeGame at the end of the file
initializeGame();
\ No newline at end of file