/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Class for Bubbles
var Bubble = Container.expand(function () {
	var self = Container.call(this);
	var bubbleGraphics = self.attachAsset('bubble', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -20; // Increased speed for much faster bubble movement
	self.update = function () {
		self.x += self.speed;
		// Check for intersection with any floor
		for (var i = 0; i < floors.length; i++) {
			if (self.intersects(floors[i])) {
				// Create a PoppedBubble at the bubble's position
				var pop = game.addChild(new PoppedBubble());
				pop.x = self.x;
				pop.y = self.y;
				// Destroy the bubble
				self.destroy();
				bubbles.splice(bubbles.indexOf(self), 1);
				// Destroy the PoppedBubble after 0.5 seconds
				LK.setTimeout(function () {
					pop.destroy();
				}, 500);
				break;
			}
		}
		// Update last known positions
		self.lastX = self.x;
		self.lastY = self.y;
	};
});
var CapturedPoppedBubble = Container.expand(function () {
	var self = Container.call(this);
	var popGraphics = self.attachAsset('poppedBubbleEnemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
});
var CapturingBubble = Container.expand(function () {
	var self = Container.call(this);
	var bubbleGraphics = self.attachAsset('bubble', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.alpha = 0.5;
	self.scaleX = 2;
	self.scaleY = 2;
	self.update = function () {};
});
//<Assets used in the game will automatically appear here>
// Class for the Dragon character
var Dragon = Container.expand(function () {
	var self = Container.call(this);
	self.dragonGraphics = self.attachAsset('dragon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.isIntersectingBubble = false; // Add a variable to track if the dragon is intersecting a bubble
	self.shootBubble = function () {
		var bubble = new Bubble();
		bubble.x = self.x + 200 * self.scaleX;
		bubble.y = self.y - 5;
		// Initially set bubble scale to 0.5
		bubble.scale.x = 0.5;
		bubble.scale.y = 0.5;
		// If the dragon is looking right, the bubble should move to the right
		if (self.scale.x == 1) {
			bubble.speed = 50;
		} else {
			// If the dragon is looking left, the bubble should move to the left
			bubble.speed = -50;
		}
		game.addChild(bubble);
		bubbles.push(bubble);
		// Animate bubble scale from 0.5 to 1 over 0.5 seconds
		tween(bubble.scale, {
			x: 1,
			y: 1
		}, {
			duration: 500,
			easing: tween.easeOut
		});
		// Play bubble sound when a bubble is shot
		LK.getSound('bubble').play();
	};
});
// Class for Pop
var PoppedBubble = Container.expand(function () {
	var self = Container.call(this);
	var popGraphics = self.attachAsset('poppedBubble', {
		anchorX: 0.5,
		anchorY: 0.5
	});
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x09899d
});
/**** 
* Game Code
****/ 
function tweenDragonContainer() {
	tween(dragonOnContainer, {
		y: dragonOnContainer.y + 300
	}, {
		duration: 1000,
		onFinish: function onFinish() {
			tween(dragonOnContainer, {
				y: dragonOnContainer.y - 300
			}, {
				duration: 1000
			});
		}
	});
}
var level = 1; // Initialize level variable in global scope
var started = false; // Initialize started flag
var intervalId = LK.setInterval(function () {
	if (!started) {
		tweenDragonContainer();
	} else {
		LK.clearInterval(intervalId); // Clear interval if started is true
	}
}, 4000);
var controlPanel = new Container();
var panelBackground = LK.getAsset('game_background', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2,
	alpha: 0.8
});
controlPanel.addChild(panelBackground);
var instructionsText = new Text2('INSTRUCTIONS', {
	size: 100,
	fill: 0xffffff,
	stroke: 0xFFFFFF,
	strokeThickness: 5,
	align: "center",
	font: "Comic Sans MS",
	fontWeight: "bold"
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 2048 / 2;
instructionsText.y = 75;
controlPanel.addChild(instructionsText);
// Rainbow color array
var rainbowColors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x8B00FF];
var colorIndex = 0;
// Function to cycle through rainbow colors
function cycleRainbowColors() {
	instructionsText.tint = rainbowColors[colorIndex];
	colorIndex = (colorIndex + 1) % rainbowColors.length;
}
// Set interval to change color every 500ms
LK.setInterval(cycleRainbowColors, 500);
var controlText = new Text2('- Click on 🐲 to shoot 🫧\n- Click above the 🐲 to jump ⬆️.\n- The higher you click, the bigger the jump ⬆️⬆️!', {
	size: 85,
	// Increased size for better visibility
	fill: 0xFFFFFF,
	align: "center",
	stroke: 0xFFFFFF,
	strokeThickness: 5,
	font: "Comic Sans MS" // Adding a cool font and bold style
});
controlText.anchor.set(0.5, 0.5);
controlText.x = 2048 / 2;
controlText.y = 400;
controlPanel.addChild(controlText);
var understoodButtonBackgroundBg = LK.getAsset('understoodBg', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 800,
	width: 2000,
	alpha: 0.5
});
controlPanel.addChild(understoodButtonBackgroundBg);
var dragonOnContainer = LK.getAsset('dragon', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 1200,
	scaleX: 2,
	scaleY: 2
});
controlPanel.addChild(dragonOnContainer);
var bubbleOnContainer = LK.getAsset('bubble', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 2,
	scaleY: 2,
	alpha: 0.35
});
dragonOnContainer.addChild(bubbleOnContainer);
var understoodButton = new Text2('Click anywhere to start', {
	size: 150,
	fill: 0x1570e0,
	align: "center",
	stroke: 0xFFFFFF,
	strokeThickness: 5
});
understoodButton.anchor.set(0.5, 0.5);
understoodButton.x = 2048 / 2;
understoodButton.y = 800;
controlPanel.addChild(understoodButton);
game.addChild(controlPanel);
// Add event listener to the 'Understood' button
understoodButton.interactive = true;
understoodButton.buttonMode = true;
game.down = function (x, y, obj) {
	controlPanel.destroy();
	startGame();
};
var bubbles = []; // Initialize bubbles array to store bubble instances
var floors = []; // Initialize floors array to store floor instances
var behaviours = {}; // Initialize behaviours object
var enemies = [];
var capturingBubbles = [];
function startGame() {
	started = true;
	function restartGame() {
		level++;
		if (level > 5) {
			LK.showYouWin();
			return;
		}
		background.destroy(); // Remove the previous background
		var bgId = level <= 5 ? 'pixel_background_' + level.toString() : 'pixel_background_6';
		background = LK.getAsset(bgId, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 2048 / 2,
			y: 2732 / 2,
			alpha: 0.95
		});
		game.addChild(background); // Add the new background
		// Restart game with new platforms and enemies
		// Clear existing platforms and enemies
		floors.forEach(function (floor) {
			floor.destroy();
		});
		floors = [];
		enemies.forEach(function (enemy) {
			enemy.destroy();
		});
		enemies = [];
		// Destroy the existing dragon
		dragon.destroy();
		// Update background for current level
		background.destroy();
		var bgId = level <= 5 ? 'pixel_background_' + level.toString() : 'pixel_background_6';
		background = LK.getAsset(bgId, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 2048 / 2,
			y: 2732 / 2,
			alpha: 0.95
		});
		game.addChild(background);
		// Important: Always call these in this specific order
		addFloors();
		addPlatforms();
		addDragon();
		addLevelText();
	}
	var background = LK.getAsset('pixel_background_' + level.toString(), {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2,
		alpha: 0.95
	});
	game.addChild(background);
	function _toConsumableArray2(r) {
		return _arrayWithoutHoles2(r) || _iterableToArray2(r) || _unsupportedIterableToArray3(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 _unsupportedIterableToArray3(r, a) {
		if (r) {
			if ("string" == typeof r) {
				return _arrayLikeToArray3(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) ? _arrayLikeToArray3(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 _arrayLikeToArray3(r);
		}
	}
	function _arrayLikeToArray3(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 _createForOfIteratorHelper(r, e) {
		var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
		if (!t) {
			if (Array.isArray(r) || (t = _unsupportedIterableToArray2(r)) || e && r && "number" == typeof r.length) {
				t && (r = t);
				var _n = 0,
					F = function F() {};
				return {
					s: F,
					n: function n() {
						return _n >= r.length ? {
							done: !0
						} : {
							done: !1,
							value: r[_n++]
						};
					},
					e: function e(r) {
						throw r;
					},
					f: F
				};
			}
			throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
		}
		var o,
			a = !0,
			u = !1;
		return {
			s: function s() {
				t = t.call(r);
			},
			n: function n() {
				var r = t.next();
				return a = r.done, r;
			},
			e: function e(r) {
				u = !0, o = r;
			},
			f: function f() {
				try {
					a || null == t["return"] || t["return"]();
				} finally {
					if (u) {
						throw o;
					}
				}
			}
		};
	}
	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 _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 jumpStartTime; // Declare jumpStartTime to track the start of the jump
	var easingFunctions = [tween.linear, tween.easeIn, tween.easeOut, tween.easeInOut, tween.bounceIn, tween.bounceOut, tween.bounceInOut, tween.elasticIn, tween.elasticOut, tween.elasticInOut, tween.cubicIn, tween.cubicOut, tween.cubicInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut];
	LK.playMusic('music');
	function isStandingOnFloor() {
		for (var i = 0; i < floors.length; i++) {
			if (dragon.intersects(floors[i])) {
				return true;
			}
		}
		return false;
	}
	function updateFall() {
		if (isFalling) {
			// Save previous position before moving
			var previousY = dragon.y;
			dragon.y += 185; // Move dragon downwards at a faster speed for quicker falling
			// Check for intersection with any floor - do collision detection on EVERY frame
			var _iterator = _createForOfIteratorHelper(floors),
				_step;
			try {
				for (_iterator.s(); !(_step = _iterator.n()).done;) {
					var floor = _step.value;
					// Check if dragon is intersecting with a floor
					if (dragon.intersects(floor)) {
						isJumping = false; // Stop jumping
						isFalling = false; // Stop falling when colliding with a floor
						canJump = true; // Allow jumping again when the dragon hits a floor
						// Position the dragon precisely on top of the floor with proper offset
						dragon.y = floor.y - floor.height * 1.5; // Align dragon to the top of the floor
						break;
					}
				}
			} catch (err) {
				_iterator.e(err);
			} finally {
				_iterator.f();
			}
		}
		// Update last known intersection state
		dragon.lastWasIntersecting = floors.some(function (floor) {
			return dragon.intersects(floor);
		});
	}
	//<Assets used in the game will automatically appear here>
	// Handle mouse move events to move the dragon
	game.move = function (x, y, obj) {
		// Ignore the event if the target is outside the screen or close to its margins
		if (x > 150 && x < 2048 - 200) {
			// Set the target x position for the dragon
			dragon.targetX = x;
		}
	};
	var isFalling = false; // Initialize isFalling to track dragon's fall state
	// Handle game updates
	game.update = function () {
		// Move dragon incrementally towards target x
		if (dragon.targetX !== undefined) {
			var increment = (dragon.targetX - dragon.x) / 10; // Move in 0.5 seconds assuming 60 FPS
			if (dragon.targetX !== undefined && (increment > 0 && dragon.x < dragon.targetX || increment < 0 && dragon.x > dragon.targetX)) {
				dragon.x += increment;
			}
			// Update last known position
			dragon.lastX = dragon.x;
			dragon.lastY = dragon.y; // Track lastY position
			// Adjust dragon's scale based on targetX position
			if (dragon.targetX < dragon.x) {
				dragon.scale.x = -1;
			} else {
				dragon.scale.x = 1;
			}
		}
		var standingOnFloor = isStandingOnFloor();
		if (!standingOnFloor && !isJumping) {
			isFalling = true;
		}
		/*if (standingOnFloor && dragon.wings) {
		dragon.wings = false;
		dragon.removeChild(dragon.dragonGraphics); // Remove the current dragon graphics
		dragon.dragonGraphics = dragon.attachAsset('dragon', {
		anchorX: 0.5,
		anchorY: 0.5
		});
		dragon.addChild(dragon.dragonGraphics);
		}*/
		if (LK.ticks % 2 === 0) {
			updateJump();
		}
		if (LK.ticks % 2 === 0) {
			updateFall();
		}
		if (LK.ticks % 1 === 0) {
			updateBubbles();
		}
		if (LK.ticks % 15 === 0) {
			updateEnemiesMovement();
		}
		// Check every 5 seconds (300 frames at 60fps) if any enemies are still alive
		if (LK.ticks % 300 === 0) {
			if (enemies.length === 0) {
				restartGame();
			}
		}
	};
	// Handle touch events for shooting bubbles
	var lastShot = 0;
	var lastClick = 0;
	var isJumping = false; // Add a variable to track if the dragon is jumping 
	var canJump = true; // Initialize canJump flag to allow jumping
	game.down = function (x, y, obj) {
		var now = Date.now();
		if (y < dragon.y - dragon.height && canJump && !isJumping) {
			isJumping = true; // Set isJumping to true when the dragon starts jumping
			// Play jump sound when the dragon starts jumping
			LK.getSound('jump').play();
			jumpStartY = y; // Capture the Y position of the mouse click
			jumpStartTime = Date.now(); // Initialize jump start time
		}
		// Check if click is anywhere near the dragon - use more generous hit testing
		// Create a larger hit area rectangle for the dragon with 1.5x the size
		var hitWidth = Math.abs(dragon.dragonGraphics.width);
		var dragonCenterX = dragon.x; // Dragon's center position
		var hitBoxWidth = hitWidth * 1.5; // 50% wider hit area
		// Calculate the rectangle's top-left corner position based on dragon's direction
		var rectX = dragon.scale.x < 0 ? dragonCenterX - hitBoxWidth * 0.25 : dragonCenterX - hitBoxWidth * 0.75;
		var dragonBounds = new Rectangle(rectX,
		// Adjust rectangle position based on dragon direction
		dragon.y - dragon.height * 0.75,
		// Taller hit area top
		hitBoxWidth,
		// 50% wider hit area
		dragon.height * 1 // 50% taller hit area
		);
		// Check if click point is within the dragon's bounds
		if (dragonBounds.contains(x, y)) {
			// Only shoot a bubble when clicking on or near the dragon
			if (now - lastShot > 200) {
				dragon.shootBubble();
				lastShot = now;
			}
		}
		lastClick = now;
	};
	function updateEnemiesMovement() {
		enemies.forEach(function (enemy) {
			if (enemy.captured) {
				if (enemy.isMoving) {
					tween.stop(enemy);
					enemy.isMoving = false;
					enemy.floating = true;
				} else if (enemy.floating) {
					tween(enemy, {
						y: 100
					}, {
						duration: 5000,
						easing: tween.linear,
						onFinish: function onFinish() {
							enemy.children[1].tint = 0xbf5555;
							if (enemies.length === 0) {
								restartGame();
							}
						}
					});
				}
			} else if (!enemy.isMoving) {
				enemy.isMoving = true;
				// Use the stored platform for this enemy if available, otherwise find it
				if (!enemy.platform) {
					var platformFloors = floors.filter(function (floor) {
						return Math.abs(floor.y - (enemy.y + 100)) < 10 && floor.x > 0 && floor.x < 2048 - 50;
					});
					// Check if we have platform floors
					if (platformFloors.length === 0) {
						enemy.isMoving = false;
						return;
					}
					// Store the platform for this enemy
					enemy.platform = platformFloors[0];
				}
				// Use the pre-calculated platform boundaries for this enemy
				var startX = enemy.minX;
				var endX = enemy.maxX;
				tween(enemy, {
					x: endX
				}, {
					duration: Math.random() * 10000,
					easing: behaviours[enemy.type],
					onFinish: function onFinish() {
						tween(enemy, {
							x: startX
						}, {
							duration: 2000,
							easing: tween.linear,
							onFinish: function onFinish() {
								enemy.isMoving = false;
							}
						});
					}
				});
			}
			enemy.scale.x = enemy.lastX < enemy.x ? 1 : -1;
			if (!enemy.captured && dragon.intersects(enemy)) {
				// Play game over sound when the dragon dies
				LK.getSound('gameover').play();
				// Rotate the dragon 90 degrees left
				dragon.rotation = -3 * Math.PI * dragon.scale.x;
				// Animate the dragon falling down
				tween(dragon, {
					y: 2732 + dragon.height,
					// Move dragon off the screen
					tint: 0xFF0000
				}, {
					duration: 500,
					// Duration of the fall
					easing: tween.linear,
					onFinish: function onFinish() {
						// Show game over after the dragon has fallen
						LK.showGameOver();
					}
				});
			}
			enemy.lastX = enemy.x;
			enemy.lastY = enemy.y;
		});
	}
	function updateBubbles() {
		// Update bubbles
		for (var i = bubbles.length - 1; i >= 0; i--) {
			var bubble = bubbles[i];
			if (!bubble) {
				continue;
			}
			// Check for bubble-bubble intersections
			for (var j = i - 1; j >= 0; j--) {
				var otherBubble = bubbles[j];
				if (!otherBubble) {
					continue;
				}
				if (bubble.intersects(otherBubble)) {
					// Create a PoppedBubble for each intersecting bubble
					var pop1 = game.addChild(new PoppedBubble());
					pop1.x = bubble.x;
					pop1.y = bubble.y;
					var pop2 = game.addChild(new PoppedBubble());
					pop2.x = otherBubble.x;
					pop2.y = otherBubble.y;
					// Destroy both bubbles
					bubble.destroy();
					otherBubble.destroy();
					bubbles.splice(i, 1);
					bubbles.splice(j, 1);
					// Play pop sound when a bubble is popped
					LK.getSound('pop').play();
					// Destroy the PoppedBubbles after 0.5 seconds
					LK.setTimeout(function () {
						pop1.destroy();
						pop2.destroy();
					}, 500);
					break;
				}
			}
			if (!bubble) {
				return;
			}
			if (bubble.y < -50) {
				bubble.destroy();
				bubbles.splice(i, 1);
			}
		}
		// Check for bubble-enemy collisions
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			for (var j = bubbles.length - 1; j >= 0; j--) {
				var bubble = bubbles[j];
				if (bubble.intersects(enemy)) {
					// Destroy the original bubble
					bubble.destroy();
					bubbles.splice(j, 1);
					// Create a new bubble as a child of the enemy
					var newBubble = new CapturingBubble();
					newBubble.x = 0; // Position relative to the enemy
					newBubble.y = 0; // Position relative to the enemy
					enemy.addChild(newBubble);
					enemy.captured = true;
					capturingBubbles.push(newBubble);
					break;
				}
			}
		}
		// Check if the dragon is intersecting a bubble
		for (var i = 0; i < bubbles.length; i++) {
			if (dragon.intersects(bubbles[i])) {
				// Create a PoppedBubble at the bubble's position
				var pop = game.addChild(new PoppedBubble());
				pop.x = bubbles[i].x;
				pop.y = bubbles[i].y;
				// Destroy the bubble
				bubbles[i].destroy();
				bubbles.splice(i, 1);
				// Play pop sound when a bubble is popped
				LK.getSound('pop').play();
				// Destroy the PoppedBubble after 0.5 seconds
				LK.setTimeout(function () {
					pop.destroy();
				}, 500);
				break;
			}
		}
		// Check if the dragon is intersecting a CapturingBubble
		for (var i = capturingBubbles.length - 1; i >= 0; i--) {
			var capturingBubble = capturingBubbles[i];
			if (dragon.intersects(capturingBubble)) {
				// Find and destroy the enemy that is the parent of the CapturingBubble
				for (var j = enemies.length - 1; j >= 0; j--) {
					var enemy = enemies[j];
					if (enemy.children.includes(capturingBubble)) {
						// Create a PoppedBubble at the capturingBubble's position
						var pop = game.addChild(new CapturedPoppedBubble());
						pop.x = enemy.x;
						pop.y = enemy.y;
						// Destroy the enemy and capturingBubble
						enemy.destroy();
						enemies.splice(j, 1);
						// Play pop sound when a capturing bubble is popped
						LK.getSound('pop').play();
						// Destroy the PoppedBubble after 2 seconds
						LK.setTimeout(function () {
							pop.destroy();
						}, 1000);
						break;
					}
				}
			}
		}
		capturingBubbles.forEach(function (capturingBubble) {
			var enemy = capturingBubble.parent;
			if (enemy && !enemy.captured) {
				enemy.y -= 150; // Make the enemy jump with the dragon
			}
		});
	}
	function updateJump() {
		if (isJumping) {
			// Calculate how far into the jump we are (0 to 1)
			var jumpElapsed = Date.now() - jumpStartTime;
			var jumpDuration = 500; // 200ms jump duration
			var jumpProgress = Math.min(jumpElapsed / jumpDuration, 1);
			// Calculate the position based on jumpStartY and current progress
			var initialY = dragon.y; // Starting position
			// Calculate maximum jump height based on click position
			// The higher the click, the smaller the jump (limited by dragon's current position)
			var maxJumpHeight = Math.min(dragon.y - jumpStartY, 500); // Cap maximum jump at 500px
			var targetY = dragon.y - maxJumpHeight; // Target position based on click
			var jumpDistance = initialY - targetY; // Total distance to cover
			// Save previous position
			var previousY = dragon.y;
			// Calculate new Y position
			dragon.y = initialY - jumpDistance * jumpProgress;
			// Check for intersection with any floor - check EVERY floor
			var intersectingFloor = null;
			for (var i = 0; i < floors.length; i++) {
				if (dragon.intersects(floors[i])) {
					intersectingFloor = floors[i];
					break;
				}
			}
			if (intersectingFloor) {
				isJumping = false; // Stop jumping
				isFalling = false; // Don't start falling - we're already on a floor
				canJump = true; // Allow jumping as we're on a floor
				dragon.y = intersectingFloor.y - intersectingFloor.height * 1.5; // Align dragon to the top of the floor
			}
			// Check if jump duration has exceeded jump time
			if (jumpProgress >= 1) {
				isJumping = false;
				isFalling = true;
			}
		}
		// Update last known intersection state
		dragon.lastWasIntersecting = floors.some(function (floor) {
			return dragon.intersects(floor);
		});
	}
	addFloors();
	addDragon();
	addPlatforms();
	addLevelText();
}
function addFloors() {
	// BLOCKS
	// Add a floor to the bottom of the screen - create 1 floor out of 5
	floors = [];
	var floor = LK.getAsset('floor', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 - 30,
		width: 2048
	});
	game.addChild(floor);
	floors.push(floor);
	// Add continuous floor on the left margin of the screen - only every 5th floor
	/*var leftFloor = LK.getAsset('floorV', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 50,
		y: 15 * 100,
		height: 3000
	});
	game.addChild(leftFloor);
	floors.push(leftFloor);
	var rightFloor = LK.getAsset('floorV', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 - 40,
		y: 15 * 100,
		height: 3000
	});
	game.addChild(rightFloor);
	floors.push(rightFloor);*/
}
// Define easing functions array for platform movement - referenced both here and in updateFall function
var easingFunctions = [tween.linear, tween.easeIn, tween.easeOut, tween.easeInOut, tween.bounceIn, tween.bounceOut, tween.bounceInOut, tween.elasticIn, tween.elasticOut, tween.elasticInOut, tween.cubicIn, tween.cubicOut, tween.cubicInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut];
function addPlatforms() {
	// Add random platforms with irregular heights and positions
	var platformYPositions = [];
	var distinctHeights = [2300, 1900, 1500, 1100, 700]; // Define 4-5 distinct heights
	distinctHeights.forEach(function (height) {
		platformYPositions.push(height);
	});
	// Add random platforms with irregular heights and positions
	for (var j = 0; j < platformYPositions.length; j++) {
		var _behaviours$enemyType;
		var platformLength = Math.floor(Math.random() * 1200) + 500; // Random length between 500-1000
		var maxStartX = 2048 - platformLength - 50; // Max start X, ensuring platform stays in screen
		var minStartX = 50; // Min start X to avoid left margin collision
		var startX = minStartX + Math.random() * maxStartX;
		var startY = platformYPositions[j];
		// Generate a random tint color for the platforms
		var randomTint = Math.floor(Math.random() * 16777215);
		var platform = LK.getAsset('floor', {
			anchorX: 0,
			anchorY: 0.5,
			x: startX,
			y: platformYPositions[j],
			width: platformLength
		});
		platform.tint = randomTint; // Apply the random tint to the platform
		game.addChild(platform);
		floors.push(platform);
		// Spawn an enemy on top of each platform
		var enemyType = 'enemy' + (j % 5 + 1); // Cycle through enemy1 to enemy5 using the loop variable j
		var behaviour = (_behaviours$enemyType = behaviours[enemyType]) !== null && _behaviours$enemyType !== void 0 ? _behaviours$enemyType : easingFunctions[Math.floor(Math.random() * easingFunctions.length)]; // Assign random easing function;
		behaviours[enemyType] = behaviour;
		var enemy = LK.getAsset(enemyType, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: startX + platformLength / 2,
			y: platformYPositions[j] - 100,
			type: enemyType
		});
		enemy.captured = false;
		// Store the reference to this enemy's platform
		enemy.platform = platform;
		// Store platform boundaries for this enemy
		enemy.minX = startX + enemy.width / 2;
		enemy.maxX = startX + platformLength - enemy.width / 2;
		game.addChild(enemy);
		enemies.push(enemy);
	}
}
function addDragon() {
	// Recreate the dragon and add it to the game
	dragon = game.addChild(new Dragon());
	// Reposition dragon at the bottom - place it on top of the floor
	dragon.x = 1024; // Center horizontally
	dragon.y = 2732 - 170; // Fallback position if no floor found
	// Initialize important tracking properties
	dragon.lastWasIntersecting = false;
	dragon.lastX = dragon.x;
	dragon.lastY = dragon.y;
}
function addLevelText() {
	var levelTextBackground = new Text2('LEVEL ' + level.toString(), {
		size: 210,
		fill: 0x000000,
		stroke: 0xFFFFFF,
		strokeThickness: 5
	});
	levelTextBackground.anchor.set(0.5, 0.5);
	levelTextBackground.x = 2048 / 2;
	levelTextBackground.y = 2732 / 2;
	game.addChild(levelTextBackground);
	LK.setTimeout(function () {
		levelTextBackground.destroy();
	}, 2000);
	var levelText = new Text2('LEVEL ' + level.toString(), {
		size: 200,
		fill: 0xFFFF00 // Changed to bright white for maximum visibility
	});
	levelText.anchor.set(0.5, 0.5);
	levelText.x = 2048 / 2;
	levelText.y = 2732 / 2;
	game.addChild(levelText);
	LK.setTimeout(function () {
		levelText.destroy();
	}, 2000);
} ===================================================================
--- original.js
+++ change.js
@@ -68,17 +68,28 @@
 	self.shootBubble = function () {
 		var bubble = new Bubble();
 		bubble.x = self.x + 200 * self.scaleX;
 		bubble.y = self.y - 5;
+		// Initially set bubble scale to 0.5
+		bubble.scale.x = 0.5;
+		bubble.scale.y = 0.5;
 		// If the dragon is looking right, the bubble should move to the right
 		if (self.scale.x == 1) {
-			bubble.speed = 125;
+			bubble.speed = 50;
 		} else {
 			// If the dragon is looking left, the bubble should move to the left
-			bubble.speed = -125;
+			bubble.speed = -50;
 		}
 		game.addChild(bubble);
 		bubbles.push(bubble);
+		// Animate bubble scale from 0.5 to 1 over 0.5 seconds
+		tween(bubble.scale, {
+			x: 1,
+			y: 1
+		}, {
+			duration: 500,
+			easing: tween.easeOut
+		});
 		// Play bubble sound when a bubble is shot
 		LK.getSound('bubble').play();
 	};
 });
@@ -158,10 +169,12 @@
 LK.setInterval(cycleRainbowColors, 500);
 var controlText = new Text2('- Click on 🐲 to shoot 🫧\n- Click above the 🐲 to jump ⬆️.\n- The higher you click, the bigger the jump ⬆️⬆️!', {
 	size: 85,
 	// Increased size for better visibility
-	fill: 0x000000,
+	fill: 0xFFFFFF,
 	align: "center",
+	stroke: 0xFFFFFF,
+	strokeThickness: 5,
 	font: "Comic Sans MS" // Adding a cool font and bold style
 });
 controlText.anchor.set(0.5, 0.5);
 controlText.x = 2048 / 2;
@@ -195,9 +208,11 @@
 dragonOnContainer.addChild(bubbleOnContainer);
 var understoodButton = new Text2('Click anywhere to start', {
 	size: 150,
 	fill: 0x1570e0,
-	align: "center"
+	align: "center",
+	stroke: 0xFFFFFF,
+	strokeThickness: 5
 });
 understoodButton.anchor.set(0.5, 0.5);
 understoodButton.x = 2048 / 2;
 understoodButton.y = 800;
@@ -414,9 +429,9 @@
 	function updateFall() {
 		if (isFalling) {
 			// Save previous position before moving
 			var previousY = dragon.y;
-			dragon.y += 85; // Move dragon downwards at a faster speed for quicker falling
+			dragon.y += 185; // Move dragon downwards at a faster speed for quicker falling
 			// Check for intersection with any floor - do collision detection on EVERY frame
 			var _iterator = _createForOfIteratorHelper(floors),
 				_step;
 			try {
@@ -529,9 +544,9 @@
 		dragon.y - dragon.height * 0.75,
 		// Taller hit area top
 		hitBoxWidth,
 		// 50% wider hit area
-		dragon.height * 1.5 // 50% taller hit area
+		dragon.height * 1 // 50% taller hit area
 		);
 		// Check if click point is within the dragon's bounds
 		if (dragonBounds.contains(x, y)) {
 			// Only shoot a bubble when clicking on or near the dragon
@@ -743,9 +758,9 @@
 	function updateJump() {
 		if (isJumping) {
 			// Calculate how far into the jump we are (0 to 1)
 			var jumpElapsed = Date.now() - jumpStartTime;
-			var jumpDuration = 200; // 200ms jump duration
+			var jumpDuration = 500; // 200ms jump duration
 			var jumpProgress = Math.min(jumpElapsed / jumpDuration, 1);
 			// Calculate the position based on jumpStartY and current progress
 			var initialY = dragon.y; // Starting position
 			// Calculate maximum jump height based on click position
@@ -883,9 +898,11 @@
 }
 function addLevelText() {
 	var levelTextBackground = new Text2('LEVEL ' + level.toString(), {
 		size: 210,
-		fill: 0x000000
+		fill: 0x000000,
+		stroke: 0xFFFFFF,
+		strokeThickness: 5
 	});
 	levelTextBackground.anchor.set(0.5, 0.5);
 	levelTextBackground.x = 2048 / 2;
 	levelTextBackground.y = 2732 / 2;
 A version of this bubble but exploded
 brick, brown color, pixel style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 better wings, pixel style, more contrasted, more visible, blue color
 a pixel clouds background. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 a pixel clouds background, with mountains, full height full width Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 
 a similar image. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 a pixel clouds background, with mountains, full height full width Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 A popped blue bobble, pixel style, bubble booble arcade game inspired. In-Game asset. 2d. High contrast. No shadows
 
 A bubble popping, pixel style, retro. In-Game asset. 2d. High contrast. No shadows