/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Lane = Container.expand(function (laneIndex) {
	var self = Container.call(this);
	var laneGraphics = self.attachAsset('lane', {
		anchorX: 0.5,
		anchorY: 0
	});
	var hitZone = self.attachAsset('hitZone', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var laneButton = self.attachAsset('laneButton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.laneIndex = laneIndex;
	self.x = 2048 / 6 * (laneIndex + 1);
	hitZone.y = 2500;
	hitZone.alpha = 0.3;
	laneButton.y = 2550;
	laneButton.alpha = 0.7;
	return self;
});
var Note = Container.expand(function () {
	var self = Container.call(this);
	// Randomly select note type (1 or 3 only)
	var noteTypes = [1, 3];
	self.noteType = noteTypes[Math.floor(Math.random() * 2)];
	var noteAssetId = 'note' + self.noteType;
	var noteGraphics = self.attachAsset(noteAssetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.lane = 0;
	self.isActive = true;
	self.update = function () {
		if (self.isActive) {
			self.y += self.speed;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a2e
});
/**** 
* Game Code
****/ 
// Game states
var gameState = 'menu'; // 'menu' or 'playing'
var menuBackground;
var menuTitle;
var playButton;
var instructionsText;
// Game variables
var lanes = [];
var notes = [];
var score = 0;
var combo = 0;
var gameSpeed = 1;
var spawnTimer = 0;
var lives = 3;
var scoreTxt;
var comboTxt;
var feedbackTxt;
var livesTxt;
var feedbackTimer = 0;
// Create main menu
function createMainMenu() {
	// Menu background - sky
	menuBackground = LK.getAsset('skyBackground', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	menuBackground.x = 2048 / 2;
	menuBackground.y = 2732 / 2;
	game.addChild(menuBackground);
	// Menu title
	menuTitle = new Text2('RHYTHM\nARENA', {
		size: 120,
		fill: 0xFFFFFF
	});
	menuTitle.anchor.set(0.5, 0.5);
	menuTitle.x = 2048 / 2;
	menuTitle.y = 800;
	game.addChild(menuTitle);
	// Play button
	playButton = LK.getAsset('laneButton', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 1.5,
		tint: 0x00ff00
	});
	playButton.x = 2048 / 2;
	playButton.y = 1400;
	game.addChild(playButton);
	// Play button text
	var playButtonText = new Text2('PLAY', {
		size: 80,
		fill: 0xFFFFFF
	});
	playButtonText.anchor.set(0.5, 0.5);
	playButtonText.x = 2048 / 2;
	playButtonText.y = 1400;
	game.addChild(playButtonText);
	// Instructions
	instructionsText = new Text2('Tap the lanes to hit notes\nwith perfect timing!\n\nDefend your tower!', {
		size: 60,
		fill: 0xFFFFFF
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 1800;
	game.addChild(instructionsText);
}
// Create game elements
function createGameElements() {
	// Create lanes
	for (var i = 0; i < 5; i++) {
		var lane = new Lane(i);
		lanes.push(lane);
		game.addChild(lane);
	}
	// Create UI text
	scoreTxt = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(scoreTxt);
	scoreTxt.x = 0;
	scoreTxt.y = 30;
	comboTxt = new Text2('Combo: 0', {
		size: 40,
		fill: 0xFFFF00
	});
	comboTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(comboTxt);
	comboTxt.x = 0;
	comboTxt.y = 80;
	livesTxt = new Text2('Lives: 3', {
		size: 50,
		fill: 0xFF0000
	});
	livesTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(livesTxt);
	livesTxt.x = 0;
	livesTxt.y = 140;
	feedbackTxt = new Text2('', {
		size: 80,
		fill: 0x00FF00
	});
	feedbackTxt.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(feedbackTxt);
}
// Initialize menu
createMainMenu();
function spawnNote() {
	var note = new Note();
	var laneIndex = Math.floor(Math.random() * 5);
	note.lane = laneIndex;
	note.x = lanes[laneIndex].x;
	note.y = -50;
	// Start with slower initial speed, but increase more dramatically over time
	note.speed = 4 + gameSpeed * 1.2;
	notes.push(note);
	game.addChild(note);
}
function checkNoteHit(note, timing) {
	var distance = Math.abs(note.y - 2500);
	var perfectRange = 30;
	var goodRange = 60;
	if (distance <= perfectRange) {
		// Perfect hit
		score += 100 + combo * 10;
		combo++;
		showFeedback('PERFECT!', 0x00ff00);
		LK.getSound('lane' + note.lane).play();
		// Add hit effect - scale up and fade out
		tween(note, {
			scaleX: 2,
			scaleY: 2,
			alpha: 0
		}, {
			duration: 300,
			easing: tween.easeOut
		});
		// Add light effect at bottom
		var lightEffect = LK.getAsset('hitZone', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 3,
			scaleY: 0.5,
			alpha: 0.8,
			tint: 0xFFFFFF
		});
		lightEffect.x = note.x;
		lightEffect.y = 2500;
		game.addChild(lightEffect);
		// Animate light effect
		tween(lightEffect, {
			scaleX: 5,
			scaleY: 1,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				lightEffect.destroy();
			}
		});
		return true;
	} else if (distance <= goodRange) {
		// Good hit
		score += 50 + combo * 5;
		combo++;
		showFeedback('GOOD', 0xffff00);
		LK.getSound('lane' + note.lane).play();
		// Add hit effect - scale up and fade out
		tween(note, {
			scaleX: 1.5,
			scaleY: 1.5,
			alpha: 0
		}, {
			duration: 250,
			easing: tween.easeOut
		});
		// Add light effect at bottom
		var lightEffect = LK.getAsset('hitZone', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 2.5,
			scaleY: 0.4,
			alpha: 0.6,
			tint: 0xFFFF00
		});
		lightEffect.x = note.x;
		lightEffect.y = 2500;
		game.addChild(lightEffect);
		// Animate light effect
		tween(lightEffect, {
			scaleX: 4,
			scaleY: 0.8,
			alpha: 0
		}, {
			duration: 350,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				lightEffect.destroy();
			}
		});
		return true;
	} else {
		// Miss
		combo = 0;
		showFeedback('MISS', 0xff0000);
		LK.getSound('miss').play();
		return false;
	}
}
function showFeedback(text, color) {
	feedbackTxt.setText(text);
	feedbackTxt.tint = color;
	feedbackTxt.alpha = 1;
	feedbackTimer = 60; // Show for 1 second
}
function updateUI() {
	scoreTxt.setText('Score: ' + score);
	comboTxt.setText('Combo: ' + combo);
	livesTxt.setText('Lives: ' + lives);
	if (feedbackTimer > 0) {
		feedbackTimer--;
		feedbackTxt.alpha = feedbackTimer / 60;
	}
}
game.down = function (x, y, obj) {
	if (gameState === 'menu') {
		// Check if play button was clicked
		if (playButton && Math.abs(x - playButton.x) < 300 && Math.abs(y - playButton.y) < 90) {
			// Start game
			gameState = 'playing';
			// Remove menu elements
			if (menuBackground) menuBackground.destroy();
			if (menuTitle) menuTitle.destroy();
			if (playButton) playButton.destroy();
			if (instructionsText) instructionsText.destroy();
			// Create game elements
			createGameElements();
			// Start background music
			LK.playMusic('bgmusic', {
				loop: true
			});
			// Add button press effect
			tween(playButton, {
				scaleX: 1.8,
				scaleY: 1.3
			}, {
				duration: 100,
				easing: tween.easeOut
			});
		}
		return;
	}
	// Game playing state
	if (gameState === 'playing') {
		// Check which lane was tapped
		var tappedLane = -1;
		for (var i = 0; i < lanes.length; i++) {
			var laneX = lanes[i].x;
			if (Math.abs(x - laneX) < 150) {
				tappedLane = i;
				// Add visual feedback when button is pressed
				LK.effects.flashObject(lanes[i], 0xffffff, 200);
				// Add button press effect - scale down and back up
				var laneButton = lanes[i].children[2]; // Lane button is the 3rd child
				tween(laneButton, {
					scaleX: 0.8,
					scaleY: 0.8
				}, {
					duration: 100,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(laneButton, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 100,
							easing: tween.easeOut
						});
					}
				});
				break;
			}
		}
		if (tappedLane === -1) return;
		// Find the closest note in that lane
		var closestNote = null;
		var closestDistance = Infinity;
		for (var i = 0; i < notes.length; i++) {
			var note = notes[i];
			if (note.lane === tappedLane && note.isActive) {
				var distance = Math.abs(note.y - 2500);
				if (distance < closestDistance && distance < 100) {
					closestDistance = distance;
					closestNote = note;
				}
			}
		}
		if (closestNote) {
			var hit = checkNoteHit(closestNote, 0);
			if (hit) {
				closestNote.isActive = false;
				closestNote.destroy();
				var index = notes.indexOf(closestNote);
				if (index > -1) {
					notes.splice(index, 1);
				}
			}
		} else {
			// No note found in tapped lane - wrong tap
			lives--;
			combo = 0;
			showFeedback('WRONG LANE!', 0xff0000);
			LK.getSound('miss').play();
			// Check if game over
			if (lives <= 0) {
				LK.showGameOver();
			}
		}
	}
};
game.update = function () {
	if (gameState === 'playing') {
		// Spawn notes with musical rhythm
		spawnTimer++;
		// Reduced note frequency - spawn every 60 ticks (1 second at 60fps) initially
		var baseSpawnRate = 60;
		// Keep spawn rate more stable, reduce frequency less aggressively
		var spawnRate = Math.max(baseSpawnRate - Math.floor(LK.ticks / 7200), 45); // Slower tempo increase
		if (spawnTimer >= spawnRate) {
			spawnNote();
			spawnTimer = 0;
		}
		// Update notes
		for (var i = notes.length - 1; i >= 0; i--) {
			var note = notes[i];
			if (!note.isActive) continue;
			// Check if note reached the bottom without being hit
			if (note.y > 2550) {
				combo = 0;
				lives--;
				showFeedback('MISSED!', 0xff0000);
				LK.getSound('miss').play();
				note.destroy();
				notes.splice(i, 1);
				// Check if game over
				if (lives <= 0) {
					LK.showGameOver();
				}
				continue;
			}
			// Remove notes that are way off screen
			if (note.y > 2800) {
				note.destroy();
				notes.splice(i, 1);
			}
		}
		// Increase difficulty over time
		if (LK.ticks % 1200 === 0) {
			// Every 20 seconds
			gameSpeed += 0.2; // Faster speed increase
		}
		// Update UI
		updateUI();
		// Update score in LK system
		LK.setScore(score);
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Lane = Container.expand(function (laneIndex) {
	var self = Container.call(this);
	var laneGraphics = self.attachAsset('lane', {
		anchorX: 0.5,
		anchorY: 0
	});
	var hitZone = self.attachAsset('hitZone', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var laneButton = self.attachAsset('laneButton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.laneIndex = laneIndex;
	self.x = 2048 / 6 * (laneIndex + 1);
	hitZone.y = 2500;
	hitZone.alpha = 0.3;
	laneButton.y = 2550;
	laneButton.alpha = 0.7;
	return self;
});
var Note = Container.expand(function () {
	var self = Container.call(this);
	// Randomly select note type (1 or 3 only)
	var noteTypes = [1, 3];
	self.noteType = noteTypes[Math.floor(Math.random() * 2)];
	var noteAssetId = 'note' + self.noteType;
	var noteGraphics = self.attachAsset(noteAssetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.lane = 0;
	self.isActive = true;
	self.update = function () {
		if (self.isActive) {
			self.y += self.speed;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a2e
});
/**** 
* Game Code
****/ 
// Game states
var gameState = 'menu'; // 'menu' or 'playing'
var menuBackground;
var menuTitle;
var playButton;
var instructionsText;
// Game variables
var lanes = [];
var notes = [];
var score = 0;
var combo = 0;
var gameSpeed = 1;
var spawnTimer = 0;
var lives = 3;
var scoreTxt;
var comboTxt;
var feedbackTxt;
var livesTxt;
var feedbackTimer = 0;
// Create main menu
function createMainMenu() {
	// Menu background - sky
	menuBackground = LK.getAsset('skyBackground', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	menuBackground.x = 2048 / 2;
	menuBackground.y = 2732 / 2;
	game.addChild(menuBackground);
	// Menu title
	menuTitle = new Text2('RHYTHM\nARENA', {
		size: 120,
		fill: 0xFFFFFF
	});
	menuTitle.anchor.set(0.5, 0.5);
	menuTitle.x = 2048 / 2;
	menuTitle.y = 800;
	game.addChild(menuTitle);
	// Play button
	playButton = LK.getAsset('laneButton', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 1.5,
		tint: 0x00ff00
	});
	playButton.x = 2048 / 2;
	playButton.y = 1400;
	game.addChild(playButton);
	// Play button text
	var playButtonText = new Text2('PLAY', {
		size: 80,
		fill: 0xFFFFFF
	});
	playButtonText.anchor.set(0.5, 0.5);
	playButtonText.x = 2048 / 2;
	playButtonText.y = 1400;
	game.addChild(playButtonText);
	// Instructions
	instructionsText = new Text2('Tap the lanes to hit notes\nwith perfect timing!\n\nDefend your tower!', {
		size: 60,
		fill: 0xFFFFFF
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 1800;
	game.addChild(instructionsText);
}
// Create game elements
function createGameElements() {
	// Create lanes
	for (var i = 0; i < 5; i++) {
		var lane = new Lane(i);
		lanes.push(lane);
		game.addChild(lane);
	}
	// Create UI text
	scoreTxt = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(scoreTxt);
	scoreTxt.x = 0;
	scoreTxt.y = 30;
	comboTxt = new Text2('Combo: 0', {
		size: 40,
		fill: 0xFFFF00
	});
	comboTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(comboTxt);
	comboTxt.x = 0;
	comboTxt.y = 80;
	livesTxt = new Text2('Lives: 3', {
		size: 50,
		fill: 0xFF0000
	});
	livesTxt.anchor.set(0.5, 0);
	LK.gui.top.addChild(livesTxt);
	livesTxt.x = 0;
	livesTxt.y = 140;
	feedbackTxt = new Text2('', {
		size: 80,
		fill: 0x00FF00
	});
	feedbackTxt.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(feedbackTxt);
}
// Initialize menu
createMainMenu();
function spawnNote() {
	var note = new Note();
	var laneIndex = Math.floor(Math.random() * 5);
	note.lane = laneIndex;
	note.x = lanes[laneIndex].x;
	note.y = -50;
	// Start with slower initial speed, but increase more dramatically over time
	note.speed = 4 + gameSpeed * 1.2;
	notes.push(note);
	game.addChild(note);
}
function checkNoteHit(note, timing) {
	var distance = Math.abs(note.y - 2500);
	var perfectRange = 30;
	var goodRange = 60;
	if (distance <= perfectRange) {
		// Perfect hit
		score += 100 + combo * 10;
		combo++;
		showFeedback('PERFECT!', 0x00ff00);
		LK.getSound('lane' + note.lane).play();
		// Add hit effect - scale up and fade out
		tween(note, {
			scaleX: 2,
			scaleY: 2,
			alpha: 0
		}, {
			duration: 300,
			easing: tween.easeOut
		});
		// Add light effect at bottom
		var lightEffect = LK.getAsset('hitZone', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 3,
			scaleY: 0.5,
			alpha: 0.8,
			tint: 0xFFFFFF
		});
		lightEffect.x = note.x;
		lightEffect.y = 2500;
		game.addChild(lightEffect);
		// Animate light effect
		tween(lightEffect, {
			scaleX: 5,
			scaleY: 1,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				lightEffect.destroy();
			}
		});
		return true;
	} else if (distance <= goodRange) {
		// Good hit
		score += 50 + combo * 5;
		combo++;
		showFeedback('GOOD', 0xffff00);
		LK.getSound('lane' + note.lane).play();
		// Add hit effect - scale up and fade out
		tween(note, {
			scaleX: 1.5,
			scaleY: 1.5,
			alpha: 0
		}, {
			duration: 250,
			easing: tween.easeOut
		});
		// Add light effect at bottom
		var lightEffect = LK.getAsset('hitZone', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 2.5,
			scaleY: 0.4,
			alpha: 0.6,
			tint: 0xFFFF00
		});
		lightEffect.x = note.x;
		lightEffect.y = 2500;
		game.addChild(lightEffect);
		// Animate light effect
		tween(lightEffect, {
			scaleX: 4,
			scaleY: 0.8,
			alpha: 0
		}, {
			duration: 350,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				lightEffect.destroy();
			}
		});
		return true;
	} else {
		// Miss
		combo = 0;
		showFeedback('MISS', 0xff0000);
		LK.getSound('miss').play();
		return false;
	}
}
function showFeedback(text, color) {
	feedbackTxt.setText(text);
	feedbackTxt.tint = color;
	feedbackTxt.alpha = 1;
	feedbackTimer = 60; // Show for 1 second
}
function updateUI() {
	scoreTxt.setText('Score: ' + score);
	comboTxt.setText('Combo: ' + combo);
	livesTxt.setText('Lives: ' + lives);
	if (feedbackTimer > 0) {
		feedbackTimer--;
		feedbackTxt.alpha = feedbackTimer / 60;
	}
}
game.down = function (x, y, obj) {
	if (gameState === 'menu') {
		// Check if play button was clicked
		if (playButton && Math.abs(x - playButton.x) < 300 && Math.abs(y - playButton.y) < 90) {
			// Start game
			gameState = 'playing';
			// Remove menu elements
			if (menuBackground) menuBackground.destroy();
			if (menuTitle) menuTitle.destroy();
			if (playButton) playButton.destroy();
			if (instructionsText) instructionsText.destroy();
			// Create game elements
			createGameElements();
			// Start background music
			LK.playMusic('bgmusic', {
				loop: true
			});
			// Add button press effect
			tween(playButton, {
				scaleX: 1.8,
				scaleY: 1.3
			}, {
				duration: 100,
				easing: tween.easeOut
			});
		}
		return;
	}
	// Game playing state
	if (gameState === 'playing') {
		// Check which lane was tapped
		var tappedLane = -1;
		for (var i = 0; i < lanes.length; i++) {
			var laneX = lanes[i].x;
			if (Math.abs(x - laneX) < 150) {
				tappedLane = i;
				// Add visual feedback when button is pressed
				LK.effects.flashObject(lanes[i], 0xffffff, 200);
				// Add button press effect - scale down and back up
				var laneButton = lanes[i].children[2]; // Lane button is the 3rd child
				tween(laneButton, {
					scaleX: 0.8,
					scaleY: 0.8
				}, {
					duration: 100,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(laneButton, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 100,
							easing: tween.easeOut
						});
					}
				});
				break;
			}
		}
		if (tappedLane === -1) return;
		// Find the closest note in that lane
		var closestNote = null;
		var closestDistance = Infinity;
		for (var i = 0; i < notes.length; i++) {
			var note = notes[i];
			if (note.lane === tappedLane && note.isActive) {
				var distance = Math.abs(note.y - 2500);
				if (distance < closestDistance && distance < 100) {
					closestDistance = distance;
					closestNote = note;
				}
			}
		}
		if (closestNote) {
			var hit = checkNoteHit(closestNote, 0);
			if (hit) {
				closestNote.isActive = false;
				closestNote.destroy();
				var index = notes.indexOf(closestNote);
				if (index > -1) {
					notes.splice(index, 1);
				}
			}
		} else {
			// No note found in tapped lane - wrong tap
			lives--;
			combo = 0;
			showFeedback('WRONG LANE!', 0xff0000);
			LK.getSound('miss').play();
			// Check if game over
			if (lives <= 0) {
				LK.showGameOver();
			}
		}
	}
};
game.update = function () {
	if (gameState === 'playing') {
		// Spawn notes with musical rhythm
		spawnTimer++;
		// Reduced note frequency - spawn every 60 ticks (1 second at 60fps) initially
		var baseSpawnRate = 60;
		// Keep spawn rate more stable, reduce frequency less aggressively
		var spawnRate = Math.max(baseSpawnRate - Math.floor(LK.ticks / 7200), 45); // Slower tempo increase
		if (spawnTimer >= spawnRate) {
			spawnNote();
			spawnTimer = 0;
		}
		// Update notes
		for (var i = notes.length - 1; i >= 0; i--) {
			var note = notes[i];
			if (!note.isActive) continue;
			// Check if note reached the bottom without being hit
			if (note.y > 2550) {
				combo = 0;
				lives--;
				showFeedback('MISSED!', 0xff0000);
				LK.getSound('miss').play();
				note.destroy();
				notes.splice(i, 1);
				// Check if game over
				if (lives <= 0) {
					LK.showGameOver();
				}
				continue;
			}
			// Remove notes that are way off screen
			if (note.y > 2800) {
				note.destroy();
				notes.splice(i, 1);
			}
		}
		// Increase difficulty over time
		if (LK.ticks % 1200 === 0) {
			// Every 20 seconds
			gameSpeed += 0.2; // Faster speed increase
		}
		// Update UI
		updateUI();
		// Update score in LK system
		LK.setScore(score);
	}
};