User prompt
add start menu music that is diffrent from the game music
User prompt
make the ball bouce a bit higher when it hits the paddle
User prompt
the text is to big make it a bit smaller
User prompt
i cant read it
User prompt
make a descripition of the game on the start menu
User prompt
make the paddle all one color ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when you die start back up right away with out going into the start menu
User prompt
make the ball bounce in random directions
User prompt
just a bit slower
User prompt
make the ball bounce a little bit slower
User prompt
make the ball bounce faster
User prompt
the ball bounces to slow
User prompt
to slow make the ball bounce faster
User prompt
ok make the ball bounce slower too fast
User prompt
make the ball bounce way faster
User prompt
make it bounce farther
User prompt
make the ball bounce farther
User prompt
make the physics of the ball more realisic ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the ends of the paddle this color #FFB612
User prompt
make the ends of the paddle rounded
User prompt
make the ends of the paddle beveld
User prompt
add a trail to the ball for when it movesa
User prompt
make each level make the ball go faster and faster
User prompt
make it so when the cursor is over the "Play Game" button the button swings back and forth quickly. @upit/tween.v1
User prompt
when the cursor is over the start game button make the button rotate back and forth quickly until the cursor is not on the button @upit/tween.v1
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0
});
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var ballGraphic = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speedX = 0;
	self.speedY = 0;
	self.active = true;
	self.trailCounter = 0;
	self.gravity = 0.18; // Further reduced gravity for slower falling
	self.airResistance = 0.995; // Slightly increased air resistance for slower movement
	self.bounciness = 0.92; // Lower bounciness for less energetic bounces
	self.spin = 0; // Ball spin (affects horizontal movement)
	self.lastHitPos = 0; // Last hit position on paddle (for spin calculation)
	self.reset = function (speedMultiplier) {
		// Set position to center of screen
		self.x = 2048 / 2;
		self.y = 2732 / 2;
		// Generate a random angle between 0 and 2π (full 360 degrees)
		var randomAngle = Math.random() * Math.PI * 2;
		// Set initial speed magnitude
		var speedMagnitude = 15 * speedMultiplier;
		// Calculate velocity components based on random angle
		self.speedX = Math.cos(randomAngle) * speedMagnitude;
		self.speedY = Math.sin(randomAngle) * speedMagnitude;
		self.active = true;
		self.spin = 0; // Reset spin
		self.lastHitPos = 0; // Reset last hit position
	};
	self.update = function () {
		if (!self.active) {
			return;
		}
		// Store last positions for collision detection
		var lastX = self.x;
		var lastY = self.y;
		// Apply gravity - increases vertical speed over time
		self.speedY += self.gravity;
		// Apply air resistance
		self.speedX *= self.airResistance;
		self.speedY *= self.airResistance;
		// Apply spin effect to horizontal movement
		self.speedX += self.spin * 0.1;
		// Gradually reduce spin over time
		self.spin *= 0.98;
		// Apply velocity
		self.x += self.speedX;
		self.y += self.speedY;
		// Add trail effect based on speed
		self.trailCounter++;
		// Adjust trail frequency based on speed - faster speed = more frequent trails
		var trailFrequency = Math.max(1, 5 - Math.floor((Math.abs(self.speedX) + Math.abs(self.speedY)) / 10));
		// Create more trails at higher speeds
		if (self.trailCounter > trailFrequency) {
			self.trailCounter = 0;
			var trail = LK.getAsset('ball', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: lastX,
				y: lastY
			});
			// Adjust trail size based on ball speed
			var speedFactor = Math.min(1, (Math.abs(self.speedX) + Math.abs(self.speedY)) / 40);
			trail.scale.set(self.scale.x * (0.7 - speedFactor * 0.2), self.scale.y * (0.7 - speedFactor * 0.2));
			trail.tint = gameColors.ball;
			// Higher alpha for faster speeds
			trail.alpha = 0.5 + speedFactor * 0.3;
			game.addChildAt(trail, game.getChildIndex(self));
			// Fade out and remove trail - faster trails disappear quicker
			var trailDuration = 300 - speedFactor * 150;
			tween(trail, {
				alpha: 0,
				scaleX: trail.scale.x * 0.5,
				scaleY: trail.scale.y * 0.5
			}, {
				duration: trailDuration,
				onFinish: function onFinish() {
					trail.destroy();
				}
			});
		}
		// Rotate the ball based on horizontal speed to show rolling effect
		ballGraphic.rotation += self.speedX * 0.05;
		// Bounce off sides with more random physics
		if (self.x < 20 || self.x > 2028) {
			// Flip the horizontal direction
			self.speedX = -self.speedX * self.bounciness * 1.2;
			// Add significant random variation to both speed components
			self.speedX += Math.random() * 6 - 3; // Major randomness on x-axis
			self.speedY += Math.random() * 4 - 2; // Add randomness to y-axis on wall bounce too
			// Chance for a very wild bounce (20% chance)
			if (Math.random() < 0.2) {
				self.speedX *= 0.5 + Math.random();
				self.speedY *= 0.5 + Math.random();
			}
			// Keep the ball within the game boundaries
			self.x = Math.max(20, Math.min(2028, self.x));
			// Play bounce sound if soundEnabled is true
			if (soundEnabled) {
				LK.getSound('bounce').play();
			}
		}
		// Check if ball hits the top of the screen with more random bounces
		if (self.y < 20) {
			// Flip the vertical direction
			self.speedY = -self.speedY * self.bounciness * 1.25;
			// Add significant random variation to both speed components
			self.speedX += Math.random() * 5 - 2.5; // Add randomness to x-axis on ceiling bounce
			self.speedY += Math.random() * 5 - 2.5; // Major randomness on y-axis
			// Chance for a very wild bounce (20% chance)
			if (Math.random() < 0.2) {
				// Completely random direction after ceiling hit
				var randomAngle = Math.random() * Math.PI + Math.PI; // Angle in bottom half
				var currentSpeed = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY);
				self.speedX = Math.cos(randomAngle) * currentSpeed;
				self.speedY = Math.sin(randomAngle) * currentSpeed;
			}
			self.y = 20;
			// Play bounce sound if soundEnabled is true
			if (soundEnabled) {
				LK.getSound('bounce').play();
			}
		}
	};
	return self;
});
var DiagonalStripe = Container.expand(function () {
	var self = Container.call(this);
	// Create a shape for the diagonal stripe
	var stripeGraphic = self.attachAsset('background', {
		anchorX: 0,
		anchorY: 0
	});
	// Configure the stripe appearance
	stripeGraphic.width = 3000; // Increased width to extend past screen edges
	stripeGraphic.height = 100;
	stripeGraphic.tint = 0xffffff; // White
	// Initial position and rotation
	stripeGraphic.rotation = Math.PI / 4; // 45 degrees in radians
	// Position it to extend past screen edges
	stripeGraphic.x = -500; // Start before the left edge
	// Empty update method (stripe will be still)
	self.update = function () {
		// No animation - stripe remains still
	};
	return self;
});
var Paddle = Container.expand(function () {
	var self = Container.call(this);
	// Create the main paddle base - middle rectangle section
	var paddleGraphic = self.attachAsset('paddle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	paddleGraphic.tint = 0xFFB612; // Set paddle color to #FFB612
	// Create the left rounded end (circle shape)
	var leftEnd = LK.getAsset('ball', {
		// Using the ball asset as it's a circle
		anchorX: 0.5,
		anchorY: 0.5,
		width: paddleGraphic.height,
		height: paddleGraphic.height,
		tint: 0xFFB612
	});
	leftEnd.x = -paddleGraphic.width / 2 + leftEnd.width / 2;
	self.addChild(leftEnd);
	// Create the right rounded end (circle shape)
	var rightEnd = LK.getAsset('ball', {
		// Using the ball asset as it's a circle
		anchorX: 0.5,
		anchorY: 0.5,
		width: paddleGraphic.height,
		height: paddleGraphic.height,
		tint: 0xFFB612
	});
	rightEnd.x = paddleGraphic.width / 2 - rightEnd.width / 2;
	// Make sure the right end is the correct color
	rightEnd.tint = 0xFFB612;
	self.addChild(rightEnd);
	// Trim the main paddle to accommodate rounded ends
	paddleGraphic.width = paddleGraphic.width - paddleGraphic.height;
	self.width = paddleGraphic.width + paddleGraphic.height; // Total width includes the circles
	self.height = paddleGraphic.height;
	self.update = function () {
		// Keep paddle within screen bounds
		self.x = Math.max(self.width / 2, Math.min(2048 - self.width / 2, self.x));
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xffffff // Light sky blue for a calmer atmosphere
});
/**** 
* Game Code
****/ 
// Game state management
var GAME_STATE = {
	MENU: 0,
	PLAYING: 1,
	SETTINGS: 2
};
var currentState = GAME_STATE.MENU;
// Default colors for game elements - softer, more calming colors
var gameColors = {
	paddle: 0xffb612,
	// Changed to requested color #ffb612
	ball: 0xFFB612,
	// Changed to requested color #FFB612
	lava: 0xC60C30 // Changed to requested color #C60C30
};
// Color saving/loading disabled
// Make game accessible to other functions
var gameInstance = game;
// Game variables
var background;
var paddle;
var lava;
var balls = [];
var score = 0;
var highScore = storage.highScore || 0;
var level = 1;
var combo = 0;
var lastBallHit = 0;
var gameActive = false;
var speedMultiplier = 1.0;
var maxBalls = 1;
var ballsInPlay = 0;
var spawnInterval;
var hitsToNextLevel = 25;
var currentHits = 0;
var hitCounterText;
// UI elements
var scoreTxt;
var levelTxt;
var comboTxt;
var highScoreTxt;
var speedTxt;
// Default sound settings
var soundEnabled = true;
var musicEnabled = true;
// Load stored sound settings
var soundSetting = storage.soundEnabled;
if (soundSetting !== undefined) {
	soundEnabled = soundSetting;
}
// Initialize game elements (called when starting game)
function initializeGameElements() {
	if (!background) {
		// Create background
		background = LK.getAsset('background', {
			anchorX: 0,
			anchorY: 0,
			x: 0,
			y: 0
		});
		game.addChild(background);
		// Initialize lava
		lava = LK.getAsset('lava', {
			anchorX: 0.5,
			anchorY: 0,
			x: 2048 / 2,
			y: 2732 - 200
		});
		lava.tint = gameColors.lava;
		game.addChild(lava);
		// Initialize paddle
		paddle = new Paddle();
		paddle.x = 2048 / 2;
		paddle.y = 2732 - 250;
		paddle.getChildAt(0).tint = 0xffb612;
		game.addChild(paddle);
		// Diagonal stripe removed from here and placed in menu
		// Create hit counter text
		scoreTxt = new Text2('0', {
			size: 180,
			fill: 0x101820
		});
		scoreTxt.anchor.set(0.5, 0.5);
		// Position score text precisely in the center of the screen
		scoreTxt.x = 2048 / 2; // True center horizontally
		scoreTxt.y = 2732 / 2; // True center vertically
		game.addChild(scoreTxt);
		// Create level text
		levelTxt = new Text2('Level: 1', {
			size: 70,
			fill: 0xFFFFFF
		});
		levelTxt.anchor.set(1, 0);
		levelTxt.x = 2000;
		levelTxt.y = 50;
		LK.gui.addChild(levelTxt);
		// Create combo text
		comboTxt = new Text2('', {
			size: 60,
			fill: 0xFFFFFF
		});
		comboTxt.anchor.set(0.5, 0);
		comboTxt.x = 1024;
		comboTxt.y = 50;
		comboTxt.alpha = 0;
		LK.gui.addChild(comboTxt);
		// Create high score text
		highScoreTxt = new Text2('High Score: ' + highScore, {
			size: 60,
			fill: 0xffb612
		});
		highScoreTxt.anchor.set(1, 0);
		highScoreTxt.x = 2000;
		highScoreTxt.y = 130; // Position below hit counter
		game.addChild(highScoreTxt); // Add directly to game to ensure visibility
		// Create speed indicator text
		speedTxt = new Text2('Speed: x' + speedMultiplier.toFixed(1), {
			size: 60,
			fill: 0xffb612
		});
		speedTxt.anchor.set(0, 0);
		speedTxt.x = 48;
		speedTxt.y = 50;
		game.addChild(speedTxt);
		// Create hit counter text
		hitCounterText = new Text2(currentHits + '/25', {
			size: 70,
			fill: 0x003087
		});
		hitCounterText.anchor.set(0.5, 0);
		hitCounterText.x = 1024;
		hitCounterText.y = 150; // More visible position at top of screen
		game.addChild(hitCounterText); // Add directly to game to ensure visibility
	}
	// Show game elements
	background.visible = true;
	lava.visible = true;
	paddle.visible = true;
	scoreTxt.visible = true;
	levelTxt.visible = true;
	comboTxt.visible = true;
	highScoreTxt.visible = true;
	hitCounterText.visible = true;
}
// Create menu elements
var titleText;
var startButton;
var settingsButton;
var settingsPanel;
var menuBackground;
// Initialize menu
initializeMenu();
function initializeMenu() {
	// Play menu music if enabled
	if (musicEnabled) {
		LK.playMusic('menuMusic', {
			fade: {
				start: 0,
				end: 0.6,
				duration: 1500
			}
		});
	}
	// Create menu background
	menuBackground = new Container();
	var menuBg = LK.getAsset('background', {
		anchorX: 0,
		anchorY: 0,
		x: 0,
		y: 0,
		tint: 0xFFFFFF // White color for menu background
	});
	// Create a border by adding a slightly larger background behind it
	var menuBorder = LK.getAsset('background', {
		anchorX: 0,
		anchorY: 0,
		x: 0,
		y: 0,
		tint: 0xA5ACAF // Border color set to #A5ACAF
	});
	menuBorder.width = 2048 + 10 * 2; // Adding 10px on each side
	menuBorder.height = 2732 + 10 * 2; // Adding 10px on each side
	menuBorder.x = -10; // Position it 10px to the left
	menuBorder.y = -10; // Position it 10px to the top
	menuBackground.addChild(menuBorder);
	menuBackground.addChild(menuBg);
	game.addChild(menuBackground);
	// Diagonal stripe removed from menu
	// Create game title
	titleText = new Text2('Lava Bounce', {
		size: 150,
		fill: 0x101820
	});
	titleText.anchor.set(0.5, 0);
	titleText.x = 1024;
	titleText.y = 200;
	game.addChild(titleText);
	// Animate the title to rotate back and forth
	function animateTitleRotation() {
		// Rotate to one side
		tween(titleText, {
			rotation: 0.1 // Slight rotation to the right (in radians)
		}, {
			duration: 1000,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				// Rotate to the other side
				tween(titleText, {
					rotation: -0.1 // Slight rotation to the left (in radians)
				}, {
					duration: 1000,
					easing: tween.easeInOut,
					onFinish: animateTitleRotation // Loop the animation
				});
			}
		});
	}
	// Start the title rotation animation
	animateTitleRotation();
	// Create the "2" as a separate, larger text element
	var titleNumber = new Text2('2', {
		size: 200,
		// Bigger than the main title text
		fill: 0xFFB612 // Gold color
	});
	titleNumber.anchor.set(0.5, 0);
	titleNumber.x = 1024; // Centered horizontally
	titleNumber.y = 350; // Positioned below the main title
	game.addChild(titleNumber);
	// Animate the "2" with a continuous bounce effect
	function animateTitle2() {
		// Bounce up animation
		tween(titleNumber, {
			y: 320,
			// Move up slightly
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 700,
			onFinish: function onFinish() {
				// Bounce down animation
				tween(titleNumber, {
					y: 350,
					// Back to original position
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 700,
					onFinish: animateTitle2 // Loop the animation
				});
			}
		});
	}
	// Start the animation
	animateTitle2();
	// Create start button
	startButton = new Text2('Start Game', {
		size: 90,
		fill: 0xFFB612
	});
	startButton.anchor.set(0.5, 0.5);
	startButton.x = 1024;
	startButton.y = 1200;
	startButton.interactive = true;
	startButton.isHovered = false; // Track hover state
	startButton.move = function (x, y, obj) {
		// Check if cursor is over the button
		if (x >= startButton.x - startButton.width / 2 && x <= startButton.x + startButton.width / 2 && y >= startButton.y - startButton.height / 2 && y <= startButton.y + startButton.height / 2) {
			// Start animation only if not already hovering
			if (!startButton.isHovered) {
				startButton.isHovered = true;
				// Apply a slight scale increase when hovered
				tween(startButton, {
					scaleX: 1.05,
					scaleY: 1.05
				}, {
					duration: 200,
					easing: tween.easeOut
				});
				animateStartButton();
			}
		} else {
			// Stop animation when cursor moves away
			if (startButton.isHovered) {
				startButton.isHovered = false;
				tween.stop(startButton, {
					rotation: true
				});
				tween(startButton, {
					rotation: 0,
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 200
				});
			}
		}
	};
	// Function to animate the start button
	function animateStartButton() {
		if (!startButton.isHovered) {
			return;
		}
		// Rotate to one side
		tween(startButton, {
			rotation: 0.08 // Slight rotation (in radians)
		}, {
			duration: 50,
			// Very quick rotation for more responsive feel
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				if (!startButton.isHovered) {
					startButton.rotation = 0;
					return;
				}
				// Rotate to the other side
				tween(startButton, {
					rotation: -0.08 // Slight rotation in opposite direction
				}, {
					duration: 50,
					// Very quick rotation for more responsive feel
					easing: tween.easeInOut,
					onFinish: animateStartButton // Continue the animation
				});
			}
		});
	}
	game.addChild(startButton);
	// Create settings button
	settingsButton = new Text2('Settings', {
		size: 90,
		fill: 0x101820
	});
	settingsButton.anchor.set(0.5, 0.5);
	settingsButton.x = 1024;
	settingsButton.y = 1400;
	settingsButton.interactive = true;
	game.addChild(settingsButton);
	// Set up event handlers for menu
	startButton.down = function () {
		if (soundEnabled) {
			LK.getSound('click').play();
		}
		// Stop menu music with fade out
		if (musicEnabled) {
			LK.playMusic('menuMusic', {
				fade: {
					start: 0.6,
					end: 0,
					duration: 500
				}
			});
		}
		hideMenu();
		initializeGameElements();
		startGame();
	};
	settingsButton.down = function () {
		if (soundEnabled) {
			LK.getSound('click').play();
		}
		hideMenu();
		showSettings();
	};
}
function hideMenu() {
	if (menuBackground) {
		menuBackground.visible = false;
	}
	if (titleText) {
		titleText.visible = false;
	}
	if (startButton) {
		startButton.visible = false;
	}
	if (settingsButton) {
		settingsButton.visible = false;
	}
	// Make sure high score is visible in game
	if (highScoreTxt) {
		highScoreTxt.visible = true;
	}
}
function showMenu() {
	currentState = GAME_STATE.MENU;
	if (menuBackground) {
		menuBackground.visible = true;
	}
	if (titleText) {
		titleText.visible = true;
	}
	if (startButton) {
		startButton.visible = true;
	}
	if (settingsButton) {
		settingsButton.visible = true;
	}
	if (settingsPanel) {
		settingsPanel.visible = false;
	}
	// Play menu music when returning to menu from game over
	if (musicEnabled && currentState === GAME_STATE.MENU) {
		LK.playMusic('menuMusic', {
			fade: {
				start: 0,
				end: 0.6,
				duration: 1000
			}
		});
	}
}
function showSettings() {
	currentState = GAME_STATE.SETTINGS;
	// Create settings panel if it doesn't exist
	if (!settingsPanel) {
		settingsPanel = new Container();
		game.addChild(settingsPanel);
		// Settings panel background without border
		var panelContainer = new Container();
		panelContainer.x = 1024;
		panelContainer.y = 1366;
		// Set initial scale to zero for animation
		panelContainer.scale.x = 0;
		panelContainer.scale.y = 0;
		// Inner panel background (without blue border)
		var panelBg = LK.getAsset('background', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 0,
			y: 0
		});
		panelBg.width = 1600;
		panelBg.height = 1000;
		panelBg.tint = 0x101820; // Dark blue/black color for settings panel
		panelContainer.addChild(panelBg);
		settingsPanel.addChild(panelContainer);
		// Settings title
		var settingsTitle = new Text2('Settings', {
			size: 80,
			fill: 0xFFFFFF
		});
		settingsTitle.anchor.set(0.5, 0);
		settingsTitle.x = 1024;
		settingsTitle.y = 500;
		settingsPanel.addChild(settingsTitle);
		// Color selectors have been removed
		// Game description text
		var gameDescription = new Text2('Lava Bounce 2: A frantic paddle game where you\ncontrol a golden paddle to bounce balls away from\ndeadly red lava. Score points with each bounce,\nlevel up for increased speed and challenge.\nCan you set a new high score record?', {
			size: 50,
			fill: 0xFFB612
		});
		gameDescription.anchor.set(0.5, 0.5);
		gameDescription.x = 1024; // True center horizontally
		gameDescription.y = 700;
		settingsPanel.addChild(gameDescription);
		// High score display in settings
		var highScoreDisplay = new Text2('High Score: ' + highScore, {
			size: 60,
			fill: 0xFFFFFF
		});
		highScoreDisplay.anchor.set(0, 0.5);
		highScoreDisplay.x = 400;
		highScoreDisplay.y = 970; // Moved down a bit
		settingsPanel.addChild(highScoreDisplay);
		// Reset high score button
		var resetButton = new Text2('Reset High Score', {
			size: 60,
			fill: 0xFF6B6B
		});
		resetButton.anchor.set(0.5, 0.5);
		resetButton.x = 1024; // True center horizontally
		resetButton.y = 1366; // True center vertically 
		resetButton.interactive = true;
		resetButton.down = function () {
			if (soundEnabled) {
				LK.getSound('click').play();
			}
			showResetConfirmation();
		};
		settingsPanel.addChild(resetButton);
		// Back to menu button
		var backButton = new Text2('Back to Menu', {
			size: 60,
			fill: 0xFFFFFF
		});
		backButton.anchor.set(0.5, 0.5);
		backButton.x = 1024;
		backButton.y = 1100;
		backButton.interactive = true;
		backButton.down = function () {
			if (soundEnabled) {
				LK.getSound('click').play();
			}
			// Animate settings panel closing
			tween(settingsPanel.getChildAt(0), {
				scaleX: 0,
				scaleY: 0
			}, {
				duration: 300,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					settingsPanel.visible = false;
					showMenu();
					// Play menu music when returning to menu
					if (musicEnabled) {
						LK.playMusic('menuMusic', {
							fade: {
								start: 0,
								end: 0.6,
								duration: 1000
							}
						});
					}
				}
			});
		};
		settingsPanel.addChild(backButton);
	} else {
		settingsPanel.visible = true;
		// Reset scale for animation if panel already exists
		settingsPanel.getChildAt(0).scale.x = 0;
		settingsPanel.getChildAt(0).scale.y = 0;
	}
	// Animate the settings panel opening with bounce effect
	tween(settingsPanel.getChildAt(0), {
		scaleX: 1,
		scaleY: 1
	}, {
		duration: 600,
		easing: tween.elasticOut
	});
	// Color buttons function has been removed
}
// Initialize balls array
function createBall() {
	if (ballsInPlay >= maxBalls || !gameActive) {
		return;
	}
	var ball = new Ball();
	ball.reset(speedMultiplier);
	ball.getChildAt(0).tint = gameColors.ball;
	// Visual indicator of speed - make ball slightly smaller as it gets faster
	var scale = Math.max(0.6, 1 - (speedMultiplier - 1) * 0.15);
	ball.scale.set(scale, scale);
	balls.push(ball);
	game.addChild(ball);
	ballsInPlay++;
}
// Handle input events based on current state
game.down = function (x, y, obj) {
	if (currentState === GAME_STATE.PLAYING) {
		paddle.x = x;
	}
	// Check if we hit any interactive elements
	if (obj && obj.event && obj.event.target && obj.event.target.down) {
		obj.event.target.down(x, y, obj);
	}
};
game.move = function (x, y, obj) {
	if (currentState === GAME_STATE.PLAYING) {
		paddle.x = x;
	}
};
// Update function
game.update = function () {
	// Update any diagonal stripes in the game (always update even when not playing)
	for (var i = 0; i < game.children.length; i++) {
		if (game.children[i] instanceof DiagonalStripe) {
			game.children[i].update();
		}
	}
	// Check if in playing state
	if (currentState !== GAME_STATE.PLAYING) {
		return;
	}
	// Game play state
	if (!gameActive) {
		return;
	}
	// Update speed indicator if it exists
	if (speedTxt) {
		speedTxt.setText('Speed: x' + speedMultiplier.toFixed(1));
	}
	// Only create a ball if none exists
	if (ballsInPlay === 0) {
		createBall();
	}
	// Update paddle and track position for physics calculations
	game.lastPaddleX = paddle.x; // Store current position for next frame
	paddle.update();
	// Update all balls
	for (var i = balls.length - 1; i >= 0; i--) {
		var ball = balls[i];
		if (!ball.active) {
			continue;
		}
		ball.update();
		// Check if ball hits paddle with improved collision detection
		if (ball.speedY > 0 && ball.y + 20 >= paddle.y - paddle.height / 2 && ball.y - 20 <= paddle.y + paddle.height / 2 && ball.x + 20 >= paddle.x - paddle.width / 2 && ball.x - 20 <= paddle.x + paddle.width / 2) {
			// Calculate hit position from -1 (left edge) to 1 (right edge)
			var hitPos = (ball.x - paddle.x) / (paddle.width / 2);
			// Calculate spin based on the difference between current and last hit position
			// This simulates the effect of a moving paddle hitting the ball
			var paddleMovementEffect = 0;
			if (game.lastPaddleX !== undefined) {
				paddleMovementEffect = (paddle.x - game.lastPaddleX) * 0.1;
			}
			// Apply reduced spin based on hit position and paddle movement
			ball.spin = hitPos * 0.3 + paddleMovementEffect * 0.6; // Reduced spin effect
			ball.lastHitPos = hitPos;
			// Calculate angle based on where the ball hits the paddle with more randomness
			// Wider angle range - full 180 degrees (0 to 180) instead of 120 degrees
			var angle = Math.PI * Math.random() + Math.PI / 2; // Random angle in upper half (90 to 270 degrees)
			// Add influence from hit position
			angle = angle * 0.7 + (Math.PI / 3 * hitPos + Math.PI / 2) * 0.3;
			// Calculate current speed with an adjustment
			var currentSpeed = Math.sqrt(ball.speedX * ball.speedX + ball.speedY * ball.speedY);
			var speed = Math.max(currentSpeed * 1.25, 12 * speedMultiplier);
			// Adjust ball direction with more random bounce physics
			ball.speedX = Math.cos(angle) * speed + paddleMovementEffect * 1.5;
			ball.speedY = -Math.sin(angle) * speed * 1.4; // Increased vertical multiplier for higher bounce
			// Add larger random variations for more unpredictable bouncing
			ball.speedX += (Math.random() * 4 - 2) * speedMultiplier; // Increased randomness
			ball.speedY += (Math.random() * 4 - 2) * speedMultiplier; // Increased randomness
			// Create a bounce effect with the paddle - make it visually respond to the hit
			tween(paddle, {
				scaleY: 0.85,
				y: paddle.y + 5
			}, {
				duration: 100,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(paddle, {
						scaleY: 1.0,
						y: paddle.y - 5
					}, {
						duration: 100,
						easing: tween.elasticOut
					});
				}
			});
			// Move ball above paddle to prevent multiple collisions
			ball.y = paddle.y - paddle.height / 2 - 20;
			// Add a visual impact effect
			var impactEffect = LK.getAsset('ball', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: ball.x,
				y: ball.y + 10,
				tint: 0xFFFFFF
			});
			impactEffect.scale.set(1.5, 0.5);
			impactEffect.alpha = 0.7;
			game.addChild(impactEffect);
			// Animate and remove the impact effect
			tween(impactEffect, {
				alpha: 0,
				scaleX: 2.5,
				scaleY: 0.2
			}, {
				duration: 200,
				onFinish: function onFinish() {
					impactEffect.destroy();
				}
			});
			// Simple scoring - always add 1 point
			score += 1;
			// Hide combo text
			comboTxt.alpha = 0;
			// Update hit counter
			scoreTxt.setText('' + score);
			// Center the score text
			scoreTxt.x = 2048 / 2; // True center horizontally
			scoreTxt.y = 2732 / 2; // True center vertically
			// Make it fade and gently grow when updated
			tween(scoreTxt, {
				scaleX: 1.1,
				// Smaller scale change
				scaleY: 1.1,
				// Smaller scale change
				alpha: 0.8 // Slight fade out
			}, {
				duration: 300,
				// Longer duration for smoother animation
				easing: tween.easeInOut,
				// Smoother easing
				onFinish: function onFinish() {
					tween(scoreTxt, {
						scaleX: 1,
						scaleY: 1,
						alpha: 1 // Back to full opacity
					}, {
						duration: 300,
						// Longer duration
						easing: tween.easeInOut // Smoother easing
					});
				}
			});
			LK.setScore(score);
			// Play bounce sound if enabled
			if (soundEnabled) {
				LK.getSound('bounce').play();
			}
			// Update hit counter for level system
			currentHits++;
			hitCounterText.setText(currentHits + '/' + hitsToNextLevel);
			// Level up based on hits
			if (currentHits >= hitsToNextLevel) {
				currentHits = 0;
				levelUp();
				hitCounterText.setText('Hits to Next Level: ' + hitsToNextLevel);
				// Animate hit counter text
				tween(hitCounterText, {
					scaleX: 1.2,
					scaleY: 1.2,
					alpha: 0.8
				}, {
					duration: 300,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						tween(hitCounterText, {
							scaleX: 1,
							scaleY: 1,
							alpha: 1
						}, {
							duration: 300,
							easing: tween.easeInOut
						});
					}
				});
			}
		}
		// Check if ball falls into lava
		if (ball.y > lava.y) {
			// Play lava sound if enabled
			if (soundEnabled) {
				LK.getSound('lava').play();
			}
			// Flash the lava
			tween(lava, {
				tint: 0xffffff
			}, {
				duration: 200,
				onFinish: function onFinish() {
					tween(lava, {
						tint: 0xe74c3c
					}, {
						duration: 200
					});
				}
			});
			// Remove ball
			ball.active = false;
			ball.destroy();
			balls.splice(i, 1);
			ballsInPlay--;
			// Check game over
			if (balls.length === 0 && ballsInPlay === 0) {
				gameOver();
			}
		}
	}
};
// Reset confirmation popup
function showResetConfirmation() {
	// Create popup container
	var popup = new Container();
	game.addChild(popup);
	// Popup background
	var popupBg = LK.getAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366
	});
	popupBg.width = 1200;
	popupBg.height = 700;
	popupBg.tint = 0x101820;
	popup.addChild(popupBg);
	// Border for popup
	var popupBorder = LK.getAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366
	});
	popupBorder.width = 1210;
	popupBorder.height = 710;
	popupBorder.tint = 0xFFB612;
	popup.addChildAt(popupBorder, 0);
	// Confirmation text
	var confirmText = new Text2('Reset High Score?', {
		size: 70,
		fill: 0xFFFFFF
	});
	confirmText.anchor.set(0.5, 0);
	confirmText.x = 1024;
	confirmText.y = 1200;
	popup.addChild(confirmText);
	// Yes button
	var yesButton = new Text2('Yes', {
		size: 60,
		fill: 0xFF6B6B
	});
	yesButton.anchor.set(0.5, 0.5);
	yesButton.x = 824;
	yesButton.y = 1450;
	yesButton.interactive = true;
	yesButton.down = function () {
		if (soundEnabled) {
			LK.getSound('click').play();
		}
		// Reset high score
		highScore = 0;
		storage.highScore = 0;
		// Update high score display
		if (highScoreTxt) {
			highScoreTxt.setText('High Score: 0');
		}
		// Update settings display
		settingsPanel.children.forEach(function (child) {
			if (child instanceof Text2 && child.text && child.text.startsWith('High Score:')) {
				child.setText('High Score: 0');
			}
		});
		// Remove popup with animation
		tween(popup, {
			alpha: 0,
			scaleX: 0.8,
			scaleY: 0.8
		}, {
			duration: 300,
			onFinish: function onFinish() {
				popup.destroy();
			}
		});
	};
	popup.addChild(yesButton);
	// No button
	var noButton = new Text2('No', {
		size: 60,
		fill: 0xFFFFFF
	});
	noButton.anchor.set(0.5, 0.5);
	noButton.x = 1224;
	noButton.y = 1450;
	noButton.interactive = true;
	noButton.down = function () {
		if (soundEnabled) {
			LK.getSound('click').play();
		}
		// Remove popup with animation
		tween(popup, {
			alpha: 0,
			scaleX: 0.8,
			scaleY: 0.8
		}, {
			duration: 300,
			onFinish: function onFinish() {
				popup.destroy();
			}
		});
	};
	popup.addChild(noButton);
	// Animate popup appearing
	popup.scale.set(0.8, 0.8);
	popup.alpha = 0;
	tween(popup, {
		alpha: 1,
		scaleX: 1,
		scaleY: 1
	}, {
		duration: 300,
		easing: tween.easeOut
	});
}
function levelUp() {
	level++;
	levelTxt.setText('Level: ' + level);
	// Show level up message with speed information
	var levelUpTxt = new Text2('LEVEL UP!\nSpeed x' + speedMultiplier.toFixed(1), {
		size: 80,
		fill: 0xFFFFFF
	});
	levelUpTxt.anchor.set(0.5, 0.5);
	levelUpTxt.x = 1024;
	levelUpTxt.y = 1366;
	LK.gui.addChild(levelUpTxt);
	// Animate level up message
	tween(levelUpTxt, {
		alpha: 0,
		scaleX: 2,
		scaleY: 2
	}, {
		duration: 1000,
		onFinish: function onFinish() {
			levelUpTxt.destroy();
		}
	});
	// Increase difficulty with a moderate speed boost for slightly slower progression
	speedMultiplier += 0.4 + level * 0.08; // Reduced speed boost for slightly slower gameplay
	maxBalls = 1; // Keep maxBalls at 1
	// Reset hit counter for next level
	currentHits = 0;
	// Increase hits required for next level for increasing challenge
	hitsToNextLevel = 25 + (level - 1) * 5;
	hitCounterText.setText('0/' + hitsToNextLevel);
}
function gameOver() {
	gameActive = false;
	// Check if we have a new high score
	if (score > highScore) {
		highScore = score;
		storage.highScore = highScore;
		// Show new high score message
		var newHighScoreTxt = new Text2('NEW HIGH SCORE!', {
			size: 80,
			fill: 0xFFB612
		});
		newHighScoreTxt.anchor.set(0.5, 0.5);
		newHighScoreTxt.x = 1024;
		newHighScoreTxt.y = 1000;
		LK.gui.addChild(newHighScoreTxt);
		// Animate high score message
		tween(newHighScoreTxt, {
			alpha: 0,
			scaleX: 2,
			scaleY: 2
		}, {
			duration: 1500,
			onFinish: function onFinish() {
				newHighScoreTxt.destroy();
			}
		});
		// Update high score display
		if (highScoreTxt) {
			highScoreTxt.setText('High Score: ' + highScore);
		}
	}
	// Flash the screen red to indicate death
	LK.effects.flashScreen(0xff0000, 500);
	// Restart the game after a short delay instead of showing menu
	LK.setTimeout(function () {
		// Keep the game elements visible, just restart game logic
		// Clear any remaining balls
		for (var i = 0; i < balls.length; i++) {
			balls[i].destroy();
		}
		balls = [];
		ballsInPlay = 0;
		// Restart the game immediately
		startGame();
		// Ensure we're in playing state
		currentState = GAME_STATE.PLAYING;
	}, 500);
}
// Start the game
function startGame() {
	// Reset variables
	score = 0;
	level = 1;
	combo = 0;
	lastBallHit = 0;
	gameActive = true;
	speedMultiplier = 1.5; // Further reduced initial speed multiplier for slower initial gameplay
	maxBalls = 3; // Maintained same number of maximum balls
	ballsInPlay = 0;
	currentHits = 0;
	hitsToNextLevel = 25;
	// Update UI
	scoreTxt.setText('0');
	scoreTxt.scale.set(1, 1); // Reset any scaling from animations
	scoreTxt.x = 2048 / 2; // True center horizontally
	scoreTxt.y = 2732 / 2; // True center vertically
	levelTxt.setText('Level: 1');
	comboTxt.setText('');
	comboTxt.alpha = 0;
	hitCounterText.setText('0/' + hitsToNextLevel);
	// Update high score display
	if (highScoreTxt) {
		highScoreTxt.setText('High Score: ' + highScore);
	}
	// Clear any existing balls
	for (var i = 0; i < balls.length; i++) {
		balls[i].destroy();
	}
	balls = [];
	// Start with one ball
	createBall();
	// Play music if enabled - softer volume for a calmer feel
	if (musicEnabled) {
		LK.playMusic('gameMusic', {
			fade: {
				start: 0,
				end: 0.4,
				// Lower volume
				duration: 2000 // Longer fade in
			}
		});
	}
	// Ensure the current state is set to playing
	currentState = GAME_STATE.PLAYING;
}
// Game will start when player presses the Play button in the menu ===================================================================
--- original.js
+++ change.js
@@ -362,8 +362,18 @@
 var menuBackground;
 // Initialize menu
 initializeMenu();
 function initializeMenu() {
+	// Play menu music if enabled
+	if (musicEnabled) {
+		LK.playMusic('menuMusic', {
+			fade: {
+				start: 0,
+				end: 0.6,
+				duration: 1500
+			}
+		});
+	}
 	// Create menu background
 	menuBackground = new Container();
 	var menuBg = LK.getAsset('background', {
 		anchorX: 0,
@@ -542,8 +552,18 @@
 	startButton.down = function () {
 		if (soundEnabled) {
 			LK.getSound('click').play();
 		}
+		// Stop menu music with fade out
+		if (musicEnabled) {
+			LK.playMusic('menuMusic', {
+				fade: {
+					start: 0.6,
+					end: 0,
+					duration: 500
+				}
+			});
+		}
 		hideMenu();
 		initializeGameElements();
 		startGame();
 	};
@@ -589,8 +609,18 @@
 	}
 	if (settingsPanel) {
 		settingsPanel.visible = false;
 	}
+	// Play menu music when returning to menu from game over
+	if (musicEnabled && currentState === GAME_STATE.MENU) {
+		LK.playMusic('menuMusic', {
+			fade: {
+				start: 0,
+				end: 0.6,
+				duration: 1000
+			}
+		});
+	}
 }
 function showSettings() {
 	currentState = GAME_STATE.SETTINGS;
 	// Create settings panel if it doesn't exist
@@ -682,8 +712,18 @@
 				easing: tween.easeIn,
 				onFinish: function onFinish() {
 					settingsPanel.visible = false;
 					showMenu();
+					// Play menu music when returning to menu
+					if (musicEnabled) {
+						LK.playMusic('menuMusic', {
+							fade: {
+								start: 0,
+								end: 0.6,
+								duration: 1000
+							}
+						});
+					}
 				}
 			});
 		};
 		settingsPanel.addChild(backButton);