/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Enemy attributes
	self.health = 100;
	self.maxHealth = 100;
	self.attackDamage = 10;
	self.attackRange = 150;
	self.attackCooldown = 0;
	self.maxAttackCooldown = 60; // frames
	self.moveSpeed = 3;
	self.isActive = true;
	// Visual representation
	var enemySprite = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Take damage method
	self.takeDamage = function (amount) {
		self.health -= amount;
		// Visual effect
		LK.effects.flashObject(self, 0xFF0000, 300);
		// Play hit sound
		LK.getSound('hit').play();
		// Check if enemy is dead
		if (self.health <= 0) {
			self.isActive = false;
			LK.getSound('enemy_die').play();
			// Death animation
			tween(self, {
				alpha: 0,
				scaleX: 0.5,
				scaleY: 0.5
			}, {
				duration: 500,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Remove from game
					self.destroy();
					// Increase score
					LK.setScore(LK.getScore() + 10);
					scoreTxt.setText(LK.getScore());
					// Find index and remove from array
					var index = enemies.indexOf(self);
					if (index !== -1) {
						enemies.splice(index, 1);
					}
				}
			});
		}
	};
	// Update method - called automatically every tick
	self.update = function () {
		if (!self.isActive) {
			return;
		}
		// Move towards player
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Move if not in attack range
		if (distance > self.attackRange) {
			var moveX = dx / distance * self.moveSpeed;
			self.x += moveX;
			// Keep on ground
			self.y = groundLevel - self.height / 2;
		} else {
			// Try to attack player if in range
			if (self.attackCooldown <= 0) {
				player.takeDamage(self.attackDamage);
				self.attackCooldown = self.maxAttackCooldown;
				// Attack animation
				tween(enemySprite, {
					scaleX: 1.3,
					scaleY: 1.3
				}, {
					duration: 200,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(enemySprite, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 200,
							easing: tween.easeIn
						});
					}
				});
			}
		}
		// Decrease attack cooldown
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
	};
	return self;
});
var Platform = Container.expand(function () {
	var self = Container.call(this);
	// Platform attributes
	self.isActive = true;
	// Visual representation
	var platformSprite = self.attachAsset('platform', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Check if player is on this platform
	self.checkCollision = function (playerObj) {
		if (!self.isActive) {
			return false;
		}
		// Basic platform collision detection
		var playerBottom = playerObj.y + playerObj.height / 2;
		var playerTop = playerObj.y - playerObj.height / 2;
		var playerLeft = playerObj.x - playerObj.width / 2;
		var playerRight = playerObj.x + playerObj.width / 2;
		var platformTop = self.y - self.height / 2;
		var platformBottom = self.y + self.height / 2;
		var platformLeft = self.x - self.width / 2;
		var platformRight = self.x + self.width / 2;
		// Check if player is falling onto platform
		if (playerObj.velocityY > 0 && playerBottom >= platformTop && playerTop < platformTop && playerRight > platformLeft && playerLeft < platformRight) {
			// Position player on top of platform
			playerObj.y = platformTop - playerObj.height / 2;
			playerObj.isJumping = false;
			playerObj.velocityY = 0;
			return true;
		}
		return false;
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Player attributes
	self.health = 100;
	self.maxHealth = 100;
	self.stance = 'swan'; // Default stance
	self.isAttacking = false;
	self.isJumping = false;
	self.velocityY = 0;
	self.gravity = 0.5;
	self.jumpPower = -15;
	self.moveSpeed = 10;
	// Stats per stance
	self.stanceData = {
		swan: {
			color: 0xFFFFFF,
			attackDamage: 20,
			attackRange: 150,
			attackSpeed: 1.0,
			moveSpeedMod: 1.2
		},
		crow: {
			color: 0x222222,
			attackDamage: 30,
			attackRange: 100,
			attackSpeed: 0.8,
			moveSpeedMod: 1.0
		},
		phoenix: {
			color: 0xFF3300,
			attackDamage: 40,
			attackRange: 80,
			attackSpeed: 0.6,
			moveSpeedMod: 0.8
		}
	};
	// Create all stance sprites but only show the current stance
	self.swanSprite = self.attachAsset('playerSwan', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: true
	});
	self.crowSprite = self.attachAsset('playerCrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	self.phoenixSprite = self.attachAsset('playerPhoenix', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Crack overlay for health visualization
	self.crackOverlay = self.attachAsset('crackOverlay', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	// Set hit area for touch detection
	self.width = 150;
	self.height = 200;
	// Movement control
	self.moveTo = function (x, y) {
		self.targetX = x;
	};
	// Jump method
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.velocityY = self.jumpPower;
		}
	};
	// Attack method
	self.attack = function () {
		if (!self.isAttacking) {
			self.isAttacking = true;
			// Different attack animation based on stance
			var stanceData = self.stanceData[self.stance];
			var attackDuration = 500 * (1 / stanceData.attackSpeed);
			// Get the current visible sprite
			var currentSprite;
			if (self.stance === 'swan') {
				currentSprite = self.swanSprite;
			} else if (self.stance === 'crow') {
				currentSprite = self.crowSprite;
			} else {
				currentSprite = self.phoenixSprite;
			}
			// Attack animation
			tween(currentSprite, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: attackDuration / 2,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(currentSprite, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: attackDuration / 2,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.isAttacking = false;
						}
					});
				}
			});
			// Create projectile based on stance
			var projectile = new Projectile(self.stance, stanceData.attackDamage);
			projectile.x = self.x;
			projectile.y = self.y;
			game.addChild(projectile);
			projectiles.push(projectile);
			// Play attack sound
			LK.getSound('attack').play();
			// Check for enemies in range
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var dx = enemy.x - self.x;
				var dy = enemy.y - self.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < stanceData.attackRange) {
					enemy.takeDamage(stanceData.attackDamage);
				}
			}
		}
	};
	// Switch stance method
	self.switchStance = function (newStance) {
		if (self.stance !== newStance) {
			self.stance = newStance;
			// Update visibility of sprites
			self.swanSprite.visible = newStance === 'swan';
			self.crowSprite.visible = newStance === 'crow';
			self.phoenixSprite.visible = newStance === 'phoenix';
			// Play stance change sound
			LK.getSound('stance_change').play();
			// Visual effect for stance change
			LK.effects.flashObject(self, self.stanceData[newStance].color, 500);
		}
	};
	// Take damage method
	self.takeDamage = function (amount) {
		self.health -= amount;
		if (self.health < 0) {
			self.health = 0;
		}
		// Update crack overlay based on health
		var crackAlpha = 1 - self.health / self.maxHealth;
		self.crackOverlay.alpha = crackAlpha;
		// Visual effect
		LK.effects.flashObject(self, 0xFF0000, 300);
		// Play hit sound
		LK.getSound('player_hit').play();
		// Check if player is dead
		if (self.health <= 0) {
			LK.showGameOver();
		}
	};
	// Update method - called automatically every tick
	self.update = function () {
		// Apply gravity
		if (self.isJumping) {
			self.velocityY += self.gravity;
			self.y += self.velocityY;
			// Check if landed on ground
			if (self.y >= groundLevel - self.height / 2) {
				self.y = groundLevel - self.height / 2;
				self.isJumping = false;
				self.velocityY = 0;
			}
		}
		// Move towards target if exists
		if (self.targetX !== undefined) {
			var moveSpeed = self.moveSpeed * self.stanceData[self.stance].moveSpeedMod;
			var dx = self.targetX - self.x;
			// If close enough to target, stop moving
			if (Math.abs(dx) < moveSpeed) {
				self.x = self.targetX;
				self.targetX = undefined;
			} else {
				// Move towards target
				self.x += dx > 0 ? moveSpeed : -moveSpeed;
			}
		}
		// Ensure player stays on screen
		if (self.x < self.width / 2) {
			self.x = self.width / 2;
		} else if (self.x > 2048 - self.width / 2) {
			self.x = 2048 - self.width / 2;
		}
	};
	// Touch event handlers
	self.down = function (x, y, obj) {
		// Check if the player should attack or jump
		if (y < self.y - self.height / 4) {
			self.jump();
		} else {
			self.attack();
		}
	};
	return self;
});
var Projectile = Container.expand(function (stanceType, damage) {
	var self = Container.call(this);
	// Projectile attributes
	self.type = stanceType || 'swan';
	self.damage = damage || 10;
	self.speed = 15;
	self.range = 500; // Max travel distance
	self.distanceTraveled = 0;
	self.isActive = true;
	// Color based on stance
	var colors = {
		swan: 0xFFFFFF,
		crow: 0x222222,
		phoenix: 0xFF3300
	};
	// Visual representation
	var projectileSprite = self.attachAsset('projectile', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: colors[self.type] || 0xFFFFFF
	});
	// Update method - called automatically every tick
	self.update = function () {
		if (!self.isActive) {
			return;
		}
		// Move forward
		self.x += self.speed;
		self.distanceTraveled += self.speed;
		// Check if out of range
		if (self.distanceTraveled >= self.range || self.x < 0 || self.x > 2048) {
			self.destroy();
			var index = projectiles.indexOf(self);
			if (index !== -1) {
				projectiles.splice(index, 1);
			}
			return;
		}
		// Check for collision with enemies
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (self.intersects(enemy) && enemy.isActive) {
				// Apply damage based on stance
				enemy.takeDamage(self.damage);
				// Destroy projectile
				self.destroy();
				var index = projectiles.indexOf(self);
				if (index !== -1) {
					projectiles.splice(index, 1);
				}
				break;
			}
		}
	};
	return self;
});
var StanceButton = Container.expand(function (stanceType) {
	var self = Container.call(this);
	// Button attributes
	self.type = stanceType;
	// Colors based on stance
	var colors = {
		swan: 0xFFFFFF,
		crow: 0x222222,
		phoenix: 0xFF3300
	};
	// Visual representation
	var buttonSprite = self.attachAsset(stanceType === 'swan' ? 'playerSwan' : stanceType === 'crow' ? 'playerCrow' : 'playerPhoenix', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Highlight when selected
	self.setSelected = function (isSelected) {
		if (isSelected) {
			tween(buttonSprite, {
				scaleX: 0.9,
				scaleY: 0.9
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		} else {
			tween(buttonSprite, {
				scaleX: 0.7,
				scaleY: 0.7
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
	};
	// Touch event handler
	self.down = function (x, y, obj) {
		// Switch player stance
		player.switchStance(self.type);
		// Update UI buttons
		updateStanceButtons();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x111827
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var enemies = [];
var platforms = [];
var projectiles = [];
var stanceButtons = {};
var groundLevel = 2500; // Y position of ground
var enemySpawnTimer = 0;
var maxEnemies = 5;
var gameStarted = false;
var difficultyLevel = 1;
var difficultyTimer = 0;
var maxDifficultyLevel = 10;
// Background
var background = game.addChild(LK.getAsset('background', {
	x: 0,
	y: 0,
	anchorX: 0,
	anchorY: 0
}));
// Initialize score display
var scoreTxt = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize health display
var healthTxt = new Text2('Health: 100%', {
	size: 80,
	fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(healthTxt);
// Create and position stance buttons
function createStanceButtons() {
	var stanceTypes = ['swan', 'crow', 'phoenix'];
	var buttonSpacing = 180;
	var startX = 2048 / 2 - (stanceTypes.length - 1) * buttonSpacing / 2;
	for (var i = 0; i < stanceTypes.length; i++) {
		var button = new StanceButton(stanceTypes[i]);
		button.x = startX + i * buttonSpacing;
		button.y = 2732 - 150;
		game.addChild(button);
		stanceButtons[stanceTypes[i]] = button;
	}
	// Set initial selection
	updateStanceButtons();
}
// Update stance button visuals
function updateStanceButtons() {
	for (var type in stanceButtons) {
		stanceButtons[type].setSelected(type === player.stance);
	}
}
// Create player
function createPlayer() {
	player = new Player();
	player.x = 2048 / 2;
	player.y = groundLevel - player.height / 2;
	game.addChild(player);
}
// Create enemy
function createEnemy() {
	var enemy = new Enemy();
	// Position enemy on edge of screen
	enemy.x = Math.random() < 0.5 ? 100 : 2048 - 100;
	enemy.y = groundLevel - enemy.height / 2;
	// Scale difficulty
	enemy.health = 50 + difficultyLevel * 10;
	enemy.maxHealth = enemy.health;
	enemy.attackDamage = 5 + difficultyLevel * 2;
	enemy.moveSpeed = 2 + difficultyLevel * 0.3;
	game.addChild(enemy);
	enemies.push(enemy);
}
// Create platforms
function createPlatforms() {
	var numPlatforms = 5;
	var platformWidth = 300;
	for (var i = 0; i < numPlatforms; i++) {
		var platform = new Platform();
		platform.x = 300 + i * 350;
		platform.y = groundLevel - 300 - i * 100;
		platform.width = platformWidth;
		platform.height = 50;
		game.addChild(platform);
		platforms.push(platform);
	}
}
// Initialize game
function initGame() {
	// Reset game state
	LK.setScore(0);
	enemies = [];
	platforms = [];
	projectiles = [];
	difficultyLevel = 1;
	difficultyTimer = 0;
	// Create player
	createPlayer();
	// Create platforms
	createPlatforms();
	// Create stance buttons
	createStanceButtons();
	// Start music
	LK.playMusic('ballet_theme');
	gameStarted = true;
}
// Event handlers
game.down = function (x, y, obj) {
	// Start game if not started
	if (!gameStarted) {
		initGame();
		return;
	}
	// Move player when clicking on game area (not on player or buttons)
	var isButtonClick = false;
	for (var type in stanceButtons) {
		if (stanceButtons[type].intersects({
			x: x,
			y: y
		})) {
			isButtonClick = true;
			break;
		}
	}
	if (!isButtonClick && !player.intersects({
		x: x,
		y: y
	})) {
		player.moveTo(x);
	}
};
// Game update loop
game.update = function () {
	if (!gameStarted) {
		// Show title screen if game not started
		if (!titleShown) {
			var titleText = new Text2('Ballet of Shadows', {
				size: 150,
				fill: 0xFFFFFF
			});
			titleText.anchor.set(0.5, 0.5);
			titleText.x = 2048 / 2;
			titleText.y = 2732 / 2 - 200;
			game.addChild(titleText);
			var startText = new Text2('Tap to Begin', {
				size: 100,
				fill: 0xAAAAAA
			});
			startText.anchor.set(0.5, 0.5);
			startText.x = 2048 / 2;
			startText.y = 2732 / 2 + 200;
			game.addChild(startText);
			titleShown = true;
		}
		return;
	}
	// Update health display
	healthTxt.setText('Health: ' + player.health + '%');
	// Spawn enemies on timer
	enemySpawnTimer++;
	if (enemySpawnTimer >= 120 && enemies.length < maxEnemies) {
		// Every 2 seconds (120 frames at 60fps)
		createEnemy();
		enemySpawnTimer = 0;
	}
	// Increase difficulty over time
	difficultyTimer++;
	if (difficultyTimer >= 1800 && difficultyLevel < maxDifficultyLevel) {
		// Every 30 seconds
		difficultyLevel++;
		difficultyTimer = 0;
		// Increase max enemies based on difficulty
		maxEnemies = 5 + Math.floor(difficultyLevel / 2);
	}
	// Platform collision detection
	if (player.isJumping) {
		for (var i = 0; i < platforms.length; i++) {
			platforms[i].checkCollision(player);
		}
	}
	// Check for game win condition (example: score 1000)
	if (LK.getScore() >= 1000) {
		LK.showYouWin();
	}
};
// Start with title screen
var titleShown = false;
// Play background music
LK.playMusic('ballet_theme', {
	fade: {
		start: 0,
		end: 0.8,
		duration: 1000
	}
}); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	// Enemy attributes
	self.health = 100;
	self.maxHealth = 100;
	self.attackDamage = 10;
	self.attackRange = 150;
	self.attackCooldown = 0;
	self.maxAttackCooldown = 60; // frames
	self.moveSpeed = 3;
	self.isActive = true;
	// Visual representation
	var enemySprite = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Take damage method
	self.takeDamage = function (amount) {
		self.health -= amount;
		// Visual effect
		LK.effects.flashObject(self, 0xFF0000, 300);
		// Play hit sound
		LK.getSound('hit').play();
		// Check if enemy is dead
		if (self.health <= 0) {
			self.isActive = false;
			LK.getSound('enemy_die').play();
			// Death animation
			tween(self, {
				alpha: 0,
				scaleX: 0.5,
				scaleY: 0.5
			}, {
				duration: 500,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Remove from game
					self.destroy();
					// Increase score
					LK.setScore(LK.getScore() + 10);
					scoreTxt.setText(LK.getScore());
					// Find index and remove from array
					var index = enemies.indexOf(self);
					if (index !== -1) {
						enemies.splice(index, 1);
					}
				}
			});
		}
	};
	// Update method - called automatically every tick
	self.update = function () {
		if (!self.isActive) {
			return;
		}
		// Move towards player
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		// Move if not in attack range
		if (distance > self.attackRange) {
			var moveX = dx / distance * self.moveSpeed;
			self.x += moveX;
			// Keep on ground
			self.y = groundLevel - self.height / 2;
		} else {
			// Try to attack player if in range
			if (self.attackCooldown <= 0) {
				player.takeDamage(self.attackDamage);
				self.attackCooldown = self.maxAttackCooldown;
				// Attack animation
				tween(enemySprite, {
					scaleX: 1.3,
					scaleY: 1.3
				}, {
					duration: 200,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(enemySprite, {
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 200,
							easing: tween.easeIn
						});
					}
				});
			}
		}
		// Decrease attack cooldown
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
	};
	return self;
});
var Platform = Container.expand(function () {
	var self = Container.call(this);
	// Platform attributes
	self.isActive = true;
	// Visual representation
	var platformSprite = self.attachAsset('platform', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Check if player is on this platform
	self.checkCollision = function (playerObj) {
		if (!self.isActive) {
			return false;
		}
		// Basic platform collision detection
		var playerBottom = playerObj.y + playerObj.height / 2;
		var playerTop = playerObj.y - playerObj.height / 2;
		var playerLeft = playerObj.x - playerObj.width / 2;
		var playerRight = playerObj.x + playerObj.width / 2;
		var platformTop = self.y - self.height / 2;
		var platformBottom = self.y + self.height / 2;
		var platformLeft = self.x - self.width / 2;
		var platformRight = self.x + self.width / 2;
		// Check if player is falling onto platform
		if (playerObj.velocityY > 0 && playerBottom >= platformTop && playerTop < platformTop && playerRight > platformLeft && playerLeft < platformRight) {
			// Position player on top of platform
			playerObj.y = platformTop - playerObj.height / 2;
			playerObj.isJumping = false;
			playerObj.velocityY = 0;
			return true;
		}
		return false;
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	// Player attributes
	self.health = 100;
	self.maxHealth = 100;
	self.stance = 'swan'; // Default stance
	self.isAttacking = false;
	self.isJumping = false;
	self.velocityY = 0;
	self.gravity = 0.5;
	self.jumpPower = -15;
	self.moveSpeed = 10;
	// Stats per stance
	self.stanceData = {
		swan: {
			color: 0xFFFFFF,
			attackDamage: 20,
			attackRange: 150,
			attackSpeed: 1.0,
			moveSpeedMod: 1.2
		},
		crow: {
			color: 0x222222,
			attackDamage: 30,
			attackRange: 100,
			attackSpeed: 0.8,
			moveSpeedMod: 1.0
		},
		phoenix: {
			color: 0xFF3300,
			attackDamage: 40,
			attackRange: 80,
			attackSpeed: 0.6,
			moveSpeedMod: 0.8
		}
	};
	// Create all stance sprites but only show the current stance
	self.swanSprite = self.attachAsset('playerSwan', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: true
	});
	self.crowSprite = self.attachAsset('playerCrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	self.phoenixSprite = self.attachAsset('playerPhoenix', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Crack overlay for health visualization
	self.crackOverlay = self.attachAsset('crackOverlay', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0
	});
	// Set hit area for touch detection
	self.width = 150;
	self.height = 200;
	// Movement control
	self.moveTo = function (x, y) {
		self.targetX = x;
	};
	// Jump method
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.velocityY = self.jumpPower;
		}
	};
	// Attack method
	self.attack = function () {
		if (!self.isAttacking) {
			self.isAttacking = true;
			// Different attack animation based on stance
			var stanceData = self.stanceData[self.stance];
			var attackDuration = 500 * (1 / stanceData.attackSpeed);
			// Get the current visible sprite
			var currentSprite;
			if (self.stance === 'swan') {
				currentSprite = self.swanSprite;
			} else if (self.stance === 'crow') {
				currentSprite = self.crowSprite;
			} else {
				currentSprite = self.phoenixSprite;
			}
			// Attack animation
			tween(currentSprite, {
				scaleX: 1.3,
				scaleY: 1.3
			}, {
				duration: attackDuration / 2,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(currentSprite, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: attackDuration / 2,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.isAttacking = false;
						}
					});
				}
			});
			// Create projectile based on stance
			var projectile = new Projectile(self.stance, stanceData.attackDamage);
			projectile.x = self.x;
			projectile.y = self.y;
			game.addChild(projectile);
			projectiles.push(projectile);
			// Play attack sound
			LK.getSound('attack').play();
			// Check for enemies in range
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var dx = enemy.x - self.x;
				var dy = enemy.y - self.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				if (distance < stanceData.attackRange) {
					enemy.takeDamage(stanceData.attackDamage);
				}
			}
		}
	};
	// Switch stance method
	self.switchStance = function (newStance) {
		if (self.stance !== newStance) {
			self.stance = newStance;
			// Update visibility of sprites
			self.swanSprite.visible = newStance === 'swan';
			self.crowSprite.visible = newStance === 'crow';
			self.phoenixSprite.visible = newStance === 'phoenix';
			// Play stance change sound
			LK.getSound('stance_change').play();
			// Visual effect for stance change
			LK.effects.flashObject(self, self.stanceData[newStance].color, 500);
		}
	};
	// Take damage method
	self.takeDamage = function (amount) {
		self.health -= amount;
		if (self.health < 0) {
			self.health = 0;
		}
		// Update crack overlay based on health
		var crackAlpha = 1 - self.health / self.maxHealth;
		self.crackOverlay.alpha = crackAlpha;
		// Visual effect
		LK.effects.flashObject(self, 0xFF0000, 300);
		// Play hit sound
		LK.getSound('player_hit').play();
		// Check if player is dead
		if (self.health <= 0) {
			LK.showGameOver();
		}
	};
	// Update method - called automatically every tick
	self.update = function () {
		// Apply gravity
		if (self.isJumping) {
			self.velocityY += self.gravity;
			self.y += self.velocityY;
			// Check if landed on ground
			if (self.y >= groundLevel - self.height / 2) {
				self.y = groundLevel - self.height / 2;
				self.isJumping = false;
				self.velocityY = 0;
			}
		}
		// Move towards target if exists
		if (self.targetX !== undefined) {
			var moveSpeed = self.moveSpeed * self.stanceData[self.stance].moveSpeedMod;
			var dx = self.targetX - self.x;
			// If close enough to target, stop moving
			if (Math.abs(dx) < moveSpeed) {
				self.x = self.targetX;
				self.targetX = undefined;
			} else {
				// Move towards target
				self.x += dx > 0 ? moveSpeed : -moveSpeed;
			}
		}
		// Ensure player stays on screen
		if (self.x < self.width / 2) {
			self.x = self.width / 2;
		} else if (self.x > 2048 - self.width / 2) {
			self.x = 2048 - self.width / 2;
		}
	};
	// Touch event handlers
	self.down = function (x, y, obj) {
		// Check if the player should attack or jump
		if (y < self.y - self.height / 4) {
			self.jump();
		} else {
			self.attack();
		}
	};
	return self;
});
var Projectile = Container.expand(function (stanceType, damage) {
	var self = Container.call(this);
	// Projectile attributes
	self.type = stanceType || 'swan';
	self.damage = damage || 10;
	self.speed = 15;
	self.range = 500; // Max travel distance
	self.distanceTraveled = 0;
	self.isActive = true;
	// Color based on stance
	var colors = {
		swan: 0xFFFFFF,
		crow: 0x222222,
		phoenix: 0xFF3300
	};
	// Visual representation
	var projectileSprite = self.attachAsset('projectile', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: colors[self.type] || 0xFFFFFF
	});
	// Update method - called automatically every tick
	self.update = function () {
		if (!self.isActive) {
			return;
		}
		// Move forward
		self.x += self.speed;
		self.distanceTraveled += self.speed;
		// Check if out of range
		if (self.distanceTraveled >= self.range || self.x < 0 || self.x > 2048) {
			self.destroy();
			var index = projectiles.indexOf(self);
			if (index !== -1) {
				projectiles.splice(index, 1);
			}
			return;
		}
		// Check for collision with enemies
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (self.intersects(enemy) && enemy.isActive) {
				// Apply damage based on stance
				enemy.takeDamage(self.damage);
				// Destroy projectile
				self.destroy();
				var index = projectiles.indexOf(self);
				if (index !== -1) {
					projectiles.splice(index, 1);
				}
				break;
			}
		}
	};
	return self;
});
var StanceButton = Container.expand(function (stanceType) {
	var self = Container.call(this);
	// Button attributes
	self.type = stanceType;
	// Colors based on stance
	var colors = {
		swan: 0xFFFFFF,
		crow: 0x222222,
		phoenix: 0xFF3300
	};
	// Visual representation
	var buttonSprite = self.attachAsset(stanceType === 'swan' ? 'playerSwan' : stanceType === 'crow' ? 'playerCrow' : 'playerPhoenix', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.7,
		scaleY: 0.7
	});
	// Highlight when selected
	self.setSelected = function (isSelected) {
		if (isSelected) {
			tween(buttonSprite, {
				scaleX: 0.9,
				scaleY: 0.9
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		} else {
			tween(buttonSprite, {
				scaleX: 0.7,
				scaleY: 0.7
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
	};
	// Touch event handler
	self.down = function (x, y, obj) {
		// Switch player stance
		player.switchStance(self.type);
		// Update UI buttons
		updateStanceButtons();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x111827
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var enemies = [];
var platforms = [];
var projectiles = [];
var stanceButtons = {};
var groundLevel = 2500; // Y position of ground
var enemySpawnTimer = 0;
var maxEnemies = 5;
var gameStarted = false;
var difficultyLevel = 1;
var difficultyTimer = 0;
var maxDifficultyLevel = 10;
// Background
var background = game.addChild(LK.getAsset('background', {
	x: 0,
	y: 0,
	anchorX: 0,
	anchorY: 0
}));
// Initialize score display
var scoreTxt = new Text2('0', {
	size: 100,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize health display
var healthTxt = new Text2('Health: 100%', {
	size: 80,
	fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(healthTxt);
// Create and position stance buttons
function createStanceButtons() {
	var stanceTypes = ['swan', 'crow', 'phoenix'];
	var buttonSpacing = 180;
	var startX = 2048 / 2 - (stanceTypes.length - 1) * buttonSpacing / 2;
	for (var i = 0; i < stanceTypes.length; i++) {
		var button = new StanceButton(stanceTypes[i]);
		button.x = startX + i * buttonSpacing;
		button.y = 2732 - 150;
		game.addChild(button);
		stanceButtons[stanceTypes[i]] = button;
	}
	// Set initial selection
	updateStanceButtons();
}
// Update stance button visuals
function updateStanceButtons() {
	for (var type in stanceButtons) {
		stanceButtons[type].setSelected(type === player.stance);
	}
}
// Create player
function createPlayer() {
	player = new Player();
	player.x = 2048 / 2;
	player.y = groundLevel - player.height / 2;
	game.addChild(player);
}
// Create enemy
function createEnemy() {
	var enemy = new Enemy();
	// Position enemy on edge of screen
	enemy.x = Math.random() < 0.5 ? 100 : 2048 - 100;
	enemy.y = groundLevel - enemy.height / 2;
	// Scale difficulty
	enemy.health = 50 + difficultyLevel * 10;
	enemy.maxHealth = enemy.health;
	enemy.attackDamage = 5 + difficultyLevel * 2;
	enemy.moveSpeed = 2 + difficultyLevel * 0.3;
	game.addChild(enemy);
	enemies.push(enemy);
}
// Create platforms
function createPlatforms() {
	var numPlatforms = 5;
	var platformWidth = 300;
	for (var i = 0; i < numPlatforms; i++) {
		var platform = new Platform();
		platform.x = 300 + i * 350;
		platform.y = groundLevel - 300 - i * 100;
		platform.width = platformWidth;
		platform.height = 50;
		game.addChild(platform);
		platforms.push(platform);
	}
}
// Initialize game
function initGame() {
	// Reset game state
	LK.setScore(0);
	enemies = [];
	platforms = [];
	projectiles = [];
	difficultyLevel = 1;
	difficultyTimer = 0;
	// Create player
	createPlayer();
	// Create platforms
	createPlatforms();
	// Create stance buttons
	createStanceButtons();
	// Start music
	LK.playMusic('ballet_theme');
	gameStarted = true;
}
// Event handlers
game.down = function (x, y, obj) {
	// Start game if not started
	if (!gameStarted) {
		initGame();
		return;
	}
	// Move player when clicking on game area (not on player or buttons)
	var isButtonClick = false;
	for (var type in stanceButtons) {
		if (stanceButtons[type].intersects({
			x: x,
			y: y
		})) {
			isButtonClick = true;
			break;
		}
	}
	if (!isButtonClick && !player.intersects({
		x: x,
		y: y
	})) {
		player.moveTo(x);
	}
};
// Game update loop
game.update = function () {
	if (!gameStarted) {
		// Show title screen if game not started
		if (!titleShown) {
			var titleText = new Text2('Ballet of Shadows', {
				size: 150,
				fill: 0xFFFFFF
			});
			titleText.anchor.set(0.5, 0.5);
			titleText.x = 2048 / 2;
			titleText.y = 2732 / 2 - 200;
			game.addChild(titleText);
			var startText = new Text2('Tap to Begin', {
				size: 100,
				fill: 0xAAAAAA
			});
			startText.anchor.set(0.5, 0.5);
			startText.x = 2048 / 2;
			startText.y = 2732 / 2 + 200;
			game.addChild(startText);
			titleShown = true;
		}
		return;
	}
	// Update health display
	healthTxt.setText('Health: ' + player.health + '%');
	// Spawn enemies on timer
	enemySpawnTimer++;
	if (enemySpawnTimer >= 120 && enemies.length < maxEnemies) {
		// Every 2 seconds (120 frames at 60fps)
		createEnemy();
		enemySpawnTimer = 0;
	}
	// Increase difficulty over time
	difficultyTimer++;
	if (difficultyTimer >= 1800 && difficultyLevel < maxDifficultyLevel) {
		// Every 30 seconds
		difficultyLevel++;
		difficultyTimer = 0;
		// Increase max enemies based on difficulty
		maxEnemies = 5 + Math.floor(difficultyLevel / 2);
	}
	// Platform collision detection
	if (player.isJumping) {
		for (var i = 0; i < platforms.length; i++) {
			platforms[i].checkCollision(player);
		}
	}
	// Check for game win condition (example: score 1000)
	if (LK.getScore() >= 1000) {
		LK.showYouWin();
	}
};
// Start with title screen
var titleShown = false;
// Play background music
LK.playMusic('ballet_theme', {
	fade: {
		start: 0,
		end: 0.8,
		duration: 1000
	}
});