/**** 
* Classes
****/ 
var BloodsplatterEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var duration = 15;
	var remaining = duration;
	var maxScale = 2.0;
	var startAlpha = 0.5;
	var graphics = self.attachAsset('bloodsplatter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	graphics.alpha = startAlpha;
	graphics.y = -graphics.height / 2;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY) {
		var progress = 1 - remaining-- / duration;
		if (remaining <= 0) {
			return true;
		}
		graphics.scale.set(1 + (maxScale - 1) * progress);
		graphics.alpha = startAlpha * (1 - progress);
		self.x -= velocityX;
		self.y -= velocityY;
	}
});
var DropEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var angle = Math.random() * Math.PI;
	var speed = 10 + Math.random() * 5;
	var speedX = Math.cos(angle) * speed;
	var speedY = Math.sin(angle) * speed;
	var spinSpeed = Math.random() * 0.2 - 0.1;
	var scale = 1;
	var scaleDecrement = 1 / 60;
	var variant = Math.floor(Math.random() * 3);
	var graphics = self.createAsset('pickup' + variant, {
		anchorX: 0.5,
		anchorY: 0.95
	});
	graphics.rotation = Math.random() * Math.PI * 2;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY) {
		self.x += speedX - velocityX;
		self.y += speedY - velocityY;
		scale -= scaleDecrement;
		graphics.rotation += spinSpeed;
		graphics.scale.set(scale);
		return scale <= 0;
	}
});
var Interface = Container.expand(function (x, y) {
	var self = Container.call(this);
	var score = 0;
	var lives = 3;
	var lifeIcons = [];
	var scoreIcon = self.attachAsset('scoreIcon', {
		anchorX: 0.5
	});
	var scoreText = self.addChild(new Text2('| ' + score, {
		size: 70,
		fill: 0x000000,
		align: 'left'
	}));
	var distanceText = self.addChild(new Text2('0m', {
		size: 70,
		fill: 0x000000,
		align: 'right'
	}));
	for (var i = 0; i < lives; i++) {
		var lifeIcon = self.attachAsset('lifeIcon', {
			anchorX: 1
		});
		lifeIcon.x = -10 - i * 60;
		lifeIcon.y = scoreIcon.height + 20;
		lifeIcons.push(lifeIcon);
	}
	scoreText.x = -5;
	scoreText.y = scoreIcon.height;
	scoreText.anchor.set(0, 0);
	distanceText.x = STAGE_WIDTH / 2 - 350;
	distanceText.y = 30;
	distanceText.anchor.set(1, 0);
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	self.changeScore = changeScore;
	self.changeLives = changeLives;
	;
	function _update_migrated(distance) {
		distanceText.setText(Math.round(distance * SCREEN_METERAGE) + 'm');
	}
	function changeLives(amount) {
		lives += amount;
		for (var i = 0; i < lifeIcons.length; i++) {
			lifeIcons[i].alpha = i < lives ? 1 : 0.5;
		}
		if (amount < 0) {
			LK.effects.flashScreen(0xaa0000, 300);
			if (lives <= 0) {
				return true;
			}
		}
		return false;
	}
	function changeScore(amount) {
		var returnValue = amount < 0 && score > 0;
		score = Math.max(0, score + amount);
		LK.setScore(score);
		scoreText.setText('| ' + score);
		return returnValue;
	}
});
var LandscapeTile = Container.expand(function (x, y, _ref) {
	var self = Container.call(this);
	var lookup = _ref.lookup,
		xIndex = _ref.xIndex,
		yIndex = _ref.yIndex,
		density = _ref.density,
		pickups = _ref.pickups,
		monsters = _ref.monsters,
		player = _ref.player,
		key = _ref.key,
		landscapeTiles = _ref.landscapeTiles,
		layers = _ref.layers,
		rampList = _ref.rampList;
	var obstructions = [];
	var background = self.attachAsset('landscapeBackground', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	background.width = TILE_SIZE;
	background.height = TILE_SIZE;
	background.alpha = 0.03;
	background.x = yIndex % 2 === 0 ? TILE_BACKGROUND_OFFSET : 0;
	;
	self.x = x;
	self.y = y;
	self.activate = activate;
	self.active = false;
	self.key = key;
	self.checkCollision = checkCollision;
	;
	function checkCollision(player) {
		if (!player.airborne) {
			var reach = 200;
			var dx = Math.abs(player.x - self.x);
			var dy = Math.abs(player.y - self.y);
			if (dx < TILE_SIZE / 2 + reach && dy < TILE_SIZE / 2 + reach) {
				for (var i = 0; i < obstructions.length; i++) {
					var obstruction = obstructions[i];
					if (obstruction.active && player.hitbox.intersects(obstruction.hitbox)) {
						obstruction.deactivate();
						return true;
					}
				}
			}
		}
		return false;
	}
	function activate() {
		if (!self.active) {
			self.active = true;
			var densityChance = density * Math.random();
			var obstructionTypes = ['largeTree', 'smallTree', 'smallTree', 'deadTree', 'smallRock', 'smallRock', 'largeRock', 'stump'];
			var clearanceDist = 300;
			var clearanceDistSqr = clearanceDist * clearanceDist;
			var spawnBorder = 25;
			var cellSize = 150;
			var cols = Math.ceil(TILE_SIZE / cellSize);
			var rows = Math.ceil(TILE_SIZE / cellSize);
			var cellWidth = TILE_SIZE / cols;
			var cellHeight = TILE_SIZE / rows;
			var landmark;
			if (Math.random() <= SPAWN_PICKUP_CHANCE) {
				var _randomPointInRect = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect.pointX,
					pointY = _randomPointInRect.pointY;
				pickups.push(landmark = self.parent.addChild(new Pickup(pointX, pointY)));
			} else if (Math.random() <= SPAWN_RAMP_CHANCE) {
				var _randomPointInRect2 = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect2.pointX,
					pointY = _randomPointInRect2.pointY;
				rampList.push(landmark = layers[LAYER_BACKGROUND].addChild(new Ramp(pointX, pointY)));
			}
			if (player.distanceTravelled > MONSTER_SPAWN_DIST && Math.random() <= SPAWN_MONSTER_CHANCE) {
				var _randomPointInRect3 = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect3.pointX,
					pointY = _randomPointInRect3.pointY;
				monsters.push(self.parent.addChild(new Monster(self.x, self.y)));
			}
			for (i = 0; i < cols; i++) {
				for (j = 0; j < rows; j++) {
					if (Math.random() <= densityChance) {
						var canPlace = true;
						var _randomPointInRect4 = randomPointInRect(cellWidth * i, cellHeight * j, cellWidth, cellHeight, spawnBorder),
							pointX = _randomPointInRect4.pointX,
							pointY = _randomPointInRect4.pointY;
						if (landmark) {
							var dx = landmark.x - pointX;
							var dy = landmark.y - pointY;
							var distSqr = dx * dx + dy * dy;
							if (distSqr <= clearanceDistSqr) {
								canPlace = false;
							}
						}
						if (canPlace) {
							var type = obstructionTypes[Math.floor(Math.random() * obstructionTypes.length)];
							obstructions.push(self.addChild(new Obstruction(pointX, pointY, type)));
						}
					}
				}
			}
		}
		var leftKey = xIndex - 1 + ':' + yIndex;
		var rightKey = xIndex + 1 + ':' + yIndex;
		var downKey = xIndex + ':' + (yIndex + 1);
		var newDensity = (1 + Math.pow(Math.log(player.distanceTravelled / DIFFICULTY_FACTOR_DIST + 2), 2)) / 100;
		if (!lookup[leftKey]) {
			landscapeTiles.push(lookup[leftKey] = self.parent.addChild(new LandscapeTile(self.x - TILE_SIZE, self.y, {
				key: leftKey,
				density: newDensity,
				xIndex: xIndex - 1,
				yIndex: yIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		if (!lookup[rightKey]) {
			landscapeTiles.push(lookup[rightKey] = self.parent.addChild(new LandscapeTile(self.x + TILE_SIZE, self.y, {
				key: rightKey,
				density: newDensity,
				xIndex: xIndex + 1,
				yIndex: yIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		if (!lookup[downKey]) {
			landscapeTiles.push(lookup[downKey] = self.parent.addChild(new LandscapeTile(self.x, self.y + TILE_SIZE, {
				key: downKey,
				density: newDensity,
				yIndex: yIndex + 1,
				xIndex: xIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		function randomPointInRect(centerX, centerY, width, height) {
			var border = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
			var startX = centerX - width / 2 + border;
			var startY = centerY - height / 2 + border;
			var innerWidth = width - border * 2;
			var innerHeight = height - border * 2;
			var pointX = startX + Math.random() * innerWidth;
			var pointY = startY + Math.random() * innerHeight;
			return {
				pointX: pointX,
				pointY: pointY
			};
		}
	}
});
var Monster = Container.expand(function (x, y) {
	var self = Container.call(this);
	var active = false;
	var updateTick = 0;
	var updatePeriod = 30;
	var jumpSpeedMax = 30;
	var jumpHeight = 100;
	var jumpVelocityX = 0;
	var jumpVelocityY = 0;
	var jumpDuration = updatePeriod * 2 / 3;
	var invulnerabilityBoost = 1.8;
	var jumpDistMax = jumpSpeedMax * jumpDuration;
	var jumpDistMaxSqr = jumpDistMax * jumpDistMax;
	var activationDist = 1000;
	var activationDistSqr = activationDist * activationDist;
	var despawnY = -2500;
	var shadowReduction = 0.1;
	var shadow = self.attachAsset('shadow', {
		anchorX: 0.45,
		anchorY: 1
	});
	var graphics = self.attachAsset('monster', {
		anchorX: 0.5,
		anchorY: 1
	});
	graphics.scale.x = Math.random() < 0.5 ? 1 : -1;
	shadow.width = graphics.width * 0.9;
	shadow.height = graphics.width * 0.45;
	shadow.tint = 0x000000;
	shadow.alpha = 0.5;
	;
	self.x = x;
	self.y = y;
	self.jumping = false;
	self.hitbox = shadow;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		if (!active) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distSqr = dx * dx + dy * dy;
			if (distSqr <= activationDistSqr) {
				active = true;
			}
		}
		if (active) {
			var updateCurve = (-Math.cos(++updateTick * Math.PI / (updatePeriod / 2)) + 0.5) / 1.5;
			if (self.jumping) {
				if (updateCurve <= 0) {
					self.jumping = false;
					jumpVelocityX = 0;
					jumpVelocityY = 0;
				}
			} else {
				if (updateCurve > 0) {
					var boost = player.invulnerable ? invulnerabilityBoost : 1;
					var targetPosX = player.x + velocityX * jumpDuration * boost;
					var targetPosY = player.y + velocityY * jumpDuration * boost;
					var ddx = targetPosX - self.x;
					var ddy = targetPosY - self.y;
					var angle = Math.atan2(ddy, ddx);
					var targetDistSqr = ddx * ddx + ddy * ddy;
					var jumpSpeed = jumpSpeedMax * (targetDistSqr >= jumpDistMaxSqr ? 1 : Math.sqrt(targetDistSqr) / jumpDistMax);
					jumpVelocityX = Math.cos(angle) * jumpSpeed;
					jumpVelocityY = Math.sin(angle) * jumpSpeed;
					self.jumping = true;
				}
			}
			graphics.y = -Math.max(0, updateCurve) * jumpHeight;
			graphics.scale.x = player.x < self.x ? -1 : 1;
			graphics.scale.y = 1 + Math.min(0, updateCurve);
			shadow.scale.set(1 - shadowReduction * updateCurve);
		}
		self.x += jumpVelocityX - velocityX;
		self.y += jumpVelocityY - velocityY;
		return self.y < despawnY;
	}
});
var Obstruction = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var graphics = self.createAsset(type, {
		anchorX: 0.5,
		anchorY: 1
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var randomScale = 0.9 + Math.random() * 0.2;
	hitbox.y = -25;
	hitbox.alpha = 0;
	hitbox.width = graphics.width * 0.8;
	hitbox.height = graphics.width * 0.45;
	;
	self.x = x;
	self.y = y;
	self.active = true;
	self.hitbox = hitbox;
	self.deactivate = deactivate;
	self.scale.set(randomScale, randomScale);
	;
	function deactivate() {
		self.active = false;
		graphics.alpha = 0.5;
	}
});
var Pickup = Container.expand(function (x, y) {
	var self = Container.call(this);
	var activeDist = 300;
	var activeDistSqr = activeDist * activeDist;
	var collectDist = 50;
	var collectDistSqr = collectDist * collectDist;
	var collectSpeed = 25;
	var collectOffset = -50;
	var active = false;
	var variant = Math.floor(Math.random() * 3);
	var graphics = self.createAsset('pickup' + variant, {
		anchorX: 0.5,
		anchorY: 0.95
	});
	var backShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var foreShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	foreShadow.width = graphics.width;
	foreShadow.height = graphics.width * 0.25;
	backShadow.width = graphics.width;
	backShadow.height = graphics.width * 0.25;
	backShadow.tint = 0x000000;
	backShadow.y = -3;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		var dx = player.x - self.x;
		var dy = player.y + collectOffset - self.y;
		var distSqr = dx * dx + dy * dy;
		if (self.active) {
			var dist = Math.sqrt(distSqr);
			self.x += dx / dist * collectSpeed;
			self.y += dy / dist * collectSpeed;
		} else if (distSqr <= activeDistSqr) {
			self.active = true;
			backShadow.destroy();
			foreShadow.destroy();
		} else {
			self.x -= velocityX;
			self.y -= velocityY;
		}
		return distSqr <= collectDistSqr;
	}
});
var Player = Container.expand(function (x, y) {
	var self = Container.call(this);
	var angle = 0;
	var speed = 0;
	var reduction = 0;
	var travelDistX = 0;
	var travelDistY = 0;
	var rampRemaining = 0;
	var rampDuration = 0;
	var rampHeight = 0;
	var rampHeightMax = 0;
	var tiltSpeedFactor = 100;
	var playerShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var platformGraphics = self.attachAsset('platform', {
		anchorX: 0.4,
		anchorY: 0.5
	});
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.575,
		anchorY: 1
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	playerShadow.alpha = 0.5;
	playerShadow.scale.set(1.0, 0.6);
	playerShadow.tint = 0x000000;
	hitbox.width = 25;
	hitbox.height = 25;
	hitbox.alpha = 0;
	;
	self.x = x;
	self.y = y;
	self.airborne = false;
	self.invulnerable = false;
	self.invulnerableTime = 3 * 60;
	self.invulnerableTimer = 0;
	self.distanceTravelled = 0;
	self.hitbox = hitbox;
	self._update_migrated = _update_migrated;
	self.ramp = ramp;
	;
	function _update_migrated(targetPosition) {
		if (self.invulnerable) {
			if (--self.invulnerableTimer <= 0) {
				self.invulnerable = false;
			}
			self.alpha = self.invulnerableTimer % 60 < 30 ? 1 : 0.5;
		}
		if (self.airborne) {
			if (--rampRemaining <= 0) {
				self.airborne = false;
			}
			rampHeight = rampHeightMax * Math.sin(Math.PI * rampRemaining / rampDuration);
			platformGraphics.y = -rampHeight;
			playerGraphics.y = -rampHeight;
		}
		if (!self.airborne) {
			var dx = targetPosition.x - self.x;
			var dy = targetPosition.y - self.y;
			angle = angleClamp(Math.atan2(dy, dx));
		}
		var acceleration = (Math.sin(angle) - 0.1) * 2.0;
		var boost = self.airborne ? RAMP_SPEED_BOOST : 1;
		reduction = self.invulnerable ? 1 - self.invulnerableTimer / self.invulnerableTime : 1;
		speed = Math.max(0, speed * 0.95 + acceleration);
		var velocityX = Math.cos(angle) * reduction * boost * speed;
		var velocityY = Math.sin(angle) * reduction * boost * speed;
		travelDistX += velocityX;
		travelDistY += velocityY;
		self.distanceTravelled = Math.sqrt(travelDistX * travelDistX + travelDistY * travelDistY);
		if (!self.airborne) {
			var facingSide = targetPosition.x < self.x ? -1 : 1;
			platformGraphics.rotation = angle;
			playerGraphics.rotation = speed * reduction / tiltSpeedFactor * (Math.PI / 2) * facingSide;
			playerGraphics.scale.x = facingSide;
		}
		return {
			velocityX: velocityX,
			velocityY: velocityY
		};
	}
	function angleClamp(angle) {
		return angle >= 0 ? angle : angle < -Math.PI / 2 ? Math.PI : 0;
	}
	function ramp() {
		if (!self.airborne && speed * reduction > RAMP_CRITICAL_SPEED) {
			var rampFactor = speed * reduction - RAMP_CRITICAL_REDUX;
			self.airborne = true;
			rampHeightMax = rampFactor * RAMP_SPEED_HEIGHT;
			rampDuration = Math.round(rampFactor * RAMP_SPEED_DURATION);
			rampRemaining = rampDuration;
		}
	}
});
var Ramp = Container.expand(function (x, y) {
	var self = Container.call(this);
	var rampPillar = self.attachAsset('rampPillar', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var rampShadow = self.attachAsset('rampShadow', {
		anchorX: 0.5
	});
	var rampGraphics = self.attachAsset('ramp', {
		anchorX: 0.5
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5
	});
	rampShadow.rotation = 0.1;
	rampShadow.alpha = 0.5;
	rampShadow.tint = 0x000000;
	rampPillar.y = rampGraphics.height;
	hitbox.width = rampGraphics.width;
	hitbox.height = 50;
	hitbox.alpha = 0;
	;
	self.x = x;
	self.y = y;
	self.hitbox = hitbox;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		self.x -= velocityX;
		self.y -= velocityY;
		if (self.y < -200) {
			return true;
		}
		if (!player.airborne && player.hitbox.intersects(self.hitbox)) {
			player.ramp();
		}
	}
});
var Trail = Container.expand(function (x, y) {
	var self = Container.call(this);
	var trailLength = 60;
	var trailAlpha = 0.4;
	var trailElements = [];
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, active) {
		var trailElement = null;
		if (active && (velocityX !== 0 || velocityY !== 0)) {
			trailElement = self.attachAsset('trail', {
				anchorY: 0.5
			});
			var angle = Math.atan2(velocityY, velocityX);
			var speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);
			trailElement.rotation = angle;
			trailElement.scale.x = speed / 100;
		}
		trailElements.push(trailElement);
		if (trailElements.length > trailLength) {
			var removedElement = trailElements.shift();
			if (removedElement) {
				removedElement.destroy();
			}
		}
		for (var i = trailElements.length - 1; i >= 0; i--) {
			var element = trailElements[i];
			if (element) {
				var alpha = trailAlpha * (i / trailLength);
				element.x -= velocityX;
				element.y -= velocityY;
				element.alpha = alpha;
			}
		}
	}
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
;
var STAGE_WIDTH = 2048;
var STAGE_HEIGHT = 2732;
var SCREEN_METERAGE = 1 / 150;
var MONSTER_SPAWN_DIST = 100 / SCREEN_METERAGE;
var DIFFICULTY_FACTOR_DIST = 150 / SCREEN_METERAGE;
var TILE_SIZE = 512;
var TILE_MARGIN = TILE_SIZE;
var TILE_BACKGROUND_OFFSET = 100;
var SPAWN_PICKUP_CHANCE = 0.1;
var SPAWN_MONSTER_CHANCE = 0.01;
var SPAWN_RAMP_CHANCE = 0.025;
var RAMP_CRITICAL_SPEED = 15.0;
var RAMP_CRITICAL_REDUX = 10;
var RAMP_SPEED_BOOST = 1.25;
var RAMP_SPEED_DURATION = 3.0;
var RAMP_SPEED_HEIGHT = 20.0;
var LAYER_BACKGROUND = 0;
var LAYER_MIDGROUND = 1;
var LAYER_FOREGROUND = 2;
;
var playerPosX = Math.round(STAGE_WIDTH / 2);
var playerPosY = Math.round(STAGE_WIDTH / 3);
var landscapeLookup = {};
var landscapeTiles = [];
var pickups = [];
var monsters = [];
var effects = [];
var rampList = [];
var layers = [game.addChild(new Container()), game.addChild(new Container()), game.addChild(new Container())];
var speed = 0;
var __interface = LK.gui.top.addChild(new Interface(0, 10));
var trail = layers[LAYER_BACKGROUND].addChild(new Trail(playerPosX, playerPosY));
var player = layers[LAYER_MIDGROUND].addChild(new Player(playerPosX, playerPosY));
landscapeTiles.push(landscapeLookup['0:0'] = layers[LAYER_FOREGROUND].addChild(new LandscapeTile(STAGE_WIDTH / 2, TILE_SIZE / 2, {
	density: -1,
	lookup: landscapeLookup,
	xIndex: 0,
	yIndex: 0,
	key: '0:0',
	landscapeTiles: landscapeTiles,
	rampList: rampList,
	monsters: monsters,
	pickups: pickups,
	layers: layers,
	player: player
})));
var isMouseDown = false;
var targetPosition = {
	x: playerPosX,
	y: playerPosY
};
game.setBackgroundColor(0xFFFFFF);
;
game.on('down', function (x, y, obj) {
	isMouseDown = true;
	updatePosition(obj);
});
game.on('up', function (x, y, obj) {
	isMouseDown = false;
});
game.on('move', function (x, y, obj) {
	if (isMouseDown) {
		updatePosition(obj);
	}
});
LK.on('tick', function () {
	var _player$update = player._update_migrated(targetPosition),
		velocityX = _player$update.velocityX,
		velocityY = _player$update.velocityY;
	trail._update_migrated(velocityX, velocityY, !player.airborne);
	__interface._update_migrated(player.distanceTravelled);
	for (var i = landscapeTiles.length - 1; i >= 0; i--) {
		var landscapeTile = landscapeTiles[i];
		landscapeTile.x -= velocityX;
		landscapeTile.y -= velocityY;
		if (landscapeTile.y < -(TILE_SIZE / 2 + TILE_MARGIN)) {
			landscapeTile.destroy();
			landscapeTiles.splice(i, 1);
			landscapeLookup[landscapeTile.key] = undefined;
		} else if (!landscapeTile.active && landscapeTile.x > -TILE_MARGIN && landscapeTile.x < STAGE_WIDTH + TILE_MARGIN && landscapeTile.y < STAGE_HEIGHT + TILE_MARGIN) {
			landscapeTile.activate();
		} else if (landscapeTile.checkCollision(player)) {
			if (__interface.changeScore(-1)) {
				effects.push(new DropEffect(game, player.x, player.y));
			}
			if (!player.invulnerable) {
				player.invulnerable = true;
				player.invulnerableTimer = player.invulnerableTime;
			}
		}
	}
	for (var i = pickups.length - 1; i >= 0; i--) {
		var pickup = pickups[i];
		if (pickup._update_migrated(velocityX, velocityY, player)) {
			__interface.changeScore(1);
			pickup.destroy();
			pickups.splice(i, 1);
		} else if (pickup.y < -(TILE_SIZE / 2 + TILE_MARGIN) || pickup.active && player.hitbox.intersects(pickup.hitbox)) {
			pickup.destroy();
			pickups.splice(i, 1);
		}
	}
	for (var i = effects.length - 1; i >= 0; i--) {
		var effect = effects[i];
		if (effect._update_migrated(velocityX, velocityY)) {
			effect.destroy();
			effects.splice(i, 1);
		}
	}
	for (var i = rampList.length - 1; i >= 0; i--) {
		var ramp = rampList[i];
		if (ramp._update_migrated(velocityX, velocityY, player)) {
			rampList.splice(i, 1);
		}
	}
	for (var i = monsters.length - 1; i >= 0; i--) {
		var monster = monsters[i];
		if (monster._update_migrated(velocityX, velocityY, player)) {
			monster.destroy();
			monsters.splice(i, 1);
		} else if (!monster.jumping && !player.airborne && monster.hitbox.intersects(player.hitbox)) {
			effects.push(new BloodsplatterEffect(game, monster.x, monster.y));
			monster.destroy();
			monsters.splice(i, 1);
			if (__interface.changeLives(-1)) {
				LK.showGameOver();
			}
		}
	}
});
;
function updatePosition(event) {
	var pos = game.toLocal(event.global);
	targetPosition.x = pos.x;
	targetPosition.y = pos.y;
} /**** 
* Classes
****/ 
var BloodsplatterEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var duration = 15;
	var remaining = duration;
	var maxScale = 2.0;
	var startAlpha = 0.5;
	var graphics = self.attachAsset('bloodsplatter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	graphics.alpha = startAlpha;
	graphics.y = -graphics.height / 2;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY) {
		var progress = 1 - remaining-- / duration;
		if (remaining <= 0) {
			return true;
		}
		graphics.scale.set(1 + (maxScale - 1) * progress);
		graphics.alpha = startAlpha * (1 - progress);
		self.x -= velocityX;
		self.y -= velocityY;
	}
});
var DropEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var angle = Math.random() * Math.PI;
	var speed = 10 + Math.random() * 5;
	var speedX = Math.cos(angle) * speed;
	var speedY = Math.sin(angle) * speed;
	var spinSpeed = Math.random() * 0.2 - 0.1;
	var scale = 1;
	var scaleDecrement = 1 / 60;
	var variant = Math.floor(Math.random() * 3);
	var graphics = self.createAsset('pickup' + variant, {
		anchorX: 0.5,
		anchorY: 0.95
	});
	graphics.rotation = Math.random() * Math.PI * 2;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY) {
		self.x += speedX - velocityX;
		self.y += speedY - velocityY;
		scale -= scaleDecrement;
		graphics.rotation += spinSpeed;
		graphics.scale.set(scale);
		return scale <= 0;
	}
});
var Interface = Container.expand(function (x, y) {
	var self = Container.call(this);
	var score = 0;
	var lives = 3;
	var lifeIcons = [];
	var scoreIcon = self.attachAsset('scoreIcon', {
		anchorX: 0.5
	});
	var scoreText = self.addChild(new Text2('| ' + score, {
		size: 70,
		fill: 0x000000,
		align: 'left'
	}));
	var distanceText = self.addChild(new Text2('0m', {
		size: 70,
		fill: 0x000000,
		align: 'right'
	}));
	for (var i = 0; i < lives; i++) {
		var lifeIcon = self.attachAsset('lifeIcon', {
			anchorX: 1
		});
		lifeIcon.x = -10 - i * 60;
		lifeIcon.y = scoreIcon.height + 20;
		lifeIcons.push(lifeIcon);
	}
	scoreText.x = -5;
	scoreText.y = scoreIcon.height;
	scoreText.anchor.set(0, 0);
	distanceText.x = STAGE_WIDTH / 2 - 350;
	distanceText.y = 30;
	distanceText.anchor.set(1, 0);
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	self.changeScore = changeScore;
	self.changeLives = changeLives;
	;
	function _update_migrated(distance) {
		distanceText.setText(Math.round(distance * SCREEN_METERAGE) + 'm');
	}
	function changeLives(amount) {
		lives += amount;
		for (var i = 0; i < lifeIcons.length; i++) {
			lifeIcons[i].alpha = i < lives ? 1 : 0.5;
		}
		if (amount < 0) {
			LK.effects.flashScreen(0xaa0000, 300);
			if (lives <= 0) {
				return true;
			}
		}
		return false;
	}
	function changeScore(amount) {
		var returnValue = amount < 0 && score > 0;
		score = Math.max(0, score + amount);
		LK.setScore(score);
		scoreText.setText('| ' + score);
		return returnValue;
	}
});
var LandscapeTile = Container.expand(function (x, y, _ref) {
	var self = Container.call(this);
	var lookup = _ref.lookup,
		xIndex = _ref.xIndex,
		yIndex = _ref.yIndex,
		density = _ref.density,
		pickups = _ref.pickups,
		monsters = _ref.monsters,
		player = _ref.player,
		key = _ref.key,
		landscapeTiles = _ref.landscapeTiles,
		layers = _ref.layers,
		rampList = _ref.rampList;
	var obstructions = [];
	var background = self.attachAsset('landscapeBackground', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	background.width = TILE_SIZE;
	background.height = TILE_SIZE;
	background.alpha = 0.03;
	background.x = yIndex % 2 === 0 ? TILE_BACKGROUND_OFFSET : 0;
	;
	self.x = x;
	self.y = y;
	self.activate = activate;
	self.active = false;
	self.key = key;
	self.checkCollision = checkCollision;
	;
	function checkCollision(player) {
		if (!player.airborne) {
			var reach = 200;
			var dx = Math.abs(player.x - self.x);
			var dy = Math.abs(player.y - self.y);
			if (dx < TILE_SIZE / 2 + reach && dy < TILE_SIZE / 2 + reach) {
				for (var i = 0; i < obstructions.length; i++) {
					var obstruction = obstructions[i];
					if (obstruction.active && player.hitbox.intersects(obstruction.hitbox)) {
						obstruction.deactivate();
						return true;
					}
				}
			}
		}
		return false;
	}
	function activate() {
		if (!self.active) {
			self.active = true;
			var densityChance = density * Math.random();
			var obstructionTypes = ['largeTree', 'smallTree', 'smallTree', 'deadTree', 'smallRock', 'smallRock', 'largeRock', 'stump'];
			var clearanceDist = 300;
			var clearanceDistSqr = clearanceDist * clearanceDist;
			var spawnBorder = 25;
			var cellSize = 150;
			var cols = Math.ceil(TILE_SIZE / cellSize);
			var rows = Math.ceil(TILE_SIZE / cellSize);
			var cellWidth = TILE_SIZE / cols;
			var cellHeight = TILE_SIZE / rows;
			var landmark;
			if (Math.random() <= SPAWN_PICKUP_CHANCE) {
				var _randomPointInRect = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect.pointX,
					pointY = _randomPointInRect.pointY;
				pickups.push(landmark = self.parent.addChild(new Pickup(pointX, pointY)));
			} else if (Math.random() <= SPAWN_RAMP_CHANCE) {
				var _randomPointInRect2 = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect2.pointX,
					pointY = _randomPointInRect2.pointY;
				rampList.push(landmark = layers[LAYER_BACKGROUND].addChild(new Ramp(pointX, pointY)));
			}
			if (player.distanceTravelled > MONSTER_SPAWN_DIST && Math.random() <= SPAWN_MONSTER_CHANCE) {
				var _randomPointInRect3 = randomPointInRect(self.x, self.y, TILE_SIZE, TILE_SIZE, clearanceDist),
					pointX = _randomPointInRect3.pointX,
					pointY = _randomPointInRect3.pointY;
				monsters.push(self.parent.addChild(new Monster(self.x, self.y)));
			}
			for (i = 0; i < cols; i++) {
				for (j = 0; j < rows; j++) {
					if (Math.random() <= densityChance) {
						var canPlace = true;
						var _randomPointInRect4 = randomPointInRect(cellWidth * i, cellHeight * j, cellWidth, cellHeight, spawnBorder),
							pointX = _randomPointInRect4.pointX,
							pointY = _randomPointInRect4.pointY;
						if (landmark) {
							var dx = landmark.x - pointX;
							var dy = landmark.y - pointY;
							var distSqr = dx * dx + dy * dy;
							if (distSqr <= clearanceDistSqr) {
								canPlace = false;
							}
						}
						if (canPlace) {
							var type = obstructionTypes[Math.floor(Math.random() * obstructionTypes.length)];
							obstructions.push(self.addChild(new Obstruction(pointX, pointY, type)));
						}
					}
				}
			}
		}
		var leftKey = xIndex - 1 + ':' + yIndex;
		var rightKey = xIndex + 1 + ':' + yIndex;
		var downKey = xIndex + ':' + (yIndex + 1);
		var newDensity = (1 + Math.pow(Math.log(player.distanceTravelled / DIFFICULTY_FACTOR_DIST + 2), 2)) / 100;
		if (!lookup[leftKey]) {
			landscapeTiles.push(lookup[leftKey] = self.parent.addChild(new LandscapeTile(self.x - TILE_SIZE, self.y, {
				key: leftKey,
				density: newDensity,
				xIndex: xIndex - 1,
				yIndex: yIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		if (!lookup[rightKey]) {
			landscapeTiles.push(lookup[rightKey] = self.parent.addChild(new LandscapeTile(self.x + TILE_SIZE, self.y, {
				key: rightKey,
				density: newDensity,
				xIndex: xIndex + 1,
				yIndex: yIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		if (!lookup[downKey]) {
			landscapeTiles.push(lookup[downKey] = self.parent.addChild(new LandscapeTile(self.x, self.y + TILE_SIZE, {
				key: downKey,
				density: newDensity,
				yIndex: yIndex + 1,
				xIndex: xIndex,
				landscapeTiles: landscapeTiles,
				rampList: rampList,
				lookup: lookup,
				pickups: pickups,
				monsters: monsters,
				layers: layers,
				player: player
			})));
		}
		function randomPointInRect(centerX, centerY, width, height) {
			var border = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
			var startX = centerX - width / 2 + border;
			var startY = centerY - height / 2 + border;
			var innerWidth = width - border * 2;
			var innerHeight = height - border * 2;
			var pointX = startX + Math.random() * innerWidth;
			var pointY = startY + Math.random() * innerHeight;
			return {
				pointX: pointX,
				pointY: pointY
			};
		}
	}
});
var Monster = Container.expand(function (x, y) {
	var self = Container.call(this);
	var active = false;
	var updateTick = 0;
	var updatePeriod = 30;
	var jumpSpeedMax = 30;
	var jumpHeight = 100;
	var jumpVelocityX = 0;
	var jumpVelocityY = 0;
	var jumpDuration = updatePeriod * 2 / 3;
	var invulnerabilityBoost = 1.8;
	var jumpDistMax = jumpSpeedMax * jumpDuration;
	var jumpDistMaxSqr = jumpDistMax * jumpDistMax;
	var activationDist = 1000;
	var activationDistSqr = activationDist * activationDist;
	var despawnY = -2500;
	var shadowReduction = 0.1;
	var shadow = self.attachAsset('shadow', {
		anchorX: 0.45,
		anchorY: 1
	});
	var graphics = self.attachAsset('monster', {
		anchorX: 0.5,
		anchorY: 1
	});
	graphics.scale.x = Math.random() < 0.5 ? 1 : -1;
	shadow.width = graphics.width * 0.9;
	shadow.height = graphics.width * 0.45;
	shadow.tint = 0x000000;
	shadow.alpha = 0.5;
	;
	self.x = x;
	self.y = y;
	self.jumping = false;
	self.hitbox = shadow;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		if (!active) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distSqr = dx * dx + dy * dy;
			if (distSqr <= activationDistSqr) {
				active = true;
			}
		}
		if (active) {
			var updateCurve = (-Math.cos(++updateTick * Math.PI / (updatePeriod / 2)) + 0.5) / 1.5;
			if (self.jumping) {
				if (updateCurve <= 0) {
					self.jumping = false;
					jumpVelocityX = 0;
					jumpVelocityY = 0;
				}
			} else {
				if (updateCurve > 0) {
					var boost = player.invulnerable ? invulnerabilityBoost : 1;
					var targetPosX = player.x + velocityX * jumpDuration * boost;
					var targetPosY = player.y + velocityY * jumpDuration * boost;
					var ddx = targetPosX - self.x;
					var ddy = targetPosY - self.y;
					var angle = Math.atan2(ddy, ddx);
					var targetDistSqr = ddx * ddx + ddy * ddy;
					var jumpSpeed = jumpSpeedMax * (targetDistSqr >= jumpDistMaxSqr ? 1 : Math.sqrt(targetDistSqr) / jumpDistMax);
					jumpVelocityX = Math.cos(angle) * jumpSpeed;
					jumpVelocityY = Math.sin(angle) * jumpSpeed;
					self.jumping = true;
				}
			}
			graphics.y = -Math.max(0, updateCurve) * jumpHeight;
			graphics.scale.x = player.x < self.x ? -1 : 1;
			graphics.scale.y = 1 + Math.min(0, updateCurve);
			shadow.scale.set(1 - shadowReduction * updateCurve);
		}
		self.x += jumpVelocityX - velocityX;
		self.y += jumpVelocityY - velocityY;
		return self.y < despawnY;
	}
});
var Obstruction = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	var graphics = self.createAsset(type, {
		anchorX: 0.5,
		anchorY: 1
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var randomScale = 0.9 + Math.random() * 0.2;
	hitbox.y = -25;
	hitbox.alpha = 0;
	hitbox.width = graphics.width * 0.8;
	hitbox.height = graphics.width * 0.45;
	;
	self.x = x;
	self.y = y;
	self.active = true;
	self.hitbox = hitbox;
	self.deactivate = deactivate;
	self.scale.set(randomScale, randomScale);
	;
	function deactivate() {
		self.active = false;
		graphics.alpha = 0.5;
	}
});
var Pickup = Container.expand(function (x, y) {
	var self = Container.call(this);
	var activeDist = 300;
	var activeDistSqr = activeDist * activeDist;
	var collectDist = 50;
	var collectDistSqr = collectDist * collectDist;
	var collectSpeed = 25;
	var collectOffset = -50;
	var active = false;
	var variant = Math.floor(Math.random() * 3);
	var graphics = self.createAsset('pickup' + variant, {
		anchorX: 0.5,
		anchorY: 0.95
	});
	var backShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var foreShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	foreShadow.width = graphics.width;
	foreShadow.height = graphics.width * 0.25;
	backShadow.width = graphics.width;
	backShadow.height = graphics.width * 0.25;
	backShadow.tint = 0x000000;
	backShadow.y = -3;
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		var dx = player.x - self.x;
		var dy = player.y + collectOffset - self.y;
		var distSqr = dx * dx + dy * dy;
		if (self.active) {
			var dist = Math.sqrt(distSqr);
			self.x += dx / dist * collectSpeed;
			self.y += dy / dist * collectSpeed;
		} else if (distSqr <= activeDistSqr) {
			self.active = true;
			backShadow.destroy();
			foreShadow.destroy();
		} else {
			self.x -= velocityX;
			self.y -= velocityY;
		}
		return distSqr <= collectDistSqr;
	}
});
var Player = Container.expand(function (x, y) {
	var self = Container.call(this);
	var angle = 0;
	var speed = 0;
	var reduction = 0;
	var travelDistX = 0;
	var travelDistY = 0;
	var rampRemaining = 0;
	var rampDuration = 0;
	var rampHeight = 0;
	var rampHeightMax = 0;
	var tiltSpeedFactor = 100;
	var playerShadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var platformGraphics = self.attachAsset('platform', {
		anchorX: 0.4,
		anchorY: 0.5
	});
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.575,
		anchorY: 1
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	playerShadow.alpha = 0.5;
	playerShadow.scale.set(1.0, 0.6);
	playerShadow.tint = 0x000000;
	hitbox.width = 25;
	hitbox.height = 25;
	hitbox.alpha = 0;
	;
	self.x = x;
	self.y = y;
	self.airborne = false;
	self.invulnerable = false;
	self.invulnerableTime = 3 * 60;
	self.invulnerableTimer = 0;
	self.distanceTravelled = 0;
	self.hitbox = hitbox;
	self._update_migrated = _update_migrated;
	self.ramp = ramp;
	;
	function _update_migrated(targetPosition) {
		if (self.invulnerable) {
			if (--self.invulnerableTimer <= 0) {
				self.invulnerable = false;
			}
			self.alpha = self.invulnerableTimer % 60 < 30 ? 1 : 0.5;
		}
		if (self.airborne) {
			if (--rampRemaining <= 0) {
				self.airborne = false;
			}
			rampHeight = rampHeightMax * Math.sin(Math.PI * rampRemaining / rampDuration);
			platformGraphics.y = -rampHeight;
			playerGraphics.y = -rampHeight;
		}
		if (!self.airborne) {
			var dx = targetPosition.x - self.x;
			var dy = targetPosition.y - self.y;
			angle = angleClamp(Math.atan2(dy, dx));
		}
		var acceleration = (Math.sin(angle) - 0.1) * 2.0;
		var boost = self.airborne ? RAMP_SPEED_BOOST : 1;
		reduction = self.invulnerable ? 1 - self.invulnerableTimer / self.invulnerableTime : 1;
		speed = Math.max(0, speed * 0.95 + acceleration);
		var velocityX = Math.cos(angle) * reduction * boost * speed;
		var velocityY = Math.sin(angle) * reduction * boost * speed;
		travelDistX += velocityX;
		travelDistY += velocityY;
		self.distanceTravelled = Math.sqrt(travelDistX * travelDistX + travelDistY * travelDistY);
		if (!self.airborne) {
			var facingSide = targetPosition.x < self.x ? -1 : 1;
			platformGraphics.rotation = angle;
			playerGraphics.rotation = speed * reduction / tiltSpeedFactor * (Math.PI / 2) * facingSide;
			playerGraphics.scale.x = facingSide;
		}
		return {
			velocityX: velocityX,
			velocityY: velocityY
		};
	}
	function angleClamp(angle) {
		return angle >= 0 ? angle : angle < -Math.PI / 2 ? Math.PI : 0;
	}
	function ramp() {
		if (!self.airborne && speed * reduction > RAMP_CRITICAL_SPEED) {
			var rampFactor = speed * reduction - RAMP_CRITICAL_REDUX;
			self.airborne = true;
			rampHeightMax = rampFactor * RAMP_SPEED_HEIGHT;
			rampDuration = Math.round(rampFactor * RAMP_SPEED_DURATION);
			rampRemaining = rampDuration;
		}
	}
});
var Ramp = Container.expand(function (x, y) {
	var self = Container.call(this);
	var rampPillar = self.attachAsset('rampPillar', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var rampShadow = self.attachAsset('rampShadow', {
		anchorX: 0.5
	});
	var rampGraphics = self.attachAsset('ramp', {
		anchorX: 0.5
	});
	var hitbox = self.attachAsset('hitbox', {
		anchorX: 0.5
	});
	rampShadow.rotation = 0.1;
	rampShadow.alpha = 0.5;
	rampShadow.tint = 0x000000;
	rampPillar.y = rampGraphics.height;
	hitbox.width = rampGraphics.width;
	hitbox.height = 50;
	hitbox.alpha = 0;
	;
	self.x = x;
	self.y = y;
	self.hitbox = hitbox;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, player) {
		self.x -= velocityX;
		self.y -= velocityY;
		if (self.y < -200) {
			return true;
		}
		if (!player.airborne && player.hitbox.intersects(self.hitbox)) {
			player.ramp();
		}
	}
});
var Trail = Container.expand(function (x, y) {
	var self = Container.call(this);
	var trailLength = 60;
	var trailAlpha = 0.4;
	var trailElements = [];
	;
	self.x = x;
	self.y = y;
	self._update_migrated = _update_migrated;
	;
	function _update_migrated(velocityX, velocityY, active) {
		var trailElement = null;
		if (active && (velocityX !== 0 || velocityY !== 0)) {
			trailElement = self.attachAsset('trail', {
				anchorY: 0.5
			});
			var angle = Math.atan2(velocityY, velocityX);
			var speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);
			trailElement.rotation = angle;
			trailElement.scale.x = speed / 100;
		}
		trailElements.push(trailElement);
		if (trailElements.length > trailLength) {
			var removedElement = trailElements.shift();
			if (removedElement) {
				removedElement.destroy();
			}
		}
		for (var i = trailElements.length - 1; i >= 0; i--) {
			var element = trailElements[i];
			if (element) {
				var alpha = trailAlpha * (i / trailLength);
				element.x -= velocityX;
				element.y -= velocityY;
				element.alpha = alpha;
			}
		}
	}
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
;
var STAGE_WIDTH = 2048;
var STAGE_HEIGHT = 2732;
var SCREEN_METERAGE = 1 / 150;
var MONSTER_SPAWN_DIST = 100 / SCREEN_METERAGE;
var DIFFICULTY_FACTOR_DIST = 150 / SCREEN_METERAGE;
var TILE_SIZE = 512;
var TILE_MARGIN = TILE_SIZE;
var TILE_BACKGROUND_OFFSET = 100;
var SPAWN_PICKUP_CHANCE = 0.1;
var SPAWN_MONSTER_CHANCE = 0.01;
var SPAWN_RAMP_CHANCE = 0.025;
var RAMP_CRITICAL_SPEED = 15.0;
var RAMP_CRITICAL_REDUX = 10;
var RAMP_SPEED_BOOST = 1.25;
var RAMP_SPEED_DURATION = 3.0;
var RAMP_SPEED_HEIGHT = 20.0;
var LAYER_BACKGROUND = 0;
var LAYER_MIDGROUND = 1;
var LAYER_FOREGROUND = 2;
;
var playerPosX = Math.round(STAGE_WIDTH / 2);
var playerPosY = Math.round(STAGE_WIDTH / 3);
var landscapeLookup = {};
var landscapeTiles = [];
var pickups = [];
var monsters = [];
var effects = [];
var rampList = [];
var layers = [game.addChild(new Container()), game.addChild(new Container()), game.addChild(new Container())];
var speed = 0;
var __interface = LK.gui.top.addChild(new Interface(0, 10));
var trail = layers[LAYER_BACKGROUND].addChild(new Trail(playerPosX, playerPosY));
var player = layers[LAYER_MIDGROUND].addChild(new Player(playerPosX, playerPosY));
landscapeTiles.push(landscapeLookup['0:0'] = layers[LAYER_FOREGROUND].addChild(new LandscapeTile(STAGE_WIDTH / 2, TILE_SIZE / 2, {
	density: -1,
	lookup: landscapeLookup,
	xIndex: 0,
	yIndex: 0,
	key: '0:0',
	landscapeTiles: landscapeTiles,
	rampList: rampList,
	monsters: monsters,
	pickups: pickups,
	layers: layers,
	player: player
})));
var isMouseDown = false;
var targetPosition = {
	x: playerPosX,
	y: playerPosY
};
game.setBackgroundColor(0xFFFFFF);
;
game.on('down', function (x, y, obj) {
	isMouseDown = true;
	updatePosition(obj);
});
game.on('up', function (x, y, obj) {
	isMouseDown = false;
});
game.on('move', function (x, y, obj) {
	if (isMouseDown) {
		updatePosition(obj);
	}
});
LK.on('tick', function () {
	var _player$update = player._update_migrated(targetPosition),
		velocityX = _player$update.velocityX,
		velocityY = _player$update.velocityY;
	trail._update_migrated(velocityX, velocityY, !player.airborne);
	__interface._update_migrated(player.distanceTravelled);
	for (var i = landscapeTiles.length - 1; i >= 0; i--) {
		var landscapeTile = landscapeTiles[i];
		landscapeTile.x -= velocityX;
		landscapeTile.y -= velocityY;
		if (landscapeTile.y < -(TILE_SIZE / 2 + TILE_MARGIN)) {
			landscapeTile.destroy();
			landscapeTiles.splice(i, 1);
			landscapeLookup[landscapeTile.key] = undefined;
		} else if (!landscapeTile.active && landscapeTile.x > -TILE_MARGIN && landscapeTile.x < STAGE_WIDTH + TILE_MARGIN && landscapeTile.y < STAGE_HEIGHT + TILE_MARGIN) {
			landscapeTile.activate();
		} else if (landscapeTile.checkCollision(player)) {
			if (__interface.changeScore(-1)) {
				effects.push(new DropEffect(game, player.x, player.y));
			}
			if (!player.invulnerable) {
				player.invulnerable = true;
				player.invulnerableTimer = player.invulnerableTime;
			}
		}
	}
	for (var i = pickups.length - 1; i >= 0; i--) {
		var pickup = pickups[i];
		if (pickup._update_migrated(velocityX, velocityY, player)) {
			__interface.changeScore(1);
			pickup.destroy();
			pickups.splice(i, 1);
		} else if (pickup.y < -(TILE_SIZE / 2 + TILE_MARGIN) || pickup.active && player.hitbox.intersects(pickup.hitbox)) {
			pickup.destroy();
			pickups.splice(i, 1);
		}
	}
	for (var i = effects.length - 1; i >= 0; i--) {
		var effect = effects[i];
		if (effect._update_migrated(velocityX, velocityY)) {
			effect.destroy();
			effects.splice(i, 1);
		}
	}
	for (var i = rampList.length - 1; i >= 0; i--) {
		var ramp = rampList[i];
		if (ramp._update_migrated(velocityX, velocityY, player)) {
			rampList.splice(i, 1);
		}
	}
	for (var i = monsters.length - 1; i >= 0; i--) {
		var monster = monsters[i];
		if (monster._update_migrated(velocityX, velocityY, player)) {
			monster.destroy();
			monsters.splice(i, 1);
		} else if (!monster.jumping && !player.airborne && monster.hitbox.intersects(player.hitbox)) {
			effects.push(new BloodsplatterEffect(game, monster.x, monster.y));
			monster.destroy();
			monsters.splice(i, 1);
			if (__interface.changeLives(-1)) {
				LK.showGameOver();
			}
		}
	}
});
;
function updatePosition(event) {
	var pos = game.toLocal(event.global);
	targetPosition.x = pos.x;
	targetPosition.y = pos.y;
}
:quality(85)/https://cdn.frvr.ai/65762d4365042397a6171500.png%3F3) 
 pixel art of a tree stump covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65762de865042397a617150f.png%3F3) 
 pixel art of a dead tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65762e6065042397a617151f.png%3F3) 
 pixel art of a christmas tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65762f4865042397a6171536.png%3F3) 
 pixel art of a spruce tree covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65762fc365042397a6171547.png%3F3) 
 pixel art of a rock covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6577704dac01de1a6056ab4b.png%3F3) 
 pixel art of a christmas present counter. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/65784c7495da6b65890ffc2e.png%3F3) 
 Pixel art heart icon . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/657b7a5de5f77c7f98342238.png%3F3) 
 two vertical lines with a blank background.
:quality(85)/https://cdn.frvr.ai/657b8453e5f77c7f98342272.png%3F3) 
 pixel art of a large, snow covered rock . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/657b862fe5f77c7f9834228c.png%3F3) 
 pixel art of skiis . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/657c23937cd84e53f91ebef7.png%3F3) 
 pixel art of a floating grinch monster . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/657c4f807cd84e53f91ebf7e.png%3F3) 
 single green firework explosion . Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6591cb1ea0750c7c9b32ea5b.png%3F3) 
 pixel art of a wooden board covered in snow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6591ccb5a0750c7c9b32ea72.png%3F3) 
 pixel art of a wooden pole with snow at it's base. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6591f63ea0750c7c9b32eb16.png%3F3) 
 tileable white water texture pixel art.
:quality(85)/https://cdn.frvr.ai/682fad416160719169779c48.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/682fafac11621815f443ed53.png%3F3)