/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Shape = Container.expand(function (options) {
	var self = Container.call(this);
	self.attachAsset('shape', {
		width: options.width,
		height: options.height,
		anchorX: options.anchorX || 0,
		anchorY: options.anchorY || 0,
		color: options.color || 0x66ff00,
		alpha: typeof options.alpha === 'number' ? options.alpha : 0
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Helper function to find a child by name.
function findChildByName(container, name) {
	for (var i = 0; i < container.children.length; i++) {
		if (container.children[i].name === name) {
			return container.children[i];
		}
	}
	return null;
}
/**** 
* Global Variables
****/ 
var jumpColGlobal = null;
var isPressHeld = false;
var pressHoldStartTime = 0;
var pressDownX = 0;
var pressDownY = 0;
var mouseX = 0;
var mouseY = 0;
game.move = function (x, y) {
	mouseX = x;
	mouseY = y;
};
var projectiles = [];
var score = 0;
var scoreTxt;
function updateScoreDisplay() {
	if (score > highScore) {
		highScore = score;
		storage.highScore = highScore;
		highScoreTxt.setText('High Score: ' + highScore);
	}
	game.removeChild(scoreTxt);
	scoreTxt = createScoreText(score);
	scoreTxt.scaleX = 1.0;
	scoreTxt.scaleY = 1.0;
	game.addChild(scoreTxt);
	tween(scoreTxt, {
		scaleX: 1.5,
		scaleY: 1.5
	}, {
		duration: 100,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(scoreTxt, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 100,
				easing: tween.easeIn
			});
		}
	});
}
function createScoreText(value) {
	var shadow = new Text2(String(value), {
		size: 600,
		fill: 0x000000,
		fontFamily: "Arial"
	});
	shadow.name = "shadow";
	shadow.anchor.set(0.5, 0);
	shadow.x = 4;
	shadow.y = 4;
	var main = new Text2(String(value), {
		size: 600,
		fill: 0xFF69B4,
		fontFamily: "Arial"
	});
	main.name = "main";
	main.anchor.set(0.5, 0);
	var container = new Container();
	container.name = "scoreTxt";
	container.x = 1024;
	container.y = 50;
	container.addChild(shadow);
	container.addChild(main);
	return container;
}
scoreTxt = createScoreText(score);
scoreTxt.scaleX = 1.0;
scoreTxt.scaleY = 1.0;
LK.playMusic('bgm', {
	loop: true
});
var bg01 = LK.getAsset('bg01', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 1366
});
game.addChild(bg01);
game.addChild(scoreTxt);
var highScore = storage.highScore || 0;
var highScoreTxt = new Text2('High Score: ' + highScore, {
	size: 50,
	fill: 0xFFFFFF
});
highScoreTxt.name = 'highScoreTxt';
highScoreTxt.anchor.set(1, 1);
highScoreTxt.x = 1900;
highScoreTxt.y = 2720;
game.addChild(highScoreTxt);
/**** 
* Persistent Power Helmet HUD (for filling up)
****/ 
var helmetMeter = 0;
var helmetMeterMax = 120;
var powerHelmet = new Container();
powerHelmet.name = "powerHelmet";
var helmetSprite = powerHelmet.attachAsset('helmet', {
	anchorX: 0.5,
	anchorY: 0.5
});
powerHelmet.x = 2048 - helmetSprite.width / 2 - 20;
powerHelmet.y = 130;
var helmetFillContainer = new Container();
helmetFillContainer.name = "helmetFillContainer";
var fillBar = new Shape({
	width: helmetSprite.width * 0.05,
	height: 40,
	color: 0xFFFFFF,
	alpha: 1
});
fillBar.anchorX = 0;
fillBar.anchorY = 0.5;
fillBar.x = -helmetSprite.width / 2;
fillBar.y = helmetSprite.height / 2 - 15;
helmetFillContainer.addChild(fillBar);
game.addChild(powerHelmet);
powerHelmet.addChild(helmetFillContainer);
function updateHelmetDisplay() {
	var fraction = helmetMeter / helmetMeterMax;
	if (helmetMeter <= 0) {
		fillBar.visible = false;
	} else {
		fillBar.visible = true;
		if (fraction > 1) {
			fraction = 1;
		}
		fillBar.width = fraction * helmetSprite.width;
	}
}
/**** 
* Petals
****/ 
var petals = [];
for (var i = 0; i < 50; i++) {
	var petal = new Container();
	petal.attachAsset('petals', {
		anchorX: 0.5,
		anchorY: 0.5,
		rotation: Math.random() * Math.PI * 2
	});
	petal.x = Math.random() * 2048;
	petal.y = Math.random() * 2732;
	petal.speedY = Math.random() * 2 + 1;
	petal.speedX = Math.random() * 2 - 1;
	petal.update = function () {
		this.y += this.speedY;
		this.x += this.speedX;
		if (this.y > 2732) {
			this.y = -50;
			this.x = Math.random() * 2048;
		}
	};
	petals.push(petal);
	game.addChild(petal);
}
/**** 
* Player Setup with Custom Collision
****/ 
var player = new Container();
var visualContainer = new Container();
visualContainer.name = 'visual';
// Attach the player_idle asset with centered anchors.
var playerSprite = visualContainer.attachAsset('player_idle', {
	anchorX: 0.5,
	anchorY: 0.5
});
player.addChild(visualContainer);
// Position the player in the scene.
player.x = 1024;
player.y = 2732 - 250;
// Add the player to the game.
game.addChild(player);
// Replace the normal collision with a custom collision shape centered on the player.
var idleCollision = player.attachAsset('shape', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 80,
	height: 120,
	alpha: 0 // Set to 0 for production (use a nonzero value for debugging)
});
idleCollision.name = 'idleCollision';
/**** 
* Idle Animations
****/ 
function startBreathingAnimation() {
	tween(player, {
		scaleX: 1.05,
		scaleY: 1.05
	}, {
		duration: 1000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(player, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: startBreathingAnimation
			});
		}
	});
}
function startTiltAnimation() {
	tween(player, {
		rotation: Math.PI / 32
	}, {
		duration: 500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(player, {
				rotation: -Math.PI / 32
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					tween(player, {
						rotation: 0
					}, {
						duration: 500,
						easing: tween.easeInOut,
						onFinish: startTiltAnimation
					});
				}
			});
		}
	});
}
startBreathingAnimation();
startTiltAnimation();
/**** 
* Attack Collider
****/ 
var attackCol = LK.getAsset('attackcol', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.75
});
game.addChild(attackCol);
attackCol.visible = false;
attackCol.alpha = 0;
/**** 
* Power-Up: Helmet HUD & Special
****/ 
var featherEffects = [];
function spawnFeatherMove() {
	if (!specialIdleActive) {
		return;
	}
	for (var i = -2; i <= 2; i++) {
		var feather = new Container();
		feather.attachAsset('feather', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		feather.x = player.x + i * 50;
		feather.y = player.y;
		game.addChild(feather);
		featherEffects.push(feather);
		tween(feather, {
			x: feather.x + i * 500,
			y: feather.y + (Math.random() * 200 - 100),
			alpha: 0
		}, {
			duration: 1000,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				feather.destroy();
			}
		});
	}
}
var helmetActive = false;
var specialIdleActive = false;
function activateHelmetPowerUp() {
	if (helmetActive) {
		return;
	}
	helmetActive = true;
	// Switch to special_idle.
	swapPlayerVisual('special_idle', player.x, player.y, visualContainer.scaleX);
	specialIdleActive = true;
	LK.getSound('warcry').play();
	LK.effects.flashScreen(0xFFFFFF, 100);
	var shakeIntensity = 10,
		shakeDuration = 500;
	var shakeStartTime = Date.now();
	var originalPosition = {
		x: game.x,
		y: game.y
	};
	function shakeScreen() {
		var elapsed = Date.now() - shakeStartTime;
		if (elapsed < shakeDuration) {
			var offsetX = (Math.random() - 0.5) * shakeIntensity;
			var offsetY = (Math.random() - 0.5) * shakeIntensity;
			game.x = originalPosition.x + offsetX;
			game.y = originalPosition.y + offsetY;
			LK.setTimeout(shakeScreen, 16);
		} else {
			game.x = originalPosition.x;
			game.y = originalPosition.y;
		}
	}
	shakeScreen();
	spawnFeatherMove();
	LK.setTimeout(spawnFeatherMove, 1500);
	LK.setTimeout(spawnFeatherMove, 3000);
	LK.setTimeout(function () {
		while (featherEffects.length) {
			featherEffects.pop().destroy();
		}
		specialIdleActive = false;
		if (!isJumping) {
			swapPlayerVisual('player_idle', player.x, player.y, visualContainer.scaleX, function () {
				startBreathingAnimation();
				startTiltAnimation();
			});
		}
		LK.effects.flashScreen(0xFFFFFF, 100);
		helmetActive = false;
		helmetMeter = 0;
		updateHelmetDisplay();
	}, 4000);
}
/**** 
* spawnEnemy and spawnShield
****/ 
function spawnEnemy() {
	var e = new Container();
	var hitbox = new Shape({
		width: 200,
		height: 209,
		anchorX: 0.5,
		anchorY: 0.5,
		color: 0x00FF00,
		alpha: 0
	});
	hitbox.x = 0;
	hitbox.y = 0;
	e.addChild(hitbox);
	var gfx = e.attachAsset('enemy01', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fromLeft = Math.random() < 0.5;
	e.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2;
	e.y = 2732 - 225;
	e.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2);
	if (Math.abs(e.speedX) >= 6) {
		gfx.tint = 0xFF0000;
	} else if (Math.abs(e.speedX) <= 3) {
		gfx.tint = 0x0000FF;
	}
	gfx.scaleX = fromLeft ? 1 : -1;
	var baseY = e.y;
	function bounce() {
		tween(e, {
			y: baseY - 50
		}, {
			duration: 500,
			easing: tween.bounceInOut,
			onFinish: function onFinish() {
				tween(e, {
					y: baseY
				}, {
					duration: 500,
					easing: tween.bounceInOut,
					onFinish: bounce
				});
			}
		});
	}
	bounce();
	enemies.push(e);
	game.addChild(e);
}
function spawnShield() {
	var shield = new Container();
	var hitbox = new Shape({
		width: 200,
		height: 209,
		anchorX: 0.5,
		anchorY: 0.5,
		color: 0x00FF00,
		alpha: 0
	});
	hitbox.x = 0;
	hitbox.y = 0;
	shield.addChild(hitbox);
	var gfx = shield.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fromLeft = Math.random() < 0.5;
	shield.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2;
	shield.y = 2732 - 225;
	shield.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2);
	// Mark shield enemy – these won't die on melee/throw hits.
	shield.isShield = true;
	// Apply a distinct tint to shield enemies.
	gfx.tint = 0xFFD700;
	gfx.scaleX = fromLeft ? 1 : -1;
	var baseY = shield.y;
	function bounce() {
		tween(shield, {
			y: baseY - 50
		}, {
			duration: 500,
			easing: tween.bounceInOut,
			onFinish: function onFinish() {
				tween(shield, {
					y: baseY
				}, {
					duration: 500,
					easing: tween.bounceInOut,
					onFinish: bounce
				});
			}
		});
	}
	bounce();
	enemies.push(shield);
	game.addChild(shield);
}
// Spawn regular enemies every ~1.5 seconds.
var enemySpawnInterval = Math.random() * 1500 + 1000;
var shieldSpawnInterval = 10000;
LK.setInterval(spawnEnemy, enemySpawnInterval);
LK.setInterval(spawnShield, shieldSpawnInterval);
// Increase spawn speed by 5% every 30 real life seconds
enemySpawnInterval *= 0.95;
shieldSpawnInterval *= 0.95;
LK.setInterval(function () {
	LK.setInterval(spawnEnemy, enemySpawnInterval);
	LK.setInterval(spawnShield, shieldSpawnInterval);
}, 30000);
/**** 
* Swap Player Sprite Function
* IMPORTANT: We add a check so that if specialIdleActive is true and we aren’t explicitly switching to 'special_idle', then no swap is performed.
****/ 
function swapPlayerVisual(newVisualId, x, y, flip, onDone) {
	// Prevent overriding the special_idle state while it’s active.
	if (specialIdleActive && newVisualId !== 'special_idle') {
		return;
	}
	var visualContainer = player.findChildByName('visual');
	if (!visualContainer) {
		visualContainer = new Container();
		visualContainer.name = 'visual';
		player.addChild(visualContainer);
	} else {
		visualContainer.removeChildAt(0);
	}
	playerSprite = visualContainer.attachAsset(newVisualId, {
		anchorX: 0.5,
		anchorY: 0.5,
		y: newVisualId === 'special_idle' ? -100 : 0,
		scaleX: newVisualId === 'special_idle' ? 1.25 : 1,
		scaleY: newVisualId === 'special_idle' ? 1.25 : 1
	});
	visualContainer.scaleX = flip;
	player.x = x;
	player.y = y;
	if (newVisualId === 'player_jump') {
		flip = Math.random() < 0.5 ? -1 : 1;
		visualContainer.scaleX = flip;
		jumpColGlobal = LK.getAsset('jumpcol', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: x,
			y: y + player.height / 2,
			alpha: 0
		});
		game.addChild(jumpColGlobal);
		tween(jumpColGlobal, {
			y: jumpColGlobal.y - 600
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				tween(jumpColGlobal, {
					y: 2732 - 250 + player.height / 2
				}, {
					duration: 300,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						jumpColGlobal.destroy();
						jumpColGlobal = null;
					}
				});
			}
		});
	}
	if (typeof onDone === 'function') {
		if (newVisualId === 'player_idle') {
			startBreathingAnimation();
			startTiltAnimation();
		}
		onDone();
	}
}
/**** 
* Input Logic
****/ 
var isSequenceRunning = false;
var isJumping = false;
var playerState = 'idle';
game.down = function (x, y) {
	// Do not process input if an action is running or special_idle is active.
	if (isSequenceRunning || specialIdleActive) {
		return;
	}
	isPressHeld = true;
	pressHoldStartTime = Date.now();
	pressDownX = x;
	pressDownY = y;
	// If click occurs in upper part and player is not already jumping, start jump sequence.
	if (y < 2732 * 2.2 / 3 && !isJumping) {
		isJumping = true;
		LK.getSound('hup').play();
		swapPlayerVisual('player_jump', player.x, player.y);
		// Generate dust effects.
		for (var i = 0; i < 10; i++) {
			var p = LK.getAsset('dust', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: player.x + (Math.random() * 100 - 50),
				y: player.y + (Math.random() * 100 - 50)
			});
			game.addChild(p);
			tween(p, {
				alpha: 0,
				x: p.x + (Math.random() * 200 - 100),
				y: p.y - Math.random() * 200
			}, {
				duration: 500,
				onFinish: function onFinish() {
					p.destroy();
				}
			});
		}
		tween(player, {
			y: player.y - 600
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				tween(player, {
					y: 2732 - 250
				}, {
					duration: 300,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						for (var j = 0; j < 10; j++) {
							var pp = LK.getAsset('dust', {
								anchorX: 0.5,
								anchorY: 0.5,
								x: player.x + (Math.random() * 100 - 50),
								y: player.y + (Math.random() * 100 - 50)
							});
							game.addChild(pp);
							tween(pp, {
								alpha: 0,
								x: pp.x + (Math.random() * 200 - 100),
								y: pp.y + Math.random() * 200
							}, {
								duration: 500,
								onFinish: function onFinish() {
									pp.destroy();
								}
							});
						}
						isJumping = false;
						var landingFlip = Math.random() < 0.5 ? -1 : 1;
						if (specialIdleActive) {
							swapPlayerVisual('special_idle', 1024, 2732 - 250, landingFlip);
						} else {
							swapPlayerVisual('player_idle', 1024, 2732 - 250, landingFlip, function () {
								startBreathingAnimation();
								startTiltAnimation();
							});
						}
						var v = player.findChildByName('visual');
						if (v) {
							var dir = v.scaleX < 0 ? -1 : 1;
							tween(v, {
								scaleX: dir * 1.3,
								scaleY: 1.3
							}, {
								duration: 50,
								onFinish: function onFinish() {
									tween(v, {
										scaleX: dir * 1.0,
										scaleY: 1.0
									}, {
										duration: 100
									});
								}
							});
						}
					}
				});
			}
		});
		return;
	}
	// Process attack input.
	isSequenceRunning = true;
	var flip = x < 1024 ? -1 : 1;
	swapPlayerVisual('player_attackf01', 1024, 2732 - 250, flip);
	LK.getSound('retroslash').play();
	var vis = player.findChildByName('visual');
	if (vis) {
		tween(vis, {
			scaleX: flip * 1.3,
			scaleY: 1.3
		}, {
			duration: 30,
			onFinish: function onFinish() {
				tween(vis, {
					scaleX: flip * 1.0,
					scaleY: 1.0
				}, {
					duration: 60
				});
			}
		});
	}
	LK.setTimeout(function () {
		swapPlayerVisual('player_attackf02', 1024, 2732 - 250, flip);
		attackCol.width = 180;
		attackCol.height = 180;
		attackCol.x = flip === -1 ? 874 : 1174;
		attackCol.y = 2732 - 250;
		attackCol.scaleX = flip;
		attackCol.visible = true;
		LK.setTimeout(function () {
			if (attackCol) {
				attackCol.visible = false;
			}
			if (!specialIdleActive) {
				swapPlayerVisual('player_idle', 1024, 2732 - 250, 1, function () {
					startBreathingAnimation();
					startTiltAnimation();
				});
			}
			isSequenceRunning = false;
			playerState = 'idle';
		}, 150);
	}, 150);
};
/**** 
* Enemies Array & Spawn
****/ 
var enemies = [];
LK.setInterval(spawnEnemy, Math.random() * 2000 + 1500);
LK.setInterval(spawnShield, 15000);
/**** 
* Projectile Logic (Throw Attack)
* Note: For throw, we use only the f01 animation then immediately revert back to idle.
****/ 
function spawnProjectile(targetX, targetY) {
	var flip = targetX < player.x ? -1 : 1;
	// Use only player_attackf01 for the throw.
	swapPlayerVisual('player_attackf01', player.x, player.y, flip);
	var proj = new Container();
	proj.attachAsset('player_throw', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	LK.getSound('throwsnd').play();
	proj.x = player.x;
	proj.y = player.y;
	var cloudSmoke = LK.getAsset('cloudsmoke', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: proj.x,
		y: proj.y,
		alpha: 0.75
	});
	game.addChild(cloudSmoke);
	tween(cloudSmoke, {
		scaleX: 1.5,
		scaleY: 1.5,
		alpha: 0
	}, {
		duration: 500,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			cloudSmoke.destroy();
		}
	});
	var dx = targetX - player.x,
		dy = targetY - player.y;
	var dist = Math.sqrt(dx * dx + dy * dy);
	if (dist !== 0) {
		dx /= dist;
		dy /= dist;
	}
	var speed = 40;
	proj.vx = dx * speed;
	proj.vy = dy * speed;
	proj.scaleX = targetX < player.x ? -1 : 1;
	proj.distanceTraveled = 0;
	proj.maxDistance = 1000;
	projectiles.push(proj);
	game.addChild(proj);
	LK.setTimeout(function () {
		// Revert directly to idle after throw.
		swapPlayerVisual('player_idle', player.x, player.y, flip, function () {
			startBreathingAnimation();
			startTiltAnimation();
		});
	}, 300);
}
/**** 
* Coins
****/ 
var coins = [];
function dropCoin(x, y) {
	var rand = Math.random();
	if (rand < 0.5) {
		var coin = new Container();
		coin.type = 'silver';
		coin.attachAsset('silver_coin', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		coin.x = x;
		coin.y = y;
		game.addChild(coin);
		coins.push(coin);
		loopCoinTween(coin, y);
	} else if (rand < 0.6) {
		var coin = new Container();
		coin.type = 'gold';
		coin.attachAsset('gold_coin', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		coin.x = x;
		coin.y = y;
		game.addChild(coin);
		coins.push(coin);
		loopCoinTween(coin, y);
	}
}
/**** 
* Looping Tween Functions
****/ 
function loopCoinTween(coin, baseY) {
	tween(coin, {
		y: baseY - 20
	}, {
		duration: 1000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(coin, {
				y: baseY + 20
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					loopCoinTween(coin, baseY);
				}
			});
		}
	});
}
/**** 
* Enemy Hit Logic – Also fills the helmet meter
****/ 
function handleEnemyHit(enemy, index, attackType) {
	if (!enemies.includes(enemy) || enemy.hit) {
		return;
	}
	// Ignore melee/throw hits if enemy is a shield.
	if (enemy.isShield && (attackType === 'melee' || attackType === 'throw')) {
		return;
	}
	enemy.hit = true;
	LK.getSound('slimedeath').play();
	if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') {
		enemy.bounceTween.cancel();
	}
	tween(enemy, {
		tint: 0xFF0000
	}, {
		duration: 0,
		onFinish: function onFinish() {
			tween(enemy, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: 50,
				onFinish: function onFinish() {
					tween(enemy, {
						scaleX: 0.5,
						scaleY: 0.5,
						alpha: 0
					}, {
						duration: 100,
						onFinish: function onFinish() {
							var idx = enemies.indexOf(enemy);
							if (idx !== -1) {
								enemies.splice(idx, 1);
							}
							enemy.hit = false;
							enemy.destroy();
							if (!enemy.coinsDropped) {
								dropCoin(enemy.x, enemy.y);
								enemy.coinsDropped = true;
							}
							// Increase helmetMeter based on attack type.
							if (attackType === 'melee') {
								helmetMeter += 5;
							} else if (attackType === 'throw') {
								helmetMeter += 5;
							} else if (attackType === 'special_idle') {
								helmetMeter += 15;
							}
							if (helmetMeter >= helmetMeterMax) {
								helmetMeter = helmetMeterMax;
								activateHelmetPowerUp();
								helmetMeter = 0;
							}
							updateHelmetDisplay();
							if (!enemy.scoreCounted) {
								if (attackType === 'melee') {
									score += 2;
								} else if (attackType === 'throw') {
									score += 1;
								} else {
									score++;
								}
								updateScoreDisplay();
								enemy.scoreCounted = true;
							}
						}
					});
				}
			});
		}
	});
}
function handleEnemyJumpHit(enemy, index) {
	if (!enemies.includes(enemy)) {
		return;
	}
	LK.getSound('boing').play();
	if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') {
		enemy.bounceTween.cancel();
	}
	tween(enemy, {
		tint: 0xFF0000
	}, {
		duration: 0,
		onFinish: function onFinish() {
			var targetX = enemy.x < 1024 ? -300 : 2048 + 300;
			var targetY = enemy.y - 600;
			tween(enemy, {
				x: targetX,
				y: targetY,
				alpha: 0
			}, {
				duration: 200,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					var idx = enemies.indexOf(enemy);
					if (idx !== -1) {
						enemies.splice(idx, 1);
					}
					enemy.destroy();
					if (!enemy.coinsDropped) {
						dropCoin(enemy.x, enemy.y);
						enemy.coinsDropped = true;
					}
					helmetMeter += 10;
					if (helmetMeter >= helmetMeterMax) {
						helmetMeter = helmetMeterMax;
						activateHelmetPowerUp();
						helmetMeter = 0;
					}
					updateHelmetDisplay();
					if (!enemy.scoreCounted) {
						score += 3;
						updateScoreDisplay();
						enemy.scoreCounted = true;
					}
				}
			});
		}
	});
}
/**** 
* findChildByName Helper
****/ 
Container.prototype.findChildByName = function (name) {
	for (var i = 0; i < this.children.length; i++) {
		if (this.children[i].name === name) {
			return this.children[i];
		}
	}
	return null;
};
/**** 
* game.up to Reset Press
****/ 
game.up = function (x, y) {
	isPressHeld = false;
	pressHoldStartTime = 0;
};
/**** 
* Main Update
****/ 
game.update = function () {
	if (isPressHeld) {
		var holdDuration = Date.now() - pressHoldStartTime;
		if (holdDuration > 500) {
			console.log("Long press detected, spawn projectile!");
			isPressHeld = false;
			spawnProjectile(pressDownX, pressDownY);
		}
	}
	for (var p = projectiles.length - 1; p >= 0; p--) {
		var proj = projectiles[p];
		proj.x += proj.vx;
		proj.y += proj.vy;
		var stepDist = Math.sqrt(proj.vx * proj.vx + proj.vy * proj.vy);
		proj.distanceTraveled += stepDist;
		if (proj.distanceTraveled > proj.maxDistance) {
			projectiles.splice(p, 1);
			proj.destroy();
			continue;
		}
		if (proj.x < -100 || proj.x > 2148 || proj.y < -100 || proj.y > 2832) {
			projectiles.splice(p, 1);
			proj.destroy();
			continue;
		}
		for (var ei = enemies.length - 1; ei >= 0; ei--) {
			var enemy = enemies[ei];
			if (proj.intersects(enemy)) {
				handleEnemyHit(enemy, ei, 'throw');
				projectiles.splice(p, 1);
				proj.destroy();
				break;
			}
		}
	}
	for (var f = featherEffects.length - 1; f >= 0; f--) {
		var feather = featherEffects[f];
		for (var ei = enemies.length - 1; ei >= 0; ei--) {
			var enemy = enemies[ei];
			if (feather.intersects(enemy)) {
				handleEnemyHit(enemy, ei, 'feather');
				featherEffects.splice(f, 1);
				feather.destroy();
				break;
			}
		}
	}
	for (var i = enemies.length - 1; i >= 0; i--) {
		var e = enemies[i];
		e.x += e.speedX;
		if (e.x < -300 || e.x > 2048 + 300) {
			var index = enemies.indexOf(e);
			if (index !== -1) {
				enemies.splice(index, 1);
			}
			e.destroy();
			continue;
		}
		if (jumpColGlobal && jumpColGlobal.visible && e.intersects(jumpColGlobal)) {
			handleEnemyJumpHit(e, i);
			continue;
		}
		if (attackCol.visible && e.intersects(attackCol)) {
			handleEnemyHit(e, i, 'melee');
		}
		var idleCollision = player.findChildByName('idleCollision');
		if (!isJumping && !attackCol.visible && idleCollision && e.intersects(idleCollision)) {
			if (specialIdleActive) {
				handleEnemyHit(e, i, 'special_idle');
				continue;
			} else {
				storage.lastScore = score;
				LK.showGameOver();
			}
		}
	}
	for (var i = coins.length - 1; i >= 0; i--) {
		var coin = coins[i];
		if (!coin.collecting && Math.abs(coin.x - mouseX) < 32.5 && Math.abs(coin.y - mouseY) < 32.5) {
			coin.collecting = true;
			tween(coin, {
				x: scoreTxt.x,
				y: scoreTxt.y,
				alpha: 0
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					var index = coins.indexOf(coin);
					if (index !== -1) {
						coins.splice(index, 1);
					}
					if (coin.type === 'silver') {
						LK.getSound('silversnd').play();
						score += 5;
					} else if (coin.type === 'gold') {
						LK.getSound('goldsnd').play();
						score += 10;
					}
					updateScoreDisplay();
					coin.destroy();
				}
			});
		}
	}
	// Helmet HUD: No collision logic.
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Shape = Container.expand(function (options) {
	var self = Container.call(this);
	self.attachAsset('shape', {
		width: options.width,
		height: options.height,
		anchorX: options.anchorX || 0,
		anchorY: options.anchorY || 0,
		color: options.color || 0x66ff00,
		alpha: typeof options.alpha === 'number' ? options.alpha : 0
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Helper function to find a child by name.
function findChildByName(container, name) {
	for (var i = 0; i < container.children.length; i++) {
		if (container.children[i].name === name) {
			return container.children[i];
		}
	}
	return null;
}
/**** 
* Global Variables
****/ 
var jumpColGlobal = null;
var isPressHeld = false;
var pressHoldStartTime = 0;
var pressDownX = 0;
var pressDownY = 0;
var mouseX = 0;
var mouseY = 0;
game.move = function (x, y) {
	mouseX = x;
	mouseY = y;
};
var projectiles = [];
var score = 0;
var scoreTxt;
function updateScoreDisplay() {
	if (score > highScore) {
		highScore = score;
		storage.highScore = highScore;
		highScoreTxt.setText('High Score: ' + highScore);
	}
	game.removeChild(scoreTxt);
	scoreTxt = createScoreText(score);
	scoreTxt.scaleX = 1.0;
	scoreTxt.scaleY = 1.0;
	game.addChild(scoreTxt);
	tween(scoreTxt, {
		scaleX: 1.5,
		scaleY: 1.5
	}, {
		duration: 100,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(scoreTxt, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 100,
				easing: tween.easeIn
			});
		}
	});
}
function createScoreText(value) {
	var shadow = new Text2(String(value), {
		size: 600,
		fill: 0x000000,
		fontFamily: "Arial"
	});
	shadow.name = "shadow";
	shadow.anchor.set(0.5, 0);
	shadow.x = 4;
	shadow.y = 4;
	var main = new Text2(String(value), {
		size: 600,
		fill: 0xFF69B4,
		fontFamily: "Arial"
	});
	main.name = "main";
	main.anchor.set(0.5, 0);
	var container = new Container();
	container.name = "scoreTxt";
	container.x = 1024;
	container.y = 50;
	container.addChild(shadow);
	container.addChild(main);
	return container;
}
scoreTxt = createScoreText(score);
scoreTxt.scaleX = 1.0;
scoreTxt.scaleY = 1.0;
LK.playMusic('bgm', {
	loop: true
});
var bg01 = LK.getAsset('bg01', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 1366
});
game.addChild(bg01);
game.addChild(scoreTxt);
var highScore = storage.highScore || 0;
var highScoreTxt = new Text2('High Score: ' + highScore, {
	size: 50,
	fill: 0xFFFFFF
});
highScoreTxt.name = 'highScoreTxt';
highScoreTxt.anchor.set(1, 1);
highScoreTxt.x = 1900;
highScoreTxt.y = 2720;
game.addChild(highScoreTxt);
/**** 
* Persistent Power Helmet HUD (for filling up)
****/ 
var helmetMeter = 0;
var helmetMeterMax = 120;
var powerHelmet = new Container();
powerHelmet.name = "powerHelmet";
var helmetSprite = powerHelmet.attachAsset('helmet', {
	anchorX: 0.5,
	anchorY: 0.5
});
powerHelmet.x = 2048 - helmetSprite.width / 2 - 20;
powerHelmet.y = 130;
var helmetFillContainer = new Container();
helmetFillContainer.name = "helmetFillContainer";
var fillBar = new Shape({
	width: helmetSprite.width * 0.05,
	height: 40,
	color: 0xFFFFFF,
	alpha: 1
});
fillBar.anchorX = 0;
fillBar.anchorY = 0.5;
fillBar.x = -helmetSprite.width / 2;
fillBar.y = helmetSprite.height / 2 - 15;
helmetFillContainer.addChild(fillBar);
game.addChild(powerHelmet);
powerHelmet.addChild(helmetFillContainer);
function updateHelmetDisplay() {
	var fraction = helmetMeter / helmetMeterMax;
	if (helmetMeter <= 0) {
		fillBar.visible = false;
	} else {
		fillBar.visible = true;
		if (fraction > 1) {
			fraction = 1;
		}
		fillBar.width = fraction * helmetSprite.width;
	}
}
/**** 
* Petals
****/ 
var petals = [];
for (var i = 0; i < 50; i++) {
	var petal = new Container();
	petal.attachAsset('petals', {
		anchorX: 0.5,
		anchorY: 0.5,
		rotation: Math.random() * Math.PI * 2
	});
	petal.x = Math.random() * 2048;
	petal.y = Math.random() * 2732;
	petal.speedY = Math.random() * 2 + 1;
	petal.speedX = Math.random() * 2 - 1;
	petal.update = function () {
		this.y += this.speedY;
		this.x += this.speedX;
		if (this.y > 2732) {
			this.y = -50;
			this.x = Math.random() * 2048;
		}
	};
	petals.push(petal);
	game.addChild(petal);
}
/**** 
* Player Setup with Custom Collision
****/ 
var player = new Container();
var visualContainer = new Container();
visualContainer.name = 'visual';
// Attach the player_idle asset with centered anchors.
var playerSprite = visualContainer.attachAsset('player_idle', {
	anchorX: 0.5,
	anchorY: 0.5
});
player.addChild(visualContainer);
// Position the player in the scene.
player.x = 1024;
player.y = 2732 - 250;
// Add the player to the game.
game.addChild(player);
// Replace the normal collision with a custom collision shape centered on the player.
var idleCollision = player.attachAsset('shape', {
	anchorX: 0.5,
	anchorY: 0.5,
	width: 80,
	height: 120,
	alpha: 0 // Set to 0 for production (use a nonzero value for debugging)
});
idleCollision.name = 'idleCollision';
/**** 
* Idle Animations
****/ 
function startBreathingAnimation() {
	tween(player, {
		scaleX: 1.05,
		scaleY: 1.05
	}, {
		duration: 1000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(player, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: startBreathingAnimation
			});
		}
	});
}
function startTiltAnimation() {
	tween(player, {
		rotation: Math.PI / 32
	}, {
		duration: 500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(player, {
				rotation: -Math.PI / 32
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					tween(player, {
						rotation: 0
					}, {
						duration: 500,
						easing: tween.easeInOut,
						onFinish: startTiltAnimation
					});
				}
			});
		}
	});
}
startBreathingAnimation();
startTiltAnimation();
/**** 
* Attack Collider
****/ 
var attackCol = LK.getAsset('attackcol', {
	anchorX: 0.5,
	anchorY: 0.5,
	alpha: 0.75
});
game.addChild(attackCol);
attackCol.visible = false;
attackCol.alpha = 0;
/**** 
* Power-Up: Helmet HUD & Special
****/ 
var featherEffects = [];
function spawnFeatherMove() {
	if (!specialIdleActive) {
		return;
	}
	for (var i = -2; i <= 2; i++) {
		var feather = new Container();
		feather.attachAsset('feather', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		feather.x = player.x + i * 50;
		feather.y = player.y;
		game.addChild(feather);
		featherEffects.push(feather);
		tween(feather, {
			x: feather.x + i * 500,
			y: feather.y + (Math.random() * 200 - 100),
			alpha: 0
		}, {
			duration: 1000,
			easing: tween.easeInOut,
			onFinish: function onFinish() {
				feather.destroy();
			}
		});
	}
}
var helmetActive = false;
var specialIdleActive = false;
function activateHelmetPowerUp() {
	if (helmetActive) {
		return;
	}
	helmetActive = true;
	// Switch to special_idle.
	swapPlayerVisual('special_idle', player.x, player.y, visualContainer.scaleX);
	specialIdleActive = true;
	LK.getSound('warcry').play();
	LK.effects.flashScreen(0xFFFFFF, 100);
	var shakeIntensity = 10,
		shakeDuration = 500;
	var shakeStartTime = Date.now();
	var originalPosition = {
		x: game.x,
		y: game.y
	};
	function shakeScreen() {
		var elapsed = Date.now() - shakeStartTime;
		if (elapsed < shakeDuration) {
			var offsetX = (Math.random() - 0.5) * shakeIntensity;
			var offsetY = (Math.random() - 0.5) * shakeIntensity;
			game.x = originalPosition.x + offsetX;
			game.y = originalPosition.y + offsetY;
			LK.setTimeout(shakeScreen, 16);
		} else {
			game.x = originalPosition.x;
			game.y = originalPosition.y;
		}
	}
	shakeScreen();
	spawnFeatherMove();
	LK.setTimeout(spawnFeatherMove, 1500);
	LK.setTimeout(spawnFeatherMove, 3000);
	LK.setTimeout(function () {
		while (featherEffects.length) {
			featherEffects.pop().destroy();
		}
		specialIdleActive = false;
		if (!isJumping) {
			swapPlayerVisual('player_idle', player.x, player.y, visualContainer.scaleX, function () {
				startBreathingAnimation();
				startTiltAnimation();
			});
		}
		LK.effects.flashScreen(0xFFFFFF, 100);
		helmetActive = false;
		helmetMeter = 0;
		updateHelmetDisplay();
	}, 4000);
}
/**** 
* spawnEnemy and spawnShield
****/ 
function spawnEnemy() {
	var e = new Container();
	var hitbox = new Shape({
		width: 200,
		height: 209,
		anchorX: 0.5,
		anchorY: 0.5,
		color: 0x00FF00,
		alpha: 0
	});
	hitbox.x = 0;
	hitbox.y = 0;
	e.addChild(hitbox);
	var gfx = e.attachAsset('enemy01', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fromLeft = Math.random() < 0.5;
	e.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2;
	e.y = 2732 - 225;
	e.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2);
	if (Math.abs(e.speedX) >= 6) {
		gfx.tint = 0xFF0000;
	} else if (Math.abs(e.speedX) <= 3) {
		gfx.tint = 0x0000FF;
	}
	gfx.scaleX = fromLeft ? 1 : -1;
	var baseY = e.y;
	function bounce() {
		tween(e, {
			y: baseY - 50
		}, {
			duration: 500,
			easing: tween.bounceInOut,
			onFinish: function onFinish() {
				tween(e, {
					y: baseY
				}, {
					duration: 500,
					easing: tween.bounceInOut,
					onFinish: bounce
				});
			}
		});
	}
	bounce();
	enemies.push(e);
	game.addChild(e);
}
function spawnShield() {
	var shield = new Container();
	var hitbox = new Shape({
		width: 200,
		height: 209,
		anchorX: 0.5,
		anchorY: 0.5,
		color: 0x00FF00,
		alpha: 0
	});
	hitbox.x = 0;
	hitbox.y = 0;
	shield.addChild(hitbox);
	var gfx = shield.attachAsset('shield', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var fromLeft = Math.random() < 0.5;
	shield.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2;
	shield.y = 2732 - 225;
	shield.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2);
	// Mark shield enemy – these won't die on melee/throw hits.
	shield.isShield = true;
	// Apply a distinct tint to shield enemies.
	gfx.tint = 0xFFD700;
	gfx.scaleX = fromLeft ? 1 : -1;
	var baseY = shield.y;
	function bounce() {
		tween(shield, {
			y: baseY - 50
		}, {
			duration: 500,
			easing: tween.bounceInOut,
			onFinish: function onFinish() {
				tween(shield, {
					y: baseY
				}, {
					duration: 500,
					easing: tween.bounceInOut,
					onFinish: bounce
				});
			}
		});
	}
	bounce();
	enemies.push(shield);
	game.addChild(shield);
}
// Spawn regular enemies every ~1.5 seconds.
var enemySpawnInterval = Math.random() * 1500 + 1000;
var shieldSpawnInterval = 10000;
LK.setInterval(spawnEnemy, enemySpawnInterval);
LK.setInterval(spawnShield, shieldSpawnInterval);
// Increase spawn speed by 5% every 30 real life seconds
enemySpawnInterval *= 0.95;
shieldSpawnInterval *= 0.95;
LK.setInterval(function () {
	LK.setInterval(spawnEnemy, enemySpawnInterval);
	LK.setInterval(spawnShield, shieldSpawnInterval);
}, 30000);
/**** 
* Swap Player Sprite Function
* IMPORTANT: We add a check so that if specialIdleActive is true and we aren’t explicitly switching to 'special_idle', then no swap is performed.
****/ 
function swapPlayerVisual(newVisualId, x, y, flip, onDone) {
	// Prevent overriding the special_idle state while it’s active.
	if (specialIdleActive && newVisualId !== 'special_idle') {
		return;
	}
	var visualContainer = player.findChildByName('visual');
	if (!visualContainer) {
		visualContainer = new Container();
		visualContainer.name = 'visual';
		player.addChild(visualContainer);
	} else {
		visualContainer.removeChildAt(0);
	}
	playerSprite = visualContainer.attachAsset(newVisualId, {
		anchorX: 0.5,
		anchorY: 0.5,
		y: newVisualId === 'special_idle' ? -100 : 0,
		scaleX: newVisualId === 'special_idle' ? 1.25 : 1,
		scaleY: newVisualId === 'special_idle' ? 1.25 : 1
	});
	visualContainer.scaleX = flip;
	player.x = x;
	player.y = y;
	if (newVisualId === 'player_jump') {
		flip = Math.random() < 0.5 ? -1 : 1;
		visualContainer.scaleX = flip;
		jumpColGlobal = LK.getAsset('jumpcol', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: x,
			y: y + player.height / 2,
			alpha: 0
		});
		game.addChild(jumpColGlobal);
		tween(jumpColGlobal, {
			y: jumpColGlobal.y - 600
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				tween(jumpColGlobal, {
					y: 2732 - 250 + player.height / 2
				}, {
					duration: 300,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						jumpColGlobal.destroy();
						jumpColGlobal = null;
					}
				});
			}
		});
	}
	if (typeof onDone === 'function') {
		if (newVisualId === 'player_idle') {
			startBreathingAnimation();
			startTiltAnimation();
		}
		onDone();
	}
}
/**** 
* Input Logic
****/ 
var isSequenceRunning = false;
var isJumping = false;
var playerState = 'idle';
game.down = function (x, y) {
	// Do not process input if an action is running or special_idle is active.
	if (isSequenceRunning || specialIdleActive) {
		return;
	}
	isPressHeld = true;
	pressHoldStartTime = Date.now();
	pressDownX = x;
	pressDownY = y;
	// If click occurs in upper part and player is not already jumping, start jump sequence.
	if (y < 2732 * 2.2 / 3 && !isJumping) {
		isJumping = true;
		LK.getSound('hup').play();
		swapPlayerVisual('player_jump', player.x, player.y);
		// Generate dust effects.
		for (var i = 0; i < 10; i++) {
			var p = LK.getAsset('dust', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: player.x + (Math.random() * 100 - 50),
				y: player.y + (Math.random() * 100 - 50)
			});
			game.addChild(p);
			tween(p, {
				alpha: 0,
				x: p.x + (Math.random() * 200 - 100),
				y: p.y - Math.random() * 200
			}, {
				duration: 500,
				onFinish: function onFinish() {
					p.destroy();
				}
			});
		}
		tween(player, {
			y: player.y - 600
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				tween(player, {
					y: 2732 - 250
				}, {
					duration: 300,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						for (var j = 0; j < 10; j++) {
							var pp = LK.getAsset('dust', {
								anchorX: 0.5,
								anchorY: 0.5,
								x: player.x + (Math.random() * 100 - 50),
								y: player.y + (Math.random() * 100 - 50)
							});
							game.addChild(pp);
							tween(pp, {
								alpha: 0,
								x: pp.x + (Math.random() * 200 - 100),
								y: pp.y + Math.random() * 200
							}, {
								duration: 500,
								onFinish: function onFinish() {
									pp.destroy();
								}
							});
						}
						isJumping = false;
						var landingFlip = Math.random() < 0.5 ? -1 : 1;
						if (specialIdleActive) {
							swapPlayerVisual('special_idle', 1024, 2732 - 250, landingFlip);
						} else {
							swapPlayerVisual('player_idle', 1024, 2732 - 250, landingFlip, function () {
								startBreathingAnimation();
								startTiltAnimation();
							});
						}
						var v = player.findChildByName('visual');
						if (v) {
							var dir = v.scaleX < 0 ? -1 : 1;
							tween(v, {
								scaleX: dir * 1.3,
								scaleY: 1.3
							}, {
								duration: 50,
								onFinish: function onFinish() {
									tween(v, {
										scaleX: dir * 1.0,
										scaleY: 1.0
									}, {
										duration: 100
									});
								}
							});
						}
					}
				});
			}
		});
		return;
	}
	// Process attack input.
	isSequenceRunning = true;
	var flip = x < 1024 ? -1 : 1;
	swapPlayerVisual('player_attackf01', 1024, 2732 - 250, flip);
	LK.getSound('retroslash').play();
	var vis = player.findChildByName('visual');
	if (vis) {
		tween(vis, {
			scaleX: flip * 1.3,
			scaleY: 1.3
		}, {
			duration: 30,
			onFinish: function onFinish() {
				tween(vis, {
					scaleX: flip * 1.0,
					scaleY: 1.0
				}, {
					duration: 60
				});
			}
		});
	}
	LK.setTimeout(function () {
		swapPlayerVisual('player_attackf02', 1024, 2732 - 250, flip);
		attackCol.width = 180;
		attackCol.height = 180;
		attackCol.x = flip === -1 ? 874 : 1174;
		attackCol.y = 2732 - 250;
		attackCol.scaleX = flip;
		attackCol.visible = true;
		LK.setTimeout(function () {
			if (attackCol) {
				attackCol.visible = false;
			}
			if (!specialIdleActive) {
				swapPlayerVisual('player_idle', 1024, 2732 - 250, 1, function () {
					startBreathingAnimation();
					startTiltAnimation();
				});
			}
			isSequenceRunning = false;
			playerState = 'idle';
		}, 150);
	}, 150);
};
/**** 
* Enemies Array & Spawn
****/ 
var enemies = [];
LK.setInterval(spawnEnemy, Math.random() * 2000 + 1500);
LK.setInterval(spawnShield, 15000);
/**** 
* Projectile Logic (Throw Attack)
* Note: For throw, we use only the f01 animation then immediately revert back to idle.
****/ 
function spawnProjectile(targetX, targetY) {
	var flip = targetX < player.x ? -1 : 1;
	// Use only player_attackf01 for the throw.
	swapPlayerVisual('player_attackf01', player.x, player.y, flip);
	var proj = new Container();
	proj.attachAsset('player_throw', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	LK.getSound('throwsnd').play();
	proj.x = player.x;
	proj.y = player.y;
	var cloudSmoke = LK.getAsset('cloudsmoke', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: proj.x,
		y: proj.y,
		alpha: 0.75
	});
	game.addChild(cloudSmoke);
	tween(cloudSmoke, {
		scaleX: 1.5,
		scaleY: 1.5,
		alpha: 0
	}, {
		duration: 500,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			cloudSmoke.destroy();
		}
	});
	var dx = targetX - player.x,
		dy = targetY - player.y;
	var dist = Math.sqrt(dx * dx + dy * dy);
	if (dist !== 0) {
		dx /= dist;
		dy /= dist;
	}
	var speed = 40;
	proj.vx = dx * speed;
	proj.vy = dy * speed;
	proj.scaleX = targetX < player.x ? -1 : 1;
	proj.distanceTraveled = 0;
	proj.maxDistance = 1000;
	projectiles.push(proj);
	game.addChild(proj);
	LK.setTimeout(function () {
		// Revert directly to idle after throw.
		swapPlayerVisual('player_idle', player.x, player.y, flip, function () {
			startBreathingAnimation();
			startTiltAnimation();
		});
	}, 300);
}
/**** 
* Coins
****/ 
var coins = [];
function dropCoin(x, y) {
	var rand = Math.random();
	if (rand < 0.5) {
		var coin = new Container();
		coin.type = 'silver';
		coin.attachAsset('silver_coin', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		coin.x = x;
		coin.y = y;
		game.addChild(coin);
		coins.push(coin);
		loopCoinTween(coin, y);
	} else if (rand < 0.6) {
		var coin = new Container();
		coin.type = 'gold';
		coin.attachAsset('gold_coin', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		coin.x = x;
		coin.y = y;
		game.addChild(coin);
		coins.push(coin);
		loopCoinTween(coin, y);
	}
}
/**** 
* Looping Tween Functions
****/ 
function loopCoinTween(coin, baseY) {
	tween(coin, {
		y: baseY - 20
	}, {
		duration: 1000,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(coin, {
				y: baseY + 20
			}, {
				duration: 1000,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					loopCoinTween(coin, baseY);
				}
			});
		}
	});
}
/**** 
* Enemy Hit Logic – Also fills the helmet meter
****/ 
function handleEnemyHit(enemy, index, attackType) {
	if (!enemies.includes(enemy) || enemy.hit) {
		return;
	}
	// Ignore melee/throw hits if enemy is a shield.
	if (enemy.isShield && (attackType === 'melee' || attackType === 'throw')) {
		return;
	}
	enemy.hit = true;
	LK.getSound('slimedeath').play();
	if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') {
		enemy.bounceTween.cancel();
	}
	tween(enemy, {
		tint: 0xFF0000
	}, {
		duration: 0,
		onFinish: function onFinish() {
			tween(enemy, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: 50,
				onFinish: function onFinish() {
					tween(enemy, {
						scaleX: 0.5,
						scaleY: 0.5,
						alpha: 0
					}, {
						duration: 100,
						onFinish: function onFinish() {
							var idx = enemies.indexOf(enemy);
							if (idx !== -1) {
								enemies.splice(idx, 1);
							}
							enemy.hit = false;
							enemy.destroy();
							if (!enemy.coinsDropped) {
								dropCoin(enemy.x, enemy.y);
								enemy.coinsDropped = true;
							}
							// Increase helmetMeter based on attack type.
							if (attackType === 'melee') {
								helmetMeter += 5;
							} else if (attackType === 'throw') {
								helmetMeter += 5;
							} else if (attackType === 'special_idle') {
								helmetMeter += 15;
							}
							if (helmetMeter >= helmetMeterMax) {
								helmetMeter = helmetMeterMax;
								activateHelmetPowerUp();
								helmetMeter = 0;
							}
							updateHelmetDisplay();
							if (!enemy.scoreCounted) {
								if (attackType === 'melee') {
									score += 2;
								} else if (attackType === 'throw') {
									score += 1;
								} else {
									score++;
								}
								updateScoreDisplay();
								enemy.scoreCounted = true;
							}
						}
					});
				}
			});
		}
	});
}
function handleEnemyJumpHit(enemy, index) {
	if (!enemies.includes(enemy)) {
		return;
	}
	LK.getSound('boing').play();
	if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') {
		enemy.bounceTween.cancel();
	}
	tween(enemy, {
		tint: 0xFF0000
	}, {
		duration: 0,
		onFinish: function onFinish() {
			var targetX = enemy.x < 1024 ? -300 : 2048 + 300;
			var targetY = enemy.y - 600;
			tween(enemy, {
				x: targetX,
				y: targetY,
				alpha: 0
			}, {
				duration: 200,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					var idx = enemies.indexOf(enemy);
					if (idx !== -1) {
						enemies.splice(idx, 1);
					}
					enemy.destroy();
					if (!enemy.coinsDropped) {
						dropCoin(enemy.x, enemy.y);
						enemy.coinsDropped = true;
					}
					helmetMeter += 10;
					if (helmetMeter >= helmetMeterMax) {
						helmetMeter = helmetMeterMax;
						activateHelmetPowerUp();
						helmetMeter = 0;
					}
					updateHelmetDisplay();
					if (!enemy.scoreCounted) {
						score += 3;
						updateScoreDisplay();
						enemy.scoreCounted = true;
					}
				}
			});
		}
	});
}
/**** 
* findChildByName Helper
****/ 
Container.prototype.findChildByName = function (name) {
	for (var i = 0; i < this.children.length; i++) {
		if (this.children[i].name === name) {
			return this.children[i];
		}
	}
	return null;
};
/**** 
* game.up to Reset Press
****/ 
game.up = function (x, y) {
	isPressHeld = false;
	pressHoldStartTime = 0;
};
/**** 
* Main Update
****/ 
game.update = function () {
	if (isPressHeld) {
		var holdDuration = Date.now() - pressHoldStartTime;
		if (holdDuration > 500) {
			console.log("Long press detected, spawn projectile!");
			isPressHeld = false;
			spawnProjectile(pressDownX, pressDownY);
		}
	}
	for (var p = projectiles.length - 1; p >= 0; p--) {
		var proj = projectiles[p];
		proj.x += proj.vx;
		proj.y += proj.vy;
		var stepDist = Math.sqrt(proj.vx * proj.vx + proj.vy * proj.vy);
		proj.distanceTraveled += stepDist;
		if (proj.distanceTraveled > proj.maxDistance) {
			projectiles.splice(p, 1);
			proj.destroy();
			continue;
		}
		if (proj.x < -100 || proj.x > 2148 || proj.y < -100 || proj.y > 2832) {
			projectiles.splice(p, 1);
			proj.destroy();
			continue;
		}
		for (var ei = enemies.length - 1; ei >= 0; ei--) {
			var enemy = enemies[ei];
			if (proj.intersects(enemy)) {
				handleEnemyHit(enemy, ei, 'throw');
				projectiles.splice(p, 1);
				proj.destroy();
				break;
			}
		}
	}
	for (var f = featherEffects.length - 1; f >= 0; f--) {
		var feather = featherEffects[f];
		for (var ei = enemies.length - 1; ei >= 0; ei--) {
			var enemy = enemies[ei];
			if (feather.intersects(enemy)) {
				handleEnemyHit(enemy, ei, 'feather');
				featherEffects.splice(f, 1);
				feather.destroy();
				break;
			}
		}
	}
	for (var i = enemies.length - 1; i >= 0; i--) {
		var e = enemies[i];
		e.x += e.speedX;
		if (e.x < -300 || e.x > 2048 + 300) {
			var index = enemies.indexOf(e);
			if (index !== -1) {
				enemies.splice(index, 1);
			}
			e.destroy();
			continue;
		}
		if (jumpColGlobal && jumpColGlobal.visible && e.intersects(jumpColGlobal)) {
			handleEnemyJumpHit(e, i);
			continue;
		}
		if (attackCol.visible && e.intersects(attackCol)) {
			handleEnemyHit(e, i, 'melee');
		}
		var idleCollision = player.findChildByName('idleCollision');
		if (!isJumping && !attackCol.visible && idleCollision && e.intersects(idleCollision)) {
			if (specialIdleActive) {
				handleEnemyHit(e, i, 'special_idle');
				continue;
			} else {
				storage.lastScore = score;
				LK.showGameOver();
			}
		}
	}
	for (var i = coins.length - 1; i >= 0; i--) {
		var coin = coins[i];
		if (!coin.collecting && Math.abs(coin.x - mouseX) < 32.5 && Math.abs(coin.y - mouseY) < 32.5) {
			coin.collecting = true;
			tween(coin, {
				x: scoreTxt.x,
				y: scoreTxt.y,
				alpha: 0
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					var index = coins.indexOf(coin);
					if (index !== -1) {
						coins.splice(index, 1);
					}
					if (coin.type === 'silver') {
						LK.getSound('silversnd').play();
						score += 5;
					} else if (coin.type === 'gold') {
						LK.getSound('goldsnd').play();
						score += 10;
					}
					updateScoreDisplay();
					coin.destroy();
				}
			});
		}
	}
	// Helmet HUD: No collision logic.
};
:quality(85)/https://cdn.frvr.ai/67f12d94a5275af3ed14c073.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f12ddfa5275af3ed14c076.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f12e1ea5275af3ed14c07c.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f16aeafea00654a40ebe8c.png%3F3) 
 high definition super nintendo background of a japanese sakura tree forest Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67f29c70a4d3a157fb76e528.png%3F3) 
 2d snes dust particle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67f29dbca4d3a157fb76e532.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f435bfc19c3cd96fa4998d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f43831c19c3cd96fa49a07.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f46f7fc19c3cd96fa49b41.png%3F3) 
 silver coin, $ sign on it, snes art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67f4702dc19c3cd96fa49b69.png%3F3) 
 gold coin, $ sign on it, snes art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67f6cac819e5cf7cc280518b.png%3F3) 
 snes white feather. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67f8221455d0d3e7a7c68d76.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f840d055d0d3e7a7c6931d.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f846d7d57fbf303fce936f.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f84a60d57fbf303fce93fe.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/67f85c027dff3a1a41deed3a.png%3F3) 
 add a wooden shield