User prompt
Put the misses counter above the lives
User prompt
Change the text High Score to Your High Score. Move the entire text 20 pixels below current positio
User prompt
Move the high score to the bottom left of the screen
User prompt
Make the button and text bigger and mo e the button To the bottom right of the screen
User prompt
Change leaderboard icon to a button that says Leaderboard in capital letters
User prompt
High score is not visible
User prompt
The high score is not visible. Make ot 100px from screen bottom
User prompt
High score is not visible. Let it be on the bottom left just below the boundary line
User prompt
Move the Users high score to the bottom right of the screen. Label it Your high score:
User prompt
Move the top line 300px from acreen top
User prompt
Let the top line demarcating, the top HUD be visible. Also elements like the lives and the leaderboard button, let them be visible in the HUD.
User prompt
Let the top HUD be opaque to hide fruits behind it.
User prompt
Let the rop hud be opaque ao that druits disappear behind it.
User prompt
Let the top line be 200px from top of acreen and bottom li e 200px from bottom
User prompt
Draw a thick line below the hud at the top and 100 px from the bottom to demarcate the play area
User prompt
Let user have extra lives. Start with three lives at beginning of game. Clicking a bomb takes a life. Show how many lives left as small red hearts
User prompt
Show level 2 boss when user gets to 50
User prompt
New level starts as soon as a boss is defeated
User prompt
Please fix the bug: 'levelText.style is undefined' in or related to this line: 'levelText.style.size = 180;' Line Number: 714
User prompt
Show Level label when a new level begins.
User prompt
Let boss 2 appear when user has received 50 points.
User prompt
Make the bosses very large
User prompt
Make the bosses bigger versions of the fruit. Make the 300 px width
User prompt
Let there be 4 levels each with its own boss which is a larger version of the most recently introduced fruit for that level. Write the Level label and number at the beginning of each level e.g Level 1, Level 2 etc
User prompt
use the players upit username for the leaderboard if they are logged in, if not, use Anon βͺπ‘ Consider importing and using the following plugins: @upit/storage.v1
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Blade = Container.expand(function () {
	var self = Container.call(this);
	self.active = false;
	self.points = [];
	self.maxPoints = 10;
	self.trail = [];
	for (var i = 0; i < self.maxPoints; i++) {
		var trailPart = self.attachAsset('blade', {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0
		});
		self.trail.push(trailPart);
	}
	self.update = function () {
		// Update trail visuals
		for (var i = 0; i < self.trail.length; i++) {
			if (i < self.points.length) {
				var point = self.points[i];
				var trailPart = self.trail[i];
				trailPart.x = point.x;
				trailPart.y = point.y;
				trailPart.alpha = 0; // Keep blade invisible
				if (i > 0) {
					var prevPoint = self.points[i - 1];
					var angle = Math.atan2(point.y - prevPoint.y, point.x - prevPoint.x);
					trailPart.rotation = angle;
				}
			} else {
				self.trail[i].alpha = 0;
			}
		}
	};
	self.addPoint = function (x, y) {
		self.points.unshift({
			x: x,
			y: y
		});
		if (self.points.length > self.maxPoints) {
			self.points.pop();
		}
	};
	self.reset = function () {
		self.points = [];
		self.active = false;
		for (var i = 0; i < self.trail.length; i++) {
			self.trail[i].alpha = 0;
		}
	};
	return self;
});
var Boss = Container.expand(function (level) {
	var self = Container.call(this);
	// Boss properties
	self.level = level || 1;
	self.health = 5 + self.level; // Health increases with level
	self.maxHealth = self.health;
	self.width = 800;
	self.height = 800;
	self.active = false;
	self.attackTimer = 0;
	self.attackInterval = 3000 - self.level * 250; // Attacks more frequently with higher levels
	// Determine boss type based on level
	var bossType = BOSS_FRUIT_TYPES[self.level - 1] || 'strawberry';
	// Create boss visual
	var bossGraphic = self.attachAsset(bossType, {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	// Health bar background
	var healthBarBg = new Container();
	healthBarBg.x = -200;
	healthBarBg.y = -450;
	var healthBarBack = LK.getAsset('blade', {
		anchorX: 0,
		anchorY: 0.5,
		width: 400,
		height: 30
	});
	healthBarBack.tint = 0x333333;
	// Health bar fill
	var healthBarFill = LK.getAsset('blade', {
		anchorX: 0,
		anchorY: 0.5,
		width: 400,
		height: 30
	});
	healthBarFill.tint = 0xFF0000;
	healthBarBg.addChild(healthBarBack);
	healthBarBg.addChild(healthBarFill);
	self.addChild(healthBarBg);
	self.healthBar = healthBarFill;
	// Boss movement
	self.vx = 2 + self.level * 0.5; // Speed increases with level
	self.targetX = GAME_WIDTH / 2;
	self.activate = function () {
		self.active = true;
		self.health = self.maxHealth;
		self.x = GAME_WIDTH / 2;
		self.y = GAME_HEIGHT / 3;
		self.updateHealthBar();
	};
	self.updateHealthBar = function () {
		self.healthBar.width = self.health / self.maxHealth * 400;
	};
	self.hit = function () {
		if (!self.active) {
			return;
		}
		self.health--;
		self.updateHealthBar();
		// Flash the boss red
		bossGraphic.tint = 0xFF0000;
		LK.setTimeout(function () {
			bossGraphic.tint = 0xFFFFFF;
		}, 200);
		// Check if boss is defeated
		if (self.health <= 0) {
			self.defeat();
			return true;
		}
		return false;
	};
	self.defeat = function () {
		self.active = false;
		// Make the health bar transparent
		healthBarBg.alpha = 0;
		// Create explosion effect
		bossGraphic.tint = 0xFFFFFF;
		tween(bossGraphic, {
			alpha: 0,
			scaleX: 3,
			scaleY: 3,
			rotation: Math.PI * 2
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Add bonus points (increased for higher level bosses)
				var bonus = 25 * self.level;
				LK.setScore(LK.getScore() + bonus);
				scoreTxt.setText(LK.getScore());
				LK.effects.flashScreen(0x00FF00, 500);
			}
		});
		// Play explosion sound
		LK.getSound('explosion').play();
	};
	self.throwFruit = function () {
		if (!self.active) {
			return;
		}
		// Launch multiple bombs at the player
		var bombCount = Math.floor(Math.random() * self.level) + 1; // More bombs at higher levels
		for (var i = 0; i < bombCount; i++) {
			var fruit = new Fruit('bomb');
			// Generate random position on the boss perimeter
			var spawnAngle = Math.random() * Math.PI * 2; // Full 360 degrees
			var spawnRadius = self.width / 3; // Radius to spawn from (edge of boss)
			// Position the bomb on the perimeter
			fruit.x = self.x + Math.cos(spawnAngle) * spawnRadius;
			fruit.y = self.y + Math.sin(spawnAngle) * spawnRadius;
			// Aim outward from the spawn point with spread
			var angle = spawnAngle + Math.PI + (Math.random() - 0.5); // Outward direction with randomness
			var speed = 3 + Math.random() * 2 + self.level * 0.5; // Faster bombs at higher levels
			fruit.vx = Math.cos(angle) * speed;
			fruit.vy = Math.sin(angle) * speed;
			game.addChild(fruit);
			fruits.push(fruit);
		}
	};
	self.update = function (delta) {
		if (!self.active) {
			return;
		}
		// Move boss back and forth
		if (Math.abs(self.x - self.targetX) < 10) {
			self.targetX = Math.random() * (GAME_WIDTH - 400) + 200;
		}
		var dirX = self.targetX - self.x;
		self.x += dirX / Math.abs(dirX) * self.vx;
		// Attack on timer
		var currentTime = Date.now();
		if (currentTime >= self.attackTimer) {
			self.throwFruit();
			self.attackTimer = currentTime + self.attackInterval;
		}
	};
	self.down = function (x, y, obj) {
		// Allow clicking on boss to damage it
		if (self.active) {
			self.hit();
		}
	};
	return self;
});
var Fruit = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type || 'apple';
	self.sliced = false;
	self.width = 0;
	self.height = 0;
	self.points = 0;
	self.baseSpeed = 0;
	var fruitGraphics;
	switch (self.type) {
		case 'watermelon':
			self.width = 480;
			self.height = 480;
			self.points = 5;
			self.baseSpeed = 1.6; // Faster base speed
			break;
		case 'apple':
			self.width = 360;
			self.height = 360;
			self.points = 4;
			self.baseSpeed = 1.7; // Faster base speed
			break;
		case 'orange':
			self.width = 320;
			self.height = 320;
			self.points = 3;
			self.baseSpeed = 1.8; // Faster base speed
			break;
		case 'kiwi':
			self.width = 240;
			self.height = 240;
			self.points = 2;
			self.baseSpeed = 2.0; // Faster base speed
			break;
		case 'strawberry':
			self.width = 200;
			self.height = 200;
			self.points = 1;
			self.baseSpeed = 2.2; // Faster base speed
			break;
		case 'bomb':
			self.width = 320;
			self.height = 320;
			self.points = -10;
			self.baseSpeed = 1.7; // Faster base speed
			break;
	}
	fruitGraphics = self.attachAsset(self.type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0.01; // Reduced gravity to make fruits go higher
	self.rotationSpeed = (Math.random() - 0.5) * 0.018; // Slightly faster rotation
	self.init = function (x, y, direction) {
		self.x = x;
		self.y = y;
		var angle = direction * (Math.PI / 4) + Math.random() * Math.PI / 8 - Math.PI / 16;
		var currentLevel = Math.floor(LK.getScore() / 50) + 1;
		var levelMultiplier = 1 + (currentLevel - 1) * 0.1; // 10% increase per level
		var speed = (self.baseSpeed + Math.random() * 0.8) * levelMultiplier; // Further reduced random speed component
		self.vx = Math.cos(angle) * speed * 1.15; // Slightly faster horizontal movement
		self.vy = -Math.sin(angle) * speed - 8; // Higher initial upward velocity
	};
	self.slice = function () {
		if (self.sliced || self.type === 'bomb') {
			return;
		}
		self.sliced = true;
		// Create explosive flash effect
		fruitGraphics.tint = 0xFFFFFF;
		fruitGraphics.alpha = 1;
		// Animate explosive flash effect with scaling
		tween(fruitGraphics, {
			alpha: 0,
			scaleX: 1.5,
			scaleY: 1.5
		}, {
			duration: 300,
			easing: tween.easeOut,
			onUpdate: function onUpdate(progress) {
				// Create a pulsing effect with rotation during explosion
				fruitGraphics.rotation += 0.1;
			},
			onFinish: function onFinish() {
				// Clean up after animation
				fruitGraphics.tint = 0xFFFFFF;
				fruitGraphics.scaleX = 1;
				fruitGraphics.scaleY = 1;
			}
		});
		// Play slice sound
		LK.getSound('slice').play();
		return self.points;
	};
	self.down = function (x, y, obj) {
		if (!self.sliced) {
			// Slice the fruit when clicked
			var points = self.slice();
			// Check if it's a bomb
			if (self.type === 'bomb') {
				// Game over when clicking a bomb
				LK.getSound('explosion').play();
				LK.effects.flashScreen(0xFF0000, 800);
				// Update high score if current score is higher
				if (LK.getScore() > highScore) {
					highScore = LK.getScore();
					storage.highScore = highScore;
				}
				// Add score to global leaderboard
				addScoreToLeaderboard(LK.getScore());
				// Pass the current score and high score to game over display
				LK.showGameOver({
					score: LK.getScore(),
					highScore: highScore
				});
				return;
			}
			// Add points to score
			LK.setScore(LK.getScore() + points);
			scoreTxt.setText(LK.getScore());
			// Update combo
			comboCount++;
			comboTimer = Date.now() + comboTimeout;
		}
	};
	self.update = function () {
		if (!self.sliced) {
			// Update whole fruit
			self.vy += self.gravity;
			self.x += self.vx;
			self.y += self.vy;
			self.rotation += self.rotationSpeed;
			// Bounce off walls if not sliced
			if (self.x < self.width / 2 && self.vx < 0) {
				self.vx = -self.vx * 0.8; // Bounce with some energy loss
				self.x = self.width / 2;
			}
			if (self.x > GAME_WIDTH - self.width / 2 && self.vx > 0) {
				self.vx = -self.vx * 0.8; // Bounce with some energy loss
				self.x = GAME_WIDTH - self.width / 2;
			}
		} else {
			// No update for sliced fruit since we're just flashing and fading them
		}
	};
	self.isOffScreen = function () {
		return self.y > 2732 + self.height || self.x > GAME_WIDTH + self.width;
	};
	return self;
});
var Leaderboard = Container.expand(function () {
	var self = Container.call(this);
	self.visible = false;
	// Background panel
	var panel = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 1500,
		height: 1800
	});
	panel.tint = 0x2c3e50;
	panel.alpha = 0.9;
	// Title
	var title = new Text2('GLOBAL LEADERBOARD', {
		size: 100,
		fill: 0xFFFFFF
	});
	title.anchor.set(0.5, 0);
	title.y = -800;
	self.addChild(title);
	// Scores container
	var scoresContainer = new Container();
	scoresContainer.y = -650;
	self.addChild(scoresContainer);
	self.scoresContainer = scoresContainer;
	// Close button
	var closeBtn = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 80,
		height: 80
	});
	closeBtn.tint = 0xFF0000;
	closeBtn.x = 700;
	closeBtn.y = -800;
	// X symbol on close button
	var closeX1 = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 40,
		height: 8
	});
	closeX1.tint = 0xFFFFFF;
	closeX1.rotation = Math.PI / 4;
	closeX1.x = 700;
	closeX1.y = -800;
	var closeX2 = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 40,
		height: 8
	});
	closeX2.tint = 0xFFFFFF;
	closeX2.rotation = -Math.PI / 4;
	closeX2.x = 700;
	closeX2.y = -800;
	// Close button interaction
	closeBtn.interactive = true;
	closeBtn.down = function (x, y, obj) {
		self.hide();
	};
	// Show leaderboard
	self.show = function (scores) {
		self.visible = true;
		self.updateScores(scores);
	};
	// Hide leaderboard
	self.hide = function () {
		self.visible = false;
	};
	// Update scores display
	self.updateScores = function (scores) {
		// Clear existing score entries
		while (scoresContainer.children.length > 0) {
			scoresContainer.removeChildAt(0);
		}
		// Add score entries
		for (var i = 0; i < scores.length; i++) {
			var entry = scores[i];
			var yPos = i * 120;
			// Rank
			var rank = new Text2(i + 1 + '.', {
				size: 80,
				fill: 0xFFFFFF
			});
			rank.anchor.set(1, 0);
			rank.x = -600;
			rank.y = yPos;
			scoresContainer.addChild(rank);
			// Username
			var username = entry.username || "Player";
			var usernameText = new Text2(username, {
				size: 60,
				fill: 0xFFFFFF
			});
			usernameText.anchor.set(0, 0);
			usernameText.x = -500;
			usernameText.y = yPos;
			scoresContainer.addChild(usernameText);
			// Score value
			var scoreText = new Text2(entry.score.toString(), {
				size: 80,
				fill: 0xFFD700
			});
			scoreText.anchor.set(0, 0);
			scoreText.x = 0;
			scoreText.y = yPos;
			scoresContainer.addChild(scoreText);
		}
		// Add message if no scores
		if (scores.length === 0) {
			var noScores = new Text2("No scores yet!", {
				size: 80,
				fill: 0xFFFFFF
			});
			noScores.anchor.set(0.5, 0);
			noScores.y = 100;
			scoresContainer.addChild(noScores);
		}
	};
	return self;
});
var LeaderboardButton = Container.expand(function () {
	var self = Container.call(this);
	// Create button background
	var buttonBg = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 80,
		height: 80
	});
	buttonBg.tint = 0x3498db;
	// Create button icon (simple trophy shape)
	var icon = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 40,
		height: 50
	});
	icon.tint = 0xFFD700;
	icon.y = -5;
	// Create button base
	var base = self.attachAsset('blade', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 30,
		height: 10
	});
	base.tint = 0xFFD700;
	base.y = 25;
	// Button interaction
	self.down = function (x, y, obj) {
		// Scale down effect on press
		tween(self, {
			scaleX: 0.9,
			scaleY: 0.9
		}, {
			duration: 100
		});
		// Show leaderboard
		showLeaderboard();
	};
	self.up = function (x, y, obj) {
		// Scale back to normal on release
		tween(self, {
			scaleX: 1,
			scaleY: 1
		}, {
			duration: 100
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x3498DB
});
/**** 
* Game Code
****/ 
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var SPAWN_INTERVAL_MIN = 1000; // Decreased spawn interval minimum for more frequent spawning
var SPAWN_INTERVAL_MAX = 2000; // Decreased spawn interval maximum for more frequent spawning
var SPAWN_COUNT_MIN = 1;
var SPAWN_COUNT_MAX = 2; // Increased to spawn more fruits at once
var FRUIT_TYPES = ['watermelon', 'apple', 'orange', 'kiwi', 'strawberry'];
var BOSS_FRUIT_TYPES = ['strawberry', 'kiwi', 'orange', 'apple']; // Boss fruit for each level
var LEVEL_THRESHOLDS = [5, 50, 150, 300]; // Score thresholds for each level boss
var LEVEL_FRUITS = [['strawberry'],
// Level 1 fruits
['strawberry', 'kiwi'],
// Level 2 fruits
['strawberry', 'kiwi', 'orange'],
// Level 3 fruits
['strawberry', 'kiwi', 'orange', 'apple'] // Level 4 fruits
];
var BOMB_PROBABILITY = 0.2; // Increased bomb probability
// Game variables
var fruits = [];
var blade = null;
var boss = null;
var lastSpawnTime = 0;
var nextSpawnTime = 0;
var gameActive = true;
var comboCount = 0;
var comboTimer = 0;
var comboTimeout = 1000; // ms to reset combo
var currentLevel = 1;
var bossActivated = false;
var nextLevelNotified = false;
var showingLevelText = false;
var levelTextTimer = 0;
var levelText; // Level notification text
var missedFruits = 0; // Counter for missed fruits
var missedText; // Text to display missed count
var highScore = storage.highScore || 0; // Get high score from storage or default to 0
var highScoreText; // Text to display high score
var leaderboardButton; // Button to open leaderboard
var leaderboard; // Leaderboard UI component
// Parse leaderboard scores from storage or use empty array if none exists
var leaderboardScores = [];
if (storage.leaderboardScores) {
	var scoresArray = storage.leaderboardScores.split(';');
	for (var i = 0; i < scoresArray.length; i++) {
		if (scoresArray[i]) {
			var parts = scoresArray[i].split(',');
			var scoreObj = {
				score: parseInt(parts[0])
			};
			if (parts.length > 1) {
				scoreObj.username = parts[1];
			}
			leaderboardScores.push(scoreObj);
		}
	}
} // Global leaderboard data
var playerName = storage.playerName || "Player"; // Get saved player name or use default
// UI elements
var scoreTxt;
var comboTxt;
function setupGame() {
	// Prompt for player name if not already stored
	if (!storage.playerName) {
		var defaultName = "Player";
		// Skip popup for now and just use default name
		// LK.showPopup is not available in the current version
		storage.playerName = defaultName;
		playerName = defaultName;
	}
	// Create blade
	blade = game.addChild(new Blade());
	// Create boss but don't activate it yet
	boss = game.addChild(new Boss(currentLevel));
	// Set up score display
	scoreTxt = new Text2('0', {
		size: 100,
		fill: 0xFFFFFF
	});
	scoreTxt.anchor.set(0.5, 0);
	scoreTxt.y = 30;
	LK.gui.top.addChild(scoreTxt);
	// Set up combo display
	comboTxt = new Text2('', {
		size: 60,
		fill: 0xFFFF00
	});
	comboTxt.anchor.set(0.5, 0);
	comboTxt.y = 140;
	comboTxt.alpha = 0;
	LK.gui.top.addChild(comboTxt);
	// Set up level text display
	levelText = new Text2('Level 1', {
		size: 120,
		fill: 0xFFFFFF
	});
	levelText.anchor.set(0.5, 0.5);
	levelText.x = GAME_WIDTH / 2;
	levelText.y = GAME_HEIGHT / 2;
	levelText.alpha = 0;
	game.addChild(levelText);
	// Set up missed fruits display
	missedText = new Text2('Missed: 0/10', {
		size: 60,
		fill: 0xFF0000
	});
	missedText.anchor.set(0, 0);
	missedText.x = 50;
	missedText.y = 30;
	LK.gui.topLeft.addChild(missedText);
	// Set up high score display
	highScoreText = new Text2('High Score: ' + highScore, {
		size: 60,
		fill: 0xFFFFFF
	});
	highScoreText.anchor.set(0, 0);
	highScoreText.x = 50;
	highScoreText.y = 100; // Position below the missed counter
	LK.gui.topLeft.addChild(highScoreText);
	// Set up leaderboard button
	leaderboardButton = new LeaderboardButton();
	leaderboardButton.x = GAME_WIDTH - 80;
	leaderboardButton.y = 80;
	game.addChild(leaderboardButton);
	// Create and position leaderboard UI
	leaderboard = new Leaderboard();
	leaderboard.x = GAME_WIDTH / 2;
	leaderboard.y = GAME_HEIGHT / 2;
	leaderboard.visible = false;
	game.addChild(leaderboard);
	// Set initial spawn time
	nextSpawnTime = Date.now() + Math.random() * (SPAWN_INTERVAL_MAX - SPAWN_INTERVAL_MIN) + SPAWN_INTERVAL_MIN;
	// Play background music
	LK.playMusic('gameMusic');
	// Reset level tracking
	currentLevel = 1;
	bossActivated = false;
	nextLevelNotified = false;
	LK.setScore(0);
	missedFruits = 0;
	// Show level 1 text at start
	showLevelText(1);
}
// Function to display level text
function showLevelText(level) {
	levelText.setText('Level ' + level);
	levelText.alpha = 0;
	showingLevelText = true;
	// Animate the level text
	tween(levelText, {
		alpha: 1
	}, {
		duration: 500,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			// Hold the text visible for a moment
			levelTextTimer = Date.now() + 2000;
		}
	});
}
function spawnFruits() {
	var count = Math.floor(Math.random() * (SPAWN_COUNT_MAX - SPAWN_COUNT_MIN + 1)) + SPAWN_COUNT_MIN;
	// Get appropriate fruit types for current level
	var availableFruits = LEVEL_FRUITS[currentLevel - 1] || ['strawberry'];
	for (var i = 0; i < count; i++) {
		var isBomb = Math.random() < BOMB_PROBABILITY;
		var type = isBomb ? 'bomb' : availableFruits[Math.floor(Math.random() * availableFruits.length)];
		var fruit = new Fruit(type);
		// Determine flight pattern
		var pattern = Math.random();
		if (pattern < 0.5) {
			// Horizontal flight from left to right
			var x = -fruit.width;
			var y = Math.random() * (GAME_HEIGHT / 3) + 300; // Higher position range
			fruit.x = x;
			fruit.y = y;
			fruit.vx = fruit.baseSpeed + Math.random() * 2.5; // Slightly faster
			fruit.vy = -Math.random() * 2; // Add slight upward movement
		} else {
			// Vertical drop
			var x = Math.random() * (GAME_WIDTH - 200) + 100;
			var direction = Math.random(); // Random direction between 0 and 1
			fruit.init(x, GAME_HEIGHT, direction);
		}
		game.addChild(fruit);
		fruits.push(fruit);
	}
	// Schedule next spawn
	nextSpawnTime = Date.now() + Math.random() * (SPAWN_INTERVAL_MAX - SPAWN_INTERVAL_MIN) + SPAWN_INTERVAL_MIN;
}
function updateCombo() {
	if (comboCount > 1) {
		comboTxt.setText('COMBO x' + comboCount + '!');
		comboTxt.alpha = 1;
		// Add combo bonus points
		LK.setScore(LK.getScore() + comboCount * 2);
		// Play combo sound
		LK.getSound('combo').play();
		// Animate combo text
		tween(comboTxt, {
			alpha: 0
		}, {
			duration: 1000,
			easing: tween.easeOut
		});
	}
	comboCount = 0;
}
function handleBladeCollisions() {
	if (!blade.active || blade.points.length < 2) {
		return;
	}
	var startPoint = blade.points[0];
	var endPoint = blade.points[1];
	// Check boss collision if active
	if (boss && boss.active && lineIntersectsCircle(startPoint.x, startPoint.y, endPoint.x, endPoint.y, boss.x, boss.y, boss.width / 3)) {
		// Hit the boss
		var defeated = boss.hit();
		// Play slice sound
		LK.getSound('slice').play();
		// Update combo
		comboCount++;
		comboTimer = Date.now() + comboTimeout;
	}
	for (var i = 0; i < fruits.length; i++) {
		var fruit = fruits[i];
		if (!fruit.sliced && lineIntersectsCircle(startPoint.x, startPoint.y, endPoint.x, endPoint.y, fruit.x, fruit.y, fruit.width / 2)) {
			if (fruit.type === 'bomb') {
				// Game over when hitting a bomb
				LK.getSound('explosion').play();
				LK.effects.flashScreen(0xFF0000, 800);
				// Update high score if current score is higher
				if (LK.getScore() > highScore) {
					highScore = LK.getScore();
					storage.highScore = highScore;
				}
				// Add score to global leaderboard
				addScoreToLeaderboard(LK.getScore());
				// Pass the current score and high score to game over display
				LK.showGameOver({
					score: LK.getScore(),
					highScore: highScore
				});
				return;
			}
			// Slice the fruit
			var points = fruit.slice();
			LK.setScore(LK.getScore() + points);
			scoreTxt.setText(LK.getScore());
			// Play slice sound
			LK.getSound('slice').play();
			// Update combo
			comboCount++;
			comboTimer = Date.now() + comboTimeout;
		}
	}
}
function lineIntersectsCircle(x1, y1, x2, y2, cx, cy, r) {
	// Find the closest point on the line segment to the circle center
	var dx = x2 - x1;
	var dy = y2 - y1;
	var len = Math.sqrt(dx * dx + dy * dy);
	// Normalize direction vector
	dx /= len;
	dy /= len;
	// Vector from line start to circle center
	var vx = cx - x1;
	var vy = cy - y1;
	// Project this vector onto the line direction
	var projection = vx * dx + vy * dy;
	// Clamp projection to line segment
	projection = Math.max(0, Math.min(len, projection));
	// Find the closest point on the line segment
	var closestX = x1 + projection * dx;
	var closestY = y1 + projection * dy;
	// Check if this point is within the circle
	var distanceSquared = (cx - closestX) * (cx - closestX) + (cy - closestY) * (cy - closestY);
	return distanceSquared <= r * r;
}
// Show the leaderboard UI
function showLeaderboard() {
	if (leaderboard) {
		leaderboard.show(leaderboardScores);
	}
}
// Add a score to the leaderboard
function addScoreToLeaderboard(score) {
	// Only add score if it's greater than 0
	if (score <= 0) {
		return;
	}
	// Add new score to leaderboard with Upit username or 'Anon'
	var username = LK.getUptUsername ? LK.getUptUsername() : 'Anon';
	leaderboardScores.push({
		score: score,
		username: username
	});
	// Sort leaderboard by score (highest first)
	leaderboardScores.sort(function (a, b) {
		return b.score - a.score;
	});
	// Limit to top 10 scores
	if (leaderboardScores.length > 10) {
		leaderboardScores = leaderboardScores.slice(0, 10);
	}
	// Save to storage - convert to simple string format to avoid undefined JSON error
	var scoresString = '';
	for (var i = 0; i < leaderboardScores.length; i++) {
		scoresString += leaderboardScores[i].score + "," + (leaderboardScores[i].username || "Player");
		if (i < leaderboardScores.length - 1) {
			scoresString += ';';
		}
	}
	storage.leaderboardScores = scoresString;
}
;
// Game update function
game.update = function () {
	var currentTime = Date.now();
	// Handle level text animation
	if (showingLevelText && currentTime > levelTextTimer && levelText.alpha > 0) {
		tween(levelText, {
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				showingLevelText = false;
			}
		});
	}
	// Check if we should activate the boss fight based on score
	if (currentLevel <= 4 && LK.getScore() >= LEVEL_THRESHOLDS[currentLevel - 1] && !bossActivated && !nextLevelNotified) {
		bossActivated = true;
		// Create a new boss for the current level
		if (boss) {
			boss.destroy();
		}
		boss = game.addChild(new Boss(currentLevel));
		boss.activate();
		// Clear existing fruits during boss transition
		for (var i = fruits.length - 1; i >= 0; i--) {
			fruits[i].destroy();
			fruits.splice(i, 1);
		}
	}
	// Only spawn normal fruits if we're not in a boss fight
	if (currentTime >= nextSpawnTime && (!bossActivated || !boss.active)) {
		spawnFruits();
	}
	// Update all fruits
	for (var i = fruits.length - 1; i >= 0; i--) {
		var fruit = fruits[i];
		fruit.update();
		// Remove fruits that are off-screen
		if (fruit.isOffScreen()) {
			// Only count missed fruits that aren't bombs or already sliced
			if (!fruit.sliced && fruit.type !== 'bomb') {
				missedFruits++;
				missedText.setText('Missed: ' + missedFruits + '/10');
				// Game over if 10 fruits are missed
				if (missedFruits >= 10) {
					LK.effects.flashScreen(0xFF0000, 800);
					// Update high score if current score is higher
					if (LK.getScore() > highScore) {
						highScore = LK.getScore();
						storage.highScore = highScore;
					}
					// Add score to global leaderboard
					addScoreToLeaderboard(LK.getScore());
					// Pass the current score and high score to game over display
					LK.showGameOver({
						score: LK.getScore(),
						highScore: highScore
					});
				}
			}
			fruit.destroy();
			fruits.splice(i, 1);
		}
	}
	// Check for blade collisions
	handleBladeCollisions();
	// Update blade
	blade.update();
	// Update boss if active
	if (boss && boss.active) {
		boss.update(1 / 60); // Pass approximate delta time
	}
	// If boss was defeated, move to next level
	if (bossActivated && boss && !boss.active) {
		bossActivated = false;
		nextLevelNotified = false;
		// Move to next level if we haven't reached level 4 yet
		if (currentLevel < 4) {
			currentLevel++;
			// Show level notification
			showLevelText(currentLevel);
		} else if (currentLevel === 4) {
			// Player has beaten all levels
			LK.effects.flashScreen(0x00FF00, 800);
			// Show "You Win" screen after completing all levels
			if (LK.getScore() > highScore) {
				highScore = LK.getScore();
				storage.highScore = highScore;
			}
			// Add score to global leaderboard
			addScoreToLeaderboard(LK.getScore());
			// Show you win screen
			LK.showYouWin({
				score: LK.getScore(),
				highScore: highScore
			});
		}
	}
	// Check combo timer
	if (comboCount > 0 && Date.now() > comboTimer) {
		updateCombo();
	}
};
// Handle touch/mouse events
game.down = function (x, y, obj) {
	blade.active = true;
	blade.reset();
	blade.addPoint(x, y);
};
game.move = function (x, y, obj) {
	if (blade.active) {
		blade.addPoint(x, y);
		handleBladeCollisions();
	}
};
game.up = function (x, y, obj) {
	blade.active = false;
};
// Start the game
setupGame(); ===================================================================
--- original.js
+++ change.js
@@ -57,20 +57,23 @@
 		}
 	};
 	return self;
 });
-var Boss = Container.expand(function () {
+var Boss = Container.expand(function (level) {
 	var self = Container.call(this);
 	// Boss properties
-	self.health = 5;
-	self.maxHealth = 5;
+	self.level = level || 1;
+	self.health = 5 + self.level; // Health increases with level
+	self.maxHealth = self.health;
 	self.width = 800;
 	self.height = 800;
 	self.active = false;
 	self.attackTimer = 0;
-	self.attackInterval = 3000; // Increased time between attacks for less frequent bombs
+	self.attackInterval = 3000 - self.level * 250; // Attacks more frequently with higher levels
+	// Determine boss type based on level
+	var bossType = BOSS_FRUIT_TYPES[self.level - 1] || 'strawberry';
 	// Create boss visual
-	var bossGraphic = self.attachAsset('watermelon', {
+	var bossGraphic = self.attachAsset(bossType, {
 		anchorX: 0.5,
 		anchorY: 0.5,
 		scaleX: 2,
 		scaleY: 2
@@ -98,9 +101,9 @@
 	healthBarBg.addChild(healthBarFill);
 	self.addChild(healthBarBg);
 	self.healthBar = healthBarFill;
 	// Boss movement
-	self.vx = 2;
+	self.vx = 2 + self.level * 0.5; // Speed increases with level
 	self.targetX = GAME_WIDTH / 2;
 	self.activate = function () {
 		self.active = true;
 		self.health = self.maxHealth;
@@ -143,10 +146,11 @@
 		}, {
 			duration: 1000,
 			easing: tween.easeOut,
 			onFinish: function onFinish() {
-				// Add bonus points
-				LK.setScore(LK.getScore() + 25);
+				// Add bonus points (increased for higher level bosses)
+				var bonus = 25 * self.level;
+				LK.setScore(LK.getScore() + bonus);
 				scoreTxt.setText(LK.getScore());
 				LK.effects.flashScreen(0x00FF00, 500);
 			}
 		});
@@ -157,9 +161,9 @@
 		if (!self.active) {
 			return;
 		}
 		// Launch multiple bombs at the player
-		var bombCount = Math.floor(Math.random() * 2) + 1; // Spawn 1-2 bombs at once
+		var bombCount = Math.floor(Math.random() * self.level) + 1; // More bombs at higher levels
 		for (var i = 0; i < bombCount; i++) {
 			var fruit = new Fruit('bomb');
 			// Generate random position on the boss perimeter
 			var spawnAngle = Math.random() * Math.PI * 2; // Full 360 degrees
@@ -168,9 +172,9 @@
 			fruit.x = self.x + Math.cos(spawnAngle) * spawnRadius;
 			fruit.y = self.y + Math.sin(spawnAngle) * spawnRadius;
 			// Aim outward from the spawn point with spread
 			var angle = spawnAngle + Math.PI + (Math.random() - 0.5); // Outward direction with randomness
-			var speed = 3 + Math.random() * 2; // Faster bombs
+			var speed = 3 + Math.random() * 2 + self.level * 0.5; // Faster bombs at higher levels
 			fruit.vx = Math.cos(angle) * speed;
 			fruit.vy = Math.sin(angle) * speed;
 			game.addChild(fruit);
 			fruits.push(fruit);
@@ -544,8 +548,18 @@
 var SPAWN_INTERVAL_MAX = 2000; // Decreased spawn interval maximum for more frequent spawning
 var SPAWN_COUNT_MIN = 1;
 var SPAWN_COUNT_MAX = 2; // Increased to spawn more fruits at once
 var FRUIT_TYPES = ['watermelon', 'apple', 'orange', 'kiwi', 'strawberry'];
+var BOSS_FRUIT_TYPES = ['strawberry', 'kiwi', 'orange', 'apple']; // Boss fruit for each level
+var LEVEL_THRESHOLDS = [5, 50, 150, 300]; // Score thresholds for each level boss
+var LEVEL_FRUITS = [['strawberry'],
+// Level 1 fruits
+['strawberry', 'kiwi'],
+// Level 2 fruits
+['strawberry', 'kiwi', 'orange'],
+// Level 3 fruits
+['strawberry', 'kiwi', 'orange', 'apple'] // Level 4 fruits
+];
 var BOMB_PROBABILITY = 0.2; // Increased bomb probability
 // Game variables
 var fruits = [];
 var blade = null;
@@ -557,9 +571,12 @@
 var comboTimer = 0;
 var comboTimeout = 1000; // ms to reset combo
 var currentLevel = 1;
 var bossActivated = false;
-var levelThreshold = 5; // Points needed to trigger boss in level 1
+var nextLevelNotified = false;
+var showingLevelText = false;
+var levelTextTimer = 0;
+var levelText; // Level notification text
 var missedFruits = 0; // Counter for missed fruits
 var missedText; // Text to display missed count
 var highScore = storage.highScore || 0; // Get high score from storage or default to 0
 var highScoreText; // Text to display high score
@@ -597,9 +614,9 @@
 	}
 	// Create blade
 	blade = game.addChild(new Blade());
 	// Create boss but don't activate it yet
-	boss = game.addChild(new Boss());
+	boss = game.addChild(new Boss(currentLevel));
 	// Set up score display
 	scoreTxt = new Text2('0', {
 		size: 100,
 		fill: 0xFFFFFF
@@ -615,8 +632,18 @@
 	comboTxt.anchor.set(0.5, 0);
 	comboTxt.y = 140;
 	comboTxt.alpha = 0;
 	LK.gui.top.addChild(comboTxt);
+	// Set up level text display
+	levelText = new Text2('Level 1', {
+		size: 120,
+		fill: 0xFFFFFF
+	});
+	levelText.anchor.set(0.5, 0.5);
+	levelText.x = GAME_WIDTH / 2;
+	levelText.y = GAME_HEIGHT / 2;
+	levelText.alpha = 0;
+	game.addChild(levelText);
 	// Set up missed fruits display
 	missedText = new Text2('Missed: 0/10', {
 		size: 60,
 		fill: 0xFF0000
@@ -651,16 +678,38 @@
 	LK.playMusic('gameMusic');
 	// Reset level tracking
 	currentLevel = 1;
 	bossActivated = false;
+	nextLevelNotified = false;
 	LK.setScore(0);
 	missedFruits = 0;
+	// Show level 1 text at start
+	showLevelText(1);
 }
+// Function to display level text
+function showLevelText(level) {
+	levelText.setText('Level ' + level);
+	levelText.alpha = 0;
+	showingLevelText = true;
+	// Animate the level text
+	tween(levelText, {
+		alpha: 1
+	}, {
+		duration: 500,
+		easing: tween.easeOut,
+		onFinish: function onFinish() {
+			// Hold the text visible for a moment
+			levelTextTimer = Date.now() + 2000;
+		}
+	});
+}
 function spawnFruits() {
 	var count = Math.floor(Math.random() * (SPAWN_COUNT_MAX - SPAWN_COUNT_MIN + 1)) + SPAWN_COUNT_MIN;
+	// Get appropriate fruit types for current level
+	var availableFruits = LEVEL_FRUITS[currentLevel - 1] || ['strawberry'];
 	for (var i = 0; i < count; i++) {
 		var isBomb = Math.random() < BOMB_PROBABILITY;
-		var type = isBomb ? 'bomb' : FRUIT_TYPES[Math.floor(Math.random() * FRUIT_TYPES.length)];
+		var type = isBomb ? 'bomb' : availableFruits[Math.floor(Math.random() * availableFruits.length)];
 		var fruit = new Fruit(type);
 		// Determine flight pattern
 		var pattern = Math.random();
 		if (pattern < 0.5) {
@@ -810,20 +859,37 @@
 }
 ;
 // Game update function
 game.update = function () {
+	var currentTime = Date.now();
+	// Handle level text animation
+	if (showingLevelText && currentTime > levelTextTimer && levelText.alpha > 0) {
+		tween(levelText, {
+			alpha: 0
+		}, {
+			duration: 500,
+			easing: tween.easeIn,
+			onFinish: function onFinish() {
+				showingLevelText = false;
+			}
+		});
+	}
 	// Check if we should activate the boss fight based on score
-	if (currentLevel === 1 && LK.getScore() >= levelThreshold && !bossActivated) {
+	if (currentLevel <= 4 && LK.getScore() >= LEVEL_THRESHOLDS[currentLevel - 1] && !bossActivated && !nextLevelNotified) {
 		bossActivated = true;
+		// Create a new boss for the current level
+		if (boss) {
+			boss.destroy();
+		}
+		boss = game.addChild(new Boss(currentLevel));
 		boss.activate();
 		// Clear existing fruits during boss transition
 		for (var i = fruits.length - 1; i >= 0; i--) {
 			fruits[i].destroy();
 			fruits.splice(i, 1);
 		}
 	}
 	// Only spawn normal fruits if we're not in a boss fight
-	var currentTime = Date.now();
 	if (currentTime >= nextSpawnTime && (!bossActivated || !boss.active)) {
 		spawnFruits();
 	}
 	// Update all fruits
@@ -867,11 +933,30 @@
 	}
 	// If boss was defeated, move to next level
 	if (bossActivated && boss && !boss.active) {
 		bossActivated = false;
-		currentLevel++;
-		// Increase level threshold for next boss
-		levelThreshold = levelThreshold + 50;
+		nextLevelNotified = false;
+		// Move to next level if we haven't reached level 4 yet
+		if (currentLevel < 4) {
+			currentLevel++;
+			// Show level notification
+			showLevelText(currentLevel);
+		} else if (currentLevel === 4) {
+			// Player has beaten all levels
+			LK.effects.flashScreen(0x00FF00, 800);
+			// Show "You Win" screen after completing all levels
+			if (LK.getScore() > highScore) {
+				highScore = LK.getScore();
+				storage.highScore = highScore;
+			}
+			// Add score to global leaderboard
+			addScoreToLeaderboard(LK.getScore());
+			// Show you win screen
+			LK.showYouWin({
+				score: LK.getScore(),
+				highScore: highScore
+			});
+		}
 	}
 	// Check combo timer
 	if (comboCount > 0 && Date.now() > comboTimer) {
 		updateCombo();
:quality(85)/https://cdn.frvr.ai/6813fb83a2f08cfafccd1760.png%3F3) 
 red bomb. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68189a95cdeca07700bc34d2.png%3F3) 
 Head of pepe meme. each face shaped as a marble shaped face made in blender 3D. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68189b6bcdeca07700bc34dd.png%3F3) 
 Head of doge meme. face shaped as a marble shaped face made in blender 3D. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818a6eaabf9fe9560ef94c3.png%3F3) 
 Head of troll face meme. face shaped as a marble shaped face made in blender 3D. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818a84cabf9fe9560ef94e3.png%3F3) 
 Head of think smart guy meme. face shaped as a marble shaped face made in blender 3D. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818aa44abf9fe9560ef94fd.png%3F3) 
 Head of white y u no meme. face shaped as a marble shaped face made in blender 3D. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818ace5abf9fe9560ef9509.png%3F3) 
 Explosion. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818ada1abf9fe9560ef9511.png%3F3) 
 Clock. In-Game asset. 3d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6818afafabf9fe9560ef9539.png%3F3) 
 Red Heart. In-Game asset. 3d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/681933365ef7e5b120ac6a5b.png%3F3) 
 gattling gun. In-Game asset. 2d. High contrast. No shadows