/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var PerfectEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var effectGraphics = self.attachAsset('perfectEffect', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.alpha = 1;
	self.scale.set(0.5, 0.5);
	tween(self, {
		alpha: 0,
		scaleX: 2,
		scaleY: 2
	}, {
		duration: 500,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			self.destroy();
			var index = perfectEffects.indexOf(self);
			if (index > -1) {
				perfectEffects.splice(index, 1);
			}
		}
	});
	return self;
});
var PianoKey = Container.expand(function (lane) {
	var self = Container.call(this);
	var keyGraphics = self.attachAsset('pianoKey', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.lane = lane;
	self.pressed = false;
	self.pressTimer = 0;
	self.update = function () {
		if (self.pressed) {
			self.pressTimer--;
			if (self.pressTimer <= 0) {
				self.setUnpressed();
			}
		}
	};
	self.setPressed = function () {
		if (!self.pressed) {
			self.pressed = true;
			self.pressTimer = 10;
			keyGraphics.removeChild(keyGraphics.children[0]);
			var pressedGraphics = keyGraphics.attachAsset('pianoKeyPressed', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			// Add bouncy press animation to match upbeat music
			tween(self, {
				scaleX: 1.2,
				scaleY: 1.2
			}, {
				duration: 100,
				easing: tween.bounceOut,
				onFinish: function onFinish() {
					tween(self, {
						scaleX: 1.0,
						scaleY: 1.0
					}, {
						duration: 200,
						easing: tween.elasticOut
					});
				}
			});
		}
	};
	self.setUnpressed = function () {
		if (self.pressed) {
			self.pressed = false;
			keyGraphics.removeChild(keyGraphics.children[0]);
			var normalGraphics = keyGraphics.attachAsset('pianoKey', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	self.down = function (x, y, obj) {
		handleKeyPress(self.lane);
	};
	return self;
});
var PianoTile = Container.expand(function (lane, noteIndex) {
	var self = Container.call(this);
	var tileGraphics = self.attachAsset('pianoTile', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.lane = lane;
	self.noteIndex = noteIndex;
	self.speed = gameSpeed;
	self.tapped = false;
	self.lastY = self.y;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
var gameSpeed = 8;
var speedIncrement = 0.5;
var maxSpeed = 20;
var combo = 0;
var gameRunning = true;
var spawnRate = 90;
var spawnCounter = 0;
var lanes = 4;
var laneWidth = 400;
var keyboardY = 2400;
var hitZoneY = 2300;
var hitZoneHeight = 200;
var tiles = [];
var pianoKeys = [];
var perfectEffects = [];
var notes = ['note1', 'note2', 'note3', 'note4'];
var songs = ['song1', 'song2', 'song3'];
var currentSongIndex = 0;
var songStarted = false;
// Create piano keyboard with pulsing animation
for (var i = 0; i < lanes; i++) {
	var key = new PianoKey(i);
	key.x = i * laneWidth + laneWidth / 2 + 224;
	key.y = keyboardY;
	pianoKeys.push(key);
	game.addChild(key);
	// Add subtle pulsing animation to match upbeat music
	tween(key, {
		scaleX: 1.05,
		scaleY: 1.05
	}, {
		duration: 600,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(key, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 600,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Create infinite loop by calling the pulse again
					if (gameRunning) {
						tween(key, {
							scaleX: 1.05,
							scaleY: 1.05
						}, {
							duration: 600,
							easing: tween.easeInOut,
							onFinish: arguments.callee.caller
						});
					}
				}
			});
		}
	});
}
// Create score display
var scoreText = new Text2('Score: 0', {
	size: 80,
	fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create combo display
var comboText = new Text2('', {
	size: 60,
	fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.y = 100;
LK.gui.top.addChild(comboText);
function updateScore() {
	scoreText.setText('Score: ' + LK.getScore());
	if (combo > 5) {
		comboText.setText('Combo: ' + combo);
	} else {
		comboText.setText('');
	}
}
function spawnTile() {
	if (!gameRunning) return;
	// Start music on first tile spawn
	if (!songStarted) {
		LK.playMusic('upbeat', {
			loop: true
		});
		songStarted = true;
	}
	var lane = Math.floor(Math.random() * lanes);
	var tile = new PianoTile(lane, notes[lane]);
	tile.x = lane * laneWidth + laneWidth / 2 + 224;
	tile.y = -50;
	tile.lastY = tile.y;
	// Add bouncy spawn animation to match upbeat music
	tile.scaleX = 0.3;
	tile.scaleY = 0.3;
	tween(tile, {
		scaleX: 1.0,
		scaleY: 1.0
	}, {
		duration: 300,
		easing: tween.bounceOut
	});
	tiles.push(tile);
	game.addChild(tile);
}
function handleKeyPress(lane) {
	if (!gameRunning) return;
	var hitTile = null;
	var bestDistance = Infinity;
	// Find the closest tile in the hit zone for this lane
	for (var i = 0; i < tiles.length; i++) {
		var tile = tiles[i];
		if (tile.lane === lane && !tile.tapped) {
			var distance = Math.abs(tile.y - hitZoneY);
			if (distance < hitZoneHeight && distance < bestDistance) {
				hitTile = tile;
				bestDistance = distance;
			}
		}
	}
	if (hitTile) {
		hitTile.tapped = true;
		pianoKeys[lane].setPressed();
		// Play note
		LK.getSound(notes[lane]).play();
		// Calculate score based on timing
		var timingScore = Math.max(1, Math.floor((hitZoneHeight - bestDistance) / hitZoneHeight * 100));
		LK.setScore(LK.getScore() + timingScore + combo * 2);
		combo++;
		// Perfect hit effect
		if (bestDistance < 30) {
			LK.getSound('perfect').play();
			var effect = new PerfectEffect(hitTile.x, hitTile.y);
			perfectEffects.push(effect);
			game.addChild(effect);
			// Add screen shake for perfect hits to match upbeat energy
			var originalX = game.x;
			var originalY = game.y;
			tween(game, {
				x: originalX + 10,
				y: originalY + 5
			}, {
				duration: 50,
				onFinish: function onFinish() {
					tween(game, {
						x: originalX - 10,
						y: originalY - 5
					}, {
						duration: 50,
						onFinish: function onFinish() {
							tween(game, {
								x: originalX,
								y: originalY
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
				}
			});
		}
		// Increase speed gradually
		if (gameSpeed < maxSpeed) {
			gameSpeed += speedIncrement / 100;
		}
		updateScore();
		// Flash tile before removing
		tween(hitTile, {
			alpha: 0
		}, {
			duration: 200,
			onFinish: function onFinish() {
				hitTile.destroy();
				var index = tiles.indexOf(hitTile);
				if (index > -1) {
					tiles.splice(index, 1);
				}
			}
		});
	}
}
game.update = function () {
	if (!gameRunning) return;
	// Add background pulsing effect every beat to match upbeat music
	if (LK.ticks % 30 === 0) {
		var currentBg = game.backgroundColor;
		tween(game, {
			backgroundColor: 0x3a4f5f
		}, {
			duration: 150,
			onFinish: function onFinish() {
				tween(game, {
					backgroundColor: currentBg
				}, {
					duration: 150
				});
			}
		});
	}
	// Spawn tiles
	spawnCounter++;
	if (spawnCounter >= spawnRate) {
		spawnTile();
		spawnCounter = 0;
		// Gradually increase spawn rate
		if (spawnRate > 30) {
			spawnRate = Math.max(30, spawnRate - 0.2);
		}
	}
	// Update tiles and check for misses
	for (var i = tiles.length - 1; i >= 0; i--) {
		var tile = tiles[i];
		// Check if tile passed the hit zone without being tapped
		if (!tile.tapped && tile.lastY < hitZoneY + hitZoneHeight && tile.y >= hitZoneY + hitZoneHeight) {
			// Missed tile - game over
			LK.getSound('miss').play();
			LK.effects.flashScreen(0xff0000, 1000);
			gameRunning = false;
			LK.setTimeout(function () {
				LK.showGameOver();
			}, 1000);
			return;
		}
		// Remove tiles that are off screen
		if (tile.y > 2800) {
			tile.destroy();
			tiles.splice(i, 1);
			continue;
		}
		tile.lastY = tile.y;
	}
	// Song progression based on score
	if (LK.getScore() >= 1000 && currentSongIndex === 0) {
		currentSongIndex = 1;
		LK.playMusic(songs[currentSongIndex], {
			loop: true,
			fade: {
				start: 0,
				end: 0.7,
				duration: 1000
			}
		});
	} else if (LK.getScore() >= 3000 && currentSongIndex === 1) {
		currentSongIndex = 2;
		LK.playMusic(songs[currentSongIndex], {
			loop: true,
			fade: {
				start: 0,
				end: 0.7,
				duration: 1000
			}
		});
	}
	// Check for winning condition (high score achievement)
	if (LK.getScore() >= 5000) {
		gameRunning = false;
		LK.setTimeout(function () {
			LK.showYouWin();
		}, 500);
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var PerfectEffect = Container.expand(function (x, y) {
	var self = Container.call(this);
	var effectGraphics = self.attachAsset('perfectEffect', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.alpha = 1;
	self.scale.set(0.5, 0.5);
	tween(self, {
		alpha: 0,
		scaleX: 2,
		scaleY: 2
	}, {
		duration: 500,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			self.destroy();
			var index = perfectEffects.indexOf(self);
			if (index > -1) {
				perfectEffects.splice(index, 1);
			}
		}
	});
	return self;
});
var PianoKey = Container.expand(function (lane) {
	var self = Container.call(this);
	var keyGraphics = self.attachAsset('pianoKey', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.lane = lane;
	self.pressed = false;
	self.pressTimer = 0;
	self.update = function () {
		if (self.pressed) {
			self.pressTimer--;
			if (self.pressTimer <= 0) {
				self.setUnpressed();
			}
		}
	};
	self.setPressed = function () {
		if (!self.pressed) {
			self.pressed = true;
			self.pressTimer = 10;
			keyGraphics.removeChild(keyGraphics.children[0]);
			var pressedGraphics = keyGraphics.attachAsset('pianoKeyPressed', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			// Add bouncy press animation to match upbeat music
			tween(self, {
				scaleX: 1.2,
				scaleY: 1.2
			}, {
				duration: 100,
				easing: tween.bounceOut,
				onFinish: function onFinish() {
					tween(self, {
						scaleX: 1.0,
						scaleY: 1.0
					}, {
						duration: 200,
						easing: tween.elasticOut
					});
				}
			});
		}
	};
	self.setUnpressed = function () {
		if (self.pressed) {
			self.pressed = false;
			keyGraphics.removeChild(keyGraphics.children[0]);
			var normalGraphics = keyGraphics.attachAsset('pianoKey', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	self.down = function (x, y, obj) {
		handleKeyPress(self.lane);
	};
	return self;
});
var PianoTile = Container.expand(function (lane, noteIndex) {
	var self = Container.call(this);
	var tileGraphics = self.attachAsset('pianoTile', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.lane = lane;
	self.noteIndex = noteIndex;
	self.speed = gameSpeed;
	self.tapped = false;
	self.lastY = self.y;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
var gameSpeed = 8;
var speedIncrement = 0.5;
var maxSpeed = 20;
var combo = 0;
var gameRunning = true;
var spawnRate = 90;
var spawnCounter = 0;
var lanes = 4;
var laneWidth = 400;
var keyboardY = 2400;
var hitZoneY = 2300;
var hitZoneHeight = 200;
var tiles = [];
var pianoKeys = [];
var perfectEffects = [];
var notes = ['note1', 'note2', 'note3', 'note4'];
var songs = ['song1', 'song2', 'song3'];
var currentSongIndex = 0;
var songStarted = false;
// Create piano keyboard with pulsing animation
for (var i = 0; i < lanes; i++) {
	var key = new PianoKey(i);
	key.x = i * laneWidth + laneWidth / 2 + 224;
	key.y = keyboardY;
	pianoKeys.push(key);
	game.addChild(key);
	// Add subtle pulsing animation to match upbeat music
	tween(key, {
		scaleX: 1.05,
		scaleY: 1.05
	}, {
		duration: 600,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(key, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 600,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Create infinite loop by calling the pulse again
					if (gameRunning) {
						tween(key, {
							scaleX: 1.05,
							scaleY: 1.05
						}, {
							duration: 600,
							easing: tween.easeInOut,
							onFinish: arguments.callee.caller
						});
					}
				}
			});
		}
	});
}
// Create score display
var scoreText = new Text2('Score: 0', {
	size: 80,
	fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create combo display
var comboText = new Text2('', {
	size: 60,
	fill: 0xFFD700
});
comboText.anchor.set(0.5, 0);
comboText.y = 100;
LK.gui.top.addChild(comboText);
function updateScore() {
	scoreText.setText('Score: ' + LK.getScore());
	if (combo > 5) {
		comboText.setText('Combo: ' + combo);
	} else {
		comboText.setText('');
	}
}
function spawnTile() {
	if (!gameRunning) return;
	// Start music on first tile spawn
	if (!songStarted) {
		LK.playMusic('upbeat', {
			loop: true
		});
		songStarted = true;
	}
	var lane = Math.floor(Math.random() * lanes);
	var tile = new PianoTile(lane, notes[lane]);
	tile.x = lane * laneWidth + laneWidth / 2 + 224;
	tile.y = -50;
	tile.lastY = tile.y;
	// Add bouncy spawn animation to match upbeat music
	tile.scaleX = 0.3;
	tile.scaleY = 0.3;
	tween(tile, {
		scaleX: 1.0,
		scaleY: 1.0
	}, {
		duration: 300,
		easing: tween.bounceOut
	});
	tiles.push(tile);
	game.addChild(tile);
}
function handleKeyPress(lane) {
	if (!gameRunning) return;
	var hitTile = null;
	var bestDistance = Infinity;
	// Find the closest tile in the hit zone for this lane
	for (var i = 0; i < tiles.length; i++) {
		var tile = tiles[i];
		if (tile.lane === lane && !tile.tapped) {
			var distance = Math.abs(tile.y - hitZoneY);
			if (distance < hitZoneHeight && distance < bestDistance) {
				hitTile = tile;
				bestDistance = distance;
			}
		}
	}
	if (hitTile) {
		hitTile.tapped = true;
		pianoKeys[lane].setPressed();
		// Play note
		LK.getSound(notes[lane]).play();
		// Calculate score based on timing
		var timingScore = Math.max(1, Math.floor((hitZoneHeight - bestDistance) / hitZoneHeight * 100));
		LK.setScore(LK.getScore() + timingScore + combo * 2);
		combo++;
		// Perfect hit effect
		if (bestDistance < 30) {
			LK.getSound('perfect').play();
			var effect = new PerfectEffect(hitTile.x, hitTile.y);
			perfectEffects.push(effect);
			game.addChild(effect);
			// Add screen shake for perfect hits to match upbeat energy
			var originalX = game.x;
			var originalY = game.y;
			tween(game, {
				x: originalX + 10,
				y: originalY + 5
			}, {
				duration: 50,
				onFinish: function onFinish() {
					tween(game, {
						x: originalX - 10,
						y: originalY - 5
					}, {
						duration: 50,
						onFinish: function onFinish() {
							tween(game, {
								x: originalX,
								y: originalY
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
				}
			});
		}
		// Increase speed gradually
		if (gameSpeed < maxSpeed) {
			gameSpeed += speedIncrement / 100;
		}
		updateScore();
		// Flash tile before removing
		tween(hitTile, {
			alpha: 0
		}, {
			duration: 200,
			onFinish: function onFinish() {
				hitTile.destroy();
				var index = tiles.indexOf(hitTile);
				if (index > -1) {
					tiles.splice(index, 1);
				}
			}
		});
	}
}
game.update = function () {
	if (!gameRunning) return;
	// Add background pulsing effect every beat to match upbeat music
	if (LK.ticks % 30 === 0) {
		var currentBg = game.backgroundColor;
		tween(game, {
			backgroundColor: 0x3a4f5f
		}, {
			duration: 150,
			onFinish: function onFinish() {
				tween(game, {
					backgroundColor: currentBg
				}, {
					duration: 150
				});
			}
		});
	}
	// Spawn tiles
	spawnCounter++;
	if (spawnCounter >= spawnRate) {
		spawnTile();
		spawnCounter = 0;
		// Gradually increase spawn rate
		if (spawnRate > 30) {
			spawnRate = Math.max(30, spawnRate - 0.2);
		}
	}
	// Update tiles and check for misses
	for (var i = tiles.length - 1; i >= 0; i--) {
		var tile = tiles[i];
		// Check if tile passed the hit zone without being tapped
		if (!tile.tapped && tile.lastY < hitZoneY + hitZoneHeight && tile.y >= hitZoneY + hitZoneHeight) {
			// Missed tile - game over
			LK.getSound('miss').play();
			LK.effects.flashScreen(0xff0000, 1000);
			gameRunning = false;
			LK.setTimeout(function () {
				LK.showGameOver();
			}, 1000);
			return;
		}
		// Remove tiles that are off screen
		if (tile.y > 2800) {
			tile.destroy();
			tiles.splice(i, 1);
			continue;
		}
		tile.lastY = tile.y;
	}
	// Song progression based on score
	if (LK.getScore() >= 1000 && currentSongIndex === 0) {
		currentSongIndex = 1;
		LK.playMusic(songs[currentSongIndex], {
			loop: true,
			fade: {
				start: 0,
				end: 0.7,
				duration: 1000
			}
		});
	} else if (LK.getScore() >= 3000 && currentSongIndex === 1) {
		currentSongIndex = 2;
		LK.playMusic(songs[currentSongIndex], {
			loop: true,
			fade: {
				start: 0,
				end: 0.7,
				duration: 1000
			}
		});
	}
	// Check for winning condition (high score achievement)
	if (LK.getScore() >= 5000) {
		gameRunning = false;
		LK.setTimeout(function () {
			LK.showYouWin();
		}, 500);
	}
};