/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Laser Cannon Class
var Cannon = Container.expand(function () {
	var self = Container.call(this);
	// Base
	var base = self.attachAsset('cannonBase', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0
	});
	// Barrel
	var barrel = self.attachAsset('cannonBarrel', {
		anchorX: 0.5,
		anchorY: 1,
		y: -80
	});
	// Glow (for charging)
	var glow = self.attachAsset('cannonGlow', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -80,
		alpha: 0
	});
	self.barrel = barrel;
	self.glow = glow;
	// Add a hitbox for the cannon body (for enemy collision)
	var bodyHitbox = LK.getAsset('cannonBase', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0,
		alpha: 0 // invisible, just for collision
	});
	self.addChild(bodyHitbox);
	self.bodyHitbox = bodyHitbox;
	// Cannon rotation (radians)
	self.angle = 0;
	// Charging state
	self.isCharging = false;
	self.chargeTime = 0; // ms
	// Set cannon angle (radians)
	self.setAngle = function (r) {
		self.angle = r;
		barrel.rotation = r - Math.PI / 2;
		glow.rotation = r - Math.PI / 2;
	};
	// Start charging
	self.startCharge = function () {
		self.isCharging = true;
		self.chargeTime = 0;
		glow.alpha = 0.5;
		glow.scaleX = 1;
		glow.scaleY = 1;
	};
	// Stop charging
	self.stopCharge = function () {
		self.isCharging = false;
		glow.alpha = 0;
		glow.scaleX = 1;
		glow.scaleY = 1;
	};
	// Update charging visuals
	self.updateCharge = function (dt) {
		if (self.isCharging) {
			self.chargeTime += dt;
			var scale = 1 + Math.min(self.chargeTime / 800, 1.5);
			glow.scaleX = scale;
			glow.scaleY = scale;
			glow.alpha = 0.5 + 0.3 * Math.sin(LK.ticks / 6);
		}
	};
	return self;
});
// Enemy Drone Class
var Drone = Container.expand(function () {
	var self = Container.call(this);
	// Body
	var body = self.attachAsset('droneBody', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Eye
	var eye = self.attachAsset('droneEye', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0
	});
	// Movement
	self.speed = 3 + Math.random() * 2; // Will be increased by wave
	self.waveOffset = Math.random() * Math.PI * 2;
	self.waveAmp = 60 + Math.random() * 40;
	// For collision
	self.radius = 60;
	// Update
	self.update = function () {
		// Sway left/right
		self.x += Math.sin(self.y / 180 + self.waveOffset) * 2;
		self.y += self.speed;
	};
	return self;
});
// Explosion Effect
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	var exp = self.attachAsset('explosion', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.8
	});
	// Animate and destroy
	tween(exp, {
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	}, {
		duration: 400,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			self.destroy();
		}
	});
	return self;
});
// Laser Beam Class
var LaserBeam = Container.expand(function () {
	var self = Container.call(this);
	// Beam
	var beam = self.attachAsset('laserBeam', {
		anchorX: 0.5,
		anchorY: 1,
		y: 0
	});
	self.beam = beam;
	// Direction (radians)
	self.angle = 0;
	// Power (1 = normal, >1 = charged)
	self.power = 1;
	// Speed (pixels per frame)
	self.speed = 60;
	// Set angle
	self.setAngle = function (r) {
		self.angle = r;
		self.rotation = r - Math.PI / 2;
	};
	// Set power (affects width/length)
	self.setPower = function (p) {
		self.power = p;
		beam.width = 24 * p;
		beam.height = 900 + 300 * (p - 1);
	};
	// Update
	self.update = function () {
		self.x += Math.cos(self.angle) * self.speed;
		self.y += Math.sin(self.angle) * self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181c2a
});
/**** 
* Game Code
****/ 
// Background shape asset
// Sound effects
// Explosion effect
// Enemy Drone
// Laser Beam
// Laser Cannon (player)
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var CANNON_Y = GAME_HEIGHT - 180;
var CANNON_X = GAME_WIDTH / 2;
// State
var cannon;
var laserBeams = [];
var drones = [];
var canFire = true;
var fireCooldown = 0;
var lastTouch = {
	x: CANNON_X,
	y: CANNON_Y - 400
};
var wave = 1;
var spawnTimer = 0;
var spawnInterval = 140; // frames (increased to reduce enemy quantity)
var scoreTxt;
// Add background shape
var background = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	width: GAME_WIDTH,
	height: GAME_HEIGHT,
	color: 0x222244
});
game.addChild(background);
// Add cannon
cannon = new Cannon();
game.addChild(cannon);
cannon.x = CANNON_X;
cannon.y = CANNON_Y;
cannon.setAngle(-Math.PI / 2);
// Score display
scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: clamp angle to upper half of screen
function clampAngle(r) {
	// Only allow aiming between -160deg and -20deg (in radians)
	var min = -Math.PI * 0.89; // ~-160deg
	var max = -Math.PI * 0.11; // ~-20deg
	if (r < min) r = min;
	if (r > max) r = max;
	return r;
}
// Touch/drag aiming and charging
var isTouching = false;
game.down = function (x, y, obj) {
	// Don't allow touch in top 100px (menu)
	if (y < 100 && x < 100) return;
	isTouching = true;
	lastTouch.x = x;
	lastTouch.y = y;
	// Calculate angle
	var dx = x - cannon.x;
	var dy = y - cannon.y;
	var angle = Math.atan2(dy, dx);
	angle = clampAngle(angle);
	cannon.setAngle(angle);
	cannon.startCharge();
};
game.move = function (x, y, obj) {
	if (!isTouching) return;
	lastTouch.x = x;
	lastTouch.y = y;
	var dx = x - cannon.x;
	var dy = y - cannon.y;
	var angle = Math.atan2(dy, dx);
	angle = clampAngle(angle);
	cannon.setAngle(angle);
};
game.up = function (x, y, obj) {
	if (!isTouching) return;
	isTouching = false;
	// Fire laser
	if (canFire) {
		var power = 1 + Math.min(cannon.chargeTime / 800, 1.5); // up to 2.5x
		fireLaser(cannon.angle, power);
		canFire = false;
		fireCooldown = 24; // frames
	}
	cannon.stopCharge();
};
// Fire laser
function fireLaser(angle, power) {
	var laser = new LaserBeam();
	laser.x = cannon.x + Math.cos(angle) * 0;
	laser.y = cannon.y + Math.sin(angle) * 0;
	laser.setAngle(angle);
	laser.setPower(power);
	laserBeams.push(laser);
	game.addChild(laser);
	LK.getSound('laserFire').play();
}
// Spawn a drone
function spawnDrone() {
	var drone = new Drone();
	// Random x, but not too close to edge
	var margin = 120;
	drone.x = margin + Math.random() * (GAME_WIDTH - margin * 2);
	drone.y = -80;
	// Increase speed with wave
	drone.speed += (wave - 1) * 0.5;
	drones.push(drone);
	game.addChild(drone);
}
// Destroy drone with explosion
function destroyDrone(drone) {
	var exp = new Explosion();
	exp.x = drone.x;
	exp.y = drone.y;
	game.addChild(exp);
	LK.getSound('droneExplode').play();
	drone.destroy();
}
// Main update loop
game.update = function () {
	// Update cannon charging visuals
	cannon.updateCharge(16.7);
	// Fire cooldown
	if (!canFire) {
		fireCooldown--;
		if (fireCooldown <= 0) canFire = true;
	}
	// Laser beams update
	for (var i = laserBeams.length - 1; i >= 0; i--) {
		var l = laserBeams[i];
		l.update();
		// Remove if off screen
		if (l.x < -100 || l.x > GAME_WIDTH + 100 || l.y < -100 || l.y > GAME_HEIGHT + 100) {
			l.destroy();
			laserBeams.splice(i, 1);
			continue;
		}
	}
	// Drones update
	for (var j = drones.length - 1; j >= 0; j--) {
		var d = drones[j];
		d.update();
		// Check if reached cannon (game over)
		// Check collision with cannon body hitbox
		if (d.bodyLastWasIntersecting === undefined) d.bodyLastWasIntersecting = false;
		var isIntersecting = d.intersects(cannon.bodyHitbox);
		if (!d.bodyLastWasIntersecting && isIntersecting) {
			// Game over
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
			return;
		}
		d.bodyLastWasIntersecting = isIntersecting;
		// Remove if off screen
		if (d.y > GAME_HEIGHT + 100) {
			d.destroy();
			drones.splice(j, 1);
			continue;
		}
	}
	// Laser-drone collision
	for (var i = laserBeams.length - 1; i >= 0; i--) {
		var l = laserBeams[i];
		var lx = l.x + Math.cos(l.angle) * l.beam.height / 2;
		var ly = l.y + Math.sin(l.angle) * l.beam.height / 2;
		for (var j = drones.length - 1; j >= 0; j--) {
			var d = drones[j];
			// Approximate collision: check if laser line passes through drone circle
			var dx = d.x - l.x;
			var dy = d.y - l.y;
			var proj = dx * Math.cos(l.angle) + dy * Math.sin(l.angle);
			if (proj > 0 && proj < l.beam.height) {
				// Closest point on beam
				var px = l.x + Math.cos(l.angle) * proj;
				var py = l.y + Math.sin(l.angle) * proj;
				var dist = Math.sqrt((d.x - px) * (d.x - px) + (d.y - py) * (d.y - py));
				if (dist < d.radius * (0.7 + 0.2 * l.power)) {
					// Hit!
					destroyDrone(d);
					drones.splice(j, 1);
					// Score
					var addScore = Math.floor(10 * l.power);
					LK.setScore(LK.getScore() + addScore);
					scoreTxt.setText(LK.getScore());
					// Remove laser
					l.destroy();
					laserBeams.splice(i, 1);
					break;
				}
			}
		}
	}
	// Spawn drones
	spawnTimer++;
	var interval = Math.max(60, spawnInterval - (wave - 1) * 3);
	if (spawnTimer >= interval) {
		spawnDrone();
		spawnTimer = 0;
	}
	// Increase wave every 20 drones destroyed
	var currentScore = LK.getScore();
	var newWave = 1 + Math.floor(currentScore / 200);
	if (newWave > wave) {
		wave = newWave;
		// Flash for new wave
		LK.effects.flashScreen(0x44ff44, 400);
	}
};
// Play background music at game start
LK.playMusic('1alarmofwar'); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Laser Cannon Class
var Cannon = Container.expand(function () {
	var self = Container.call(this);
	// Base
	var base = self.attachAsset('cannonBase', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0
	});
	// Barrel
	var barrel = self.attachAsset('cannonBarrel', {
		anchorX: 0.5,
		anchorY: 1,
		y: -80
	});
	// Glow (for charging)
	var glow = self.attachAsset('cannonGlow', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -80,
		alpha: 0
	});
	self.barrel = barrel;
	self.glow = glow;
	// Add a hitbox for the cannon body (for enemy collision)
	var bodyHitbox = LK.getAsset('cannonBase', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0,
		alpha: 0 // invisible, just for collision
	});
	self.addChild(bodyHitbox);
	self.bodyHitbox = bodyHitbox;
	// Cannon rotation (radians)
	self.angle = 0;
	// Charging state
	self.isCharging = false;
	self.chargeTime = 0; // ms
	// Set cannon angle (radians)
	self.setAngle = function (r) {
		self.angle = r;
		barrel.rotation = r - Math.PI / 2;
		glow.rotation = r - Math.PI / 2;
	};
	// Start charging
	self.startCharge = function () {
		self.isCharging = true;
		self.chargeTime = 0;
		glow.alpha = 0.5;
		glow.scaleX = 1;
		glow.scaleY = 1;
	};
	// Stop charging
	self.stopCharge = function () {
		self.isCharging = false;
		glow.alpha = 0;
		glow.scaleX = 1;
		glow.scaleY = 1;
	};
	// Update charging visuals
	self.updateCharge = function (dt) {
		if (self.isCharging) {
			self.chargeTime += dt;
			var scale = 1 + Math.min(self.chargeTime / 800, 1.5);
			glow.scaleX = scale;
			glow.scaleY = scale;
			glow.alpha = 0.5 + 0.3 * Math.sin(LK.ticks / 6);
		}
	};
	return self;
});
// Enemy Drone Class
var Drone = Container.expand(function () {
	var self = Container.call(this);
	// Body
	var body = self.attachAsset('droneBody', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Eye
	var eye = self.attachAsset('droneEye', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 0
	});
	// Movement
	self.speed = 3 + Math.random() * 2; // Will be increased by wave
	self.waveOffset = Math.random() * Math.PI * 2;
	self.waveAmp = 60 + Math.random() * 40;
	// For collision
	self.radius = 60;
	// Update
	self.update = function () {
		// Sway left/right
		self.x += Math.sin(self.y / 180 + self.waveOffset) * 2;
		self.y += self.speed;
	};
	return self;
});
// Explosion Effect
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	var exp = self.attachAsset('explosion', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.8
	});
	// Animate and destroy
	tween(exp, {
		scaleX: 2,
		scaleY: 2,
		alpha: 0
	}, {
		duration: 400,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			self.destroy();
		}
	});
	return self;
});
// Laser Beam Class
var LaserBeam = Container.expand(function () {
	var self = Container.call(this);
	// Beam
	var beam = self.attachAsset('laserBeam', {
		anchorX: 0.5,
		anchorY: 1,
		y: 0
	});
	self.beam = beam;
	// Direction (radians)
	self.angle = 0;
	// Power (1 = normal, >1 = charged)
	self.power = 1;
	// Speed (pixels per frame)
	self.speed = 60;
	// Set angle
	self.setAngle = function (r) {
		self.angle = r;
		self.rotation = r - Math.PI / 2;
	};
	// Set power (affects width/length)
	self.setPower = function (p) {
		self.power = p;
		beam.width = 24 * p;
		beam.height = 900 + 300 * (p - 1);
	};
	// Update
	self.update = function () {
		self.x += Math.cos(self.angle) * self.speed;
		self.y += Math.sin(self.angle) * self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x181c2a
});
/**** 
* Game Code
****/ 
// Background shape asset
// Sound effects
// Explosion effect
// Enemy Drone
// Laser Beam
// Laser Cannon (player)
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var CANNON_Y = GAME_HEIGHT - 180;
var CANNON_X = GAME_WIDTH / 2;
// State
var cannon;
var laserBeams = [];
var drones = [];
var canFire = true;
var fireCooldown = 0;
var lastTouch = {
	x: CANNON_X,
	y: CANNON_Y - 400
};
var wave = 1;
var spawnTimer = 0;
var spawnInterval = 140; // frames (increased to reduce enemy quantity)
var scoreTxt;
// Add background shape
var background = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	width: GAME_WIDTH,
	height: GAME_HEIGHT,
	color: 0x222244
});
game.addChild(background);
// Add cannon
cannon = new Cannon();
game.addChild(cannon);
cannon.x = CANNON_X;
cannon.y = CANNON_Y;
cannon.setAngle(-Math.PI / 2);
// Score display
scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: clamp angle to upper half of screen
function clampAngle(r) {
	// Only allow aiming between -160deg and -20deg (in radians)
	var min = -Math.PI * 0.89; // ~-160deg
	var max = -Math.PI * 0.11; // ~-20deg
	if (r < min) r = min;
	if (r > max) r = max;
	return r;
}
// Touch/drag aiming and charging
var isTouching = false;
game.down = function (x, y, obj) {
	// Don't allow touch in top 100px (menu)
	if (y < 100 && x < 100) return;
	isTouching = true;
	lastTouch.x = x;
	lastTouch.y = y;
	// Calculate angle
	var dx = x - cannon.x;
	var dy = y - cannon.y;
	var angle = Math.atan2(dy, dx);
	angle = clampAngle(angle);
	cannon.setAngle(angle);
	cannon.startCharge();
};
game.move = function (x, y, obj) {
	if (!isTouching) return;
	lastTouch.x = x;
	lastTouch.y = y;
	var dx = x - cannon.x;
	var dy = y - cannon.y;
	var angle = Math.atan2(dy, dx);
	angle = clampAngle(angle);
	cannon.setAngle(angle);
};
game.up = function (x, y, obj) {
	if (!isTouching) return;
	isTouching = false;
	// Fire laser
	if (canFire) {
		var power = 1 + Math.min(cannon.chargeTime / 800, 1.5); // up to 2.5x
		fireLaser(cannon.angle, power);
		canFire = false;
		fireCooldown = 24; // frames
	}
	cannon.stopCharge();
};
// Fire laser
function fireLaser(angle, power) {
	var laser = new LaserBeam();
	laser.x = cannon.x + Math.cos(angle) * 0;
	laser.y = cannon.y + Math.sin(angle) * 0;
	laser.setAngle(angle);
	laser.setPower(power);
	laserBeams.push(laser);
	game.addChild(laser);
	LK.getSound('laserFire').play();
}
// Spawn a drone
function spawnDrone() {
	var drone = new Drone();
	// Random x, but not too close to edge
	var margin = 120;
	drone.x = margin + Math.random() * (GAME_WIDTH - margin * 2);
	drone.y = -80;
	// Increase speed with wave
	drone.speed += (wave - 1) * 0.5;
	drones.push(drone);
	game.addChild(drone);
}
// Destroy drone with explosion
function destroyDrone(drone) {
	var exp = new Explosion();
	exp.x = drone.x;
	exp.y = drone.y;
	game.addChild(exp);
	LK.getSound('droneExplode').play();
	drone.destroy();
}
// Main update loop
game.update = function () {
	// Update cannon charging visuals
	cannon.updateCharge(16.7);
	// Fire cooldown
	if (!canFire) {
		fireCooldown--;
		if (fireCooldown <= 0) canFire = true;
	}
	// Laser beams update
	for (var i = laserBeams.length - 1; i >= 0; i--) {
		var l = laserBeams[i];
		l.update();
		// Remove if off screen
		if (l.x < -100 || l.x > GAME_WIDTH + 100 || l.y < -100 || l.y > GAME_HEIGHT + 100) {
			l.destroy();
			laserBeams.splice(i, 1);
			continue;
		}
	}
	// Drones update
	for (var j = drones.length - 1; j >= 0; j--) {
		var d = drones[j];
		d.update();
		// Check if reached cannon (game over)
		// Check collision with cannon body hitbox
		if (d.bodyLastWasIntersecting === undefined) d.bodyLastWasIntersecting = false;
		var isIntersecting = d.intersects(cannon.bodyHitbox);
		if (!d.bodyLastWasIntersecting && isIntersecting) {
			// Game over
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
			return;
		}
		d.bodyLastWasIntersecting = isIntersecting;
		// Remove if off screen
		if (d.y > GAME_HEIGHT + 100) {
			d.destroy();
			drones.splice(j, 1);
			continue;
		}
	}
	// Laser-drone collision
	for (var i = laserBeams.length - 1; i >= 0; i--) {
		var l = laserBeams[i];
		var lx = l.x + Math.cos(l.angle) * l.beam.height / 2;
		var ly = l.y + Math.sin(l.angle) * l.beam.height / 2;
		for (var j = drones.length - 1; j >= 0; j--) {
			var d = drones[j];
			// Approximate collision: check if laser line passes through drone circle
			var dx = d.x - l.x;
			var dy = d.y - l.y;
			var proj = dx * Math.cos(l.angle) + dy * Math.sin(l.angle);
			if (proj > 0 && proj < l.beam.height) {
				// Closest point on beam
				var px = l.x + Math.cos(l.angle) * proj;
				var py = l.y + Math.sin(l.angle) * proj;
				var dist = Math.sqrt((d.x - px) * (d.x - px) + (d.y - py) * (d.y - py));
				if (dist < d.radius * (0.7 + 0.2 * l.power)) {
					// Hit!
					destroyDrone(d);
					drones.splice(j, 1);
					// Score
					var addScore = Math.floor(10 * l.power);
					LK.setScore(LK.getScore() + addScore);
					scoreTxt.setText(LK.getScore());
					// Remove laser
					l.destroy();
					laserBeams.splice(i, 1);
					break;
				}
			}
		}
	}
	// Spawn drones
	spawnTimer++;
	var interval = Math.max(60, spawnInterval - (wave - 1) * 3);
	if (spawnTimer >= interval) {
		spawnDrone();
		spawnTimer = 0;
	}
	// Increase wave every 20 drones destroyed
	var currentScore = LK.getScore();
	var newWave = 1 + Math.floor(currentScore / 200);
	if (newWave > wave) {
		wave = newWave;
		// Flash for new wave
		LK.effects.flashScreen(0x44ff44, 400);
	}
};
// Play background music at game start
LK.playMusic('1alarmofwar');