/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0,
	aiDifficulty: 0.7
});
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = ballGraphics.width / 2;
	self.velocity = {
		x: 0,
		y: 0
	};
	self.baseSpeed = 12;
	self.speedMultiplier = 1.0;
	self.maxSpeedMultiplier = 2.5;
	self.reset = function () {
		self.x = 2048 / 2;
		self.y = 2732 / 2;
		self.speedMultiplier = 1.0;
		// Random initial direction
		var angle = Math.random() * Math.PI / 2 - Math.PI / 4;
		if (Math.random() < 0.5) {
			angle += Math.PI;
		}
		self.velocity.x = Math.cos(angle) * self.baseSpeed;
		self.velocity.y = Math.sin(angle) * self.baseSpeed;
		// Make sure horizontal speed is significant
		if (Math.abs(self.velocity.x) < self.baseSpeed * 0.6) {
			self.velocity.x = (self.velocity.x > 0 ? 1 : -1) * self.baseSpeed * 0.6;
		}
	};
	self.update = function () {
		// Move ball based on velocity
		self.x += self.velocity.x * self.speedMultiplier;
		self.y += self.velocity.y * self.speedMultiplier;
		// Collision with top and bottom walls
		if (self.y < self.radius) {
			self.y = self.radius;
			self.velocity.y *= -1;
			LK.getSound('hit').play();
		} else if (self.y > 2732 - self.radius) {
			self.y = 2732 - self.radius;
			self.velocity.y *= -1;
			LK.getSound('hit').play();
		}
	};
	self.hitPaddle = function (paddle) {
		// Normalize collision point (-1 to 1) from paddle center
		var relativeY = (self.y - paddle.y) / (paddle.height / 2);
		// Adjust angle based on where the ball hit the paddle
		var angle = relativeY * Math.PI / 3; // max ±60 degrees
		// Reverse x direction and apply new angle
		self.velocity.x = -Math.sign(self.velocity.x) * Math.cos(angle) * self.baseSpeed;
		self.velocity.y = Math.sin(angle) * self.baseSpeed;
		// Increase speed with each hit, up to a maximum
		self.speedMultiplier = Math.min(self.maxSpeedMultiplier, self.speedMultiplier + 0.05);
		// Play hit sound
		LK.getSound('hit').play();
	};
	return self;
});
var Paddle = Container.expand(function () {
	var self = Container.call(this);
	var paddleGraphics = self.attachAsset('paddle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = paddleGraphics.width;
	self.height = paddleGraphics.height;
	self.speed = 0;
	self.target = 0;
	self.isAI = false;
	self.aiReactionSpeed = 0.7; // Default AI difficulty level (0.1-0.9)
	// AI paddle movement logic
	self.updateAI = function (ball, dt) {
		if (!self.isAI) {
			return;
		}
		// Only update target if ball is moving toward this paddle
		if (self.x < 1024 && ball.velocity.x < 0 || self.x > 1024 && ball.velocity.x > 0) {
			// Predict where the ball will be
			var distanceX = Math.abs(self.x - ball.x);
			var timeToReach = distanceX / Math.abs(ball.velocity.x);
			var futureY = ball.y + ball.velocity.y * timeToReach;
			// Keep the future position in bounds
			futureY = Math.max(self.height / 2, Math.min(2732 - self.height / 2, futureY));
			// Add some imperfection based on AI difficulty
			var errorFactor = (1 - self.aiReactionSpeed) * 300;
			futureY += Math.random() * errorFactor * 2 - errorFactor;
			// Gradually move toward the predicted position
			self.target = futureY;
		}
	};
	self.update = function (dt) {
		// Gradually move toward target position (whether controlled by player or AI)
		if (self.target !== null) {
			self.speed = (self.target - self.y) * 0.2;
			// Cap movement speed
			var maxSpeed = 40;
			self.speed = Math.max(-maxSpeed, Math.min(maxSpeed, self.speed));
			self.y += self.speed;
			// Keep paddle in bounds
			self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Game state
var gameStarted = false;
var gameMode = "single"; // "single" or "multi"
var scoreLeft = 0;
var scoreRight = 0;
var maxScore = 11;
var lastFrameTime = Date.now();
// Create paddles
var leftPaddle = game.addChild(new Paddle());
leftPaddle.x = 100;
leftPaddle.y = 2732 / 2;
var rightPaddle = game.addChild(new Paddle());
rightPaddle.x = 2048 - 100;
rightPaddle.y = 2732 / 2;
rightPaddle.isAI = true;
rightPaddle.aiReactionSpeed = storage.aiDifficulty;
// Create ball
var ball = game.addChild(new Ball());
ball.reset();
// Create center line
var centerLineContainer = game.addChild(new Container());
centerLineContainer.x = 2048 / 2;
for (var y = 15; y < 2732; y += 60) {
	var lineSegment = centerLineContainer.attachAsset('centerLine', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: y
	});
}
// Score text
var scoreLeftText = new Text2(scoreLeft.toString(), {
	size: 150,
	fill: 0xFFFFFF
});
scoreLeftText.anchor.set(1, 0);
scoreLeftText.x = 2048 / 2 - 50;
scoreLeftText.y = 50;
LK.gui.addChild(scoreLeftText);
var scoreRightText = new Text2(scoreRight.toString(), {
	size: 150,
	fill: 0xFFFFFF
});
scoreRightText.anchor.set(0, 0);
scoreRightText.x = 2048 / 2 + 50;
scoreRightText.y = 50;
LK.gui.addChild(scoreRightText);
// Game mode button
var singlePlayerButton = new Text2("1P", {
	size: 80,
	fill: gameMode === "single" ? "#ffffff" : "#888888"
});
singlePlayerButton.anchor.set(1, 0);
singlePlayerButton.x = 2048 / 2 - 20;
singlePlayerButton.y = 220;
LK.gui.addChild(singlePlayerButton);
var multiPlayerButton = new Text2("2P", {
	size: 80,
	fill: gameMode === "multi" ? "#ffffff" : "#888888"
});
multiPlayerButton.anchor.set(0, 0);
multiPlayerButton.x = 2048 / 2 + 20;
multiPlayerButton.y = 220;
LK.gui.addChild(multiPlayerButton);
// Start text
var startText = new Text2("TAP TO START", {
	size: 100,
	fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 2732 / 2;
LK.gui.addChild(startText);
// Store which paddle the user is currently controlling
var activePaddle = null;
// Update scores
function updateScore() {
	scoreLeftText.setText(scoreLeft.toString());
	scoreRightText.setText(scoreRight.toString());
}
// Check for win condition
function checkWinCondition() {
	if (scoreLeft >= maxScore) {
		if (gameMode === "single") {
			// Update high score if playing single player
			if (scoreLeft > storage.highScore) {
				storage.highScore = scoreLeft;
			}
		}
		LK.showYouWin();
	} else if (scoreRight >= maxScore) {
		if (gameMode === "multi") {
			LK.showYouWin(); // In multiplayer, right player winning is still a win
		} else {
			LK.showGameOver();
		}
	}
}
// Handle touch events
game.down = function (x, y, obj) {
	if (!gameStarted) {
		gameStarted = true;
		startText.visible = false;
		LK.playMusic('gameMusic');
		return;
	}
	// Check if game mode buttons were clicked
	if (!gameStarted && y < 300) {
		var centerX = 2048 / 2;
		if (x < centerX) {
			gameMode = "single";
			rightPaddle.isAI = true;
			singlePlayerButton.style.fill = "#ffffff";
			multiPlayerButton.style.fill = "#888888";
		} else {
			gameMode = "multi";
			rightPaddle.isAI = false;
			singlePlayerButton.style.fill = "#888888";
			multiPlayerButton.style.fill = "#ffffff";
		}
		return;
	}
	// Determine which paddle to control based on screen side
	if (gameMode === "multi") {
		if (x < 2048 / 2) {
			activePaddle = leftPaddle;
		} else {
			activePaddle = rightPaddle;
		}
	} else {
		// In single player, only control left paddle
		activePaddle = leftPaddle;
	}
	if (activePaddle) {
		activePaddle.target = y;
	}
};
game.move = function (x, y, obj) {
	if (activePaddle) {
		activePaddle.target = y;
	}
};
game.up = function (x, y, obj) {
	// Keep tracking the paddle's target position
	// This allows for smooth movement even after lifting finger
};
// Main game update loop
game.update = function () {
	// Calculate delta time for smoother animations
	var currentTime = Date.now();
	var dt = (currentTime - lastFrameTime) / 16.67; // Normalize to 60fps
	lastFrameTime = currentTime;
	// Don't update game logic if not started
	if (!gameStarted) {
		return;
	}
	// Update AI
	rightPaddle.updateAI(ball, dt);
	// Update paddles
	leftPaddle.update(dt);
	rightPaddle.update(dt);
	// Update ball
	ball.update();
	// Check for collisions with paddles
	if (ball.velocity.x < 0 && ball.x - ball.radius <= leftPaddle.x + leftPaddle.width / 2 && ball.x - ball.radius > leftPaddle.x - leftPaddle.width / 2 && ball.y >= leftPaddle.y - leftPaddle.height / 2 && ball.y <= leftPaddle.y + leftPaddle.height / 2) {
		// Position ball at paddle edge to prevent sticking
		ball.x = leftPaddle.x + leftPaddle.width / 2 + ball.radius;
		ball.hitPaddle(leftPaddle);
	} else if (ball.velocity.x > 0 && ball.x + ball.radius >= rightPaddle.x - rightPaddle.width / 2 && ball.x + ball.radius < rightPaddle.x + rightPaddle.width / 2 && ball.y >= rightPaddle.y - rightPaddle.height / 2 && ball.y <= rightPaddle.y + rightPaddle.height / 2) {
		// Position ball at paddle edge to prevent sticking
		ball.x = rightPaddle.x - rightPaddle.width / 2 - ball.radius;
		ball.hitPaddle(rightPaddle);
	}
	// Check for scoring
	if (ball.x < -ball.radius) {
		// Right scores
		scoreRight++;
		updateScore();
		LK.getSound('score').play();
		ball.reset();
		checkWinCondition();
	} else if (ball.x > 2048 + ball.radius) {
		// Left scores
		scoreLeft++;
		updateScore();
		LK.getSound('score').play();
		ball.reset();
		checkWinCondition();
	}
	// Flash effect for center line if ball crosses it
	if (ball.x < 1024 && ball.velocity.x > 0 && ball.x + ball.velocity.x >= 1024 || ball.x > 1024 && ball.velocity.x < 0 && ball.x + ball.velocity.x <= 1024) {
		tween(centerLineContainer, {
			alpha: 0.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(centerLineContainer, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0,
	aiDifficulty: 0.7
});
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = ballGraphics.width / 2;
	self.velocity = {
		x: 0,
		y: 0
	};
	self.baseSpeed = 12;
	self.speedMultiplier = 1.0;
	self.maxSpeedMultiplier = 2.5;
	self.reset = function () {
		self.x = 2048 / 2;
		self.y = 2732 / 2;
		self.speedMultiplier = 1.0;
		// Random initial direction
		var angle = Math.random() * Math.PI / 2 - Math.PI / 4;
		if (Math.random() < 0.5) {
			angle += Math.PI;
		}
		self.velocity.x = Math.cos(angle) * self.baseSpeed;
		self.velocity.y = Math.sin(angle) * self.baseSpeed;
		// Make sure horizontal speed is significant
		if (Math.abs(self.velocity.x) < self.baseSpeed * 0.6) {
			self.velocity.x = (self.velocity.x > 0 ? 1 : -1) * self.baseSpeed * 0.6;
		}
	};
	self.update = function () {
		// Move ball based on velocity
		self.x += self.velocity.x * self.speedMultiplier;
		self.y += self.velocity.y * self.speedMultiplier;
		// Collision with top and bottom walls
		if (self.y < self.radius) {
			self.y = self.radius;
			self.velocity.y *= -1;
			LK.getSound('hit').play();
		} else if (self.y > 2732 - self.radius) {
			self.y = 2732 - self.radius;
			self.velocity.y *= -1;
			LK.getSound('hit').play();
		}
	};
	self.hitPaddle = function (paddle) {
		// Normalize collision point (-1 to 1) from paddle center
		var relativeY = (self.y - paddle.y) / (paddle.height / 2);
		// Adjust angle based on where the ball hit the paddle
		var angle = relativeY * Math.PI / 3; // max ±60 degrees
		// Reverse x direction and apply new angle
		self.velocity.x = -Math.sign(self.velocity.x) * Math.cos(angle) * self.baseSpeed;
		self.velocity.y = Math.sin(angle) * self.baseSpeed;
		// Increase speed with each hit, up to a maximum
		self.speedMultiplier = Math.min(self.maxSpeedMultiplier, self.speedMultiplier + 0.05);
		// Play hit sound
		LK.getSound('hit').play();
	};
	return self;
});
var Paddle = Container.expand(function () {
	var self = Container.call(this);
	var paddleGraphics = self.attachAsset('paddle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = paddleGraphics.width;
	self.height = paddleGraphics.height;
	self.speed = 0;
	self.target = 0;
	self.isAI = false;
	self.aiReactionSpeed = 0.7; // Default AI difficulty level (0.1-0.9)
	// AI paddle movement logic
	self.updateAI = function (ball, dt) {
		if (!self.isAI) {
			return;
		}
		// Only update target if ball is moving toward this paddle
		if (self.x < 1024 && ball.velocity.x < 0 || self.x > 1024 && ball.velocity.x > 0) {
			// Predict where the ball will be
			var distanceX = Math.abs(self.x - ball.x);
			var timeToReach = distanceX / Math.abs(ball.velocity.x);
			var futureY = ball.y + ball.velocity.y * timeToReach;
			// Keep the future position in bounds
			futureY = Math.max(self.height / 2, Math.min(2732 - self.height / 2, futureY));
			// Add some imperfection based on AI difficulty
			var errorFactor = (1 - self.aiReactionSpeed) * 300;
			futureY += Math.random() * errorFactor * 2 - errorFactor;
			// Gradually move toward the predicted position
			self.target = futureY;
		}
	};
	self.update = function (dt) {
		// Gradually move toward target position (whether controlled by player or AI)
		if (self.target !== null) {
			self.speed = (self.target - self.y) * 0.2;
			// Cap movement speed
			var maxSpeed = 40;
			self.speed = Math.max(-maxSpeed, Math.min(maxSpeed, self.speed));
			self.y += self.speed;
			// Keep paddle in bounds
			self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Game state
var gameStarted = false;
var gameMode = "single"; // "single" or "multi"
var scoreLeft = 0;
var scoreRight = 0;
var maxScore = 11;
var lastFrameTime = Date.now();
// Create paddles
var leftPaddle = game.addChild(new Paddle());
leftPaddle.x = 100;
leftPaddle.y = 2732 / 2;
var rightPaddle = game.addChild(new Paddle());
rightPaddle.x = 2048 - 100;
rightPaddle.y = 2732 / 2;
rightPaddle.isAI = true;
rightPaddle.aiReactionSpeed = storage.aiDifficulty;
// Create ball
var ball = game.addChild(new Ball());
ball.reset();
// Create center line
var centerLineContainer = game.addChild(new Container());
centerLineContainer.x = 2048 / 2;
for (var y = 15; y < 2732; y += 60) {
	var lineSegment = centerLineContainer.attachAsset('centerLine', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: y
	});
}
// Score text
var scoreLeftText = new Text2(scoreLeft.toString(), {
	size: 150,
	fill: 0xFFFFFF
});
scoreLeftText.anchor.set(1, 0);
scoreLeftText.x = 2048 / 2 - 50;
scoreLeftText.y = 50;
LK.gui.addChild(scoreLeftText);
var scoreRightText = new Text2(scoreRight.toString(), {
	size: 150,
	fill: 0xFFFFFF
});
scoreRightText.anchor.set(0, 0);
scoreRightText.x = 2048 / 2 + 50;
scoreRightText.y = 50;
LK.gui.addChild(scoreRightText);
// Game mode button
var singlePlayerButton = new Text2("1P", {
	size: 80,
	fill: gameMode === "single" ? "#ffffff" : "#888888"
});
singlePlayerButton.anchor.set(1, 0);
singlePlayerButton.x = 2048 / 2 - 20;
singlePlayerButton.y = 220;
LK.gui.addChild(singlePlayerButton);
var multiPlayerButton = new Text2("2P", {
	size: 80,
	fill: gameMode === "multi" ? "#ffffff" : "#888888"
});
multiPlayerButton.anchor.set(0, 0);
multiPlayerButton.x = 2048 / 2 + 20;
multiPlayerButton.y = 220;
LK.gui.addChild(multiPlayerButton);
// Start text
var startText = new Text2("TAP TO START", {
	size: 100,
	fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startText.x = 2048 / 2;
startText.y = 2732 / 2;
LK.gui.addChild(startText);
// Store which paddle the user is currently controlling
var activePaddle = null;
// Update scores
function updateScore() {
	scoreLeftText.setText(scoreLeft.toString());
	scoreRightText.setText(scoreRight.toString());
}
// Check for win condition
function checkWinCondition() {
	if (scoreLeft >= maxScore) {
		if (gameMode === "single") {
			// Update high score if playing single player
			if (scoreLeft > storage.highScore) {
				storage.highScore = scoreLeft;
			}
		}
		LK.showYouWin();
	} else if (scoreRight >= maxScore) {
		if (gameMode === "multi") {
			LK.showYouWin(); // In multiplayer, right player winning is still a win
		} else {
			LK.showGameOver();
		}
	}
}
// Handle touch events
game.down = function (x, y, obj) {
	if (!gameStarted) {
		gameStarted = true;
		startText.visible = false;
		LK.playMusic('gameMusic');
		return;
	}
	// Check if game mode buttons were clicked
	if (!gameStarted && y < 300) {
		var centerX = 2048 / 2;
		if (x < centerX) {
			gameMode = "single";
			rightPaddle.isAI = true;
			singlePlayerButton.style.fill = "#ffffff";
			multiPlayerButton.style.fill = "#888888";
		} else {
			gameMode = "multi";
			rightPaddle.isAI = false;
			singlePlayerButton.style.fill = "#888888";
			multiPlayerButton.style.fill = "#ffffff";
		}
		return;
	}
	// Determine which paddle to control based on screen side
	if (gameMode === "multi") {
		if (x < 2048 / 2) {
			activePaddle = leftPaddle;
		} else {
			activePaddle = rightPaddle;
		}
	} else {
		// In single player, only control left paddle
		activePaddle = leftPaddle;
	}
	if (activePaddle) {
		activePaddle.target = y;
	}
};
game.move = function (x, y, obj) {
	if (activePaddle) {
		activePaddle.target = y;
	}
};
game.up = function (x, y, obj) {
	// Keep tracking the paddle's target position
	// This allows for smooth movement even after lifting finger
};
// Main game update loop
game.update = function () {
	// Calculate delta time for smoother animations
	var currentTime = Date.now();
	var dt = (currentTime - lastFrameTime) / 16.67; // Normalize to 60fps
	lastFrameTime = currentTime;
	// Don't update game logic if not started
	if (!gameStarted) {
		return;
	}
	// Update AI
	rightPaddle.updateAI(ball, dt);
	// Update paddles
	leftPaddle.update(dt);
	rightPaddle.update(dt);
	// Update ball
	ball.update();
	// Check for collisions with paddles
	if (ball.velocity.x < 0 && ball.x - ball.radius <= leftPaddle.x + leftPaddle.width / 2 && ball.x - ball.radius > leftPaddle.x - leftPaddle.width / 2 && ball.y >= leftPaddle.y - leftPaddle.height / 2 && ball.y <= leftPaddle.y + leftPaddle.height / 2) {
		// Position ball at paddle edge to prevent sticking
		ball.x = leftPaddle.x + leftPaddle.width / 2 + ball.radius;
		ball.hitPaddle(leftPaddle);
	} else if (ball.velocity.x > 0 && ball.x + ball.radius >= rightPaddle.x - rightPaddle.width / 2 && ball.x + ball.radius < rightPaddle.x + rightPaddle.width / 2 && ball.y >= rightPaddle.y - rightPaddle.height / 2 && ball.y <= rightPaddle.y + rightPaddle.height / 2) {
		// Position ball at paddle edge to prevent sticking
		ball.x = rightPaddle.x - rightPaddle.width / 2 - ball.radius;
		ball.hitPaddle(rightPaddle);
	}
	// Check for scoring
	if (ball.x < -ball.radius) {
		// Right scores
		scoreRight++;
		updateScore();
		LK.getSound('score').play();
		ball.reset();
		checkWinCondition();
	} else if (ball.x > 2048 + ball.radius) {
		// Left scores
		scoreLeft++;
		updateScore();
		LK.getSound('score').play();
		ball.reset();
		checkWinCondition();
	}
	// Flash effect for center line if ball crosses it
	if (ball.x < 1024 && ball.velocity.x > 0 && ball.x + ball.velocity.x >= 1024 || ball.x > 1024 && ball.velocity.x < 0 && ball.x + ball.velocity.x <= 1024) {
		tween(centerLineContainer, {
			alpha: 0.3
		}, {
			duration: 100,
			onFinish: function onFinish() {
				tween(centerLineContainer, {
					alpha: 1
				}, {
					duration: 100
				});
			}
		});
	}
};