/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
// Enemy: Bat
var Bat = Container.expand(function (x, y) {
	var self = Container.call(this);
	var bat = self.attachAsset('bat', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (2.5 + Math.random() * 2); // Slower bats
	self.vy = (Math.random() > 0.5 ? 1 : -1) * 0.5; // Slower vertical movement
	self.frozen = false;
	self.frozenTimer = 0;
	self.trapped = false;
	self.trapTimer = 0;
	self.update = function () {
		// Pause logic for speed powerup
		if (self.pausedBySpeed) {
			return;
		}
		if (self.trapped) {
			self.trapTimer--;
			if (self.trapTimer <= 0) {
				self.trapped = false;
				self.alpha = 1;
			}
			return;
		}
		if (self.frozen) {
			self.frozenTimer--;
			if (self.frozenTimer <= 0) {
				self.frozen = false;
				bat.tint = 0x2a2a2a;
				// Remove freeze overlay if present
				if (self.iceOverlay) {
					self.removeChild(self.iceOverlay);
					self.iceOverlay = null;
				}
			}
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		if (self.y < 200 || self.y > 2732 - 200) self.vy *= -1;
		// Prevent bats from touching platforms: bounce off if intersecting
		for (var i = 0; i < platforms.length; i++) {
			var p = platforms[i];
			if (self.intersects(p)) {
				// Bounce bat away from platform
				// Determine if bat is coming from above/below or left/right
				var dx = self.x - p.x;
				var dy = self.y - p.y;
				if (Math.abs(dx) > Math.abs(dy)) {
					// Bounce horizontally
					self.vx *= -1;
					// Move bat out of platform horizontally
					if (dx > 0) {
						self.x = p.x + p.width / 2 + 40;
					} else {
						self.x = p.x - p.width / 2 - 40;
					}
				} else {
					// Bounce vertically
					self.vy *= -1;
					// Move bat out of platform vertically
					if (dy > 0) {
						self.y = p.y + p.height / 2 + 40;
					} else {
						self.y = p.y - p.height / 2 - 40;
					}
				}
			}
		}
	};
	// Freeze effect
	self.freeze = function () {
		self.frozen = true;
		self.frozenTimer = 180;
		bat.tint = 0x7fdfff;
	};
	// Trap effect
	self.trap = function () {
		self.trapped = true;
		self.trapTimer = 90;
		self.alpha = 0.4;
	};
	// Shatter (destroy)
	self.shatter = function () {
		LK.getSound('shatter').play();
		self.destroy();
		var idx = enemies.indexOf(self);
		if (idx >= 0) enemies.splice(idx, 1);
		LK.setScore(LK.getScore() + 1);
		scoreTxt.setText(LK.getScore());
	};
	return self;
});
// Boss: Moves randomly
var Boss = Container.expand(function (x, y) {
	var self = Container.call(this);
	var boss = self.attachAsset('Boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = 0;
	self.vy = 0;
	self.randomMoveTimer = 60 + Math.floor(Math.random() * 60);
	self.lastX = self.x;
	self.lastY = self.y;
	self.update = function () {
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			var speed = 6 + Math.random() * 4;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.7;
			self.randomMoveTimer = 60 + Math.floor(Math.random() * 60);
		}
		self.lastX = self.x;
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 400 && self.y < 2732 - 400) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 400) self.y = 2732 - 400;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Power-up: Broom
var BroomPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var broom = self.attachAsset('Broom', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'broom';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Evanasense (player) class
var Evanasense = Container.expand(function () {
	var self = Container.call(this);
	// Body
	var body = self.attachAsset('evana', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Hat
	var hat = self.attachAsset('evana_hat', {
		anchorX: 0.5,
		anchorY: 1.1,
		y: -60
	});
	// Physics
	self.vx = 0;
	self.vy = 0;
	self.lastY = 0;
	self.isOnGround = false;
	self.facing = 1; // 1: right, -1: left
	self.canShoot = true;
	self.shootCooldown = 0;
	self.shielded = false;
	self.speedBoost = 0;
	self.fullMoon = false;
	self.fullMoonTimer = 0;
	self.canFly = false;
	self.flyTimer = 0;
	// For power-up visuals
	self.shieldSprite = null;
	// Freeze spell
	self.castFreeze = function () {
		if (!self.canShoot) return;
		self.canShoot = false;
		self.shootCooldown = 30; // 0.5s cooldown
		var orb = new FreezeOrb(self.x, self.y - 60, self.facing);
		game.addChild(orb);
		freezeOrbs.push(orb);
		LK.getSound('freeze').play();
	};
	// Trap spell (ice block, only in full moon mode)
	self.castTrap = function () {
		if (!self.fullMoon) return;
		var trap = new IceBlock(self.x + 100 * self.facing, self.y - 40);
		game.addChild(trap);
		iceBlocks.push(trap);
		LK.getSound('trap').play();
	};
	// Power-up: Shield
	self.gainShield = function () {
		self.shielded = true;
		if (!self.shieldSprite) {
			self.shieldSprite = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
		}
		self.shieldSprite.visible = true;
	};
	self.loseShield = function () {
		self.shielded = false;
		if (self.shieldSprite) self.shieldSprite.visible = false;
	};
	// Power-up: Speed
	self.gainSpeed = function () {
		self.speedBoost = 180;
		LK.effects.flashObject(self, 0xffe066, 400);
	};
	// Power-up: Full Moon
	self.activateFullMoon = function () {
		self.fullMoon = true;
		self.fullMoonTimer = 360; // 6 seconds
		LK.effects.flashObject(self, 0xf6f1c7, 600);
	};
	// Update
	self.update = function () {
		// Flying logic
		if (self.canFly) {
			// While flying, allow free vertical movement with up/down, and reduce gravity
			if (upPressed) {
				self.vy = -18;
			} else if (downPressed) {
				self.vy = 18;
			} else {
				self.vy *= 0.7;
				if (Math.abs(self.vy) < 1) self.vy = 0;
			}
			// Optional: add a little gravity so she floats down if not pressing up
			self.vy += 0.5;
			if (self.vy > 24) self.vy = 24;
			if (self.vy < -24) self.vy = -24;
			// Flying timer
			if (typeof self.flyTimer === "undefined") self.flyTimer = 600;
			self.flyTimer--;
			if (self.flyTimer <= 0) {
				self.canFly = false;
				self.flyTimer = 0;
			}
		} else {
			// Gravity
			self.vy += 2.2;
			if (self.vy > 40) self.vy = 40;
		}
		// Set moveDir for left/right, and moveVert for up/down (support diagonals)
		self.moveDir = 0;
		self.moveVert = 0;
		if (leftPressed && !rightPressed) {
			self.moveDir = -1;
		} else if (rightPressed && !leftPressed) {
			self.moveDir = 1;
		}
		if (upPressed && !downPressed) {
			self.moveVert = -1;
		} else if (downPressed && !upPressed) {
			self.moveVert = 1;
		}
		// If both a horizontal and vertical direction are pressed, normalize diagonal speed
		if (self.moveDir !== 0 && self.moveVert !== 0) {
			// Reduce speed for diagonal movement to keep consistent velocity
			self.moveDir *= Math.SQRT1_2;
			self.moveVert *= Math.SQRT1_2;
		}
		// --- Up/Down button logic (for future use, e.g. drop through platforms) ---
		// (Handled above for movement)
		// --- Fire button logic ---
		if (firePressed && self.canShoot) {
			self.castFreeze();
			firePressed = false; // Only fire once per press
		}
		// Movement
		var moveSpeed = 18 + (self.speedBoost > 0 ? 10 : 0);
		if (self.moveDir || self.moveVert) {
			self.vx = moveSpeed * self.moveDir;
			self.vy = self.canFly ? moveSpeed * self.moveVert : self.vy;
			if (self.moveDir) self.facing = self.moveDir > 0 ? 1 : -1;
		} else {
			self.vx *= 0.7;
			if (Math.abs(self.vx) < 1) self.vx = 0;
			if (!self.canFly) {
				// Only apply gravity if not flying
				// (already handled above)
			}
		}
		// Apply position
		self.lastY = self.y;
		// --- Mario-style jump: allow jump if jumpPressed and isOnGround ---
		// Double jump support: allow one extra jump if yuDoubleJump is true
		if (typeof self.yuDoubleJump === "undefined") self.yuDoubleJump = false;
		if (typeof self.hasDoubleJumped === "undefined") self.hasDoubleJumped = false;
		if (jumpPressed) {
			var jumpPower = -38;
			if (self.moonJumpTimer && self.moonJumpTimer > 0) {
				jumpPower = -54; // Higher jump during moon effect
			}
			if (self.isOnGround) {
				self.vy = jumpPower;
				self.isOnGround = false;
				self.hasDoubleJumped = false;
			} else if (self.yuDoubleJump && !self.hasDoubleJumped) {
				self.vy = jumpPower;
				self.hasDoubleJumped = true;
				// Optional: flash effect for double jump
				LK.effects.flashObject(self, 0xb8e6ff, 200);
			}
		}
		if (self.moonJumpTimer && self.moonJumpTimer > 0) {
			self.moonJumpTimer--;
			if (self.moonJumpTimer === 0) {
				// Optionally, add a visual effect to show moon jump ended
				LK.effects.flashObject(self, 0xf6f1c7, 200);
			}
		}
		self.x += self.vx;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Clamp vertically and collide with all platforms
		self.isOnGround = false;
		var prevBottom = self.lastY + body.height / 2;
		var currBottom = self.y + body.height / 2;
		for (var i = 0; i < platforms.length; i++) {
			var plat = platforms[i];
			var platTop = plat.y - plat.height / 2;
			// Allow drop through platforms if downPressed, except for the floor (y >= 2732-60)
			var isFloor = plat.y >= 2732 - 60;
			if (self.vy > 0 && prevBottom <= platTop && currBottom >= platTop && self.x + body.width / 2 > plat.x - plat.width / 2 && self.x - body.width / 2 < plat.x + plat.width / 2 && (!downPressed || isFloor)) {
				self.y = platTop - body.height / 2;
				self.vy = 0;
				self.isOnGround = true;
				// Play platform sound when landing
				if (typeof self.lastWasOnGround === "undefined") self.lastWasOnGround = false;
				// (platform sound removed as requested)
				self.lastWasOnGround = true;
			} else {
				if (typeof self.lastWasOnGround === "undefined") self.lastWasOnGround = false;
				self.lastWasOnGround = false;
			}
		}
		// Clamp to bottom of screen
		if (self.y > 2732 - 60) {
			self.y = 2732 - 60;
			self.vy = 0;
			self.isOnGround = true;
		}
		// Shooting cooldown
		if (!self.canShoot) {
			self.shootCooldown--;
			if (self.shootCooldown <= 0) {
				self.canShoot = true;
			}
		}
		// Speed boost timer
		if (self.speedBoost > 0) {
			self.speedBoost--;
		}
		// Full moon timer
		if (self.fullMoon) {
			self.fullMoonTimer--;
			if (self.fullMoonTimer <= 0) {
				self.fullMoon = false;
			}
		}
	};
	return self;
});
// Freeze orb spell
var FreezeOrb = Container.expand(function (x, y, dir) {
	var self = Container.call(this);
	var orb = self.attachAsset('freeze_orb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = 32 * dir;
	self.lifetime = 60;
	self.update = function () {
		self.x += self.vx;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		self.lifetime--;
		if (self.lifetime <= 0) {
			self.destroy();
			var idx = freezeOrbs.indexOf(self);
			if (idx >= 0) freezeOrbs.splice(idx, 1);
		}
	};
	return self;
});
// Enemy: Ghost
var Ghost = Container.expand(function (x, y) {
	var self = Container.call(this);
	var ghost = self.attachAsset('ghost', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.85
	});
	self.x = x;
	self.y = y;
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (3 + Math.random() * 2); // Slower ghosts
	self.vy = (Math.random() - 0.5) * 2; // Add a little vertical movement
	self.frozen = false;
	self.frozenTimer = 0;
	self.trapped = false;
	self.trapTimer = 0;
	self.randomMoveTimer = 30 + Math.floor(Math.random() * 60); // How many frames until next direction change
	self.lastY = self.y;
	self.update = function () {
		// Pause logic for speed powerup
		if (self.pausedBySpeed) {
			return;
		}
		if (self.trapped) {
			self.trapTimer--;
			if (self.trapTimer <= 0) {
				self.trapped = false;
				self.alpha = 0.85;
			}
			return;
		}
		if (self.frozen) {
			self.frozenTimer--;
			if (self.frozenTimer <= 0) {
				self.frozen = false;
				ghost.tint = 0xcfd6e6;
				// Remove freeze overlay if present
				if (self.iceOverlay) {
					self.removeChild(self.iceOverlay);
					self.iceOverlay = null;
				}
			}
			return;
		}
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			// Change direction randomly
			var speed = 3 + Math.random() * 2;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.5; // Less vertical movement
			self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
		}
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	// Freeze effect
	self.freeze = function () {
		self.frozen = true;
		self.frozenTimer = 180;
		ghost.tint = 0x7fdfff;
	};
	// Trap effect
	self.trap = function () {
		self.trapped = true;
		self.trapTimer = 90;
		self.alpha = 0.4;
	};
	// Shatter (destroy)
	self.shatter = function () {
		LK.getSound('shatter').play();
		self.destroy();
		var idx = enemies.indexOf(self);
		if (idx >= 0) enemies.splice(idx, 1);
		LK.setScore(LK.getScore() + 1);
		scoreTxt.setText(LK.getScore());
	};
	return self;
});
// Ice block trap (full moon mode)
var IceBlock = Container.expand(function (x, y) {
	var self = Container.call(this);
	var block = self.attachAsset('ice_block', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.85
	});
	self.x = x;
	self.y = y;
	self.lifetime = 120;
	self.update = function () {
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		self.lifetime--;
		if (self.lifetime <= 0) {
			self.destroy();
			var idx = iceBlocks.indexOf(self);
			if (idx >= 0) iceBlocks.splice(idx, 1);
		}
	};
	return self;
});
// Power-up: Lifepotion (adds a life)
var LifepotionPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var potion = self.attachAsset('Lifepotion', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'lifepotion';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Power-up: Moon (full moon mode)
var MoonPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var moon = self.attachAsset('moon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'moon';
	self.vx = 3 + Math.random() * 2; // Slower moon movement
	self.lastX = self.x;
	self.update = function () {
		self.lastX = self.x;
		self.x += self.vx;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Platform
var Platform = Container.expand(function (x, y, w) {
	var self = Container.call(this);
	var plat = self.attachAsset('platform', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: w || 320
	});
	self.x = x;
	self.y = y;
	self.width = w || 320;
	self.height = 40;
	return self;
});
// Power-up: Shield
var ShieldPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var shield = self.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'shield';
	self.update = function () {
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Power-up: Speed
var SpeedPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var speed = self.attachAsset('speed', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'speed';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Power-up: Yu (moves randomly)
var YuPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var yu = self.attachAsset('Yu', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'yu';
	// Random movement variables
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (3 + Math.random() * 2);
	self.vy = (Math.random() - 0.5) * 2;
	self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
	self.lastY = self.y;
	self.update = function () {
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			var speed = 3 + Math.random() * 2;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.5;
			self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
		}
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x18141e
});
/**** 
* Game Code
****/ 
// Add background image
// Add background image
var bg = LK.getAsset('bg', {
	anchorX: 0,
	anchorY: 0,
	width: 2048,
	height: 2732,
	x: 0,
	y: 0
});
game.addChild(bg);
// (rulesPanel removed as per request)
// --- Game Start Overlay ---
var startOverlay = new Container();
var rulesText = new Text2("🧙♀️ Witch's Night: Game Rules\n\n" + "- Move the witch with the blue buttons.\n" + "- Tap the yellow button to cast freeze spells.\n" + "- Collect powerups: Moon (full moon mode), Shield, Speed, Life Potion, Broom (fly!), Yu (cancel speed).\n" + "- Avoid ghosts and bats! Touching them loses a life unless shielded.\n" + "- Freeze or trap enemies, then touch them again to shatter.\n" + "- Clear all enemies to advance to the next stage.\n" + "- Survive as long as you can!\n\n" + "Good luck! Tap Start to play.", {
	size: 70,
	fill: 0xF6F1C7,
	align: "center",
	wordWrap: true,
	wordWrapWidth: 1600
});
rulesText.anchor.set(0.5, 0.5);
rulesText.x = 1024;
rulesText.y = 900;
startOverlay.addChild(rulesText);
var startBtn = new Text2("START", {
	size: 180,
	fill: 0xB8E6FF,
	fontWeight: "bold"
});
startBtn.anchor.set(0.5, 0.5);
startBtn.x = 1024;
startBtn.y = 1800;
startOverlay.addChild(startBtn);
// Block gameplay until start is pressed
game.paused = true;
// Add start overlay to the very front so it appears above everything
LK.gui.addChild(startOverlay);
// Hide overlay and start game on button press
startBtn.down = function () {
	if (startOverlay.parent) startOverlay.parent.removeChild(startOverlay);
	game.paused = false;
};
// Main character: Evanasense (witch)
// Witch body
// Witch hat
// Enemy: Ghost
// Enemy: Bat
// Platform
// Spell: Freeze orb
// Spell: Trap (ice block)
// Power-up: Moon
// Power-up: Shield
// Power-up: Speed
// Sound effects
// Music
// --- Classic D-pad controls (eight buttons, with diagonals) ---
// D-pad button size and spacing (increased for better touch usability)
var dpadBtnSize = 260;
var dpadSpacing = 50;
// Move D-pad higher by decreasing dpadY (more negative = higher on screen)
var dpadY = -420;
var dpadX = 360;
// Diagonal offset (for diagonal buttons)
var diagOffset = Math.round((dpadBtnSize + dpadSpacing) * 0.7);
// Helper: reset all direction states (for compatibility)
function resetButtonDirections() {
	leftPressed = false;
	rightPressed = false;
	upPressed = false;
	downPressed = false;
	// Also clear jumpPressed for diagonals
	jumpPressed = false;
}
// Left button
var leftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - dpadBtnSize - dpadSpacing,
	y: dpadY,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(leftBtn);
var leftArrow = new Text2("◀", {
	size: 180,
	fill: 0x222244
});
leftArrow.anchor.set(0.5, 0.5);
leftArrow.x = leftBtn.x;
leftArrow.y = leftBtn.y;
LK.gui.bottomLeft.addChild(leftArrow);
// Right button
var rightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + dpadBtnSize + dpadSpacing,
	y: dpadY,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(rightBtn);
var rightArrow = new Text2("▶", {
	size: 180,
	fill: 0x222244
});
rightArrow.anchor.set(0.5, 0.5);
rightArrow.x = rightBtn.x;
rightArrow.y = rightBtn.y;
LK.gui.bottomLeft.addChild(rightArrow);
// Up button
var upBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX,
	y: dpadY - dpadBtnSize - dpadSpacing,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upBtn);
var upArrow = new Text2("▲", {
	size: 180,
	fill: 0x222244
});
upArrow.anchor.set(0.5, 0.5);
upArrow.x = upBtn.x;
upArrow.y = upBtn.y;
LK.gui.bottomLeft.addChild(upArrow);
// Down button
var downBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX,
	y: dpadY + dpadBtnSize + dpadSpacing,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downBtn);
var downArrow = new Text2("▼", {
	size: 180,
	fill: 0x222244
});
downArrow.anchor.set(0.5, 0.5);
downArrow.x = downBtn.x;
downArrow.y = downBtn.y;
LK.gui.bottomLeft.addChild(downArrow);
// Up-Left button
var upLeftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - diagOffset,
	y: dpadY - diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upLeftBtn);
var upLeftArrow = new Text2("◤", {
	size: 180,
	fill: 0x222244
});
upLeftArrow.anchor.set(0.5, 0.5);
upLeftArrow.x = upLeftBtn.x;
upLeftArrow.y = upLeftBtn.y;
LK.gui.bottomLeft.addChild(upLeftArrow);
// Up-Right button
var upRightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + diagOffset,
	y: dpadY - diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upRightBtn);
var upRightArrow = new Text2("◥", {
	size: 180,
	fill: 0x222244
});
upRightArrow.anchor.set(0.5, 0.5);
upRightArrow.x = upRightBtn.x;
upRightArrow.y = upRightBtn.y;
LK.gui.bottomLeft.addChild(upRightArrow);
// Down-Left button
var downLeftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - diagOffset,
	y: dpadY + diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downLeftBtn);
var downLeftArrow = new Text2("◣", {
	size: 180,
	fill: 0x222244
});
downLeftArrow.anchor.set(0.5, 0.5);
downLeftArrow.x = downLeftBtn.x;
downLeftArrow.y = downLeftBtn.y;
LK.gui.bottomLeft.addChild(downLeftArrow);
// Down-Right button
var downRightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + diagOffset,
	y: dpadY + diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downRightBtn);
var downRightArrow = new Text2("◢", {
	size: 180,
	fill: 0x222244
});
downRightArrow.anchor.set(0.5, 0.5);
downRightArrow.x = downRightBtn.x;
downRightArrow.y = downRightBtn.y;
LK.gui.bottomLeft.addChild(downRightArrow);
// (Diagonal D-pad buttons added)
// D-pad button handlers
leftBtn.down = function () {
	if (game.paused) return;
	leftPressed = true;
};
leftBtn.up = function () {
	leftPressed = false;
};
rightBtn.down = function () {
	if (game.paused) return;
	rightPressed = true;
};
rightBtn.up = function () {
	rightPressed = false;
};
upBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	jumpPressed = true;
};
upBtn.up = function () {
	upPressed = false;
	jumpPressed = false;
};
downBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
};
downBtn.up = function () {
	downPressed = false;
};
// Up-Left button handlers
upLeftBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	leftPressed = true;
	jumpPressed = true;
};
upLeftBtn.up = function () {
	upPressed = false;
	leftPressed = false;
	jumpPressed = false;
};
// Up-Right button handlers
upRightBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	rightPressed = true;
	jumpPressed = true;
};
upRightBtn.up = function () {
	upPressed = false;
	rightPressed = false;
	jumpPressed = false;
};
// Down-Left button handlers
downLeftBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
	leftPressed = true;
};
downLeftBtn.up = function () {
	downPressed = false;
	leftPressed = false;
};
// Down-Right button handlers
downRightBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
	rightPressed = true;
};
downRightBtn.up = function () {
	downPressed = false;
	rightPressed = false;
};
// (Diagonal D-pad button handlers added)
var fireBtn = new Text2('🔥', {
	size: 170,
	fill: 0xF6F1C7
});
fireBtn.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(fireBtn);
fireBtn.x = -500;
fireBtn.y = -220;
// Control state
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
var jumpPressed = false;
var firePressed = false;
// (Diagonal (ara yön) support removed)
// Touch handlers for fire button
fireBtn.down = function (x, y, obj) {
	if (game.paused) return;
	firePressed = true;
	LK.getSound('Fire').play();
};
fireBtn.up = function (x, y, obj) {
	if (game.paused) return;
	firePressed = false;
};
var player;
var platforms = [];
var enemies = [];
var freezeOrbs = [];
var iceBlocks = [];
var powerups = [];
var stage = 1;
var stageCleared = false;
var stageTimer = 0;
var dragNode = null;
var moveStartX = 0;
var moveDir = 0;
var scoreTxt;
// Add lives
var lives = 1;
var livesTxt = new Text2('Lives: ' + lives, {
	size: 70,
	fill: 0xF6F1C7
});
livesTxt.anchor.set(0, 0);
LK.gui.top.addChild(livesTxt);
// Place lives at top left, but not in the 100x100 reserved area
livesTxt.x = 120;
livesTxt.y = 20;
// Score display
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xF6F1C7
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Per-stage score tracking
var stageScores = [];
var currentStageScore = 0;
// Always keep score display updated
if (typeof scoreUpdateTimerId === "undefined") {
	var scoreUpdateTimerId = LK.setInterval(function () {
		if (scoreTxt && typeof LK.getScore === "function") {
			var currentScore = LK.getScore();
			if (scoreTxt.text !== String(currentScore)) {
				scoreTxt.setText(currentScore);
			}
		}
	}, 100);
}
// Stage display
var stageTxt = new Text2('Stage 1', {
	size: 70,
	fill: 0xB8E6FF
});
stageTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(stageTxt);
stageTxt.y = 120;
// Helper: spawn platforms
function spawnPlatforms() {
	// Clear old
	for (var i = 0; i < platforms.length; i++) platforms[i].destroy();
	platforms = [];
	// Floor
	var floor = new Platform(1024, 2732 - 40, 2048);
	game.addChild(floor);
	platforms.push(floor);
	// Snow Bros style: 5-6 fixed rows, wide platforms, even spacing, classic arcade
	var rows = 6;
	var yStart = 2732 - 300;
	var yStep = 320;
	for (var i = 0; i < rows; i++) {
		var y = yStart - i * yStep;
		// Classic: alternate left/right gaps for each row
		if (i % 2 === 0) {
			// Full width platform
			var plat = new Platform(1024, y, 1600);
			game.addChild(plat);
			platforms.push(plat);
		} else {
			// Two half platforms with a gap in the middle
			var leftPlat = new Platform(512, y, 700);
			var rightPlat = new Platform(1536, y, 700);
			game.addChild(leftPlat);
			game.addChild(rightPlat);
			platforms.push(leftPlat);
			platforms.push(rightPlat);
		}
	}
}
// Helper: spawn enemies
function spawnEnemies() {
	for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
	enemies = [];
	var ghostCount = 2 + Math.floor(stage / 2);
	var batCount = 3 + Math.floor(stage / 2); // Increased number of bats for more slow bats
	for (var i = 0; i < ghostCount; i++) {
		var px = 200 + Math.random() * (2048 - 400);
		var py = 400 + Math.random() * 1200;
		var g = new Ghost(px, py);
		// Make ghosts faster in stage 2+
		if (stage >= 2) {
			var speed = (Math.random() > 0.5 ? 1 : -1) * (5 + Math.random() * 2.5);
			var angle = Math.random() * Math.PI * 2;
			g.vx = Math.cos(angle) * speed;
			g.vy = Math.sin(angle) * speed * 0.7;
		}
		game.addChild(g);
		enemies.push(g);
	}
	for (var i = 0; i < batCount; i++) {
		var px = 200 + Math.random() * (2048 - 400);
		var py = 300 + Math.random() * 1000;
		var b = new Bat(px, py);
		// Make bats faster in stage 2+
		if (stage >= 2) {
			b.vx = (Math.random() > 0.5 ? 1 : -1) * (5 + Math.random() * 2.5);
			b.vy = (Math.random() > 0.5 ? 1 : -1) * 1.2;
		}
		game.addChild(b);
		enemies.push(b);
	}
}
// Helper: spawn powerups
function spawnPowerups() {
	for (var i = 0; i < powerups.length; i++) powerups[i].destroy();
	powerups = [];
	// Always one moon per stage
	var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
	game.addChild(moon);
	powerups.push(moon);
	// Limit shields to max 3 per stage
	var shieldsThisStage = 0;
	// 50% chance for shield
	if (Math.random() < 0.5 && shieldsThisStage < 3) {
		var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(shield);
		powerups.push(shield);
		shieldsThisStage++;
	}
	// 50% chance for speed
	if (Math.random() < 0.5) {
		var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(speed);
		powerups.push(speed);
	}
	// Always spawn a lifepotion at the beginning of every stage
	var lifepotion = new LifepotionPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
	game.addChild(lifepotion);
	powerups.push(lifepotion);
	// 40% chance for an extra lifepotion
	if (Math.random() < 0.4) {
		var extraLifepotion = new LifepotionPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(extraLifepotion);
		powerups.push(extraLifepotion);
	}
	// Store shield count for this stage globally for use in other shield spawns
	game.shieldsThisStage = shieldsThisStage;
}
// Start new stage
function startStage() {
	stageCleared = false;
	stageTimer = 0;
	stageTxt.setText('Stage ' + stage);
	// Store previous stage score
	if (typeof currentStageScore !== "undefined" && stage > 1) {
		stageScores[stage - 2] = currentStageScore;
	}
	// Reset score for new stage
	currentStageScore = 0;
	LK.setScore(0);
	scoreTxt.setText('0');
	lives = 7;
	livesTxt.setText('Lives: ' + lives);
	spawnPlatforms();
	spawnEnemies();
	// Reset shield count for this stage before spawning powerups
	game.shieldsThisStage = 0;
	spawnPowerups();
	// Send Yu in stages 2, 3, 4, 5
	if (stage >= 2 && stage <= 5) {
		var yu = new YuPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(yu);
		powerups.push(yu);
	}
	// Place player
	if (player) player.destroy();
	player = new Evanasense();
	player.x = 1024;
	player.y = 2732 - 200;
	game.addChild(player);
}
// Begin first stage
startStage();
// Timer to spawn a random shield every 30 seconds
if (typeof shieldTimerId === "undefined") {
	var shieldTimerId = LK.setInterval(function () {
		// Count current shields on the field
		var shieldCount = 0;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'shield') shieldCount++;
		}
		// Also count shields spawned this stage (if tracked)
		if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
		// Only spawn if less than 3 shields on the field and not more than 3 spawned this stage
		if (shieldCount < 3 && game.shieldsThisStage < 3) {
			var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(shield);
			powerups.push(shield);
			game.shieldsThisStage++;
		}
	}, 30000); // 30,000 ms = 30 seconds
}
// Timer to spawn a speed powerup every 40 seconds, only one at a time
if (typeof speedPowerTimerId === "undefined") {
	var speedPowerTimerId = LK.setInterval(function () {
		// Only spawn if there is no speed powerup currently on the field
		var hasSpeed = false;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'speed') {
				hasSpeed = true;
				break;
			}
		}
		if (!hasSpeed) {
			var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(speed);
			powerups.push(speed);
		}
	}, 40000); // 40,000 ms = 40 seconds
}
// Timer to spawn a broom every 30 seconds
if (typeof broomTimerId === "undefined") {
	var broomTimerId = LK.setInterval(function () {
		// Spawn a broom powerup at a random position
		var broom = new BroomPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(broom);
		powerups.push(broom);
	}, 30000); // 30,000 ms = 30 seconds
}
// Timer to send 10 Yu powerups, one every 3 seconds, only in stage 2+
if (typeof yuSendCount === "undefined") {
	var yuSendCount = 0;
	var yuSendTimerId = LK.setInterval(function () {
		// Only send Yu if stage >= 2
		if (stage >= 2 && yuSendCount < 10) {
			var yu = new YuPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(yu);
			powerups.push(yu);
			yuSendCount++;
		}
		// Reset yuSendCount if stage changes (so Yu can be sent again in new stage)
		if (typeof lastYuStage === "undefined") {
			var lastYuStage = stage;
		}
		if (stage !== lastYuStage) {
			yuSendCount = 0;
			lastYuStage = stage;
		}
		if (yuSendCount >= 10) {
			// Don't clear interval, just stop sending until next stage
		}
	}, 3000); // 3,000 ms = 3 seconds
}
// Bat flying effect: swap bat/bat2 asset every 1 second
if (typeof batFlyTimerId === "undefined") {
	var batFlyTimerId = LK.setInterval(function () {
		for (var i = 0; i < enemies.length; i++) {
			var e = enemies[i];
			if (e instanceof Bat && e.children && e.children.length > 0) {
				// Find the bat asset (assume it's the first child)
				var batSprite = e.children[0];
				// Swap asset: if bat, change to bat2; if bat2, change to bat
				var currentAssetId = batSprite.assetId || 'bat';
				e.removeChild(batSprite);
				var newAssetId = currentAssetId === 'bat' ? 'bat2' : 'bat';
				var newBat = e.attachAsset(newAssetId, {
					anchorX: 0.5,
					anchorY: 0.5
				});
				// Store which asset is currently used
				newBat.assetId = newAssetId;
				// Move new bat to the front
				e.setChildIndex(newBat, 0);
			}
		}
	}, 1000); // 1000 ms = 1 second
}
// Ghost flying effect: swap ghost/ghost2 asset every 1 second
if (typeof ghostFlyTimerId === "undefined") {
	var ghostFlyTimerId = LK.setInterval(function () {
		for (var i = 0; i < enemies.length; i++) {
			var e = enemies[i];
			if (e instanceof Ghost && e.children && e.children.length > 0) {
				// Find the ghost asset (assume it's the first child)
				var ghostSprite = e.children[0];
				// Swap asset: if ghost, change to ghost2; if ghost2, change to ghost
				var currentAssetId = ghostSprite.assetId || 'ghost';
				e.removeChild(ghostSprite);
				var newAssetId = currentAssetId === 'ghost' ? 'Ghost2' : 'ghost';
				var newGhost = e.attachAsset(newAssetId, {
					anchorX: 0.5,
					anchorY: 0.5,
					alpha: 0.85
				});
				// Store which asset is currently used
				newGhost.assetId = newAssetId;
				// Move new ghost to the front
				e.setChildIndex(newGhost, 0);
			}
		}
	}, 1000); // 1000 ms = 1 second
}
// Add portals to the game
var portal1 = new Container();
var portal1Sprite = portal1.attachAsset('Portal1', {
	anchorX: 0.5,
	anchorY: 0.5
});
portal1.x = 400;
portal1.y = 400;
game.addChild(portal1);
var portal2 = new Container();
var portal2Sprite = portal2.attachAsset('Portal2', {
	anchorX: 0.5,
	anchorY: 0.5
});
portal2.x = 1600;
portal2.y = 2000;
game.addChild(portal2);
// Track last intersection state for portal1
var lastPortal1Intersecting = false;
// Main update loop
game.update = function () {
	// Pause all gameplay and input until start is pressed
	if (game.paused) return;
	// (Removed shield spawn every 25 points logic)
	// --- Shield spawn every 25 points, only once per threshold ---
	if (typeof lastShieldScore === "undefined") {
		var lastShieldScore = 0;
	}
	var currentScore = LK.getScore();
	if (currentScore > 0 && currentScore % 25 === 0 && lastShieldScore !== currentScore) {
		// Only spawn one shield per threshold, and only if less than 3 shields this stage
		var shieldCount = 0;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'shield') shieldCount++;
		}
		if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
		if (shieldCount < 3 && game.shieldsThisStage < 3) {
			var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(shield);
			powerups.push(shield);
			game.shieldsThisStage++;
		}
		lastShieldScore = currentScore;
	}
	if (currentScore % 25 !== 0) {
		// Reset so next threshold can trigger
		lastShieldScore = 0;
	}
	// Update player
	if (player) player.update();
	// Portal teleport logic
	if (player && portal1 && portal2) {
		// Portal1 -> Portal2
		var isIntersecting1 = player.intersects(portal1);
		if (!lastPortal1Intersecting && isIntersecting1) {
			// Teleport player to portal2's position
			player.x = portal2.x;
			player.y = portal2.y;
			// Optional: flash effect to show teleport
			LK.effects.flashObject(player, 0xb8e6ff, 300);
		}
		lastPortal1Intersecting = isIntersecting1;
		// Portal2 -> Portal1
		if (typeof lastPortal2Intersecting === "undefined") {
			var lastPortal2Intersecting = false;
		}
		var isIntersecting2 = player.intersects(portal2);
		if (!lastPortal2Intersecting && isIntersecting2) {
			// Teleport player to portal1's position
			player.x = portal1.x;
			player.y = portal1.y;
			// Optional: flash effect to show teleport
			LK.effects.flashObject(player, 0xb8e6ff, 300);
		}
		lastPortal2Intersecting = isIntersecting2;
	}
	// Track ice orb hits for bat freeze mechanic
	if (typeof batFreezeHitCount === "undefined") {
		var batFreezeHitCount = 0;
		var batFreezeActive = false;
		var batFreezeTimer = 0;
	}
	// --- FreezeOrb grow effect: 3x size for 5 seconds after moon ---
	if (typeof freezeOrbGrowTimer === "undefined") {
		var freezeOrbGrowTimer = 0;
	}
	if (freezeOrbGrowTimer > 0) {
		freezeOrbGrowTimer--;
		for (var i = 0; i < freezeOrbs.length; i++) {
			var orb = freezeOrbs[i];
			if (!orb._grew) {
				if (orb.children && orb.children.length > 0) {
					var sprite = orb.children[0];
					sprite.scaleX = 3;
					sprite.scaleY = 3;
					orb._grew = true;
				}
			}
		}
	} else {
		for (var i = 0; i < freezeOrbs.length; i++) {
			var orb = freezeOrbs[i];
			if (orb._grew && orb.children && orb.children.length > 0) {
				var sprite = orb.children[0];
				sprite.scaleX = 1;
				sprite.scaleY = 1;
				orb._grew = false;
			}
		}
	}
	// Update freeze orbs
	for (var i = freezeOrbs.length - 1; i >= 0; i--) {
		var orb = freezeOrbs[i];
		orb.update();
		// Collide with enemies
		for (var j = 0; j < enemies.length; j++) {
			var e = enemies[j];
			if (!e.frozen && !e.trapped && orb.intersects(e)) {
				// --- Freeze effect for all enemies hit by freeze_orb ---
				if (typeof e.freeze === "function") {
					e.freeze();
					LK.getSound('hit').play();
				}
				// Add a visual freeze effect: overlay an ice_block image on top of the enemy for the freeze duration
				if (!e.iceOverlay) {
					e.iceOverlay = e.attachAsset('ice_block', {
						anchorX: 0.5,
						anchorY: 0.5,
						alpha: 0.6
					});
					// Make sure overlay is above the enemy sprite
					e.setChildIndex(e.iceOverlay, e.children.length - 1);
				}
				// Remove overlay when unfrozen (handled in enemy update)
				// If enemy is a Bat, count the hit
				if (e instanceof Bat) {
					batFreezeHitCount++;
					// When 3 hits, freeze all bats for 60 seconds (3600 frames)
					if (batFreezeHitCount >= 3 && !batFreezeActive) {
						batFreezeActive = true;
						batFreezeTimer = 3600;
						for (var k = 0; k < enemies.length; k++) {
							if (enemies[k] instanceof Bat) {
								enemies[k].frozen = true;
								enemies[k].frozenTimer = 3600;
								if (enemies[k].children && enemies[k].children.length > 0) {
									enemies[k].children[0].tint = 0x7fdfff;
								}
								// Add overlay to all bats
								if (!enemies[k].iceOverlay) {
									enemies[k].iceOverlay = enemies[k].attachAsset('ice_block', {
										anchorX: 0.5,
										anchorY: 0.5,
										alpha: 0.6
									});
									enemies[k].setChildIndex(enemies[k].iceOverlay, enemies[k].children.length - 1);
								}
							}
						}
					}
				}
				orb.destroy();
				freezeOrbs.splice(i, 1);
				break;
			}
		}
	}
	// Bat freeze global timer
	if (batFreezeActive) {
		batFreezeTimer--;
		if (batFreezeTimer <= 0) {
			batFreezeActive = false;
			batFreezeHitCount = 0;
			// Unfreeze all bats
			for (var k = 0; k < enemies.length; k++) {
				if (enemies[k] instanceof Bat) {
					enemies[k].frozen = false;
					enemies[k].frozenTimer = 0;
					if (enemies[k].children && enemies[k].children.length > 0) {
						enemies[k].children[0].tint = 0x2a2a2a;
					}
				}
			}
		}
	}
	// Update ice blocks
	for (var i = iceBlocks.length - 1; i >= 0; i--) {
		var block = iceBlocks[i];
		block.update();
		// Collide with enemies
		for (var j = 0; j < enemies.length; j++) {
			var e = enemies[j];
			if (!e.trapped && block.intersects(e)) {
				if (typeof e.trap === "function") {
					e.trap();
				}
				block.destroy();
				iceBlocks.splice(i, 1);
				break;
			}
		}
	}
	// Update enemies
	if (typeof globalEnemyPauseTimer === "undefined") {
		var globalEnemyPauseTimer = 0;
	}
	if (globalEnemyPauseTimer > 0) {
		globalEnemyPauseTimer--;
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			// Only update if enemy is frozen/trapped (so shatter still works), but skip normal update
			if (e.frozen || e.trapped) {
				e.update();
			}
			// Keep pausedBySpeed flag set
			e.pausedBySpeed = true;
			// If frozen or trapped, can be shattered by touching again
			if ((e.frozen || e.trapped) && player && player.intersects(e)) {
				e.shatter();
			}
			// If not frozen/trapped, collision with player
			if (!e.frozen && !e.trapped && player && player.intersects(e)) {
				if (player.shielded) {
					player.loseShield();
					LK.getSound('hit').play();
					LK.effects.flashObject(player, 0x8fffd6, 400);
				} else {
					lives--;
					livesTxt.setText('Lives: ' + lives);
					LK.effects.flashScreen(0x7e4a9c, 900);
					if (lives <= 0) {
						// Save and show best score
						var bestScore = 0;
						if (typeof storage !== "undefined" && typeof storage.get === "function") {
							bestScore = storage.get("bestScore") || 0;
							if (LK.getScore() > bestScore) {
								bestScore = LK.getScore();
								storage.set("bestScore", bestScore);
							}
						}
						// Show best score overlay
						var bestScoreOverlay = new Container();
						var bestScoreText = new Text2("Best Score: " + bestScore, {
							size: 120,
							fill: 0xF6F1C7,
							align: "center"
						});
						bestScoreText.anchor.set(0.5, 0.5);
						bestScoreText.x = 1024;
						bestScoreText.y = 1366;
						bestScoreOverlay.addChild(bestScoreText);
						LK.gui.addChild(bestScoreOverlay);
						// Remove overlay after 2.5 seconds
						LK.setTimeout(function () {
							if (bestScoreOverlay.parent) bestScoreOverlay.parent.removeChild(bestScoreOverlay);
						}, 2500);
						LK.showGameOver();
						return;
					} else {
						// Respawn player at start position
						player.x = 1024;
						player.y = 2732 - 200;
						player.vx = 0;
						player.vy = 0;
						player.loseShield();
					}
				}
			}
		}
		// When timer ends, unpause all enemies
		if (globalEnemyPauseTimer === 0) {
			for (var i = 0; i < enemies.length; i++) {
				enemies[i].pausedBySpeed = false;
			}
		}
	} else {
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			e.update();
			// If frozen or trapped, can be shattered by touching again
			if ((e.frozen || e.trapped) && player && player.intersects(e)) {
				e.shatter();
			}
			// If not frozen/trapped, collision with player
			if (!e.frozen && !e.trapped && player && player.intersects(e)) {
				if (player.shielded) {
					player.loseShield();
					LK.getSound('hit').play();
					LK.effects.flashObject(player, 0x8fffd6, 400);
				} else {
					lives--;
					livesTxt.setText('Lives: ' + lives);
					LK.effects.flashScreen(0x7e4a9c, 900);
					if (lives <= 0) {
						// Save and show best score
						var bestScore = 0;
						if (typeof storage !== "undefined" && typeof storage.get === "function") {
							bestScore = storage.get("bestScore") || 0;
							if (LK.getScore() > bestScore) {
								bestScore = LK.getScore();
								storage.set("bestScore", bestScore);
							}
						}
						// Show best score overlay
						var bestScoreOverlay = new Container();
						var bestScoreText = new Text2("Best Score: " + bestScore, {
							size: 120,
							fill: 0xF6F1C7,
							align: "center"
						});
						bestScoreText.anchor.set(0.5, 0.5);
						bestScoreText.x = 1024;
						bestScoreText.y = 1366;
						bestScoreOverlay.addChild(bestScoreText);
						LK.gui.addChild(bestScoreOverlay);
						// Remove overlay after 2.5 seconds
						LK.setTimeout(function () {
							if (bestScoreOverlay.parent) bestScoreOverlay.parent.removeChild(bestScoreOverlay);
						}, 2500);
						LK.showGameOver();
						return;
					} else {
						// Respawn player at start position
						player.x = 1024;
						player.y = 2732 - 200;
						player.vx = 0;
						player.vy = 0;
						player.loseShield();
					}
				}
			}
		}
	}
	// Update powerups
	for (var i = powerups.length - 1; i >= 0; i--) {
		var p = powerups[i];
		if (player && player.intersects(p)) {
			if (typeof moonCollectCount === "undefined") {
				var moonCollectCount = 0;
			}
			if (p.type === 'moon') {
				moonCollectCount++;
				player.activateFullMoon();
				// Start moon jump timer for 10 seconds (600 frames)
				player.moonJumpTimer = 600;
				LK.setScore(LK.getScore() + 5);
				scoreTxt.setText(LK.getScore());
				currentStageScore = LK.getScore();
				currentStageScore = LK.getScore();
				currentStageScore = LK.getScore();
				// (Lightning effect removed when collecting moon)
				// --- FreezeOrb grow effect: 3x size for 5 seconds ---
				if (typeof freezeOrbGrowTimer === "undefined") {
					var freezeOrbGrowTimer = 0;
				}
				freezeOrbGrowTimer = 300; // 5 seconds at 60fps
				// Spawn a new moon at a random position
				var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
				game.addChild(moon);
				powerups.push(moon);
				// If 5 moons collected, spawn a random shield and reset counter
				if (typeof lastMoonShieldGiven === "undefined") {
					var lastMoonShieldGiven = 0;
				}
				if (moonCollectCount >= 5) {
					moonCollectCount = 0;
					// Only give one shield per 5 moons, and only if less than 3 shields this stage
					var shieldCount = 0;
					for (var i = 0; i < powerups.length; i++) {
						if (powerups[i].type === 'shield') shieldCount++;
					}
					if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
					if (shieldCount < 3 && game.shieldsThisStage < 3 && lastMoonShieldGiven !== LK.getScore()) {
						var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
						game.addChild(shield);
						powerups.push(shield);
						game.shieldsThisStage++;
						lastMoonShieldGiven = LK.getScore();
					}
				}
				// If 100 moons collected, spawn a shield (only once per 100 moons)
				if (typeof lastHundredMoonShieldGiven === "undefined") {
					var lastHundredMoonShieldGiven = 0;
				}
				if (moonCollectCountTotal === undefined) {
					var moonCollectCountTotal = 0;
				}
				moonCollectCountTotal++;
				if (moonCollectCountTotal > 0 && moonCollectCountTotal % 100 === 0 && lastHundredMoonShieldGiven !== moonCollectCountTotal) {
					// Only spawn if less than 3 shields this stage
					var shieldCount = 0;
					for (var i = 0; i < powerups.length; i++) {
						if (powerups[i].type === 'shield') shieldCount++;
					}
					if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
					if (shieldCount < 3 && game.shieldsThisStage < 3) {
						var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
						game.addChild(shield);
						powerups.push(shield);
						game.shieldsThisStage++;
						lastHundredMoonShieldGiven = moonCollectCountTotal;
					}
				}
			} else if (p.type === 'shield') {
				player.gainShield();
				// Send ice orbs in all directions
				var orbCount = 12;
				for (var d = 0; d < orbCount; d++) {
					var angle = 2 * Math.PI * d / orbCount;
					var dirX = Math.cos(angle);
					var orb = new FreezeOrb(player.x, player.y - 60, dirX);
					// Give each orb a custom vx/vy for radial spread
					orb.vx = 24 * Math.cos(angle);
					orb.vy = 24 * Math.sin(angle);
					// Override update to move in both x and y
					(function (orb) {
						var baseUpdate = orb.update;
						orb.update = function () {
							orb.x += orb.vx;
							orb.y += orb.vy;
							orb.lifetime--;
							// Wrap horizontally
							if (orb.x < 0) orb.x = 2048;
							if (orb.x > 2048) orb.x = 0;
							// Remove if out of bounds vertically
							if (orb.y < 0 || orb.y > 2732 || orb.lifetime <= 0) {
								orb.destroy();
								var idx = freezeOrbs.indexOf(orb);
								if (idx >= 0) freezeOrbs.splice(idx, 1);
								return;
							}
						};
					})(orb);
					game.addChild(orb);
					freezeOrbs.push(orb);
				}
			} else if (p.type === 'speed') {
				player.gainSpeed();
				player.speedBoost = 240; // Speed lasts 4 seconds (60fps*4)
				// Only freeze all enemies for 10 seconds if not already frozen by speed
				if (typeof globalEnemyPauseTimer === "undefined") {
					var globalEnemyPauseTimer = 0;
				}
				if (globalEnemyPauseTimer <= 0) {
					globalEnemyPauseTimer = 600; // 10 seconds at 60fps
					for (var ep = 0; ep < enemies.length; ep++) {
						enemies[ep].pausedBySpeed = true;
					}
				}
			} else if (p.type === 'lifepotion') {
				lives++;
				livesTxt.setText('Lives: ' + lives);
				LK.effects.flashObject(player, 0x8fffd6, 400);
			} else if (p.type === 'broom') {
				// Witch can now fly for 20 seconds (1200 frames)
				player.canFly = true;
				player.flyTimer = 1200;
				LK.effects.flashObject(player, 0xb8e6ff, 600);
			} else if (p.type === 'yu') {
				// Cancel speed power when witch takes the yu
				player.speedBoost = 0;
				// Enable double jump for the player
				player.yuDoubleJump = true;
				player.hasDoubleJumped = false;
				// Remove speed pause from all enemies
				if (typeof globalEnemyPauseTimer !== "undefined") {
					globalEnemyPauseTimer = 0;
					for (var ep = 0; ep < enemies.length; ep++) {
						enemies[ep].pausedBySpeed = false;
					}
				}
				// Prevent shooting for 2 seconds (120 frames)
				player.canShoot = false;
				player.shootCooldown = 120;
			}
			LK.getSound('powerup').play();
			p.destroy();
			powerups.splice(i, 1);
		}
	}
	// Full moon: allow trap spell by tap with two fingers (simulate by double tap)
	if (player && player.fullMoon && LK.ticks % 60 === 0) {
		// For MVP, allow trap spell every second in full moon
		player.castTrap();
	}
	// Stage clear
	if (!stageCleared && enemies.length === 0) {
		stageCleared = true;
		stageTimer = 90;
		LK.effects.flashScreen(0xb8e6ff, 600);
	}
	if (stageCleared) {
		stageTimer--;
		if (stageTimer <= 0) {
			stage++;
			if (stage % 5 === 0) {
				// Boss stage: show Boss asset and spawn extra enemies
				stageTxt.setText('Boss Stage!');
				// Spawn Boss at center as a moving enemy
				var boss = new Boss(1024, 900);
				game.addChild(boss);
				enemies.push(boss);
				for (var i = 0; i < 3; i++) {
					var px = 200 + Math.random() * (2048 - 400);
					var py = 400 + Math.random() * 1200;
					var g = new Ghost(px, py);
					game.addChild(g);
					enemies.push(g);
				}
				for (var i = 0; i < 2; i++) {
					var px = 200 + Math.random() * (2048 - 400);
					var py = 300 + Math.random() * 1000;
					var b = new Bat(px, py);
					game.addChild(b);
					enemies.push(b);
				}
				stageCleared = false;
			} else {
				startStage();
			}
		}
	}
};
LK.playMusic('gothic_theme', {
	fade: {
		start: 0,
		end: 1,
		duration: 1200
	}
});
// Play music /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
// Enemy: Bat
var Bat = Container.expand(function (x, y) {
	var self = Container.call(this);
	var bat = self.attachAsset('bat', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (2.5 + Math.random() * 2); // Slower bats
	self.vy = (Math.random() > 0.5 ? 1 : -1) * 0.5; // Slower vertical movement
	self.frozen = false;
	self.frozenTimer = 0;
	self.trapped = false;
	self.trapTimer = 0;
	self.update = function () {
		// Pause logic for speed powerup
		if (self.pausedBySpeed) {
			return;
		}
		if (self.trapped) {
			self.trapTimer--;
			if (self.trapTimer <= 0) {
				self.trapped = false;
				self.alpha = 1;
			}
			return;
		}
		if (self.frozen) {
			self.frozenTimer--;
			if (self.frozenTimer <= 0) {
				self.frozen = false;
				bat.tint = 0x2a2a2a;
				// Remove freeze overlay if present
				if (self.iceOverlay) {
					self.removeChild(self.iceOverlay);
					self.iceOverlay = null;
				}
			}
			return;
		}
		self.x += self.vx;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		if (self.y < 200 || self.y > 2732 - 200) self.vy *= -1;
		// Prevent bats from touching platforms: bounce off if intersecting
		for (var i = 0; i < platforms.length; i++) {
			var p = platforms[i];
			if (self.intersects(p)) {
				// Bounce bat away from platform
				// Determine if bat is coming from above/below or left/right
				var dx = self.x - p.x;
				var dy = self.y - p.y;
				if (Math.abs(dx) > Math.abs(dy)) {
					// Bounce horizontally
					self.vx *= -1;
					// Move bat out of platform horizontally
					if (dx > 0) {
						self.x = p.x + p.width / 2 + 40;
					} else {
						self.x = p.x - p.width / 2 - 40;
					}
				} else {
					// Bounce vertically
					self.vy *= -1;
					// Move bat out of platform vertically
					if (dy > 0) {
						self.y = p.y + p.height / 2 + 40;
					} else {
						self.y = p.y - p.height / 2 - 40;
					}
				}
			}
		}
	};
	// Freeze effect
	self.freeze = function () {
		self.frozen = true;
		self.frozenTimer = 180;
		bat.tint = 0x7fdfff;
	};
	// Trap effect
	self.trap = function () {
		self.trapped = true;
		self.trapTimer = 90;
		self.alpha = 0.4;
	};
	// Shatter (destroy)
	self.shatter = function () {
		LK.getSound('shatter').play();
		self.destroy();
		var idx = enemies.indexOf(self);
		if (idx >= 0) enemies.splice(idx, 1);
		LK.setScore(LK.getScore() + 1);
		scoreTxt.setText(LK.getScore());
	};
	return self;
});
// Boss: Moves randomly
var Boss = Container.expand(function (x, y) {
	var self = Container.call(this);
	var boss = self.attachAsset('Boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = 0;
	self.vy = 0;
	self.randomMoveTimer = 60 + Math.floor(Math.random() * 60);
	self.lastX = self.x;
	self.lastY = self.y;
	self.update = function () {
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			var speed = 6 + Math.random() * 4;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.7;
			self.randomMoveTimer = 60 + Math.floor(Math.random() * 60);
		}
		self.lastX = self.x;
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 400 && self.y < 2732 - 400) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 400) self.y = 2732 - 400;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Power-up: Broom
var BroomPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var broom = self.attachAsset('Broom', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'broom';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Evanasense (player) class
var Evanasense = Container.expand(function () {
	var self = Container.call(this);
	// Body
	var body = self.attachAsset('evana', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Hat
	var hat = self.attachAsset('evana_hat', {
		anchorX: 0.5,
		anchorY: 1.1,
		y: -60
	});
	// Physics
	self.vx = 0;
	self.vy = 0;
	self.lastY = 0;
	self.isOnGround = false;
	self.facing = 1; // 1: right, -1: left
	self.canShoot = true;
	self.shootCooldown = 0;
	self.shielded = false;
	self.speedBoost = 0;
	self.fullMoon = false;
	self.fullMoonTimer = 0;
	self.canFly = false;
	self.flyTimer = 0;
	// For power-up visuals
	self.shieldSprite = null;
	// Freeze spell
	self.castFreeze = function () {
		if (!self.canShoot) return;
		self.canShoot = false;
		self.shootCooldown = 30; // 0.5s cooldown
		var orb = new FreezeOrb(self.x, self.y - 60, self.facing);
		game.addChild(orb);
		freezeOrbs.push(orb);
		LK.getSound('freeze').play();
	};
	// Trap spell (ice block, only in full moon mode)
	self.castTrap = function () {
		if (!self.fullMoon) return;
		var trap = new IceBlock(self.x + 100 * self.facing, self.y - 40);
		game.addChild(trap);
		iceBlocks.push(trap);
		LK.getSound('trap').play();
	};
	// Power-up: Shield
	self.gainShield = function () {
		self.shielded = true;
		if (!self.shieldSprite) {
			self.shieldSprite = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
		}
		self.shieldSprite.visible = true;
	};
	self.loseShield = function () {
		self.shielded = false;
		if (self.shieldSprite) self.shieldSprite.visible = false;
	};
	// Power-up: Speed
	self.gainSpeed = function () {
		self.speedBoost = 180;
		LK.effects.flashObject(self, 0xffe066, 400);
	};
	// Power-up: Full Moon
	self.activateFullMoon = function () {
		self.fullMoon = true;
		self.fullMoonTimer = 360; // 6 seconds
		LK.effects.flashObject(self, 0xf6f1c7, 600);
	};
	// Update
	self.update = function () {
		// Flying logic
		if (self.canFly) {
			// While flying, allow free vertical movement with up/down, and reduce gravity
			if (upPressed) {
				self.vy = -18;
			} else if (downPressed) {
				self.vy = 18;
			} else {
				self.vy *= 0.7;
				if (Math.abs(self.vy) < 1) self.vy = 0;
			}
			// Optional: add a little gravity so she floats down if not pressing up
			self.vy += 0.5;
			if (self.vy > 24) self.vy = 24;
			if (self.vy < -24) self.vy = -24;
			// Flying timer
			if (typeof self.flyTimer === "undefined") self.flyTimer = 600;
			self.flyTimer--;
			if (self.flyTimer <= 0) {
				self.canFly = false;
				self.flyTimer = 0;
			}
		} else {
			// Gravity
			self.vy += 2.2;
			if (self.vy > 40) self.vy = 40;
		}
		// Set moveDir for left/right, and moveVert for up/down (support diagonals)
		self.moveDir = 0;
		self.moveVert = 0;
		if (leftPressed && !rightPressed) {
			self.moveDir = -1;
		} else if (rightPressed && !leftPressed) {
			self.moveDir = 1;
		}
		if (upPressed && !downPressed) {
			self.moveVert = -1;
		} else if (downPressed && !upPressed) {
			self.moveVert = 1;
		}
		// If both a horizontal and vertical direction are pressed, normalize diagonal speed
		if (self.moveDir !== 0 && self.moveVert !== 0) {
			// Reduce speed for diagonal movement to keep consistent velocity
			self.moveDir *= Math.SQRT1_2;
			self.moveVert *= Math.SQRT1_2;
		}
		// --- Up/Down button logic (for future use, e.g. drop through platforms) ---
		// (Handled above for movement)
		// --- Fire button logic ---
		if (firePressed && self.canShoot) {
			self.castFreeze();
			firePressed = false; // Only fire once per press
		}
		// Movement
		var moveSpeed = 18 + (self.speedBoost > 0 ? 10 : 0);
		if (self.moveDir || self.moveVert) {
			self.vx = moveSpeed * self.moveDir;
			self.vy = self.canFly ? moveSpeed * self.moveVert : self.vy;
			if (self.moveDir) self.facing = self.moveDir > 0 ? 1 : -1;
		} else {
			self.vx *= 0.7;
			if (Math.abs(self.vx) < 1) self.vx = 0;
			if (!self.canFly) {
				// Only apply gravity if not flying
				// (already handled above)
			}
		}
		// Apply position
		self.lastY = self.y;
		// --- Mario-style jump: allow jump if jumpPressed and isOnGround ---
		// Double jump support: allow one extra jump if yuDoubleJump is true
		if (typeof self.yuDoubleJump === "undefined") self.yuDoubleJump = false;
		if (typeof self.hasDoubleJumped === "undefined") self.hasDoubleJumped = false;
		if (jumpPressed) {
			var jumpPower = -38;
			if (self.moonJumpTimer && self.moonJumpTimer > 0) {
				jumpPower = -54; // Higher jump during moon effect
			}
			if (self.isOnGround) {
				self.vy = jumpPower;
				self.isOnGround = false;
				self.hasDoubleJumped = false;
			} else if (self.yuDoubleJump && !self.hasDoubleJumped) {
				self.vy = jumpPower;
				self.hasDoubleJumped = true;
				// Optional: flash effect for double jump
				LK.effects.flashObject(self, 0xb8e6ff, 200);
			}
		}
		if (self.moonJumpTimer && self.moonJumpTimer > 0) {
			self.moonJumpTimer--;
			if (self.moonJumpTimer === 0) {
				// Optionally, add a visual effect to show moon jump ended
				LK.effects.flashObject(self, 0xf6f1c7, 200);
			}
		}
		self.x += self.vx;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Clamp vertically and collide with all platforms
		self.isOnGround = false;
		var prevBottom = self.lastY + body.height / 2;
		var currBottom = self.y + body.height / 2;
		for (var i = 0; i < platforms.length; i++) {
			var plat = platforms[i];
			var platTop = plat.y - plat.height / 2;
			// Allow drop through platforms if downPressed, except for the floor (y >= 2732-60)
			var isFloor = plat.y >= 2732 - 60;
			if (self.vy > 0 && prevBottom <= platTop && currBottom >= platTop && self.x + body.width / 2 > plat.x - plat.width / 2 && self.x - body.width / 2 < plat.x + plat.width / 2 && (!downPressed || isFloor)) {
				self.y = platTop - body.height / 2;
				self.vy = 0;
				self.isOnGround = true;
				// Play platform sound when landing
				if (typeof self.lastWasOnGround === "undefined") self.lastWasOnGround = false;
				// (platform sound removed as requested)
				self.lastWasOnGround = true;
			} else {
				if (typeof self.lastWasOnGround === "undefined") self.lastWasOnGround = false;
				self.lastWasOnGround = false;
			}
		}
		// Clamp to bottom of screen
		if (self.y > 2732 - 60) {
			self.y = 2732 - 60;
			self.vy = 0;
			self.isOnGround = true;
		}
		// Shooting cooldown
		if (!self.canShoot) {
			self.shootCooldown--;
			if (self.shootCooldown <= 0) {
				self.canShoot = true;
			}
		}
		// Speed boost timer
		if (self.speedBoost > 0) {
			self.speedBoost--;
		}
		// Full moon timer
		if (self.fullMoon) {
			self.fullMoonTimer--;
			if (self.fullMoonTimer <= 0) {
				self.fullMoon = false;
			}
		}
	};
	return self;
});
// Freeze orb spell
var FreezeOrb = Container.expand(function (x, y, dir) {
	var self = Container.call(this);
	var orb = self.attachAsset('freeze_orb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.vx = 32 * dir;
	self.lifetime = 60;
	self.update = function () {
		self.x += self.vx;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		self.lifetime--;
		if (self.lifetime <= 0) {
			self.destroy();
			var idx = freezeOrbs.indexOf(self);
			if (idx >= 0) freezeOrbs.splice(idx, 1);
		}
	};
	return self;
});
// Enemy: Ghost
var Ghost = Container.expand(function (x, y) {
	var self = Container.call(this);
	var ghost = self.attachAsset('ghost', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.85
	});
	self.x = x;
	self.y = y;
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (3 + Math.random() * 2); // Slower ghosts
	self.vy = (Math.random() - 0.5) * 2; // Add a little vertical movement
	self.frozen = false;
	self.frozenTimer = 0;
	self.trapped = false;
	self.trapTimer = 0;
	self.randomMoveTimer = 30 + Math.floor(Math.random() * 60); // How many frames until next direction change
	self.lastY = self.y;
	self.update = function () {
		// Pause logic for speed powerup
		if (self.pausedBySpeed) {
			return;
		}
		if (self.trapped) {
			self.trapTimer--;
			if (self.trapTimer <= 0) {
				self.trapped = false;
				self.alpha = 0.85;
			}
			return;
		}
		if (self.frozen) {
			self.frozenTimer--;
			if (self.frozenTimer <= 0) {
				self.frozen = false;
				ghost.tint = 0xcfd6e6;
				// Remove freeze overlay if present
				if (self.iceOverlay) {
					self.removeChild(self.iceOverlay);
					self.iceOverlay = null;
				}
			}
			return;
		}
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			// Change direction randomly
			var speed = 3 + Math.random() * 2;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.5; // Less vertical movement
			self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
		}
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	// Freeze effect
	self.freeze = function () {
		self.frozen = true;
		self.frozenTimer = 180;
		ghost.tint = 0x7fdfff;
	};
	// Trap effect
	self.trap = function () {
		self.trapped = true;
		self.trapTimer = 90;
		self.alpha = 0.4;
	};
	// Shatter (destroy)
	self.shatter = function () {
		LK.getSound('shatter').play();
		self.destroy();
		var idx = enemies.indexOf(self);
		if (idx >= 0) enemies.splice(idx, 1);
		LK.setScore(LK.getScore() + 1);
		scoreTxt.setText(LK.getScore());
	};
	return self;
});
// Ice block trap (full moon mode)
var IceBlock = Container.expand(function (x, y) {
	var self = Container.call(this);
	var block = self.attachAsset('ice_block', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.85
	});
	self.x = x;
	self.y = y;
	self.lifetime = 120;
	self.update = function () {
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		self.lifetime--;
		if (self.lifetime <= 0) {
			self.destroy();
			var idx = iceBlocks.indexOf(self);
			if (idx >= 0) iceBlocks.splice(idx, 1);
		}
	};
	return self;
});
// Power-up: Lifepotion (adds a life)
var LifepotionPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var potion = self.attachAsset('Lifepotion', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'lifepotion';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Power-up: Moon (full moon mode)
var MoonPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var moon = self.attachAsset('moon', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'moon';
	self.vx = 3 + Math.random() * 2; // Slower moon movement
	self.lastX = self.x;
	self.update = function () {
		self.lastX = self.x;
		self.x += self.vx;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Platform
var Platform = Container.expand(function (x, y, w) {
	var self = Container.call(this);
	var plat = self.attachAsset('platform', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: w || 320
	});
	self.x = x;
	self.y = y;
	self.width = w || 320;
	self.height = 40;
	return self;
});
// Power-up: Shield
var ShieldPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var shield = self.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'shield';
	self.update = function () {
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
// Power-up: Speed
var SpeedPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var speed = self.attachAsset('speed', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'speed';
	self.vy = 7 + Math.random() * 3;
	self.lastY = self.y;
	self.update = function () {
		self.lastY = self.y;
		self.y += self.vy;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
		// Bounce at vertical edges
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
	};
	return self;
});
// Power-up: Yu (moves randomly)
var YuPower = Container.expand(function (x, y) {
	var self = Container.call(this);
	var yu = self.attachAsset('Yu', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.x = x;
	self.y = y;
	self.type = 'yu';
	// Random movement variables
	self.vx = (Math.random() > 0.5 ? 1 : -1) * (3 + Math.random() * 2);
	self.vy = (Math.random() - 0.5) * 2;
	self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
	self.lastY = self.y;
	self.update = function () {
		// Random movement logic
		self.randomMoveTimer--;
		if (self.randomMoveTimer <= 0) {
			var speed = 3 + Math.random() * 2;
			var angle = Math.random() * Math.PI * 2;
			self.vx = Math.cos(angle) * speed;
			self.vy = Math.sin(angle) * speed * 0.5;
			self.randomMoveTimer = 30 + Math.floor(Math.random() * 60);
		}
		self.lastY = self.y;
		self.x += self.vx;
		self.y += self.vy;
		// Bounce vertically at top/bottom bounds
		if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
			self.vy *= -1;
		}
		if (self.y < 200) self.y = 200;
		if (self.y > 2732 - 200) self.y = 2732 - 200;
		// Snow Bros style: wrap horizontally
		if (self.x < 0) self.x = 2048;
		if (self.x > 2048) self.x = 0;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x18141e
});
/**** 
* Game Code
****/ 
// Add background image
// Add background image
var bg = LK.getAsset('bg', {
	anchorX: 0,
	anchorY: 0,
	width: 2048,
	height: 2732,
	x: 0,
	y: 0
});
game.addChild(bg);
// (rulesPanel removed as per request)
// --- Game Start Overlay ---
var startOverlay = new Container();
var rulesText = new Text2("🧙♀️ Witch's Night: Game Rules\n\n" + "- Move the witch with the blue buttons.\n" + "- Tap the yellow button to cast freeze spells.\n" + "- Collect powerups: Moon (full moon mode), Shield, Speed, Life Potion, Broom (fly!), Yu (cancel speed).\n" + "- Avoid ghosts and bats! Touching them loses a life unless shielded.\n" + "- Freeze or trap enemies, then touch them again to shatter.\n" + "- Clear all enemies to advance to the next stage.\n" + "- Survive as long as you can!\n\n" + "Good luck! Tap Start to play.", {
	size: 70,
	fill: 0xF6F1C7,
	align: "center",
	wordWrap: true,
	wordWrapWidth: 1600
});
rulesText.anchor.set(0.5, 0.5);
rulesText.x = 1024;
rulesText.y = 900;
startOverlay.addChild(rulesText);
var startBtn = new Text2("START", {
	size: 180,
	fill: 0xB8E6FF,
	fontWeight: "bold"
});
startBtn.anchor.set(0.5, 0.5);
startBtn.x = 1024;
startBtn.y = 1800;
startOverlay.addChild(startBtn);
// Block gameplay until start is pressed
game.paused = true;
// Add start overlay to the very front so it appears above everything
LK.gui.addChild(startOverlay);
// Hide overlay and start game on button press
startBtn.down = function () {
	if (startOverlay.parent) startOverlay.parent.removeChild(startOverlay);
	game.paused = false;
};
// Main character: Evanasense (witch)
// Witch body
// Witch hat
// Enemy: Ghost
// Enemy: Bat
// Platform
// Spell: Freeze orb
// Spell: Trap (ice block)
// Power-up: Moon
// Power-up: Shield
// Power-up: Speed
// Sound effects
// Music
// --- Classic D-pad controls (eight buttons, with diagonals) ---
// D-pad button size and spacing (increased for better touch usability)
var dpadBtnSize = 260;
var dpadSpacing = 50;
// Move D-pad higher by decreasing dpadY (more negative = higher on screen)
var dpadY = -420;
var dpadX = 360;
// Diagonal offset (for diagonal buttons)
var diagOffset = Math.round((dpadBtnSize + dpadSpacing) * 0.7);
// Helper: reset all direction states (for compatibility)
function resetButtonDirections() {
	leftPressed = false;
	rightPressed = false;
	upPressed = false;
	downPressed = false;
	// Also clear jumpPressed for diagonals
	jumpPressed = false;
}
// Left button
var leftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - dpadBtnSize - dpadSpacing,
	y: dpadY,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(leftBtn);
var leftArrow = new Text2("◀", {
	size: 180,
	fill: 0x222244
});
leftArrow.anchor.set(0.5, 0.5);
leftArrow.x = leftBtn.x;
leftArrow.y = leftBtn.y;
LK.gui.bottomLeft.addChild(leftArrow);
// Right button
var rightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + dpadBtnSize + dpadSpacing,
	y: dpadY,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(rightBtn);
var rightArrow = new Text2("▶", {
	size: 180,
	fill: 0x222244
});
rightArrow.anchor.set(0.5, 0.5);
rightArrow.x = rightBtn.x;
rightArrow.y = rightBtn.y;
LK.gui.bottomLeft.addChild(rightArrow);
// Up button
var upBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX,
	y: dpadY - dpadBtnSize - dpadSpacing,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upBtn);
var upArrow = new Text2("▲", {
	size: 180,
	fill: 0x222244
});
upArrow.anchor.set(0.5, 0.5);
upArrow.x = upBtn.x;
upArrow.y = upBtn.y;
LK.gui.bottomLeft.addChild(upArrow);
// Down button
var downBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX,
	y: dpadY + dpadBtnSize + dpadSpacing,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downBtn);
var downArrow = new Text2("▼", {
	size: 180,
	fill: 0x222244
});
downArrow.anchor.set(0.5, 0.5);
downArrow.x = downBtn.x;
downArrow.y = downBtn.y;
LK.gui.bottomLeft.addChild(downArrow);
// Up-Left button
var upLeftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - diagOffset,
	y: dpadY - diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upLeftBtn);
var upLeftArrow = new Text2("◤", {
	size: 180,
	fill: 0x222244
});
upLeftArrow.anchor.set(0.5, 0.5);
upLeftArrow.x = upLeftBtn.x;
upLeftArrow.y = upLeftBtn.y;
LK.gui.bottomLeft.addChild(upLeftArrow);
// Up-Right button
var upRightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + diagOffset,
	y: dpadY - diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(upRightBtn);
var upRightArrow = new Text2("◥", {
	size: 180,
	fill: 0x222244
});
upRightArrow.anchor.set(0.5, 0.5);
upRightArrow.x = upRightBtn.x;
upRightArrow.y = upRightBtn.y;
LK.gui.bottomLeft.addChild(upRightArrow);
// Down-Left button
var downLeftBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX - diagOffset,
	y: dpadY + diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downLeftBtn);
var downLeftArrow = new Text2("◣", {
	size: 180,
	fill: 0x222244
});
downLeftArrow.anchor.set(0.5, 0.5);
downLeftArrow.x = downLeftBtn.x;
downLeftArrow.y = downLeftBtn.y;
LK.gui.bottomLeft.addChild(downLeftArrow);
// Down-Right button
var downRightBtn = LK.getAsset('centerCircle', {
	anchorX: 0.5,
	anchorY: 0.5,
	scaleX: 1.7,
	scaleY: 1.7,
	x: dpadX + diagOffset,
	y: dpadY + diagOffset,
	alpha: 0.45
});
LK.gui.bottomLeft.addChild(downRightBtn);
var downRightArrow = new Text2("◢", {
	size: 180,
	fill: 0x222244
});
downRightArrow.anchor.set(0.5, 0.5);
downRightArrow.x = downRightBtn.x;
downRightArrow.y = downRightBtn.y;
LK.gui.bottomLeft.addChild(downRightArrow);
// (Diagonal D-pad buttons added)
// D-pad button handlers
leftBtn.down = function () {
	if (game.paused) return;
	leftPressed = true;
};
leftBtn.up = function () {
	leftPressed = false;
};
rightBtn.down = function () {
	if (game.paused) return;
	rightPressed = true;
};
rightBtn.up = function () {
	rightPressed = false;
};
upBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	jumpPressed = true;
};
upBtn.up = function () {
	upPressed = false;
	jumpPressed = false;
};
downBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
};
downBtn.up = function () {
	downPressed = false;
};
// Up-Left button handlers
upLeftBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	leftPressed = true;
	jumpPressed = true;
};
upLeftBtn.up = function () {
	upPressed = false;
	leftPressed = false;
	jumpPressed = false;
};
// Up-Right button handlers
upRightBtn.down = function () {
	if (game.paused) return;
	upPressed = true;
	rightPressed = true;
	jumpPressed = true;
};
upRightBtn.up = function () {
	upPressed = false;
	rightPressed = false;
	jumpPressed = false;
};
// Down-Left button handlers
downLeftBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
	leftPressed = true;
};
downLeftBtn.up = function () {
	downPressed = false;
	leftPressed = false;
};
// Down-Right button handlers
downRightBtn.down = function () {
	if (game.paused) return;
	downPressed = true;
	rightPressed = true;
};
downRightBtn.up = function () {
	downPressed = false;
	rightPressed = false;
};
// (Diagonal D-pad button handlers added)
var fireBtn = new Text2('🔥', {
	size: 170,
	fill: 0xF6F1C7
});
fireBtn.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(fireBtn);
fireBtn.x = -500;
fireBtn.y = -220;
// Control state
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
var jumpPressed = false;
var firePressed = false;
// (Diagonal (ara yön) support removed)
// Touch handlers for fire button
fireBtn.down = function (x, y, obj) {
	if (game.paused) return;
	firePressed = true;
	LK.getSound('Fire').play();
};
fireBtn.up = function (x, y, obj) {
	if (game.paused) return;
	firePressed = false;
};
var player;
var platforms = [];
var enemies = [];
var freezeOrbs = [];
var iceBlocks = [];
var powerups = [];
var stage = 1;
var stageCleared = false;
var stageTimer = 0;
var dragNode = null;
var moveStartX = 0;
var moveDir = 0;
var scoreTxt;
// Add lives
var lives = 1;
var livesTxt = new Text2('Lives: ' + lives, {
	size: 70,
	fill: 0xF6F1C7
});
livesTxt.anchor.set(0, 0);
LK.gui.top.addChild(livesTxt);
// Place lives at top left, but not in the 100x100 reserved area
livesTxt.x = 120;
livesTxt.y = 20;
// Score display
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xF6F1C7
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Per-stage score tracking
var stageScores = [];
var currentStageScore = 0;
// Always keep score display updated
if (typeof scoreUpdateTimerId === "undefined") {
	var scoreUpdateTimerId = LK.setInterval(function () {
		if (scoreTxt && typeof LK.getScore === "function") {
			var currentScore = LK.getScore();
			if (scoreTxt.text !== String(currentScore)) {
				scoreTxt.setText(currentScore);
			}
		}
	}, 100);
}
// Stage display
var stageTxt = new Text2('Stage 1', {
	size: 70,
	fill: 0xB8E6FF
});
stageTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(stageTxt);
stageTxt.y = 120;
// Helper: spawn platforms
function spawnPlatforms() {
	// Clear old
	for (var i = 0; i < platforms.length; i++) platforms[i].destroy();
	platforms = [];
	// Floor
	var floor = new Platform(1024, 2732 - 40, 2048);
	game.addChild(floor);
	platforms.push(floor);
	// Snow Bros style: 5-6 fixed rows, wide platforms, even spacing, classic arcade
	var rows = 6;
	var yStart = 2732 - 300;
	var yStep = 320;
	for (var i = 0; i < rows; i++) {
		var y = yStart - i * yStep;
		// Classic: alternate left/right gaps for each row
		if (i % 2 === 0) {
			// Full width platform
			var plat = new Platform(1024, y, 1600);
			game.addChild(plat);
			platforms.push(plat);
		} else {
			// Two half platforms with a gap in the middle
			var leftPlat = new Platform(512, y, 700);
			var rightPlat = new Platform(1536, y, 700);
			game.addChild(leftPlat);
			game.addChild(rightPlat);
			platforms.push(leftPlat);
			platforms.push(rightPlat);
		}
	}
}
// Helper: spawn enemies
function spawnEnemies() {
	for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
	enemies = [];
	var ghostCount = 2 + Math.floor(stage / 2);
	var batCount = 3 + Math.floor(stage / 2); // Increased number of bats for more slow bats
	for (var i = 0; i < ghostCount; i++) {
		var px = 200 + Math.random() * (2048 - 400);
		var py = 400 + Math.random() * 1200;
		var g = new Ghost(px, py);
		// Make ghosts faster in stage 2+
		if (stage >= 2) {
			var speed = (Math.random() > 0.5 ? 1 : -1) * (5 + Math.random() * 2.5);
			var angle = Math.random() * Math.PI * 2;
			g.vx = Math.cos(angle) * speed;
			g.vy = Math.sin(angle) * speed * 0.7;
		}
		game.addChild(g);
		enemies.push(g);
	}
	for (var i = 0; i < batCount; i++) {
		var px = 200 + Math.random() * (2048 - 400);
		var py = 300 + Math.random() * 1000;
		var b = new Bat(px, py);
		// Make bats faster in stage 2+
		if (stage >= 2) {
			b.vx = (Math.random() > 0.5 ? 1 : -1) * (5 + Math.random() * 2.5);
			b.vy = (Math.random() > 0.5 ? 1 : -1) * 1.2;
		}
		game.addChild(b);
		enemies.push(b);
	}
}
// Helper: spawn powerups
function spawnPowerups() {
	for (var i = 0; i < powerups.length; i++) powerups[i].destroy();
	powerups = [];
	// Always one moon per stage
	var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
	game.addChild(moon);
	powerups.push(moon);
	// Limit shields to max 3 per stage
	var shieldsThisStage = 0;
	// 50% chance for shield
	if (Math.random() < 0.5 && shieldsThisStage < 3) {
		var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(shield);
		powerups.push(shield);
		shieldsThisStage++;
	}
	// 50% chance for speed
	if (Math.random() < 0.5) {
		var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(speed);
		powerups.push(speed);
	}
	// Always spawn a lifepotion at the beginning of every stage
	var lifepotion = new LifepotionPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
	game.addChild(lifepotion);
	powerups.push(lifepotion);
	// 40% chance for an extra lifepotion
	if (Math.random() < 0.4) {
		var extraLifepotion = new LifepotionPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(extraLifepotion);
		powerups.push(extraLifepotion);
	}
	// Store shield count for this stage globally for use in other shield spawns
	game.shieldsThisStage = shieldsThisStage;
}
// Start new stage
function startStage() {
	stageCleared = false;
	stageTimer = 0;
	stageTxt.setText('Stage ' + stage);
	// Store previous stage score
	if (typeof currentStageScore !== "undefined" && stage > 1) {
		stageScores[stage - 2] = currentStageScore;
	}
	// Reset score for new stage
	currentStageScore = 0;
	LK.setScore(0);
	scoreTxt.setText('0');
	lives = 7;
	livesTxt.setText('Lives: ' + lives);
	spawnPlatforms();
	spawnEnemies();
	// Reset shield count for this stage before spawning powerups
	game.shieldsThisStage = 0;
	spawnPowerups();
	// Send Yu in stages 2, 3, 4, 5
	if (stage >= 2 && stage <= 5) {
		var yu = new YuPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(yu);
		powerups.push(yu);
	}
	// Place player
	if (player) player.destroy();
	player = new Evanasense();
	player.x = 1024;
	player.y = 2732 - 200;
	game.addChild(player);
}
// Begin first stage
startStage();
// Timer to spawn a random shield every 30 seconds
if (typeof shieldTimerId === "undefined") {
	var shieldTimerId = LK.setInterval(function () {
		// Count current shields on the field
		var shieldCount = 0;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'shield') shieldCount++;
		}
		// Also count shields spawned this stage (if tracked)
		if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
		// Only spawn if less than 3 shields on the field and not more than 3 spawned this stage
		if (shieldCount < 3 && game.shieldsThisStage < 3) {
			var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(shield);
			powerups.push(shield);
			game.shieldsThisStage++;
		}
	}, 30000); // 30,000 ms = 30 seconds
}
// Timer to spawn a speed powerup every 40 seconds, only one at a time
if (typeof speedPowerTimerId === "undefined") {
	var speedPowerTimerId = LK.setInterval(function () {
		// Only spawn if there is no speed powerup currently on the field
		var hasSpeed = false;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'speed') {
				hasSpeed = true;
				break;
			}
		}
		if (!hasSpeed) {
			var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(speed);
			powerups.push(speed);
		}
	}, 40000); // 40,000 ms = 40 seconds
}
// Timer to spawn a broom every 30 seconds
if (typeof broomTimerId === "undefined") {
	var broomTimerId = LK.setInterval(function () {
		// Spawn a broom powerup at a random position
		var broom = new BroomPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
		game.addChild(broom);
		powerups.push(broom);
	}, 30000); // 30,000 ms = 30 seconds
}
// Timer to send 10 Yu powerups, one every 3 seconds, only in stage 2+
if (typeof yuSendCount === "undefined") {
	var yuSendCount = 0;
	var yuSendTimerId = LK.setInterval(function () {
		// Only send Yu if stage >= 2
		if (stage >= 2 && yuSendCount < 10) {
			var yu = new YuPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(yu);
			powerups.push(yu);
			yuSendCount++;
		}
		// Reset yuSendCount if stage changes (so Yu can be sent again in new stage)
		if (typeof lastYuStage === "undefined") {
			var lastYuStage = stage;
		}
		if (stage !== lastYuStage) {
			yuSendCount = 0;
			lastYuStage = stage;
		}
		if (yuSendCount >= 10) {
			// Don't clear interval, just stop sending until next stage
		}
	}, 3000); // 3,000 ms = 3 seconds
}
// Bat flying effect: swap bat/bat2 asset every 1 second
if (typeof batFlyTimerId === "undefined") {
	var batFlyTimerId = LK.setInterval(function () {
		for (var i = 0; i < enemies.length; i++) {
			var e = enemies[i];
			if (e instanceof Bat && e.children && e.children.length > 0) {
				// Find the bat asset (assume it's the first child)
				var batSprite = e.children[0];
				// Swap asset: if bat, change to bat2; if bat2, change to bat
				var currentAssetId = batSprite.assetId || 'bat';
				e.removeChild(batSprite);
				var newAssetId = currentAssetId === 'bat' ? 'bat2' : 'bat';
				var newBat = e.attachAsset(newAssetId, {
					anchorX: 0.5,
					anchorY: 0.5
				});
				// Store which asset is currently used
				newBat.assetId = newAssetId;
				// Move new bat to the front
				e.setChildIndex(newBat, 0);
			}
		}
	}, 1000); // 1000 ms = 1 second
}
// Ghost flying effect: swap ghost/ghost2 asset every 1 second
if (typeof ghostFlyTimerId === "undefined") {
	var ghostFlyTimerId = LK.setInterval(function () {
		for (var i = 0; i < enemies.length; i++) {
			var e = enemies[i];
			if (e instanceof Ghost && e.children && e.children.length > 0) {
				// Find the ghost asset (assume it's the first child)
				var ghostSprite = e.children[0];
				// Swap asset: if ghost, change to ghost2; if ghost2, change to ghost
				var currentAssetId = ghostSprite.assetId || 'ghost';
				e.removeChild(ghostSprite);
				var newAssetId = currentAssetId === 'ghost' ? 'Ghost2' : 'ghost';
				var newGhost = e.attachAsset(newAssetId, {
					anchorX: 0.5,
					anchorY: 0.5,
					alpha: 0.85
				});
				// Store which asset is currently used
				newGhost.assetId = newAssetId;
				// Move new ghost to the front
				e.setChildIndex(newGhost, 0);
			}
		}
	}, 1000); // 1000 ms = 1 second
}
// Add portals to the game
var portal1 = new Container();
var portal1Sprite = portal1.attachAsset('Portal1', {
	anchorX: 0.5,
	anchorY: 0.5
});
portal1.x = 400;
portal1.y = 400;
game.addChild(portal1);
var portal2 = new Container();
var portal2Sprite = portal2.attachAsset('Portal2', {
	anchorX: 0.5,
	anchorY: 0.5
});
portal2.x = 1600;
portal2.y = 2000;
game.addChild(portal2);
// Track last intersection state for portal1
var lastPortal1Intersecting = false;
// Main update loop
game.update = function () {
	// Pause all gameplay and input until start is pressed
	if (game.paused) return;
	// (Removed shield spawn every 25 points logic)
	// --- Shield spawn every 25 points, only once per threshold ---
	if (typeof lastShieldScore === "undefined") {
		var lastShieldScore = 0;
	}
	var currentScore = LK.getScore();
	if (currentScore > 0 && currentScore % 25 === 0 && lastShieldScore !== currentScore) {
		// Only spawn one shield per threshold, and only if less than 3 shields this stage
		var shieldCount = 0;
		for (var i = 0; i < powerups.length; i++) {
			if (powerups[i].type === 'shield') shieldCount++;
		}
		if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
		if (shieldCount < 3 && game.shieldsThisStage < 3) {
			var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
			game.addChild(shield);
			powerups.push(shield);
			game.shieldsThisStage++;
		}
		lastShieldScore = currentScore;
	}
	if (currentScore % 25 !== 0) {
		// Reset so next threshold can trigger
		lastShieldScore = 0;
	}
	// Update player
	if (player) player.update();
	// Portal teleport logic
	if (player && portal1 && portal2) {
		// Portal1 -> Portal2
		var isIntersecting1 = player.intersects(portal1);
		if (!lastPortal1Intersecting && isIntersecting1) {
			// Teleport player to portal2's position
			player.x = portal2.x;
			player.y = portal2.y;
			// Optional: flash effect to show teleport
			LK.effects.flashObject(player, 0xb8e6ff, 300);
		}
		lastPortal1Intersecting = isIntersecting1;
		// Portal2 -> Portal1
		if (typeof lastPortal2Intersecting === "undefined") {
			var lastPortal2Intersecting = false;
		}
		var isIntersecting2 = player.intersects(portal2);
		if (!lastPortal2Intersecting && isIntersecting2) {
			// Teleport player to portal1's position
			player.x = portal1.x;
			player.y = portal1.y;
			// Optional: flash effect to show teleport
			LK.effects.flashObject(player, 0xb8e6ff, 300);
		}
		lastPortal2Intersecting = isIntersecting2;
	}
	// Track ice orb hits for bat freeze mechanic
	if (typeof batFreezeHitCount === "undefined") {
		var batFreezeHitCount = 0;
		var batFreezeActive = false;
		var batFreezeTimer = 0;
	}
	// --- FreezeOrb grow effect: 3x size for 5 seconds after moon ---
	if (typeof freezeOrbGrowTimer === "undefined") {
		var freezeOrbGrowTimer = 0;
	}
	if (freezeOrbGrowTimer > 0) {
		freezeOrbGrowTimer--;
		for (var i = 0; i < freezeOrbs.length; i++) {
			var orb = freezeOrbs[i];
			if (!orb._grew) {
				if (orb.children && orb.children.length > 0) {
					var sprite = orb.children[0];
					sprite.scaleX = 3;
					sprite.scaleY = 3;
					orb._grew = true;
				}
			}
		}
	} else {
		for (var i = 0; i < freezeOrbs.length; i++) {
			var orb = freezeOrbs[i];
			if (orb._grew && orb.children && orb.children.length > 0) {
				var sprite = orb.children[0];
				sprite.scaleX = 1;
				sprite.scaleY = 1;
				orb._grew = false;
			}
		}
	}
	// Update freeze orbs
	for (var i = freezeOrbs.length - 1; i >= 0; i--) {
		var orb = freezeOrbs[i];
		orb.update();
		// Collide with enemies
		for (var j = 0; j < enemies.length; j++) {
			var e = enemies[j];
			if (!e.frozen && !e.trapped && orb.intersects(e)) {
				// --- Freeze effect for all enemies hit by freeze_orb ---
				if (typeof e.freeze === "function") {
					e.freeze();
					LK.getSound('hit').play();
				}
				// Add a visual freeze effect: overlay an ice_block image on top of the enemy for the freeze duration
				if (!e.iceOverlay) {
					e.iceOverlay = e.attachAsset('ice_block', {
						anchorX: 0.5,
						anchorY: 0.5,
						alpha: 0.6
					});
					// Make sure overlay is above the enemy sprite
					e.setChildIndex(e.iceOverlay, e.children.length - 1);
				}
				// Remove overlay when unfrozen (handled in enemy update)
				// If enemy is a Bat, count the hit
				if (e instanceof Bat) {
					batFreezeHitCount++;
					// When 3 hits, freeze all bats for 60 seconds (3600 frames)
					if (batFreezeHitCount >= 3 && !batFreezeActive) {
						batFreezeActive = true;
						batFreezeTimer = 3600;
						for (var k = 0; k < enemies.length; k++) {
							if (enemies[k] instanceof Bat) {
								enemies[k].frozen = true;
								enemies[k].frozenTimer = 3600;
								if (enemies[k].children && enemies[k].children.length > 0) {
									enemies[k].children[0].tint = 0x7fdfff;
								}
								// Add overlay to all bats
								if (!enemies[k].iceOverlay) {
									enemies[k].iceOverlay = enemies[k].attachAsset('ice_block', {
										anchorX: 0.5,
										anchorY: 0.5,
										alpha: 0.6
									});
									enemies[k].setChildIndex(enemies[k].iceOverlay, enemies[k].children.length - 1);
								}
							}
						}
					}
				}
				orb.destroy();
				freezeOrbs.splice(i, 1);
				break;
			}
		}
	}
	// Bat freeze global timer
	if (batFreezeActive) {
		batFreezeTimer--;
		if (batFreezeTimer <= 0) {
			batFreezeActive = false;
			batFreezeHitCount = 0;
			// Unfreeze all bats
			for (var k = 0; k < enemies.length; k++) {
				if (enemies[k] instanceof Bat) {
					enemies[k].frozen = false;
					enemies[k].frozenTimer = 0;
					if (enemies[k].children && enemies[k].children.length > 0) {
						enemies[k].children[0].tint = 0x2a2a2a;
					}
				}
			}
		}
	}
	// Update ice blocks
	for (var i = iceBlocks.length - 1; i >= 0; i--) {
		var block = iceBlocks[i];
		block.update();
		// Collide with enemies
		for (var j = 0; j < enemies.length; j++) {
			var e = enemies[j];
			if (!e.trapped && block.intersects(e)) {
				if (typeof e.trap === "function") {
					e.trap();
				}
				block.destroy();
				iceBlocks.splice(i, 1);
				break;
			}
		}
	}
	// Update enemies
	if (typeof globalEnemyPauseTimer === "undefined") {
		var globalEnemyPauseTimer = 0;
	}
	if (globalEnemyPauseTimer > 0) {
		globalEnemyPauseTimer--;
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			// Only update if enemy is frozen/trapped (so shatter still works), but skip normal update
			if (e.frozen || e.trapped) {
				e.update();
			}
			// Keep pausedBySpeed flag set
			e.pausedBySpeed = true;
			// If frozen or trapped, can be shattered by touching again
			if ((e.frozen || e.trapped) && player && player.intersects(e)) {
				e.shatter();
			}
			// If not frozen/trapped, collision with player
			if (!e.frozen && !e.trapped && player && player.intersects(e)) {
				if (player.shielded) {
					player.loseShield();
					LK.getSound('hit').play();
					LK.effects.flashObject(player, 0x8fffd6, 400);
				} else {
					lives--;
					livesTxt.setText('Lives: ' + lives);
					LK.effects.flashScreen(0x7e4a9c, 900);
					if (lives <= 0) {
						// Save and show best score
						var bestScore = 0;
						if (typeof storage !== "undefined" && typeof storage.get === "function") {
							bestScore = storage.get("bestScore") || 0;
							if (LK.getScore() > bestScore) {
								bestScore = LK.getScore();
								storage.set("bestScore", bestScore);
							}
						}
						// Show best score overlay
						var bestScoreOverlay = new Container();
						var bestScoreText = new Text2("Best Score: " + bestScore, {
							size: 120,
							fill: 0xF6F1C7,
							align: "center"
						});
						bestScoreText.anchor.set(0.5, 0.5);
						bestScoreText.x = 1024;
						bestScoreText.y = 1366;
						bestScoreOverlay.addChild(bestScoreText);
						LK.gui.addChild(bestScoreOverlay);
						// Remove overlay after 2.5 seconds
						LK.setTimeout(function () {
							if (bestScoreOverlay.parent) bestScoreOverlay.parent.removeChild(bestScoreOverlay);
						}, 2500);
						LK.showGameOver();
						return;
					} else {
						// Respawn player at start position
						player.x = 1024;
						player.y = 2732 - 200;
						player.vx = 0;
						player.vy = 0;
						player.loseShield();
					}
				}
			}
		}
		// When timer ends, unpause all enemies
		if (globalEnemyPauseTimer === 0) {
			for (var i = 0; i < enemies.length; i++) {
				enemies[i].pausedBySpeed = false;
			}
		}
	} else {
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			e.update();
			// If frozen or trapped, can be shattered by touching again
			if ((e.frozen || e.trapped) && player && player.intersects(e)) {
				e.shatter();
			}
			// If not frozen/trapped, collision with player
			if (!e.frozen && !e.trapped && player && player.intersects(e)) {
				if (player.shielded) {
					player.loseShield();
					LK.getSound('hit').play();
					LK.effects.flashObject(player, 0x8fffd6, 400);
				} else {
					lives--;
					livesTxt.setText('Lives: ' + lives);
					LK.effects.flashScreen(0x7e4a9c, 900);
					if (lives <= 0) {
						// Save and show best score
						var bestScore = 0;
						if (typeof storage !== "undefined" && typeof storage.get === "function") {
							bestScore = storage.get("bestScore") || 0;
							if (LK.getScore() > bestScore) {
								bestScore = LK.getScore();
								storage.set("bestScore", bestScore);
							}
						}
						// Show best score overlay
						var bestScoreOverlay = new Container();
						var bestScoreText = new Text2("Best Score: " + bestScore, {
							size: 120,
							fill: 0xF6F1C7,
							align: "center"
						});
						bestScoreText.anchor.set(0.5, 0.5);
						bestScoreText.x = 1024;
						bestScoreText.y = 1366;
						bestScoreOverlay.addChild(bestScoreText);
						LK.gui.addChild(bestScoreOverlay);
						// Remove overlay after 2.5 seconds
						LK.setTimeout(function () {
							if (bestScoreOverlay.parent) bestScoreOverlay.parent.removeChild(bestScoreOverlay);
						}, 2500);
						LK.showGameOver();
						return;
					} else {
						// Respawn player at start position
						player.x = 1024;
						player.y = 2732 - 200;
						player.vx = 0;
						player.vy = 0;
						player.loseShield();
					}
				}
			}
		}
	}
	// Update powerups
	for (var i = powerups.length - 1; i >= 0; i--) {
		var p = powerups[i];
		if (player && player.intersects(p)) {
			if (typeof moonCollectCount === "undefined") {
				var moonCollectCount = 0;
			}
			if (p.type === 'moon') {
				moonCollectCount++;
				player.activateFullMoon();
				// Start moon jump timer for 10 seconds (600 frames)
				player.moonJumpTimer = 600;
				LK.setScore(LK.getScore() + 5);
				scoreTxt.setText(LK.getScore());
				currentStageScore = LK.getScore();
				currentStageScore = LK.getScore();
				currentStageScore = LK.getScore();
				// (Lightning effect removed when collecting moon)
				// --- FreezeOrb grow effect: 3x size for 5 seconds ---
				if (typeof freezeOrbGrowTimer === "undefined") {
					var freezeOrbGrowTimer = 0;
				}
				freezeOrbGrowTimer = 300; // 5 seconds at 60fps
				// Spawn a new moon at a random position
				var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
				game.addChild(moon);
				powerups.push(moon);
				// If 5 moons collected, spawn a random shield and reset counter
				if (typeof lastMoonShieldGiven === "undefined") {
					var lastMoonShieldGiven = 0;
				}
				if (moonCollectCount >= 5) {
					moonCollectCount = 0;
					// Only give one shield per 5 moons, and only if less than 3 shields this stage
					var shieldCount = 0;
					for (var i = 0; i < powerups.length; i++) {
						if (powerups[i].type === 'shield') shieldCount++;
					}
					if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
					if (shieldCount < 3 && game.shieldsThisStage < 3 && lastMoonShieldGiven !== LK.getScore()) {
						var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
						game.addChild(shield);
						powerups.push(shield);
						game.shieldsThisStage++;
						lastMoonShieldGiven = LK.getScore();
					}
				}
				// If 100 moons collected, spawn a shield (only once per 100 moons)
				if (typeof lastHundredMoonShieldGiven === "undefined") {
					var lastHundredMoonShieldGiven = 0;
				}
				if (moonCollectCountTotal === undefined) {
					var moonCollectCountTotal = 0;
				}
				moonCollectCountTotal++;
				if (moonCollectCountTotal > 0 && moonCollectCountTotal % 100 === 0 && lastHundredMoonShieldGiven !== moonCollectCountTotal) {
					// Only spawn if less than 3 shields this stage
					var shieldCount = 0;
					for (var i = 0; i < powerups.length; i++) {
						if (powerups[i].type === 'shield') shieldCount++;
					}
					if (typeof game.shieldsThisStage === "undefined") game.shieldsThisStage = shieldCount;
					if (shieldCount < 3 && game.shieldsThisStage < 3) {
						var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
						game.addChild(shield);
						powerups.push(shield);
						game.shieldsThisStage++;
						lastHundredMoonShieldGiven = moonCollectCountTotal;
					}
				}
			} else if (p.type === 'shield') {
				player.gainShield();
				// Send ice orbs in all directions
				var orbCount = 12;
				for (var d = 0; d < orbCount; d++) {
					var angle = 2 * Math.PI * d / orbCount;
					var dirX = Math.cos(angle);
					var orb = new FreezeOrb(player.x, player.y - 60, dirX);
					// Give each orb a custom vx/vy for radial spread
					orb.vx = 24 * Math.cos(angle);
					orb.vy = 24 * Math.sin(angle);
					// Override update to move in both x and y
					(function (orb) {
						var baseUpdate = orb.update;
						orb.update = function () {
							orb.x += orb.vx;
							orb.y += orb.vy;
							orb.lifetime--;
							// Wrap horizontally
							if (orb.x < 0) orb.x = 2048;
							if (orb.x > 2048) orb.x = 0;
							// Remove if out of bounds vertically
							if (orb.y < 0 || orb.y > 2732 || orb.lifetime <= 0) {
								orb.destroy();
								var idx = freezeOrbs.indexOf(orb);
								if (idx >= 0) freezeOrbs.splice(idx, 1);
								return;
							}
						};
					})(orb);
					game.addChild(orb);
					freezeOrbs.push(orb);
				}
			} else if (p.type === 'speed') {
				player.gainSpeed();
				player.speedBoost = 240; // Speed lasts 4 seconds (60fps*4)
				// Only freeze all enemies for 10 seconds if not already frozen by speed
				if (typeof globalEnemyPauseTimer === "undefined") {
					var globalEnemyPauseTimer = 0;
				}
				if (globalEnemyPauseTimer <= 0) {
					globalEnemyPauseTimer = 600; // 10 seconds at 60fps
					for (var ep = 0; ep < enemies.length; ep++) {
						enemies[ep].pausedBySpeed = true;
					}
				}
			} else if (p.type === 'lifepotion') {
				lives++;
				livesTxt.setText('Lives: ' + lives);
				LK.effects.flashObject(player, 0x8fffd6, 400);
			} else if (p.type === 'broom') {
				// Witch can now fly for 20 seconds (1200 frames)
				player.canFly = true;
				player.flyTimer = 1200;
				LK.effects.flashObject(player, 0xb8e6ff, 600);
			} else if (p.type === 'yu') {
				// Cancel speed power when witch takes the yu
				player.speedBoost = 0;
				// Enable double jump for the player
				player.yuDoubleJump = true;
				player.hasDoubleJumped = false;
				// Remove speed pause from all enemies
				if (typeof globalEnemyPauseTimer !== "undefined") {
					globalEnemyPauseTimer = 0;
					for (var ep = 0; ep < enemies.length; ep++) {
						enemies[ep].pausedBySpeed = false;
					}
				}
				// Prevent shooting for 2 seconds (120 frames)
				player.canShoot = false;
				player.shootCooldown = 120;
			}
			LK.getSound('powerup').play();
			p.destroy();
			powerups.splice(i, 1);
		}
	}
	// Full moon: allow trap spell by tap with two fingers (simulate by double tap)
	if (player && player.fullMoon && LK.ticks % 60 === 0) {
		// For MVP, allow trap spell every second in full moon
		player.castTrap();
	}
	// Stage clear
	if (!stageCleared && enemies.length === 0) {
		stageCleared = true;
		stageTimer = 90;
		LK.effects.flashScreen(0xb8e6ff, 600);
	}
	if (stageCleared) {
		stageTimer--;
		if (stageTimer <= 0) {
			stage++;
			if (stage % 5 === 0) {
				// Boss stage: show Boss asset and spawn extra enemies
				stageTxt.setText('Boss Stage!');
				// Spawn Boss at center as a moving enemy
				var boss = new Boss(1024, 900);
				game.addChild(boss);
				enemies.push(boss);
				for (var i = 0; i < 3; i++) {
					var px = 200 + Math.random() * (2048 - 400);
					var py = 400 + Math.random() * 1200;
					var g = new Ghost(px, py);
					game.addChild(g);
					enemies.push(g);
				}
				for (var i = 0; i < 2; i++) {
					var px = 200 + Math.random() * (2048 - 400);
					var py = 300 + Math.random() * 1000;
					var b = new Bat(px, py);
					game.addChild(b);
					enemies.push(b);
				}
				stageCleared = false;
			} else {
				startStage();
			}
		}
	}
};
LK.playMusic('gothic_theme', {
	fade: {
		start: 0,
		end: 1,
		duration: 1200
	}
});
// Play music
 Ghost. In-Game asset. 2d. High contrast. No shadows
 One life potion. In-Game asset. 2d. High contrast. No shadows
 Change
 Witch boiler. In-Game asset. 2d. High contrast. No shadows
 Diffrent colour
 Broom. In-Game asset. 2d. High contrast. No shadows
 Snake. In-Game asset. 2d. High contrast. No shadows
 Add legs
 Snowball. In-Game asset. 2d. High contrast. No shadows
 
 Bat closed wings
 Behind
 Flying boss. In-Game asset. 2d. High contrast. No shadows
 Fireball. In-Game asset. 2d. High contrast. No shadows
 Moon. In-Game asset. 2d. High contrast. No shadows
 Dark forrest. In-Game asset. 2d. High contrast. No shadows
 Ice block. In-Game asset. 2d. High contrast. No shadows
 Ice wall. In-Game asset. 2d. High contrast. No shadows
 Portal. In-Game asset. 2d. High contrast. No shadows