/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Bullet class
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 45;
	self.vx = 0;
	self.scaleX = MaxScale;
	self.scaleY = MaxScale;
	self.update = function () {
		self.scaleX -= 0.1;
		self.scaleY -= 0.1;
		self.y -= self.speed;
		self.x += self.vx;
		self.rotation += 0.1; // Add rotation effect
		if (self.scaleX <= MinScale && self.scaleY <= MinScale) {
			var index = bullets.indexOf(self);
			if (index > -1) {
				bullets.splice(index, 1);
			}
			game.removeChild(self);
			self.destroy();
		}
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			var threshold = 0.1;
			if (self.intersects(enemy) && self.scaleY >= enemy.scaleY - threshold && self.scaleY <= enemy.scaleY + threshold) {
				// Bullet hit the enemy
				// Show particle effect on impact
				var particleEffect = LK.getAsset('bloodSplatter', {
					anchorX: 0.5,
					anchorY: 0.5,
					scaleX: 0.5,
					scaleY: 0.5
				});
				particleEffect.x = self.x;
				particleEffect.y = self.y;
				game.addChild(particleEffect);
				tween(particleEffect, {
					alpha: 0,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					onFinish: function onFinish() {
						game.removeChild(particleEffect);
						particleEffect.destroy();
					}
				});
				// Remove the bullet
				var index = bullets.indexOf(self);
				if (index > -1) {
					bullets.splice(index, 1);
				}
				game.removeChild(self);
				self.destroy();
				//shake the enemy for 0.5 seconds if they are hit by bullet when frozen. 
				if (enemy.state == STATES.FREEZE) {
					enemy.shake();
				} else {
					// Play orc_hurt1 or orc_hurt2 sound at random if the enemy is not frozen.
					var hurtSound = Math.random() < 0.5 ? 'orc_hurt1' : 'orc_hurt2';
					LK.getSound(hurtSound).play();
					// Flash enemy red when hit
					tween(enemy, {
						tint: 0xFF0000
					}, {
						duration: 100,
						onFinish: function onFinish() {
							tween(enemy, {
								tint: 0xFFFFFF
							}, {
								duration: 100
							});
						}
					});
				}
				// Decrease enemy health
				enemy.health -= 1;
				if (enemy.health <= 0 && enemy.state != STATES.DEAD) {
					enemy.prevState = enemy.state;
					enemy.state = STATES.DEAD;
					// Increment the kill counter
					killCounter++;
					killCounterText.setText('Kills: ' + killCounter);
					enemy.onDeath();
				}
				break; // Stop the loop after one enemy is killed
			}
		}
		// Apply fade-in effect using tween
		tween(self, {
			alpha: 1
		}, {
			duration: 500,
			easing: tween.easeIn
		});
	};
});
// Enemy class
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Define states
	var STATES = {
		SPAWN: 'spawn',
		MOVE: 'move',
		ATTACK: 'attack',
		WAIT: 'wait',
		FREEZE: 'freeze',
		HURT: 'hurt',
		DEAD: 'dead'
	};
	// Initialize state
	self.state = STATES.SPAWN;
	self.prevState = null;
	//handle dead state.
	self.onDeath = function () {
		var enemy = self;
		// Destroy the enemy
		var enemyIndex = enemies.indexOf(enemy);
		if (enemyIndex > -1) {
			enemies.splice(enemyIndex, 1);
		}
		tween(enemy, {
			tint: 0xFF0000,
			scaleY: enemy.scaleY - 0.5,
			alpha: 0,
			y: enemy.y - 300
		}, {
			duration: 500,
			onFinish: function onFinish() {
				game.removeChild(enemy);
				enemy.destroy();
			}
		});
	};
	self.shake = function () {
		var offsetVal = Math.random() < 0.5 ? -10 : 10;
		// Shake the enemy for 0.5 seconds
		tween(self, {
			x: self.x + offsetVal
		}, {
			duration: 100,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				tween(self, {
					x: self.x - offsetVal
				}, {
					duration: 100,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						tween(self, {
							x: self.x
						}, {
							duration: 100,
							easing: tween.easeInOut
						});
					}
				});
			}
		});
	};
	// State machine handler
	self.handleState = function () {
		switch (self.state) {
			case STATES.SPAWN:
				self.handleSpawnState();
				break;
			case STATES.MOVE:
				self.handleMoveState();
				break;
			case STATES.ATTACK:
				self.handleAttackState();
				break;
			case STATES.WAIT:
				self.handleWaitState();
				break;
			case STATES.FREEZE:
				self.handleFreezeState();
				break;
		}
	};
	//handle freeze state.
	self.handleFreezeState = function () {
		// Tint the enemy blue
		tween(self, {
			tint: 0x0000FF
		}, {
			duration: 250,
			onFinish: function onFinish() {
				// Tint the enemy white
				tween(self, {
					tint: 0xFFFFFF
				}, {
					duration: 250,
					onFinish: function onFinish() {
						// Repeat the tinting effect for 5 seconds
						LK.setTimeout(function () {
							self.state = self.prevState; // Return to previous state after 5 seconds
						}, 5000);
					}
				});
			}
		});
	};
	// Handle spawn state
	self.handleSpawnState = function () {
		// Transition to move state after spawn tween is done
		if (self.speed == 2) {
			self.prevState = self.state;
			self.state = STATES.MOVE;
		}
	};
	// Handle move state
	self.handleMoveState = function () {
		// Rotate enemy 10 degrees to the left and right alternatively
		if (LK.ticks % 60 < 30) {
			self.rotation = self.startRotation * Math.PI / 36; // Rotate 10 degrees to the left or right based on startRotation
		} else {
			self.rotation = -self.startRotation * Math.PI / 36; // Rotate 10 degrees to the right or left based on startRotation
		}
		if (self.y + self.speed < 2732 - 600) {
			self.targetReachedTime = null; // Reset targetReachedTime when moving away from target
			self.y += self.speed;
			self.scaleX += 0.002;
			self.scaleY += 0.002;
		} else {
			// Reset rotation to zero when reaching target
			self.rotation = 0;
			self.reachedTarget = true; // Set reachedTarget to true when target is reached
			self.prevState = self.state;
			//Transition to the wait state. 
			self.state = STATES.WAIT;
		}
		// Pause enemy movement every 0.5 seconds for a duration of 0.25 seconds
		if (LK.ticks % 30 == 0) {
			self.speed = 0;
			LK.setTimeout(function () {
				self.speed = 2;
			}, 250);
		}
	};
	// Handle wait state
	self.handleWaitState = function () {
		// Transition to move state after waiting for 1 second
		if (!self.waitStartTime) {
			self.waitStartTime = Date.now();
		}
		if (Date.now() - self.waitStartTime >= 1000) {
			self.prevState = self.state;
			self.state = STATES.ATTACK;
			self.waitStartTime = null;
		}
	};
	// Handle attack state
	self.handleAttackState = function () {
		// Check if enemy can attack player
		if (self.canAttackPlayer === false) {
			return;
		}
		// Play sword slash sound effect
		LK.getSound('sword_slash').play();
		//toggle the canAttack so we dont' execute this again. 
		self.canAttackPlayer = false;
		// Change enemy image to attack start
		self.removeChild(enemyGraphics);
		enemyGraphics = self.addChild(self.imageDictionary.enemy_attack_start);
		var curScale = self.scaleX;
		var curPos = {
			x: self.x,
			y: self.y
		};
		// Animate enemy to move towards player and back
		tween(self, {
			x: player.x,
			y: player.y + player.height,
			scaleX: curScale + 2,
			scaleY: curScale + 2
		}, {
			duration: 250,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				// Reduce health by making a circle invisible
				if (healthCircles.length > 0) {
					var circle = healthCircles.pop();
					circle.visible = false;
				}
				// End game if no health circles are visible
				if (healthCircles.length === 0) {
					LK.showGameOver();
				}
				//show attack_finish on anim finish
				self.removeChild(enemyGraphics);
				enemyGraphics = self.addChild(self.imageDictionary.enemy_attack_finish);
				// Flash the player's hands red to indicate an attack
				tween(handsIdleLeft, {
					tint: 0xFF0000
				}, {
					duration: 250,
					onFinish: function onFinish() {
						tween(handsIdleLeft, {
							tint: 0xFFFFFF
						}, {
							duration: 250
						});
					}
				});
				tween(handsIdleRight, {
					tint: 0xFF0000
				}, {
					duration: 250,
					onFinish: function onFinish() {
						tween(handsIdleRight, {
							tint: 0xFFFFFF
						}, {
							duration: 250
						});
					}
				});
				tween(self, {
					x: curPos.x,
					y: curPos.y,
					scaleX: curScale,
					scaleY: curScale
				}, {
					duration: 250,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						self.removeChild(enemyGraphics);
						enemyGraphics = self.addChild(self.imageDictionary.idle);
					}
				});
			}
		});
	};
	// Dictionary of images for the enemy
	self.imageDictionary = {
		idle: LK.getAsset('enemy', {
			anchorX: 0.5,
			anchorY: 1
		}),
		attack: LK.getAsset('hands_idle', {
			anchorX: 0.5,
			anchorY: 1
		}),
		hit: LK.getAsset('bloodSplatter', {
			anchorX: 0.5,
			anchorY: 1
		}),
		enemy_attack_start: LK.getAsset('enemy_attack_start', {
			anchorX: 0.5,
			anchorY: 1
		}),
		enemy_attack_finish: LK.getAsset('enemy_attack_finish', {
			anchorX: 0.5,
			anchorY: 1
		})
	};
	// Attach the default enemy image
	var enemyGraphics = self.addChild(self.imageDictionary.idle);
	self.health = Math.min(2 + Math.floor(killCounter / 5), 10); // Initialize health based on kill count
	self.reachedTarget = false; // Initialize reachedTarget to false
	self.canAttackPlayer = false; // Initialize canAttackPlayer to false
	self.speed = 0;
	self.scaleX = MinScale;
	self.scaleY = MinScale / 4;
	tween(self, {
		scaleX: MinScale,
		scaleY: MinScale
	}, {
		duration: 250,
		onFinish: function onFinish() {
			self.speed = 0;
			LK.setTimeout(function () {
				self.speed = 2;
			}, 500);
		}
	});
	// Assign a random starting rotation to each enemy
	self.startRotation = Math.random() < 0.5 ? -1 : 1;
	self.handleTargetReached = function () {};
	self.update = function () {
		self.handleState(); // Call state machine handler
		return;
	};
});
// FreezeBullet class
var FreezeBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('FreezeBall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 45;
	self.vx = 0;
	self.scaleX = MaxScale;
	self.scaleY = MaxScale;
	self.update = function () {
		self.scaleX -= 0.1;
		self.scaleY -= 0.1;
		self.y -= self.speed;
		self.x += self.vx;
		self.rotation += 0.1; // Add rotation effect
		if (self.scaleX <= MinScale && self.scaleY <= MinScale) {
			var index = bullets.indexOf(self);
			if (index > -1) {
				bullets.splice(index, 1);
			}
			game.removeChild(self);
			self.destroy();
		}
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			var threshold = 0.1;
			if (self.intersects(enemy) && self.scaleY >= enemy.scaleY - threshold && self.scaleY <= enemy.scaleY + threshold) {
				// FreezeBullet hit the enemy
				// Show particle effect on impact
				var particleEffect = LK.getAsset('freezesplatter', {
					anchorX: 0.5,
					anchorY: 0.5,
					scaleX: 0.5,
					scaleY: 0.5
				});
				particleEffect.x = self.x;
				particleEffect.y = self.y;
				game.addChild(particleEffect);
				tween(particleEffect, {
					alpha: 0,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					onFinish: function onFinish() {
						game.removeChild(particleEffect);
						particleEffect.destroy();
					}
				});
				// Remove the bullet
				var index = bullets.indexOf(self);
				if (index > -1) {
					bullets.splice(index, 1);
				}
				game.removeChild(self);
				self.destroy();
				// Decrease enemy health by 2 units
				// enemy.health -= 2;
				if (enemy.prevState != STATES.FREEZE) {
					enemy.prevState = enemy.state;
					enemy.state = STATES.FREEZE;
				}
				// Flash enemy red when hit
				tween(enemy, {
					tint: 0x0000ff
				}, {
					duration: 100,
					onFinish: function onFinish() {
						tween(enemy, {
							tint: 0xFFFFFF
						}, {
							duration: 100
						});
					}
				});
				if (enemy.health <= 0) {
					// Destroy the enemy
					var enemyIndex = enemies.indexOf(enemy);
					if (enemyIndex > -1) {
						enemies.splice(enemyIndex, 1);
					}
					// Increment the kill counter
					killCounter++;
					killCounterText.setText('Kills: ' + killCounter);
					tween(enemy, {
						tint: 0xFF0000
					}, {
						duration: 100,
						onFinish: function onFinish() {
							game.removeChild(enemy);
							enemy.destroy();
						}
					});
				}
				break; // Stop the loop after one enemy is killed
			}
		}
		// Apply fade-in effect using tween
		tween(self, {
			alpha: 1
		}, {
			duration: 500,
			easing: tween.easeIn
		});
	};
});
//<Assets used in the game will automatically appear here>
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.update = function () {
		// Make the player invisible
		self.alpha = 0;
	};
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000 //Init game with black background 
});
/**** 
* Game Code
****/ 
// Create a brown rectangle box to cover the width of the screen
// Define states globally
var GameplayEffects = function GameplayEffects(actor) {
	this.actor = actor;
};
GameplayEffects.prototype.start = function () {
	// To be implemented by subclasses
};
GameplayEffects.prototype.update = function () {
	// To be implemented by subclasses
};
GameplayEffects.prototype.stop = function () {
	// To be implemented by subclasses
};
var FireEffect = function FireEffect(actor) {
	GameplayEffects.call(this, actor);
};
FireEffect.prototype = Object.create(GameplayEffects.prototype);
FireEffect.prototype.constructor = FireEffect;
FireEffect.prototype.start = function () {
	// Implement start logic for FireEffect
};
FireEffect.prototype.update = function () {
	// Implement update logic for FireEffect
};
FireEffect.prototype.stop = function () {
	// Implement stop logic for FireEffect
};
var STATES = {
	SPAWN: 'spawn',
	MOVE: 'move',
	ATTACK: 'attack',
	WAIT: 'wait',
	FREEZE: 'freeze'
};
var guiContainer = new Container();
var killCounterBackground = new Container();
var backgroundBox = LK.getAsset('rectangle', {
	anchorX: 0.5,
	anchorY: 0
});
backgroundBox.width = 2048; // Set width to cover the screen
backgroundBox.height = 150; // Set height to fit behind the text
backgroundBox.tint = 0x8B4513; // Brown color
killCounterBackground.addChild(backgroundBox);
killCounterBackground.y = 0; // Position at the top of the screen
killCounterBackground.x = backgroundBox.width / 2;
guiContainer.addChild(killCounterBackground);
// Initialize kill counter
var killCounter = 0;
// Create a Text2 object to display the kill counter
var killCounterText = new Text2('Kills: 0', {
	size: 100,
	fill: 0xf1ca04,
	font: "'Papyrus', 'Lucida Handwriting', 'Comic Sans MS'" // Use ancient script-like fonts
});
killCounterText.anchor.set(0.5, 0); // Center the text horizontally
killCounterText.x = killCounterBackground.width / 2;
guiContainer.addChild(killCounterText); // Add the text to the GUI container
// Initialize health circles
var healthCircles = [];
for (var i = 0; i < 3; i++) {
	var circle = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	circle.x = 2048 / 2 - 110 + i * 120; // Adjusted to have 20 units between circles
	circle.y = 2732 - 50;
	healthCircles.push(circle);
	guiContainer.addChild(circle);
}
// Initialize bullets
var bullets = [];
// Initialize bullet type
var currentBulletType = 'magic';
// Create a small circle to indicate the selected bullet type
var selectionIndicator = LK.getAsset('bulletselection', {
	anchorX: 0.5,
	anchorY: 0.5
});
selectionIndicator.scaleX = 1;
selectionIndicator.scaleY = 1;
guiContainer.addChild(selectionIndicator);
// Function to update the position of the selection indicator
function updateSelectionIndicator() {
	if (currentBulletType === 'magic') {
		selectionIndicator.x = magicButton.x;
		selectionIndicator.y = magicButton.y;
	} else if (currentBulletType === 'freeze' && typeof freezeButton !== 'undefined') {
		selectionIndicator.x = freezeButton.x;
		selectionIndicator.y = freezeButton.y;
	}
}
// Create button for Magic Ball
var magicButton = LK.getAsset('bullet', {
	anchorX: 0.5,
	anchorY: 0.5
});
magicButton.x = 100;
magicButton.y = 2732 - 100;
guiContainer.addChild(magicButton);
// Create button for Freeze Bullet
var freezeButton = LK.getAsset('FreezeBall', {
	anchorX: 0.5,
	anchorY: 0.5
});
freezeButton.x = 100;
freezeButton.y = 2732 - 300;
guiContainer.addChild(freezeButton);
// Create a fullscreen overlay
var fullscreenOverlay = LK.getAsset('overlay', {
	anchorX: 0.5,
	anchorY: 0.5
});
fullscreenOverlay.x = 2048 / 2;
fullscreenOverlay.y = 2732 / 2;
fullscreenOverlay.width = 2048;
fullscreenOverlay.height = 2732;
fullscreenOverlay.color = "#000000";
fullscreenOverlay.alpha = 0.5; // Set transparency level
fullscreenOverlay.visible = false;
// Add the fullscreen overlay to the GUI container
guiContainer.addChild(fullscreenOverlay);
// Initial position of the selection indicator
updateSelectionIndicator();
// Function to continuously fade in and out the selection indicator
function animateSelectionIndicator() {
	tween(selectionIndicator, {
		alpha: 0.5
	}, {
		duration: 500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(selectionIndicator, {
				alpha: 1
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: animateSelectionIndicator
			});
		}
	});
}
// Start the animation
animateSelectionIndicator();
//initialize the locations of hands.
var hand_initialy = 2732;
var lefthand_initialx = 2048 / 2 - 600;
var righthand_initialx = 2048 / 2 + 600;
// Handle player movement
game.move = function (x, y, obj) {
	player.x = (handsIdleLeft.x + handsIdleRight.x) / 2;
	player.y = (handsIdleLeft.y + handsIdleRight.y) / 2;
};
// Handle shooting and hand animation
game.down = function (x, y, obj) {
	console.log(obj, x, y);
	// Check if the click is on any bullet button
	var bulletButtons = [magicButton, freezeButton];
	for (var index = 0; index < bulletButtons.length; index++) {
		var button = bulletButtons[index];
		if (x >= button.x - button.width / 2 && x <= button.x + button.width / 2 && y >= button.y - button.height / 2 && y <= button.y + button.height / 2) {
			// Set current bullet type based on the button clicked
			currentBulletType = index === 0 ? 'magic' : 'freeze';
			// Update the position of the selection indicator
			updateSelectionIndicator();
			return;
		}
	}
	// Animate left hand
	tween(handsIdleLeft, {
		scaleX: 1.5,
		scaleY: 1.5,
		y: hand_initialy + 100
	}, {
		duration: 125,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(handsIdleLeft, {
				scaleX: 1,
				scaleY: 1,
				y: hand_initialy - 100
			}, {
				duration: 125,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Create bullet after animation
					var bullet;
					if (currentBulletType === 'freeze') {
						bullet = new FreezeBullet();
					} else {
						bullet = new Bullet();
					}
					bullet.x = player.x;
					bullet.y = player.y - 100;
					var dx = (x - player.x) / bullet.speed;
					bullet.vx = dx;
					bullets.push(bullet);
					game.addChild(bullet);
				}
			});
		}
	});
	// Animate right hand
	tween(handsIdleRight, {
		scaleX: -1.5,
		scaleY: 1.5,
		y: hand_initialy + 100
	}, {
		duration: 125,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(handsIdleRight, {
				scaleX: -1,
				scaleY: 1,
				y: hand_initialy - 100
			}, {
				duration: 125,
				easing: tween.easeInOut
			});
		}
	});
};
game.addChild(player);
// Initialize bullets
var bullets = [];
// Handle player movement
game.move = function (x, y, obj) {
	player.x = x;
	player.y = y;
};
// Handle shooting
game.addChild(player);
// Draw hands_idle image 200 units to the left of the horizontal center
//<Assets used in the game will automatically appear here>
var handsIdleLeft = game.addChild(LK.getAsset('hands_idle', {
	anchorX: 0.5,
	anchorY: 1
}));
handsIdleLeft.x = lefthand_initialx;
handsIdleLeft.y = hand_initialy;
handsIdleLeft.rotation = Math.PI / 6; // Rotate 30 degrees
//handsIdleLeft.scale.x = -1;
// Draw hands_idle image 200 units to the right of the horizontal center
var handsIdleRight = game.addChild(LK.getAsset('hands_idle', {
	anchorX: 0.5,
	anchorY: 1
}));
handsIdleRight.x = righthand_initialx;
handsIdleRight.y = hand_initialy;
handsIdleRight.rotation = -Math.PI / 6; // Rotate -30 degrees
handsIdleRight.scale.x = -1;
// Initialize player
// Define MinScale and MaxScale
var MinScale = 1;
var MaxScale = 4;
var player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 200;
// Initialize cyan rectangle
var cyanRectangle = game.addChild(LK.getAsset('cyanRectangle', {
	anchorX: 0,
	anchorY: 1
}));
cyanRectangle.x = 0;
cyanRectangle.y = 2732 / 2;
// Initialize another cyan rectangle
var cyanRectangle2 = game.addChild(LK.getAsset('cyanRectangle', {
	anchorX: 1,
	anchorY: 1
}));
cyanRectangle2.x = 2048;
cyanRectangle2.y = 2732 / 2;
// Initialize rectangle
var rectangle = game.addChild(LK.getAsset('rectangle', {
	anchorX: 0.5,
	anchorY: 1
}));
rectangle.x = 2048 / 2;
rectangle.y = 2732 / 2;
// Initialize grey rectangle
var greyRectangle = game.addChildAt(LK.getAsset('greyRectangle', {
	anchorX: 0.5,
	anchorY: 0
}), 0);
greyRectangle.x = 2048 / 2;
greyRectangle.y = 2732 / 2;
greyRectangle.height = 2732 / 2; // Adjust the height to cover the bottom half of the screen
// Define base_y variable
var base_y = greyRectangle.y - greyRectangle.height / 2;
// Initialize enemies
var enemies = [];
var enemyContainer = new Container();
game.addChild(enemyContainer);
var currentWave = 0;
function spawnWave() {
	var predefinedPositions = [300, 700, 1100, 1500, 1900]; // Predefined x positions for enemies
	var usedPositions = []; // Track used positions
	for (var i = 0; i < currentWave % 2 + 1; i++) {
		var enemy = new Enemy();
		var positionIndex;
		// Ensure each enemy picks a unique slot
		do {
			positionIndex = Math.floor(Math.random() * predefinedPositions.length);
		} while (usedPositions.includes(positionIndex));
		usedPositions.push(positionIndex);
		enemy.x = predefinedPositions[positionIndex];
		enemy.y = 2732 / 2 - enemy.height / 2 + 150;
		enemy.scaleX = 0;
		enemy.scaleY = 0;
		enemies.push(enemy);
		enemyContainer.addChild(enemy);
		// Tween enemy from random off screen point on X axis to spawn point
		var spawnX = enemy.x;
		enemy.x = Math.random() < 0.5 ? -100 : 2148; // Random off screen point on X axis
		tween(enemy, {
			x: spawnX
		}, {
			duration: 4000
		});
	}
	currentWave++;
}
spawnWave();
// Add enemies to game after the cyan and blue rectangles
for (var i = 0; i < enemies.length; i++) {
	game.addChild(enemies[i]);
}
// Ensure hands are drawn over enemies
game.addChild(handsIdleLeft);
game.addChild(handsIdleRight);
//add guicontainer after every other elment.
game.addChild(guiContainer);
// Initialize bullets
var bullets = [];
// Function to randomly select an enemy and set its canAttackPlayer to true
function selectRandomEnemy() {
	if (enemies.length > 0) {
		// Reset all enemies' canAttackPlayer to false
		enemies.forEach(function (enemy) {
			return enemy.canAttackPlayer = false;
		});
		// Select a random enemy
		var randomIndex = Math.floor(Math.random() * enemies.length);
		if (enemies[randomIndex].reachedTarget && enemies[randomIndex].state == STATES.ATTACK) {
			enemies[randomIndex].canAttackPlayer = true;
		}
	}
}
// Initialize enemy attack delay
var enemyAttackDelay = 3000; // 3 seconds in milliseconds
// Function to update enemy attack delay based on kill count
function updateEnemyAttackDelay() {
	enemyAttackDelay = 3000 - Math.floor(killCounter / 5) * 100;
	if (enemyAttackDelay < 1000) {
		enemyAttackDelay = 1000; // Minimum delay of 1 second
	}
}
// Set interval to select a random enemy based on dynamic delay
function scheduleEnemyAttack() {
	LK.setTimeout(function () {
		selectRandomEnemy();
		scheduleEnemyAttack();
	}, enemyAttackDelay);
}
// Start scheduling enemy attacks
scheduleEnemyAttack();
// Handle player movement
game.move = function (x, y, obj) {};
// Handle shooting
// Add player to game
game.addChild(player);
// Game update loop
game.update = function () {
	// Update enemies
	for (var j = 0; j < enemies.length; j++) {
		var enemy = enemies[j];
		enemy.update();
	}
	// Sort the enemies array in ascending order of enemy.y value
	enemyContainer.children.sort(function (a, b) {
		return a.y - b.y;
	});
	// Tween tint of hands over 20 frames
	var tweenDuration = 500;
	var hand_boby = 20;
	if (LK.ticks % 60 === 0) {
		tween(handsIdleLeft, {
			y: hand_initialy - hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
		tween(handsIdleRight, {
			y: hand_initialy - hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
	} else if (LK.ticks % 60 === 30) {
		tween(handsIdleLeft, {
			y: hand_initialy + hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
		tween(handsIdleRight, {
			y: hand_initialy + hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
	}
	// Check if all enemies are dead or frozen
	if (enemies.length === 0) {
		// Spawn a new wave if all enemies are dead or frozen
		spawnWave();
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Bullet class
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 45;
	self.vx = 0;
	self.scaleX = MaxScale;
	self.scaleY = MaxScale;
	self.update = function () {
		self.scaleX -= 0.1;
		self.scaleY -= 0.1;
		self.y -= self.speed;
		self.x += self.vx;
		self.rotation += 0.1; // Add rotation effect
		if (self.scaleX <= MinScale && self.scaleY <= MinScale) {
			var index = bullets.indexOf(self);
			if (index > -1) {
				bullets.splice(index, 1);
			}
			game.removeChild(self);
			self.destroy();
		}
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			var threshold = 0.1;
			if (self.intersects(enemy) && self.scaleY >= enemy.scaleY - threshold && self.scaleY <= enemy.scaleY + threshold) {
				// Bullet hit the enemy
				// Show particle effect on impact
				var particleEffect = LK.getAsset('bloodSplatter', {
					anchorX: 0.5,
					anchorY: 0.5,
					scaleX: 0.5,
					scaleY: 0.5
				});
				particleEffect.x = self.x;
				particleEffect.y = self.y;
				game.addChild(particleEffect);
				tween(particleEffect, {
					alpha: 0,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					onFinish: function onFinish() {
						game.removeChild(particleEffect);
						particleEffect.destroy();
					}
				});
				// Remove the bullet
				var index = bullets.indexOf(self);
				if (index > -1) {
					bullets.splice(index, 1);
				}
				game.removeChild(self);
				self.destroy();
				//shake the enemy for 0.5 seconds if they are hit by bullet when frozen. 
				if (enemy.state == STATES.FREEZE) {
					enemy.shake();
				} else {
					// Play orc_hurt1 or orc_hurt2 sound at random if the enemy is not frozen.
					var hurtSound = Math.random() < 0.5 ? 'orc_hurt1' : 'orc_hurt2';
					LK.getSound(hurtSound).play();
					// Flash enemy red when hit
					tween(enemy, {
						tint: 0xFF0000
					}, {
						duration: 100,
						onFinish: function onFinish() {
							tween(enemy, {
								tint: 0xFFFFFF
							}, {
								duration: 100
							});
						}
					});
				}
				// Decrease enemy health
				enemy.health -= 1;
				if (enemy.health <= 0 && enemy.state != STATES.DEAD) {
					enemy.prevState = enemy.state;
					enemy.state = STATES.DEAD;
					// Increment the kill counter
					killCounter++;
					killCounterText.setText('Kills: ' + killCounter);
					enemy.onDeath();
				}
				break; // Stop the loop after one enemy is killed
			}
		}
		// Apply fade-in effect using tween
		tween(self, {
			alpha: 1
		}, {
			duration: 500,
			easing: tween.easeIn
		});
	};
});
// Enemy class
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Define states
	var STATES = {
		SPAWN: 'spawn',
		MOVE: 'move',
		ATTACK: 'attack',
		WAIT: 'wait',
		FREEZE: 'freeze',
		HURT: 'hurt',
		DEAD: 'dead'
	};
	// Initialize state
	self.state = STATES.SPAWN;
	self.prevState = null;
	//handle dead state.
	self.onDeath = function () {
		var enemy = self;
		// Destroy the enemy
		var enemyIndex = enemies.indexOf(enemy);
		if (enemyIndex > -1) {
			enemies.splice(enemyIndex, 1);
		}
		tween(enemy, {
			tint: 0xFF0000,
			scaleY: enemy.scaleY - 0.5,
			alpha: 0,
			y: enemy.y - 300
		}, {
			duration: 500,
			onFinish: function onFinish() {
				game.removeChild(enemy);
				enemy.destroy();
			}
		});
	};
	self.shake = function () {
		var offsetVal = Math.random() < 0.5 ? -10 : 10;
		// Shake the enemy for 0.5 seconds
		tween(self, {
			x: self.x + offsetVal
		}, {
			duration: 100,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				tween(self, {
					x: self.x - offsetVal
				}, {
					duration: 100,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						tween(self, {
							x: self.x
						}, {
							duration: 100,
							easing: tween.easeInOut
						});
					}
				});
			}
		});
	};
	// State machine handler
	self.handleState = function () {
		switch (self.state) {
			case STATES.SPAWN:
				self.handleSpawnState();
				break;
			case STATES.MOVE:
				self.handleMoveState();
				break;
			case STATES.ATTACK:
				self.handleAttackState();
				break;
			case STATES.WAIT:
				self.handleWaitState();
				break;
			case STATES.FREEZE:
				self.handleFreezeState();
				break;
		}
	};
	//handle freeze state.
	self.handleFreezeState = function () {
		// Tint the enemy blue
		tween(self, {
			tint: 0x0000FF
		}, {
			duration: 250,
			onFinish: function onFinish() {
				// Tint the enemy white
				tween(self, {
					tint: 0xFFFFFF
				}, {
					duration: 250,
					onFinish: function onFinish() {
						// Repeat the tinting effect for 5 seconds
						LK.setTimeout(function () {
							self.state = self.prevState; // Return to previous state after 5 seconds
						}, 5000);
					}
				});
			}
		});
	};
	// Handle spawn state
	self.handleSpawnState = function () {
		// Transition to move state after spawn tween is done
		if (self.speed == 2) {
			self.prevState = self.state;
			self.state = STATES.MOVE;
		}
	};
	// Handle move state
	self.handleMoveState = function () {
		// Rotate enemy 10 degrees to the left and right alternatively
		if (LK.ticks % 60 < 30) {
			self.rotation = self.startRotation * Math.PI / 36; // Rotate 10 degrees to the left or right based on startRotation
		} else {
			self.rotation = -self.startRotation * Math.PI / 36; // Rotate 10 degrees to the right or left based on startRotation
		}
		if (self.y + self.speed < 2732 - 600) {
			self.targetReachedTime = null; // Reset targetReachedTime when moving away from target
			self.y += self.speed;
			self.scaleX += 0.002;
			self.scaleY += 0.002;
		} else {
			// Reset rotation to zero when reaching target
			self.rotation = 0;
			self.reachedTarget = true; // Set reachedTarget to true when target is reached
			self.prevState = self.state;
			//Transition to the wait state. 
			self.state = STATES.WAIT;
		}
		// Pause enemy movement every 0.5 seconds for a duration of 0.25 seconds
		if (LK.ticks % 30 == 0) {
			self.speed = 0;
			LK.setTimeout(function () {
				self.speed = 2;
			}, 250);
		}
	};
	// Handle wait state
	self.handleWaitState = function () {
		// Transition to move state after waiting for 1 second
		if (!self.waitStartTime) {
			self.waitStartTime = Date.now();
		}
		if (Date.now() - self.waitStartTime >= 1000) {
			self.prevState = self.state;
			self.state = STATES.ATTACK;
			self.waitStartTime = null;
		}
	};
	// Handle attack state
	self.handleAttackState = function () {
		// Check if enemy can attack player
		if (self.canAttackPlayer === false) {
			return;
		}
		// Play sword slash sound effect
		LK.getSound('sword_slash').play();
		//toggle the canAttack so we dont' execute this again. 
		self.canAttackPlayer = false;
		// Change enemy image to attack start
		self.removeChild(enemyGraphics);
		enemyGraphics = self.addChild(self.imageDictionary.enemy_attack_start);
		var curScale = self.scaleX;
		var curPos = {
			x: self.x,
			y: self.y
		};
		// Animate enemy to move towards player and back
		tween(self, {
			x: player.x,
			y: player.y + player.height,
			scaleX: curScale + 2,
			scaleY: curScale + 2
		}, {
			duration: 250,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				// Reduce health by making a circle invisible
				if (healthCircles.length > 0) {
					var circle = healthCircles.pop();
					circle.visible = false;
				}
				// End game if no health circles are visible
				if (healthCircles.length === 0) {
					LK.showGameOver();
				}
				//show attack_finish on anim finish
				self.removeChild(enemyGraphics);
				enemyGraphics = self.addChild(self.imageDictionary.enemy_attack_finish);
				// Flash the player's hands red to indicate an attack
				tween(handsIdleLeft, {
					tint: 0xFF0000
				}, {
					duration: 250,
					onFinish: function onFinish() {
						tween(handsIdleLeft, {
							tint: 0xFFFFFF
						}, {
							duration: 250
						});
					}
				});
				tween(handsIdleRight, {
					tint: 0xFF0000
				}, {
					duration: 250,
					onFinish: function onFinish() {
						tween(handsIdleRight, {
							tint: 0xFFFFFF
						}, {
							duration: 250
						});
					}
				});
				tween(self, {
					x: curPos.x,
					y: curPos.y,
					scaleX: curScale,
					scaleY: curScale
				}, {
					duration: 250,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						self.removeChild(enemyGraphics);
						enemyGraphics = self.addChild(self.imageDictionary.idle);
					}
				});
			}
		});
	};
	// Dictionary of images for the enemy
	self.imageDictionary = {
		idle: LK.getAsset('enemy', {
			anchorX: 0.5,
			anchorY: 1
		}),
		attack: LK.getAsset('hands_idle', {
			anchorX: 0.5,
			anchorY: 1
		}),
		hit: LK.getAsset('bloodSplatter', {
			anchorX: 0.5,
			anchorY: 1
		}),
		enemy_attack_start: LK.getAsset('enemy_attack_start', {
			anchorX: 0.5,
			anchorY: 1
		}),
		enemy_attack_finish: LK.getAsset('enemy_attack_finish', {
			anchorX: 0.5,
			anchorY: 1
		})
	};
	// Attach the default enemy image
	var enemyGraphics = self.addChild(self.imageDictionary.idle);
	self.health = Math.min(2 + Math.floor(killCounter / 5), 10); // Initialize health based on kill count
	self.reachedTarget = false; // Initialize reachedTarget to false
	self.canAttackPlayer = false; // Initialize canAttackPlayer to false
	self.speed = 0;
	self.scaleX = MinScale;
	self.scaleY = MinScale / 4;
	tween(self, {
		scaleX: MinScale,
		scaleY: MinScale
	}, {
		duration: 250,
		onFinish: function onFinish() {
			self.speed = 0;
			LK.setTimeout(function () {
				self.speed = 2;
			}, 500);
		}
	});
	// Assign a random starting rotation to each enemy
	self.startRotation = Math.random() < 0.5 ? -1 : 1;
	self.handleTargetReached = function () {};
	self.update = function () {
		self.handleState(); // Call state machine handler
		return;
	};
});
// FreezeBullet class
var FreezeBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('FreezeBall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 45;
	self.vx = 0;
	self.scaleX = MaxScale;
	self.scaleY = MaxScale;
	self.update = function () {
		self.scaleX -= 0.1;
		self.scaleY -= 0.1;
		self.y -= self.speed;
		self.x += self.vx;
		self.rotation += 0.1; // Add rotation effect
		if (self.scaleX <= MinScale && self.scaleY <= MinScale) {
			var index = bullets.indexOf(self);
			if (index > -1) {
				bullets.splice(index, 1);
			}
			game.removeChild(self);
			self.destroy();
		}
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			var threshold = 0.1;
			if (self.intersects(enemy) && self.scaleY >= enemy.scaleY - threshold && self.scaleY <= enemy.scaleY + threshold) {
				// FreezeBullet hit the enemy
				// Show particle effect on impact
				var particleEffect = LK.getAsset('freezesplatter', {
					anchorX: 0.5,
					anchorY: 0.5,
					scaleX: 0.5,
					scaleY: 0.5
				});
				particleEffect.x = self.x;
				particleEffect.y = self.y;
				game.addChild(particleEffect);
				tween(particleEffect, {
					alpha: 0,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					onFinish: function onFinish() {
						game.removeChild(particleEffect);
						particleEffect.destroy();
					}
				});
				// Remove the bullet
				var index = bullets.indexOf(self);
				if (index > -1) {
					bullets.splice(index, 1);
				}
				game.removeChild(self);
				self.destroy();
				// Decrease enemy health by 2 units
				// enemy.health -= 2;
				if (enemy.prevState != STATES.FREEZE) {
					enemy.prevState = enemy.state;
					enemy.state = STATES.FREEZE;
				}
				// Flash enemy red when hit
				tween(enemy, {
					tint: 0x0000ff
				}, {
					duration: 100,
					onFinish: function onFinish() {
						tween(enemy, {
							tint: 0xFFFFFF
						}, {
							duration: 100
						});
					}
				});
				if (enemy.health <= 0) {
					// Destroy the enemy
					var enemyIndex = enemies.indexOf(enemy);
					if (enemyIndex > -1) {
						enemies.splice(enemyIndex, 1);
					}
					// Increment the kill counter
					killCounter++;
					killCounterText.setText('Kills: ' + killCounter);
					tween(enemy, {
						tint: 0xFF0000
					}, {
						duration: 100,
						onFinish: function onFinish() {
							game.removeChild(enemy);
							enemy.destroy();
						}
					});
				}
				break; // Stop the loop after one enemy is killed
			}
		}
		// Apply fade-in effect using tween
		tween(self, {
			alpha: 1
		}, {
			duration: 500,
			easing: tween.easeIn
		});
	};
});
//<Assets used in the game will automatically appear here>
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 10;
	self.update = function () {
		// Make the player invisible
		self.alpha = 0;
	};
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000 //Init game with black background 
});
/**** 
* Game Code
****/ 
// Create a brown rectangle box to cover the width of the screen
// Define states globally
var GameplayEffects = function GameplayEffects(actor) {
	this.actor = actor;
};
GameplayEffects.prototype.start = function () {
	// To be implemented by subclasses
};
GameplayEffects.prototype.update = function () {
	// To be implemented by subclasses
};
GameplayEffects.prototype.stop = function () {
	// To be implemented by subclasses
};
var FireEffect = function FireEffect(actor) {
	GameplayEffects.call(this, actor);
};
FireEffect.prototype = Object.create(GameplayEffects.prototype);
FireEffect.prototype.constructor = FireEffect;
FireEffect.prototype.start = function () {
	// Implement start logic for FireEffect
};
FireEffect.prototype.update = function () {
	// Implement update logic for FireEffect
};
FireEffect.prototype.stop = function () {
	// Implement stop logic for FireEffect
};
var STATES = {
	SPAWN: 'spawn',
	MOVE: 'move',
	ATTACK: 'attack',
	WAIT: 'wait',
	FREEZE: 'freeze'
};
var guiContainer = new Container();
var killCounterBackground = new Container();
var backgroundBox = LK.getAsset('rectangle', {
	anchorX: 0.5,
	anchorY: 0
});
backgroundBox.width = 2048; // Set width to cover the screen
backgroundBox.height = 150; // Set height to fit behind the text
backgroundBox.tint = 0x8B4513; // Brown color
killCounterBackground.addChild(backgroundBox);
killCounterBackground.y = 0; // Position at the top of the screen
killCounterBackground.x = backgroundBox.width / 2;
guiContainer.addChild(killCounterBackground);
// Initialize kill counter
var killCounter = 0;
// Create a Text2 object to display the kill counter
var killCounterText = new Text2('Kills: 0', {
	size: 100,
	fill: 0xf1ca04,
	font: "'Papyrus', 'Lucida Handwriting', 'Comic Sans MS'" // Use ancient script-like fonts
});
killCounterText.anchor.set(0.5, 0); // Center the text horizontally
killCounterText.x = killCounterBackground.width / 2;
guiContainer.addChild(killCounterText); // Add the text to the GUI container
// Initialize health circles
var healthCircles = [];
for (var i = 0; i < 3; i++) {
	var circle = LK.getAsset('centerCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	circle.x = 2048 / 2 - 110 + i * 120; // Adjusted to have 20 units between circles
	circle.y = 2732 - 50;
	healthCircles.push(circle);
	guiContainer.addChild(circle);
}
// Initialize bullets
var bullets = [];
// Initialize bullet type
var currentBulletType = 'magic';
// Create a small circle to indicate the selected bullet type
var selectionIndicator = LK.getAsset('bulletselection', {
	anchorX: 0.5,
	anchorY: 0.5
});
selectionIndicator.scaleX = 1;
selectionIndicator.scaleY = 1;
guiContainer.addChild(selectionIndicator);
// Function to update the position of the selection indicator
function updateSelectionIndicator() {
	if (currentBulletType === 'magic') {
		selectionIndicator.x = magicButton.x;
		selectionIndicator.y = magicButton.y;
	} else if (currentBulletType === 'freeze' && typeof freezeButton !== 'undefined') {
		selectionIndicator.x = freezeButton.x;
		selectionIndicator.y = freezeButton.y;
	}
}
// Create button for Magic Ball
var magicButton = LK.getAsset('bullet', {
	anchorX: 0.5,
	anchorY: 0.5
});
magicButton.x = 100;
magicButton.y = 2732 - 100;
guiContainer.addChild(magicButton);
// Create button for Freeze Bullet
var freezeButton = LK.getAsset('FreezeBall', {
	anchorX: 0.5,
	anchorY: 0.5
});
freezeButton.x = 100;
freezeButton.y = 2732 - 300;
guiContainer.addChild(freezeButton);
// Create a fullscreen overlay
var fullscreenOverlay = LK.getAsset('overlay', {
	anchorX: 0.5,
	anchorY: 0.5
});
fullscreenOverlay.x = 2048 / 2;
fullscreenOverlay.y = 2732 / 2;
fullscreenOverlay.width = 2048;
fullscreenOverlay.height = 2732;
fullscreenOverlay.color = "#000000";
fullscreenOverlay.alpha = 0.5; // Set transparency level
fullscreenOverlay.visible = false;
// Add the fullscreen overlay to the GUI container
guiContainer.addChild(fullscreenOverlay);
// Initial position of the selection indicator
updateSelectionIndicator();
// Function to continuously fade in and out the selection indicator
function animateSelectionIndicator() {
	tween(selectionIndicator, {
		alpha: 0.5
	}, {
		duration: 500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(selectionIndicator, {
				alpha: 1
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: animateSelectionIndicator
			});
		}
	});
}
// Start the animation
animateSelectionIndicator();
//initialize the locations of hands.
var hand_initialy = 2732;
var lefthand_initialx = 2048 / 2 - 600;
var righthand_initialx = 2048 / 2 + 600;
// Handle player movement
game.move = function (x, y, obj) {
	player.x = (handsIdleLeft.x + handsIdleRight.x) / 2;
	player.y = (handsIdleLeft.y + handsIdleRight.y) / 2;
};
// Handle shooting and hand animation
game.down = function (x, y, obj) {
	console.log(obj, x, y);
	// Check if the click is on any bullet button
	var bulletButtons = [magicButton, freezeButton];
	for (var index = 0; index < bulletButtons.length; index++) {
		var button = bulletButtons[index];
		if (x >= button.x - button.width / 2 && x <= button.x + button.width / 2 && y >= button.y - button.height / 2 && y <= button.y + button.height / 2) {
			// Set current bullet type based on the button clicked
			currentBulletType = index === 0 ? 'magic' : 'freeze';
			// Update the position of the selection indicator
			updateSelectionIndicator();
			return;
		}
	}
	// Animate left hand
	tween(handsIdleLeft, {
		scaleX: 1.5,
		scaleY: 1.5,
		y: hand_initialy + 100
	}, {
		duration: 125,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(handsIdleLeft, {
				scaleX: 1,
				scaleY: 1,
				y: hand_initialy - 100
			}, {
				duration: 125,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Create bullet after animation
					var bullet;
					if (currentBulletType === 'freeze') {
						bullet = new FreezeBullet();
					} else {
						bullet = new Bullet();
					}
					bullet.x = player.x;
					bullet.y = player.y - 100;
					var dx = (x - player.x) / bullet.speed;
					bullet.vx = dx;
					bullets.push(bullet);
					game.addChild(bullet);
				}
			});
		}
	});
	// Animate right hand
	tween(handsIdleRight, {
		scaleX: -1.5,
		scaleY: 1.5,
		y: hand_initialy + 100
	}, {
		duration: 125,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(handsIdleRight, {
				scaleX: -1,
				scaleY: 1,
				y: hand_initialy - 100
			}, {
				duration: 125,
				easing: tween.easeInOut
			});
		}
	});
};
game.addChild(player);
// Initialize bullets
var bullets = [];
// Handle player movement
game.move = function (x, y, obj) {
	player.x = x;
	player.y = y;
};
// Handle shooting
game.addChild(player);
// Draw hands_idle image 200 units to the left of the horizontal center
//<Assets used in the game will automatically appear here>
var handsIdleLeft = game.addChild(LK.getAsset('hands_idle', {
	anchorX: 0.5,
	anchorY: 1
}));
handsIdleLeft.x = lefthand_initialx;
handsIdleLeft.y = hand_initialy;
handsIdleLeft.rotation = Math.PI / 6; // Rotate 30 degrees
//handsIdleLeft.scale.x = -1;
// Draw hands_idle image 200 units to the right of the horizontal center
var handsIdleRight = game.addChild(LK.getAsset('hands_idle', {
	anchorX: 0.5,
	anchorY: 1
}));
handsIdleRight.x = righthand_initialx;
handsIdleRight.y = hand_initialy;
handsIdleRight.rotation = -Math.PI / 6; // Rotate -30 degrees
handsIdleRight.scale.x = -1;
// Initialize player
// Define MinScale and MaxScale
var MinScale = 1;
var MaxScale = 4;
var player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 200;
// Initialize cyan rectangle
var cyanRectangle = game.addChild(LK.getAsset('cyanRectangle', {
	anchorX: 0,
	anchorY: 1
}));
cyanRectangle.x = 0;
cyanRectangle.y = 2732 / 2;
// Initialize another cyan rectangle
var cyanRectangle2 = game.addChild(LK.getAsset('cyanRectangle', {
	anchorX: 1,
	anchorY: 1
}));
cyanRectangle2.x = 2048;
cyanRectangle2.y = 2732 / 2;
// Initialize rectangle
var rectangle = game.addChild(LK.getAsset('rectangle', {
	anchorX: 0.5,
	anchorY: 1
}));
rectangle.x = 2048 / 2;
rectangle.y = 2732 / 2;
// Initialize grey rectangle
var greyRectangle = game.addChildAt(LK.getAsset('greyRectangle', {
	anchorX: 0.5,
	anchorY: 0
}), 0);
greyRectangle.x = 2048 / 2;
greyRectangle.y = 2732 / 2;
greyRectangle.height = 2732 / 2; // Adjust the height to cover the bottom half of the screen
// Define base_y variable
var base_y = greyRectangle.y - greyRectangle.height / 2;
// Initialize enemies
var enemies = [];
var enemyContainer = new Container();
game.addChild(enemyContainer);
var currentWave = 0;
function spawnWave() {
	var predefinedPositions = [300, 700, 1100, 1500, 1900]; // Predefined x positions for enemies
	var usedPositions = []; // Track used positions
	for (var i = 0; i < currentWave % 2 + 1; i++) {
		var enemy = new Enemy();
		var positionIndex;
		// Ensure each enemy picks a unique slot
		do {
			positionIndex = Math.floor(Math.random() * predefinedPositions.length);
		} while (usedPositions.includes(positionIndex));
		usedPositions.push(positionIndex);
		enemy.x = predefinedPositions[positionIndex];
		enemy.y = 2732 / 2 - enemy.height / 2 + 150;
		enemy.scaleX = 0;
		enemy.scaleY = 0;
		enemies.push(enemy);
		enemyContainer.addChild(enemy);
		// Tween enemy from random off screen point on X axis to spawn point
		var spawnX = enemy.x;
		enemy.x = Math.random() < 0.5 ? -100 : 2148; // Random off screen point on X axis
		tween(enemy, {
			x: spawnX
		}, {
			duration: 4000
		});
	}
	currentWave++;
}
spawnWave();
// Add enemies to game after the cyan and blue rectangles
for (var i = 0; i < enemies.length; i++) {
	game.addChild(enemies[i]);
}
// Ensure hands are drawn over enemies
game.addChild(handsIdleLeft);
game.addChild(handsIdleRight);
//add guicontainer after every other elment.
game.addChild(guiContainer);
// Initialize bullets
var bullets = [];
// Function to randomly select an enemy and set its canAttackPlayer to true
function selectRandomEnemy() {
	if (enemies.length > 0) {
		// Reset all enemies' canAttackPlayer to false
		enemies.forEach(function (enemy) {
			return enemy.canAttackPlayer = false;
		});
		// Select a random enemy
		var randomIndex = Math.floor(Math.random() * enemies.length);
		if (enemies[randomIndex].reachedTarget && enemies[randomIndex].state == STATES.ATTACK) {
			enemies[randomIndex].canAttackPlayer = true;
		}
	}
}
// Initialize enemy attack delay
var enemyAttackDelay = 3000; // 3 seconds in milliseconds
// Function to update enemy attack delay based on kill count
function updateEnemyAttackDelay() {
	enemyAttackDelay = 3000 - Math.floor(killCounter / 5) * 100;
	if (enemyAttackDelay < 1000) {
		enemyAttackDelay = 1000; // Minimum delay of 1 second
	}
}
// Set interval to select a random enemy based on dynamic delay
function scheduleEnemyAttack() {
	LK.setTimeout(function () {
		selectRandomEnemy();
		scheduleEnemyAttack();
	}, enemyAttackDelay);
}
// Start scheduling enemy attacks
scheduleEnemyAttack();
// Handle player movement
game.move = function (x, y, obj) {};
// Handle shooting
// Add player to game
game.addChild(player);
// Game update loop
game.update = function () {
	// Update enemies
	for (var j = 0; j < enemies.length; j++) {
		var enemy = enemies[j];
		enemy.update();
	}
	// Sort the enemies array in ascending order of enemy.y value
	enemyContainer.children.sort(function (a, b) {
		return a.y - b.y;
	});
	// Tween tint of hands over 20 frames
	var tweenDuration = 500;
	var hand_boby = 20;
	if (LK.ticks % 60 === 0) {
		tween(handsIdleLeft, {
			y: hand_initialy - hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
		tween(handsIdleRight, {
			y: hand_initialy - hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
	} else if (LK.ticks % 60 === 30) {
		tween(handsIdleLeft, {
			y: hand_initialy + hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
		tween(handsIdleRight, {
			y: hand_initialy + hand_boby
		}, {
			duration: tweenDuration,
			easing: tween.easeOut
		});
	}
	// Check if all enemies are dead or frozen
	if (enemies.length === 0) {
		// Spawn a new wave if all enemies are dead or frozen
		spawnWave();
	}
};
:quality(85)/https://cdn.frvr.ai/67c66e43e7bf9ded3c425410.png%3F3) 
 magic energy ball in 16 bit pixel art style. It should have a glow effect so it feels like a powerful magic spell. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67c6de63937553d0582ec412.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67c7bcae14a81dccd3896efc.png%3F3) 
 brick wall with shield and swords hanging in the middle of it.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67c7bdca14a81dccd3896f11.png%3F3) 
 the brick wall is seamless and i should be able to use it to repeat the image multiple times by placing them side by side.
:quality(85)/https://cdn.frvr.ai/67c7c25414a81dccd3896f32.png%3F3) 
 dungeon floor with cracks in the floor. Small grass scattered on the floor. . No shadows. 2d. In-Game asset. flat
:quality(85)/https://cdn.frvr.ai/67c9c5626c67cfe40f8d0ec2.png%3F3) 
 red colored heart for representing player health in the game.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67ca5b689febb78ebd21dbe8.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67cb26903b19280b799c6730.png%3F3) 
 Magical projectile that will freeze the enemies.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67d0ee4a094bc712dffe0ac4.png%3F3) 
 magic projectile impact effect. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67d5c169a2c38300477f4a4d.png%3F3) 
 magical fireball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67ea45df5386bc54cdfb258b.png%3F3) 
 orc mage, leather armor, staff with glowing crystal with freezing power. front facing, arms and legs clearly visible, wearing a hood made of cloth.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows, 16 bit pixel art