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.bonusIcon = null;
	self.currentBonusIndex = 0;
	self.bonusIcon = null;
	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 = 0; // TEMP DEBUG (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 = 16000; // 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.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)) {
			if (bonusManager.currentActiveBonus == 1) {
				// Have Helmet!
				LK.effects.flashScreen(0xffffff, 2000);
				self.reset();
				bonusManager.stopBonus();
				return;
			}
			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 () {
				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;
		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 ? -190 : -210;
				}
			}
		}
	};
	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();
// DEVLOG:
// Fix Conis behavious with Bonus 3 (magnet) ===================================================================
--- original.js
+++ change.js
@@ -113,9 +113,12 @@
 });
 var BonusManager = Container.expand(function () {
 	var self = Container.call(this);
 	self.bonuses = [];
+	self.bonusIcon = null;
+	self.bonusIcon = null;
 	self.currentBonusIndex = 0;
+	self.bonusIcon = null;
 	self.currentActiveBonus = 0;
 	self.lastBonusUpdate = 0;
 	self.bonusDelay = 16000; // Delay in milliseconds before updating bonus
 	self.addBonus = function (bonus) {
@@ -137,14 +140,15 @@
 				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.currentBonusIndex = 0; // TEMP DEBUG (self.currentBonusIndex + 1) % self.bonuses.length;
 			self.bonuses[self.currentBonusIndex].inactive = false;
 			self.lastBonusUpdate = currentTime;
 		}
 	};
@@ -185,10 +189,14 @@
 		}, baseBonusDelay - 3000);
 	};
 	self.stopBonus = function () {
 		self.currentActiveBonus = 0;
-		LK.gui.top.removeChild(self.bonusIcon);
-		self.bonusIcon.destroy();
+		if (self.bonusIcon) {
+			LK.gui.top.removeChild(self.bonusIcon);
+		}
+		if (self.bonusIcon) {
+			self.bonusIcon.destroy();
+		}
 		self.bonusIcon = null;
 		self.lastBonusUpdate = Date.now();
 	};
 });
@@ -978,9 +986,9 @@
 				self.helmet.visible = bonusManager.currentActiveBonus == 1;
 				if (self.helmet.visible) {
 					self.helmet.scale.x *= -1;
 					self.helmet.x *= -1;
-					self.helmet.y = currentLevel == 2 ? 20 : 0;
+					self.helmet.y = currentLevel == 2 ? -190 : -210;
 				}
 			}
 		}
 	};
:quality(85)/https://cdn.frvr.ai/66cb777cc36bc8152d8f8031.png%3F3) 
 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
:quality(85)/https://cdn.frvr.ai/66ccf14b9c4e45d382d11309.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66ce18e5423e03c81f87a015.png%3F3) 
 a traffic cone. video game sprite
:quality(85)/https://cdn.frvr.ai/66ce2581423e03c81f87a053.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66ce25c4423e03c81f87a056.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d0bbac423e03c81f87a179.png%3F3) 
 face view of a big start button in the shape of a dollar bill. video game style
:quality(85)/https://cdn.frvr.ai/66d1fc0e4c0bfbf86463ae2d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d428c01a40feadd85fc2ad.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d42e241a40feadd85fc2e9.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d43f291a40feadd85fc37b.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d490b11a40feadd85fc4af.png%3F3) 
 a tree. video game style
:quality(85)/https://cdn.frvr.ai/66d4d0c367ce33ddda304025.png%3F3) 
 a black garbage bag. video game style
:quality(85)/https://cdn.frvr.ai/66d4de00401d2c2487b96f5a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d4e47c651049126fa096cc.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d4e4be401d2c2487b96f78.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d555bd651049126fa096f0.png%3F3) 
 Dollar bill. Perspective. video game sprite
:quality(85)/https://cdn.frvr.ai/66d6f447a3e8b4a4a4829fb3.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d844022a19586325bec80d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d844362a19586325bec810.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d8c2645c7c6fbac545d122.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66d9373598ec289fd45d77b2.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66dd38dddaaa27ee3942c131.png%3F3) 
 perspective of a simple snake rolled up on itself.. video game sprite
:quality(85)/https://cdn.frvr.ai/66dd3a2bdaaa27ee3942c13e.png%3F3) 
 Ball of dry desert bushes. video game sprite
:quality(85)/https://cdn.frvr.ai/66dd3c02daaa27ee3942c154.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66ddb2e9bf754a83aa523fb1.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66ddb7aecc485d4eb466960b.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66de8560d88e3b2f9d0d34dd.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e0a42193e17031e44d9902.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e0a8f4ccaaa6aa21e29430.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e2701b2345adf8f56be232.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e271832345adf8f56be236.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e271d62345adf8f56be241.png%3F3) 
 tractor. high definition video game sprite
:quality(85)/https://cdn.frvr.ai/66e272f12345adf8f56be257.png%3F3) 
 street ad billboard with 1 or 2 posts with "Get rich!" on it. high definition video game sprite
:quality(85)/https://cdn.frvr.ai/66e278682345adf8f56be29e.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e27f5a2345adf8f56be2fe.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e35a3953e2dd7786ae56f8.png%3F3) 
 a dog sleeping on a street. video game sprite
:quality(85)/https://cdn.frvr.ai/66e35caa53e2dd7786ae571a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66e887ca939ae2c335f047d6.png%3F3) 
 desert bush. video game sprite
:quality(85)/https://cdn.frvr.ai/66f09079353aeac5eb1686c0.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66f09358353aeac5eb1686cc.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66f0985a353aeac5eb168728.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66f09a6c353aeac5eb16875a.png%3F3) 
 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
:quality(85)/https://cdn.frvr.ai/66f09bc6353aeac5eb16879c.png%3F3) 
 simple red and white magnet. video game style
:quality(85)/https://cdn.frvr.ai/66f0f3e0673e5ef9433cb9ac.png%3F3) 
 gold sign with a "X" and a "2". video game style
:quality(85)/https://cdn.frvr.ai/66f14bbd07176eca63330db8.png%3F3) 
 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