/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('ballShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = graphics.width;
	self.height = graphics.height;
	self.vx = 0;
	self.vy = 0;
	self.initialSpeed = 15; // Adjusted initial speed
	self.currentSpeedFactor = 1.0;
	self.maxSpeedFactor = 2.8;
	self.serve = function (directionY) {
		self.currentSpeedFactor = 1.0;
		var angle = Math.random() * Math.PI / 2.5 - Math.PI / 5;
		var speed = self.initialSpeed * self.currentSpeedFactor;
		self.vx = speed * Math.sin(angle);
		self.vy = speed * Math.cos(angle) * directionY;
	};
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		if (self.x <= self.width / 2 || self.x >= gameWidth - self.width / 2) {
			self.vx *= -1.01;
			self.x = Math.max(self.width / 2, Math.min(self.x, gameWidth - self.width / 2));
			LK.getSound('wallBounceSound').play({
				volume: 0.7
			});
		}
	};
	self.bounce = function (paddle) {
		self.vy *= -1;
		var hitPos = (self.x - paddle.x) / (paddle.getWidth() / 2);
		self.vx = self.vx * 0.5 + hitPos * self.initialSpeed * 1.2;
		self.currentSpeedFactor = Math.min(self.maxSpeedFactor, self.currentSpeedFactor * 1.04);
		var baseSpeed = self.initialSpeed * self.currentSpeedFactor;
		var maxHorizontalRatio = 1.4;
		self.vx = Math.max(-baseSpeed * maxHorizontalRatio, Math.min(self.vx, baseSpeed * maxHorizontalRatio));
		var currentMagnitude = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
		if (currentMagnitude > 0) {
			var speedRatio = baseSpeed / currentMagnitude;
			self.vx *= speedRatio;
			self.vy *= speedRatio;
		} else {
			var angle = Math.random() * Math.PI / 2.5 - Math.PI / 5;
			self.vx = baseSpeed * Math.sin(angle);
			self.vy = baseSpeed * Math.cos(angle) * (self.vy > 0 ? -1 : 1);
		}
		self.y += self.vy > 0 ? 5 : -5;
		if (paddle === playerPaddle) {
			LK.getSound('hitSoundPlayer').play();
		} else {
			LK.getSound('hitSoundAI').play();
		}
	};
	return self;
});
var GameIcon = Container.expand(function () {
	var self = Container.call(this);
	// Main circle background
	var bg = self.attachAsset('gameIcon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bg.tint = 0x0000FF; // Blue background for Samuil theme
	// Create paddles for icon
	var paddle1 = LK.getAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.8,
		scaleY: 0.8
	});
	paddle1.y = -100;
	self.addChild(paddle1);
	var paddle2 = LK.getAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.8,
		scaleY: 0.8
	});
	paddle2.y = 100;
	self.addChild(paddle2);
	// Ball in the center
	var ball = LK.getAsset('ballShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5
	});
	self.addChild(ball);
	// Text for "SAMUIL"
	var iconText = new Text2("SAMUIL", {
		size: 50,
		fill: 0xFFFFFF,
		align: 'center',
		stroke: 0x000000,
		strokeThickness: 3,
		fontWeight: 'bold'
	});
	iconText.anchor.set(0.5, 0.5);
	iconText.y = -170;
	self.addChild(iconText);
	return self;
});
var Paddle = Container.expand(function (isAI) {
	var self = Container.call(this);
	var graphics = self.attachAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var PADDLE_WIDTH = graphics.width;
	var PADDLE_HEIGHT = graphics.height;
	var PADDLE_COLOR = graphics.color; // Initial color from asset
	self.isAI = isAI;
	self.originalWidth = PADDLE_WIDTH;
	self.originalHeight = PADDLE_HEIGHT;
	self.originalColor = PADDLE_COLOR; // Store the initial white color
	self.width = PADDLE_WIDTH;
	self.height = PADDLE_HEIGHT;
	self.hasShield = false;
	self.shieldTimer = null;
	self.sizeChangeTimer = null;
	self.shieldVisual = null;
	self.isRed = false; // Track red debuff state
	self.reset = function (keepShield) {
		tween.stop(graphics, {
			width: true,
			tint: true
		});
		tween(graphics, {
			width: self.originalWidth
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		self.width = self.originalWidth;
		self.isRed = false; // Reset red state FIRST 
		// Determine target tint
		var targetTint = self.originalColor; // Default to original white
		if (keepShield && self.hasShield) {
			targetTint = 0x88CCFF; // Light Blue for shield
		}
		// Set tint DIRECTLY - NO TWEEN
		graphics.tint = targetTint;
		// Handle shield removal if necessary (this might change tint back to white if !isRed)
		if (!keepShield) {
			self.removeShield();
		}
		// Clear related timer
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null;
		}
		// Update shield visual visibility based on the CURRENT state of hasShield
		if (self.shieldVisual) {
			self.shieldVisual.visible = self.hasShield;
		}
	};
	self.removeShield = function () {
		self.hasShield = false;
		if (self.shieldTimer) {
			LK.clearTimeout(self.shieldTimer);
			self.shieldTimer = null;
		}
		// Manage shield visual
		if (self.shieldVisual) {
			// Only modify visual if it exists
			if (self.shieldVisual.parent) {
				// Check if attached before removing
				self.removeChild(self.shieldVisual);
				// Keep self.shieldVisual reference but ensure it's hidden if re-added later?
				// For now, let's assume removeChild is sufficient. Nulling might be better if bugs persist.
				// self.shieldVisual = null; // Let's not nullify, just remove from display list
			}
			// Ensure it's marked invisible even if not attached (belt-and-suspenders)
			self.shieldVisual.visible = false;
		} //{Z} // Line ID approx
		// Reset tint ONLY if NOT currently under the red debuff
		if (!self.isRed) {
			graphics.tint = self.originalColor;
		}
	};
	self.updateAI = function (ballX, ballY, ballVY) {
		// AI reacts *only* when ball is moving towards it (negative vy)
		if (self.isAI && ballVY < 0) {
			var targetX = ballX;
			var aiSpeed = 18; // Increased AI speed significantly
			var deadZone = self.width * 0.03; // Very small dead zone
			// More direct following by reducing interpolation factor or directly setting position
			// Option 1: Less interpolation (smoother than direct set)
			var moveAmount = (targetX - self.x) * 0.35; // Faster reaction interpolation factor
			self.x += Math.max(-aiSpeed, Math.min(aiSpeed, moveAmount));
			// Option 2: Near-direct set (can look jittery)
			// var diff = targetX - self.x;
			// self.x += Math.max(-aiSpeed, Math.min(aiSpeed, diff));
		}
		self.clampPosition();
	};
	self.clampPosition = function () {
		var halfWidth = self.width / 2;
		self.x = Math.max(halfWidth, Math.min(self.x, gameWidth - halfWidth));
	};
	self.applySizeChange = function (factor, duration, color) {
		// Clear any *pending* reset from a previous size change
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null; // Clear timer reference
		}
		// Stop ongoing width/tint tweens that might interfere
		tween.stop(graphics, {
			width: true,
			tint: true
		}); //{1c} approx
		// Apply new width via tween
		var targetWidth = self.originalWidth * factor;
		tween(graphics, {
			width: targetWidth
		}, {
			duration: 300,
			easing: tween.easeOut
		}); //{1h} approx
		self.width = targetWidth; // Update logical width immediately
		// Handle color / red debuff state and associated visuals
		if (color === 0xFF0000) {
			// RED Debuff
			graphics.tint = 0xFF0000;
			self.isRed = true;
			if (self.shieldVisual) {
				self.shieldVisual.visible = false; // Hide shield during red debuff
			}
		} else {
			// Blue Buff or Neutral (size change only) 
			// Only change tint if NOT currently RED
			if (!self.isRed) {
				// Set tint based on whether shield is active
				graphics.tint = self.hasShield ? 0x88CCFF : self.originalColor;
				if (self.shieldVisual) {
					// Ensure shield visibility matches shield state
					self.shieldVisual.visible = self.hasShield;
				}
			} else {//{1p} approx
				// If currently RED, tint remains RED, shield remains hidden. Do nothing here.
			}
		}
		// Update shield visual size to match new paddle size IF shield is active and visual exists
		if (self.hasShield && self.shieldVisual) {
			self.shieldVisual.width = self.width + 10;
			self.shieldVisual.height = self.height + 10;
			// Visibility is handled above based on isRed state
		}
		// Set timer to reset the size/color effects
		self.sizeChangeTimer = LK.setTimeout(function () {
			var wasShielded = self.hasShield; // Check shield status *before* reset potentially changes it
			// Call reset, passing whether a shield was active.
			// reset() handles setting isRed=false, width tween, tint, and shield visibility based on wasShielded.
			self.reset(wasShielded);
			// Simplified logic: Trust reset() to restore the correct visual state.
			// The original shield timer (if it existed and hasn't fired) will handle shield expiration.
			// No need for complex shield duration restoration here, which was potentially buggy.
			self.sizeChangeTimer = null;
		}, duration);
	};
	self.applyShield = function (duration) {
		// Clear any existing shield first to prevent timer duplication/conflicts
		// Note: removeShield() already handles timer clearing and tint reset (if not red)
		self.removeShield(); //{1x} // Line ID approx
		self.hasShield = true;
		if (!self.shieldVisual) {
			// Create shield visual if it doesn't exist
			self.shieldVisual = LK.getAsset('shieldShape', {
				anchorX: 0.5,
				anchorY: 0.5
			}); //{1z} approx
			self.addChild(self.shieldVisual); //{1A} approx
		}
		// Ensure visual matches current paddle size (might be affected by powerups)
		self.shieldVisual.width = self.width + 10; // Use current self.width
		self.shieldVisual.height = self.height + 10; // Use current self.height
		self.shieldVisual.visible = true;
		// Apply blue tint ONLY if NOT currently under the red debuff
		if (!self.isRed) {
			graphics.tint = 0x88CCFF; // Set to light blue
		}
		// Set timer to remove the shield effect
		self.shieldTimer = LK.setTimeout(function () {
			// Double-check if shield is still active before removing,
			// it might have been removed by other means (e.g., red powerup reset)
			if (self.hasShield) {
				self.removeShield();
			}
		}, duration);
	};
	self.clearAllTimers = function () {
		self.removeShield();
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null;
		}
		self.isRed = false;
	};
	self.getWidth = function () {
		return self.width;
	};
	self.getHeight = function () {
		return self.height;
	};
	return self;
});
var PowerUp = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type;
	var assetName = type === 'blue' ? 'powerUpBlueShape' : 'powerUpRedShape';
	var graphics = self.attachAsset(assetName, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = graphics.width;
	self.height = graphics.height;
	// Set tint before starting the tween
	graphics.tint = type === 'blue' ? 0x4488FF : 0xFF4444;
	tween(graphics, {
		scaleX: 1.1,
		scaleY: 1.1,
		tint: type === 'blue' ? 0x4488FF : 0xFF4444
	}, {
		duration: 700,
		easing: tween.easeInOut,
		repeat: -1,
		yoyo: true
	});
	self.update = function () {};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x050510
});
/**** 
* Game Code
****/ 
// Sound Assets (Replace IDs)
// Cyan shield
var gameWidth = 2048;
var gameHeight = 2732;
var playerPaddle;
var aiPaddle;
var ball;
var powerUps = [];
var lastPaddleHitter = null;
var gameState = 'intro';
var powerUpSpawnTimer = null;
var introTimeout1 = null;
var introTimeout2 = null;
var playerScore = 0;
var aiScore = 0;
var winScore = 7;
var gameIcon = null;
var background = LK.getAsset('backgroundRect', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
game.addChild(background);
var centerLineXStart = 50;
var centerLineXEnd = gameWidth - 50;
var segmentWidth = 40;
var gapWidth = 25; // Slightly larger gap
var currentX = centerLineXStart;
while (currentX < centerLineXEnd) {
	var segment = LK.getAsset('centerLineSegment', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	segment.width = segmentWidth;
	segment.x = currentX + segmentWidth / 2;
	segment.y = gameHeight / 2;
	game.addChild(segment);
	currentX += segmentWidth + gapWidth;
}
var scoreTextPlayer = new Text2("0", {
	size: 100,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 4
});
scoreTextPlayer.anchor.set(0.5, 1);
scoreTextPlayer.x = gameWidth / 2;
scoreTextPlayer.y = gameHeight - 30;
game.addChild(scoreTextPlayer);
var scoreTextAI = new Text2("0", {
	size: 100,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 4
});
scoreTextAI.anchor.set(0.5, 0);
scoreTextAI.x = gameWidth / 2;
scoreTextAI.y = 30;
game.addChild(scoreTextAI);
var introText1 = new Text2('Samuil Paddle', {
	size: 200,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 8,
	fontWeight: 'bold'
});
introText1.anchor.set(0.5, 0.5);
introText1.x = gameWidth / 2;
introText1.y = gameHeight / 2 - 100;
introText1.visible = false;
game.addChild(introText1);
var introText2 = new Text2('Samuil', {
	size: 180,
	fill: 0x0000FF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 7,
	fontWeight: 'bold'
});
introText2.anchor.set(0.5, 0.5);
introText2.x = gameWidth / 2;
introText2.y = gameHeight / 2 + 100;
introText2.visible = false;
game.addChild(introText2);
var gameOverText = new Text2('', {
	size: 150,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 6
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.x = gameWidth / 2;
gameOverText.y = gameHeight / 2 - 100;
gameOverText.visible = false;
game.addChild(gameOverText);
var restartText = new Text2('Click to Restart', {
	size: 90,
	fill: 0xDDDDDD,
	align: 'center'
});
restartText.anchor.set(0.5, 0.5);
restartText.x = gameWidth / 2;
restartText.y = gameHeight / 2 + 100;
restartText.visible = false;
restartText.interactive = true;
restartText.down = function () {
	if (gameState === 'gameOver') {
		startIntroSequence();
		LK.getSound('restartSound').play();
	}
};
game.addChild(restartText);
function resetGame() {
	if (gameIcon && gameIcon.parent) {
		game.removeChild(gameIcon);
		gameIcon = null;
	}
	if (playerPaddle && playerPaddle.parent) {
		game.removeChild(playerPaddle);
	}
	if (aiPaddle && aiPaddle.parent) {
		game.removeChild(aiPaddle);
	}
	if (ball && ball.parent) {
		game.removeChild(ball);
	}
	powerUps.forEach(function (p) {
		if (p && p.parent) {
			game.removeChild(p);
		}
	});
	powerUps = [];
	if (powerUpSpawnTimer) {
		LK.clearInterval(powerUpSpawnTimer);
	}
	if (introTimeout1) {
		LK.clearTimeout(introTimeout1);
	}
	if (introTimeout2) {
		LK.clearTimeout(introTimeout2);
	}
	playerScore = 0;
	aiScore = 0;
	scoreTextPlayer.setText("0");
	scoreTextAI.setText("0");
	introText1.visible = false;
	introText2.visible = false;
	gameOverText.visible = false;
	restartText.visible = false;
	lastPaddleHitter = null;
	playerPaddle = null;
	aiPaddle = null;
	ball = null;
}
function startGame() {
	resetGame();
	gameState = 'playing';
	playerPaddle = new Paddle(false);
	playerPaddle.x = gameWidth / 2;
	playerPaddle.y = gameHeight - 70;
	game.addChild(playerPaddle);
	aiPaddle = new Paddle(true);
	aiPaddle.x = gameWidth / 2;
	aiPaddle.y = 70;
	game.addChild(aiPaddle);
	ball = new Ball();
	game.addChild(ball);
	resetBall(Math.random() < 0.5 ? -1 : 1);
	LK.setTimeout(spawnPowerUp, 4000 + Math.random() * 4000);
	powerUpSpawnTimer = LK.setInterval(spawnPowerUp, 10000 + Math.random() * 6000);
	scoreTextPlayer.visible = true;
	scoreTextAI.visible = true;
	LK.playMusic('gameMusic');
}
function resetBall(directionY) {
	if (ball) {
		ball.x = gameWidth / 2;
		ball.y = gameHeight / 2;
		ball.serve(directionY);
	}
}
function spawnPowerUp() {
	if (gameState !== 'playing' || powerUps.length > 0) {
		return;
	}
	var type = Math.random() < 0.6 ? 'blue' : 'red';
	var powerUp = new PowerUp(type);
	powerUp.x = gameWidth * (0.2 + Math.random() * 0.6); // Spawn in middle 60% horizontally
	powerUp.y = gameHeight * (0.3 + Math.random() * 0.4); // Spawn in middle 40% vertically
	game.addChild(powerUp);
	powerUps.push(powerUp);
	LK.getSound('powerupSpawnSound').play({
		volume: 0.8
	});
}
game.move = function (x, y, obj) {
	if (gameState === 'playing' && playerPaddle) {
		var gamePos = game.toLocal({
			x: x,
			y: y
		});
		playerPaddle.x = gamePos.x;
		playerPaddle.clampPosition();
	}
};
game.down = function (x, y, obj) {
	if (gameState === 'gameOver' && restartText.visible) {
		startIntroSequence();
		LK.getSound('restartSound').play();
	}
};
game.update = function () {
	if (gameState !== 'playing') {
		return;
	}
	if (!ball || !playerPaddle || !aiPaddle) {
		console.error("Game elements missing!");
		endGame(false);
		return;
	}
	ball.update();
	aiPaddle.updateAI(ball.x, ball.y, ball.vy);
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var p = powerUps[i];
		if (!p || p.destroyed || !p.parent) {
			powerUps.splice(i, 1);
			continue;
		}
		p.update();
		if (ball.intersects(p)) {
			var targetPaddle = lastPaddleHitter;
			if (targetPaddle) {
				if (p.type === 'blue') {
					LK.getSound('powerupGoodSound').play();
					if (Math.random() < 0.5) {
						targetPaddle.applyShield(5000);
					} else {
						targetPaddle.applySizeChange(1.5, 5000, null);
					}
				} else {
					LK.getSound('powerupBadSound').play();
					targetPaddle.applySizeChange(0.6, 3000, 0xFF0000); // Shrink + RED
				}
			}
			if (p.parent) {
				game.removeChild(p);
			}
			p.destroy();
			powerUps.splice(i, 1);
		}
	}
	var ballHitPaddle = false;
	if (ball.intersects(playerPaddle)) {
		if (playerPaddle.hasShield) {
			LK.getSound('shieldBlockSound').play();
			playerPaddle.removeShield();
			ball.vy = -Math.abs(ball.vy) * 1.1 - 5;
			ball.vx += (Math.random() - 0.5) * 6;
			ball.y = playerPaddle.y - playerPaddle.getHeight() / 2 - ball.height / 2 - 3;
			lastPaddleHitter = null;
		} else {
			ball.bounce(playerPaddle);
			lastPaddleHitter = playerPaddle;
			ballHitPaddle = true;
		}
	} else if (ball.intersects(aiPaddle)) {
		if (aiPaddle.hasShield) {
			LK.getSound('shieldBlockSound').play();
			aiPaddle.removeShield();
			ball.vy = Math.abs(ball.vy) * 1.1 + 5;
			ball.vx += (Math.random() - 0.5) * 6;
			ball.y = aiPaddle.y + aiPaddle.getHeight() / 2 + ball.height / 2 + 3;
			lastPaddleHitter = null;
		} else {
			ball.bounce(aiPaddle);
			lastPaddleHitter = aiPaddle;
			ballHitPaddle = true;
		}
	}
	if (ballHitPaddle) {
		var nudgeAttempts = 0;
		while (ball.intersects(playerPaddle) && playerPaddle && nudgeAttempts < 10) {
			ball.y += ball.vy > 0 ? 1 : -1;
			nudgeAttempts++;
		}
		nudgeAttempts = 0;
		while (ball.intersects(aiPaddle) && aiPaddle && nudgeAttempts < 10) {
			ball.y += ball.vy > 0 ? 1 : -1;
			nudgeAttempts++;
		}
	}
	if (ball.y < -ball.height) {
		playerScore++;
		scoreTextPlayer.setText(playerScore);
		LK.getSound('scoreSoundPlayer').play();
		lastPaddleHitter = null;
		if (playerScore >= winScore) {
			endGame(true);
		} else {
			resetBall(1);
		}
	} else if (ball.y > gameHeight + ball.height) {
		aiScore++;
		scoreTextAI.setText(aiScore);
		LK.getSound('scoreSoundAI').play();
		lastPaddleHitter = null;
		if (aiScore >= winScore) {
			endGame(false);
		} else {
			resetBall(-1);
		}
	}
};
function endGame(playerWon) {
	gameState = 'gameOver';
	LK.stopMusic('gameMusic');
	if (powerUpSpawnTimer) {
		LK.clearInterval(powerUpSpawnTimer);
	}
	powerUps.forEach(function (p) {
		if (p && p.parent) {
			game.removeChild(p);
		}
		p.destroy();
	});
	powerUps = [];
	if (playerPaddle) {
		playerPaddle.clearAllTimers();
	}
	if (aiPaddle) {
		aiPaddle.clearAllTimers();
	}
	gameOverText.setText(playerWon ? "YOU WIN!" : "COMPUTER WINS!");
	gameOverText.visible = true;
	restartText.visible = true;
	if (ball && ball.parent) {
		game.removeChild(ball);
	}
	if (playerPaddle && playerPaddle.parent) {
		game.removeChild(playerPaddle);
	}
	if (aiPaddle && aiPaddle.parent) {
		game.removeChild(aiPaddle);
	}
	scoreTextPlayer.visible = false;
	scoreTextAI.visible = false;
	if (playerWon) {
		LK.getSound('gameOverSoundWin').play();
	} else {
		LK.getSound('gameOverSoundLose').play();
	}
}
function startIntroSequence() {
	resetGame();
	gameState = 'intro';
	scoreTextPlayer.visible = false;
	scoreTextAI.visible = false;
	// Create and add game icon
	if (!gameIcon) {
		gameIcon = new GameIcon();
		gameIcon.x = gameWidth / 2;
		gameIcon.y = gameHeight / 2 - 400;
		gameIcon.scale.set(0.8);
		game.addChild(gameIcon);
	}
	introText1.alpha = 0;
	introText1.visible = true;
	tween(introText1, {
		alpha: 1
	}, {
		duration: 500
	});
	LK.getSound('introSound1').play();
	introTimeout1 = LK.setTimeout(function () {
		tween(introText1, {
			alpha: 0
		}, {
			duration: 300,
			onFinish: function onFinish() {
				introText1.visible = false;
			}
		});
		introText2.alpha = 0;
		introText2.visible = true;
		tween(introText2, {
			alpha: 1
		}, {
			duration: 500
		});
		LK.getSound('introSound2').play();
		introTimeout2 = LK.setTimeout(function () {
			tween(introText2, {
				alpha: 0
			}, {
				duration: 300,
				onFinish: function onFinish() {
					introText2.visible = false;
					startGame();
				}
			});
		}, 2000);
	}, 3000);
}
startIntroSequence(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('ballShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = graphics.width;
	self.height = graphics.height;
	self.vx = 0;
	self.vy = 0;
	self.initialSpeed = 15; // Adjusted initial speed
	self.currentSpeedFactor = 1.0;
	self.maxSpeedFactor = 2.8;
	self.serve = function (directionY) {
		self.currentSpeedFactor = 1.0;
		var angle = Math.random() * Math.PI / 2.5 - Math.PI / 5;
		var speed = self.initialSpeed * self.currentSpeedFactor;
		self.vx = speed * Math.sin(angle);
		self.vy = speed * Math.cos(angle) * directionY;
	};
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
		if (self.x <= self.width / 2 || self.x >= gameWidth - self.width / 2) {
			self.vx *= -1.01;
			self.x = Math.max(self.width / 2, Math.min(self.x, gameWidth - self.width / 2));
			LK.getSound('wallBounceSound').play({
				volume: 0.7
			});
		}
	};
	self.bounce = function (paddle) {
		self.vy *= -1;
		var hitPos = (self.x - paddle.x) / (paddle.getWidth() / 2);
		self.vx = self.vx * 0.5 + hitPos * self.initialSpeed * 1.2;
		self.currentSpeedFactor = Math.min(self.maxSpeedFactor, self.currentSpeedFactor * 1.04);
		var baseSpeed = self.initialSpeed * self.currentSpeedFactor;
		var maxHorizontalRatio = 1.4;
		self.vx = Math.max(-baseSpeed * maxHorizontalRatio, Math.min(self.vx, baseSpeed * maxHorizontalRatio));
		var currentMagnitude = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
		if (currentMagnitude > 0) {
			var speedRatio = baseSpeed / currentMagnitude;
			self.vx *= speedRatio;
			self.vy *= speedRatio;
		} else {
			var angle = Math.random() * Math.PI / 2.5 - Math.PI / 5;
			self.vx = baseSpeed * Math.sin(angle);
			self.vy = baseSpeed * Math.cos(angle) * (self.vy > 0 ? -1 : 1);
		}
		self.y += self.vy > 0 ? 5 : -5;
		if (paddle === playerPaddle) {
			LK.getSound('hitSoundPlayer').play();
		} else {
			LK.getSound('hitSoundAI').play();
		}
	};
	return self;
});
var GameIcon = Container.expand(function () {
	var self = Container.call(this);
	// Main circle background
	var bg = self.attachAsset('gameIcon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	bg.tint = 0x0000FF; // Blue background for Samuil theme
	// Create paddles for icon
	var paddle1 = LK.getAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.8,
		scaleY: 0.8
	});
	paddle1.y = -100;
	self.addChild(paddle1);
	var paddle2 = LK.getAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.8,
		scaleY: 0.8
	});
	paddle2.y = 100;
	self.addChild(paddle2);
	// Ball in the center
	var ball = LK.getAsset('ballShape', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5
	});
	self.addChild(ball);
	// Text for "SAMUIL"
	var iconText = new Text2("SAMUIL", {
		size: 50,
		fill: 0xFFFFFF,
		align: 'center',
		stroke: 0x000000,
		strokeThickness: 3,
		fontWeight: 'bold'
	});
	iconText.anchor.set(0.5, 0.5);
	iconText.y = -170;
	self.addChild(iconText);
	return self;
});
var Paddle = Container.expand(function (isAI) {
	var self = Container.call(this);
	var graphics = self.attachAsset('paddleShape', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var PADDLE_WIDTH = graphics.width;
	var PADDLE_HEIGHT = graphics.height;
	var PADDLE_COLOR = graphics.color; // Initial color from asset
	self.isAI = isAI;
	self.originalWidth = PADDLE_WIDTH;
	self.originalHeight = PADDLE_HEIGHT;
	self.originalColor = PADDLE_COLOR; // Store the initial white color
	self.width = PADDLE_WIDTH;
	self.height = PADDLE_HEIGHT;
	self.hasShield = false;
	self.shieldTimer = null;
	self.sizeChangeTimer = null;
	self.shieldVisual = null;
	self.isRed = false; // Track red debuff state
	self.reset = function (keepShield) {
		tween.stop(graphics, {
			width: true,
			tint: true
		});
		tween(graphics, {
			width: self.originalWidth
		}, {
			duration: 200,
			easing: tween.easeOut
		});
		self.width = self.originalWidth;
		self.isRed = false; // Reset red state FIRST 
		// Determine target tint
		var targetTint = self.originalColor; // Default to original white
		if (keepShield && self.hasShield) {
			targetTint = 0x88CCFF; // Light Blue for shield
		}
		// Set tint DIRECTLY - NO TWEEN
		graphics.tint = targetTint;
		// Handle shield removal if necessary (this might change tint back to white if !isRed)
		if (!keepShield) {
			self.removeShield();
		}
		// Clear related timer
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null;
		}
		// Update shield visual visibility based on the CURRENT state of hasShield
		if (self.shieldVisual) {
			self.shieldVisual.visible = self.hasShield;
		}
	};
	self.removeShield = function () {
		self.hasShield = false;
		if (self.shieldTimer) {
			LK.clearTimeout(self.shieldTimer);
			self.shieldTimer = null;
		}
		// Manage shield visual
		if (self.shieldVisual) {
			// Only modify visual if it exists
			if (self.shieldVisual.parent) {
				// Check if attached before removing
				self.removeChild(self.shieldVisual);
				// Keep self.shieldVisual reference but ensure it's hidden if re-added later?
				// For now, let's assume removeChild is sufficient. Nulling might be better if bugs persist.
				// self.shieldVisual = null; // Let's not nullify, just remove from display list
			}
			// Ensure it's marked invisible even if not attached (belt-and-suspenders)
			self.shieldVisual.visible = false;
		} //{Z} // Line ID approx
		// Reset tint ONLY if NOT currently under the red debuff
		if (!self.isRed) {
			graphics.tint = self.originalColor;
		}
	};
	self.updateAI = function (ballX, ballY, ballVY) {
		// AI reacts *only* when ball is moving towards it (negative vy)
		if (self.isAI && ballVY < 0) {
			var targetX = ballX;
			var aiSpeed = 18; // Increased AI speed significantly
			var deadZone = self.width * 0.03; // Very small dead zone
			// More direct following by reducing interpolation factor or directly setting position
			// Option 1: Less interpolation (smoother than direct set)
			var moveAmount = (targetX - self.x) * 0.35; // Faster reaction interpolation factor
			self.x += Math.max(-aiSpeed, Math.min(aiSpeed, moveAmount));
			// Option 2: Near-direct set (can look jittery)
			// var diff = targetX - self.x;
			// self.x += Math.max(-aiSpeed, Math.min(aiSpeed, diff));
		}
		self.clampPosition();
	};
	self.clampPosition = function () {
		var halfWidth = self.width / 2;
		self.x = Math.max(halfWidth, Math.min(self.x, gameWidth - halfWidth));
	};
	self.applySizeChange = function (factor, duration, color) {
		// Clear any *pending* reset from a previous size change
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null; // Clear timer reference
		}
		// Stop ongoing width/tint tweens that might interfere
		tween.stop(graphics, {
			width: true,
			tint: true
		}); //{1c} approx
		// Apply new width via tween
		var targetWidth = self.originalWidth * factor;
		tween(graphics, {
			width: targetWidth
		}, {
			duration: 300,
			easing: tween.easeOut
		}); //{1h} approx
		self.width = targetWidth; // Update logical width immediately
		// Handle color / red debuff state and associated visuals
		if (color === 0xFF0000) {
			// RED Debuff
			graphics.tint = 0xFF0000;
			self.isRed = true;
			if (self.shieldVisual) {
				self.shieldVisual.visible = false; // Hide shield during red debuff
			}
		} else {
			// Blue Buff or Neutral (size change only) 
			// Only change tint if NOT currently RED
			if (!self.isRed) {
				// Set tint based on whether shield is active
				graphics.tint = self.hasShield ? 0x88CCFF : self.originalColor;
				if (self.shieldVisual) {
					// Ensure shield visibility matches shield state
					self.shieldVisual.visible = self.hasShield;
				}
			} else {//{1p} approx
				// If currently RED, tint remains RED, shield remains hidden. Do nothing here.
			}
		}
		// Update shield visual size to match new paddle size IF shield is active and visual exists
		if (self.hasShield && self.shieldVisual) {
			self.shieldVisual.width = self.width + 10;
			self.shieldVisual.height = self.height + 10;
			// Visibility is handled above based on isRed state
		}
		// Set timer to reset the size/color effects
		self.sizeChangeTimer = LK.setTimeout(function () {
			var wasShielded = self.hasShield; // Check shield status *before* reset potentially changes it
			// Call reset, passing whether a shield was active.
			// reset() handles setting isRed=false, width tween, tint, and shield visibility based on wasShielded.
			self.reset(wasShielded);
			// Simplified logic: Trust reset() to restore the correct visual state.
			// The original shield timer (if it existed and hasn't fired) will handle shield expiration.
			// No need for complex shield duration restoration here, which was potentially buggy.
			self.sizeChangeTimer = null;
		}, duration);
	};
	self.applyShield = function (duration) {
		// Clear any existing shield first to prevent timer duplication/conflicts
		// Note: removeShield() already handles timer clearing and tint reset (if not red)
		self.removeShield(); //{1x} // Line ID approx
		self.hasShield = true;
		if (!self.shieldVisual) {
			// Create shield visual if it doesn't exist
			self.shieldVisual = LK.getAsset('shieldShape', {
				anchorX: 0.5,
				anchorY: 0.5
			}); //{1z} approx
			self.addChild(self.shieldVisual); //{1A} approx
		}
		// Ensure visual matches current paddle size (might be affected by powerups)
		self.shieldVisual.width = self.width + 10; // Use current self.width
		self.shieldVisual.height = self.height + 10; // Use current self.height
		self.shieldVisual.visible = true;
		// Apply blue tint ONLY if NOT currently under the red debuff
		if (!self.isRed) {
			graphics.tint = 0x88CCFF; // Set to light blue
		}
		// Set timer to remove the shield effect
		self.shieldTimer = LK.setTimeout(function () {
			// Double-check if shield is still active before removing,
			// it might have been removed by other means (e.g., red powerup reset)
			if (self.hasShield) {
				self.removeShield();
			}
		}, duration);
	};
	self.clearAllTimers = function () {
		self.removeShield();
		if (self.sizeChangeTimer) {
			LK.clearTimeout(self.sizeChangeTimer);
			self.sizeChangeTimer = null;
		}
		self.isRed = false;
	};
	self.getWidth = function () {
		return self.width;
	};
	self.getHeight = function () {
		return self.height;
	};
	return self;
});
var PowerUp = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type;
	var assetName = type === 'blue' ? 'powerUpBlueShape' : 'powerUpRedShape';
	var graphics = self.attachAsset(assetName, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.width = graphics.width;
	self.height = graphics.height;
	// Set tint before starting the tween
	graphics.tint = type === 'blue' ? 0x4488FF : 0xFF4444;
	tween(graphics, {
		scaleX: 1.1,
		scaleY: 1.1,
		tint: type === 'blue' ? 0x4488FF : 0xFF4444
	}, {
		duration: 700,
		easing: tween.easeInOut,
		repeat: -1,
		yoyo: true
	});
	self.update = function () {};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x050510
});
/**** 
* Game Code
****/ 
// Sound Assets (Replace IDs)
// Cyan shield
var gameWidth = 2048;
var gameHeight = 2732;
var playerPaddle;
var aiPaddle;
var ball;
var powerUps = [];
var lastPaddleHitter = null;
var gameState = 'intro';
var powerUpSpawnTimer = null;
var introTimeout1 = null;
var introTimeout2 = null;
var playerScore = 0;
var aiScore = 0;
var winScore = 7;
var gameIcon = null;
var background = LK.getAsset('backgroundRect', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
game.addChild(background);
var centerLineXStart = 50;
var centerLineXEnd = gameWidth - 50;
var segmentWidth = 40;
var gapWidth = 25; // Slightly larger gap
var currentX = centerLineXStart;
while (currentX < centerLineXEnd) {
	var segment = LK.getAsset('centerLineSegment', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	segment.width = segmentWidth;
	segment.x = currentX + segmentWidth / 2;
	segment.y = gameHeight / 2;
	game.addChild(segment);
	currentX += segmentWidth + gapWidth;
}
var scoreTextPlayer = new Text2("0", {
	size: 100,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 4
});
scoreTextPlayer.anchor.set(0.5, 1);
scoreTextPlayer.x = gameWidth / 2;
scoreTextPlayer.y = gameHeight - 30;
game.addChild(scoreTextPlayer);
var scoreTextAI = new Text2("0", {
	size: 100,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 4
});
scoreTextAI.anchor.set(0.5, 0);
scoreTextAI.x = gameWidth / 2;
scoreTextAI.y = 30;
game.addChild(scoreTextAI);
var introText1 = new Text2('Samuil Paddle', {
	size: 200,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 8,
	fontWeight: 'bold'
});
introText1.anchor.set(0.5, 0.5);
introText1.x = gameWidth / 2;
introText1.y = gameHeight / 2 - 100;
introText1.visible = false;
game.addChild(introText1);
var introText2 = new Text2('Samuil', {
	size: 180,
	fill: 0x0000FF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 7,
	fontWeight: 'bold'
});
introText2.anchor.set(0.5, 0.5);
introText2.x = gameWidth / 2;
introText2.y = gameHeight / 2 + 100;
introText2.visible = false;
game.addChild(introText2);
var gameOverText = new Text2('', {
	size: 150,
	fill: 0xFFFFFF,
	align: 'center',
	stroke: 0x000000,
	strokeThickness: 6
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.x = gameWidth / 2;
gameOverText.y = gameHeight / 2 - 100;
gameOverText.visible = false;
game.addChild(gameOverText);
var restartText = new Text2('Click to Restart', {
	size: 90,
	fill: 0xDDDDDD,
	align: 'center'
});
restartText.anchor.set(0.5, 0.5);
restartText.x = gameWidth / 2;
restartText.y = gameHeight / 2 + 100;
restartText.visible = false;
restartText.interactive = true;
restartText.down = function () {
	if (gameState === 'gameOver') {
		startIntroSequence();
		LK.getSound('restartSound').play();
	}
};
game.addChild(restartText);
function resetGame() {
	if (gameIcon && gameIcon.parent) {
		game.removeChild(gameIcon);
		gameIcon = null;
	}
	if (playerPaddle && playerPaddle.parent) {
		game.removeChild(playerPaddle);
	}
	if (aiPaddle && aiPaddle.parent) {
		game.removeChild(aiPaddle);
	}
	if (ball && ball.parent) {
		game.removeChild(ball);
	}
	powerUps.forEach(function (p) {
		if (p && p.parent) {
			game.removeChild(p);
		}
	});
	powerUps = [];
	if (powerUpSpawnTimer) {
		LK.clearInterval(powerUpSpawnTimer);
	}
	if (introTimeout1) {
		LK.clearTimeout(introTimeout1);
	}
	if (introTimeout2) {
		LK.clearTimeout(introTimeout2);
	}
	playerScore = 0;
	aiScore = 0;
	scoreTextPlayer.setText("0");
	scoreTextAI.setText("0");
	introText1.visible = false;
	introText2.visible = false;
	gameOverText.visible = false;
	restartText.visible = false;
	lastPaddleHitter = null;
	playerPaddle = null;
	aiPaddle = null;
	ball = null;
}
function startGame() {
	resetGame();
	gameState = 'playing';
	playerPaddle = new Paddle(false);
	playerPaddle.x = gameWidth / 2;
	playerPaddle.y = gameHeight - 70;
	game.addChild(playerPaddle);
	aiPaddle = new Paddle(true);
	aiPaddle.x = gameWidth / 2;
	aiPaddle.y = 70;
	game.addChild(aiPaddle);
	ball = new Ball();
	game.addChild(ball);
	resetBall(Math.random() < 0.5 ? -1 : 1);
	LK.setTimeout(spawnPowerUp, 4000 + Math.random() * 4000);
	powerUpSpawnTimer = LK.setInterval(spawnPowerUp, 10000 + Math.random() * 6000);
	scoreTextPlayer.visible = true;
	scoreTextAI.visible = true;
	LK.playMusic('gameMusic');
}
function resetBall(directionY) {
	if (ball) {
		ball.x = gameWidth / 2;
		ball.y = gameHeight / 2;
		ball.serve(directionY);
	}
}
function spawnPowerUp() {
	if (gameState !== 'playing' || powerUps.length > 0) {
		return;
	}
	var type = Math.random() < 0.6 ? 'blue' : 'red';
	var powerUp = new PowerUp(type);
	powerUp.x = gameWidth * (0.2 + Math.random() * 0.6); // Spawn in middle 60% horizontally
	powerUp.y = gameHeight * (0.3 + Math.random() * 0.4); // Spawn in middle 40% vertically
	game.addChild(powerUp);
	powerUps.push(powerUp);
	LK.getSound('powerupSpawnSound').play({
		volume: 0.8
	});
}
game.move = function (x, y, obj) {
	if (gameState === 'playing' && playerPaddle) {
		var gamePos = game.toLocal({
			x: x,
			y: y
		});
		playerPaddle.x = gamePos.x;
		playerPaddle.clampPosition();
	}
};
game.down = function (x, y, obj) {
	if (gameState === 'gameOver' && restartText.visible) {
		startIntroSequence();
		LK.getSound('restartSound').play();
	}
};
game.update = function () {
	if (gameState !== 'playing') {
		return;
	}
	if (!ball || !playerPaddle || !aiPaddle) {
		console.error("Game elements missing!");
		endGame(false);
		return;
	}
	ball.update();
	aiPaddle.updateAI(ball.x, ball.y, ball.vy);
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var p = powerUps[i];
		if (!p || p.destroyed || !p.parent) {
			powerUps.splice(i, 1);
			continue;
		}
		p.update();
		if (ball.intersects(p)) {
			var targetPaddle = lastPaddleHitter;
			if (targetPaddle) {
				if (p.type === 'blue') {
					LK.getSound('powerupGoodSound').play();
					if (Math.random() < 0.5) {
						targetPaddle.applyShield(5000);
					} else {
						targetPaddle.applySizeChange(1.5, 5000, null);
					}
				} else {
					LK.getSound('powerupBadSound').play();
					targetPaddle.applySizeChange(0.6, 3000, 0xFF0000); // Shrink + RED
				}
			}
			if (p.parent) {
				game.removeChild(p);
			}
			p.destroy();
			powerUps.splice(i, 1);
		}
	}
	var ballHitPaddle = false;
	if (ball.intersects(playerPaddle)) {
		if (playerPaddle.hasShield) {
			LK.getSound('shieldBlockSound').play();
			playerPaddle.removeShield();
			ball.vy = -Math.abs(ball.vy) * 1.1 - 5;
			ball.vx += (Math.random() - 0.5) * 6;
			ball.y = playerPaddle.y - playerPaddle.getHeight() / 2 - ball.height / 2 - 3;
			lastPaddleHitter = null;
		} else {
			ball.bounce(playerPaddle);
			lastPaddleHitter = playerPaddle;
			ballHitPaddle = true;
		}
	} else if (ball.intersects(aiPaddle)) {
		if (aiPaddle.hasShield) {
			LK.getSound('shieldBlockSound').play();
			aiPaddle.removeShield();
			ball.vy = Math.abs(ball.vy) * 1.1 + 5;
			ball.vx += (Math.random() - 0.5) * 6;
			ball.y = aiPaddle.y + aiPaddle.getHeight() / 2 + ball.height / 2 + 3;
			lastPaddleHitter = null;
		} else {
			ball.bounce(aiPaddle);
			lastPaddleHitter = aiPaddle;
			ballHitPaddle = true;
		}
	}
	if (ballHitPaddle) {
		var nudgeAttempts = 0;
		while (ball.intersects(playerPaddle) && playerPaddle && nudgeAttempts < 10) {
			ball.y += ball.vy > 0 ? 1 : -1;
			nudgeAttempts++;
		}
		nudgeAttempts = 0;
		while (ball.intersects(aiPaddle) && aiPaddle && nudgeAttempts < 10) {
			ball.y += ball.vy > 0 ? 1 : -1;
			nudgeAttempts++;
		}
	}
	if (ball.y < -ball.height) {
		playerScore++;
		scoreTextPlayer.setText(playerScore);
		LK.getSound('scoreSoundPlayer').play();
		lastPaddleHitter = null;
		if (playerScore >= winScore) {
			endGame(true);
		} else {
			resetBall(1);
		}
	} else if (ball.y > gameHeight + ball.height) {
		aiScore++;
		scoreTextAI.setText(aiScore);
		LK.getSound('scoreSoundAI').play();
		lastPaddleHitter = null;
		if (aiScore >= winScore) {
			endGame(false);
		} else {
			resetBall(-1);
		}
	}
};
function endGame(playerWon) {
	gameState = 'gameOver';
	LK.stopMusic('gameMusic');
	if (powerUpSpawnTimer) {
		LK.clearInterval(powerUpSpawnTimer);
	}
	powerUps.forEach(function (p) {
		if (p && p.parent) {
			game.removeChild(p);
		}
		p.destroy();
	});
	powerUps = [];
	if (playerPaddle) {
		playerPaddle.clearAllTimers();
	}
	if (aiPaddle) {
		aiPaddle.clearAllTimers();
	}
	gameOverText.setText(playerWon ? "YOU WIN!" : "COMPUTER WINS!");
	gameOverText.visible = true;
	restartText.visible = true;
	if (ball && ball.parent) {
		game.removeChild(ball);
	}
	if (playerPaddle && playerPaddle.parent) {
		game.removeChild(playerPaddle);
	}
	if (aiPaddle && aiPaddle.parent) {
		game.removeChild(aiPaddle);
	}
	scoreTextPlayer.visible = false;
	scoreTextAI.visible = false;
	if (playerWon) {
		LK.getSound('gameOverSoundWin').play();
	} else {
		LK.getSound('gameOverSoundLose').play();
	}
}
function startIntroSequence() {
	resetGame();
	gameState = 'intro';
	scoreTextPlayer.visible = false;
	scoreTextAI.visible = false;
	// Create and add game icon
	if (!gameIcon) {
		gameIcon = new GameIcon();
		gameIcon.x = gameWidth / 2;
		gameIcon.y = gameHeight / 2 - 400;
		gameIcon.scale.set(0.8);
		game.addChild(gameIcon);
	}
	introText1.alpha = 0;
	introText1.visible = true;
	tween(introText1, {
		alpha: 1
	}, {
		duration: 500
	});
	LK.getSound('introSound1').play();
	introTimeout1 = LK.setTimeout(function () {
		tween(introText1, {
			alpha: 0
		}, {
			duration: 300,
			onFinish: function onFinish() {
				introText1.visible = false;
			}
		});
		introText2.alpha = 0;
		introText2.visible = true;
		tween(introText2, {
			alpha: 1
		}, {
			duration: 500
		});
		LK.getSound('introSound2').play();
		introTimeout2 = LK.setTimeout(function () {
			tween(introText2, {
				alpha: 0
			}, {
				duration: 300,
				onFinish: function onFinish() {
					introText2.visible = false;
					startGame();
				}
			});
		}, 2000);
	}, 3000);
}
startIntroSequence();
wallBounceSound
Sound effect
hitSoundPlayer
Sound effect
hitSoundAI
Sound effect
restartSound
Sound effect
powerupSpawnSound
Sound effect
gameMusic
Music
powerupGoodSound
Sound effect
powerupBadSound
Sound effect
shieldBlockSound
Sound effect
scoreSoundPlayer
Sound effect
scoreSoundAI
Sound effect
gameOverSoundWin
Sound effect
gameOverSoundLose
Sound effect
introSound1
Sound effect
introSound2
Sound effect