Code edit (1 edits merged)
Please save this source code
User prompt
OKay, so move click up50 pixxels and remove the damage next to it since we have it below now
User prompt
Can we should the clickdamage belwo the cick text here: createUpgradeButton('Click', startX + 8 * (buttonWidth + spacing), 'clickCost', 'clickDamage', 25, null, null);
User prompt
Please fix the bug: 'Uncaught ReferenceError: labelText is not defined' in or related to this line: 'labelText.fill = isEnabled ? 0x000000 : 0x666666; // Grey out label text when disabled' Line Number: 1065
User prompt
clisck powerup button, should have 3 rows: 1: Click text 2: Power up level 3: Powe up cost
User prompt
increse the size of the font on the ball powerups button
User prompt
add a little more space between the upgrade buttons, but make sure they are still in the screen
User prompt
For text in upgrades us SPD instead of Speed, and DMG instead of Power.
User prompt
when start button is pressed, fade out the elelemtns leaving and fade int the ones coming in ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When start button is pressed, add teh same explosion effect as when brick is detroyed
Code edit (11 edits merged)
Please save this source code
User prompt
Remove all current balls when a level end, and resspawn them from either the bottom or top of the screen.
User prompt
on level end, destroy all balls, and when next level starts, restore them from memory. like we do when we start a game that already had balls
User prompt
When a new level start if a ball is overlapping with a brick, teleportit to a brick free area
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
un comment levels code
User prompt
remove commented levels
User prompt
Make game title end screen container (currently pink) instead make it tween with colors like the bottom frame ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: tintEndScreenTitle is not defined' in or related to this line: 'tintEndScreenTitle();' Line Number: 527
Code edit (1 edits merged)
Please save this source code
User prompt
create new fucntion to explicitly tints the end screen game title container
Code edit (4 edits merged)
Please save this source code
User prompt
Move restart and rest on end screen 40 pixels up
User prompt
comment all levels out except level 1
/**** 
* Plugins
****/ 
var storage = LK.import("@upit/storage.v1");
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Ball = Container.expand(function () {
	var self = Container.call(this);
	var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal';
	var ballGraphics = self.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	ballGraphics.tint = type === 'splash' ? 0xff0066 : type === 'sniper' ? 0x00ff99 : type === 'scatter' ? 0xffff00 : type === 'smallScatter' ? 0xffff00 : 0xffffff;
	self.type = type;
	self.speed = type === 'splash' ? upgrades.splashSpeed : type === 'sniper' ? upgrades.sniperSpeed : type === 'scatter' ? upgrades.scatterSpeed : type === 'smallScatter' ? upgrades.scatterSpeed * 0.8 : upgrades.normalSpeed;
	self.power = type === 'splash' ? upgrades.splashPower : type === 'sniper' ? upgrades.sniperPower : type === 'scatter' ? upgrades.scatterPower : type === 'smallScatter' ? Math.max(1, Math.floor(upgrades.scatterPower * 0.5)) : upgrades.normalPower;
	self.direction = {
		x: 1,
		y: -1
	};
	self.sniperCooldown = 0;
	self.sniperCooldownMax = 60;
	self.interactive = true;
	self.down = function (x, y, obj) {
		var angle = Math.random() * 2 * Math.PI;
		self.direction.x = Math.cos(angle);
		self.direction.y = Math.sin(angle);
		var magnitude = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
		self.direction.x /= magnitude;
		self.direction.y /= magnitude;
	};
	self.update = function () {
		var gridSize = levelConfig[level] ? levelConfig[level].gridSize : 200;
		var stepSize = self.speed;
		if (self.type === 'sniper') {
			self.sniperCooldown--;
			if (self.sniperCooldown <= 0) {
				var nearestBrick = findNearestBrick(self.x, self.y);
				if (nearestBrick) {
					var dx = nearestBrick.x - self.x;
					var dy = nearestBrick.y - self.y;
					var magnitude = Math.sqrt(dx * dx + dy * dy);
					self.direction.x = dx / magnitude;
					self.direction.y = dy / magnitude;
					self.sniperCooldown = self.sniperCooldownMax;
				}
			}
		}
		// Move in smaller steps to catch collisions accurately
		var steps = Math.ceil(stepSize / BALL_RADIUS); // Break movement into smaller chunks
		var dx = self.direction.x * stepSize / steps;
		var dy = self.direction.y * stepSize / steps;
		for (var step = 0; step < steps; step++) {
			self.x += dx;
			self.y += dy;
			// Wall collisions
			if (self.x <= BALL_RADIUS || self.x >= GAME_WIDTH - BALL_RADIUS) {
				self.direction.x *= -1;
				self.x = Math.max(BALL_RADIUS, Math.min(GAME_WIDTH - BALL_RADIUS, self.x));
				self.direction.y += (Math.random() - 0.5) * 0.1;
				LK.getSound('bounce').play();
			}
			if (self.y <= BALL_RADIUS || self.y >= GAME_HEIGHT - BALL_RADIUS) {
				self.direction.y *= -1;
				self.y = Math.max(BALL_RADIUS, Math.min(GAME_HEIGHT - BALL_RADIUS, self.y));
				self.direction.x += (Math.random() - 0.5) * 0.1;
				LK.getSound('bounce').play();
			}
			// Skip brick collision check if not near bricks
			if (!isNearBricks(self.x, self.y)) {
				continue;
			}
			// Check collisions with bricks in nearby grid cells
			var gridXMin = Math.floor((self.x - BALL_RADIUS) / gridSize);
			var gridXMax = Math.floor((self.x + BALL_RADIUS) / gridSize);
			var gridYMin = Math.floor((self.y - BALL_RADIUS) / gridSize);
			var gridYMax = Math.floor((self.y + BALL_RADIUS) / gridSize);
			var hasCollided = false;
			for (var gx = gridXMin; gx <= gridXMax && !hasCollided; gx++) {
				for (var gy = gridYMin; gy <= gridYMax && !hasCollided; gy++) {
					var gridKey = "".concat(gx, ",").concat(gy);
					var cellBricks = brickGrid[gridKey];
					if (!cellBricks || cellBricks.length === 0) {
						continue;
					}
					for (var j = cellBricks.length - 1; j >= 0; j--) {
						var brick = cellBricks[j];
						if (!brick || brick.health <= 0) {
							continue;
						}
						// Precise circle vs. rectangle collision
						var collision = checkCollision(self, brick);
						if (!collision) {
							continue;
						}
						// Resolve collision
						resolveCollision(self, brick, collision);
						brick.hit(self.power);
						if (self.type === 'splash' && brick.health > 0) {
							applySplashDamage(brick, gridSize);
						} else if (self.type === 'scatter') {
							scatterOnImpact(self);
							self.destroy();
							balls.splice(balls.indexOf(self), 1);
							hasCollided = true;
							break;
						}
						if (brick.health <= 0) {
							cellBricks.splice(j, 1);
						}
						hasCollided = true;
						break;
					}
				}
			}
			if (hasCollided) {
				break;
			} // Stop stepping after a collision
		}
		// Normalize direction to maintain consistent speed
		var magnitude = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
		if (magnitude > 0) {
			self.direction.x /= magnitude;
			self.direction.y /= magnitude;
		}
	};
	// Precise collision check: Circle (ball) vs. Rectangle (brick)
	function checkCollision(ball, brick) {
		var closestX = Math.max(brick.x - BRICK_WIDTH / 2, Math.min(ball.x, brick.x + BRICK_WIDTH / 2));
		var closestY = Math.max(brick.y - BRICK_HEIGHT / 2, Math.min(ball.y, brick.y + BRICK_HEIGHT / 2));
		var dx = ball.x - closestX;
		var dy = ball.y - closestY;
		var distanceSquared = dx * dx + dy * dy;
		if (distanceSquared <= BALL_RADIUS * BALL_RADIUS) {
			// Determine collision side
			var relX = ball.x - brick.x;
			var relY = ball.y - brick.y;
			var absX = Math.abs(relX);
			var absY = Math.abs(relY);
			var halfW = BRICK_WIDTH / 2 + BALL_RADIUS;
			var halfH = BRICK_HEIGHT / 2 + BALL_RADIUS;
			if (absX > halfW || absY > halfH) {
				return null;
			} // Outside bounding box
			if (absX / halfW > absY / halfH) {
				return {
					side: relX > 0 ? 'right' : 'left',
					normalX: relX > 0 ? 1 : -1,
					normalY: 0
				};
			} else {
				return {
					side: relY > 0 ? 'bottom' : 'top',
					normalX: 0,
					normalY: relY > 0 ? 1 : -1
				};
			}
		}
		return null;
	}
	// Resolve collision: Adjust position and reflect direction
	function resolveCollision(ball, brick, collision) {
		// Move ball out of brick based on collision normal
		var overlapX = BALL_RADIUS - Math.abs(ball.x - (brick.x + collision.normalX * BRICK_WIDTH / 2));
		var overlapY = BALL_RADIUS - Math.abs(ball.y - (brick.y + collision.normalY * BRICK_HEIGHT / 2));
		if (collision.normalX !== 0) {
			ball.x += collision.normalX * overlapX;
			ball.direction.x = -ball.direction.x;
		} else if (collision.normalY !== 0) {
			ball.y += collision.normalY * overlapY;
			ball.direction.y = -ball.direction.y;
		}
		// Add slight randomness to prevent sticking or straight bounces
		ball.direction.x += (Math.random() - 0.5) * 0.2;
		ball.direction.y += (Math.random() - 0.5) * 0.2;
		LK.getSound('bounce').play();
	}
});
var Brick = Container.expand(function () {
	var self = Container.call(this);
	var brickGraphics = self.attachAsset('brick', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.health = 1;
	self.maxHealth = 1;
	self.healthText = new Text2(self.health.toString(), {
		size: 50,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	self.healthText.anchor.set(0.5, 0.5);
	self.addChild(self.healthText);
	// Helper function to convert hex color to RGB
	function hexToRGB(hex) {
		return {
			r: hex >> 16 & 0xff,
			g: hex >> 8 & 0xff,
			b: hex & 0xff
		};
	}
	// Helper function to convert RGB back to hex
	function rgbToHex(r, g, b) {
		return (Math.floor(r) << 16) + (Math.floor(g) << 8) + Math.floor(b);
	}
	// Update brick tint based on health
	self.updateTint = function () {
		var baseColors = LEVEL_COLORS;
		var colorCount = baseColors.length; // 10 colors
		if (self.health <= colorCount) {
			// For HP 1-10, use the direct color from LEVEL_COLORS
			brickGraphics.tint = baseColors[self.health - 1];
		} else {
			// For HP > 10, use the last digit to determine the color
			var lastDigit = self.health % 10; // Get the last digit (0-9)
			// Map last digit 0 to index 9 (HP 10), 1 to index 0 (HP 1), etc.
			var colorIndex = lastDigit === 0 ? 9 : lastDigit - 1;
			brickGraphics.tint = baseColors[colorIndex];
		}
	};
	self.updateTint();
	self.hit = function () {
		var damage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
		self.health -= damage;
		if (self.health <= 0) {
			LK.getSound('explosion').play();
			score += self.maxHealth === 1 ? 1 : self.maxHealth;
			scoreTxt.setText('$' + score.toString());
			storage.score = score;
			var brickIndex = bricks.indexOf(self);
			if (brickIndex !== -1) {
				bricks.splice(brickIndex, 1);
			}
			var explosionColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff];
			var randomColor = explosionColors[Math.floor(Math.random() * explosionColors.length)];
			var randomScale = Math.random() * 1.5 + 1.5;
			var randomDuration = Math.random() * 300 + 400;
			tween(self, {
				tint: randomColor,
				scaleX: randomScale,
				scaleY: randomScale,
				alpha: 0
			}, {
				duration: randomDuration,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					self.destroy();
				}
			});
		} else {
			self.healthText.setText(self.health.toString());
			self.updateTint();
		}
	};
});
var GameTitle = Container.expand(function () {
	var self = Container.call(this);
	var titleGraphics = self.attachAsset('gametitle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var titleText = new Text2('Idle BrickBreaker', {
		size: 150,
		fill: 0x000000
	});
	titleText.anchor.set(0.5, 0.5);
	self.addChild(titleText);
});
var ResetButton = Container.expand(function () {
	var self = Container.call(this);
	var buttonGraphics = self.attachAsset('resetButton', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0xff6666
	});
	var buttonText = new Text2('RESET', {
		size: 50,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	buttonText.anchor.set(0.5, 0.5);
	self.addChild(buttonText);
	self.interactive = true;
	self.down = function () {
		LK.getSound('click').play();
		clearLocalStorage();
		playTime = 0;
		storage.playTime = playTime;
		LK.showGameOver(); // Show game over when reset is pressed 
	};
});
var Star = Container.expand(function () {
	var self = Container.call(this);
	var starGraphics = self.attachAsset('star', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = Math.random() * 2 + 1;
	self.update = function () {
		self.y += self.speed;
		if (self.y > GAME_HEIGHT) {
			self.y = 0;
			self.x = Math.random() * GAME_WIDTH;
		}
	};
});
var StartButton = Container.expand(function () {
	var self = Container.call(this);
	var buttonGraphics = self.attachAsset('startButton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var buttonText = new Text2('START', {
		size: 80,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	buttonText.anchor.set(0.5, 0.5);
	self.addChild(buttonText);
	self.interactive = true;
	self.down = function () {
		LK.getSound('click').play();
		startGame();
	};
});
var UpgradeButton = Container.expand(function () {
	var self = Container.call(this);
	var buttonGraphics = self.attachAsset('upgrade', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0x00ffff
	});
	var buttonText = new Text2('UPGRADES', {
		size: 50,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	buttonText.anchor.set(0.5, 0.5);
	self.addChild(buttonText);
	self.interactive = true;
	self.down = function () {
		LK.getSound('click').play();
		powerupContainer.visible = !powerupContainer.visible;
	};
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a2e
});
/**** 
* Game Code
****/ 
function tintEndScreenTitle() {
	// This function will tint the end screen game title container
	// You can customize the tint logic here if needed
	gameTitleContainer.children.forEach(function (child) {
		child.tint = 0xff33cc; // Example tint color
	});
}
// Create a frame around the screen using a custom 'frame' asset
var frameThickness = 10; // Thickness of the frame
// Top frame
var topFrame = new Container();
var topFrameGraphics = topFrame.attachAsset('frame', {
	anchorX: 0,
	anchorY: 0,
	width: GAME_WIDTH,
	height: frameThickness
});
topFrame.x = 0;
topFrame.y = 0;
game.addChild(topFrame);
function animateTopFrameTint() {
	tween(topFrameGraphics, {
		tint: 0xff33cc
	}, {
		duration: 2000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(topFrameGraphics, {
				tint: 0x00ff99
			}, {
				duration: 2000,
				easing: tween.easeInOut,
				onFinish: animateTopFrameTint
			});
		}
	});
}
animateTopFrameTint();
// Bottom frame
var bottomFrame = new Container();
var bottomFrameGraphics = bottomFrame.attachAsset('frame', {
	anchorX: 0,
	anchorY: 0,
	width: GAME_WIDTH,
	height: frameThickness
});
bottomFrame.x = 0;
bottomFrame.y = 2720;
game.addChild(bottomFrame);
function animateBottomFrameTint() {
	tween(bottomFrameGraphics, {
		tint: 0xff33cc
	}, {
		duration: 2000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(bottomFrameGraphics, {
				tint: 0x00ff99
			}, {
				duration: 2000,
				easing: tween.easeInOut,
				onFinish: animateBottomFrameTint
			});
		}
	});
}
animateBottomFrameTint();
// Left frame
var leftFrame = new Container();
var leftFrameGraphics = leftFrame.attachAsset('frame', {
	anchorX: 0,
	anchorY: 0,
	width: frameThickness,
	height: GAME_HEIGHT
});
leftFrame.x = 0;
leftFrame.y = 0;
game.addChild(leftFrame);
function animateLeftFrameTint() {
	tween(leftFrameGraphics, {
		tint: 0xff33cc
	}, {
		duration: 2000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(leftFrameGraphics, {
				tint: 0x00ff99
			}, {
				duration: 2000,
				easing: tween.easeInOut,
				onFinish: animateLeftFrameTint
			});
		}
	});
}
animateLeftFrameTint();
// Right frame
var rightFrame = new Container();
var rightFrameGraphics = rightFrame.attachAsset('frame', {
	anchorX: 0,
	anchorY: 0,
	width: frameThickness,
	height: GAME_HEIGHT
});
rightFrame.x = 2035;
rightFrame.y = 0;
game.addChild(rightFrame);
function animateRightFrameTint() {
	tween(rightFrameGraphics, {
		tint: 0xff33cc
	}, {
		duration: 2000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(rightFrameGraphics, {
				tint: 0x00ff99
			}, {
				duration: 2000,
				easing: tween.easeInOut,
				onFinish: animateRightFrameTint
			});
		}
	});
}
animateRightFrameTint();
var welcomeText = null;
function showEndScreen() {
	game.isGameOver = true; // Set the flag to indicate the end screen is up
	// Hide all game elements
	hud.visible = false;
	powerupContainer.visible = false;
	upgradeButton.visible = false;
	balls.forEach(function (ball) {
		return ball.visible = true;
	});
	bricks.forEach(function (brick) {
		return brick.visible = false;
	});
	var congratsText = new Text2('Congratulations! You broke them ALL!', {
		size: 100,
		fill: 0xffffff
	});
	congratsText.anchor.set(0.5, 0);
	congratsText.x = GAME_WIDTH / 2;
	congratsText.y = GAME_HEIGHT / 2 - 500 + 550;
	game.addChild(congratsText);
	// Add game title with color switching
	var gameTitle = new GameTitle();
	gameTitle.x = GAME_WIDTH / 2;
	gameTitle.y = congratsText.y - 400;
	gameTitleContainer.addChild(gameTitle);
	function animateEndTitleColor() {
		tintEndScreenTitle();
		tween(gameTitle, {
			tint: 0xff33cc
		}, {
			duration: 2000,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				tween(gameTitle, {
					tint: 0x00ff99
				}, {
					duration: 2000,
					easing: tween.easeInOut,
					onFinish: animateEndTitleColor
				});
			}
		});
	}
	animateEndTitleColor();
	// Add play time text
	var playTimeText = new Text2('Time Played: ' + playTime + ' seconds', {
		size: 80,
		fill: 0xffffff
	});
	playTimeText.anchor.set(0.5, 0);
	playTimeText.x = GAME_WIDTH / 2;
	playTimeText.y = congratsText.y + 300;
	game.addChild(playTimeText);
	// Add a note below the time played
	var noteText = new Text2('Start over with all your upgrades, or reset for a fresh new run! Your choice!', {
		size: 50,
		fill: 0xffffff
	});
	noteText.anchor.set(0.5, 0);
	noteText.x = GAME_WIDTH / 2;
	noteText.y = playTimeText.y + 400;
	game.addChild(noteText);
	// Add end game button
	var endGameButton = new Container();
	var buttonGraphics = endGameButton.attachAsset('endGameButton', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0x00ffff // Match the upgrade button tint
	});
	var buttonText = new Text2('RESTART!', {
		size: 50,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	buttonText.anchor.set(0.5, 0.5);
	endGameButton.addChild(buttonText);
	endGameButton.x = GAME_WIDTH / 2;
	endGameButton.y = GAME_HEIGHT - 240;
	endGameButton.interactive = true;
	endGameButton.down = function () {
		LK.showGameOver();
	};
	game.addChild(endGameButton);
	// Add reset button
	var resetButton = new ResetButton();
	resetButton.x = GAME_WIDTH / 2;
	resetButton.y = endGameButton.y + 160;
	game.addChild(resetButton);
	// Debugging: Log to ensure animations are triggered
	LK.clearInterval(playTimeInterval);
	playTimeInterval = null; // Reset the interval variable to null
	playTimeInterval = null; // Reset the interval variable to null
}
function _toConsumableArray2(r) {
	return _arrayWithoutHoles2(r) || _iterableToArray2(r) || _unsupportedIterableToArray2(r) || _nonIterableSpread2();
}
function _nonIterableSpread2() {
	throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray2(r, a) {
	if (r) {
		if ("string" == typeof r) {
			return _arrayLikeToArray2(r, a);
		}
		var t = {}.toString.call(r).slice(8, -1);
		return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray2(r, a) : void 0;
	}
}
function _iterableToArray2(r) {
	if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
		return Array.from(r);
	}
}
function _arrayWithoutHoles2(r) {
	if (Array.isArray(r)) {
		return _arrayLikeToArray2(r);
	}
}
function _arrayLikeToArray2(r, a) {
	(null == a || a > r.length) && (a = r.length);
	for (var e = 0, n = Array(a); e < a; e++) {
		n[e] = r[e];
	}
	return n;
}
function _toConsumableArray(r) {
	return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
	throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(r, a) {
	if (r) {
		if ("string" == typeof r) {
			return _arrayLikeToArray(r, a);
		}
		var t = {}.toString.call(r).slice(8, -1);
		return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
	}
}
function _iterableToArray(r) {
	if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
		return Array.from(r);
	}
}
function _arrayWithoutHoles(r) {
	if (Array.isArray(r)) {
		return _arrayLikeToArray(r);
	}
}
function _arrayLikeToArray(r, a) {
	(null == a || a > r.length) && (a = r.length);
	for (var e = 0, n = Array(a); e < a; e++) {
		n[e] = r[e];
	}
	return n;
}
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2720; // Adjusted to match bottom frame position
var BALL_RADIUS = 50;
var BRICK_WIDTH = 300;
var BRICK_HEIGHT = 99;
var LEVEL_COLORS = [0xff00ff, 0x00ffff, 0xffff00, 0xff0066, 0x00ff99, 0xff33cc, 0x66ff33, 0xcc00ff, 0x33ffcc, 0xff3300];
var levelConfig = {
	1: {
		totalBricks: 63,
		hitpoints: 2,
		gridSize: 400,
		pattern: 'clustered'
	},
	2: {
		totalBricks: 77,
		hitpoints: 3,
		gridSize: 400,
		pattern: 'clustered'
	},
	3: {
		totalBricks: 91,
		hitpoints: 6,
		gridSize: 320,
		pattern: 'staggered'
	},
	4: {
		totalBricks: 90,
		hitpoints: 10,
		gridSize: 500,
		pattern: 'clustered'
	},
	5: {
		totalBricks: 96,
		hitpoints: 12,
		gridSize: 240,
		pattern: 'staggered'
	},
	6: {
		totalBricks: 112,
		hitpoints: 15,
		gridSize: 220,
		pattern: 'clustered'
	},
	7: {
		totalBricks: 112,
		hitpoints: 20,
		gridSize: 200,
		pattern: 'staggered'
	},
	8: {
		totalBricks: 112,
		hitpoints: 99,
		gridSize: 180,
		pattern: 'clustered'
	},
	9: {
		totalBricks: 112,
		hitpoints: 997,
		gridSize: 160,
		pattern: 'staggered'
	},
	10: {
		totalBricks: 112,
		hitpoints: 9998,
		gridSize: 140,
		pattern: 'clustered'
	}
};
var upgrades = storage.upgrades || {
	normalSpeed: 1,
	normalPower: 1,
	splashSpeed: 1,
	splashPower: 1,
	sniperSpeed: 1,
	sniperPower: 1,
	scatterSpeed: 1,
	scatterPower: 1,
	clickDamage: 1,
	normalSpeedCost: 50,
	normalPowerCost: 50,
	splashSpeedCost: 75,
	splashPowerCost: 75,
	sniperSpeedCost: 100,
	sniperPowerCost: 100,
	scatterSpeedCost: 125,
	scatterPowerCost: 125,
	clickCost: 25,
	normalBallCost: 25,
	splashBallCost: 100,
	sniperBallCost: 500,
	scatterBallCost: 2000
};
var balls = [];
var ballQuantities = storage.ballQuantities || {
	normal: 0,
	splash: 0,
	sniper: 0,
	scatter: 0
};
var bricks = [];
var brickGrid = {};
var score = storage.score || 0;
var level = storage.level || 1;
var brickGridBounds = null;
var unlockedTiers = storage.unlockedTiers || {
	normal: true,
	splash: false,
	sniper: false,
	scatter: false
};
var playTime = storage.playTime || 0;
playTimeInterval = LK.setInterval(function () {
	if (!game.isGameOver) {
		// Check if the game is not over
		playTime += 1;
		storage.playTime = playTime;
		console.log('Time Played2:', playTime, 'seconds');
	}
}, 1000);
var playTimeInterval = null;
game.isGameOver = false; // Initialize the flag to indicate the end screen is not up
function clearLocalStorage() {
	storage.score = 0;
	storage.level = 1;
	storage.unlockedTiers = {
		normal: true,
		splash: false,
		sniper: false,
		scatter: false
	};
	unlockedTiers = Object.assign({}, storage.unlockedTiers);
	storage.upgrades = {
		normalSpeed: 1,
		normalPower: 1,
		splashSpeed: 1,
		splashPower: 1,
		sniperSpeed: 1,
		sniperPower: 1,
		scatterSpeed: 1,
		scatterPower: 1,
		clickDamage: 1,
		normalSpeedCost: 50,
		normalPowerCost: 50,
		splashSpeedCost: 75,
		splashPowerCost: 75,
		sniperSpeedCost: 100,
		sniperPowerCost: 100,
		scatterSpeedCost: 125,
		scatterPowerCost: 125,
		clickCost: 25,
		normalBallCost: 25,
		splashBallCost: 150,
		sniperBallCost: 500,
		scatterBallCost: 2000
	};
	score = 0;
	storage.ballQuantities = {
		normal: 0,
		splash: 0,
		sniper: 0,
		scatter: 0
	};
	storage.firstLoad = false;
	ballQuantities = Object.assign({}, storage.ballQuantities);
	level = 1;
	unlockedTiers = Object.assign({}, storage.unlockedTiers);
	scoreTxt.setText('$' + score.toString());
	levelTxt.setText('Level: ' + level);
	updateButtonStates();
}
// HUD Setup
var hud = new Container();
LK.gui.top.addChild(hud);
var scoreTxt = new Text2('$0', {
	size: 60,
	fill: 0x39ff14 // Neon green color
});
scoreTxt.anchor.set(0.3, 0);
scoreTxt.x += 570;
hud.addChild(scoreTxt);
var levelTxt = new Text2('Level: ' + level, {
	size: 50,
	fill: 0xffffff
});
levelTxt.anchor.set(1, 0);
levelTxt.x = scoreTxt.x + 100;
levelTxt.y = scoreTxt.height + 10;
hud.addChild(levelTxt);
var ballButtons = {};
function createBallButton(type, x, cost, asset, prevTier) {
	var button = new Container();
	var buttonGraphics = button.attachAsset('button', {
		anchorX: 0.5,
		anchorY: 0,
		tint: 0x1a1a2e
	});
	button.y = 50;
	button.x = x + 20;
	var contentContainer = new Container();
	button.addChild(contentContainer);
	var ballIcon = button.attachAsset('ball', {
		anchorX: 0.5,
		anchorY: -0.5,
		scaleX: 0.6,
		scaleY: 0.6,
		y: -10
	});
	// Set initial tint
	ballIcon.tint = type === 'splash' ? 0xff0066 : type === 'sniper' ? 0x00ff99 : type === 'scatter' ? 0xffff00 : 0xffffff; // Normal ball
	contentContainer.addChild(ballIcon);
	var displayType = type === 'scatter' ? 'Multi' : type.charAt(0).toUpperCase() + type.slice(1);
	var typeText = new Text2(displayType, {
		size: 30,
		fill: 0xffffff,
		// Initial white color
		fontWeight: 'bold'
	});
	typeText.anchor.set(0.5, 0);
	typeText.y = -50;
	button.addChild(typeText);
	var costText = new Text2('$' + (type === 'sniper' ? 500 : type === 'splash' ? 150 : type === 'scatter' ? 2000 : upgrades[type + 'BallCost']), {
		size: 40,
		fill: 0xffffff // Change to white color
	});
	costText.anchor.set(0.5, 0);
	costText.y = 100;
	button.addChild(costText);
	button.interactive = true;
	button.down = function () {
		if (score < upgrades[type + 'BallCost']) {
			return;
		}
		// Remove welcome message if it exists
		if (welcomeText && welcomeText.parent) {
			welcomeText.parent.removeChild(welcomeText);
		}
		score -= upgrades[type + 'BallCost'];
		scoreTxt.setText('$' + score.toString());
		createBall(type);
		ballQuantities[type] = (ballQuantities[type] || 0) + 1;
		storage.ballQuantities = Object.assign({}, ballQuantities);
		upgrades[type + 'BallCost'] = Math.floor(upgrades[type + 'BallCost'] * 1.5);
		storage.upgrades = Object.assign({}, upgrades);
		costText.setText('$' + upgrades[type + 'BallCost']);
		if (!unlockedTiers[type]) {
			unlockedTiers[type] = true;
			storage.unlockedTiers = Object.assign({}, unlockedTiers);
			updateButtonStates();
		}
	};
	button.updateState = function () {
		var isEnabled = (prevTier ? unlockedTiers[prevTier] : true) && score >= upgrades[type + 'BallCost'];
		buttonGraphics.tint = isEnabled ? 0x00ffff : 0x666666; // Button background tint
		button.interactive = isEnabled;
		// Update ballIcon tint based on enabled state
		if (isEnabled) {
			ballIcon.tint = type === 'splash' ? 0xff0066 : type === 'sniper' ? 0x00ff99 : type === 'scatter' ? 0xffff00 : 0xffffff; // Restore original ball color
			typeText.fill = 0xffffff; // White for ball name
			costText.fill = 0x00ffff; // Cyan for price
		} else {
			ballIcon.tint = 0x666666; // Grey out ball icon
			typeText.fill = 0x666666; // Grey out ball name
			costText.fill = 0x666666; // Grey out price
		}
	};
	hud.addChild(button);
	ballButtons[type] = button;
}
createBallButton('normal', -450, 25, 'ball', null);
createBallButton('splash', -300, upgrades.splashBallCost, 'splashBall', 'normal');
createBallButton('sniper', -150, upgrades.sniperBallCost, 'sniperBall', 'splash');
createBallButton('scatter', 0, upgrades.scatterBallCost, 'scatterBall', 'sniper');
var clearStorageButton = LK.getAsset('button', {
	size: 0,
	fill: 0x1a1a2e,
	anchorX: 0.5,
	anchorY: 0,
	x: scoreTxt.width + 12000,
	y: 0
});
var clearStorageText = new Text2('', {
	size: 0,
	fill: 0xffffff
});
clearStorageText.anchor.set(0.5, 0);
clearStorageText.y = 100;
clearStorageButton.addChild(clearStorageText);
clearStorageButton.down = clearLocalStorage;
hud.addChild(clearStorageButton);
var powerupContainer = new Container();
powerupContainer.y = 1800;
powerupContainer.visible = false;
game.addChild(powerupContainer);
var bottomHud = new Container();
bottomHud.y = GAME_HEIGHT - 200;
game.addChild(bottomHud);
var upgradeButtons = {};
function createUpgradeButton(labelPrefix, x, costKey, upgradeKey, baseCost, iconType, prevTier) {
	var button = new Container();
	var buttonGraphics = button.attachAsset('powerupbutton', {
		anchorX: 0.5,
		anchorY: 0,
		tint: 0x1a1a2e
	});
	button.x = x + 60;
	button.y = 350;
	button.addChild(buttonGraphics);
	var contentContainer = new Container();
	button.addChild(contentContainer);
	var icon = null;
	if (iconType) {
		icon = button.attachAsset('ball', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.5,
			scaleY: 0.5,
			y: 40,
			tint: iconType === 'splashBall' ? 0xff0066 : iconType === 'sniperBall' ? 0x00ff99 : iconType === 'scatterBall' ? 0xffff00 : iconType === 'ball' ? 0xffffff : 0x00ffff // Fallback
		});
		contentContainer.addChild(icon);
	}
	var labelText = new Text2("".concat(labelPrefix.replace('Speed', 'SPD').replace('Power', 'DMG'), " +").concat(upgrades[upgradeKey]), {
		size: upgradeKey === 'clickDamage' ? 60 : 40,
		fill: 0x000000,
		fontWeight: 'bold'
	});
	labelText.anchor.set(0.5, 0);
	labelText.y = 30; // Move up by 50 pixels
	contentContainer.addChild(labelText);
	if (upgradeKey === 'clickDamage') {
		var clickDamageText = new Text2("+".concat(upgrades.clickDamage), {
			size: 30,
			fill: 0x000000,
			fontWeight: 'bold'
		});
		clickDamageText.anchor.set(0.5, 0);
		clickDamageText.y = 120;
		contentContainer.addChild(clickDamageText);
	}
	var costText = new Text2('$' + (baseCost * upgrades[upgradeKey]).toString(), {
		size: 40,
		fill: 0x000000
	});
	costText.anchor.set(0.5, 0);
	costText.y = 140;
	contentContainer.addChild(costText);
	button.interactive = true;
	button.down = function () {
		// Remove welcome message if it exists
		if (welcomeText && welcomeText.parent) {
			welcomeText.parent.removeChild(welcomeText);
		}
		var cost = baseCost * upgrades[upgradeKey];
		var ballType = upgradeKey.split('Speed')[0].split('Power')[0];
		if (upgradeKey === 'clickDamage') {
			if (score < cost) {
				return;
			}
		} else {
			if (!unlockedTiers[ballType] || score < cost) {
				return;
			}
		}
		score -= cost;
		LK.getSound('click').play();
		upgrades[upgradeKey]++;
		storage.upgrades = Object.assign({}, upgrades);
		costText.setText('$' + (baseCost * upgrades[upgradeKey]).toString());
		labelText.setText("".concat(labelPrefix, " +").concat(upgrades[upgradeKey]));
		scoreTxt.setText('$' + score.toString());
		balls.forEach(function (b) {
			if (b.type === 'normal' && upgradeKey.includes('normal')) {
				b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey];
			} else if (b.type === 'splash' && upgradeKey.includes('splash')) {
				b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey];
			} else if (b.type === 'sniper' && upgradeKey.includes('sniper')) {
				b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey];
			} else if ((b.type === 'scatter' || b.type === 'smallScatter') && upgradeKey.includes('scatter')) {
				b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey];
			}
		});
		if (upgradeKey === 'clickDamage') {
			upgrades.clickDamage = upgrades[upgradeKey];
			storage.upgrades = Object.assign({}, upgrades);
		}
	};
	button.updateState = function () {
		var ballType = upgradeKey.split('Speed')[0].split('Power')[0];
		var isEnabled = upgradeKey === 'clickDamage' ? score >= baseCost * upgrades[upgradeKey] : unlockedTiers[ballType] && (prevTier ? unlockedTiers[prevTier] : true) && score >= baseCost * upgrades[upgradeKey];
		buttonGraphics.tint = isEnabled ? 0x00ffff : 0x666666; // Button background tint
		button.interactive = isEnabled;
		// Update icon tint based on enabled state
		if (icon) {
			if (isEnabled) {
				// Restore original ball color when enabled
				icon.tint = iconType === 'splashBall' ? 0xff0066 : iconType === 'sniperBall' ? 0x00ff99 : iconType === 'scatterBall' ? 0xffff00 : iconType === 'ball' ? 0xffffff : 0x00ffff;
			} else {
				// Grey out when disabled
				icon.tint = 0x666666;
			}
		}
		// Update text color based on enabled state
		labelText.fill = isEnabled ? 0x000000 : 0x666666; // Grey out label text when disabled
		costText.fill = isEnabled ? 0x000000 : 0x666666; // Grey out cost text when disabled
	};
	powerupContainer.addChild(button);
	upgradeButtons[upgradeKey] = button;
}
var buttonWidth = 150;
var spacing = 70;
var totalButtons = 9;
var totalWidth = totalButtons * buttonWidth + (totalButtons - 1) * spacing;
var startX = (GAME_WIDTH - totalWidth) / 2;
createUpgradeButton('Speed', startX, 'normalSpeedCost', 'normalSpeed', 25, 'ball', null);
createUpgradeButton('Power', startX + (buttonWidth + spacing), 'normalPowerCost', 'normalPower', 50, 'ball', null);
createUpgradeButton('Speed', startX + 2 * (buttonWidth + spacing), 'splashSpeedCost', 'splashSpeed', 75, 'splashBall', 'normal');
createUpgradeButton('Power', startX + 3 * (buttonWidth + spacing), 'splashPowerCost', 'splashPower', 75, 'splashBall', 'normal');
createUpgradeButton('Speed', startX + 4 * (buttonWidth + spacing), 'sniperSpeedCost', 'sniperSpeed', 100, 'sniperBall', 'splash');
createUpgradeButton('Power', startX + 5 * (buttonWidth + spacing), 'sniperPowerCost', 'sniperPower', 100, 'sniperBall', 'splash');
createUpgradeButton('Speed', startX + 6 * (buttonWidth + spacing), 'scatterSpeedCost', 'scatterSpeed', 125, 'scatterBall', 'sniper');
createUpgradeButton('Power', startX + 7 * (buttonWidth + spacing), 'scatterPowerCost', 'scatterPower', 125, 'scatterBall', 'sniper');
createUpgradeButton('Click', startX + 8 * (buttonWidth + spacing), 'clickCost', 'clickDamage', 25, null, null);
var upgradeButton = new UpgradeButton();
upgradeButton.x = GAME_WIDTH / 2;
upgradeButton.y = GAME_HEIGHT - 100;
upgradeButton.visible = false;
game.addChild(upgradeButton);
game.setChildIndex(upgradeButton, game.children.length - 1);
hud.visible = false;
function updateButtonStates() {
	for (var type in ballButtons) {
		ballButtons[type].updateState();
	}
	var canPurchaseAny = false;
	for (var key in upgradeButtons) {
		upgradeButtons[key].updateState();
		if (upgradeButtons[key].interactive) {
			canPurchaseAny = true;
		}
	}
	upgradeButton.tint = canPurchaseAny ? 0x00ffff : 0x666666; // Grey out if no power-ups can be purchased
	upgradeButton.interactive = canPurchaseAny;
}
function handleBallBrickCollision(ball, brick) {
	// No need for position/direction logic here; handled in Ball.update
	// Just handle special effects if needed
}
function applySplashDamage(brick, gridSize) {
	var gridX = Math.floor(brick.x / gridSize);
	var gridY = Math.floor(brick.y / gridSize);
	for (var key in brickGrid) {
		brickGrid[key].forEach(function (adjBrick) {
			if (adjBrick && adjBrick.health > 0) {
				var dx = adjBrick.x - brick.x;
				var dy = adjBrick.y - brick.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance <= 200) {
					adjBrick.hit(brick.health > 0 ? brick.health : upgrades.splashPower);
				}
			}
		});
	}
}
function scatterOnImpact(ball) {
	for (var i = 0; i < 4; i++) {
		var smallBall = new Ball('smallScatter');
		smallBall.x = ball.x;
		smallBall.y = ball.y;
		var angle = i / 4 * 2 * Math.PI;
		smallBall.direction.x = Math.cos(angle);
		smallBall.direction.y = Math.sin(angle);
		balls.push(smallBall);
		game.addChild(smallBall);
	}
}
function findNearestBrick(x, y) {
	if (bricks.length === 0) {
		return null;
	}
	return bricks.reduce(function (closest, brick) {
		var dx = brick.x - x;
		var dy = brick.y - y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		return !closest || distance < closest.distance ? {
			brick: brick,
			distance: distance
		} : closest;
	}, null).brick;
}
function isNearBricks(x, y) {
	if (!brickGridBounds) {
		return true;
	}
	var buffer = BALL_RADIUS * 2;
	return x >= brickGridBounds.minX - buffer && x <= brickGridBounds.maxX + buffer && y >= brickGridBounds.minY - buffer && y <= brickGridBounds.maxY + buffer;
}
function createBricks() {
	var config = levelConfig[level] || {};
	var totalBricks = config.totalBricks || 50;
	var baseHitpoints = config.hitpoints || 1; // Base HP from level config
	var gridSize = config.gridSize || 200;
	var pattern = config.pattern || 'grid';
	var spacingX = -15; // Reduced spacing between columns
	var spacingY = 0;
	brickGrid = {};
	bricks = [];
	var cols = 7; // Set to 7 columns
	var rows = Math.ceil(totalBricks / cols);
	var totalWidth = cols * BRICK_WIDTH + (cols - 1) * spacingX;
	var totalHeight = rows * BRICK_HEIGHT + (rows - 1) * spacingY;
	var startX = (GAME_WIDTH - totalWidth) / 2 + BRICK_WIDTH / 2;
	var startY = (GAME_HEIGHT - totalHeight) / 2 + BRICK_HEIGHT / 2;
	var brickCount = 0;
	if (pattern === 'grid') {
		for (var i = 0; i < rows && brickCount < totalBricks; i++) {
			for (var j = 0; j < cols && brickCount < totalBricks; j++) {
				addBrick(startX + j * (BRICK_WIDTH + spacingX), startY + i * (BRICK_HEIGHT + spacingY), baseHitpoints, gridSize);
				brickCount++;
			}
		}
	} else if (pattern === 'staggered') {
		// Staggered pattern with HP gradient from center
		var centerRow = Math.floor(rows / 2); // Approximate center row
		var centerCol = Math.floor(cols / 2); // Approximate center column
		for (var i = 0; i < rows && brickCount < totalBricks; i++) {
			var offsetX = 0; // No offset for staggered grid
			for (var j = 0; j < cols && brickCount < totalBricks; j++) {
				var x = startX + offsetX + j * (BRICK_WIDTH + spacingX);
				var y = startY + i * (BRICK_HEIGHT + spacingY);
				// Calculate distance from center (Manhattan distance for simplicity)
				var rowDistance = Math.abs(i - centerRow);
				var colDistance = Math.abs(j - centerCol);
				var maxDistance = Math.max(centerRow, centerCol); // Max possible distance to edge
				var distance = Math.max(rowDistance, colDistance);
				// HP decreases linearly from center to edge
				// Center gets baseHitpoints, edges get at least 1 HP
				var hitpoints = Math.max(1, Math.round(baseHitpoints * (1 - distance / maxDistance)));
				addBrick(x, y, hitpoints, gridSize);
				brickCount++;
			}
		}
	} else if (pattern === 'clustered') {
		// Clustered pattern: fill from outside in
		var centerRow = Math.floor(rows / 2);
		var centerCol = Math.floor(cols / 2);
		var maxDistance = Math.max(centerRow, centerCol);
		// Create a list of all possible grid positions with their distances
		var positions = [];
		for (var i = 0; i < rows; i++) {
			for (var j = 0; j < cols; j++) {
				var rowDistance = Math.abs(i - centerRow);
				var colDistance = Math.abs(j - centerCol);
				var distance = Math.max(rowDistance, colDistance);
				positions.push({
					i: i,
					j: j,
					distance: distance
				});
			}
		}
		// Sort positions by distance (descending) to fill from outside in
		positions.sort(function (a, b) {
			return b.distance - a.distance;
		});
		// Place bricks up to totalBricks limit
		for (var k = 0; k < positions.length && brickCount < totalBricks; k++) {
			var pos = positions[k];
			var i = pos.i;
			var j = pos.j;
			var distance = pos.distance;
			var x = startX + j * (BRICK_WIDTH + spacingX);
			var y = startY + i * (BRICK_HEIGHT + spacingY);
			// Optional: HP can still vary if desired, higher on edges here
			var hitpoints = Math.max(1, Math.round(baseHitpoints * (distance / maxDistance)));
			addBrick(x, y, hitpoints, gridSize);
			brickCount++;
		}
	} else if (pattern === 'diagonal') {
		// [Unchanged diagonal pattern code]
		var stepX = (GAME_WIDTH - BRICK_WIDTH) / (totalBricks - 1);
		var stepY = GAME_HEIGHT / 3 / (totalBricks - 1);
		for (var i = 0; i < totalBricks; i++) {
			var offsetX = i % 2 === 0 ? BRICK_WIDTH / 4 : 0;
			addBrick(startX + i * stepX + offsetX, startY + i * stepY, baseHitpoints, gridSize);
			brickCount++;
		}
	} else if (pattern === 'sparse') {
		// Sparse pattern: groups of 3 rows with 2-row gaps
		var groupSize = 3; // 3 rows per group
		var gapSize = 2; // 2 rows gap
		var cycleLength = groupSize + gapSize; // Total rows in one cycle (3 + 2 = 5)
		while (brickCount < totalBricks) {
			// Pick a random column
			var col = Math.floor(Math.random() * cols);
			var x = startX + col * (BRICK_WIDTH + spacingX);
			// Pick a random group start row, ensuring space for 3 rows
			var maxGroupStart = rows - groupSize; // Leave room for 3 rows
			var groupStart = Math.floor(Math.random() * Math.floor(maxGroupStart / cycleLength)) * cycleLength;
			// Place bricks in the 3 rows of the group
			for (var rowOffset = 0; rowOffset < groupSize && brickCount < totalBricks; rowOffset++) {
				var row = groupStart + rowOffset;
				if (row >= rows) {
					continue;
				} // Skip if beyond grid bounds
				var y = startY + row * (BRICK_HEIGHT + spacingY);
				// Check for collision to maintain sparsity
				if (!bricks.some(function (b) {
					return b.x === x && b.y === y;
				})) {
					addBrick(x, y, baseHitpoints, gridSize);
					brickCount++;
				}
			}
		}
	}
	brickGridBounds = {
		minX: Math.min.apply(Math, _toConsumableArray2(bricks.map(function (b) {
			return b.x - BRICK_WIDTH / 2;
		}))),
		maxX: Math.max.apply(Math, _toConsumableArray2(bricks.map(function (b) {
			return b.x + BRICK_WIDTH / 2;
		}))),
		minY: Math.min.apply(Math, _toConsumableArray2(bricks.map(function (b) {
			return b.y - BRICK_HEIGHT / 2;
		}))),
		maxY: Math.max.apply(Math, _toConsumableArray2(bricks.map(function (b) {
			return b.y + BRICK_HEIGHT / 2;
		})))
	};
}
function addBrick(x, y, hitpoints, gridSize) {
	var brick = new Brick();
	brick.x = x;
	brick.y = y;
	brick.health = hitpoints;
	brick.maxHealth = hitpoints;
	brick.healthText.setText(brick.health.toString());
	brick.updateTint();
	bricks.push(brick);
	game.addChild(brick);
	var gridX = Math.floor(brick.x / gridSize);
	var gridY = Math.floor(brick.y / gridSize);
	var gridKey = "".concat(gridX, ",").concat(gridY);
	if (!brickGrid[gridKey]) {
		brickGrid[gridKey] = [];
	}
	brickGrid[gridKey].push(brick);
}
function createBall() {
	var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal';
	var ball = new Ball(type);
	var gridBottom = brickGridBounds ? brickGridBounds.maxY + 150 : GAME_HEIGHT * 0.7;
	var spawnFromTop = balls.length % 2 === 0;
	ball.x = GAME_WIDTH / 2 + (Math.random() * 200 - 100);
	ball.y = spawnFromTop ? BALL_RADIUS : GAME_HEIGHT - BALL_RADIUS;
	for (var i = 0; i < bricks.length; i++) {
		if (ball.intersects(bricks[i])) {
			ball.y = spawnFromTop ? BALL_RADIUS : GAME_HEIGHT - BALL_RADIUS;
			break;
		}
	}
	var angle = (Math.random() * 0.5 + 0.25) * Math.PI;
	ball.direction.x = Math.cos(angle);
	ball.direction.y = -Math.sin(angle);
	var magnitude = Math.sqrt(ball.direction.x * ball.direction.x + ball.direction.y * ball.direction.y);
	ball.direction.x /= magnitude;
	ball.direction.y /= magnitude;
	for (var i = 0; i < bricks.length; i++) {
		if (ball.intersects(bricks[i])) {
			ball.y = brickGridBounds.maxY + BALL_RADIUS + 10;
			break;
		}
	}
	balls.push(ball);
	game.addChild(ball);
}
game.update = function () {
	for (var i = 0; i < stars.length; i++) {
		stars[i].update();
	}
	for (var i = balls.length - 1; i >= 0; i--) {
		var ball = balls[i];
		ball.update();
		if (ball.y > GAME_HEIGHT + BALL_RADIUS) {
			ball.destroy();
			balls.splice(i, 1);
		}
	}
	if (bricks.length === 0) {
		if (level === Object.keys(levelConfig).length) {
			showEndScreen();
		} else {
			level += 1;
			storage.level = level;
			levelTxt.setText('Level: ' + level);
			createBricks();
			// Respawn balls from top or bottom
			balls.forEach(function (ball, index) {
				ball.x = GAME_WIDTH / 2 + (Math.random() * 200 - 100);
				ball.y = index % 2 === 0 ? BALL_RADIUS : GAME_HEIGHT - BALL_RADIUS;
				var angle = (Math.random() * 0.5 + 0.25) * Math.PI;
				ball.direction.x = Math.cos(angle);
				ball.direction.y = index % 2 === 0 ? Math.sin(angle) : -Math.sin(angle);
				var magnitude = Math.sqrt(ball.direction.x * ball.direction.x + ball.direction.y * ball.direction.y);
				ball.direction.x /= magnitude;
				ball.direction.y /= magnitude;
			});
		}
	}
	updateButtonStates();
	// Increment playTime by 1 second (assuming update is called 60 times per second)
	// Removed playTime increment to ensure it only prints once
};
game.down = function (x, y, obj) {
	if (!bricks || !Array.isArray(bricks)) {
		return;
	}
	x = Number(x);
	y = Number(y);
	for (var i = 0; i < bricks.length; i++) {
		var brick = bricks[i];
		if (!brick.x || !brick.y || !brick.width || !brick.height) {
			continue;
		}
		if (x >= brick.x - brick.width / 2 && x <= brick.x + brick.width / 2 && y >= brick.y - brick.height / 2 && y <= brick.y + brick.height / 2) {
			brick.hit(upgrades.clickDamage);
			powerupContainer.visible = false;
			LK.getSound('click').play();
			scoreTxt.setText('$' + score.toString());
			storage.score = score;
			return;
		}
	}
};
var stars = [];
for (var i = 0; i < 100; i++) {
	var star = new Star();
	star.x = Math.random() * GAME_WIDTH;
	star.y = Math.random() * GAME_HEIGHT;
	stars.push(star);
	game.addChildAt(star, 0);
}
var gameTitleContainer = new Container();
game.addChild(gameTitleContainer);
var gameTitle = new GameTitle();
gameTitle.x = GAME_WIDTH / 2;
gameTitle.y = GAME_HEIGHT / 2 - 600;
gameTitleContainer.addChild(gameTitle);
function animateTitleColor() {
	tween(gameTitle, {
		tint: 0xff33cc
	}, {
		duration: 2000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(gameTitle, {
				tint: 0x00ff99
			}, {
				duration: 2000,
				easing: tween.easeInOut,
				onFinish: animateTitleColor
			});
		}
	});
}
animateTitleColor();
tween(gameTitle, {
	y: GAME_HEIGHT / 2 - 500
}, {
	duration: 1000,
	easing: tween.bounceOut
});
var startButton = new StartButton();
startButton.x = GAME_WIDTH / 2;
startButton.y = GAME_HEIGHT / 2 + 300;
startButton.tint = 0x00ff99;
game.addChild(startButton);
tween(startButton, {
	y: startButton.y - 20
}, {
	duration: 1000,
	easing: tween.easeInOut,
	onFinish: function onFinish() {
		tween(startButton, {
			y: startButton.y + 20
		}, {
			duration: 1000,
			easing: tween.easeInOut
		});
	}
});
var resetButton = new ResetButton();
resetButton.x = GAME_WIDTH / 2;
resetButton.y = startButton.y + 900;
game.addChild(resetButton);
tween(resetButton, {
	y: resetButton.y - 20
}, {
	duration: 1000,
	easing: tween.easeInOut,
	onFinish: function onFinish() {
		tween(resetButton, {
			y: resetButton.y + 20
		}, {
			duration: 1000,
			easing: tween.easeInOut
		});
	}
});
LK.playMusic('backgroundmusic');
function startGame() {
	startButton.destroy();
	gameTitle.destroy();
	resetButton.visible = false;
	upgradeButton.visible = true;
	hud.visible = true;
	createBricks();
	createBall('normal'); // Add a normal ball to the game on start
	if (score > 0) {
		scoreTxt.setText('$' + score.toString());
	}
	// Check if it's the first time the game is loaded
	if (storage.firstLoad !== true) {
		// Display welcome message
		welcomeText = new Text2('Welcome! Click to cash in and power up!', {
			size: 90,
			fill: 0xffffff
		});
		welcomeText.anchor.set(0.5, 0);
		welcomeText.x = GAME_WIDTH / 2;
		welcomeText.y = GAME_HEIGHT / 2 + 700;
		game.addChild(welcomeText);
		// Set firstLoad to true to prevent showing the message again
		storage.firstLoad = true;
	}
	playTimeInterval = LK.setInterval(function () {
		playTime += 1;
		// Ensure playTime is printed once
		console.log('Time Played:', playTime, 'seconds');
	}, 1000);
	// Load balls from storage
	for (var type in ballQuantities) {
		for (var i = 0; i < ballQuantities[type]; i++) {
			createBall(type);
		}
	}
	updateButtonStates();
	game.update = function () {
		for (var i = 0; i < stars.length; i++) {
			stars[i].update();
		}
		for (var i = balls.length - 1; i >= 0; i--) {
			var ball = balls[i];
			ball.update();
			if (ball.y > GAME_HEIGHT + BALL_RADIUS) {
				ball.destroy();
				balls.splice(i, 1);
			}
		}
		if (bricks.length === 0) {
			if (level === Object.keys(levelConfig).length) {
				showEndScreen();
			} else {
				level += 1;
				storage.level = level;
				levelTxt.setText('Level: ' + level);
				createBricks();
			}
		}
		updateButtonStates();
	};
}
game.update = function () {
	for (var i = 0; i < stars.length; i++) {
		stars[i].update();
	}
}; ===================================================================
--- original.js
+++ change.js
@@ -970,9 +970,9 @@
 	labelText.anchor.set(0.5, 0);
 	labelText.y = 30; // Move up by 50 pixels
 	contentContainer.addChild(labelText);
 	if (upgradeKey === 'clickDamage') {
-		var clickDamageText = new Text2("Damage: ".concat(upgrades.clickDamage), {
+		var clickDamageText = new Text2("+".concat(upgrades.clickDamage), {
 			size: 30,
 			fill: 0x000000,
 			fontWeight: 'bold'
 		});