Code edit (12 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: self.bonusIcon is null' in or related to this line: 'self.bonusIcon.destroy();' Line Number: 269
Code edit (4 edits merged)
Please save this source code
User prompt
play bonus_approaching when bonus manager activate a bonus
User prompt
play bonus_take when taking a bonus
Code edit (1 edits merged)
Please save this source code
User prompt
in BOnus update, make bonusHalo rotate sequencially
/**** * Classes ****/ var Background = Container.expand(function () { var self = Container.call(this); var backgroundGraphics1 = self.attachAsset('background_1', { anchorX: 0.5, anchorY: 0.5, visible: true }); var backgroundGraphics2 = self.attachAsset('background_2', { anchorX: 0.5, anchorY: 0.5, visible: false }); var backgroundGraphics3 = self.attachAsset('background_3', { anchorX: 0.5, anchorY: 0.5, visible: false }); self.updateForLevel = function (level) { backgroundGraphics1.visible = level === 1; backgroundGraphics2.visible = level === 2; backgroundGraphics3.visible = level === 3; }; }); var Bonus = Container.expand(function (index) { var self = Container.call(this); self.index = index; var bonusHalo = self.attachAsset('bonusHalo', { anchorX: 0.5, anchorY: 0.5, visible: false }); var assets = ['bonus_1', 'bonus_2', 'bonus_3']; self.assetIndex = index % assets.length; var randomAsset = assets[self.assetIndex]; var bonusGraphics = self.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0.5 }); var speed = 5; var startY = roadTop - 20; var endY = startY + roadHeight; var leftStartX = 1024 - 100; var leftEndX = 1024 - 650; var rightStartX = 1024 + 100; var rightEndX = 1024 + 650; var startSize = 1; var endSize = 200; var assetHeightRatio = 1; // Adjusted for bonus asset ratio bonusGraphics.width = startSize; bonusGraphics.height = startSize; bonusHalo.width = startSize * 3; bonusHalo.height = startSize * 3; self.pathIndex = 0; self.inactive = true; self.inactiveStartTime = Date.now(); self.update = function () { if (!isPlaying || isKilled) { return; } if (self.inactive) { return; } if (!isKilled && player && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) { // Handle bonus collection logic here bonusManager.applyBonus(self.index); self.reset(); return; } self.progress = Math.max(0, self.y - startY) / (endY - startY); bonusGraphics.width = startSize + (endSize - startSize) * self.progress; bonusGraphics.height = assetHeightRatio * bonusGraphics.width; bonusHalo.visible = true; bonusHalo.rotation += 0.01 + (self.progress * 100 % 3 == 0); // Rotate bonusHalo sequentially bonusHalo.width = bonusGraphics.width * 3; bonusHalo.height = bonusGraphics.height * 3; var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3); var newSpeed = currentSpeed * 1; newSpeed = tempSpeed * 1; self.y += newSpeed; if (self.pathIndex == 0 && self.x != leftEndX) { self.x = leftStartX + (leftEndX - leftStartX) * self.progress; } if (self.pathIndex == 2 && self.x != rightEndX) { self.x = rightStartX + (rightEndX - rightStartX) * self.progress; } if (self.y > endY + endSize / 2) { self.reset(); } }; self.reset = function () { bonusHalo.rotation = 0; // Initialize bonusHalo rotation self.y = startY; self.progress = 0; bonusGraphics.width = startSize; bonusGraphics.height = startSize; bonusHalo.width = startSize * 3; bonusHalo.height = startSize * 3; bonusHalo.visible = false; self.pathIndex = Math.floor(Math.random() * 3); if (self.pathIndex === 0) { self.x = leftStartX; } else if (self.pathIndex === 2) { self.x = rightStartX; } else { self.x = 1024; } self.inactive = true; self.inactiveStartTime = Date.now(); }; }); var BonusManager = Container.expand(function () { var self = Container.call(this); self.bonuses = []; self.bonusIcon = null; self.currentBonusIndex = 0; self.currentActiveBonus = 0; self.lastBonusUpdate = 0; self.bonusDelay = 16000; // Delay in milliseconds before updating bonus self.addBonus = function (bonus) { self.bonuses.push(bonus); }; self.update = function () { if (!isGameStarted || !isPlaying || isKilled) { self.lastBonusUpdate = Date.now(); // Reset the last bonus update time when the game starts return; } if (self.currentActiveBonus > 0) { if (!self.bonusIcon) { self.bonusIcon = LK.getAsset('bonus_' + self.currentActiveBonus, { anchorX: 0.5, anchorY: 0.5, x: scoreTxt.x, y: scoreTxt.y + scoreTxt.height + 50 }); LK.gui.top.addChild(self.bonusIcon); } } else if (self.bonusIcon) { self.bonusIcon.visible = false; self.bonusIcon = null; } var currentTime = Date.now(); var currentDelay = currentTime - self.lastBonusUpdate; if (currentDelay >= self.bonusDelay) { LK.getSound('bonus_approaching').play(); self.currentBonusIndex = (self.currentBonusIndex + 1) % self.bonuses.length; self.bonuses[self.currentBonusIndex].inactive = false; self.lastBonusUpdate = currentTime; } }; self.resetBonuses = function () { self.bonuses.forEach(function (bonus) { bonus.reset(); }); self.currentBonusIndex = 0; self.lastBonusUpdate = Date.now(); }; self.updateForLevel = function (level) { if (level === 1) { self.bonusDelay = 8000; // Delay in milliseconds for level 1 } else if (level === 2) { self.bonusDelay = 12000; // Delay in milliseconds for level 2 } else if (level === 3) { self.bonusDelay = 16000; // Delay in milliseconds for level 3 } }; self.applyBonus = function (index) { self.currentActiveBonus = index + 1; LK.getSound('bonus_take').play(); self.lastBonusUpdate = Date.now(); LK.setTimeout(function () { // Start blinking effect 3 seconds before bonus ends var blinkStartTime = Date.now(); var blinkInterval = LK.setInterval(function () { var elapsed = Date.now() - blinkStartTime; if (elapsed >= 3000) { LK.clearInterval(blinkInterval); self.stopBonus(); } else { if (self.bonusIcon) { self.bonusIcon.alpha = self.bonusIcon.alpha === 1 ? 0.5 : 1; } } }, 150); // Blink every 500ms }, baseBonusDelay - 3000); }; self.stopBonus = function () { self.currentActiveBonus = 0; if (self.bonusIcon) { LK.gui.top.removeChild(self.bonusIcon); } if (self.bonusIcon) { self.bonusIcon.destroy(); } self.bonusIcon = null; self.lastBonusUpdate = Date.now(); }; }); // Assets will be automatically created and loaded during gameplay // Coin class var Coin = Container.expand(function (index) { var self = Container.call(this); self.index = index; var coinGraphics = self.attachAsset('coin1', { anchorX: 0.5, anchorY: 0.5 }); var coinGraphics2 = self.attachAsset('coin2', { //'dollarsBundle' anchorX: 0.5, anchorY: 0.5, visible: false }); var coinGraphics3 = self.attachAsset('dollarsBundle', { //'dollarsBundle' anchorX: 0.5, anchorY: 0.5, visible: false }); var coinGraphicsClone = self.attachAsset('coin1', { anchorX: 0.5, anchorY: 0.5, x: -20, visible: false }); var coinGraphics2Clone = self.attachAsset('coin2', { //'dollarsBundle' anchorX: 0.5, anchorY: 0.5, x: -20, visible: false }); var coinGraphics3Clone = self.attachAsset('dollarsBundle', { anchorX: 0.5, anchorY: 0.5, x: -20, visible: false }); var speed = 5; var startY = roadTop + 50; var endY = startY + roadHeight; var leftStartX = 1024 - 100; var leftEndX = 1024 - 650; var rightStartX = 1024 + 100; var rightEndX = 1024 + 650; var startSize = 2; var endSize = 140; coinGraphics.width = startSize; coinGraphics.height = startSize; coinGraphics2.width = startSize; coinGraphics2.height = startSize; coinGraphics3.width = startSize; coinGraphics3.height = startSize; self.pathIndex = 0; self.update = function () { if (!isGameStarted) { return; } // Road should animate even if the game hasn't started if (!isPlaying || isKilled) { return; } ; obstacleManager.updateObstacles(); self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property coinGraphics.width = startSize + (endSize - startSize) * self.progress; coinGraphics.height = startSize + (endSize - startSize) * self.progress; coinGraphics2.width = startSize + (endSize - startSize) * self.progress; coinGraphics2.height = startSize + (endSize - startSize) * self.progress; coinGraphics3.width = startSize + (endSize - startSize) * self.progress; coinGraphics3.height = startSize + (endSize - startSize) * self.progress; if (bonusManager.currentActiveBonus == 2) { coinGraphicsClone.width = coinGraphics.width; coinGraphicsClone.height = coinGraphics.height; coinGraphics2Clone.width = coinGraphics2.width; coinGraphics2Clone.height = coinGraphics2.height; coinGraphics3Clone.width = coinGraphics3.width; coinGraphics3Clone.height = coinGraphics3.height; coinGraphicsClone.visible = currentLevel === 1; coinGraphics2Clone.visible = currentLevel === 2; coinGraphics3Clone.visible = currentLevel === 3; coinGraphics.x = 20; coinGraphics2.x = 20; coinGraphics3.x = 20; } else { coinGraphics.x = 0; coinGraphics2.x = 0; coinGraphics3.x = 0; coinGraphicsClone.visible = false; coinGraphics2Clone.visible = false; coinGraphics3Clone.visible = false; } if (bonusManager.currentActiveBonus == 3 && self.y > 1500) { // Magnet bonus logic var distanceX = player.x - self.x; var distanceY = player.y - self.y; var distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); if (distance < 1500) { var attractionSpeed = 20; self.x += distanceX / distance * attractionSpeed; self.y += distanceY / distance * attractionSpeed; } distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); if (distance < 100) { LK.getSound('coin_1').play(); updateScore(false); // coinsCollected increment moved to increaseScore function LK.effects.flashObject(player, 0x00ff00, 500); // Flash green for 0.5 seconds self.reset(); } } else { var newSpeed = currentSpeed; // + 10 * self.progress; var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3); newSpeed = tempSpeed; self.y += newSpeed; // Move innerLineLeft x progressively to innerLeftLineEndX if (self.pathIndex == 0 && self.x != leftEndX) { self.x = leftStartX + (leftEndX - leftStartX) * self.progress; } if (self.pathIndex == 2 && self.x != rightEndX) { self.x = rightStartX + (rightEndX - rightStartX) * self.progress; } } if (self.y > endY + endSize / 2) { self.reset(); } // Check for collision with player if (!player.isJumping && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) { LK.getSound('coin_1').play(); updateScore(false); // coinsCollected increment moved to increaseScore function LK.effects.flashObject(player, 0x00ff00, 500); // Flash green for 0.5 seconds self.reset(); // Increase speed every 3 coins collected /* if (coinsCollected % nextCoinTypeThreshold === 0 && currentSpeed < maxSpeed) { currentSpeed += 3; // Increase speed by 3 } */ } }; self.reset = function () { self.y = startY; self.progress = 0; // Initialize progress property coinGraphics.width = startSize; coinGraphics.height = startSize; coinGraphics2.width = startSize; coinGraphics2.height = startSize; coinGraphics3.width = startSize; coinGraphics3.height = startSize; coinGraphicsClone.visible = false; coinGraphics2Clone.visible = false; coinGraphics3Clone.visible = false; self.pathIndex = Math.floor(Math.random() * 3); if (self.pathIndex === 0) { self.x = leftStartX; } else if (self.pathIndex === 2) { self.x = rightStartX; } else { self.x = 1024; } }; self.updateForLevel = function (level) { coinGraphics.visible = level === 1; coinGraphics2.visible = level === 2; coinGraphics3.visible = level === 3; }; }); // CoinAnimation class var CoinAnimation = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin1', { anchorX: 0.5, anchorY: 0.5, visible: currentLevel === 1 }); var coinGraphics2 = self.attachAsset('coin2', { anchorX: 0.5, anchorY: 0.5, visible: currentLevel === 2 }); var coinGraphics3 = self.attachAsset('dollarsBundle', { anchorX: 0.5, anchorY: 0.5, visible: currentLevel === 3 }); // Initialize velocity and gravity self.vx = (Math.random() < 0.5 ? -1 : 1) * 5; // Random horizontal velocity self.vy = -15; // Initial vertical velocity self.gravity = 0.5; // Gravity effect self.update = function () { self.vy += self.gravity; // Apply gravity to vertical velocity self.x += self.vx; // Update horizontal position self.y += self.vy; // Update vertical position self.alpha -= 0.0035; // Fade out the coin coinGraphics.visible = currentLevel === 1; coinGraphics2.visible = currentLevel === 2; coinGraphics3.visible = currentLevel === 3; if (self.alpha <= 0) { self.destroy(); // Remove the coin when it becomes invisible } }; }); // Decoration class var Decoration = Container.expand(function (decoIndex) { var self = Container.call(this); self.index = decoIndex; var assets = ['decoration_1_1', 'decoration_1_2', 'decoration_1_3', 'decoration_2_1', 'decoration_2_2', 'decoration_2_3', 'decoration_3_1', 'decoration_3_2', 'decoration_3_3']; self.assets = assets.map(function (assetId) { return self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, visible: false }); }); self.ready = false; var speed = 5; var startY = roadTop + 50; var endY = startY + roadHeight; var xOffset = 1024; var baseLeftStartX = 780; var rand = Math.random(); self.leftStartX = baseLeftStartX; // - rand * xOffset; self.leftEndX = self.leftStartX - xOffset * (1.5 + rand); var baseRightStartX = 1280; self.rightStartX = baseRightStartX; // + rand * xOffset / 2; self.rightEndX = self.rightStartX + xOffset * (1.5 + rand); self.assetWidthRatios = [0.33, 1, 1, 1, 1, 1, 1, 1, 1]; self.endSizes = [600, 600, 600, 600, 600, 600, 600, 600, 600]; var startSize = 1; self.assetIndex = Math.floor(Math.random() * 3) + (currentLevel - 1) * 3; mainGraphics = self.assets[self.assetIndex]; mainGraphics.width = startSize; mainGraphics.height = startSize; self.pathIndex = 0; self.update = function () { if (isKilled) { return; } var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf; //mainGraphics.tint = newTint; var tempSpeed = currentSpeed * 0.055 + currentSpeed * (self.progress * 3); var newSpeed = currentSpeed; // + 10 * self.progress; newSpeed = tempSpeed * 1; // TEMP DEBUG !!! self.y += newSpeed; self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property // Move innerLineLeft x progressively to innerLeftLineEndX if (self.index == 7) { //log("Decoration " + self.index + " update - p=", self.progress, "x:", Math.round(self.x), "y:", Math.round(self.y)); //log(self.progress); } if (self.pathIndex == 0 && self.x > self.leftEndX) { self.x = self.leftStartX + (self.leftEndX - self.leftStartX) * self.progress * 3; } if (self.pathIndex == 1 && self.x < self.rightEndX) { self.x = self.rightStartX + (self.rightEndX - self.rightStartX) * self.progress * 3; } if (self.y > endY + self.endSizes[self.assetIndex] / 2) { //self.y = -startSize; // Move obstacle back to the top self.reset(); } //mainGraphics = self.assets[self.assetIndex]; mainGraphics.height = startSize + (self.endSizes[self.assetIndex] - startSize) * self.progress * 2; mainGraphics.width = mainGraphics.height * self.assetWidthRatios[self.assetIndex]; if (self.index == 8 && mainGraphics.width > 200) { //log("Decoration " + self.index + " update - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "x:", Math.round(self.x), "y:", Math.round(self.y)); } if (self.index == 7 && mainGraphics.width > 200) { //log("Decoration " + self.index + " update - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "x:", Math.round(self.x), "y:", Math.round(self.y)); } if (!self.ready) { //log("Decoration " + self.index + " ready =" + self.ready); } //log("Decoration " + self.index + " update width:", Math.round(mainGraphics.width), "x:", Math.round(self.x), "y:", Math.round(self.y)); }; self.reset = function () { self.ready = false; //log("Decoration reset" + self.index); self.y = startY; self.progress = 0; // Initialize progress property rand = Math.random(); self.assetIndex = Math.floor(Math.random() * 3) + (currentLevel - 1) * 3; self.assets.forEach(function (asset, index) { asset.visible = index === self.assetIndex; }); mainGraphics = self.assets[self.assetIndex]; mainGraphics.height = startSize; mainGraphics.width = mainGraphics.height * self.assetWidthRatios[self.assetIndex]; if (self.index == 1 && mainGraphics.width > 200) { //log("=== Decoration " + self.index + " reset - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "y:", self.y, " ==="); } self.leftStartX = baseLeftStartX; // - rand * xOffset; self.leftEndX = self.leftStartX - xOffset * (1 + rand); self.rightStartX = baseRightStartX; // + rand * xOffset; self.rightEndX = self.rightStartX + xOffset * (1 + rand); if (self.index == 1) { //log("=== Decoration " + self.index); //log("Left StartX:", self.leftStartX, "Left EndX:", self.leftEndX); //log("Right StartX:", self.rightStartX, "Right EndX:", self.rightEndX); } self.pathIndex = Math.floor(rand * 2); if (self.pathIndex === 0) { self.x = self.leftStartX; } else { self.x = self.rightStartX; } self.ready = true; }; }); var Killer = Container.expand(function (index) { var self = Container.call(this); self.index = index; var assets = ['killer1', 'killer2', 'killer3']; self.assetIndex = index % assets.length; var randomAsset = assets[self.assetIndex]; var killerGraphics = self.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0.5 }); var speed = 5; var startY = roadTop - 20; var endY = startY + roadHeight; var leftStartX = 1024 - 100; var leftEndX = 1024 - 650; var rightStartX = 1024 + 100; var rightEndX = 1024 + 650; var startSize = 1; var endSize = 800; var assetHeightRatio = 500 / 400; killerGraphics.width = startSize; killerGraphics.height = startSize; self.pathIndex = 0; self.inactive = true; self.inactiveStartTime = Date.now(); self.update = function () { if (!isPlaying) { return; } if (self.inactive) { return; } if (!isKilled && player && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) { LK.getSound('accident_1').play(); if (bonusManager.currentActiveBonus == 1) { // Have Helmet! LK.effects.flashScreen(0xffffff, 2000); self.reset(); bonusManager.stopBonus(); return; } isKilled = true; player.visible = false; LK.stopMusic(); LK.setTimeout(function () { LK.getSound('killed_1').play(); }, 100); // Adjust the delay as needed LK.setTimeout(function () { LK.getSound('rip_1').play(); }, 1000); // Play rip_1 sound 1 second after killed LK.effects.flashScreen(0xff0000, 4000); // Spawn MurderShape at player's last position var murderShape = new MurderShape(); murderShape.x = player.x; murderShape.y = playerBaseY; murderShape.fixPosition(); game.addChildAt(murderShape, game.getChildIndex(road) + 1); // Store the score in LK score before game over LK.setScore(score * 100); LK.setTimeout(function () { LK.showGameOver(); }, 5000); return; } self.progress = Math.max(0, self.y - startY) / (endY - startY); killerGraphics.width = startSize + (endSize - startSize) * self.progress; debugTxt.setText(self.progress.toFixed(2)); killerGraphics.height = assetHeightRatio * killerGraphics.width; var tempSpeed = currentSpeed * 0.5 + currentSpeed * (self.progress * 3); var newSpeed = currentSpeed * 3 + (currentLevel - 1); newSpeed = tempSpeed * 1; self.y += newSpeed; if (self.pathIndex == 0 && self.x != leftEndX) { self.x = leftStartX + (leftEndX - leftStartX) * self.progress; } if (self.pathIndex == 2 && self.x != rightEndX) { self.x = rightStartX + (rightEndX - rightStartX) * self.progress; } if (self.y > endY + endSize / 2) { self.reset(); } }; self.reset = function () { self.y = startY; self.progress = 0; killerGraphics.width = startSize; killerGraphics.height = startSize; self.pathIndex = Math.floor(Math.random() * 3); if (self.pathIndex === 0) { self.x = leftStartX; } else if (self.pathIndex === 2) { self.x = rightStartX; } else { self.x = 1024; } self.inactive = true; self.inactiveStartTime = Date.now(); }; }); var KillerManager = Container.expand(function () { var self = Container.call(this); self.killers = []; self.currentKillerIndex = 0; self.lastKillerUpdate = 0; self.killerDelay = 10000; // Delay in milliseconds before updating killer self.addKiller = function (killer) { self.killers.push(killer); }; self.update = function () { if (!isGameStarted) { self.lastKillerUpdate = Date.now(); // Reset the last killer update time when the game starts return; } var currentTime = Date.now(); var currentDelay = currentTime - self.lastKillerUpdate; if (currentDelay >= self.killerDelay) { self.killers[self.currentKillerIndex].inactive = false; if (self.currentKillerIndex === 0) { LK.getSound('car_1').play(); } else if (self.currentKillerIndex === 1) { LK.getSound('police_1').play(); } else if (self.currentKillerIndex === 2) { LK.getSound('ambulance_1').play(); } self.currentKillerIndex = (self.currentKillerIndex + 1) % self.killers.length; self.lastKillerUpdate = currentTime; } }; self.resetKillers = function () { self.killers.forEach(function (killer) { killer.reset(); }); self.currentKillerIndex = 0; self.lastKillerUpdate = Date.now(); }; self.updateForLevel = function (level) { if (level === 1) { self.killerDelay = 12000; // Delay in milliseconds for level 1 } else if (level === 2) { self.killerDelay = 10000; // Delay in milliseconds for level 2 } else if (level === 3) { self.killerDelay = 8000; // Delay in milliseconds for level 3 } }; }); var Landscape = Container.expand(function () { var self = Container.call(this); var landscapeGraphics = self.attachAsset('landscape_1', { anchorX: 0.5, anchorY: 0.0 }); var landscapeGraphics2 = self.attachAsset('landscape_2', { anchorX: 0.5, anchorY: 0.0, visible: false }); var landscapeGraphics3 = self.attachAsset('landscape_3', { anchorX: 0.5, anchorY: 0.0, visible: false }); var gradientGraphics = self.attachAsset('gradient', { anchorX: 0.5, anchorY: 0.0, scaleY: -1, y: 1024, blendMode: 2, alpha: 0.5, tint: 0xFEFEFE, height: 15 }); self.x = 2048 / 2; // Center horizontally self.y = 0; // Position at the top self.update = function () { var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf; landscapeGraphics.tint = newTint; // Apply reduced tint to the road based on the intensity }; self.updateForLevel = function (level) { landscapeGraphics.visible = level === 1; landscapeGraphics2.visible = level === 2; landscapeGraphics3.visible = level === 3; }; }); var MurderShape = Container.expand(function () { var self = Container.call(this); var murderShapeGraphics = self.attachAsset('murderShape', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // MurderShape does not need to update its position or behavior }; self.fixPosition = function () { if (self.x < 600) { self.x += 150; } else if (self.x > 1400) { self.x -= 150; } }; }); // Obstacle class var Obstacle = Container.expand(function (index) { var self = Container.call(this); self.active = true; self.index = index; var assets = []; if (currentLevel === 1) { assets = ['obstacle_1_1', 'obstacle_1_2', 'obstacle_1_3']; } else if (currentLevel === 2) { assets = ['obstacle_2_1', 'obstacle_2_2', 'obstacle_2_3']; } else if (currentLevel === 3) { assets = ['obstacle_3_1', 'obstacle_3_2', 'obstacle_3_3']; } self.assetIndex = Math.floor(Math.random() * assets.length); var randomAsset = assets[self.assetIndex]; var obstacleGraphics = self.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0.5 }); var speed = 5; var startY = roadTop + 50; var endY = startY + roadHeight; var leftStartX = 1024 - 100; var leftEndX = 1024 - 650; var rightStartX = 1024 + 100; var rightEndX = 1024 + 650; var innerLeftLineStartX = -150; var innerLeftLineEndX = -390; self.assetWidthRatios = [1, 1, 1.5, 1.8, 1.8, 1.6, 1, 0.8, 1.1]; var startSize, endSize; if (self.assetIndex == 0) { startSize = 3; endSize = 200; } else if (self.assetIndex == 1) { startSize = 1; endSize = 250; } else if (self.assetIndex == 2) { startSize = 2; endSize = 300; } obstacleGraphics.width = startSize; obstacleGraphics.height = startSize; self.pathIndex = 0; self.update = function () { if (!isPlaying || isKilled) { return; } // coinsCollected increment moved to updateScore function var currentTime = Date.now(); if (currentTime - lastObstacleHitTime > immunityDelay && player && !player.isJumping && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) { lastObstacleHitTime = currentTime; // Update the last hit time if (bonusManager.currentActiveBonus != 1) { // Without helmet playHit(); // Make player flash red for 1 second LK.effects.flashObject(player, 0xff0000, 1000); // Add coin animation only if score is greater than 0 if (score > 0) { var coinAnimation = new CoinAnimation(); coinAnimation.x = player.x; coinAnimation.y = player.y; game.addChild(coinAnimation); } // Reduce score by 1 updateScore(true); //log("Obstacle y:", self.y); // Reduce currentSpeed by a factor (e.g., 0.8) //log("Old speed :", currentSpeed); //currentSpeed = Math.max(10, Math.min(20, Math.round(currentSpeed * 0.8))); //log("New speed :", currentSpeed); } } self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property //self.assetWidthRatios[self.assetIndex] obstacleGraphics.height = startSize + (endSize - startSize) * self.progress; obstacleGraphics.width = obstacleGraphics.height * self.assetWidthRatios[self.assetIndex + 3 * (currentLevel - 1)]; var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3); var newSpeed = currentSpeed; // + 10 * self.progress; newSpeed = tempSpeed * 1; // TEMP DEBUG !!! self.y += newSpeed; // Move innerLineLeft x progressively to innerLeftLineEndX if (self.pathIndex == 0 && self.x != leftEndX) { self.x = leftStartX + (leftEndX - leftStartX) * self.progress; } if (self.pathIndex == 2 && self.x != rightEndX) { self.x = rightStartX + (rightEndX - rightStartX) * self.progress; } if (self.y > endY + endSize / 2) { self.reset(); } }; self.reset = function () { obstacleManager.freePath(self.pathIndex); // Mark the path as unoccupied self.active = false; self.y = startY; self.progress = 0; // Initialize progress property obstacleGraphics.width = startSize; obstacleGraphics.height = startSize; }; self.setPath = function (newPathIndex) { self.pathIndex = newPathIndex; //Math.floor(Math.random() * 3); if (self.pathIndex === 0) { self.x = leftStartX; } else if (self.pathIndex === 2) { self.x = rightStartX; } else { self.x = 1024; } }; self.updateForLevel = function (level) { log("Obstacle updateForLevel", level); var assets = []; if (level === 1) { assets = ['obstacle_1_1', 'obstacle_1_2', 'obstacle_1_3']; } else if (level === 2) { assets = ['obstacle_2_1', 'obstacle_2_2', 'obstacle_2_3']; } else if (level === 3) { assets = ['obstacle_3_1', 'obstacle_3_2', 'obstacle_3_3']; } self.assetIndex = Math.floor(Math.random() * 3); var randomAsset = assets[self.assetIndex]; log("Obstacle asset =>", randomAsset); obstacleGraphics.destroy(); obstacleGraphics = self.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0.5 }); self.reset(); }; }); var ObstacleManager = Container.expand(function () { var self = Container.call(this); self.obstacles = []; self.occupiedPaths = [false, false, false]; self.addObstacle = function (obstacle) { self.obstacles.push(obstacle); }; self.resetObstacles = function () { self.occupiedPaths = [false, false, false]; self.obstacles.forEach(function (obstacle) { obstacle.reset(); }); }; self.updateObstacles = function () { self.obstacles.forEach(function (obstacle) { if (!obstacle.active) { obstacle.reset(); } }); }; self.update = function () { if (!isPlaying || isKilled) { return; } // Activate obstacles regularly in random path var currentTime = Date.now(); log("ObstacleManager update..."); if (currentTime - lastObstacleSpawnTime > baseObstacleSpawnDelay * 0.75) { log("Attempting to spawn obstacle. Current time:", currentTime, "Last spawn time:", lastObstacleSpawnTime); var availablePaths = self.occupiedPaths.map(function (occupied, index) { return occupied ? null : index; }).filter(function (index) { return index !== null; }); log("Available paths for obstacle activation:", availablePaths); if (availablePaths.length > 0) { var randomPathIndex = availablePaths[Math.floor(Math.random() * availablePaths.length)]; var inactiveObstacles = self.obstacles.filter(function (obstacle) { return !obstacle.active; }); log("Inactive obstacles available for activation:", inactiveObstacles.length); if (inactiveObstacles.length > 0) { var obstacleToActivate = inactiveObstacles[Math.floor(Math.random() * inactiveObstacles.length)]; log("Activating obstacle in path:", randomPathIndex); obstacleToActivate.setPath(randomPathIndex); log("Obstacle activated:", obstacleToActivate); obstacleToActivate.active = true; self.setPathOccupied(randomPathIndex, true); log("Path occupied status updated. Path:", randomPathIndex, "Occupied:", self.isPathOccupied(randomPathIndex)); lastObstacleSpawnTime = currentTime; // Update the last spawn time } } } }; self.isPathOccupied = function (pathIndex) { return self.occupiedPaths[pathIndex]; }; self.setPathOccupied = function (pathIndex, occupied) { self.occupiedPaths[pathIndex] = occupied; }; self.freePath = function (pathIndex) { self.setPathOccupied(pathIndex, false); }; self.updateForLevel = function (level) { self.obstacles.forEach(function (obstacle) { obstacle.updateForLevel(level); }); }; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); self.shadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5 }); self.isJumping = false; // Initialize isJumping to false self.shadow.alpha = 0.5; // Make the shadow semi-transparent self.shadow.y = 270; // Offset the shadow slightly below the player var playerGraphics1_1 = self.attachAsset('player_1_1', { anchorX: 0.5, anchorY: 0.5, x: -5 }); var playerGraphics1_2 = self.attachAsset('player_1_2', { anchorX: 0.5, anchorY: 0.5, x: 5 }); var playerGraphics2_1 = self.attachAsset('player_2_1', { anchorX: 0.5, anchorY: 0.5, x: -5, visible: false // Initially hide player2_1 asset }); var playerGraphics2_2 = self.attachAsset('player_2_2', { anchorX: 0.5, anchorY: 0.5, x: 5, visible: false // Initially hide player2_2 asset }); var playerGraphics3_1 = self.attachAsset('player_3_1', { anchorX: 0.5, anchorY: 0.5, x: -5, visible: false // Initially hide player3_1 asset }); var playerGraphics3_2 = self.attachAsset('player_3_2', { anchorX: 0.5, anchorY: 0.5, x: 5, visible: false // Initially hide player3_2 asset }); self.helmet = self.attachAsset('helmet', { anchorX: 0.5, anchorY: 0.5, x: -4, visible: false }); self.helmet.y = -210; var frame = 0; self.update = function () { if (!self.isJumping) { frame += Math.min(currentSpeed, 20); // Add a max limit to avoid optical effects if (frame >= 100) { frame = 0; // Swap frames every 10 game ticks if (currentLevel <= 1) { var visible = playerGraphics1_1.visible; playerGraphics1_1.visible = !visible; playerGraphics1_2.visible = visible; } if (currentLevel === 2) { var visible = playerGraphics2_1.visible; playerGraphics2_1.visible = !visible; playerGraphics2_2.visible = visible; } if (currentLevel === 3) { var visible = playerGraphics3_1.visible; playerGraphics3_1.visible = !visible; playerGraphics3_2.visible = visible; } self.helmet.visible = bonusManager.currentActiveBonus == 1; if (self.helmet.visible) { self.helmet.scale.x *= -1; self.helmet.x *= -1; self.helmet.y = currentLevel == 2 ? -170 : -210; self.helmet.scale.x = currentLevel == 3 ? 1.1 : 1; self.helmet.scale.y = currentLevel == 3 ? 1.1 : 1; } } } }; self.updateForLevel = function (level) { playerGraphics1_1.visible = level === 1; playerGraphics1_2.visible = level === 1; playerGraphics2_1.visible = level === 2; playerGraphics2_2.visible = level === 2; playerGraphics3_1.visible = level === 3; playerGraphics3_2.visible = level === 3; }; self.jump = function () { if (!self.isJumping) { self.isJumping = true; LK.getSound('jump_1').play(); var initialY = self.y; var initialShadowY = self.shadow.y; var jumpHeight = 300; var jumpDuration = 30; var jumpStep = jumpHeight / jumpDuration; var fallStep = jumpHeight / jumpDuration; var jumpStartTime = Date.now(); var jumpInterval = LK.setInterval(function () { var elapsed = Date.now() - jumpStartTime; var progress = elapsed / (jumpDuration * 1000 / 60); if (progress < 1) { var easeProgress = Math.sin(progress * Math.PI / 2); self.y = initialY - jumpHeight * easeProgress; self.shadow.y = initialShadowY + jumpHeight * easeProgress; // Move shadow inversely self.shadow.width = 240 * (1 - 0.5 * easeProgress); // Reduce shadow width self.shadow.height = 100 * (1 - 0.5 * easeProgress); // Reduce shadow height } else { LK.clearInterval(jumpInterval); var fallStartTime = Date.now(); var fallInterval = LK.setInterval(function () { var elapsed = Date.now() - fallStartTime; var progress = elapsed / (jumpDuration * 1000 / 60); if (progress < 1) { var easeProgress = Math.sin(progress * Math.PI / 2); self.y = initialY - jumpHeight + jumpHeight * easeProgress; self.shadow.y = initialShadowY + jumpHeight - jumpHeight * easeProgress; // Move shadow inversely self.shadow.width = 120 + 120 * easeProgress; // Reset shadow width self.shadow.height = 50 + 50 * easeProgress; // Reset shadow height } else { self.y = initialY; self.shadow.y = initialShadowY; // Reset shadow position self.isJumping = false; LK.clearInterval(fallInterval); } }, 1000 / 60); } }, 1000 / 60); } }; }); // Road class var Road = Container.expand(function () { var self = Container.call(this); var baseY = 750; var roadGraphics = self.attachAsset('triangle', { tint: 0x555555, // Initialize tint to white anchorX: 0.5, anchorY: 0, width: 2048, height: roadHeight, y: baseY }); var speed = 5; var lineOffset = -150; // Inner lines var innerLineStartY = roadTop; var innerLineEndY = roadTop + roadHeight + 200; // Left var innerLeftLineStartX = -50; var innerLeftLineEndX = -412; var innerLeftLineStartW = 3; var innerLeftLineEndW = 80; var innerLeftLineStartH = 3; var innerLeftLineEndH = 500; var innerLeftLineStartR = 0.22; //0.075; var innerLeftLineEndR = 0.275; // Right var innerRightLineStartX = 50; var innerRightLineEndX = 412; var innerRightLineStartW = 3; var innerRightLineEndW = 80; var innerRightLineStartH = 3; var innerRightLineEndH = 500; var innerRightLineStartR = -0.22; var innerRightLineEndR = -0.275; // Lamp posts // Left Lamp var leftLampStartX = -130; var leftLampEndX = -1600; var leftLampStartY = roadTop; var leftLampEndY = roadTop + roadHeight + 0; // Define leftLampEndY variable var leftLampStartH = 2; var leftLampEndH = 900; var leftLampWRatio = 1 / 3; // Right Lamp var rightLampStartX = 130; var rightLampEndX = 1600; var rightLampStartY = roadTop; var rightLampEndY = roadTop + roadHeight + 0; // Define leftLampEndY variable var rightLampStartH = 2; var rightLampEndH = 900; var rightLampWRatio = 1 / 3; var nbInnerLines = 6; var leftLine = self.attachAsset('triangle', { anchorX: 0.5, anchorY: 0, width: 100, height: 1950, rotation: 0.45 }); leftLine.x = lineOffset; // Position the left line on the left side of the road leftLine.y = roadTop + 45; // Center the left line vertically var rightLine = self.attachAsset('triangle', { anchorX: 0.5, anchorY: 0, width: 100, height: 1950, rotation: -0.45 }); rightLine.x = -lineOffset; // Position the right line on the right side of the road rightLine.y = roadTop + 45; // Center the right line vertically self.innerLeftLines = []; self.innerRightLines = []; self.leftLampPosts = []; self.rightLampPosts = []; // Define arrays to store assets for each level var leftLampPostAssets = ['lampPost_1', // Level 1 asset 'lampPost_2', // Level 2 asset 'lampPost_3' // Level 3 asset ]; var rightLampPostAssets = ['lampPost_1', // Level 1 asset 'lampPost_2', // Level 2 asset 'lampPost_3' // Level 3 asset ]; for (var i = 0; i < nbInnerLines; i++) { var innerLineLeft = self.attachAsset('line', { anchorX: 0.5, anchorY: 0.5, width: innerLeftLineStartW, height: innerLeftLineStartH, rotation: innerLeftLineStartR, alpha: 1 }); innerLineLeft.x = innerLeftLineStartX; innerLineLeft.y = innerLineStartY - 0.1 * i * roadHeight / nbInnerLines; //log(i + " : " + innerLineStartY + " + " + i * roadHeight / nbInnerLines + " => " + innerLineLeft.y); innerLineLeft.progress = 0; // Initialize progress property self.innerLeftLines.push(innerLineLeft); var innerLineRight = self.attachAsset('line', { anchorX: 0.5, anchorY: 0.5, width: innerRightLineStartW, height: innerRightLineStartH, rotation: innerRightLineStartR, alpha: 1 }); innerLineRight.x = innerRightLineStartX; innerLineRight.y = innerLineStartY - 0.1 * i * roadHeight / nbInnerLines; innerLineRight.progress = 0; // Initialize progress property self.innerRightLines.push(innerLineRight); if (i % 2 == 0) { continue; } var leftLampPost = self.attachAsset(leftLampPostAssets[currentLevel - 1], { anchorX: 0.5, anchorY: 0.5, height: leftLampStartH, width: leftLampStartH * leftLampWRatio }); var leftLampShadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5, width: leftLampPost.width * 0.8, height: leftLampPost.height * 0.1, y: leftLampPost.height * 0.5 + 10 // Offset shadow slightly below the lamp post }); leftLampPost.addChild(leftLampShadow); leftLampPost.x = leftLampStartX; leftLampPost.y = leftLampStartY - (i - 1) * 40; self.addChild(leftLampPost); self.leftLampPosts.push(leftLampPost); var rightLampPost = self.attachAsset(rightLampPostAssets[currentLevel - 1], { anchorX: 0.5, anchorY: 0.5, scaleX: -1, height: rightLampStartH, width: rightLampStartH * rightLampWRatio }); var rightLampShadow = self.attachAsset('shadow', { anchorX: 0.5, anchorY: 0.5, width: rightLampPost.width * 0.8, height: rightLampPost.height * 0.1, y: rightLampPost.height * 0.5 + 10 // Offset shadow slightly below the lamp post }); rightLampPost.addChild(rightLampShadow); rightLampPost.x = rightLampStartX; rightLampPost.y = rightLampStartY - (i - 1) * 40; self.addChild(rightLampPost); self.rightLampPosts.push(rightLampPost); } self.update = function () { if (isKilled) { return; } var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf; //roadGraphics.tint = newTint; // Apply reduced tint to the road based on the intensity leftLine.tint = newTint; rightLine.tint = newTint; // Add any update logic for the road if needed for (var i = 0; i < self.innerLeftLines.length; i++) { innerLineLeft = self.innerLeftLines[i]; innerLineLeft.tint = newTint; if (innerLineLeft.y > innerLineEndY) { self.resetInnerLine(innerLineLeft, true); } else { innerLineLeft.progress = Math.max(0, innerLineLeft.y - innerLineStartY) / (innerLineEndY - innerLineStartY); // Update progress property } var tempSpeed = currentSpeed * 0.05 + currentSpeed * (innerLineLeft.progress * 3); var newSpeed = currentSpeed; // + 10 * self.progress; newSpeed = tempSpeed * 1; // TEMP DEBUG !!! innerLineLeft.y += newSpeed; // Move innerLineLeft x progressively to innerLeftLineEndX if (innerLineLeft.x != innerLeftLineEndX) { innerLineLeft.x = innerLeftLineStartX + (innerLeftLineEndX - innerLeftLineStartX) * innerLineLeft.progress; } // Move innerLineLeft x progressively if (innerLineLeft.rotation != innerLeftLineEndR) { //innerLineLeft.rotation = innerLeftLineStartR + (innerLeftLineEndR - innerLeftLineStartR) * innerLineLeft.progress; } // Move innerLineLeft x progressively if (innerLineLeft.width != innerLeftLineEndW) { innerLineLeft.width = innerLeftLineStartW + (innerLeftLineEndW - innerLeftLineStartW) * innerLineLeft.progress; } // Move innerLineLeft x progressively if (innerLineLeft.height != innerLeftLineEndH) { innerLineLeft.height = innerLeftLineStartH + (innerLeftLineEndH - innerLeftLineStartH) * innerLineLeft.progress; } } for (var i = 0; i < self.innerRightLines.length; i++) { innerLineRight = self.innerRightLines[i]; innerLineRight.tint = newTint; if (innerLineRight.y > innerLineEndY) { self.resetInnerLine(innerLineRight, false); } else { innerLineRight.progress = Math.max(0, innerLineRight.y - innerLineStartY) / (innerLineEndY - innerLineStartY); } var tempSpeed = currentSpeed * 0.05 + currentSpeed * (innerLineRight.progress * 3); var newSpeed = currentSpeed; // + 10 * self.progress; newSpeed = tempSpeed * 1; // TEMP DEBUG !!! innerLineRight.y += newSpeed; // Move innerLineRight x progressively to innerRightLineEndX if (innerLineRight.x != innerRightLineEndX) { innerLineRight.x = innerRightLineStartX + (innerRightLineEndX - innerRightLineStartX) * innerLineRight.progress; } // Move innerLineRight x progressively if (innerLineRight.rotation != innerRightLineEndR) { //innerLineRight.rotation = innerRightLineStartR + (innerRightLineEndR - innerRightLineStartR) * innerLineRight.progress; } // Move innerLineRight x progressively if (innerLineRight.width != innerRightLineEndW) { innerLineRight.width = innerRightLineStartW + (innerRightLineEndW - innerRightLineStartW) * innerLineRight.progress; } // Move innerLineRight x progressively if (innerLineRight.height != innerRightLineEndH) { innerLineRight.height = innerRightLineStartH + (innerRightLineEndH - innerRightLineStartH) * innerLineRight.progress; } } // Lamp posts for (var i = 0; i < self.leftLampPosts.length; i++) { var leftLampPost = self.leftLampPosts[i]; //leftLampPost.tint = newTint; var tempProgress = Math.max(0, leftLampPost.y - leftLampStartY) / (leftLampEndY - leftLampStartY); var tempSpeed = currentSpeed * 0.05 + currentSpeed * (tempProgress * 3); leftLampPost.y += tempSpeed; //leftLampPost.visible = currentLevel !== 1; // Make lampPost not visible when level is 1 if (leftLampPost.y > leftLampEndY) { leftLampPost.y = leftLampStartY; leftLampPost.x = leftLampStartX; leftLampPost.height = leftLampStartH; } leftLampPost.progress = Math.max(0, leftLampPost.y - leftLampStartY) / (leftLampEndY - leftLampStartY); // Update progress property leftLampPost.alpha = 0.75 + Math.min(0.25, leftLampPost.progress); if (i == 0) { //debugTxt.setText(leftLampPost.progress.toFixed(2)); } if (leftLampPost.x != leftLampEndX) { leftLampPost.x = leftLampStartX + (leftLampEndX - leftLampStartX) * Math.min(1, leftLampPost.progress * 1); } if (leftLampPost.height != leftLampEndH) { leftLampPost.height = Math.min(1, leftLampPost.progress * 2) * leftLampEndH; // leftLampStartH + (leftLampEndH - leftLampStartH) * Math.min(1, leftLampPost.progress * 1); leftLampPost.width = leftLampPost.height * leftLampWRatio; } } for (var i = 0; i < self.rightLampPosts.length; i++) { var rightLampPost = self.rightLampPosts[i]; var tempProgress = Math.max(0, rightLampPost.y - rightLampStartY) / (rightLampEndY - rightLampStartY); var tempSpeed = currentSpeed * 0.05 + currentSpeed * (tempProgress * 3); rightLampPost.y += tempSpeed; //rightLampPost.visible = currentLevel !== 1; // Make right lampPost not visible when level is 1 if (rightLampPost.y > rightLampEndY) { rightLampPost.y = rightLampStartY; rightLampPost.x = rightLampStartX; rightLampPost.height = rightLampStartH; } rightLampPost.progress = Math.max(0, rightLampPost.y - rightLampStartY) / (rightLampEndY - rightLampStartY); rightLampPost.alpha = 0.75 + Math.min(0.25, rightLampPost.progress); if (rightLampPost.x != rightLampEndX) { rightLampPost.x = rightLampStartX + (rightLampEndX - rightLampStartX) * rightLampPost.progress; } if (rightLampPost.height != leftLampEndH) { rightLampPost.height = rightLampStartH + (rightLampEndH - rightLampStartH) * Math.min(1, rightLampPost.progress * 2); rightLampPost.width = rightLampPost.height * rightLampWRatio; } } }; self.updateForLevel = function (level) { // Iterate through left lamp posts for (var i = 0; i < self.leftLampPosts.length; i++) { var leftLampPost = self.leftLampPosts[i]; var newLeftLampPost = self.attachAsset(leftLampPostAssets[level - 1], { anchorX: 0.5, anchorY: 0.5, height: leftLampPost.height, width: leftLampPost.width }); newLeftLampPost.visible = leftLampPost.visible; newLeftLampPost.x = leftLampPost.x; newLeftLampPost.y = leftLampPost.y; self.leftLampPosts[i] = newLeftLampPost; leftLampPost.destroy(); } for (var i = 0; i < self.rightLampPosts.length; i++) { var rightLampPost = self.rightLampPosts[i]; rightLampPost.children.forEach(function (child) { child.visible = false; }); var newRightLampPost = self.attachAsset(rightLampPostAssets[level - 1], { anchorX: 0.5, anchorY: 0.5, scaleX: -1, height: rightLampPost.height, width: rightLampPost.width }); newRightLampPost.visible = rightLampPost.visible; newRightLampPost.x = rightLampPost.x; newRightLampPost.y = rightLampPost.y; self.rightLampPosts[i] = newRightLampPost; rightLampPost.destroy(); } }; self.resetInnerLine = function (innerLine, isLeft) { if (isLeft) { innerLine.x = innerLeftLineStartX; innerLine.rotation = innerLeftLineStartR; innerLine.width = innerLeftLineStartW; innerLine.height = innerLeftLineStartH; } else { innerLine.x = innerRightLineStartX; innerLine.rotation = innerRightLineStartR; innerLine.width = innerRightLineStartW; innerLine.height = innerRightLineStartH; } innerLine.y = innerLineStartY - 0.2 * roadHeight / nbInnerLines; innerLine.progress = 0; // Reset progress property }; }); var StartButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5 }); self.interactive = true; self.buttonMode = true; self.on('down', function () { LK.playMusic('bgMusic', { loop: true }); self.visible = false; updateGoalForLevel(1); // Call updateGoalForLevel(1) when start button is pressed LK.setTimeout(function () { goalText.visible = false; scoreTxt.visible = true; isPlaying = true; isGameStarted = true; }, goalAnnounceDelay); }); }); var Stripe = Container.expand(function () { var self = Container.call(this); self.stripeGraphics = self.attachAsset('stripe_1', { anchorX: 0, anchorY: 1, height: 1 }); self.stripeGraphics2 = self.attachAsset('stripe_2', { anchorX: 0, anchorY: 1, height: 1, visible: false }); self.stripeGraphics3 = self.attachAsset('stripe_3', { anchorX: 0, anchorY: 1, height: 1, visible: false }); self.progress = 0; // Initialize progress property self.update = function () { if (isKilled) { return; } self.progress = Math.max(0, self.y - roadTop) / roadHeight; // Update progress property var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf; self.stripeGraphics.tint = newTint; self.stripeGraphics2.tint = newTint; self.stripeGraphics3.tint = newTint; var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3); self.y += tempSpeed; self.stripeGraphics.height = 400 * self.progress; // Adjust height based on progress self.stripeGraphics2.height = 400 * self.progress; // Adjust height based on progress self.stripeGraphics3.height = 400 * self.progress; // Adjust height based on progress if (self.y > roadTop + roadHeight) { self.y = roadTop; self.stripeGraphics.height = 0; // Reset height to initial value self.stripeGraphics.tint = 0xFFFFFF; // Reset tint to initial value self.stripeGraphics2.height = 0; self.stripeGraphics2.tint = 0xFFFFFF; self.stripeGraphics3.height = 0; self.stripeGraphics3.tint = 0xFFFFFF; } }; self.updateForLevel = function (level) { self.stripeGraphics.visible = level === 1; self.stripeGraphics2.visible = level === 2; self.stripeGraphics3.visible = level === 3; }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Init game with black background }); /**** * Game Code ****/ function updateGoalForLevel(level) { if (level === 1) { goalText.setText('COLLECT\r\n$10'); } else if (level === 2) { goalText.setText('COLLECT\r\n$100'); } else if (level === 3) { goalText.setText('COLLECT\r\n$1 000 000+'); bonusManager.update(); // Update bonuses every game tick } ; goalText.visible = true; LK.setTimeout(function () { goalText.visible = false; }, goalAnnounceDelay); } var moneyLost = 0; // Initialize global moneyLost variable var isDebug = false; // Define global isDebug variable var occupiedPaths = [false, false, false]; // Initialize an array to track occupied paths var baseObstacleSpawnDelay = 1500; // Define global baseObstacleSpawnDelay var obstacleManager; // Define obstacleManager in the global scope var killerManager = new KillerManager(); // Initialize killerManager in the global scope var bonusManager = new BonusManager(); // Initialize killerManager in the global scope var bonusIcon = null; // Variable to store the bonus icon var lastObstacleSpawnTime = 0; // Track the last time an obstacle was spawned var bonusManager = new BonusManager(); // Initialize bonusManager in the global scope var levelConfigs = [{}, { name: "Level 1", backgroundTint: 0xeda716, coinValue: 0.10, baseSpeed: 10, nextLevelScore: 10 }, { name: "Level 2", backgroundTint: 0x2faf1d, coinValue: 1, baseSpeed: 15, nextLevelScore: 100 }, { name: "Level 3", backgroundTint: 0x6c6060, coinValue: 100, baseSpeed: 20, nextLevelScore: Infinity // Endless Runner ;) }]; var stripes = []; var nbDecorations = 10; var decorations = []; // Initialize arrays and variables var currentLevel = 1; var road = new Road(); var isPlaying = false; var isGameStarted = false; var isMouseDown = false; // Flag to track if the mouse/finger is down var isMoveAboveThreshold = false; // Flag to track if a move above threshold has been detected var isKilled = false; var killerDelay = 10000; // Delay in milliseconds before updating killer var lastKillerUpdate = 0; // Timestamp of the last killer update var currentCoinType = 0; var nextCoinTypeThreshold = 1000; var isNight = false; var roadHeight = 2000; var roadTop = 1000; // ~= road.height/2 - baseY var background; var landscape; var nbStripes = 33; var baseNbCoins = 10; var baseNbObstacles = 10; var baseBonusDelay = 10000; var coins = []; var obstacles = []; var killers = []; var road; var score = 0; var scoreTxt; var goalText; var goalAnnounceDelay = 3000; var startX = 0; var startY = 0; var endX = 0; var endY = 0; var intensity = 0; var intensityHalf = 0; var leftLampPosts = []; var rightLampPosts = []; var leftDecorations = []; var rightDecorationss = []; var maxSpeed = 70; // Define a maximum speed limit var currentSpeed = 15; //20; // Initialize currentSpeed var coinsCollected = 0; // Initialize coins collected counter var isIntersectingObstacle = false; // Flag to track if the player is currently intersecting an obstacle var lastObstacleHitTime = 0; // Timestamp of the last obstacle hit var immunityDelay = 500; // Immunity delay in milliseconds var playerPositionIndex = 1; // Initialize player position index var playerBaseY = 2732 - 300; // Define the three fixed x positions for the player var playerPositions = [2048 / 5, 2048 / 2, 4 * 2048 / 5]; // Create player var player; var debugMarker; var debugText; var debugTxt; /****************************************************************************************** */ /************************************** GAME FUNCTIONS ************************************ */ /****************************************************************************************** */ function updateScore() { var negative = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (negative) { if (score > 0) { moneyLost += Math.min(levelConfigs[currentLevel].coinValue || 1, score); } score -= levelConfigs[currentLevel].coinValue || 1; score = parseFloat(score.toFixed(1)); score = Math.max(0, score); // Ensure score doesn't go below 0 } else { var gain = levelConfigs[currentLevel].coinValue || 1; if (bonusManager.currentActiveBonus == 2) { // Multiplier bonus gain *= 2; } score += gain; score = parseFloat(score.toFixed(1)); coinsCollected += 1; // Increment coins collected counter } if (score >= levelConfigs[currentLevel].nextLevelScore) { changeLevel(currentLevel + 1); } // Format score log("score=", score, " => ", (score * 100).toFixed(0) + "¢"); if (score < 1) { scoreTxt.setText((score * 100).toFixed(0) + "¢"); } else if (score < 10) { scoreTxt.setText("$" + score.toFixed(2)); } else { scoreTxt.setText("$" + Math.floor(score)); } } // Function to change the level function changeLevel(newLevel) { log("changeLevel:", newLevel); newLevel = Math.max(1, Math.min(levelConfigs.length, newLevel)); currentLevel = newLevel; obstacleManager.updateForLevel(newLevel); currentSpeed = levelConfigs[currentLevel].baseSpeed; console.log("Level changed to:", currentLevel); // Add a big white flash effect LK.effects.flashScreen(0xFFFFFF, 1000); // Flash white for 1 second // Change background tint using levelConfig background.updateForLevel(currentLevel); // Update stripe graphics visibility based on the level stripes.forEach(function (stripe) { stripe.updateForLevel(currentLevel); }); // Update landscape based on the level landscape.updateForLevel(currentLevel); // Update player graphics based on the level player.updateForLevel(currentLevel); if (road) { road.updateForLevel(currentLevel); } coins.forEach(function (coin) { coin.updateForLevel(currentLevel); }); LK.getSound('levelWin_1').play(); updateGoalForLevel(currentLevel); bonusManager.updateForLevel(newLevel); killerManager.updateForLevel(newLevel); killerManager.lastKillerUpdate = Date.now(); // Reset the last killer update time when level changes } function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; } function playHit() { var hitSounds = ['hit_1', 'hit_2', 'hit_3']; var randomIndex = Math.floor(Math.random() * hitSounds.length); LK.getSound(hitSounds[randomIndex]).play(); } function updateBackgroundColor() { var time = 1000 + new Date().getTime() * 0.0002; intensity = Math.sin(time) * 127 + 128; var baseColor = levelConfigs[currentLevel].backgroundTint; var r = (baseColor >> 16 & 0xFF) + intensity; var g = (baseColor >> 8 & 0xFF) + intensity; var b = (baseColor & 0xFF) + intensity; r = Math.min(255, Math.max(0, r)); g = Math.min(255, Math.max(0, g)); b = Math.min(255, Math.max(0, b)); var color = r << 16 | g << 8 | b; background.tint = color; isNight = intensity < 128; intensityHalf = 128 + Math.floor(intensity * 0.5); } function log() { if (isDebug) { var _console; (_console = console).log.apply(_console, arguments); } } /****************************************************************************************** */ /************************************** INPUT HANDLERS ************************************ */ /****************************************************************************************** */ // Handle move events game.down = function (x, y, obj) { if (!isPlaying) { return; } startX = x; startY = y; isMouseDown = true; // Set flag to true when mouse/finger is down }; game.move = function (x, y, obj) { if (!isPlaying || !isMouseDown) { return; } var deltaX = x - startX; var deltaY = startY - y; var threshold = 10; // Define a threshold for movement if ((Math.abs(deltaX) > threshold || deltaY > threshold) && !isMoveAboveThreshold) { isMoveAboveThreshold = true; if (Math.abs(deltaX) > deltaY) { if (deltaX > 0) { // Swipe right if (playerPositionIndex < 2) { playerPositionIndex++; } } else { // Swipe left if (playerPositionIndex > 0) { playerPositionIndex--; } } // Make the player move progressively to the next path var targetX = playerPositions[playerPositionIndex]; var initialX = player.x; var moveDuration = 20; var moveStartTime = Date.now(); var moveInterval = LK.setInterval(function () { var elapsed = Date.now() - moveStartTime; var progress = elapsed / (moveDuration * 1000 / 60); if (progress < 1) { var easeProgress = easeInOutQuad(progress); player.x = initialX + (targetX - initialX) * easeProgress; } else { player.x = targetX; LK.clearInterval(moveInterval); } }, 1000 / 60); } else { if (deltaY > threshold) { // Swipe up player.jump(); } } } }; game.up = function (x, y, obj) { isMouseDown = false; // Set flag to false when mouse/finger is up isMoveAboveThreshold = false; // Reset flag when the move ends if (isKilled) { LK.setScore(score * 100); // Store the score in LK score before game over LK.setTimeout(function () { LK.stopMusic(); LK.showGameOver(); }, 500); return; } if (!isPlaying) { return; } }; // Update game every tick game.update = function () { updateBackgroundColor(); if (!isPlaying || isKilled) { return; } }; // Initialize game function gameInitialize() { bonusManager.resetBonuses(); // Reset bonuses when initializing the game killerManager.resetKillers(); killerManager.lastKillerUpdate = Date.now(); // Reset the last killer update time when initializing the game // Initialize arrays and variables // Attach the background asset to the game background = game.addChild(new Background()); background.updateForLevel(currentLevel); // Add a series of Stripe instances to cover the bottom half of the screen for (var i = 0; i < nbStripes; i++) { var stripe = new Stripe(); stripe.y = i === 0 ? roadTop : stripes[i - 1].y + stripes[i - 1].stripeGraphics.height; // Position stripe under the previous one using previous stripe y and height stripe.progress = Math.max(0, stripe.y - roadTop) / roadHeight; // Calculate progress stripes.push(stripe); game.addChild(stripe); stripe.stripeGraphics.height = 1 + 400 * stripe.progress; // Adjust height based on progress //log("Stripe ", i, " y=", stripe.y, " h=", stripe.stripeGraphics.height, " p=", stripe.progress); } for (var i = 0; i < stripes.length; i++) { stripes[i].update(); } // Create and attach decoration instances to the game for (var i = 0; i < nbDecorations; i++) { var newDecoration = new Decoration(i); newDecoration.reset(); decorations.push(newDecoration); game.addChild(newDecoration); } // Create and attach the road instance to the game road = game.addChild(new Road()); road.x = 2048 / 2; road.y = 0; if (road) { //road.updateForLevel(currentLevel); } score = 0; scoreTxt = new Text2('0¢', { size: 150, fill: "#ffffff", dropShadow: true, dropShadowColor: "#000000", dropShadowBlur: 5, dropShadowDistance: 5 }); scoreTxt.anchor.set(0.5, 0); scoreTxt.visible = false; goalText = new Text2('', { size: 150, fill: "#ffffff", dropShadow: true, dropShadowColor: "#111111", dropShadowBlur: 10, dropShadowDistance: 10, align: 'center', weight: 1000 }); goalText.anchor.set(0.5, 1); LK.gui.center.addChild(goalText); //goalText.x = 2048 / 2; //goalText.y = 100; //goalText.visible = true; LK.gui.top.addChild(scoreTxt); coins = []; for (var i = 0; i < baseNbCoins; i++) { var newCoin = new Coin(i); newCoin.reset(); newCoin.y = roadTop - i * 50; coins.push(newCoin); game.addChild(newCoin); } // Create a variable to store the current player position index playerPositionIndex = 1; // Create and attach obstacle instances to the game obstacleManager = new ObstacleManager(); var numObstacles = Math.floor(Math.random() * baseNbObstacles) + 1; // Randomize number of obstacles (1 to baseNbObstacles) for (var i = 0; i < numObstacles; i++) { var newObstacle = new Obstacle(i); obstacleManager.addObstacle(newObstacle); game.addChild(newObstacle); } obstacleManager.resetObstacles(); game.addChild(obstacleManager); // Create and attach the killer instance to the game // killerManager is already initialized in the global scope for (var i = 0; i < 3; i++) { var newKiller = new Killer(i); // Pass index for each killer killerManager.addKiller(newKiller); game.addChild(newKiller); } killerManager.resetKillers(); game.addChild(killerManager); // Create and attach the bonus instance to the game // bonusManager is already initialized in the global scope for (var i = 0; i < 3; i++) { var newBonus = new Bonus(i); // Pass index for each killer bonusManager.addBonus(newBonus); game.addChild(newBonus); } bonusManager.resetBonuses(); game.addChild(bonusManager); // Create player player = game.addChild(new Player()); player.frame = 0; player.x = playerPositions[playerPositionIndex]; // Start at the center position player.y = playerBaseY; // Create and attach the landscape instance to the game landscape = game.addChild(new Landscape()); var startButton = game.addChild(new StartButton()); startButton.x = 2048 / 2; startButton.y = 2732 / 4; // TEMP DEBUG !!! //startButton.width = 100; //startButton.height = 100; // Attach a debugMarker asset to the game at position (1000, 0) debugMarker = game.attachAsset('debugMarker', { anchorX: 0.5, anchorY: 0.5, visible: isDebug }); debugMarker.x = 1280; debugMarker.y = roadTop; debugTxt = new Text2('Debug Info', { size: 50, fill: "#ff0000" }); debugTxt.anchor.set(1, 1); // Set anchor to the bottom right corner debugTxt.visible = isDebug; LK.gui.bottomRight.addChild(debugTxt); isPlaying = false; } gameInitialize();
===================================================================
--- original.js
+++ change.js
@@ -144,9 +144,9 @@
var currentTime = Date.now();
var currentDelay = currentTime - self.lastBonusUpdate;
if (currentDelay >= self.bonusDelay) {
LK.getSound('bonus_approaching').play();
- self.currentBonusIndex = 0; // TEMP DEBUG (self.currentBonusIndex + 1) % self.bonuses.length;
+ self.currentBonusIndex = (self.currentBonusIndex + 1) % self.bonuses.length;
self.bonuses[self.currentBonusIndex].inactive = false;
self.lastBonusUpdate = currentTime;
}
};
@@ -158,13 +158,13 @@
self.lastBonusUpdate = Date.now();
};
self.updateForLevel = function (level) {
if (level === 1) {
- self.bonusDelay = 16000; // Delay in milliseconds for level 1
+ self.bonusDelay = 8000; // Delay in milliseconds for level 1
} else if (level === 2) {
self.bonusDelay = 12000; // Delay in milliseconds for level 2
} else if (level === 3) {
- self.bonusDelay = 9000; // Delay in milliseconds for level 3
+ self.bonusDelay = 16000; // Delay in milliseconds for level 3
}
};
self.applyBonus = function (index) {
self.currentActiveBonus = index + 1;
@@ -541,8 +541,9 @@
if (self.inactive) {
return;
}
if (!isKilled && player && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) {
+ LK.getSound('accident_1').play();
if (bonusManager.currentActiveBonus == 1) {
// Have Helmet!
LK.effects.flashScreen(0xffffff, 2000);
self.reset();
@@ -551,9 +552,8 @@
}
isKilled = true;
player.visible = false;
LK.stopMusic();
- LK.getSound('accident_1').play();
LK.setTimeout(function () {
LK.getSound('killed_1').play();
}, 100); // Adjust the delay as needed
LK.setTimeout(function () {
@@ -577,9 +577,9 @@
killerGraphics.width = startSize + (endSize - startSize) * self.progress;
debugTxt.setText(self.progress.toFixed(2));
killerGraphics.height = assetHeightRatio * killerGraphics.width;
var tempSpeed = currentSpeed * 0.5 + currentSpeed * (self.progress * 3);
- var newSpeed = currentSpeed * 3;
+ var newSpeed = currentSpeed * 3 + (currentLevel - 1);
newSpeed = tempSpeed * 1;
self.y += newSpeed;
if (self.pathIndex == 0 && self.x != leftEndX) {
self.x = leftStartX + (leftEndX - leftStartX) * self.progress;
@@ -984,9 +984,11 @@
self.helmet.visible = bonusManager.currentActiveBonus == 1;
if (self.helmet.visible) {
self.helmet.scale.x *= -1;
self.helmet.x *= -1;
- self.helmet.y = currentLevel == 2 ? -190 : -210;
+ self.helmet.y = currentLevel == 2 ? -170 : -210;
+ self.helmet.scale.x = currentLevel == 3 ? 1.1 : 1;
+ self.helmet.scale.y = currentLevel == 3 ? 1.1 : 1;
}
}
}
};
@@ -1476,9 +1478,9 @@
name: "Level 1",
backgroundTint: 0xeda716,
coinValue: 0.10,
baseSpeed: 10,
- nextLevelScore: 1
+ nextLevelScore: 10
}, {
name: "Level 2",
backgroundTint: 0x2faf1d,
coinValue: 1,
@@ -1853,7 +1855,5 @@
debugTxt.visible = isDebug;
LK.gui.bottomRight.addChild(debugTxt);
isPlaying = false;
}
-gameInitialize();
-// DEVLOG:
-// Fix Conis behavious with Bonus 3 (magnet)
\ No newline at end of file
+gameInitialize();
\ No newline at end of file
Directly overhead, plumb view of a beggar heading top (we see his back).. Zenith view, directly overhead, plumb view. NOT PERSPECTIVE! Fantasy theme. Pixel art
a traffic cone. video game sprite
face view of a big start button in the shape of a dollar bill. video game style
a tree. video game style
a black garbage bag. video game style
Dollar bill. Perspective. video game sprite
perspective of a simple snake rolled up on itself.. video game sprite
Ball of dry desert bushes. video game sprite
tractor. high definition video game sprite
street ad billboard with 1 or 2 posts with "Get rich!" on it. high definition video game sprite
a dog sleeping on a street. video game sprite
desert bush. video game sprite
profile view of an empty motorcycle helmet. black with a white vertical central band and another thiner orange band on the center. NOT PERSPECTIVE!. Pixel art high definition
simple red and white magnet. video game style
gold sign with a "X" and a "2". video game style
bgMusic
Music
coin_1
Sound effect
hit_1
Sound effect
hit_2
Sound effect
hit_3
Sound effect
levelWin_1
Sound effect
car_1
Sound effect
police_1
Sound effect
ambulance_1
Sound effect
accident_1
Sound effect
killed_1
Sound effect
jump_1
Sound effect
rip_1
Sound effect
bonus_take
Sound effect
bonus_approaching
Sound effect