User prompt
haz que el ogro tenga 2 de vida
User prompt
haz que cada los esqueletos tengan 1 de vida
User prompt
haz que cuando se congelan el color azul se quita despues que se quite el efecto de azul de los enemigos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ahora haz que se congelen por 1s
User prompt
haz que los enemigos no se muevan por 0.5s cuando se congelan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cauando los enemigos se congelen por la mejora se quedaran paralizados por 0.5 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cambia la mejora de frost armor por una que congele a los enemigos cada 4 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cuando el menu de mejora se abre haz que se pausen las mejoras
User prompt
cambia la opcion de speed boost por una que cada 4 segundos empuje a todos los enemigos hacia atras a los enemigos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cambia la opcion de speed boost por una que cada 5 segundos empuje para atras a los enemigos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
expande el menu de mejoras para que se pueda poner hasta 10 mejoras
User prompt
crea una mejora que haga un disparo doble
User prompt
separa un poco las mejoras
User prompt
crea una quinta mejora que te permita disparar doble
User prompt
crea una mejora que haga un disparo doble
User prompt
quita el menu naranja que aparece antes del menu principal
User prompt
ahora haz una interfaz de menu de inicio con un color blanco hueso
User prompt
haz que aparesca un tercer menu de mejoras despeues del enemigo 50
User prompt
pon la esfera un poquito mas a la drecha y un poquito mas ababjo
User prompt
haz que la esfera este a un lado del jugador
User prompt
haz que la esfera no se mueva
User prompt
agrega una mejora que ponga una esfera de energia que cada 3s haga un ataque a el enemigo mas cercano ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
arreglalo
User prompt
haz que el coste inicial de las mejoras sea 5
User prompt
aumenta las monedas cuando el menu es mostrado
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coinGraphics = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.bobOffset = Math.random() * Math.PI * 2;
	self.initialY = 0;
	self.update = function () {
		if (self.initialY === 0) {
			self.initialY = self.y;
		}
		// Only do bobbing animation and collection if not animating to coin counter
		if (!self.isAnimating) {
			// Bobbing animation
			self.y = self.initialY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 10;
			// Check collection by knight
			if (knight && self.intersects(knight)) {
				self.collect();
			}
		}
	};
	self.collect = function () {
		LK.getSound('coinCollect').play();
		LK.setScore(LK.getScore() + 5);
		coinCounter++;
		coinText.setText('Coins: ' + coinCounter);
		// Remove from coins array
		for (var i = coins.length - 1; i >= 0; i--) {
			if (coins[i] === self) {
				coins.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
// Game arrays to track objects
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Animation system for skeleton
	self.currentFrame = 1;
	self.animationTimer = 0;
	self.animationSpeed = 15; // Change frame every 15 ticks (250ms at 60fps)
	self.animationState = 'walking'; // walking, attacking, dying, idle
	// Create all skeleton graphics frames and store them
	self.skeletonFrames = [];
	for (var i = 1; i <= 4; i++) {
		var frameGraphics = self.attachAsset('esqueleto' + i, {
			anchorX: 0.5,
			anchorY: 1.0,
			scaleX: 2.0,
			scaleY: 2.0
		});
		frameGraphics.visible = i === 1; // Only show first frame initially
		self.skeletonFrames.push(frameGraphics);
	}
	// Create invisible hitbox with double size
	var hitbox = self.attachAsset('esqueleto1', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 4,
		scaleY: 4
	});
	hitbox.alpha = 0; // Make hitbox invisible
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 7;
	// Note: health, maxHealth and speed will be overridden by difficulty system
	self.lastX = 0;
	self.update = function () {
		// Animation system - cycle through skeleton frames based on state
		self.animationTimer++;
		var frameSpeed = self.animationSpeed;
		if (self.animationState === 'attacking') {
			frameSpeed = 8; // Faster animation for attacking
		} else if (self.animationState === 'dying') {
			frameSpeed = 20; // Slower animation for dying
		} else if (self.animationState === 'idle') {
			frameSpeed = 25; // Very slow animation for idle
		}
		if (self.animationTimer >= frameSpeed) {
			self.animationTimer = 0;
			// Hide current frame
			self.skeletonFrames[self.currentFrame - 1].visible = false;
			// Move to next frame based on animation state
			if (self.animationState === 'walking') {
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 1;
				}
			} else if (self.animationState === 'attacking') {
				// Cycle through frames 2-4 for attacking
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 2;
				}
			} else if (self.animationState === 'dying') {
				// Play frames 3-4 once for dying
				if (self.currentFrame < 4) {
					self.currentFrame++;
				}
			} else if (self.animationState === 'idle') {
				// Cycle between frames 1-2 for idle
				self.currentFrame = self.currentFrame === 1 ? 2 : 1;
			}
			// Show new frame
			self.skeletonFrames[self.currentFrame - 1].visible = true;
		}
		// Progressive speed increase - increase speed by 50% over 10 seconds
		if (!self.speedTweenStarted) {
			self.speedTweenStarted = true;
			var targetSpeed = self.speed * 2.5; // Increase speed by 150%
			tween(self, {
				speed: targetSpeed
			}, {
				duration: 10000,
				// 10 seconds
				easing: tween.easeOut
			});
		}
		// Always move directly toward the wizard to ensure enemies reach the player
		if (wizard) {
			// Calculate direction from enemy to wizard
			var dx = wizard.x - self.x;
			var dy = wizard.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				// Normalize direction and apply speed
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			// Face toward the wizard - flip horizontally based on wizard position
			if (dx < 0) {
				// Wizard is to the left - flip to face left
				for (var frameIdx = 0; frameIdx < self.skeletonFrames.length; frameIdx++) {
					self.skeletonFrames[frameIdx].scaleX = -2.0; // Flip to face left
				}
			} else {
				// Wizard is to the right - face right
				for (var frameIdx = 0; frameIdx < self.skeletonFrames.length; frameIdx++) {
					self.skeletonFrames[frameIdx].scaleX = 2.0; // Normal orientation to face right
				}
			}
		} else {
			// Fallback: move down if wizard doesn't exist
			self.y += self.speed;
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		// Change animation state to attacking when hit
		self.animationState = 'attacking';
		// Flash red when hit
		LK.effects.flashObject(self, 0xFF0000, 200);
		// Return to walking animation after brief attacking animation
		tween({}, {}, {
			duration: 300,
			onFinish: function onFinish() {
				if (self.animationState === 'attacking') {
					self.animationState = 'walking';
				}
			}
		});
		// Enemies die from any projectile hit
		self.die();
	};
	self.down = function (x, y, obj) {
		// Set this enemy as the selected target
		selectedEnemy = self;
		// Visual feedback for selection
		LK.effects.flashObject(self, 0xFFFF00, 500); // Yellow flash to indicate selection
		// Create projectile from wizard to enemy when enemy is tapped
		if (wizard && projectiles.length < 10) {
			// Limit projectiles to prevent spam
			var projectile = game.addChild(new Projectile());
			projectile.x = wizard.x;
			projectile.y = wizard.y;
			// Calculate direction from wizard to enemy
			var dx = self.x - wizard.x;
			var dy = self.y - wizard.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				projectile.direction.x = dx / distance;
				projectile.direction.y = dy / distance;
			}
			projectile.targetEnemy = self; // Set the target for this projectile
			projectiles.push(projectile);
			LK.getSound('spellCast').play();
		}
	};
	self.die = function () {
		// Change animation state to dying
		self.animationState = 'dying';
		self.currentFrame = 3; // Start dying animation from frame 3
		// Play pain sound when enemy dies
		LK.getSound('painSound').play();
		// Drop coin
		var coin = game.addChild(new Coin());
		coin.x = self.x;
		coin.y = self.y - 50;
		coin.isAnimating = true;
		coins.push(coin);
		// Animate coin moving toward coin counter
		var coinTargetX = 120 + coinText.width / 2;
		var coinTargetY = 90 + coinText.height / 2;
		tween(coin, {
			x: coinTargetX,
			y: coinTargetY,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Increment coin counter after animation
				coinCounter++;
				coinText.setText('Coins: ' + coinCounter);
				// Remove coin from array and destroy
				for (var i = coins.length - 1; i >= 0; i--) {
					if (coins[i] === coin) {
						coins.splice(i, 1);
						break;
					}
				}
				coin.destroy();
			}
		});
		// Increment enemy kill counter
		enemyKillCounter++;
		killCountText.setText('Puntuacion: ' + enemyKillCounter);
		// Add experience to wizard
		wizard.gainExperience(25);
		// Life drain upgrade - 5% chance to restore 10 health
		if (wizard.lifeDrainLevel && wizard.lifeDrainLevel > 0) {
			var drainChance = Math.random();
			if (drainChance < 0.05) {
				// 5% chance
				wizard.health = Math.min(wizard.health + 10, wizard.maxHealth);
				updateHealthBar();
				// Visual feedback for life drain
				LK.effects.flashObject(wizard, 0x00FF00, 300);
			}
		}
		// Clear selected enemy if this was the target
		if (selectedEnemy === self) {
			selectedEnemy = null;
		}
		// Remove from enemies array
		for (var i = enemies.length - 1; i >= 0; i--) {
			if (enemies[i] === self) {
				enemies.splice(i, 1);
				break;
			}
		}
		self.destroy();
		LK.setScore(LK.getScore() + 10);
	};
	return self;
});
var EnergyBeam = Container.expand(function () {
	var self = Container.call(this);
	// Create beam visual using projectile glow
	var beamGraphics = self.attachAsset('projectileGlow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.0,
		scaleY: 1.0
	});
	beamGraphics.tint = 0x00ffff; // Cyan color
	beamGraphics.alpha = 0.9;
	self.speed = 60;
	self.direction = {
		x: 0,
		y: 0
	};
	self.targetEnemy = null;
	self.lastIntersecting = false;
	self.update = function () {
		// Move toward target
		self.x += self.direction.x * self.speed;
		self.y += self.direction.y * self.speed;
		// Rotate beam to point toward movement direction
		var angle = Math.atan2(self.direction.y, self.direction.x);
		beamGraphics.rotation = angle;
		// Remove if off screen
		if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
			self.destroy();
			return;
		}
		// Check collision with target enemy
		if (self.targetEnemy && self.targetEnemy.parent) {
			var currentIntersecting = self.intersects(self.targetEnemy);
			if (!self.lastIntersecting && currentIntersecting) {
				// Hit the target enemy
				self.targetEnemy.takeDamage(40);
				self.destroy();
				return;
			}
			self.lastIntersecting = currentIntersecting;
		} else {
			// Target destroyed, remove beam
			self.destroy();
		}
	};
	return self;
});
var EnergyOrb = Container.expand(function () {
	var self = Container.call(this);
	// Create energy sphere visual
	var sphereGraphics = self.attachAsset('energySphere', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 1.5
	});
	// Add glowing effect
	sphereGraphics.alpha = 0.8;
	self.attackTimer = 0;
	self.attackInterval = 180; // 3 seconds at 60fps
	self.orbitalAngle = 0;
	self.orbitalRadius = 120;
	self.update = function () {
		// Keep sphere at wizard's position (stationary relative to wizard)
		if (wizard) {
			self.x = wizard.x + 140; // Position further to the right side of wizard
			self.y = wizard.y - 20; // Position slightly lower relative to wizard
		}
		// Pulsing glow effect
		var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
		sphereGraphics.scaleX = 1.5 * pulse;
		sphereGraphics.scaleY = 1.5 * pulse;
		// Attack timer
		self.attackTimer++;
		if (self.attackTimer >= self.attackInterval) {
			self.attackTimer = 0;
			self.attackClosestEnemy();
		}
	};
	self.attackClosestEnemy = function () {
		var closestEnemy = null;
		var closestDistance = Infinity;
		// Check all enemy types for closest one
		var allEnemies = enemies.concat(ogres).concat(knights);
		for (var i = 0; i < allEnemies.length; i++) {
			var enemy = allEnemies[i];
			var dx = enemy.x - self.x;
			var dy = enemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < closestDistance) {
				closestDistance = distance;
				closestEnemy = enemy;
			}
		}
		// Attack closest enemy if found
		if (closestEnemy) {
			// Create energy beam projectile
			var energyBeam = game.addChild(new EnergyBeam());
			energyBeam.x = self.x;
			energyBeam.y = self.y;
			energyBeam.targetEnemy = closestEnemy;
			// Calculate direction to target
			var dx = closestEnemy.x - self.x;
			var dy = closestEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				energyBeam.direction.x = dx / distance;
				energyBeam.direction.y = dy / distance;
			}
			// Flash effect on sphere when attacking
			tween(sphereGraphics, {
				scaleX: 2.5,
				scaleY: 2.5,
				alpha: 1.0
			}, {
				duration: 200,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(sphereGraphics, {
						scaleX: 1.5,
						scaleY: 1.5,
						alpha: 0.8
					}, {
						duration: 200,
						easing: tween.easeIn
					});
				}
			});
			LK.getSound('spellCast').play();
		}
	};
	return self;
});
var GameMenu = Container.expand(function () {
	var self = Container.call(this);
	// Menu background image instead of cave background
	var menuBg = self.attachAsset('menuBackground', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2,
		scaleX: 4.0,
		scaleY: 4.0
	});
	menuBg.alpha = 1.0;
	// Title text
	var titleText = new Text2('WIZARD DEFENDER', {
		size: 150,
		fill: 0xFFD700,
		font: "monospace"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = 2048 / 2;
	titleText.y = 800;
	self.addChild(titleText);
	// Instructions text
	var instructionsText = new Text2('TAP PATHS TO CAST SPELLS\nDEFEND YOUR CASTLE!', {
		size: 80,
		fill: 0xFFFFFF,
		font: "monospace"
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 1200;
	self.addChild(instructionsText);
	// Start button
	var startButton = self.attachAsset('wizard1', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 1600,
		scaleX: 2,
		scaleY: 2
	});
	var startButtonText = new Text2('START GAME', {
		size: 100,
		fill: 0x000000,
		font: "monospace"
	});
	startButtonText.anchor.set(0.5, 0.5);
	startButtonText.x = 2048 / 2;
	startButtonText.y = 1700;
	self.addChild(startButtonText);
	// Button interaction
	self.down = function (x, y, obj) {
		// Start the game by hiding menu
		self.startGame();
	};
	self.startGame = function () {
		// Hide menu and start game
		self.visible = false;
		gameStarted = true;
		// Show cave background when game starts
		if (backgroundMap) {
			backgroundMap.visible = true;
		}
		// Show all game elements
		wizard.visible = true;
		for (var i = 0; i < paths.length; i++) {
			paths[i].visible = true;
		}
		// Show all stone path segments and make them visible
		for (var i = 0; i < game.children.length; i++) {
			var child = game.children[i];
			if (child.pathIndex !== undefined && child !== paths[child.pathIndex]) {
				child.visible = true;
				// Check if it's a stone path segment or path number
				if (child.alpha !== undefined && child.setText === undefined) {
					child.alpha = 0; // Keep stone paths invisible
				}
			}
		}
		coinText.visible = true;
		killCountText.visible = true;
		tapText.visible = true;
		healthBarBg.visible = true;
		healthBar.visible = true;
		healthText.visible = true;
		// Start medieval music
		LK.playMusic('medievalTheme', {
			volume: 0.7,
			fade: {
				start: 0,
				end: 0.7,
				duration: 2000
			}
		});
	};
	return self;
});
var Knight = Container.expand(function () {
	var self = Container.call(this);
	// Animation system for knight
	self.currentFrame = 1;
	self.animationTimer = 0;
	self.animationSpeed = 22; // Change frame every 22 ticks (367ms at 60fps)
	self.animationState = 'walking'; // walking, attacking, dying, idle
	// Create all knight graphics frames and store them
	self.knightFrames = [];
	for (var i = 1; i <= 4; i++) {
		var frameGraphics = self.attachAsset('knight' + i, {
			anchorX: 0.5,
			anchorY: 1.0,
			scaleX: 2.0,
			scaleY: 2.0
		});
		frameGraphics.visible = i === 1; // Only show first frame initially
		self.knightFrames.push(frameGraphics);
	}
	// Create invisible hitbox with double size
	var hitbox = self.attachAsset('knight1', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 4,
		scaleY: 4
	});
	hitbox.alpha = 0; // Make hitbox invisible
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 7;
	self.hitsToKill = 3; // Knights need 3 hits to die
	self.hitsTaken = 0;
	// Note: health, maxHealth and speed will be overridden by difficulty system
	self.lastX = 0;
	self.update = function () {
		// Animation system - cycle through knight frames based on state
		self.animationTimer++;
		var frameSpeed = self.animationSpeed;
		if (self.animationState === 'attacking') {
			frameSpeed = 12; // Faster animation for attacking
		} else if (self.animationState === 'dying') {
			frameSpeed = 28; // Slower animation for dying
		} else if (self.animationState === 'idle') {
			frameSpeed = 35; // Very slow animation for idle
		}
		if (self.animationTimer >= frameSpeed) {
			self.animationTimer = 0;
			// Hide current frame
			self.knightFrames[self.currentFrame - 1].visible = false;
			// Move to next frame based on animation state
			if (self.animationState === 'walking') {
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 1;
				}
			} else if (self.animationState === 'attacking') {
				// Cycle through frames 2-4 for attacking
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 2;
				}
			} else if (self.animationState === 'dying') {
				// Play frames 3-4 once for dying
				if (self.currentFrame < 4) {
					self.currentFrame++;
				}
			} else if (self.animationState === 'idle') {
				// Cycle between frames 1-2 for idle
				self.currentFrame = self.currentFrame === 1 ? 2 : 1;
			}
			// Show new frame
			self.knightFrames[self.currentFrame - 1].visible = true;
		}
		// Progressive speed increase - increase speed by 150% over 10 seconds
		if (!self.speedTweenStarted) {
			self.speedTweenStarted = true;
			var targetSpeed = self.speed * 2.5; // Increase speed by 150%
			tween(self, {
				speed: targetSpeed
			}, {
				duration: 10000,
				// 10 seconds
				easing: tween.easeOut
			});
		}
		// Always move directly toward the wizard to ensure knights reach the player
		if (wizard) {
			// Calculate direction from knight to wizard
			var dx = wizard.x - self.x;
			var dy = wizard.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				// Normalize direction and apply speed
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			// Face toward the wizard - flip horizontally based on wizard position
			if (dx < 0) {
				// Wizard is to the left - flip to face left
				for (var frameIdx = 0; frameIdx < self.knightFrames.length; frameIdx++) {
					self.knightFrames[frameIdx].scaleX = -2.0; // Flip to face left
				}
			} else {
				// Wizard is to the right - face right
				for (var frameIdx = 0; frameIdx < self.knightFrames.length; frameIdx++) {
					self.knightFrames[frameIdx].scaleX = 2.0; // Normal orientation to face right
				}
			}
		} else {
			// Fallback: move down if wizard doesn't exist
			self.y += self.speed;
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		self.hitsTaken++;
		// Change animation state to attacking when hit
		self.animationState = 'attacking';
		// Flash red when hit
		LK.effects.flashObject(self, 0xFF0000, 200);
		// Return to walking animation after brief attacking animation
		tween({}, {}, {
			duration: 500,
			onFinish: function onFinish() {
				if (self.animationState === 'attacking') {
					self.animationState = 'walking';
				}
			}
		});
		// Knights need 3 hits to die
		if (self.hitsTaken >= self.hitsToKill) {
			self.die();
		}
	};
	self.down = function (x, y, obj) {
		// Set this knight as the selected target
		selectedEnemy = self;
		// Visual feedback for selection
		LK.effects.flashObject(self, 0xFFFF00, 500); // Yellow flash to indicate selection
		// Create projectile from wizard to knight when knight is tapped
		if (wizard && projectiles.length < 10) {
			// Limit projectiles to prevent spam
			var projectile = game.addChild(new Projectile());
			projectile.x = wizard.x;
			projectile.y = wizard.y;
			// Calculate direction from wizard to knight
			var dx = self.x - wizard.x;
			var dy = self.y - wizard.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				projectile.direction.x = dx / distance;
				projectile.direction.y = dy / distance;
			}
			projectile.targetEnemy = self; // Set the target for this projectile
			projectiles.push(projectile);
			LK.getSound('spellCast').play();
		}
	};
	self.die = function () {
		// Change animation state to dying
		self.animationState = 'dying';
		self.currentFrame = 3; // Start dying animation from frame 3
		// Play pain sound when knight dies
		LK.getSound('painSound').play();
		// Drop coin
		var coin = game.addChild(new Coin());
		coin.x = self.x;
		coin.y = self.y - 50;
		coin.isAnimating = true;
		coins.push(coin);
		// Animate coin moving toward coin counter
		var coinTargetX = 120 + coinText.width / 2;
		var coinTargetY = 90 + coinText.height / 2;
		tween(coin, {
			x: coinTargetX,
			y: coinTargetY,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Increment coin counter after animation
				coinCounter++;
				coinText.setText('Coins: ' + coinCounter);
				// Remove coin from array and destroy
				for (var i = coins.length - 1; i >= 0; i--) {
					if (coins[i] === coin) {
						coins.splice(i, 1);
						break;
					}
				}
				coin.destroy();
			}
		});
		// Increment enemy kill counter
		enemyKillCounter++;
		killCountText.setText('Puntuacion: ' + enemyKillCounter);
		// Add experience to wizard
		wizard.gainExperience(25);
		// Life drain upgrade - 5% chance to restore 10 health
		if (wizard.lifeDrainLevel && wizard.lifeDrainLevel > 0) {
			var drainChance = Math.random();
			if (drainChance < 0.05) {
				// 5% chance
				wizard.health = Math.min(wizard.health + 10, wizard.maxHealth);
				updateHealthBar();
				// Visual feedback for life drain
				LK.effects.flashObject(wizard, 0x00FF00, 300);
			}
		}
		// Clear selected enemy if this was the target
		if (selectedEnemy === self) {
			selectedEnemy = null;
		}
		// Remove from knights array
		for (var i = knights.length - 1; i >= 0; i--) {
			if (knights[i] === self) {
				knights.splice(i, 1);
				break;
			}
		}
		self.destroy();
		LK.setScore(LK.getScore() + 20);
	};
	return self;
});
var Ogre = Container.expand(function () {
	var self = Container.call(this);
	// Animation system for ogre
	self.currentFrame = 1;
	self.animationTimer = 0;
	self.animationSpeed = 20; // Change frame every 20 ticks (333ms at 60fps)
	self.animationState = 'walking'; // walking, attacking, dying, idle
	// Create all ogre graphics frames and store them
	self.ogreFrames = [];
	for (var i = 1; i <= 4; i++) {
		var frameGraphics = self.attachAsset('ogre' + i, {
			anchorX: 0.5,
			anchorY: 1.0,
			scaleX: 2.0,
			scaleY: 2.0
		});
		frameGraphics.visible = i === 1; // Only show first frame initially
		self.ogreFrames.push(frameGraphics);
	}
	// Create invisible hitbox with double size
	var hitbox = self.attachAsset('ogre1', {
		anchorX: 0.5,
		anchorY: 1.0,
		scaleX: 4,
		scaleY: 4
	});
	hitbox.alpha = 0; // Make hitbox invisible
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 7;
	self.hitsToKill = 2;
	self.hitsTaken = 0;
	// Note: health, maxHealth and speed will be overridden by difficulty system
	self.lastX = 0;
	self.update = function () {
		// Animation system - cycle through ogre frames based on state
		self.animationTimer++;
		var frameSpeed = self.animationSpeed;
		if (self.animationState === 'attacking') {
			frameSpeed = 10; // Faster animation for attacking
		} else if (self.animationState === 'dying') {
			frameSpeed = 25; // Slower animation for dying
		} else if (self.animationState === 'idle') {
			frameSpeed = 30; // Very slow animation for idle
		}
		if (self.animationTimer >= frameSpeed) {
			self.animationTimer = 0;
			// Hide current frame
			self.ogreFrames[self.currentFrame - 1].visible = false;
			// Move to next frame based on animation state
			if (self.animationState === 'walking') {
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 1;
				}
			} else if (self.animationState === 'attacking') {
				// Cycle through frames 2-4 for attacking
				self.currentFrame++;
				if (self.currentFrame > 4) {
					self.currentFrame = 2;
				}
			} else if (self.animationState === 'dying') {
				// Play frames 3-4 once for dying
				if (self.currentFrame < 4) {
					self.currentFrame++;
				}
			} else if (self.animationState === 'idle') {
				// Cycle between frames 1-2 for idle
				self.currentFrame = self.currentFrame === 1 ? 2 : 1;
			}
			// Show new frame
			self.ogreFrames[self.currentFrame - 1].visible = true;
		}
		// Progressive speed increase - increase speed by 150% over 10 seconds
		if (!self.speedTweenStarted) {
			self.speedTweenStarted = true;
			var targetSpeed = self.speed * 2.5; // Increase speed by 150%
			tween(self, {
				speed: targetSpeed
			}, {
				duration: 10000,
				// 10 seconds
				easing: tween.easeOut
			});
		}
		// Always move directly toward the wizard to ensure ogres reach the player
		if (wizard) {
			// Calculate direction from ogre to wizard
			var dx = wizard.x - self.x;
			var dy = wizard.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				// Normalize direction and apply speed
				self.x += dx / distance * self.speed;
				self.y += dy / distance * self.speed;
			}
			// Face toward the wizard - flip horizontally based on wizard position
			if (dx < 0) {
				// Wizard is to the left - flip to face left
				for (var frameIdx = 0; frameIdx < self.ogreFrames.length; frameIdx++) {
					self.ogreFrames[frameIdx].scaleX = -2.0; // Flip to face left
				}
			} else {
				// Wizard is to the right - face right
				for (var frameIdx = 0; frameIdx < self.ogreFrames.length; frameIdx++) {
					self.ogreFrames[frameIdx].scaleX = 2.0; // Normal orientation to face right
				}
			}
		} else {
			// Fallback: move down if wizard doesn't exist
			self.y += self.speed;
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		self.hitsTaken++;
		// Change animation state to attacking when hit
		self.animationState = 'attacking';
		// Flash red when hit
		LK.effects.flashObject(self, 0xFF0000, 200);
		// Return to walking animation after brief attacking animation
		tween({}, {}, {
			duration: 400,
			onFinish: function onFinish() {
				if (self.animationState === 'attacking') {
					self.animationState = 'walking';
				}
			}
		});
		// Ogres need 2 hits to die
		if (self.hitsTaken >= self.hitsToKill) {
			self.die();
		}
	};
	self.down = function (x, y, obj) {
		// Set this ogre as the selected target
		selectedEnemy = self;
		// Visual feedback for selection
		LK.effects.flashObject(self, 0xFFFF00, 500); // Yellow flash to indicate selection
		// Create projectile from wizard to ogre when ogre is tapped
		if (wizard && projectiles.length < 10) {
			// Limit projectiles to prevent spam
			var projectile = game.addChild(new Projectile());
			projectile.x = wizard.x;
			projectile.y = wizard.y;
			// Calculate direction from wizard to ogre
			var dx = self.x - wizard.x;
			var dy = self.y - wizard.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance > 0) {
				projectile.direction.x = dx / distance;
				projectile.direction.y = dy / distance;
			}
			projectile.targetEnemy = self; // Set the target for this projectile
			projectiles.push(projectile);
			LK.getSound('spellCast').play();
		}
	};
	self.die = function () {
		// Change animation state to dying
		self.animationState = 'dying';
		self.currentFrame = 3; // Start dying animation from frame 3
		// Play pain sound when ogre dies
		LK.getSound('painSound').play();
		// Drop coin
		var coin = game.addChild(new Coin());
		coin.x = self.x;
		coin.y = self.y - 50;
		coin.isAnimating = true;
		coins.push(coin);
		// Animate coin moving toward coin counter
		var coinTargetX = 120 + coinText.width / 2;
		var coinTargetY = 90 + coinText.height / 2;
		tween(coin, {
			x: coinTargetX,
			y: coinTargetY,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 1000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Increment coin counter after animation
				coinCounter++;
				coinText.setText('Coins: ' + coinCounter);
				// Remove coin from array and destroy
				for (var i = coins.length - 1; i >= 0; i--) {
					if (coins[i] === coin) {
						coins.splice(i, 1);
						break;
					}
				}
				coin.destroy();
			}
		});
		// Increment enemy kill counter
		enemyKillCounter++;
		killCountText.setText('Puntuacion: ' + enemyKillCounter);
		// Add experience to wizard
		wizard.gainExperience(25);
		// Life drain upgrade - 5% chance to restore 10 health
		if (wizard.lifeDrainLevel && wizard.lifeDrainLevel > 0) {
			var drainChance = Math.random();
			if (drainChance < 0.05) {
				// 5% chance
				wizard.health = Math.min(wizard.health + 10, wizard.maxHealth);
				updateHealthBar();
				// Visual feedback for life drain
				LK.effects.flashObject(wizard, 0x00FF00, 300);
			}
		}
		// Clear selected enemy if this was the target
		if (selectedEnemy === self) {
			selectedEnemy = null;
		}
		// Remove from ogres array
		for (var i = ogres.length - 1; i >= 0; i--) {
			if (ogres[i] === self) {
				ogres.splice(i, 1);
				break;
			}
		}
		self.destroy();
		LK.setScore(LK.getScore() + 15);
	};
	return self;
});
var Projectile = Container.expand(function () {
	var self = Container.call(this);
	// Create glowing light effect behind projectile
	var lightGlow = self.attachAsset('projectileGlow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2.0,
		scaleY: 2.0
	});
	lightGlow.alpha = 0.15;
	lightGlow.tint = 0x44aaff; // Blue-white glow
	// Animate the glow effect
	tween(lightGlow, {
		scaleX: 3.5,
		scaleY: 3.5,
		alpha: 0.05
	}, {
		duration: 800,
		easing: tween.easeInOut
	});
	tween(lightGlow, {
		rotation: Math.PI * 4
	}, {
		duration: 1000,
		easing: tween.linear
	});
	var projectileGraphics = self.attachAsset('projectile', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 3.0,
		scaleY: 3.0
	});
	self.speed = 50;
	self.direction = {
		x: 0,
		y: 0
	};
	self.lastIntersecting = {};
	self.targetEnemy = null; // The specific enemy this projectile should damage
	self.update = function () {
		// Move projectile
		self.x += self.direction.x * self.speed;
		self.y += self.direction.y * self.speed;
		// Rotate projectile to point towards movement direction
		var angle = Math.atan2(self.direction.y, self.direction.x);
		projectileGraphics.rotation = angle + Math.PI / 2; // Add 90 degrees so top points forward
		// Add pulsing light effect
		if (lightGlow && lightGlow.parent) {
			var pulse = 1 + Math.sin(LK.ticks * 0.3) * 0.4;
			lightGlow.scaleX = 2.0 * pulse;
			lightGlow.scaleY = 2.0 * pulse;
			var alphaFlicker = 0.1 + Math.sin(LK.ticks * 0.5) * 0.08;
			lightGlow.alpha = alphaFlicker;
		}
		// Remove if off screen
		if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
			self.removeFromGame();
			return;
		}
		// Only check collision with the target enemy if one is set
		if (self.targetEnemy && self.targetEnemy.parent) {
			if (!self.lastIntersecting.target) {
				self.lastIntersecting.target = false;
			}
			var currentTargetIntersecting = self.intersects(self.targetEnemy);
			if (!self.lastIntersecting.target && currentTargetIntersecting) {
				// Hit the target enemy
				self.targetEnemy.takeDamage(50);
				self.removeFromGame();
				return;
			}
			self.lastIntersecting.target = currentTargetIntersecting;
		}
	};
	self.removeFromGame = function () {
		// Remove from projectiles array
		for (var i = projectiles.length - 1; i >= 0; i--) {
			if (projectiles[i] === self) {
				projectiles.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
var StartMenu = Container.expand(function () {
	var self = Container.call(this);
	// Full screen bone white background
	var menuBg = self.attachAsset('startMenuBackground', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 2732 / 2
	});
	// Game title
	var titleText = new Text2('WIZARD DEFENDER', {
		size: 180,
		fill: 0x8B4513,
		font: "monospace"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = 2048 / 2;
	titleText.y = 800;
	self.addChild(titleText);
	// Subtitle
	var subtitleText = new Text2('DEFEND YOUR CASTLE', {
		size: 100,
		fill: 0x654321,
		font: "monospace"
	});
	subtitleText.anchor.set(0.5, 0.5);
	subtitleText.x = 2048 / 2;
	subtitleText.y = 1000;
	self.addChild(subtitleText);
	// Instructions
	var instructionsText = new Text2('TAP PATHS TO CAST SPELLS\nDEFEND AGAINST ENEMIES!', {
		size: 80,
		fill: 0x8B4513,
		font: "monospace"
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 1400;
	self.addChild(instructionsText);
	// Start button background
	var startButtonBg = self.attachAsset('menuBackground', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 1800,
		scaleX: 2,
		scaleY: 1.5
	});
	startButtonBg.tint = 0xD2691E;
	// Start button text
	var startButtonText = new Text2('START GAME', {
		size: 120,
		fill: 0xF5F5DC,
		font: "monospace"
	});
	startButtonText.anchor.set(0.5, 0.5);
	startButtonText.x = 2048 / 2;
	startButtonText.y = 1800;
	self.addChild(startButtonText);
	// Button interaction
	self.down = function (x, y, obj) {
		// Check if start button area was clicked
		if (x >= 1024 - 200 && x <= 1024 + 200 && y >= 1700 && y <= 1900) {
			self.startGame();
		}
	};
	self.startGame = function () {
		// Hide start menu and show game menu
		self.visible = false;
		if (gameMenu) {
			gameMenu.visible = true;
		}
	};
	return self;
});
var UpgradeMenu = Container.expand(function () {
	var self = Container.call(this);
	// Set high z-index to ensure menu appears above all game elements
	self.zIndex = 1000;
	// Cooldown system for upgrade menu
	self.cooldownDuration = 120; // 2 seconds at 60fps
	self.cooldownTimer = 0;
	// Background removed - no overlay needed
	// Title text
	var titleText = new Text2('UPGRADES', {
		size: 120,
		fill: 0xFFD700,
		font: "monospace"
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = 2048 / 2;
	titleText.y = 1050;
	self.addChild(titleText);
	// Initialize upgrade cost
	self.upgradeCost = 5;
	// Store references to upgrade text elements for updates
	self.upgradeTextElements = [];
	// Upgrade options
	var upgradeOptions = [{
		name: 'SHIELD',
		description: 'Block 1 attack'
	}, {
		name: 'HEALTH BOOST',
		description: 'More health'
	}, {
		name: 'LIFE DRAIN',
		description: '5% chance +10 HP'
	}, {
		name: 'ENERGY SPHERE',
		description: 'Auto-attack every 3s'
	}];
	// Create upgrade buttons
	for (var i = 0; i < upgradeOptions.length; i++) {
		var upgrade = upgradeOptions[i];
		var xPos = 2048 / 2 - 600 + i * 400; // Center the 4 upgrades horizontally
		var yPos = 1300; // Same Y position for all
		// Upgrade button background
		var upgradeBtn = self.attachAsset('pathSelector', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: xPos,
			y: yPos,
			scaleX: 6,
			scaleY: 4
		});
		upgradeBtn.upgradeIndex = i;
		upgradeBtn.tint = 0x8B008B;
		// Upgrade text
		var upgradeText = new Text2(upgrade.name + '\n' + upgrade.description + '\nCost: ' + self.upgradeCost + ' coins', {
			size: 45,
			fill: 0xFFFFFF,
			font: "monospace"
		});
		upgradeText.anchor.set(0.5, 0.5);
		upgradeText.x = xPos;
		upgradeText.y = yPos;
		upgradeText.upgradeIndex = i; // Store upgrade index for reference
		upgradeText.upgradeName = upgrade.name;
		upgradeText.upgradeDescription = upgrade.description;
		self.addChild(upgradeText);
		self.upgradeTextElements.push(upgradeText); // Store reference for updates
	}
	// Close button
	var closeBtn = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 2048 / 2,
		y: 1600,
		scaleX: 2,
		scaleY: 2
	});
	closeBtn.tint = 0xFF0000;
	var closeText = new Text2('CLOSE', {
		size: 80,
		fill: 0xFFFFFF,
		font: "monospace"
	});
	closeText.anchor.set(0.5, 0.5);
	closeText.x = 2048 / 2;
	closeText.y = 1600;
	self.addChild(closeText);
	// Method to update upgrade text with new costs
	self.updateUpgradeCosts = function () {
		for (var i = 0; i < self.upgradeTextElements.length; i++) {
			var textElement = self.upgradeTextElements[i];
			textElement.setText(textElement.upgradeName + '\n' + textElement.upgradeDescription + '\nCost: ' + self.upgradeCost + ' coins');
		}
	};
	// Update method for cooldown timer
	self.update = function () {
		if (self.cooldownTimer > 0) {
			self.cooldownTimer--;
			// Apply visual feedback during cooldown
			var cooldownAlpha = 0.3 + self.cooldownTimer / self.cooldownDuration * 0.7;
			self.alpha = cooldownAlpha;
		} else {
			self.alpha = 1.0; // Full opacity when cooldown is over
		}
	};
	// Handle upgrade purchases
	self.down = function (x, y, obj) {
		// Check if cooldown is active
		if (self.cooldownTimer > 0) {
			// Flash red to indicate cooldown is active
			LK.effects.flashScreen(0xFF0000, 200);
			return; // Exit early if cooldown is active
		}
		// Determine which upgrade was clicked based on X position (horizontal layout)
		var upgradeIndex = -1;
		if (x >= 224 && x <= 524 && y >= 1150 && y <= 1450) {
			upgradeIndex = 0; // Shield
		} else if (x >= 624 && x <= 924 && y >= 1150 && y <= 1450) {
			upgradeIndex = 1; // Health Boost
		} else if (x >= 1024 && x <= 1324 && y >= 1150 && y <= 1450) {
			upgradeIndex = 2; // Life Drain
		} else if (x >= 1424 && x <= 1724 && y >= 1150 && y <= 1450) {
			upgradeIndex = 3; // Energy Sphere
		}
		// Check if upgrade button was clicked
		if (upgradeIndex !== -1) {
			// Close menu immediately when any upgrade option is selected
			self.closeMenu();
			var currentCost = self.upgradeCost || 5; // Use dynamic cost or default to 5
			if (coinCounter >= currentCost) {
				coinCounter -= currentCost;
				coinText.setText('Coins: ' + coinCounter);
				// Apply upgrade based on index
				switch (upgradeIndex) {
					case 0:
						// Shield - give one-time protection
						if (!wizard.shieldActive) {
							wizard.shieldActive = false;
						}
						wizard.shieldActive = true;
						// Visual feedback for shield activation
						LK.effects.flashObject(wizard, 0x00BFFF, 500);
						// Add shield activation animation effect
						tween(wizard.shieldGraphics, {
							scaleX: 5,
							scaleY: 5,
							alpha: 1.0
						}, {
							duration: 400,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(wizard.shieldGraphics, {
									scaleX: 3,
									scaleY: 3,
									alpha: 0.7
								}, {
									duration: 300,
									easing: tween.easeIn
								});
							}
						});
						break;
					case 1:
						// Health Boost
						wizard.maxHealth += 30;
						wizard.health = Math.min(wizard.health + 30, wizard.maxHealth);
						updateHealthBar();
						break;
					case 2:
						// Life Drain - enable health restoration on kill
						if (!wizard.lifeDrainLevel) {
							wizard.lifeDrainLevel = 0;
						}
						wizard.lifeDrainLevel++;
						break;
					case 3:
						// Energy Sphere - create orbiting energy sphere
						if (!wizard.energySphere) {
							wizard.energySphere = game.addChild(new EnergyOrb());
							// Visual feedback for energy sphere activation
							LK.effects.flashObject(wizard, 0x00FFFF, 500);
						}
						break;
				}
				// Visual feedback - flash the upgrade area green
				LK.effects.flashScreen(0x00FF00, 300);
			} else {
				// Not enough coins - flash red
				LK.effects.flashScreen(0xFF0000, 300);
			}
		} else if (y >= 1450 && y <= 1750) {
			// Close button area clicked
			self.closeMenu();
		}
	};
	self.closeMenu = function () {
		self.visible = false;
		gameStarted = true;
		// Resume appropriate music based on game progress
		if (enemyKillCounter >= 25) {
			LK.playMusic('mysticalAmbient', {
				volume: 0.6,
				fade: {
					start: 0,
					end: 0.6,
					duration: 1000
				}
			});
		} else if (enemyKillCounter >= 10) {
			LK.playMusic('epicBattle', {
				volume: 0.8,
				fade: {
					start: 0,
					end: 0.8,
					duration: 1000
				}
			});
		} else {
			LK.playMusic('medievalTheme', {
				volume: 0.7,
				fade: {
					start: 0,
					end: 0.7,
					duration: 1000
				}
			});
		}
	};
	return self;
});
var Wizard = Container.expand(function () {
	var self = Container.call(this);
	// Animation system for wizard
	self.currentFrame = 1;
	self.animationTimer = 0;
	self.animationSpeed = 18; // Change frame every 18 ticks (300ms at 60fps)
	// Create all wizard graphics frames and store them
	self.wizardFrames = [];
	for (var i = 1; i <= 4; i++) {
		var frameGraphics = self.attachAsset('wizard' + i, {
			anchorX: 0.5,
			anchorY: 1.0,
			scaleX: 2.5,
			scaleY: 2.5
		});
		frameGraphics.visible = i === 1; // Only show first frame initially
		self.wizardFrames.push(frameGraphics);
	}
	// Create shield visual effect
	self.shieldGraphics = self.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 3,
		scaleY: 3
	});
	self.shieldGraphics.alpha = 0.7;
	self.shieldGraphics.visible = false;
	self.attackCooldown = 0;
	self.level = 1;
	self.experience = 0;
	self.health = 100;
	self.maxHealth = 100;
	self.spellPowerLevel = 0; // Track spell power upgrades
	self.shieldActive = false; // Track shield status
	self.update = function () {
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
		// Update shield visibility based on shield status
		self.shieldGraphics.visible = self.shieldActive;
		if (self.shieldActive) {
			// Animate shield with pulsing effect
			var pulse = 1 + Math.sin(LK.ticks * 0.15) * 0.2;
			self.shieldGraphics.scaleX = 3 * pulse;
			self.shieldGraphics.scaleY = 3 * pulse;
			// Slowly rotate shield
			self.shieldGraphics.rotation += 0.03;
			// Add glowing effect
			self.shieldGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.1) * 0.2;
		}
		// Animation system - cycle through wizard frames
		self.animationTimer++;
		if (self.animationTimer >= self.animationSpeed) {
			self.animationTimer = 0;
			// Hide current frame
			self.wizardFrames[self.currentFrame - 1].visible = false;
			// Move to next frame
			self.currentFrame++;
			if (self.currentFrame > 4) {
				self.currentFrame = 1;
			}
			// Show new frame
			self.wizardFrames[self.currentFrame - 1].visible = true;
		}
	};
	self.attack = function (direction) {
		if (self.attackCooldown <= 0) {
			// Default direction if none specified
			if (direction === undefined) {
				direction = 0; // Default to center path
			}
			// Get attack angle based on path direction
			var attackAngle = pathAngles[direction];
			var attackDistance = 100;
			// Calculate spell position based on attack direction
			var spellX = self.x + Math.cos(attackAngle) * attackDistance;
			var spellY = self.y + Math.sin(attackAngle) * attackDistance;
			// Create spell effect
			var spell = game.addChild(LK.getAsset('spell', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: spellX,
				y: spellY,
				scaleX: 0.5,
				scaleY: 0.5
			}));
			// Animate spell with magical effects
			tween(spell, {
				scaleX: 2,
				scaleY: 2,
				alpha: 0
			}, {
				duration: 500,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					spell.destroy();
				}
			});
			// Add rotation animation to spell
			tween(spell, {
				rotation: Math.PI * 2
			}, {
				duration: 500,
				easing: tween.linear
			});
			self.attackCooldown = 30; // 0.5 seconds at 60fps
			LK.getSound('spellCast').play();
			// Base damage without spell power upgrades
			var totalDamage = 50;
			// Attack enemies in the specified direction/path
			for (var i = enemies.length - 1; i >= 0; i--) {
				var enemy = enemies[i];
				if (enemy.pathIndex === direction) {
					// Only hit enemies on exact same path - no distance validation
					enemy.takeDamage(totalDamage);
				}
			}
			// Attack ogres in the specified direction/path
			for (var i = ogres.length - 1; i >= 0; i--) {
				var ogre = ogres[i];
				if (ogre.pathIndex === direction) {
					// Only hit ogres on exact same path - no distance validation
					ogre.takeDamage(totalDamage);
				}
			}
			// Attack knights in the specified direction/path
			for (var i = knights.length - 1; i >= 0; i--) {
				var knight = knights[i];
				if (knight.pathIndex === direction) {
					// Only hit knights on exact same path - no distance validation
					knight.takeDamage(totalDamage);
				}
			}
			return true;
		}
		return false;
	};
	self.gainExperience = function (amount) {
		self.experience += amount;
		var expNeeded = self.level * 100;
		if (self.experience >= expNeeded) {
			self.levelUp();
		}
	};
	self.levelUp = function () {
		self.level++;
		self.experience = 0;
		// Visual level up effect
		LK.effects.flashObject(self, 0xFFD700, 500);
	};
	self.takeDamage = function (damage) {
		// Check if shield is active
		if (self.shieldActive) {
			// Shield blocks the damage
			self.shieldActive = false;
			// Visual feedback for shield use
			LK.effects.flashObject(self, 0x00BFFF, 300);
			// Start shield regeneration timer (10 seconds)
			tween({}, {}, {
				duration: 10000,
				// 10 seconds
				onFinish: function onFinish() {
					// Regenerate shield after 10 seconds
					self.shieldActive = true;
					// Visual feedback for shield regeneration
					LK.effects.flashObject(self, 0x00BFFF, 500);
					// Add shield regeneration animation
					tween(self.shieldGraphics, {
						scaleX: 5,
						scaleY: 5,
						alpha: 1.0
					}, {
						duration: 600,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(self.shieldGraphics, {
								scaleX: 3,
								scaleY: 3,
								alpha: 0.7
							}, {
								duration: 400,
								easing: tween.easeIn
							});
						}
					});
				}
			});
			// No damage taken, shield absorbed it
			return;
		}
		self.health -= damage;
		if (self.health <= 0) {
			self.health = 0;
			// Game over when health reaches 0
			LK.effects.flashScreen(0xFF0000, 1000);
			LK.showGameOver();
		}
		// Update health bar
		updateHealthBar();
		// Flash red when hit
		LK.effects.flashObject(self, 0xFF0000, 200);
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000 // Black background for pixel art
});
/**** 
* Game Code
****/ 
// Game state variables
var gameStarted = false;
var gameMenu;
var upgradeMenu;
var upgradeMenuShown = false;
var secondUpgradeMenuShown = false;
var thirdUpgradeMenuShown = false;
var selectedEnemy = null; // Track currently selected enemy for projectile targeting
var energySphere = null; // Track energy sphere instance
// Game arrays to track objects
var enemies = [];
var ogres = [];
var knights = [];
var coins = [];
var projectiles = [];
// Create and show start menu first
var startMenu = game.addChild(new StartMenu());
// Create game menu (initially hidden)
gameMenu = game.addChild(new GameMenu());
gameMenu.visible = false;
// Create upgrade menu (initially hidden)
upgradeMenu = game.addChild(new UpgradeMenu());
upgradeMenu.visible = false;
// Create 5 stone paths leading toward the wizard position
var paths = [];
var knightX = 2048 / 2;
var knightY = 2732 - 250;
// Create paths: all pointing toward the wizard position
var pathAngles = [-Math.PI / 2,
// Center (straight down toward wizard)
-Math.PI / 3,
// Diagonal right toward wizard
-2 * Math.PI / 3,
// Diagonal left toward wizard
Math.PI / 6,
// Path 4: opposite to path 2 (diagonal left)
5 * Math.PI / 6 // Path 5: opposite to path 3 (diagonal right)
]; // 5 paths: all directed toward wizard position
// Create multiple stone segments for each path to form visible stone roads
for (var p = 0; p < 5; p++) {
	var angle = pathAngles[p];
	// Calculate distance from spawn point to wizard position
	var wizardX = knightX;
	var wizardY = 2732 - 600; // Wizard position
	var spawnDistance = p === 0 ? 2000 : p === 3 || p === 4 ? 1200 : 1800; // Distance from wizard to spawn point
	// Set spawn points to screen edges for all paths
	var spawnX, spawnY;
	if (p === 0) {
		// Center path - spawn at top edge
		spawnX = 2048 / 2;
		spawnY = -100;
	} else if (p === 1) {
		// Path 2 - spawn at top right edge
		spawnX = 2048 + 50;
		spawnY = -50;
	} else if (p === 2) {
		// Path 3 - spawn at top left edge
		spawnX = -50;
		spawnY = -50;
	} else if (p === 3) {
		// Path 4 - spawn at left edge
		spawnX = -100;
		spawnY = 2732 / 2 + 400;
	} else if (p === 4) {
		// Path 5 - spawn at right edge
		spawnX = 2048 + 100;
		spawnY = 2732 / 2 + 400;
	}
	// Calculate actual path length from spawn point to wizard
	var actualPathLength = Math.sqrt((spawnX - wizardX) * (spawnX - wizardX) + (spawnY - wizardY) * (spawnY - wizardY));
	var segmentSize = 120; // Size of each stone segment
	var numSegments = Math.floor(actualPathLength / segmentSize);
	// Create individual stone segments along the path from spawn point toward wizard
	for (var s = 0; s < numSegments; s++) {
		var segmentDistance = s * segmentSize + segmentSize / 2;
		var segmentX = spawnX - Math.cos(angle) * segmentDistance;
		var segmentY = spawnY - Math.sin(angle) * segmentDistance;
		// Only create segments that are within the visible game area
		if (segmentX >= -100 && segmentX <= 2148 && segmentY >= -100 && segmentY <= 2832) {
			// Create stone path segment
			var stoneSegment = game.addChild(LK.getAsset('stonePath', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: segmentX,
				y: segmentY,
				scaleX: 2.0,
				scaleY: 2.0,
				rotation: angle + Math.PI / 2 // Rotate stone to align with path
			}));
			// Make stone paths completely invisible
			stoneSegment.alpha = 0; // Make completely invisible
			stoneSegment.visible = false; // Initially hidden, will be shown when game starts
			stoneSegment.pathIndex = p;
		}
	}
}
// Create invisible path collision areas for touch detection
for (var p = 0; p < 5; p++) {
	var angle = pathAngles[p];
	// Calculate distance from spawn point to wizard position
	var wizardX = knightX;
	var wizardY = 2732 - 600; // Wizard position
	var spawnDistance = p === 0 ? 3000 : p === 3 || p === 4 ? 1200 : 1800; // Distance from wizard to spawn point
	var spawnX = wizardX + Math.cos(angle) * spawnDistance;
	var spawnY = wizardY + Math.sin(angle) * spawnDistance;
	// Move all spawn points to screen edges
	if (p === 0) {
		// Center path - spawn at top edge
		spawnX = 2048 / 2;
		spawnY = -100;
	} else if (p === 1) {
		// Path 2 - spawn at top right edge
		spawnX = 2048 + 50;
		spawnY = -50;
	} else if (p === 2) {
		// Path 3 - spawn at top left edge
		spawnX = -50;
		spawnY = -50;
	} else if (p === 3) {
		// Path 4 - spawn at left edge
		spawnX = -100;
		spawnY = 2732 / 2 + 400;
	} else if (p === 4) {
		// Path 5 - spawn at right edge
		spawnX = 2048 + 100;
		spawnY = 2732 / 2 + 400;
	}
	// Calculate actual path length from spawn point to wizard
	var actualPathLength = Math.sqrt((spawnX - wizardX) * (spawnX - wizardX) + (spawnY - wizardY) * (spawnY - wizardY));
	var centerX = (spawnX + wizardX) / 2;
	var centerY = (spawnY + wizardY) / 2;
	// Create invisible collision path
	var path = game.addChild(LK.getAsset('pathSelector', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: centerX,
		y: centerY,
		scaleX: 4,
		scaleY: actualPathLength / 60,
		rotation: angle + Math.PI / 2
	}));
	// Make collision path completely invisible
	path.alpha = 0;
	path.visible = false;
	path.pathIndex = p;
	// Add numbered text label for each path
	var pathNumber = new Text2((p + 1).toString(), {
		size: 120,
		fill: 0xFFD700,
		font: "monospace"
	});
	pathNumber.anchor.set(0.5, 0.5);
	// Position number directly at spawn point
	pathNumber.x = spawnX;
	pathNumber.y = spawnY - 80; // Position slightly above spawn point
	pathNumber.visible = false; // Initially hidden, will be shown when game starts
	pathNumber.pathIndex = p;
	game.addChild(pathNumber);
	// Add touch handler for directional attacks
	path.down = function (x, y, obj) {
		// Attack in this path's direction
		wizard.attack(obj.pathIndex);
		// Visual feedback - no flash for invisible paths
		// Paths remain invisible when tapped
	};
	paths.push(path);
}
// Pixel art scaling handled by engine automatically
// Set fondodelacueva as the actual game background
var backgroundMap = game.addChild(LK.getAsset('fondodelacueva', {
	anchorX: 0,
	anchorY: 0,
	scaleX: 19.5,
	scaleY: 26.0,
	x: 0,
	y: 0
}));
// Send background to the back but use a less extreme z-index
backgroundMap.zIndex = -100;
// Hide background initially during menu
backgroundMap.visible = false;
backgroundMap.alpha = 1.0;
// Create wizard
var wizard = game.addChild(new Wizard());
wizard.x = knightX;
wizard.y = 2732 - 600; // Position wizard higher on screen
wizard.visible = false;
// UI Elements
// Removed scoreText and levelText to eliminate stray characters in top right
var coinCounter = 0;
var enemyKillCounter = 0;
var coinText = new Text2('Coins: 0', {
	size: 60,
	fill: 0xFFD700,
	font: "monospace"
});
coinText.anchor.set(0, 0);
LK.gui.topLeft.addChild(coinText);
coinText.x = 120;
coinText.y = 90;
coinText.visible = false;
var killCountText = new Text2('Puntuacion: 0', {
	size: 60,
	fill: 0xFF6B6B,
	font: "monospace"
});
killCountText.anchor.set(0, 0);
LK.gui.topLeft.addChild(killCountText);
killCountText.x = 120;
killCountText.y = 150;
killCountText.visible = false;
var tapText = new Text2('TAP TO CAST SPELLS!', {
	size: 100,
	fill: 0xFF6B6B,
	font: "monospace"
});
tapText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(tapText);
tapText.y = -200;
tapText.visible = false;
// Health bar UI
var healthBarBg = LK.getAsset('healthBarBg', {
	anchorX: 0,
	anchorY: 0
});
LK.gui.topLeft.addChild(healthBarBg);
healthBarBg.x = 120;
healthBarBg.y = 20;
healthBarBg.visible = false;
var healthBar = LK.getAsset('healthBar', {
	anchorX: 0,
	anchorY: 0
});
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
healthBar.visible = false;
var healthText = new Text2('Health: 100/100', {
	size: 50,
	fill: 0xFFFFFF,
	font: "monospace"
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120;
healthText.y = 50;
healthText.visible = false;
function updateHealthBar() {
	var healthPercent = wizard.health / wizard.maxHealth;
	healthBar.scaleX = healthPercent;
	healthText.setText('Health: ' + wizard.health + '/' + wizard.maxHealth);
	// Change color based on health
	if (healthPercent > 0.6) {
		healthBar.tint = 0x00ff00; // Green
	} else if (healthPercent > 0.3) {
		healthBar.tint = 0xffff00; // Yellow
	} else {
		healthBar.tint = 0xff0000; // Red
	}
}
// Enemy spawning variables
var enemySpawnTimer = 0;
var lastSpawnedPath = -1; // Track the last spawned path
var consecutiveSpawns = 0; // Track consecutive spawns from same path
// Cooldown system variables
var pathLastSpawnTime = [-1, -1, -1, -1, -1]; // Track last spawn time for each path
var pathConsecutiveSpawns = [0, 0, 0, 0, 0]; // Track consecutive spawns per path
var pathCooldownDuration = 300; // 5 seconds at 60fps
// Game input handling
game.down = function (x, y, obj) {
	// Check if a path was tapped for directional attack
	var pathTapped = false;
	for (var p = 0; p < paths.length; p++) {
		var path = paths[p];
		// Convert tap position to path's local coordinates
		var localPos = path.toLocal({
			x: x,
			y: y
		});
		// Check if tap is within path bounds
		if (Math.abs(localPos.x) < path.width / 2 && Math.abs(localPos.y) < path.height / 2) {
			// Attack in this path's direction
			wizard.attack(path.pathIndex);
			pathTapped = true;
			break;
		}
	}
	// No default attack - player must tap a path to attack
};
// Main game update loop
game.update = function () {
	// Sort children by z-index to ensure proper rendering order
	game.children.sort(function (a, b) {
		return (a.zIndex || 0) - (b.zIndex || 0);
	});
	// Only update game logic if game has started
	if (!gameStarted) {
		return;
	}
	// Change music to epic battle theme at 10 enemies killed
	if (enemyKillCounter === 10) {
		LK.playMusic('epicBattle', {
			volume: 0.8,
			fade: {
				start: 0,
				end: 0.8,
				duration: 1500
			}
		});
	}
	// Change to mystical ambient music at 25 enemies killed
	if (enemyKillCounter === 25) {
		LK.playMusic('mysticalAmbient', {
			volume: 0.6,
			fade: {
				start: 0,
				end: 0.6,
				duration: 2000
			}
		});
	}
	// Show upgrade menu after 12 enemies are killed
	if (enemyKillCounter >= 12 && !upgradeMenuShown) {
		upgradeMenuShown = true;
		// Increase upgrade costs by 5 coins when menu is shown
		if (!upgradeMenu.upgradeCost) {
			upgradeMenu.upgradeCost = 5; // Initial cost
		}
		upgradeMenu.upgradeCost += 5; // Increase by 5 coins each time
		// Update all upgrade text to show new costs
		upgradeMenu.updateUpgradeCosts();
		upgradeMenu.visible = true;
		upgradeMenu.cooldownTimer = upgradeMenu.cooldownDuration; // Start 2-second cooldown
		gameStarted = false; // Pause game while menu is open
		LK.stopMusic(); // Pause music
		// Clear all enemies on screen when upgrade menu is shown
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			enemies.splice(i, 1);
			enemy.destroy();
		}
		// Clear all ogres on screen when upgrade menu is shown
		for (var i = ogres.length - 1; i >= 0; i--) {
			var ogre = ogres[i];
			ogres.splice(i, 1);
			ogre.destroy();
		}
		// Clear all knights on screen when upgrade menu is shown
		for (var i = knights.length - 1; i >= 0; i--) {
			var knight = knights[i];
			knights.splice(i, 1);
			knight.destroy();
		}
	}
	// Show upgrade menu again after 35 enemies are killed
	if (enemyKillCounter >= 35 && upgradeMenuShown && !secondUpgradeMenuShown) {
		secondUpgradeMenuShown = true;
		// Increase upgrade costs by 5 coins when menu is shown
		if (!upgradeMenu.upgradeCost) {
			upgradeMenu.upgradeCost = 5; // Initial cost
		}
		upgradeMenu.upgradeCost += 5; // Increase by 5 coins each time
		// Update all upgrade text to show new costs
		upgradeMenu.updateUpgradeCosts();
		upgradeMenu.visible = true;
		upgradeMenu.cooldownTimer = upgradeMenu.cooldownDuration; // Start 2-second cooldown
		gameStarted = false; // Pause game while menu is open
		LK.stopMusic(); // Pause music
		// Clear all enemies on screen when upgrade menu is shown
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			enemies.splice(i, 1);
			enemy.destroy();
		}
		// Clear all ogres on screen when upgrade menu is shown
		for (var i = ogres.length - 1; i >= 0; i--) {
			var ogre = ogres[i];
			ogres.splice(i, 1);
			ogre.destroy();
		}
		// Clear all knights on screen when upgrade menu is shown
		for (var i = knights.length - 1; i >= 0; i--) {
			var knight = knights[i];
			knights.splice(i, 1);
			knight.destroy();
		}
	}
	// Show third upgrade menu after 50 enemies are killed
	if (enemyKillCounter >= 50 && secondUpgradeMenuShown && !thirdUpgradeMenuShown) {
		thirdUpgradeMenuShown = true;
		// Increase upgrade costs by 5 coins when menu is shown
		if (!upgradeMenu.upgradeCost) {
			upgradeMenu.upgradeCost = 5; // Initial cost
		}
		upgradeMenu.upgradeCost += 5; // Increase by 5 coins each time
		// Update all upgrade text to show new costs
		upgradeMenu.updateUpgradeCosts();
		upgradeMenu.visible = true;
		upgradeMenu.cooldownTimer = upgradeMenu.cooldownDuration; // Start 2-second cooldown
		gameStarted = false; // Pause game while menu is open
		LK.stopMusic(); // Pause music
		// Clear all enemies on screen when upgrade menu is shown
		for (var i = enemies.length - 1; i >= 0; i--) {
			var enemy = enemies[i];
			enemies.splice(i, 1);
			enemy.destroy();
		}
		// Clear all ogres on screen when upgrade menu is shown
		for (var i = ogres.length - 1; i >= 0; i--) {
			var ogre = ogres[i];
			ogres.splice(i, 1);
			ogre.destroy();
		}
		// Clear all knights on screen when upgrade menu is shown
		for (var i = knights.length - 1; i >= 0; i--) {
			var knight = knights[i];
			knights.splice(i, 1);
			knight.destroy();
		}
	}
	// Reset consecutive spawns for paths that have cooled down (runs every frame)
	for (var pathIdx = 0; pathIdx < 5; pathIdx++) {
		// Check if enough time has passed since last spawn (cooldown expired)
		if (pathLastSpawnTime[pathIdx] !== -1 && LK.ticks - pathLastSpawnTime[pathIdx] > pathCooldownDuration) {
			// Reset consecutive spawns for this path due to cooldown
			pathConsecutiveSpawns[pathIdx] = 0;
		}
	}
	// Progressive difficulty system based on kills
	var difficultyLevel = Math.floor(enemyKillCounter / 10); // Every 10 kills increases difficulty
	var currentSpawnRate = Math.max(30, 90 - difficultyLevel * 8); // Faster spawning over time
	var enemyHealthMultiplier = 1 + difficultyLevel * 0.3; // 30% more health per difficulty level
	var enemySpeedMultiplier = 1 + difficultyLevel * 0.35; // 35% faster per difficulty level
	// Spawn enemies
	enemySpawnTimer++;
	if (enemySpawnTimer >= currentSpawnRate) {
		enemySpawnTimer = 0;
		var enemy = game.addChild(new Enemy());
		// Apply difficulty scaling to enemy stats
		enemy.health = Math.floor(100 * enemyHealthMultiplier);
		enemy.maxHealth = enemy.health;
		enemy.speed = 3 * enemySpeedMultiplier;
		// Spawn enemy at a random path entrance
		var randomPathIndex;
		if (enemyKillCounter < 5) {
			// First 5 enemies spawn from center path only
			randomPathIndex = 0; // Center path
		} else {
			// After 5 enemies, spawn from any path but limit consecutive spawns with cooldown system
			// Build available paths list
			var availablePaths = [];
			for (var pathIdx = 0; pathIdx < 5; pathIdx++) {
				// If path has spawned less than 2 consecutive times, it's available
				if (pathConsecutiveSpawns[pathIdx] < 2) {
					availablePaths.push(pathIdx);
				}
			}
			// If no paths available, reset ALL paths to ensure balanced distribution
			if (availablePaths.length === 0) {
				// Reset all paths' consecutive spawn counters
				for (var pathIdx = 0; pathIdx < 5; pathIdx++) {
					pathConsecutiveSpawns[pathIdx] = 0;
					availablePaths.push(pathIdx);
				}
			}
			randomPathIndex = availablePaths[Math.floor(Math.random() * availablePaths.length)];
		}
		// Update path-specific spawn tracking
		// Always increment consecutive spawns for the selected path
		pathConsecutiveSpawns[randomPathIndex]++;
		// Update path spawn time and global tracking
		pathLastSpawnTime[randomPathIndex] = LK.ticks;
		lastSpawnedPath = randomPathIndex;
		consecutiveSpawns = pathConsecutiveSpawns[randomPathIndex];
		var pathAngle = pathAngles[randomPathIndex];
		// Store the path information on the enemy
		enemy.pathIndex = randomPathIndex;
		enemy.pathAngle = pathAngle;
		// Calculate spawn position at screen edges
		if (randomPathIndex === 0) {
			// Center path - spawn at top edge
			enemy.x = 2048 / 2;
			enemy.y = -100;
		} else if (randomPathIndex === 1) {
			// Path 2 - spawn at top right edge
			enemy.x = 2048 + 50;
			enemy.y = -50;
		} else if (randomPathIndex === 2) {
			// Path 3 - spawn at top left edge
			enemy.x = -50;
			enemy.y = -50;
		} else if (randomPathIndex === 3) {
			// Path 4 - spawn at left edge
			enemy.x = -100;
			enemy.y = 2732 / 2 + 400;
		} else if (randomPathIndex === 4) {
			// Path 5 - spawn at right edge
			enemy.x = 2048 + 100;
			enemy.y = 2732 / 2 + 400;
		}
		// Make sure enemies spawn within screen bounds
		enemy.x = Math.max(50, Math.min(1998, enemy.x));
		enemy.y = Math.max(-200, Math.min(2732 + 100, enemy.y));
		enemy.lastX = enemy.x;
		enemies.push(enemy);
	}
	// Spawn ogres after 15 seconds (900 ticks at 60fps)
	if (LK.ticks >= 900 && LK.ticks % 180 === 0) {
		// Every 3 seconds after 15 seconds
		var ogre = game.addChild(new Ogre());
		// Apply difficulty scaling to ogre stats
		ogre.health = Math.floor(150 * enemyHealthMultiplier); // Ogres have more base health
		ogre.maxHealth = ogre.health;
		ogre.speed = 2.5 * enemySpeedMultiplier; // Ogres are slightly slower
		// Spawn ogre at a random path entrance
		var ogrePathIndex = Math.floor(Math.random() * 5);
		var ogrePathAngle = pathAngles[ogrePathIndex];
		// Store the path information on the ogre
		ogre.pathIndex = ogrePathIndex;
		ogre.pathAngle = ogrePathAngle;
		// Calculate spawn position at screen edges
		if (ogrePathIndex === 0) {
			// Center path - spawn at top edge
			ogre.x = 2048 / 2;
			ogre.y = -100;
		} else if (ogrePathIndex === 1) {
			// Path 2 - spawn at top right edge
			ogre.x = 2048 + 50;
			ogre.y = -50;
		} else if (ogrePathIndex === 2) {
			// Path 3 - spawn at top left edge
			ogre.x = -50;
			ogre.y = -50;
		} else if (ogrePathIndex === 3) {
			// Path 4 - spawn at left edge
			ogre.x = -100;
			ogre.y = 2732 / 2 + 400;
		} else if (ogrePathIndex === 4) {
			// Path 5 - spawn at right edge
			ogre.x = 2048 + 100;
			ogre.y = 2732 / 2 + 400;
		}
		// Make sure ogres spawn within screen bounds
		ogre.x = Math.max(50, Math.min(1998, ogre.x));
		ogre.y = Math.max(-200, Math.min(2732 + 100, ogre.y));
		ogre.lastX = ogre.x;
		ogres.push(ogre);
	}
	// Spawn knights after 30 enemies killed
	if (enemyKillCounter >= 30 && LK.ticks % 300 === 0) {
		// Every 5 seconds after 30th enemy
		var knight = game.addChild(new Knight());
		// Apply difficulty scaling to knight stats
		knight.health = Math.floor(200 * enemyHealthMultiplier); // Knights have highest base health
		knight.maxHealth = knight.health;
		knight.speed = 2 * enemySpeedMultiplier; // Knights are slowest
		// Spawn knight at a random path entrance
		var knightPathIndex = Math.floor(Math.random() * 5);
		var knightPathAngle = pathAngles[knightPathIndex];
		// Store the path information on the knight
		knight.pathIndex = knightPathIndex;
		knight.pathAngle = knightPathAngle;
		// Calculate spawn position at screen edges
		if (knightPathIndex === 0) {
			// Center path - spawn at top edge
			knight.x = 2048 / 2;
			knight.y = -100;
		} else if (knightPathIndex === 1) {
			// Path 2 - spawn at top right edge
			knight.x = 2048 + 50;
			knight.y = -50;
		} else if (knightPathIndex === 2) {
			// Path 3 - spawn at top left edge
			knight.x = -50;
			knight.y = -50;
		} else if (knightPathIndex === 3) {
			// Path 4 - spawn at left edge
			knight.x = -100;
			knight.y = 2732 / 2 + 400;
		} else if (knightPathIndex === 4) {
			// Path 5 - spawn at right edge
			knight.x = 2048 + 100;
			knight.y = 2732 / 2 + 400;
		}
		// Make sure knights spawn within screen bounds
		knight.x = Math.max(50, Math.min(1998, knight.x));
		knight.y = Math.max(-200, Math.min(2732 + 100, knight.y));
		knight.lastX = knight.x;
		knights.push(knight);
	}
	// Check enemy-knight collisions and cleanup off-screen enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		// Remove enemies that went off-screen at bottom
		if (enemy.y > 2732 + 100) {
			enemies.splice(i, 1);
			enemy.destroy();
			continue;
		}
		// Initialize lastIntersecting if not set
		if (enemy.lastIntersecting === undefined) {
			enemy.lastIntersecting = false;
		}
		// Check for collision transition
		var currentIntersecting = enemy.intersects(wizard);
		if (!enemy.lastIntersecting && currentIntersecting) {
			// Damage wizard when enemy touches for the first time
			wizard.takeDamage(20);
			// Remove enemy after dealing damage
			enemies.splice(i, 1);
			enemy.destroy();
			continue;
		}
		// Update last intersecting state
		enemy.lastIntersecting = currentIntersecting;
	}
	// Check ogre-wizard collisions and cleanup off-screen ogres
	for (var i = ogres.length - 1; i >= 0; i--) {
		var ogre = ogres[i];
		// Remove ogres that went off-screen at bottom
		if (ogre.y > 2732 + 100) {
			ogres.splice(i, 1);
			ogre.destroy();
			continue;
		}
		// Initialize lastIntersecting if not set
		if (ogre.lastIntersecting === undefined) {
			ogre.lastIntersecting = false;
		}
		// Check for collision transition
		var currentOgreIntersecting = ogre.intersects(wizard);
		if (!ogre.lastIntersecting && currentOgreIntersecting) {
			// Damage wizard when ogre touches for the first time
			wizard.takeDamage(30); // Ogres deal 30 damage
			// Remove ogre after dealing damage
			ogres.splice(i, 1);
			ogre.destroy();
			continue;
		}
		// Update last intersecting state
		ogre.lastIntersecting = currentOgreIntersecting;
	}
	// Check knight-wizard collisions and cleanup off-screen knights
	for (var i = knights.length - 1; i >= 0; i--) {
		var knight = knights[i];
		// Remove knights that went off-screen at bottom
		if (knight.y > 2732 + 100) {
			knights.splice(i, 1);
			knight.destroy();
			continue;
		}
		// Initialize lastIntersecting if not set
		if (knight.lastIntersecting === undefined) {
			knight.lastIntersecting = false;
		}
		// Check for collision transition
		var currentKnightIntersecting = knight.intersects(wizard);
		if (!knight.lastIntersecting && currentKnightIntersecting) {
			// Damage wizard when knight touches for the first time
			wizard.takeDamage(40); // Knights deal 40 damage
			// Remove knight after dealing damage
			knights.splice(i, 1);
			knight.destroy();
			continue;
		}
		// Update last intersecting state
		knight.lastIntersecting = currentKnightIntersecting;
	}
	// Make tap text pulse
	var pulse = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
	tapText.scale.set(pulse, pulse);
};
// Remove tap text after 5 seconds
tween({}, {}, {
	duration: 5000,
	onFinish: function onFinish() {
		if (tapText && tapText.parent) {
			tapText.destroy();
		}
	}
}); ===================================================================
--- original.js
+++ change.js
@@ -1037,8 +1037,83 @@
 		self.destroy();
 	};
 	return self;
 });
+var StartMenu = Container.expand(function () {
+	var self = Container.call(this);
+	// Full screen bone white background
+	var menuBg = self.attachAsset('startMenuBackground', {
+		anchorX: 0.5,
+		anchorY: 0.5,
+		x: 2048 / 2,
+		y: 2732 / 2
+	});
+	// Game title
+	var titleText = new Text2('WIZARD DEFENDER', {
+		size: 180,
+		fill: 0x8B4513,
+		font: "monospace"
+	});
+	titleText.anchor.set(0.5, 0.5);
+	titleText.x = 2048 / 2;
+	titleText.y = 800;
+	self.addChild(titleText);
+	// Subtitle
+	var subtitleText = new Text2('DEFEND YOUR CASTLE', {
+		size: 100,
+		fill: 0x654321,
+		font: "monospace"
+	});
+	subtitleText.anchor.set(0.5, 0.5);
+	subtitleText.x = 2048 / 2;
+	subtitleText.y = 1000;
+	self.addChild(subtitleText);
+	// Instructions
+	var instructionsText = new Text2('TAP PATHS TO CAST SPELLS\nDEFEND AGAINST ENEMIES!', {
+		size: 80,
+		fill: 0x8B4513,
+		font: "monospace"
+	});
+	instructionsText.anchor.set(0.5, 0.5);
+	instructionsText.x = 2048 / 2;
+	instructionsText.y = 1400;
+	self.addChild(instructionsText);
+	// Start button background
+	var startButtonBg = self.attachAsset('menuBackground', {
+		anchorX: 0.5,
+		anchorY: 0.5,
+		x: 2048 / 2,
+		y: 1800,
+		scaleX: 2,
+		scaleY: 1.5
+	});
+	startButtonBg.tint = 0xD2691E;
+	// Start button text
+	var startButtonText = new Text2('START GAME', {
+		size: 120,
+		fill: 0xF5F5DC,
+		font: "monospace"
+	});
+	startButtonText.anchor.set(0.5, 0.5);
+	startButtonText.x = 2048 / 2;
+	startButtonText.y = 1800;
+	self.addChild(startButtonText);
+	// Button interaction
+	self.down = function (x, y, obj) {
+		// Check if start button area was clicked
+		if (x >= 1024 - 200 && x <= 1024 + 200 && y >= 1700 && y <= 1900) {
+			self.startGame();
+		}
+	};
+	self.startGame = function () {
+		// Hide start menu and show game menu
+		self.visible = false;
+		if (gameMenu) {
+			gameMenu.visible = true;
+		}
+	};
+	return self;
+});
 var UpgradeMenu = Container.expand(function () {
 	var self = Container.call(this);
 	// Set high z-index to ensure menu appears above all game elements
 	self.zIndex = 1000;
@@ -1496,10 +1571,13 @@
 var ogres = [];
 var knights = [];
 var coins = [];
 var projectiles = [];
-// Create and show game menu
+// Create and show start menu first
+var startMenu = game.addChild(new StartMenu());
+// Create game menu (initially hidden)
 gameMenu = game.addChild(new GameMenu());
+gameMenu.visible = false;
 // Create upgrade menu (initially hidden)
 upgradeMenu = game.addChild(new UpgradeMenu());
 upgradeMenu.visible = false;
 // Create 5 stone paths leading toward the wizard position