/**** 
* 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();
	}
};
 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
 
 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
 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.
 dungeon floor with cracks in the floor. Small grass scattered on the floor. . No shadows. 2d. In-Game asset. flat
 red colored heart for representing player health in the game.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 
 Magical projectile that will freeze the enemies.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 magic projectile impact effect. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 magical fireball. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 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