/**** 
* Classes
****/
var EnemyBulletIndicator = Container.expand(function () {
	var self = Container.call(this);
	var indicatorGraphics = self.attachAsset('enemyBulletIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicatorGraphics.alpha = 0.5;
});
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	var obstacleGraphics = self.attachAsset('obstacle', {
		anchorX: 0.5,
		anchorY: 1
	});
	obstacleGraphics.y += 50;
});
var ExitDoor = Container.expand(function () {
	var self = Container.call(this);
	var backgroundElement = self.attachAsset('backgroundElement1', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundElement.y -= 760;
	var backgroundElement2 = self.attachAsset('backgroundElement2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundElement2.y -= 760;
	backgroundElement2.blendMode = 1;
	var doorGraphics = self.attachAsset('exitDoor', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.rotate = function () {
		backgroundElement.rotation += 0.00125;
		backgroundElement2.rotation -= 0.00175;
	};
});
var EnemySpawnIndicator = Container.expand(function () {
	var self = Container.call(this);
	var spawnIndicatorGraphics = self.attachAsset('spawnIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	spawnIndicatorGraphics.alpha = 0.5;
});
var ExplosionParticle = Container.expand(function () {
	var self = Container.call(this);
	var particleGraphics = self.attachAsset('particle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	particleGraphics.blendMode = 1;
	self.dx = (Math.random() - 0.5) * 10;
	self.dy = (Math.random() - 0.5) * 7;
	self.move = function () {
		self.setPosition(self.x + self.dx, self.y + self.dy);
		self.alpha -= 0.02;
		particleGraphics.scale.set(particleGraphics.scale.x * 0.98, particleGraphics.scale.y * 0.98);
		self.dx *= 0.98;
		self.dy *= 0.98;
		if (self.alpha <= 0) {
			self.destroy();
		}
	};
});
var HealthBar = Container.expand(function () {
	var self = Container.call(this);
	var healthBarGraphics = self.attachAsset('healthBar', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.setTint = function (tint) {
		healthBarGraphics.tint = tint;
	};
	self.setTint(0x00FF00);
	self.updateHealth = function (health) {
		self.scale.set(health / 100, 1);
	};
});
var TargetIndicator = Container.expand(function () {
	var self = Container.call(this);
	var targetGraphics = self.attachAsset('target', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	targetGraphics.alpha = 0.5;
	targetGraphics.y -= 30;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	self.health = 100;
	self.findNearestEnemy = function (enemies) {
		var nearestEnemy = null;
		var nearestDistance = Infinity;
		for (var i = 0; i < enemies.length; i++) {
			var dx = enemies[i].x - self.x;
			var dy = enemies[i].y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < nearestDistance && !self.parent.lineIntersectsObstacle(self.x, self.y, enemies[i].x, enemies[i].y)) {
				nearestDistance = distance;
				nearestEnemy = enemies[i];
			}
		}
		return nearestEnemy;
	};
	var playerShadow = self.attachAsset('playerShadow', {
		anchorX: 0.5,
		anchorY: 0.8
	});
	playerShadow.alpha = 0.3;
	var playerAsset = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 1
	});
	var healthBar = new HealthBar();
	self.addChild(healthBar).y = -self.children[1].height;
	self.healthBar = healthBar;
	self.targetX = 2048 / 2;
	self.targetY = 2732 / 2;
	self.speed = 5;
	self.lastShot = 0;
	self.move = function (obstacles) {
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance > self.speed) {
			self.setPosition(self.x + dx / distance * self.speed, self.y + dy / distance * self.speed);
			for (var i = 0; i < obstacles.length; i++) {
				var dx = obstacles[i].x - self.x;
				var dy = obstacles[i].y - self.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < obstacles[i].width / 2) {
					self.x -= dx / distance * 10;
					self.y -= dy / distance * 10;
				}
			}
			self.healthBar.updateHealth(self.health);
			return true;
		}
		self.healthBar.updateHealth(self.health);
		return false;
	};
	self.setTarget = function (x, y) {
		self.targetX = x;
		self.targetY = y;
	};
	self.shoot = function (enemies) {
		var nearestEnemy = self.findNearestEnemy(enemies);
		if (nearestEnemy) {
			var bullet = new PlayerBullet();
			bullet.setPosition(self.x, self.y);
			var dx = nearestEnemy.x - self.x;
			var dy = nearestEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			bullet.dx = dx / distance;
			bullet.dy = dy / distance;
			return bullet;
		}
		return null;
	};
	self.flashRed = function () {
		LK.effects.flashObject(playerAsset, 0xFF0000, 1000);
	};
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	self.throwProjectile = function (player) {
		if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			var projectile = new EnemyBullet();
			projectile.setPosition(self.x, self.y);
			projectile.originX = self.x;
			projectile.originY = self.y;
			projectile.targetX = player.x;
			projectile.targetY = player.y;
			projectile.dx = dx / distance;
			projectile.dy = dy / distance;
			return projectile;
		}
		return null;
	};
	self.moveTowardsPlayer = function (player) {
		if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 800) {
				self.dx += dx / distance * 0.3;
				self.dy += dy / distance * 0.3;
				return true;
			}
		}
		return false;
	};
	;
	self.alpha = 0;
	self.lastProjectile = 0;
	self.dx = 0;
	self.dy = 0;
	self.health = 100;
	self.animateIn = function () {
		self.fadeInTicks = 50;
	};
	var enemyShadow = self.attachAsset('enemyShadow', {
		anchorX: 0.5,
		anchorY: 0.8
	});
	enemyShadow.alpha = 0.3;
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 1
	});
	var healthBar = new HealthBar();
	healthBar.setTint(0xFF0000);
	healthBar.y = -enemyGraphics.height;
	self.addChild(healthBar);
	self.healthBar = healthBar;
	self.healthBar.updateHealth(self.health);
	self.move = function (obstacles, player) {
		var movedTowardsPlayer = true;
		if (self.fadeInTicks > 0) {
			self.alpha += 0.02;
			self.fadeInTicks--;
		} else {
			movedTowardsPlayer = self.moveTowardsPlayer(player);
		}
		self.setPosition(self.x + self.dx, self.y + self.dy);
		self.dx *= 0.80;
		self.dy *= 0.80;
		if (self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) {
			self.x = Math.max(Math.min(self.x, 2048 - 150), 150);
			self.y = Math.max(Math.min(self.y, 2732 - 150), 700);
		}
		for (var i = 0; i < obstacles.length; i++) {
			var dx = obstacles[i].x - self.x;
			var dy = obstacles[i].y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < obstacles[i].width / 2) {
				self.x -= dx / distance * 10;
				self.y -= dy / distance * 10;
			}
		}
		return movedTowardsPlayer;
	};
	self.flashRed = function () {
		LK.effects.flashObject(enemyGraphics, 0xFF0000, 1000);
	};
});
var PlayerBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bulletGraphics.y -= 150;
	bulletGraphics.blendMode = 1;
	self.dx = 0;
	self.dy = 0;
	self.move = function () {
		self.dx *= 1.02;
		self.dy *= 1.02;
		self.setPosition(self.x + self.dx * 4, self.y + self.dy * 4);
		return self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150;
	};
});
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bulletGraphics.y -= 150;
	self.dx = 0;
	self.dy = 0;
	self.originX = 0;
	self.originY = 0;
	self.move = function () {
		self.setPosition(self.x + self.dx * 4.2, self.y + self.dy * 4.2);
		bulletGraphics.rotation += 0.1;
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2));
		var percentCompleted = distance / totalDistance;
		bulletGraphics.y = -150 * percentCompleted - 200 * Math.sin(Math.PI * percentCompleted);
		if (!self.indicator) {
			self.indicator = new EnemyBulletIndicator();
			self.indicator.setPosition(self.targetX, self.targetY);
			self.parent.addChild(self.indicator);
		}
		var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2));
		var percentCompleted = 1 - distance / totalDistance;
		self.indicator.scale.set(3 - 2 * percentCompleted, 3 - 2 * percentCompleted);
		self.indicator.alpha = percentCompleted;
		if (distance < 25 || self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) {
			self.indicator.destroy();
			return true;
		}
		return false;
	};
});
var Background = Container.expand(function () {
	var self = Container.call(this);
	var backgroundGraphics = self.attachAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundGraphics.setPosition(2048 / 2, 2732 / 2 + 300);
	self.exitDoor = self.addChildAt(new ExitDoor(), 1);
	self.exitDoor.setPosition(2048 / 2, 2732 / 2 - 670 + 400);
	self.exitDoor.visible = false;
});
/**** 
* Initialize Game
****/
var game = new LK.Game({
	backgroundColor: 0x343942
});
/**** 
* Game Code
****/
game.enemyBulletMove = function () {
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i] && enemyBullets[i].move()) {
			var dx = player.x - enemyBullets[i].x;
			var dy = player.y - enemyBullets[i].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 225 && !game.allEnemiesKilled) {
				player.health -= 10;
				player.healthBar.updateHealth(player.health);
				player.flashRed();
				if (player.health <= 0) {
					LK.showGameOver();
				}
			}
			game.createExplosion(enemyBullets[i].x, enemyBullets[i].y);
			enemyBullets[i].destroy();
			enemyBullets.splice(i, 1);
		}
	}
};
game.lineIntersectsObstacle = function (x1, y1, x2, y2) {
	for (var i = 0; i < obstacles.length; i++) {
		var dx = obstacles[i].x - x1;
		var dy = obstacles[i].y - y1;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var radius = obstacles[i].width * 0.7 / 2;
		if (distance < radius) {
			return true;
		}
		var t = ((x2 - x1) * (obstacles[i].x - x1) + (y2 - y1) * (obstacles[i].y - y1)) / (Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
		t = Math.max(0, Math.min(1, t));
		var nearestX = x1 + t * (x2 - x1);
		var nearestY = y1 + t * (y2 - y1);
		dx = obstacles[i].x - nearestX;
		dy = obstacles[i].y - nearestY;
		distance = Math.sqrt(dx * dx + dy * dy);
		if (distance <= radius) {
			return true;
		}
	}
	return false;
};
game.allEnemiesKilled = false;
game.waveCount = 2;
game.setPlayerTarget = function (x, y) {
	x = Math.max(Math.min(x, 2048 - 150), 150);
	y = Math.max(Math.min(y, 2732 - 150), 700);
	player.setTarget(x, y);
	targetIndicator.setPosition(x, y);
	targetIndicator.visible = true;
};
game.checkEnemies = function () {
	if (!game.allEnemiesKilled && enemies.length === 0 && spawnIndicators.length === 0) {
		background.exitDoor.visible = true;
		game.allEnemiesKilled = true;
		LK.effects.flashScreen(0xFFFFFF, 1000);
		game.setPlayerTarget(background.exitDoor.x, background.exitDoor.y - 300);
	}
};
game.rotateBackground = function () {
	background.children[1].rotate();
};
game.particleMove = function () {
	for (var i = particles.length - 1; i >= 0; i--) {
		if (particles[i].alpha <= 0) {
			particles[i].destroy();
			particles.splice(i, 1);
		} else {
			particles[i].move();
		}
	}
};
game.bulletMove = function () {
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i] && bullets[i].move()) {
			game.createExplosion(bullets[i].x, bullets[i].y - 150);
			bullets[i].destroy();
			bullets.splice(i, 1);
		} else {
			bullets[i].move();
			for (var j = 0; j < enemies.length; j++) {
				if (bullets[i].intersects(enemies[j])) {
					enemies[j].health -= 10;
					enemies[j].healthBar.updateHealth(enemies[j].health);
					enemies[j].flashRed();
					if (enemies[j].health <= 0) {
						enemies[j].destroy();
						enemies.splice(j, 1);
						score += 1;
						LK.setScore(score);
						scoreDisplay.setText(score.toString());
					} else {
						var angle = Math.atan2(bullets[i].dy, bullets[i].dx);
						enemies[j].x += Math.cos(angle) * 15;
						enemies[j].y += Math.sin(angle) * 15;
						enemies[j].dx = Math.cos(angle) * 10;
						enemies[j].dy = Math.sin(angle) * 10;
					}
					game.createExplosion(bullets[i].x, bullets[i].y - 150);
					bullets[i].destroy();
					bullets.splice(i, 1);
					break;
				}
			}
		}
	}
};
game.enemyTick = function () {
	for (var i = 0; i < enemies.length; i++) {
		var moved = enemies[i].move(obstacles, player);
		for (var j = i + 1; j < enemies.length; j++) {
			var dx = enemies[j].x - enemies[i].x;
			var dy = enemies[j].y - enemies[i].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < enemies[i].width) {
				enemies[i].x -= dx / distance;
				enemies[i].y -= dy / distance;
				enemies[j].x += dx / distance;
				enemies[j].y += dy / distance;
			}
		}
		if (!moved && LK.ticks - enemies[i].lastProjectile >= 180) {
			enemies[i].lastProjectile = LK.ticks;
			var projectile = enemies[i].throwProjectile(player);
			if (projectile) {
				enemyBullets.push(projectile);
				game.addChild(projectile);
			}
		}
	}
};
game.playerMove = function (obstacles) {
	player.move(obstacles);
	var dx = player.targetX - player.x;
	var dy = player.targetY - player.y;
	var distance = Math.sqrt(dx * dx + dy * dy);
	if (distance < player.speed && LK.ticks - player.lastShot >= 30 && enemies.length > 0) {
		player.lastShot = LK.ticks;
		var bullet = player.shoot(enemies);
		if (bullet) {
			bullets.push(bullet);
			game.addChild(bullet);
		}
	}
	if (distance < player.speed) {
		targetIndicator.visible = false;
		if (game.allEnemiesKilled) {
			game.spawnNextWave();
		}
	}
};
var spawnIndicators = [];
game.isTooClose = function (x, y) {
	for (var i = 0; i < spawnIndicators.length; i++) {
		var dx = spawnIndicators[i].x - x;
		var dy = spawnIndicators[i].y - y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 200) {
			return true;
		}
	}
	return false;
};
game.spawnEnemies = function (count) {
	for (var i = 0; i < count; i++) {
		var x, y;
		do {
			x = Math.random() * (2048 - 300) + 150;
			y = Math.random() * (2732 - 850) + 700;
		} while (game.isTooClose(x, y) || game.lineIntersectsObstacle(x, y, x, y));
		var spawnIndicator = game.addChild(new EnemySpawnIndicator());
		spawnIndicator.setPosition(x, y);
		spawnIndicators.push(spawnIndicator);
		(function (spawnIndicator) {
			LK.setTimeout(function () {
				var enemy = game.addChild(new Enemy());
				enemy.setPosition(spawnIndicator.x, spawnIndicator.y);
				enemies.push(enemy);
				spawnIndicator.destroy();
				enemy.animateIn();
				var index = spawnIndicators.indexOf(spawnIndicator);
				if (index > -1) {
					spawnIndicators.splice(index, 1);
				}
			}, 2000);
		})(spawnIndicator);
	}
};
game.createExplosion = function (x, y) {
	for (var j = 0; j < 10; j++) {
		var particle = new ExplosionParticle();
		particle.setPosition(x, y);
		particle.dx = (Math.random() - 0.5) * 10;
		particle.dy = (Math.random() - 0.5) * 7;
		game.addChild(particle);
		particles.push(particle);
	}
};
var particles = [];
game.sortGameObjects = function () {
	game.children.sort(function (a, b) {
		return a.y < b.y ? -1 : 1;
	});
	for (var i = 0; i < game.children.length; i++) {
		if (game.children[i] instanceof EnemyBulletIndicator) {
			game.setChildIndex(game.children[i], 1);
		}
	}
	game.setChildIndex(targetIndicator, 1);
};
var background = game.addChild(new Background());
var player = game.addChild(new Player());
player.setPosition(2048 / 2, 2732 - player.height);
player.setTarget(player.x, player.y);
var targetIndicator = game.addChild(new TargetIndicator());
targetIndicator.setPosition(player.x, player.y);
var obstacles = [];
var enemies = [];
game.spawnEnemies(1);
var obstacleSpacing = 2048 / 3;
for (var i = 0; i < 2; i++) {
	for (var j = 0; j < 2; j++) {
		var obstacle = game.addChild(new Obstacle());
		obstacle.setPosition(obstacleSpacing * (i + 1), 2732 / 2 + obstacleSpacing * j);
		obstacles.push(obstacle);
	}
}
var bullets = [];
var enemyBullets = [];
var score = 0;
var scoreDisplay = new Text2(score.toString(), {
	size: 80,
	fill: '#ffffff',
	font: 'Impact',
	dropShadow: true,
	dropShadowColor: '#000000',
	dropShadowBlur: 4,
	dropShadowAngle: Math.PI / 6,
	dropShadowDistance: 6
});
scoreDisplay.anchor.set(0.5, 0);
LK.gui.topCenter.addChild(scoreDisplay);
var waveDisplay = new Text2('Wave: 1', {
	size: 40,
	fill: '#ffffff',
	font: 'Impact',
	dropShadow: true,
	dropShadowColor: '#000000',
	dropShadowBlur: 4,
	dropShadowAngle: Math.PI / 6,
	dropShadowDistance: 6
});
waveDisplay.anchor.set(0.5, 1);
LK.gui.bottom.addChild(waveDisplay);
LK.on('tick', function () {
	game.playerMove(obstacles);
	game.bulletMove();
	game.enemyTick();
	game.enemyBulletMove();
	game.particleMove();
	game.rotateBackground();
	game.sortGameObjects();
	game.checkEnemies();
});
game.spawnNextWave = function () {
	player.setPosition(2048 / 2, 2732 - player.height);
	player.setTarget(player.x, player.y);
	background.exitDoor.visible = false;
	game.allEnemiesKilled = false;
	waveDisplay.setText('Wave: ' + game.waveCount);
	game.spawnEnemies(game.waveCount++);
	LK.effects.flashScreen(0x000000, 2000);
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i].indicator) {
			enemyBullets[i].indicator.destroy();
		}
		enemyBullets[i].destroy();
		enemyBullets.splice(i, 1);
	}
};
game.on('down', function (obj) {
	if (!game.allEnemiesKilled) {
		var pos = obj.event.getLocalPosition(game);
		game.setPlayerTarget(pos.x, pos.y);
	}
}); /**** 
* Classes
****/
var EnemyBulletIndicator = Container.expand(function () {
	var self = Container.call(this);
	var indicatorGraphics = self.attachAsset('enemyBulletIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicatorGraphics.alpha = 0.5;
});
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	var obstacleGraphics = self.attachAsset('obstacle', {
		anchorX: 0.5,
		anchorY: 1
	});
	obstacleGraphics.y += 50;
});
var ExitDoor = Container.expand(function () {
	var self = Container.call(this);
	var backgroundElement = self.attachAsset('backgroundElement1', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundElement.y -= 760;
	var backgroundElement2 = self.attachAsset('backgroundElement2', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundElement2.y -= 760;
	backgroundElement2.blendMode = 1;
	var doorGraphics = self.attachAsset('exitDoor', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.rotate = function () {
		backgroundElement.rotation += 0.00125;
		backgroundElement2.rotation -= 0.00175;
	};
});
var EnemySpawnIndicator = Container.expand(function () {
	var self = Container.call(this);
	var spawnIndicatorGraphics = self.attachAsset('spawnIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	spawnIndicatorGraphics.alpha = 0.5;
});
var ExplosionParticle = Container.expand(function () {
	var self = Container.call(this);
	var particleGraphics = self.attachAsset('particle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	particleGraphics.blendMode = 1;
	self.dx = (Math.random() - 0.5) * 10;
	self.dy = (Math.random() - 0.5) * 7;
	self.move = function () {
		self.setPosition(self.x + self.dx, self.y + self.dy);
		self.alpha -= 0.02;
		particleGraphics.scale.set(particleGraphics.scale.x * 0.98, particleGraphics.scale.y * 0.98);
		self.dx *= 0.98;
		self.dy *= 0.98;
		if (self.alpha <= 0) {
			self.destroy();
		}
	};
});
var HealthBar = Container.expand(function () {
	var self = Container.call(this);
	var healthBarGraphics = self.attachAsset('healthBar', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.setTint = function (tint) {
		healthBarGraphics.tint = tint;
	};
	self.setTint(0x00FF00);
	self.updateHealth = function (health) {
		self.scale.set(health / 100, 1);
	};
});
var TargetIndicator = Container.expand(function () {
	var self = Container.call(this);
	var targetGraphics = self.attachAsset('target', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	targetGraphics.alpha = 0.5;
	targetGraphics.y -= 30;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	self.health = 100;
	self.findNearestEnemy = function (enemies) {
		var nearestEnemy = null;
		var nearestDistance = Infinity;
		for (var i = 0; i < enemies.length; i++) {
			var dx = enemies[i].x - self.x;
			var dy = enemies[i].y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < nearestDistance && !self.parent.lineIntersectsObstacle(self.x, self.y, enemies[i].x, enemies[i].y)) {
				nearestDistance = distance;
				nearestEnemy = enemies[i];
			}
		}
		return nearestEnemy;
	};
	var playerShadow = self.attachAsset('playerShadow', {
		anchorX: 0.5,
		anchorY: 0.8
	});
	playerShadow.alpha = 0.3;
	var playerAsset = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 1
	});
	var healthBar = new HealthBar();
	self.addChild(healthBar).y = -self.children[1].height;
	self.healthBar = healthBar;
	self.targetX = 2048 / 2;
	self.targetY = 2732 / 2;
	self.speed = 5;
	self.lastShot = 0;
	self.move = function (obstacles) {
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance > self.speed) {
			self.setPosition(self.x + dx / distance * self.speed, self.y + dy / distance * self.speed);
			for (var i = 0; i < obstacles.length; i++) {
				var dx = obstacles[i].x - self.x;
				var dy = obstacles[i].y - self.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < obstacles[i].width / 2) {
					self.x -= dx / distance * 10;
					self.y -= dy / distance * 10;
				}
			}
			self.healthBar.updateHealth(self.health);
			return true;
		}
		self.healthBar.updateHealth(self.health);
		return false;
	};
	self.setTarget = function (x, y) {
		self.targetX = x;
		self.targetY = y;
	};
	self.shoot = function (enemies) {
		var nearestEnemy = self.findNearestEnemy(enemies);
		if (nearestEnemy) {
			var bullet = new PlayerBullet();
			bullet.setPosition(self.x, self.y);
			var dx = nearestEnemy.x - self.x;
			var dy = nearestEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			bullet.dx = dx / distance;
			bullet.dy = dy / distance;
			return bullet;
		}
		return null;
	};
	self.flashRed = function () {
		LK.effects.flashObject(playerAsset, 0xFF0000, 1000);
	};
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	self.throwProjectile = function (player) {
		if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			var projectile = new EnemyBullet();
			projectile.setPosition(self.x, self.y);
			projectile.originX = self.x;
			projectile.originY = self.y;
			projectile.targetX = player.x;
			projectile.targetY = player.y;
			projectile.dx = dx / distance;
			projectile.dy = dy / distance;
			return projectile;
		}
		return null;
	};
	self.moveTowardsPlayer = function (player) {
		if (!self.parent.lineIntersectsObstacle(self.x, self.y, player.x, player.y)) {
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 800) {
				self.dx += dx / distance * 0.3;
				self.dy += dy / distance * 0.3;
				return true;
			}
		}
		return false;
	};
	;
	self.alpha = 0;
	self.lastProjectile = 0;
	self.dx = 0;
	self.dy = 0;
	self.health = 100;
	self.animateIn = function () {
		self.fadeInTicks = 50;
	};
	var enemyShadow = self.attachAsset('enemyShadow', {
		anchorX: 0.5,
		anchorY: 0.8
	});
	enemyShadow.alpha = 0.3;
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 1
	});
	var healthBar = new HealthBar();
	healthBar.setTint(0xFF0000);
	healthBar.y = -enemyGraphics.height;
	self.addChild(healthBar);
	self.healthBar = healthBar;
	self.healthBar.updateHealth(self.health);
	self.move = function (obstacles, player) {
		var movedTowardsPlayer = true;
		if (self.fadeInTicks > 0) {
			self.alpha += 0.02;
			self.fadeInTicks--;
		} else {
			movedTowardsPlayer = self.moveTowardsPlayer(player);
		}
		self.setPosition(self.x + self.dx, self.y + self.dy);
		self.dx *= 0.80;
		self.dy *= 0.80;
		if (self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) {
			self.x = Math.max(Math.min(self.x, 2048 - 150), 150);
			self.y = Math.max(Math.min(self.y, 2732 - 150), 700);
		}
		for (var i = 0; i < obstacles.length; i++) {
			var dx = obstacles[i].x - self.x;
			var dy = obstacles[i].y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < obstacles[i].width / 2) {
				self.x -= dx / distance * 10;
				self.y -= dy / distance * 10;
			}
		}
		return movedTowardsPlayer;
	};
	self.flashRed = function () {
		LK.effects.flashObject(enemyGraphics, 0xFF0000, 1000);
	};
});
var PlayerBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bulletGraphics.y -= 150;
	bulletGraphics.blendMode = 1;
	self.dx = 0;
	self.dy = 0;
	self.move = function () {
		self.dx *= 1.02;
		self.dy *= 1.02;
		self.setPosition(self.x + self.dx * 4, self.y + self.dy * 4);
		return self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150;
	};
});
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bulletGraphics.y -= 150;
	self.dx = 0;
	self.dy = 0;
	self.originX = 0;
	self.originY = 0;
	self.move = function () {
		self.setPosition(self.x + self.dx * 4.2, self.y + self.dy * 4.2);
		bulletGraphics.rotation += 0.1;
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2));
		var percentCompleted = distance / totalDistance;
		bulletGraphics.y = -150 * percentCompleted - 200 * Math.sin(Math.PI * percentCompleted);
		if (!self.indicator) {
			self.indicator = new EnemyBulletIndicator();
			self.indicator.setPosition(self.targetX, self.targetY);
			self.parent.addChild(self.indicator);
		}
		var totalDistance = Math.sqrt(Math.pow(self.targetX - self.originX, 2) + Math.pow(self.targetY - self.originY, 2));
		var percentCompleted = 1 - distance / totalDistance;
		self.indicator.scale.set(3 - 2 * percentCompleted, 3 - 2 * percentCompleted);
		self.indicator.alpha = percentCompleted;
		if (distance < 25 || self.x < 150 || self.x > 2048 - 150 || self.y < 700 || self.y > 2732 - 150) {
			self.indicator.destroy();
			return true;
		}
		return false;
	};
});
var Background = Container.expand(function () {
	var self = Container.call(this);
	var backgroundGraphics = self.attachAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	backgroundGraphics.setPosition(2048 / 2, 2732 / 2 + 300);
	self.exitDoor = self.addChildAt(new ExitDoor(), 1);
	self.exitDoor.setPosition(2048 / 2, 2732 / 2 - 670 + 400);
	self.exitDoor.visible = false;
});
/**** 
* Initialize Game
****/
var game = new LK.Game({
	backgroundColor: 0x343942
});
/**** 
* Game Code
****/
game.enemyBulletMove = function () {
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i] && enemyBullets[i].move()) {
			var dx = player.x - enemyBullets[i].x;
			var dy = player.y - enemyBullets[i].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < 225 && !game.allEnemiesKilled) {
				player.health -= 10;
				player.healthBar.updateHealth(player.health);
				player.flashRed();
				if (player.health <= 0) {
					LK.showGameOver();
				}
			}
			game.createExplosion(enemyBullets[i].x, enemyBullets[i].y);
			enemyBullets[i].destroy();
			enemyBullets.splice(i, 1);
		}
	}
};
game.lineIntersectsObstacle = function (x1, y1, x2, y2) {
	for (var i = 0; i < obstacles.length; i++) {
		var dx = obstacles[i].x - x1;
		var dy = obstacles[i].y - y1;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var radius = obstacles[i].width * 0.7 / 2;
		if (distance < radius) {
			return true;
		}
		var t = ((x2 - x1) * (obstacles[i].x - x1) + (y2 - y1) * (obstacles[i].y - y1)) / (Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
		t = Math.max(0, Math.min(1, t));
		var nearestX = x1 + t * (x2 - x1);
		var nearestY = y1 + t * (y2 - y1);
		dx = obstacles[i].x - nearestX;
		dy = obstacles[i].y - nearestY;
		distance = Math.sqrt(dx * dx + dy * dy);
		if (distance <= radius) {
			return true;
		}
	}
	return false;
};
game.allEnemiesKilled = false;
game.waveCount = 2;
game.setPlayerTarget = function (x, y) {
	x = Math.max(Math.min(x, 2048 - 150), 150);
	y = Math.max(Math.min(y, 2732 - 150), 700);
	player.setTarget(x, y);
	targetIndicator.setPosition(x, y);
	targetIndicator.visible = true;
};
game.checkEnemies = function () {
	if (!game.allEnemiesKilled && enemies.length === 0 && spawnIndicators.length === 0) {
		background.exitDoor.visible = true;
		game.allEnemiesKilled = true;
		LK.effects.flashScreen(0xFFFFFF, 1000);
		game.setPlayerTarget(background.exitDoor.x, background.exitDoor.y - 300);
	}
};
game.rotateBackground = function () {
	background.children[1].rotate();
};
game.particleMove = function () {
	for (var i = particles.length - 1; i >= 0; i--) {
		if (particles[i].alpha <= 0) {
			particles[i].destroy();
			particles.splice(i, 1);
		} else {
			particles[i].move();
		}
	}
};
game.bulletMove = function () {
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i] && bullets[i].move()) {
			game.createExplosion(bullets[i].x, bullets[i].y - 150);
			bullets[i].destroy();
			bullets.splice(i, 1);
		} else {
			bullets[i].move();
			for (var j = 0; j < enemies.length; j++) {
				if (bullets[i].intersects(enemies[j])) {
					enemies[j].health -= 10;
					enemies[j].healthBar.updateHealth(enemies[j].health);
					enemies[j].flashRed();
					if (enemies[j].health <= 0) {
						enemies[j].destroy();
						enemies.splice(j, 1);
						score += 1;
						LK.setScore(score);
						scoreDisplay.setText(score.toString());
					} else {
						var angle = Math.atan2(bullets[i].dy, bullets[i].dx);
						enemies[j].x += Math.cos(angle) * 15;
						enemies[j].y += Math.sin(angle) * 15;
						enemies[j].dx = Math.cos(angle) * 10;
						enemies[j].dy = Math.sin(angle) * 10;
					}
					game.createExplosion(bullets[i].x, bullets[i].y - 150);
					bullets[i].destroy();
					bullets.splice(i, 1);
					break;
				}
			}
		}
	}
};
game.enemyTick = function () {
	for (var i = 0; i < enemies.length; i++) {
		var moved = enemies[i].move(obstacles, player);
		for (var j = i + 1; j < enemies.length; j++) {
			var dx = enemies[j].x - enemies[i].x;
			var dy = enemies[j].y - enemies[i].y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < enemies[i].width) {
				enemies[i].x -= dx / distance;
				enemies[i].y -= dy / distance;
				enemies[j].x += dx / distance;
				enemies[j].y += dy / distance;
			}
		}
		if (!moved && LK.ticks - enemies[i].lastProjectile >= 180) {
			enemies[i].lastProjectile = LK.ticks;
			var projectile = enemies[i].throwProjectile(player);
			if (projectile) {
				enemyBullets.push(projectile);
				game.addChild(projectile);
			}
		}
	}
};
game.playerMove = function (obstacles) {
	player.move(obstacles);
	var dx = player.targetX - player.x;
	var dy = player.targetY - player.y;
	var distance = Math.sqrt(dx * dx + dy * dy);
	if (distance < player.speed && LK.ticks - player.lastShot >= 30 && enemies.length > 0) {
		player.lastShot = LK.ticks;
		var bullet = player.shoot(enemies);
		if (bullet) {
			bullets.push(bullet);
			game.addChild(bullet);
		}
	}
	if (distance < player.speed) {
		targetIndicator.visible = false;
		if (game.allEnemiesKilled) {
			game.spawnNextWave();
		}
	}
};
var spawnIndicators = [];
game.isTooClose = function (x, y) {
	for (var i = 0; i < spawnIndicators.length; i++) {
		var dx = spawnIndicators[i].x - x;
		var dy = spawnIndicators[i].y - y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < 200) {
			return true;
		}
	}
	return false;
};
game.spawnEnemies = function (count) {
	for (var i = 0; i < count; i++) {
		var x, y;
		do {
			x = Math.random() * (2048 - 300) + 150;
			y = Math.random() * (2732 - 850) + 700;
		} while (game.isTooClose(x, y) || game.lineIntersectsObstacle(x, y, x, y));
		var spawnIndicator = game.addChild(new EnemySpawnIndicator());
		spawnIndicator.setPosition(x, y);
		spawnIndicators.push(spawnIndicator);
		(function (spawnIndicator) {
			LK.setTimeout(function () {
				var enemy = game.addChild(new Enemy());
				enemy.setPosition(spawnIndicator.x, spawnIndicator.y);
				enemies.push(enemy);
				spawnIndicator.destroy();
				enemy.animateIn();
				var index = spawnIndicators.indexOf(spawnIndicator);
				if (index > -1) {
					spawnIndicators.splice(index, 1);
				}
			}, 2000);
		})(spawnIndicator);
	}
};
game.createExplosion = function (x, y) {
	for (var j = 0; j < 10; j++) {
		var particle = new ExplosionParticle();
		particle.setPosition(x, y);
		particle.dx = (Math.random() - 0.5) * 10;
		particle.dy = (Math.random() - 0.5) * 7;
		game.addChild(particle);
		particles.push(particle);
	}
};
var particles = [];
game.sortGameObjects = function () {
	game.children.sort(function (a, b) {
		return a.y < b.y ? -1 : 1;
	});
	for (var i = 0; i < game.children.length; i++) {
		if (game.children[i] instanceof EnemyBulletIndicator) {
			game.setChildIndex(game.children[i], 1);
		}
	}
	game.setChildIndex(targetIndicator, 1);
};
var background = game.addChild(new Background());
var player = game.addChild(new Player());
player.setPosition(2048 / 2, 2732 - player.height);
player.setTarget(player.x, player.y);
var targetIndicator = game.addChild(new TargetIndicator());
targetIndicator.setPosition(player.x, player.y);
var obstacles = [];
var enemies = [];
game.spawnEnemies(1);
var obstacleSpacing = 2048 / 3;
for (var i = 0; i < 2; i++) {
	for (var j = 0; j < 2; j++) {
		var obstacle = game.addChild(new Obstacle());
		obstacle.setPosition(obstacleSpacing * (i + 1), 2732 / 2 + obstacleSpacing * j);
		obstacles.push(obstacle);
	}
}
var bullets = [];
var enemyBullets = [];
var score = 0;
var scoreDisplay = new Text2(score.toString(), {
	size: 80,
	fill: '#ffffff',
	font: 'Impact',
	dropShadow: true,
	dropShadowColor: '#000000',
	dropShadowBlur: 4,
	dropShadowAngle: Math.PI / 6,
	dropShadowDistance: 6
});
scoreDisplay.anchor.set(0.5, 0);
LK.gui.topCenter.addChild(scoreDisplay);
var waveDisplay = new Text2('Wave: 1', {
	size: 40,
	fill: '#ffffff',
	font: 'Impact',
	dropShadow: true,
	dropShadowColor: '#000000',
	dropShadowBlur: 4,
	dropShadowAngle: Math.PI / 6,
	dropShadowDistance: 6
});
waveDisplay.anchor.set(0.5, 1);
LK.gui.bottom.addChild(waveDisplay);
LK.on('tick', function () {
	game.playerMove(obstacles);
	game.bulletMove();
	game.enemyTick();
	game.enemyBulletMove();
	game.particleMove();
	game.rotateBackground();
	game.sortGameObjects();
	game.checkEnemies();
});
game.spawnNextWave = function () {
	player.setPosition(2048 / 2, 2732 - player.height);
	player.setTarget(player.x, player.y);
	background.exitDoor.visible = false;
	game.allEnemiesKilled = false;
	waveDisplay.setText('Wave: ' + game.waveCount);
	game.spawnEnemies(game.waveCount++);
	LK.effects.flashScreen(0x000000, 2000);
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		if (enemyBullets[i].indicator) {
			enemyBullets[i].indicator.destroy();
		}
		enemyBullets[i].destroy();
		enemyBullets.splice(i, 1);
	}
};
game.on('down', function (obj) {
	if (!game.allEnemiesKilled) {
		var pos = obj.event.getLocalPosition(game);
		game.setPlayerTarget(pos.x, pos.y);
	}
});
:quality(85)/https://cdn.frvr.ai/205530ae-47e8-4773-8e8a-227301037d53_bl.png%3F3) 
 giant wall Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical
:quality(85)/https://cdn.frvr.ai/27e54e42-cf86-4b83-bb0d-76f327c8e15d_tl_transparent_trim.png%3F3) 
 Single Short round Isometric dungeon column, simple, few stones, single column, no floor, dark room, Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/631f6fda-a702-4735-bf5b-c7683c6ee557_bl.png%3F3) 
 Multi color chaotic noise, primary colors Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/6bdfe9a9-1e4d-41a4-89f5-a84925eb01bd_tl_transparent_trim.png%3F3) 
 Round purple magic fireball. White core Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/720ba024-f46a-4f52-84ac-2ba0c644bc1e_bl_transparent_trim.png%3F3) 
 enemy goblin , Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical, seen from front. No staff.
:quality(85)/https://cdn.frvr.ai/86afcb9f-210d-4e29-a7ea-32701dea2912_tl_transparent_trim.png%3F3) 
 Single fire particle Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/8e1135fc-30ec-4259-9446-178acea915ff_tl.png%3F3) 
 https://i.imgur.com/R3ZLguO.jpg Dungeon, Empty open floor, dark, fullscreen, Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. high detail. High contrast. --ar 2:3
:quality(85)/https://cdn.frvr.ai/a3e47ade-c6eb-4dc5-a8f7-ee7392944239_br_transparent_trim.png%3F3) 
 single wizard, hooded Pixel art, 16 bit, isometric, SNES, top-down, no background, white background, low resolution, symmetrical, seen from front.
:quality(85)/https://cdn.frvr.ai/af50747f-5307-4901-8761-e417dd9958d4_bl_transparent_trim.png%3F3) 
 round bomb. fuse on fire Single Game Texture. In-Game asset. 2d. Pixelart. White background. Blank background. Low detail. High contrast.
:quality(85)/https://cdn.frvr.ai/e845b503-9a77-4fde-b7db-b7b43f18539a_tl.png%3F3) 
 Multi color chaotic noise, primary colors. Rays from the center. Darker center Single Game Texture. In-Game asset. 2d. Pixelart. Low detail. High contrast.