/**** 
* Classes
****/ 
// Background class
var Background = Container.expand(function () {
	var self = Container.call(this);
	var backgroundGraphics = self.attachAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 2048,
		height: 2732
	});
	backgroundGraphics.anchor.set(0, 0);
	// Add black overlay on top of the background
	var overlay = self.attachAsset('shape', {
		width: 2048,
		height: 2732,
		color: 0x000000,
		alpha: 0.0,
		shape: 'box'
	});
	overlay.anchor.set(0, 0);
	// This is automatically called every game tick, if the background is attached!
	self.update = function () {
		if (overlay.alpha < 1) {
			overlay.alpha += 0.0001; // Increase alpha over time
		}
	};
});
// Bubble class
var Bubble = Container.expand(function () {
	var self = Container.call(this);
	var bubbleGraphics = self.attachAsset('bubble', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.5
	});
	var scale = Math.random() * 0.5 + 0.5;
	bubbleGraphics.scale.set(scale, scale);
	// Set bubble speed
	self.speed = -3;
	// Initialize colliding property
	self.colliding = false;
	// This is automatically called every game tick, if the bubble is attached!
	self.update = function () {
		// Move the bubble upwards and sideways
		self.y += self.speed;
		self.x += Math.sin(LK.ticks / 10) * 0.1;
		// Reset the position of the bubble when it reaches the top
		if (self.y <= 0) {
			self.y = 2732;
		}
		// Check if the bubble is colliding with an obstacle using spatial hash
		var cellSize = 150;
		var hashX = Math.floor(self.x / cellSize);
		var hashY = Math.floor(self.y / cellSize);
		var hashKey = hashX + ',' + hashY;
		if (spatialHash[hashKey]) {
			for (var i = 0; i < spatialHash[hashKey].length; i++) {
				var obstacle = spatialHash[hashKey][i];
				if (self.intersects(obstacle)) {
					// Bring the bubble to the top of the z axis
					game.setChildIndex(self, game.children.length - 1);
					self.colliding = true;
				} else {
					self.collidingWithShield = false;
					self.colliding = false;
				}
			}
		} else {
			self.colliding = false;
		}
	};
});
// Diver class
var Diver = Container.expand(function () {
	var self = Container.call(this);
	var diverGraphics = self.attachAsset('diver', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Add an invisible hitbox with smaller dimensions
	var hitbox = self.attachAsset('shape', {
		width: 200,
		// Smaller width
		height: 260,
		// Increased height by 30%
		// Smaller height
		color: 0x000000,
		alpha: 0 // Invisible
	});
	// Add a sideways movement to the diver
	self.movement = 0;
	self.direction = 1;
	self.update = function () {
		self.movement += self.direction * 0.03;
		if (self.movement > 0.5 || self.movement < -0.5) {
			self.direction *= -1;
		}
		self.x += self.movement;
	};
	// Center the hitbox on the diver
	hitbox.anchor.set(0.5, 0.5);
	// Add flippers to the diver
	var leftFlipper = self.addChild(new Flipper());
	leftFlipper.x = -50;
	leftFlipper.depth = -1;
	var rightFlipper = self.addChild(new Flipper());
	rightFlipper.x = 60;
	rightFlipper.depth = -1;
});
// Flipper class
var Flipper = Container.expand(function () {
	var self = Container.call(this);
	var flipperGraphics = self.attachAsset('flippers', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Set flipper movement
	self.movement = 0;
	self.direction = 1;
	// This is automatically called every game tick, if the flipper is attached!
	self.update = function () {
		// Move the flipper subtly to simulate flipping
		self.movement += self.direction * 0.03;
		if (self.movement > 0.5 || self.movement < -0.5) {
			self.direction *= -1;
		}
		self.rotation = self.movement;
	};
});
// Obstacle1 class
var Obstacle1 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle1Graphics = self.attachAsset('obstacle1', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle1 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle1 is attached!
	self.update = function () {
		// Rotate obstacle1 on its axis
		self.rotation += 0.05;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
		self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle2 class
var Obstacle2 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle2Graphics = self.attachAsset('obstacle2', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle2 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle2 is attached!
	self.update = function () {
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add wiggly movement to the obstacle
		self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
		self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle3 class
var Obstacle3 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle3Graphics = self.attachAsset('obstacle3', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle3 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle3 is attached!
	self.update = function () {
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add slow spinning effect
		self.rotation += 0.01;
		// Add unique behavior to obstacle3
		self.scale.x = 1 + Math.sin(LK.ticks / 5) * 0.05; // Larger size change
		self.scale.y = 1 + Math.sin(LK.ticks / 5) * 0.05;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle4 class
var Obstacle4 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle4Graphics = self.attachAsset('obstacle4', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle4 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle4 is attached!
	self.update = function () {
		// Add up and down movement
		self.y += Math.sin(LK.ticks / 20) * 2;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier + Math.sin(LK.ticks / 20) * 2;
		self.scale.x = 1 + Math.sin(LK.ticks / 15) * 0.03; // Different size change
		self.scale.y = 1 + Math.sin(LK.ticks / 15) * 0.03;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle5 class
var Obstacle5 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle5Graphics = self.attachAsset('obstacle5', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle5 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle5 is attached!
	self.update = function () {
		// Add very small sideways movement
		self.x += Math.sin(LK.ticks / 100) * 0.5;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add unique behavior to obstacle5
		self.scale.x = 1 + Math.sin(LK.ticks / 20) * 0.1; // Increase size change amplitude
		self.scale.y = 1 + Math.sin(LK.ticks / 20) * 0.1;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle6 class
var Obstacle6 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle6Graphics = self.attachAsset('obstacle6', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle6 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle6 is attached!
	self.update = function () {
		// Flickering effect
		self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
		// Fast side-to-side movement
		self.x += Math.sin(LK.ticks / 10) * 1; // Further reduced horizontal movement
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add unique behavior to obstacle6
		self.scale.x = 1 + Math.sin(LK.ticks / 25) * 0.05; // Different size change
		self.scale.y = 1 + Math.sin(LK.ticks / 25) * 0.05;
		self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
		self.x += Math.sin(LK.ticks / 5) * 10; // Fast horizontal movement
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.y += 1.6; // Move power-up downwards (reduced by 20%)
		self.x += Math.sin(LK.ticks / 20) * 2; // Add pendular movement
		// Check if the power-up is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the power-up
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the power-up away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
		}
		if (self.intersects(diver)) {
			LK.getSound('powerup').play();
			shield.scale.x *= 2;
			shield.scale.y *= 2;
			LK.setTimeout(function () {
				// Start blinking effect after 8 seconds
				var blinkInterval = LK.setInterval(function () {
					shield.alpha = shield.alpha === 1 ? 0.5 : 1;
					if (shield.alpha === 0.5 && !self.shieldOffPlayed) {
						LK.getSound('shieldoff').play();
						self.shieldOffPlayed = true;
					}
				}, 60); // Blink every 500ms
				// Stop blinking and reset shield size after 10 seconds
				LK.setTimeout(function () {
					LK.clearInterval(blinkInterval);
					shield.alpha = 0.9; // Reset alpha to original value
					shield.scale.x /= 2;
					shield.scale.y /= 2;
					self.shieldOffPlayed = false;
				}, 2000); // Blink for 2 seconds
			}, 8000); // Start blinking after 8 seconds
			self.destroy();
		}
	};
});
// Shield class
var Shield = Container.expand(function () {
	var self = Container.call(this);
	var shieldGraphics = self.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.75
	});
	self.originalAlpha = shieldGraphics.alpha; // Store the original alpha value
	self.down = function (x, y, obj) {
		dragNode = shield;
	};
});
/**** 
* Initialize Game
****/ 
// Create a diver instance
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
	backgroundColor: 0xADD8E6 //Init game with a softer blue background
});
/**** 
* Game Code
****/ 
var wavePositionLabel;
// Function to spawn power-ups every 20 seconds
function spawnPowerUp() {
	if (!firstPowerUpSpawned) {
		if (LK.ticks < 300) {
			// 300 ticks = 5 seconds
			return;
		}
		firstPowerUpSpawned = true;
	} else if (LK.ticks - lastPowerUpSpawnTime < 1200) {
		// 1200 ticks = 20 seconds
		return;
	}
	var powerUp = game.addChild(new PowerUp());
	lastPowerUpSpawnTime = LK.ticks;
	do {
		powerUp.x = Math.random() * 2048;
	} while (diver && Math.abs(powerUp.x - diver.x) < 200);
	powerUp.y = -100; // Start offscreen at the top
	// Schedule the next power-up spawn
	LK.setTimeout(spawnPowerUp, 20000); // 20 seconds
}
// Initial call to spawn the first power-up after 20 seconds
LK.setTimeout(spawnPowerUp, 20000);
var lastBubbleSoundTime = 0;
var lastPowerUpSpawnTime = 0;
var speedMultiplier = 1;
var waveInterval = 6000; // Initial interval of 5 seconds between waves
var firstPowerUpSpawned = false;
// Declare and initialize backgroundMusic variable
var backgroundMusic = LK.getSound('background');
// Play background music on loop when the game starts
LK.on('tick', function () {
	if (!backgroundMusic.playing) {
		backgroundMusic.play();
	}
});
var background1 = game.addChild(new Background());
background1.y = 0;
// Create a shield instance
var shield = game.addChildAt(new Shield(), game.children.length);
// Position the shield at the center of the screen
shield.x = 2048 / 2;
shield.y = 2732 / 2;
// Create a diver instance
var dragNode = null;
var diver = new Diver();
diver.depth = 2;
// Position the diver at the top center of the screen, 200 pixels down from the top
diver.x = 2048 / 2;
diver.y = 500;
// Ensure diver's dimensions are fully initialized before positioning flippers
diver.on('added', function () {
	// Position the flippers relative to the diver
	diver.children[0].y = diver.height / 2 - 20; // Left flipper
	diver.children[1].y = diver.height / 2 - 20; // Right flipper
});
// Position the flippers relative to the diver
diver.children[0].y = diver.height / 2 - 20; // Left flipper
diver.children[0].y = diver.children[0].y; // Right flipper
// Set diver to a higher depth than flippers
diver.depth = 2;
// Create an obstacle1 instance
game.move = function (x, y, obj) {
	if (dragNode) {
		if (dragNode !== shield) {
			shield.x += x - shield.x;
			shield.y += y - shield.y;
		} else {
			dragNode.x = x;
			dragNode.y = y;
		}
	}
	if (dragNode === shield) {
		shield.x = x;
		shield.y = y;
	}
};
var obstacles = [];
var spatialHash = {};
game.addChild(diver);
game.setChildIndex(diver, game.children.length - 1);
// Create power-up instance
var powerUp = game.addChild(new PowerUp());
do {
	powerUp.x = Math.random() * 2048;
} while (Math.abs(powerUp.x - diver.x) < 200);
powerUp.y = -100; // Start offscreen at the top
// Create bubbles after obstacles
var bubbles = [];
for (var i = 0; i < 20; i++) {
	var bubble = new Bubble();
	bubble.x = Math.random() * 2048;
	bubble.y = Math.random() * 2732;
	bubbles.push(bubble);
	game.addChildAt(bubble, game.children.length);
}
// Spawn the first wave of obstacles
spawnWave();
;
// Initialize score
var score = LK.getScore();
// Create score text
var depthScoreText = new Text2('Depth:0m', {
	size: 70,
	fill: "#ffffff",
	stroke: "#000000",
	strokeThickness: 6,
	font: "monospace" // Change font to be more square
});
depthScoreText.anchor.set(0.5, 0.5);
depthScoreText.x = 400;
depthScoreText.y = 100;
LK.gui.top.addChild(depthScoreText);
// Initialize a timer to update the score every second and increase speed multiplier
var scoreUpdateInterval = LK.setInterval(function () {
	LK.setScore(LK.getScore() + 1);
	if (depthScoreText) {
		depthScoreText.setText('Depth:' + LK.getScore() + 'm');
	}
	speedMultiplier += 0.01; // Increase speed multiplier by 0.02 every second
}, 1000);
game.up = function (x, y, obj) {
	dragNode = null;
};
// Check if background music is playing, if not, play it
if (!backgroundMusic.playing) {
	backgroundMusic.play();
}
// Update background
background1.update();
// Update bubbles
for (var i = 0; i < bubbles.length; i++) {
	bubbles[i].update();
}
// Define the current wave
var currentWave = 0;
var allWavesSpawnedOnce = false;
// Spawn wave function
function spawnWave() {
	// Define the layout of the obstacles for each wave
	var obstacleLayouts = [{
		type: 'line',
		grid: ['.....', '.....', '.#.#.', '.....', '.....']
	}, {
		type: 'triangle',
		grid: ['.....', '..#..', '.....', '.#.#.', '.....']
	}, {
		type: 'square',
		grid: ['.....', '.#.#.', '.....', '.#.#.', '.....']
	}, {
		type: 'circle',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}, {
		type: 'cross',
		grid: ['.....', '..#..', '.#.#.', '..#..', '.....']
	}, {
		type: 'hexagon',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}, {
		type: 'heptagon',
		grid: ['..#..', '.....', '#...#', '.....', '..#..']
	}, {
		type: 'octagon',
		grid: ['.....', '#####', '.....', '.....', '.....']
	}, {
		type: 'nonagon',
		grid: ['#....', '.#....', '..#..', '...#.', '....#']
	}, {
		type: 'nonagon2',
		grid: ['....#', '...#.', '..#..', '.#...', '#....']
	}, {
		type: 'gon2',
		grid: ['#.#.#', '......', '..#..', '.....', '#.#.#']
	}, {
		type: 'gonn3',
		grid: ['#.#.#', '......', '.....', '.....', '#.#.#']
	}, {
		type: 'decagon',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}];
	// Get the layout for the current wave
	var layout = obstacleLayouts[currentWave];
	if (!layout) {
		console.error('Error: layout is undefined. Check the obstacleLayouts array.');
		return;
	}
	var layoutPositions = [];
	layout.grid.forEach(function (row, rowIndex) {
		row.split('').forEach(function (cell, colIndex) {
			if (cell === '#') {
				layoutPositions.push({
					x: colIndex,
					y: rowIndex
				});
			}
		});
	});
	// Randomly choose an obstacle type for the entire wave
	var obstacleTypes = [Obstacle1, Obstacle2, Obstacle3, Obstacle4, Obstacle5, Obstacle6];
	var obstacleType = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
	// Randomly choose one of the three starting x positions for the entire wave
	var startXPositions = [{
		position: 2048 / 4.5,
		label: 'left'
	}, {
		position: 2048 / 1.08,
		label: 'right'
	}, {
		position: 2048 / 1.9,
		label: 'center'
	}];
	var randomStart = startXPositions[Math.floor(Math.random() * startXPositions.length)];
	var randomStartX = randomStart.position;
	wavePositionLabel = randomStart.label;
	console.log('Wave starting position:', wavePositionLabel);
	console.log('Wave starting position:', wavePositionLabel);
	// Generate a random spacing multiplier between 1 and 2 for the current wave
	var spacingMultiplier = 1 + Math.random();
	layoutPositions.forEach(function (position) {
		var obstacle = game.addChild(new obstacleType());
		// Position the obstacles according to the layout, using the grid for positioning
		obstacle.x = randomStartX + (position.x - gridSize / 2) * cellSize * spacingMultiplier;
		obstacle.y = 2732 + position.y * cellSize * spacingMultiplier; // Spawn obstacles offscreen at the bottom
		obstacle.waveSpeedX = wavePositionLabel === 'right' ? -1.5 : wavePositionLabel === 'left' ? 1.5 : 0;
		obstacles.push(obstacle);
	});
	currentWave++;
	if (currentWave >= obstacleLayouts.length) {
		allWavesSpawnedOnce = true;
		currentWave = 0;
	}
	if (allWavesSpawnedOnce) {
		currentWave = Math.floor(Math.random() * (obstacleLayouts.length - 3)) + 3;
	}
	// Add interval of wait between waves, decreasing over time
	var waveInterval = Math.max(1000, 5000 - LK.getScore() * 10); // Minimum interval of 1 second
	LK.setTimeout(function () {
		spawnWave();
	}, waveInterval);
}
// Define the grid size and the size of each cell in the grid
var gridSize = 5;
var cellSize = 150;
// Call the spawn wave function every 1 second
// Initial call to spawn the first wave
spawnWave();
; /**** 
* Classes
****/ 
// Background class
var Background = Container.expand(function () {
	var self = Container.call(this);
	var backgroundGraphics = self.attachAsset('background', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 2048,
		height: 2732
	});
	backgroundGraphics.anchor.set(0, 0);
	// Add black overlay on top of the background
	var overlay = self.attachAsset('shape', {
		width: 2048,
		height: 2732,
		color: 0x000000,
		alpha: 0.0,
		shape: 'box'
	});
	overlay.anchor.set(0, 0);
	// This is automatically called every game tick, if the background is attached!
	self.update = function () {
		if (overlay.alpha < 1) {
			overlay.alpha += 0.0001; // Increase alpha over time
		}
	};
});
// Bubble class
var Bubble = Container.expand(function () {
	var self = Container.call(this);
	var bubbleGraphics = self.attachAsset('bubble', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.5
	});
	var scale = Math.random() * 0.5 + 0.5;
	bubbleGraphics.scale.set(scale, scale);
	// Set bubble speed
	self.speed = -3;
	// Initialize colliding property
	self.colliding = false;
	// This is automatically called every game tick, if the bubble is attached!
	self.update = function () {
		// Move the bubble upwards and sideways
		self.y += self.speed;
		self.x += Math.sin(LK.ticks / 10) * 0.1;
		// Reset the position of the bubble when it reaches the top
		if (self.y <= 0) {
			self.y = 2732;
		}
		// Check if the bubble is colliding with an obstacle using spatial hash
		var cellSize = 150;
		var hashX = Math.floor(self.x / cellSize);
		var hashY = Math.floor(self.y / cellSize);
		var hashKey = hashX + ',' + hashY;
		if (spatialHash[hashKey]) {
			for (var i = 0; i < spatialHash[hashKey].length; i++) {
				var obstacle = spatialHash[hashKey][i];
				if (self.intersects(obstacle)) {
					// Bring the bubble to the top of the z axis
					game.setChildIndex(self, game.children.length - 1);
					self.colliding = true;
				} else {
					self.collidingWithShield = false;
					self.colliding = false;
				}
			}
		} else {
			self.colliding = false;
		}
	};
});
// Diver class
var Diver = Container.expand(function () {
	var self = Container.call(this);
	var diverGraphics = self.attachAsset('diver', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Add an invisible hitbox with smaller dimensions
	var hitbox = self.attachAsset('shape', {
		width: 200,
		// Smaller width
		height: 260,
		// Increased height by 30%
		// Smaller height
		color: 0x000000,
		alpha: 0 // Invisible
	});
	// Add a sideways movement to the diver
	self.movement = 0;
	self.direction = 1;
	self.update = function () {
		self.movement += self.direction * 0.03;
		if (self.movement > 0.5 || self.movement < -0.5) {
			self.direction *= -1;
		}
		self.x += self.movement;
	};
	// Center the hitbox on the diver
	hitbox.anchor.set(0.5, 0.5);
	// Add flippers to the diver
	var leftFlipper = self.addChild(new Flipper());
	leftFlipper.x = -50;
	leftFlipper.depth = -1;
	var rightFlipper = self.addChild(new Flipper());
	rightFlipper.x = 60;
	rightFlipper.depth = -1;
});
// Flipper class
var Flipper = Container.expand(function () {
	var self = Container.call(this);
	var flipperGraphics = self.attachAsset('flippers', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Set flipper movement
	self.movement = 0;
	self.direction = 1;
	// This is automatically called every game tick, if the flipper is attached!
	self.update = function () {
		// Move the flipper subtly to simulate flipping
		self.movement += self.direction * 0.03;
		if (self.movement > 0.5 || self.movement < -0.5) {
			self.direction *= -1;
		}
		self.rotation = self.movement;
	};
});
// Obstacle1 class
var Obstacle1 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle1Graphics = self.attachAsset('obstacle1', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle1 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle1 is attached!
	self.update = function () {
		// Rotate obstacle1 on its axis
		self.rotation += 0.05;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
		self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle2 class
var Obstacle2 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle2Graphics = self.attachAsset('obstacle2', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle2 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle2 is attached!
	self.update = function () {
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add wiggly movement to the obstacle
		self.scale.x = 1 + Math.sin(LK.ticks / 10) * 0.02;
		self.scale.y = 1 + Math.sin(LK.ticks / 10) * 0.02;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle3 class
var Obstacle3 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle3Graphics = self.attachAsset('obstacle3', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle3 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle3 is attached!
	self.update = function () {
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add slow spinning effect
		self.rotation += 0.01;
		// Add unique behavior to obstacle3
		self.scale.x = 1 + Math.sin(LK.ticks / 5) * 0.05; // Larger size change
		self.scale.y = 1 + Math.sin(LK.ticks / 5) * 0.05;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle4 class
var Obstacle4 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle4Graphics = self.attachAsset('obstacle4', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle4 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle4 is attached!
	self.update = function () {
		// Add up and down movement
		self.y += Math.sin(LK.ticks / 20) * 2;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier + Math.sin(LK.ticks / 20) * 2;
		self.scale.x = 1 + Math.sin(LK.ticks / 15) * 0.03; // Different size change
		self.scale.y = 1 + Math.sin(LK.ticks / 15) * 0.03;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle5 class
var Obstacle5 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle5Graphics = self.attachAsset('obstacle5', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle5 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle5 is attached!
	self.update = function () {
		// Add very small sideways movement
		self.x += Math.sin(LK.ticks / 100) * 0.5;
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add unique behavior to obstacle5
		self.scale.x = 1 + Math.sin(LK.ticks / 20) * 0.1; // Increase size change amplitude
		self.scale.y = 1 + Math.sin(LK.ticks / 20) * 0.1;
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
// Obstacle6 class
var Obstacle6 = Container.expand(function () {
	var self = Container.call(this);
	var obstacle6Graphics = self.attachAsset('obstacle6', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: Math.random() < 0.5 ? 0.7 : -0.7,
		// Randomly mirror horizontally
		scaleY: 0.7
	});
	// Set obstacle6 speed
	self.speed = -5;
	self.originalSpeedX = self.speed;
	// This is automatically called every game tick, if the obstacle6 is attached!
	self.update = function () {
		// Flickering effect
		self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
		// Fast side-to-side movement
		self.x += Math.sin(LK.ticks / 10) * 1; // Further reduced horizontal movement
		// Check if the obstacle is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the obstacle
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the obstacle away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
			self.speed = self.originalSpeedX;
		}
		// Check for collision with diver
		if (self.intersects(diver.children.find(function (child) {
			return child.alpha === 0;
		}), {
			tolerance: 10
		})) {
			// Flash screen red for 1 second (1000ms) to show game over
			LK.effects.flashScreen(0xff0000, 1000);
			// Show game over. The game will be automatically paused while game over is showing.
			LK.showGameOver();
		}
		// Update spatial hash
		var oldHashX = Math.floor((self.x - self.speed * speedMultiplier) / cellSize);
		var oldHashY = Math.floor((self.y - self.speed * speedMultiplier) / cellSize);
		var newHashX = Math.floor(self.x / cellSize);
		var newHashY = Math.floor(self.y / cellSize);
		var oldHashKey = oldHashX + ',' + oldHashY;
		var newHashKey = newHashX + ',' + newHashY;
		if (oldHashKey !== newHashKey) {
			if (spatialHash[oldHashKey]) {
				var index = spatialHash[oldHashKey].indexOf(self);
				if (index > -1) {
					spatialHash[oldHashKey].splice(index, 1);
				}
			}
			if (!spatialHash[newHashKey]) {
				spatialHash[newHashKey] = [];
			}
			spatialHash[newHashKey].push(self);
		}
		// Continue moving upwards
		self.x += self.waveSpeedX;
		self.y += self.speed * speedMultiplier;
		// Add unique behavior to obstacle6
		self.scale.x = 1 + Math.sin(LK.ticks / 25) * 0.05; // Different size change
		self.scale.y = 1 + Math.sin(LK.ticks / 25) * 0.05;
		self.alpha = Math.random() * 0.5 + 0.5; // Random alpha between 0.5 and 1
		self.x += Math.sin(LK.ticks / 5) * 10; // Fast horizontal movement
		if (self.y < 0) {
			self.destroy();
			var index = obstacles.indexOf(self);
			if (index > -1) {
				obstacles.splice(index, 1);
			}
		}
		// Check if the obstacle is colliding with another obstacle
		for (var i = 0; i < obstacles.length; i++) {
			var otherObstacle = obstacles[i];
			if (self !== otherObstacle && self.intersects(otherObstacle)) {
				// Calculate the direction vector between the two obstacles
				var dx = self.x - otherObstacle.x;
				var dy = self.y - otherObstacle.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// Normalize the direction vector
				dx /= distance;
				dy /= distance;
				// Increase the repulsion force and always push the obstacle to the outside
				self.x += dx * 10;
				self.y += dy * 10;
			}
		}
	};
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.y += 1.6; // Move power-up downwards (reduced by 20%)
		self.x += Math.sin(LK.ticks / 20) * 2; // Add pendular movement
		// Check if the power-up is colliding with the shield
		if (self.intersects(shield, {
			tolerance: 10
		})) {
			if (!self.collidingWithShield) {
				LK.getSound('bubble').play();
				self.collidingWithShield = true;
			}
			// Calculate the direction vector between the shield and the power-up
			var dx = self.x - shield.x;
			var dy = self.y - shield.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Normalize the direction vector
			dx /= distance;
			dy /= distance;
			// Push the power-up away from the shield
			self.x += dx * 5;
			self.y += dy * 5;
		} else {
			self.collidingWithShield = false;
		}
		if (self.intersects(diver)) {
			LK.getSound('powerup').play();
			shield.scale.x *= 2;
			shield.scale.y *= 2;
			LK.setTimeout(function () {
				// Start blinking effect after 8 seconds
				var blinkInterval = LK.setInterval(function () {
					shield.alpha = shield.alpha === 1 ? 0.5 : 1;
					if (shield.alpha === 0.5 && !self.shieldOffPlayed) {
						LK.getSound('shieldoff').play();
						self.shieldOffPlayed = true;
					}
				}, 60); // Blink every 500ms
				// Stop blinking and reset shield size after 10 seconds
				LK.setTimeout(function () {
					LK.clearInterval(blinkInterval);
					shield.alpha = 0.9; // Reset alpha to original value
					shield.scale.x /= 2;
					shield.scale.y /= 2;
					self.shieldOffPlayed = false;
				}, 2000); // Blink for 2 seconds
			}, 8000); // Start blinking after 8 seconds
			self.destroy();
		}
	};
});
// Shield class
var Shield = Container.expand(function () {
	var self = Container.call(this);
	var shieldGraphics = self.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.75
	});
	self.originalAlpha = shieldGraphics.alpha; // Store the original alpha value
	self.down = function (x, y, obj) {
		dragNode = shield;
	};
});
/**** 
* Initialize Game
****/ 
// Create a diver instance
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
	backgroundColor: 0xADD8E6 //Init game with a softer blue background
});
/**** 
* Game Code
****/ 
var wavePositionLabel;
// Function to spawn power-ups every 20 seconds
function spawnPowerUp() {
	if (!firstPowerUpSpawned) {
		if (LK.ticks < 300) {
			// 300 ticks = 5 seconds
			return;
		}
		firstPowerUpSpawned = true;
	} else if (LK.ticks - lastPowerUpSpawnTime < 1200) {
		// 1200 ticks = 20 seconds
		return;
	}
	var powerUp = game.addChild(new PowerUp());
	lastPowerUpSpawnTime = LK.ticks;
	do {
		powerUp.x = Math.random() * 2048;
	} while (diver && Math.abs(powerUp.x - diver.x) < 200);
	powerUp.y = -100; // Start offscreen at the top
	// Schedule the next power-up spawn
	LK.setTimeout(spawnPowerUp, 20000); // 20 seconds
}
// Initial call to spawn the first power-up after 20 seconds
LK.setTimeout(spawnPowerUp, 20000);
var lastBubbleSoundTime = 0;
var lastPowerUpSpawnTime = 0;
var speedMultiplier = 1;
var waveInterval = 6000; // Initial interval of 5 seconds between waves
var firstPowerUpSpawned = false;
// Declare and initialize backgroundMusic variable
var backgroundMusic = LK.getSound('background');
// Play background music on loop when the game starts
LK.on('tick', function () {
	if (!backgroundMusic.playing) {
		backgroundMusic.play();
	}
});
var background1 = game.addChild(new Background());
background1.y = 0;
// Create a shield instance
var shield = game.addChildAt(new Shield(), game.children.length);
// Position the shield at the center of the screen
shield.x = 2048 / 2;
shield.y = 2732 / 2;
// Create a diver instance
var dragNode = null;
var diver = new Diver();
diver.depth = 2;
// Position the diver at the top center of the screen, 200 pixels down from the top
diver.x = 2048 / 2;
diver.y = 500;
// Ensure diver's dimensions are fully initialized before positioning flippers
diver.on('added', function () {
	// Position the flippers relative to the diver
	diver.children[0].y = diver.height / 2 - 20; // Left flipper
	diver.children[1].y = diver.height / 2 - 20; // Right flipper
});
// Position the flippers relative to the diver
diver.children[0].y = diver.height / 2 - 20; // Left flipper
diver.children[0].y = diver.children[0].y; // Right flipper
// Set diver to a higher depth than flippers
diver.depth = 2;
// Create an obstacle1 instance
game.move = function (x, y, obj) {
	if (dragNode) {
		if (dragNode !== shield) {
			shield.x += x - shield.x;
			shield.y += y - shield.y;
		} else {
			dragNode.x = x;
			dragNode.y = y;
		}
	}
	if (dragNode === shield) {
		shield.x = x;
		shield.y = y;
	}
};
var obstacles = [];
var spatialHash = {};
game.addChild(diver);
game.setChildIndex(diver, game.children.length - 1);
// Create power-up instance
var powerUp = game.addChild(new PowerUp());
do {
	powerUp.x = Math.random() * 2048;
} while (Math.abs(powerUp.x - diver.x) < 200);
powerUp.y = -100; // Start offscreen at the top
// Create bubbles after obstacles
var bubbles = [];
for (var i = 0; i < 20; i++) {
	var bubble = new Bubble();
	bubble.x = Math.random() * 2048;
	bubble.y = Math.random() * 2732;
	bubbles.push(bubble);
	game.addChildAt(bubble, game.children.length);
}
// Spawn the first wave of obstacles
spawnWave();
;
// Initialize score
var score = LK.getScore();
// Create score text
var depthScoreText = new Text2('Depth:0m', {
	size: 70,
	fill: "#ffffff",
	stroke: "#000000",
	strokeThickness: 6,
	font: "monospace" // Change font to be more square
});
depthScoreText.anchor.set(0.5, 0.5);
depthScoreText.x = 400;
depthScoreText.y = 100;
LK.gui.top.addChild(depthScoreText);
// Initialize a timer to update the score every second and increase speed multiplier
var scoreUpdateInterval = LK.setInterval(function () {
	LK.setScore(LK.getScore() + 1);
	if (depthScoreText) {
		depthScoreText.setText('Depth:' + LK.getScore() + 'm');
	}
	speedMultiplier += 0.01; // Increase speed multiplier by 0.02 every second
}, 1000);
game.up = function (x, y, obj) {
	dragNode = null;
};
// Check if background music is playing, if not, play it
if (!backgroundMusic.playing) {
	backgroundMusic.play();
}
// Update background
background1.update();
// Update bubbles
for (var i = 0; i < bubbles.length; i++) {
	bubbles[i].update();
}
// Define the current wave
var currentWave = 0;
var allWavesSpawnedOnce = false;
// Spawn wave function
function spawnWave() {
	// Define the layout of the obstacles for each wave
	var obstacleLayouts = [{
		type: 'line',
		grid: ['.....', '.....', '.#.#.', '.....', '.....']
	}, {
		type: 'triangle',
		grid: ['.....', '..#..', '.....', '.#.#.', '.....']
	}, {
		type: 'square',
		grid: ['.....', '.#.#.', '.....', '.#.#.', '.....']
	}, {
		type: 'circle',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}, {
		type: 'cross',
		grid: ['.....', '..#..', '.#.#.', '..#..', '.....']
	}, {
		type: 'hexagon',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}, {
		type: 'heptagon',
		grid: ['..#..', '.....', '#...#', '.....', '..#..']
	}, {
		type: 'octagon',
		grid: ['.....', '#####', '.....', '.....', '.....']
	}, {
		type: 'nonagon',
		grid: ['#....', '.#....', '..#..', '...#.', '....#']
	}, {
		type: 'nonagon2',
		grid: ['....#', '...#.', '..#..', '.#...', '#....']
	}, {
		type: 'gon2',
		grid: ['#.#.#', '......', '..#..', '.....', '#.#.#']
	}, {
		type: 'gonn3',
		grid: ['#.#.#', '......', '.....', '.....', '#.#.#']
	}, {
		type: 'decagon',
		grid: ['.....', '..#..', '.#.#.', '.#.#.', '..#..']
	}];
	// Get the layout for the current wave
	var layout = obstacleLayouts[currentWave];
	if (!layout) {
		console.error('Error: layout is undefined. Check the obstacleLayouts array.');
		return;
	}
	var layoutPositions = [];
	layout.grid.forEach(function (row, rowIndex) {
		row.split('').forEach(function (cell, colIndex) {
			if (cell === '#') {
				layoutPositions.push({
					x: colIndex,
					y: rowIndex
				});
			}
		});
	});
	// Randomly choose an obstacle type for the entire wave
	var obstacleTypes = [Obstacle1, Obstacle2, Obstacle3, Obstacle4, Obstacle5, Obstacle6];
	var obstacleType = obstacleTypes[Math.floor(Math.random() * obstacleTypes.length)];
	// Randomly choose one of the three starting x positions for the entire wave
	var startXPositions = [{
		position: 2048 / 4.5,
		label: 'left'
	}, {
		position: 2048 / 1.08,
		label: 'right'
	}, {
		position: 2048 / 1.9,
		label: 'center'
	}];
	var randomStart = startXPositions[Math.floor(Math.random() * startXPositions.length)];
	var randomStartX = randomStart.position;
	wavePositionLabel = randomStart.label;
	console.log('Wave starting position:', wavePositionLabel);
	console.log('Wave starting position:', wavePositionLabel);
	// Generate a random spacing multiplier between 1 and 2 for the current wave
	var spacingMultiplier = 1 + Math.random();
	layoutPositions.forEach(function (position) {
		var obstacle = game.addChild(new obstacleType());
		// Position the obstacles according to the layout, using the grid for positioning
		obstacle.x = randomStartX + (position.x - gridSize / 2) * cellSize * spacingMultiplier;
		obstacle.y = 2732 + position.y * cellSize * spacingMultiplier; // Spawn obstacles offscreen at the bottom
		obstacle.waveSpeedX = wavePositionLabel === 'right' ? -1.5 : wavePositionLabel === 'left' ? 1.5 : 0;
		obstacles.push(obstacle);
	});
	currentWave++;
	if (currentWave >= obstacleLayouts.length) {
		allWavesSpawnedOnce = true;
		currentWave = 0;
	}
	if (allWavesSpawnedOnce) {
		currentWave = Math.floor(Math.random() * (obstacleLayouts.length - 3)) + 3;
	}
	// Add interval of wait between waves, decreasing over time
	var waveInterval = Math.max(1000, 5000 - LK.getScore() * 10); // Minimum interval of 1 second
	LK.setTimeout(function () {
		spawnWave();
	}, waveInterval);
}
// Define the grid size and the size of each cell in the grid
var gridSize = 5;
var cellSize = 150;
// Call the spawn wave function every 1 second
// Initial call to spawn the first wave
spawnWave();
;
:quality(85)/https://cdn.frvr.ai/668bb01272715dcfc88d88a4.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d055672715dcfc88d89a5.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d0d5172715dcfc88d89c9.png%3F3) 
 8bit. cartoon. jellyfish.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/668d0ea572715dcfc88d89f0.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d176772715dcfc88d8a95.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d2aadf389b5a8c22af7d1.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d2c2af389b5a8c22af7f0.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/668d2ef0f389b5a8c22af80a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6690e1c5b7c8eed252dc5cd7.png%3F3) 
 empty 8 bit cartoon white circle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6694d71bc5225bf8be2530af.png%3F3) 
 cartoon. 8-bit. octopus. colorful.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6694d840c5225bf8be2530c0.png%3F3) 
 cartoon. 8-bit. sea urchin. colorful. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/6694df05c5225bf8be2530ea.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/66b5f62bfbc2197754e6a900.png%3F3) 
 cartoon 8bit stingray. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
:quality(85)/https://cdn.frvr.ai/66b5fbf1fbc2197754e6a948.png%3F3)