/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Coin class: collectible
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coinAsset = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = coinAsset.width;
	self.height = coinAsset.height;
	self.lane = 1; // will be set on spawn
	self.speed = 16; // will be set by game for difficulty
	self.update = function () {
		self.y += self.speed;
		// Optional: spin effect
		self.rotation += 0.03;
	};
	return self;
});
// Obstacle class: cracks, snow piles, ice blocks, trees, rocks
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	// Default to 'block', will be replaced on spawn if needed
	var assetId = 'block';
	var obstacleAsset = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = assetId;
	self.width = obstacleAsset.width;
	self.height = obstacleAsset.height;
	self.lane = 1; // will be set on spawn
	self.speed = 16; // will be set by game for difficulty
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Player class: the sliding character
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Attach player asset (blue ellipse for ice runner)
	var playerAsset = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set up initial properties
	self.width = playerAsset.width;
	self.height = playerAsset.height;
	self.lane = 1; // 0: left, 1: center, 2: right
	// For smooth lane transitions
	self.targetX = 0;
	// Walking animation state
	self._walkTween = null;
	self._walkDir = 1;
	// Start walking animation
	function startWalking() {
		// Stop any previous tweens on playerAsset for scaleX and scaleY
		tween.stop(playerAsset, {
			scaleX: true,
			scaleY: true
		});
		// Animate scaleX to create a "waddle" effect
		tween(playerAsset, {
			scaleX: 1.15
		}, {
			duration: 120,
			easing: tween.linear,
			yoyo: true,
			repeat: Infinity,
			onYoyo: function onYoyo() {
				// Flip direction for next step
				self._walkDir *= -1;
				playerAsset.scaleX = 1 + 0.15 * self._walkDir;
			}
		});
		// Animate scaleY for a subtle bounce
		tween(playerAsset, {
			scaleY: 0.92
		}, {
			duration: 120,
			easing: tween.linear,
			yoyo: true,
			repeat: Infinity
		});
	}
	startWalking();
	// Update method: smoothly move to targetX
	self.update = function () {
		// Smoothly move towards targetX
		self.x += (self.targetX - self.x) * 0.25;
	};
	return self;
});
// SpecialPower class: clears all obstacles when collected
var SpecialPower = Container.expand(function () {
	var self = Container.call(this);
	var asset = self.attachAsset('star', {
		// Use new star asset for superpower
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = asset.width;
	self.height = asset.height;
	self.lane = 1;
	self.speed = 16;
	self.update = function () {
		self.y += self.speed;
		self.rotation += 0.03;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	// No title, no description
	// Always backgroundColor is black
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// --- Moving, repeating background setup ---
var bg1 = LK.getAsset('bg_ice_landscape', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	width: 2048,
	height: 2732
});
var bg2 = LK.getAsset('bg_ice_landscape', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: -2732,
	width: 2048,
	height: 2732
});
game.addChild(bg1);
game.addChild(bg2);
// --- Lane setup ---
// new superpower asset
var laneCount = 3;
var laneWidth = 400; // Each lane is 400px wide
var laneCenters = [2048 / 2 - laneWidth,
// left
2048 / 2,
// center
2048 / 2 + laneWidth // right
];
// --- Player setup ---
var player = new Player();
player.y = 2732 - 400; // Near bottom
player.lane = 1;
player.x = laneCenters[player.lane];
player.targetX = player.x;
game.addChild(player);
// --- Score and GUI ---
var score = 0;
var scoreTxt = new Text2('Score: 0', {
	size: 70,
	fill: 0xFFFFFF,
	font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
scoreTxt.anchor.set(1, 0); // Anchor to right edge, top
scoreTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
scoreTxt.y = 20; // Padding from top
LK.gui.topRight.addChild(scoreTxt);
// --- Coin counter ---
var coinCount = 0;
var coinTxt = new Text2('Coin: 0', {
	size: 50,
	fill: 0xFFE066,
	font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
coinTxt.anchor.set(1, 0); // Anchor to right edge, top
coinTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
coinTxt.y = 150; // Place below score
LK.gui.topRight.addChild(coinTxt);
// --- Game state ---
var obstacles = [];
var coins = [];
var specialPowers = [];
var gameSpeed = 16; // Initial speed
var ticksSinceLastObstacle = 0;
var ticksSinceLastCoin = 0;
var ticksSinceLastPower = 0;
var nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Random interval for next power
var obstacleInterval = 60; // Frames between obstacles
var coinInterval = 90; // Frames between coins
var isDragging = false;
var dragStartX = 0;
var dragStartLane = 1;
// --- Asset initialization (shapes) ---
// --- Touch/drag controls ---
game.down = function (x, y, obj) {
	isDragging = true;
	dragStartX = x;
	dragStartLane = player.lane;
};
game.move = function (x, y, obj) {
	if (!isDragging) return;
	// Calculate drag offset
	var dx = x - dragStartX;
	// Determine which lane the drag is closest to, relative to dragStartX
	var laneOffset = Math.round(dx / laneWidth);
	var newLane = dragStartLane + laneOffset;
	if (newLane < 0) newLane = 0;
	if (newLane > 2) newLane = 2;
	if (newLane !== player.lane) {
		player.lane = newLane;
		player.targetX = laneCenters[player.lane];
	}
};
game.up = function (x, y, obj) {
	isDragging = false;
};
// --- Main game update loop ---
game.update = function () {
	// --- Animate and repeat background ---
	bg1.y += gameSpeed;
	bg2.y += gameSpeed;
	// If a background has moved off the bottom, move it above the other
	if (bg1.y >= 2732) {
		bg1.y = bg2.y - 2732;
	}
	if (bg2.y >= 2732) {
		bg2.y = bg1.y - 2732;
	}
	// Scale speed and intervals with score for dynamic difficulty (0 to 1000 points)
	var difficulty = score;
	if (difficulty > 1000) difficulty = 1000;
	// Speed: from 12 (easy) to 40 (hard) linearly
	gameSpeed = 12 + difficulty / 1000 * (40 - 12);
	// Intervals: from 60 (easy) to 30 (hard) for obstacles, 90 to 50 for coins
	obstacleInterval = 60 - difficulty / 1000 * (60 - 30);
	if (obstacleInterval < 30) obstacleInterval = 30;
	coinInterval = 90 - difficulty / 1000 * (90 - 50);
	if (coinInterval < 50) coinInterval = 50;
	gameSpeed = Math.round(gameSpeed);
	obstacleInterval = Math.round(obstacleInterval);
	coinInterval = Math.round(coinInterval);
	// Player update (smooth lane movement)
	player.update();
	// --- Spawn obstacles ---
	ticksSinceLastObstacle++;
	if (ticksSinceLastObstacle >= obstacleInterval) {
		ticksSinceLastObstacle = 0;
		// Prevent same obstacle type from spawning consecutively
		var lastType = obstacles.length > 0 ? obstacles[obstacles.length - 1].type : null;
		var possibleTypes = ['crack', 'snow', 'block', 'tree', 'rock'];
		if (lastType !== null && possibleTypes.length > 1) {
			var idx = possibleTypes.indexOf(lastType);
			if (idx !== -1) possibleTypes.splice(idx, 1);
		}
		var chosenType = possibleTypes[Math.floor(Math.random() * possibleTypes.length)];
		var obs = new Obstacle();
		obs.lane = Math.floor(Math.random() * laneCount);
		obs.x = laneCenters[obs.lane];
		obs.y = -120;
		obs.speed = gameSpeed; // Always use current gameSpeed
		// Overwrite type and asset if needed
		obs.type = chosenType;
		// Remove old asset and attach new one
		while (obs.children.length > 0) obs.removeChild(obs.children[0]);
		var obstacleAsset = obs.attachAsset(chosenType, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		obs.width = obstacleAsset.width;
		obs.height = obstacleAsset.height;
		obstacles.push(obs);
		game.addChild(obs);
	}
	// --- Spawn coins ---
	ticksSinceLastCoin++;
	if (ticksSinceLastCoin >= coinInterval) {
		ticksSinceLastCoin = 0;
		// Try to spawn coin in a lane without an obstacle at the spawn Y
		var availableLanes = [0, 1, 2];
		// Remove lanes where an obstacle is at the spawn Y (within 200px above)
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(obs.y + 100) < 200) {
				// Obstacle is close to coin spawn Y
				var idx = availableLanes.indexOf(obs.lane);
				if (idx !== -1) availableLanes.splice(idx, 1);
			}
		}
		if (availableLanes.length > 0) {
			var coin = new Coin();
			coin.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
			coin.x = laneCenters[coin.lane];
			coin.y = -100;
			coin.speed = gameSpeed; // Always use current gameSpeed
			coin.value = 1 + Math.floor(Math.random() * 5); // Random value 1-5
			coins.push(coin);
			game.addChild(coin);
		}
	}
	// --- Update obstacles ---
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		obs.update();
		// Remove if off screen
		if (obs.y > 2732 + 200) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision with player
		if (obs.lane === player.lane) {
			// Use bounding box collision
			if (obs.intersects(player)) {
				LK.effects.flashScreen(0xff0000, 800);
				LK.showGameOver();
				return;
			}
		}
	}
	// --- Update coins ---
	for (var j = coins.length - 1; j >= 0; j--) {
		var coin = coins[j];
		coin.update();
		// Remove if off screen
		if (coin.y > 2732 + 120) {
			coin.destroy();
			coins.splice(j, 1);
			continue;
		}
		// Collect coin
		if (coin.lane === player.lane) {
			if (coin.intersects(player)) {
				coinCount += coin.value || 1;
				coinTxt.setText('Coin: ' + coinCount);
				coin.destroy();
				coins.splice(j, 1);
				continue;
			}
		}
	}
	// --- Special Power spawn/update ---
	ticksSinceLastPower++;
	if (ticksSinceLastPower >= nextPowerInterval) {
		ticksSinceLastPower = 0;
		nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Next random interval
		// Try to spawn in a lane without an obstacle at spawn Y
		var availableLanes = [0, 1, 2];
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(obs.y + 100) < 200) {
				var idx = availableLanes.indexOf(obs.lane);
				if (idx !== -1) availableLanes.splice(idx, 1);
			}
		}
		if (availableLanes.length > 0) {
			var power = new SpecialPower();
			power.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
			power.x = laneCenters[power.lane];
			power.y = -100;
			power.speed = gameSpeed;
			specialPowers.push(power);
			game.addChild(power);
		}
	}
	// --- Update special powers ---
	for (var k = specialPowers.length - 1; k >= 0; k--) {
		var power = specialPowers[k];
		power.update();
		if (power.y > 2732 + 120) {
			power.destroy();
			specialPowers.splice(k, 1);
			continue;
		}
		// Collect special power
		if (power.lane === player.lane) {
			if (power.intersects(player)) {
				// Clear all obstacles on screen
				for (var i = obstacles.length - 1; i >= 0; i--) {
					obstacles[i].destroy();
					obstacles.splice(i, 1);
				}
				power.destroy();
				specialPowers.splice(k, 1);
				continue;
			}
		}
	}
	// --- Score increases with time survived ---
	if (LK.ticks % 6 === 0) {
		score += 1;
		scoreTxt.setText('Score: ' + score);
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Coin class: collectible
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coinAsset = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = coinAsset.width;
	self.height = coinAsset.height;
	self.lane = 1; // will be set on spawn
	self.speed = 16; // will be set by game for difficulty
	self.update = function () {
		self.y += self.speed;
		// Optional: spin effect
		self.rotation += 0.03;
	};
	return self;
});
// Obstacle class: cracks, snow piles, ice blocks, trees, rocks
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	// Default to 'block', will be replaced on spawn if needed
	var assetId = 'block';
	var obstacleAsset = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = assetId;
	self.width = obstacleAsset.width;
	self.height = obstacleAsset.height;
	self.lane = 1; // will be set on spawn
	self.speed = 16; // will be set by game for difficulty
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
// Player class: the sliding character
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Attach player asset (blue ellipse for ice runner)
	var playerAsset = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Set up initial properties
	self.width = playerAsset.width;
	self.height = playerAsset.height;
	self.lane = 1; // 0: left, 1: center, 2: right
	// For smooth lane transitions
	self.targetX = 0;
	// Walking animation state
	self._walkTween = null;
	self._walkDir = 1;
	// Start walking animation
	function startWalking() {
		// Stop any previous tweens on playerAsset for scaleX and scaleY
		tween.stop(playerAsset, {
			scaleX: true,
			scaleY: true
		});
		// Animate scaleX to create a "waddle" effect
		tween(playerAsset, {
			scaleX: 1.15
		}, {
			duration: 120,
			easing: tween.linear,
			yoyo: true,
			repeat: Infinity,
			onYoyo: function onYoyo() {
				// Flip direction for next step
				self._walkDir *= -1;
				playerAsset.scaleX = 1 + 0.15 * self._walkDir;
			}
		});
		// Animate scaleY for a subtle bounce
		tween(playerAsset, {
			scaleY: 0.92
		}, {
			duration: 120,
			easing: tween.linear,
			yoyo: true,
			repeat: Infinity
		});
	}
	startWalking();
	// Update method: smoothly move to targetX
	self.update = function () {
		// Smoothly move towards targetX
		self.x += (self.targetX - self.x) * 0.25;
	};
	return self;
});
// SpecialPower class: clears all obstacles when collected
var SpecialPower = Container.expand(function () {
	var self = Container.call(this);
	var asset = self.attachAsset('star', {
		// Use new star asset for superpower
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = asset.width;
	self.height = asset.height;
	self.lane = 1;
	self.speed = 16;
	self.update = function () {
		self.y += self.speed;
		self.rotation += 0.03;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	// No title, no description
	// Always backgroundColor is black
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// --- Moving, repeating background setup ---
var bg1 = LK.getAsset('bg_ice_landscape', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	width: 2048,
	height: 2732
});
var bg2 = LK.getAsset('bg_ice_landscape', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: -2732,
	width: 2048,
	height: 2732
});
game.addChild(bg1);
game.addChild(bg2);
// --- Lane setup ---
// new superpower asset
var laneCount = 3;
var laneWidth = 400; // Each lane is 400px wide
var laneCenters = [2048 / 2 - laneWidth,
// left
2048 / 2,
// center
2048 / 2 + laneWidth // right
];
// --- Player setup ---
var player = new Player();
player.y = 2732 - 400; // Near bottom
player.lane = 1;
player.x = laneCenters[player.lane];
player.targetX = player.x;
game.addChild(player);
// --- Score and GUI ---
var score = 0;
var scoreTxt = new Text2('Score: 0', {
	size: 70,
	fill: 0xFFFFFF,
	font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
scoreTxt.anchor.set(1, 0); // Anchor to right edge, top
scoreTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
scoreTxt.y = 20; // Padding from top
LK.gui.topRight.addChild(scoreTxt);
// --- Coin counter ---
var coinCount = 0;
var coinTxt = new Text2('Coin: 0', {
	size: 50,
	fill: 0xFFE066,
	font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
coinTxt.anchor.set(1, 0); // Anchor to right edge, top
coinTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
coinTxt.y = 150; // Place below score
LK.gui.topRight.addChild(coinTxt);
// --- Game state ---
var obstacles = [];
var coins = [];
var specialPowers = [];
var gameSpeed = 16; // Initial speed
var ticksSinceLastObstacle = 0;
var ticksSinceLastCoin = 0;
var ticksSinceLastPower = 0;
var nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Random interval for next power
var obstacleInterval = 60; // Frames between obstacles
var coinInterval = 90; // Frames between coins
var isDragging = false;
var dragStartX = 0;
var dragStartLane = 1;
// --- Asset initialization (shapes) ---
// --- Touch/drag controls ---
game.down = function (x, y, obj) {
	isDragging = true;
	dragStartX = x;
	dragStartLane = player.lane;
};
game.move = function (x, y, obj) {
	if (!isDragging) return;
	// Calculate drag offset
	var dx = x - dragStartX;
	// Determine which lane the drag is closest to, relative to dragStartX
	var laneOffset = Math.round(dx / laneWidth);
	var newLane = dragStartLane + laneOffset;
	if (newLane < 0) newLane = 0;
	if (newLane > 2) newLane = 2;
	if (newLane !== player.lane) {
		player.lane = newLane;
		player.targetX = laneCenters[player.lane];
	}
};
game.up = function (x, y, obj) {
	isDragging = false;
};
// --- Main game update loop ---
game.update = function () {
	// --- Animate and repeat background ---
	bg1.y += gameSpeed;
	bg2.y += gameSpeed;
	// If a background has moved off the bottom, move it above the other
	if (bg1.y >= 2732) {
		bg1.y = bg2.y - 2732;
	}
	if (bg2.y >= 2732) {
		bg2.y = bg1.y - 2732;
	}
	// Scale speed and intervals with score for dynamic difficulty (0 to 1000 points)
	var difficulty = score;
	if (difficulty > 1000) difficulty = 1000;
	// Speed: from 12 (easy) to 40 (hard) linearly
	gameSpeed = 12 + difficulty / 1000 * (40 - 12);
	// Intervals: from 60 (easy) to 30 (hard) for obstacles, 90 to 50 for coins
	obstacleInterval = 60 - difficulty / 1000 * (60 - 30);
	if (obstacleInterval < 30) obstacleInterval = 30;
	coinInterval = 90 - difficulty / 1000 * (90 - 50);
	if (coinInterval < 50) coinInterval = 50;
	gameSpeed = Math.round(gameSpeed);
	obstacleInterval = Math.round(obstacleInterval);
	coinInterval = Math.round(coinInterval);
	// Player update (smooth lane movement)
	player.update();
	// --- Spawn obstacles ---
	ticksSinceLastObstacle++;
	if (ticksSinceLastObstacle >= obstacleInterval) {
		ticksSinceLastObstacle = 0;
		// Prevent same obstacle type from spawning consecutively
		var lastType = obstacles.length > 0 ? obstacles[obstacles.length - 1].type : null;
		var possibleTypes = ['crack', 'snow', 'block', 'tree', 'rock'];
		if (lastType !== null && possibleTypes.length > 1) {
			var idx = possibleTypes.indexOf(lastType);
			if (idx !== -1) possibleTypes.splice(idx, 1);
		}
		var chosenType = possibleTypes[Math.floor(Math.random() * possibleTypes.length)];
		var obs = new Obstacle();
		obs.lane = Math.floor(Math.random() * laneCount);
		obs.x = laneCenters[obs.lane];
		obs.y = -120;
		obs.speed = gameSpeed; // Always use current gameSpeed
		// Overwrite type and asset if needed
		obs.type = chosenType;
		// Remove old asset and attach new one
		while (obs.children.length > 0) obs.removeChild(obs.children[0]);
		var obstacleAsset = obs.attachAsset(chosenType, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		obs.width = obstacleAsset.width;
		obs.height = obstacleAsset.height;
		obstacles.push(obs);
		game.addChild(obs);
	}
	// --- Spawn coins ---
	ticksSinceLastCoin++;
	if (ticksSinceLastCoin >= coinInterval) {
		ticksSinceLastCoin = 0;
		// Try to spawn coin in a lane without an obstacle at the spawn Y
		var availableLanes = [0, 1, 2];
		// Remove lanes where an obstacle is at the spawn Y (within 200px above)
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(obs.y + 100) < 200) {
				// Obstacle is close to coin spawn Y
				var idx = availableLanes.indexOf(obs.lane);
				if (idx !== -1) availableLanes.splice(idx, 1);
			}
		}
		if (availableLanes.length > 0) {
			var coin = new Coin();
			coin.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
			coin.x = laneCenters[coin.lane];
			coin.y = -100;
			coin.speed = gameSpeed; // Always use current gameSpeed
			coin.value = 1 + Math.floor(Math.random() * 5); // Random value 1-5
			coins.push(coin);
			game.addChild(coin);
		}
	}
	// --- Update obstacles ---
	for (var i = obstacles.length - 1; i >= 0; i--) {
		var obs = obstacles[i];
		obs.update();
		// Remove if off screen
		if (obs.y > 2732 + 200) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision with player
		if (obs.lane === player.lane) {
			// Use bounding box collision
			if (obs.intersects(player)) {
				LK.effects.flashScreen(0xff0000, 800);
				LK.showGameOver();
				return;
			}
		}
	}
	// --- Update coins ---
	for (var j = coins.length - 1; j >= 0; j--) {
		var coin = coins[j];
		coin.update();
		// Remove if off screen
		if (coin.y > 2732 + 120) {
			coin.destroy();
			coins.splice(j, 1);
			continue;
		}
		// Collect coin
		if (coin.lane === player.lane) {
			if (coin.intersects(player)) {
				coinCount += coin.value || 1;
				coinTxt.setText('Coin: ' + coinCount);
				coin.destroy();
				coins.splice(j, 1);
				continue;
			}
		}
	}
	// --- Special Power spawn/update ---
	ticksSinceLastPower++;
	if (ticksSinceLastPower >= nextPowerInterval) {
		ticksSinceLastPower = 0;
		nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Next random interval
		// Try to spawn in a lane without an obstacle at spawn Y
		var availableLanes = [0, 1, 2];
		for (var i = 0; i < obstacles.length; i++) {
			var obs = obstacles[i];
			if (Math.abs(obs.y + 100) < 200) {
				var idx = availableLanes.indexOf(obs.lane);
				if (idx !== -1) availableLanes.splice(idx, 1);
			}
		}
		if (availableLanes.length > 0) {
			var power = new SpecialPower();
			power.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
			power.x = laneCenters[power.lane];
			power.y = -100;
			power.speed = gameSpeed;
			specialPowers.push(power);
			game.addChild(power);
		}
	}
	// --- Update special powers ---
	for (var k = specialPowers.length - 1; k >= 0; k--) {
		var power = specialPowers[k];
		power.update();
		if (power.y > 2732 + 120) {
			power.destroy();
			specialPowers.splice(k, 1);
			continue;
		}
		// Collect special power
		if (power.lane === player.lane) {
			if (power.intersects(player)) {
				// Clear all obstacles on screen
				for (var i = obstacles.length - 1; i >= 0; i--) {
					obstacles[i].destroy();
					obstacles.splice(i, 1);
				}
				power.destroy();
				specialPowers.splice(k, 1);
				continue;
			}
		}
	}
	// --- Score increases with time survived ---
	if (LK.ticks % 6 === 0) {
		score += 1;
		scoreTxt.setText('Score: ' + score);
	}
};
 Pixel 2d coin. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 2d pixel snow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 2d pixel ice block. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 2d pixel crack. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 2d pixel potion. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 Let it be turned back
 2d pixel dried tree. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 2d pixel rock. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 Let it be in a way that can repeat itself when it moves