/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 12 + Math.random() * 8; // Random speed between 12-20 for music sync
	self.lastY = 0;
	self.lastCaught = false;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Crystal = Container.expand(function () {
	var self = Container.call(this);
	var crystalGraphics = self.attachAsset('crystal', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	crystalGraphics.rotation = Math.PI / 4; // Rotate 45 degrees for visual distinction
	self.speed = 10 + Math.random() * 6; // Slightly different speed range
	self.lastY = 0;
	self.lastCaught = false;
	self.update = function () {
		self.y += self.speed;
		crystalGraphics.rotation += 0.1; // Rotate while falling
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var balls = [];
var crystals = [];
var dragNode = null;
var ballSpawnTimer = 0;
var ballSpawnInterval = 45; // Spawn every 0.75 seconds at 60fps for faster pace
// Background elements
var backgroundStars = [];
var backgroundNebulae = [];
var backgroundPlanets = [];
// Create animated starfield background
function createBackground() {
	// Create stars
	for (var i = 0; i < 150; i++) {
		var star = game.addChild(LK.getAsset('star', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		star.x = Math.random() * 2048;
		star.y = Math.random() * 2732;
		star.alpha = 0.3 + Math.random() * 0.7;
		star.speed = 0.5 + Math.random() * 2;
		backgroundStars.push(star);
	}
	// Create big stars
	for (var i = 0; i < 20; i++) {
		var bigStar = game.addChild(LK.getAsset('bigStar', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		bigStar.x = Math.random() * 2048;
		bigStar.y = Math.random() * 2732;
		bigStar.alpha = 0.4 + Math.random() * 0.6;
		bigStar.speed = 0.3 + Math.random() * 1;
		backgroundStars.push(bigStar);
	}
	// Create nebulae
	for (var i = 0; i < 8; i++) {
		var nebula = game.addChild(LK.getAsset('nebula', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		nebula.x = Math.random() * 2048;
		nebula.y = Math.random() * 2732;
		nebula.alpha = 0.1 + Math.random() * 0.2;
		nebula.speed = 0.2 + Math.random() * 0.8;
		nebula.scaleX = 0.5 + Math.random() * 1.5;
		nebula.scaleY = 0.5 + Math.random() * 1.5;
		backgroundNebulae.push(nebula);
	}
	// Create planets
	for (var i = 0; i < 3; i++) {
		var planet = game.addChild(LK.getAsset(Math.random() > 0.5 ? 'planet1' : 'planet2', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		planet.x = Math.random() * 2048;
		planet.y = Math.random() * 2732;
		planet.alpha = 0.3 + Math.random() * 0.4;
		planet.speed = 0.1 + Math.random() * 0.5;
		backgroundPlanets.push(planet);
	}
}
// Update background animation
function updateBackground() {
	// Animate stars
	for (var i = 0; i < backgroundStars.length; i++) {
		var star = backgroundStars[i];
		star.y += star.speed;
		star.alpha += Math.sin(LK.ticks * 0.1 + i) * 0.01;
		// Reset star position when it goes off screen
		if (star.y > 2732 + 50) {
			star.y = -50;
			star.x = Math.random() * 2048;
		}
	}
	// Animate nebulae
	for (var i = 0; i < backgroundNebulae.length; i++) {
		var nebula = backgroundNebulae[i];
		nebula.y += nebula.speed;
		nebula.rotation += 0.005;
		// Reset nebula position when it goes off screen
		if (nebula.y > 2732 + 200) {
			nebula.y = -200;
			nebula.x = Math.random() * 2048;
		}
	}
	// Animate planets
	for (var i = 0; i < backgroundPlanets.length; i++) {
		var planet = backgroundPlanets[i];
		planet.y += planet.speed;
		planet.rotation += 0.002;
		// Reset planet position when it goes off screen
		if (planet.y > 2732 + 150) {
			planet.y = -150;
			planet.x = Math.random() * 2048;
		}
	}
}
// Initialize background
createBackground();
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150; // Near bottom of screen
// Music will start after first ball is caught
var musicStarted = false;
// Move handler
function handleMove(x, y, obj) {
	if (dragNode) {
		dragNode.x = x;
		// Keep player within screen bounds
		if (dragNode.x < 60) dragNode.x = 60;
		if (dragNode.x > 2048 - 60) dragNode.x = 2048 - 60;
	}
}
// Event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
	dragNode = player;
	handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Main game update loop
game.update = function () {
	// Update animated background
	updateBackground();
	// Spawn balls and crystals
	ballSpawnTimer++;
	if (ballSpawnTimer >= ballSpawnInterval) {
		ballSpawnTimer = 0;
		// Randomly spawn either a ball or crystal
		if (Math.random() < 0.7) {
			// 70% chance for ball
			var newBall = new Ball();
			newBall.x = 100 + Math.random() * (2048 - 200); // Random x position
			newBall.y = -50; // Start above screen
			newBall.lastY = newBall.y;
			balls.push(newBall);
			game.addChild(newBall);
		} else {
			// 30% chance for crystal
			var newCrystal = new Crystal();
			newCrystal.x = 100 + Math.random() * (2048 - 200); // Random x position
			newCrystal.y = -50; // Start above screen
			newCrystal.lastY = newCrystal.y;
			crystals.push(newCrystal);
			game.addChild(newCrystal);
		}
	}
	// Update balls and check collisions
	for (var i = balls.length - 1; i >= 0; i--) {
		var ball = balls[i];
		// Check if ball touches player
		var currentCaught = ball.intersects(player);
		if (!ball.lastCaught && currentCaught) {
			// Start music when ball first touches player
			if (!musicStarted) {
				LK.playMusic('background');
				musicStarted = true;
			}
			// Ball just got caught
			LK.setScore(LK.getScore() + 1);
			scoreTxt.setText(LK.getScore());
			LK.getSound('catch').play();
			ball.destroy();
			balls.splice(i, 1);
			continue;
		}
		// Check if ball hit the ground (missed)
		if (ball.lastY < 2732 && ball.y >= 2732) {
			// Ball just hit the ground - game over
			LK.stopMusic();
			LK.showGameOver();
			return;
		}
		// Remove balls that are way off screen
		if (ball.y > 2732 + 100) {
			ball.destroy();
			balls.splice(i, 1);
			continue;
		}
		// Update last states
		ball.lastY = ball.y;
		ball.lastCaught = currentCaught;
	}
	// Update crystals and check collisions
	for (var j = crystals.length - 1; j >= 0; j--) {
		var crystal = crystals[j];
		// Check if crystal touches player
		var currentCrystalCaught = crystal.intersects(player);
		if (!crystal.lastCaught && currentCrystalCaught) {
			// Start music when crystal first touches player
			if (!musicStarted) {
				LK.playMusic('background');
				musicStarted = true;
			}
			// Crystal just got caught - worth more points
			LK.setScore(LK.getScore() + 2);
			scoreTxt.setText(LK.getScore());
			LK.getSound('catch').play();
			crystal.destroy();
			crystals.splice(j, 1);
			continue;
		}
		// Check if crystal hit the ground (missed)
		if (crystal.lastY < 2732 && crystal.y >= 2732) {
			// Crystal just hit the ground - game over
			LK.stopMusic();
			LK.showGameOver();
			return;
		}
		// Remove crystals that are way off screen
		if (crystal.y > 2732 + 100) {
			crystal.destroy();
			crystals.splice(j, 1);
			continue;
		}
		// Update last states
		crystal.lastY = crystal.y;
		crystal.lastCaught = currentCrystalCaught;
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 12 + Math.random() * 8; // Random speed between 12-20 for music sync
	self.lastY = 0;
	self.lastCaught = false;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Crystal = Container.expand(function () {
	var self = Container.call(this);
	var crystalGraphics = self.attachAsset('crystal', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	crystalGraphics.rotation = Math.PI / 4; // Rotate 45 degrees for visual distinction
	self.speed = 10 + Math.random() * 6; // Slightly different speed range
	self.lastY = 0;
	self.lastCaught = false;
	self.update = function () {
		self.y += self.speed;
		crystalGraphics.rotation += 0.1; // Rotate while falling
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var balls = [];
var crystals = [];
var dragNode = null;
var ballSpawnTimer = 0;
var ballSpawnInterval = 45; // Spawn every 0.75 seconds at 60fps for faster pace
// Background elements
var backgroundStars = [];
var backgroundNebulae = [];
var backgroundPlanets = [];
// Create animated starfield background
function createBackground() {
	// Create stars
	for (var i = 0; i < 150; i++) {
		var star = game.addChild(LK.getAsset('star', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		star.x = Math.random() * 2048;
		star.y = Math.random() * 2732;
		star.alpha = 0.3 + Math.random() * 0.7;
		star.speed = 0.5 + Math.random() * 2;
		backgroundStars.push(star);
	}
	// Create big stars
	for (var i = 0; i < 20; i++) {
		var bigStar = game.addChild(LK.getAsset('bigStar', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		bigStar.x = Math.random() * 2048;
		bigStar.y = Math.random() * 2732;
		bigStar.alpha = 0.4 + Math.random() * 0.6;
		bigStar.speed = 0.3 + Math.random() * 1;
		backgroundStars.push(bigStar);
	}
	// Create nebulae
	for (var i = 0; i < 8; i++) {
		var nebula = game.addChild(LK.getAsset('nebula', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		nebula.x = Math.random() * 2048;
		nebula.y = Math.random() * 2732;
		nebula.alpha = 0.1 + Math.random() * 0.2;
		nebula.speed = 0.2 + Math.random() * 0.8;
		nebula.scaleX = 0.5 + Math.random() * 1.5;
		nebula.scaleY = 0.5 + Math.random() * 1.5;
		backgroundNebulae.push(nebula);
	}
	// Create planets
	for (var i = 0; i < 3; i++) {
		var planet = game.addChild(LK.getAsset(Math.random() > 0.5 ? 'planet1' : 'planet2', {
			anchorX: 0.5,
			anchorY: 0.5
		}));
		planet.x = Math.random() * 2048;
		planet.y = Math.random() * 2732;
		planet.alpha = 0.3 + Math.random() * 0.4;
		planet.speed = 0.1 + Math.random() * 0.5;
		backgroundPlanets.push(planet);
	}
}
// Update background animation
function updateBackground() {
	// Animate stars
	for (var i = 0; i < backgroundStars.length; i++) {
		var star = backgroundStars[i];
		star.y += star.speed;
		star.alpha += Math.sin(LK.ticks * 0.1 + i) * 0.01;
		// Reset star position when it goes off screen
		if (star.y > 2732 + 50) {
			star.y = -50;
			star.x = Math.random() * 2048;
		}
	}
	// Animate nebulae
	for (var i = 0; i < backgroundNebulae.length; i++) {
		var nebula = backgroundNebulae[i];
		nebula.y += nebula.speed;
		nebula.rotation += 0.005;
		// Reset nebula position when it goes off screen
		if (nebula.y > 2732 + 200) {
			nebula.y = -200;
			nebula.x = Math.random() * 2048;
		}
	}
	// Animate planets
	for (var i = 0; i < backgroundPlanets.length; i++) {
		var planet = backgroundPlanets[i];
		planet.y += planet.speed;
		planet.rotation += 0.002;
		// Reset planet position when it goes off screen
		if (planet.y > 2732 + 150) {
			planet.y = -150;
			planet.x = Math.random() * 2048;
		}
	}
}
// Initialize background
createBackground();
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create player
player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150; // Near bottom of screen
// Music will start after first ball is caught
var musicStarted = false;
// Move handler
function handleMove(x, y, obj) {
	if (dragNode) {
		dragNode.x = x;
		// Keep player within screen bounds
		if (dragNode.x < 60) dragNode.x = 60;
		if (dragNode.x > 2048 - 60) dragNode.x = 2048 - 60;
	}
}
// Event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
	dragNode = player;
	handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Main game update loop
game.update = function () {
	// Update animated background
	updateBackground();
	// Spawn balls and crystals
	ballSpawnTimer++;
	if (ballSpawnTimer >= ballSpawnInterval) {
		ballSpawnTimer = 0;
		// Randomly spawn either a ball or crystal
		if (Math.random() < 0.7) {
			// 70% chance for ball
			var newBall = new Ball();
			newBall.x = 100 + Math.random() * (2048 - 200); // Random x position
			newBall.y = -50; // Start above screen
			newBall.lastY = newBall.y;
			balls.push(newBall);
			game.addChild(newBall);
		} else {
			// 30% chance for crystal
			var newCrystal = new Crystal();
			newCrystal.x = 100 + Math.random() * (2048 - 200); // Random x position
			newCrystal.y = -50; // Start above screen
			newCrystal.lastY = newCrystal.y;
			crystals.push(newCrystal);
			game.addChild(newCrystal);
		}
	}
	// Update balls and check collisions
	for (var i = balls.length - 1; i >= 0; i--) {
		var ball = balls[i];
		// Check if ball touches player
		var currentCaught = ball.intersects(player);
		if (!ball.lastCaught && currentCaught) {
			// Start music when ball first touches player
			if (!musicStarted) {
				LK.playMusic('background');
				musicStarted = true;
			}
			// Ball just got caught
			LK.setScore(LK.getScore() + 1);
			scoreTxt.setText(LK.getScore());
			LK.getSound('catch').play();
			ball.destroy();
			balls.splice(i, 1);
			continue;
		}
		// Check if ball hit the ground (missed)
		if (ball.lastY < 2732 && ball.y >= 2732) {
			// Ball just hit the ground - game over
			LK.stopMusic();
			LK.showGameOver();
			return;
		}
		// Remove balls that are way off screen
		if (ball.y > 2732 + 100) {
			ball.destroy();
			balls.splice(i, 1);
			continue;
		}
		// Update last states
		ball.lastY = ball.y;
		ball.lastCaught = currentCaught;
	}
	// Update crystals and check collisions
	for (var j = crystals.length - 1; j >= 0; j--) {
		var crystal = crystals[j];
		// Check if crystal touches player
		var currentCrystalCaught = crystal.intersects(player);
		if (!crystal.lastCaught && currentCrystalCaught) {
			// Start music when crystal first touches player
			if (!musicStarted) {
				LK.playMusic('background');
				musicStarted = true;
			}
			// Crystal just got caught - worth more points
			LK.setScore(LK.getScore() + 2);
			scoreTxt.setText(LK.getScore());
			LK.getSound('catch').play();
			crystal.destroy();
			crystals.splice(j, 1);
			continue;
		}
		// Check if crystal hit the ground (missed)
		if (crystal.lastY < 2732 && crystal.y >= 2732) {
			// Crystal just hit the ground - game over
			LK.stopMusic();
			LK.showGameOver();
			return;
		}
		// Remove crystals that are way off screen
		if (crystal.y > 2732 + 100) {
			crystal.destroy();
			crystals.splice(j, 1);
			continue;
		}
		// Update last states
		crystal.lastY = crystal.y;
		crystal.lastCaught = currentCrystalCaught;
	}
};