/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Enemy = Container.expand(function (type) {
	var self = Container.call(this);
	var assetName = type === 'armored' ? 'armoredEnemy' : type === 'shooting' ? 'shootingEnemy' : 'basicEnemy';
	var enemyGraphics = self.attachAsset(assetName, {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.type = type || 'basic';
	self.speed = type === 'armored' ? -3 : type === 'shooting' ? -2 : -4;
	self.maxHealth = type === 'shooting' ? 2 : 1;
	self.health = self.maxHealth;
	self.damage = type === 'armored' ? 30 : type === 'shooting' ? 25 : 20;
	self.points = type === 'armored' ? 30 : type === 'shooting' ? 25 : 10;
	// Direction tracking for all enemy types
	self.direction = self.speed > 0 ? 1 : -1; // Track current direction for all enemies
	self.lastDirection = self.direction; // Track last direction to detect changes
	// Armored enemy movement properties
	if (type === 'armored') {
		self.baseSpeed = Math.abs(self.speed); // Store base speed value
		self.direction = self.speed > 0 ? 1 : -1; // Track current direction
		self.lastX = 0; // Track last position for direction changes
		self.directionChangeTimer = 0;
		self.directionChangeInterval = 120 + Math.random() * 120; // Random interval 2-4 seconds
	}
	// Shooting properties for shooting enemies
	if (type === 'shooting') {
		self.shootTimer = 0;
		self.shootInterval = 60; // Shoot every 1 second (60 frames at 60fps)
		self.bulletsShot = 0; // Track number of bullets fired
		self.maxBullets = 1; // Maximum bullets this enemy can shoot - only one bullet per enemy
		self.shoot = function () {
			// Check if enemy has bullets remaining
			if (self.bulletsShot >= self.maxBullets) {
				return; // Don't shoot if limit reached
			}
			// Determine direction to shoot towards player
			var direction = player.x > self.x ? 1 : -1;
			var bullet = game.addChild(new EnemyBullet(direction));
			bullet.x = self.x;
			bullet.y = self.y - 40;
			enemyBullets.push(bullet);
			self.bulletsShot++; // Increment bullet count
		};
	}
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 200);
		LK.getSound('enemyHit').play();
		if (self.health <= 0) {
			// Create main explosion effect
			var explosionEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			explosionEffect.x = self.x;
			explosionEffect.y = self.y - 40;
			explosionEffect.tint = 0xff4500; // Orange explosion color
			explosionEffect.alpha = 0.9;
			explosionEffect.scaleX = 0.5;
			explosionEffect.scaleY = 0.5;
			// Animate main explosion effect
			tween(explosionEffect, {
				scaleX: 3.0,
				scaleY: 3.0,
				alpha: 0
			}, {
				duration: 400,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					explosionEffect.destroy();
				}
			});
			// Create fragmented explosion pieces
			var fragmentCount = 6 + Math.floor(Math.random() * 4); // 6-9 fragments
			for (var f = 0; f < fragmentCount; f++) {
				var fragment = game.addChild(LK.getAsset(assetName, {
					anchorX: 0.5,
					anchorY: 0.5
				}));
				fragment.x = self.x;
				fragment.y = self.y - 40;
				fragment.tint = 0xff6600; // Darker orange for fragments
				fragment.alpha = 0.8;
				fragment.scaleX = 0.3 + Math.random() * 0.4; // Random size 0.3-0.7
				fragment.scaleY = 0.3 + Math.random() * 0.4;
				fragment.rotation = Math.random() * Math.PI * 2; // Random rotation
				// Calculate random scatter direction
				var angle = Math.PI * 2 / fragmentCount * f + (Math.random() - 0.5) * 0.8;
				var velocity = 150 + Math.random() * 100; // Random velocity 150-250
				var targetX = fragment.x + Math.cos(angle) * velocity;
				var targetY = fragment.y + Math.sin(angle) * velocity;
				// Animate fragment scatter with rotation and fade
				tween(fragment, {
					x: targetX,
					y: targetY,
					rotation: fragment.rotation + (Math.random() - 0.5) * Math.PI * 4,
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 600 + Math.random() * 400,
					// Random duration 600-1000ms
					easing: tween.easeOut,
					onFinish: function onFinish() {
						fragment.destroy();
					}
				});
			}
			// Award points
			LK.setScore(LK.getScore() + self.points);
			// Chance to drop power-up
			if (Math.random() < 0.15) {
				var powerUp = game.addChild(new PowerUp());
				powerUp.x = self.x;
				powerUp.y = self.y - 20;
				powerUps.push(powerUp);
			}
			// Remove from enemies array
			var index = enemies.indexOf(self);
			if (index > -1) {
				enemies.splice(index, 1);
			}
			self.destroy();
		}
	};
	// Initialize jumping properties
	self.baseY = 0;
	self.isJumping = false;
	self.jumpTimer = 0;
	self.jumpInterval = 150 + Math.random() * 90; // Random jump interval between 2.5-4 seconds for long jumps
	self.startJump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.baseY = self.y;
			var baseX = self.x;
			var jumpDistance = 200 + Math.random() * 150; // Long horizontal jump 200-350 pixels
			var jumpHeight = 120 + Math.random() * 80; // Higher jump 120-200 pixels
			// Jump direction based on movement direction
			var jumpDirectionX = self.speed > 0 ? jumpDistance : -jumpDistance;
			// Long jump with arc motion - jump up and forward
			tween(self, {
				y: self.baseY - jumpHeight,
				x: baseX + jumpDirectionX
			}, {
				duration: 800,
				// Longer duration for long jump
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Fall back down while continuing forward motion
					tween(self, {
						y: self.baseY
					}, {
						duration: 600,
						easing: tween.bounceOut,
						onFinish: function onFinish() {
							self.isJumping = false;
						}
					});
				}
			});
		}
	};
	self.update = function () {
		// Handle armored enemy direction changes
		if (self.type === 'armored') {
			// Initialize lastX if not set
			if (self.lastX === 0) self.lastX = self.x;
			// Check for screen boundaries and change direction
			if (self.x <= 100 && self.direction === -1 || self.x >= 1948 && self.direction === 1) {
				self.direction *= -1; // Reverse direction
				self.speed = self.baseSpeed * self.direction;
			}
			// Random direction changes
			self.directionChangeTimer++;
			if (self.directionChangeTimer >= self.directionChangeInterval) {
				self.direction *= -1; // Reverse direction
				self.speed = self.baseSpeed * self.direction;
				self.directionChangeTimer = 0;
				self.directionChangeInterval = 120 + Math.random() * 120; // Reset random interval
			}
			// Update lastX
			self.lastX = self.x;
		}
		// Update direction based on speed for all enemy types (including armored)
		self.direction = self.speed > 0 ? 1 : -1;
		// Flip enemy image based on screen position for all enemy types
		var targetScale;
		if (self.x < 1024) {
			// Left half of screen (2048/2 = 1024)
			targetScale = -1; // Face left
		} else {
			// Right half of screen
			targetScale = 1; // Face right
		}
		// Only animate if the scale needs to change
		if (enemyGraphics.scaleX !== targetScale) {
			tween(enemyGraphics, {
				scaleX: targetScale
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		self.x += self.speed;
		// Handle jumping
		self.jumpTimer++;
		if (self.jumpTimer >= self.jumpInterval && !self.isJumping) {
			self.startJump();
			self.jumpTimer = 0;
			self.jumpInterval = 150 + Math.random() * 90; // Reset random interval for long jumps
		}
		// Handle shooting for shooting enemies
		if (self.type === 'shooting') {
			self.shootTimer++;
			if (self.shootTimer >= self.shootInterval && self.bulletsShot < self.maxBullets) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
		// Check collision with player
		if (self.intersects(player) && !player.invulnerable) {
			player.takeDamage(self.damage);
		}
	};
	return self;
});
var EnemyBullet = Container.expand(function (direction) {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.damage = 15;
	self.direction = direction || 1; // 1 for right, -1 for left
	self.update = function () {
		self.x += self.speed * self.direction;
		// Check collision with player
		if (self.intersects(player) && !player.invulnerable) {
			player.takeDamage(self.damage);
			// Remove from enemyBullets array
			var index = enemyBullets.indexOf(self);
			if (index > -1) {
				enemyBullets.splice(index, 1);
			}
			self.destroy();
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.slashDamage = 1;
	self.slashRange = 150;
	self.isSlashing = false;
	self.slashCooldown = 0;
	self.isDashing = false;
	self.dashCooldown = 0;
	self.dashDistance = 200;
	self.dashDuration = 300;
	self.invulnerable = false;
	self.invulnerabilityTime = 0;
	self.facingDirection = 1; // 1 for right, -1 for left
	self.isJumping = false;
	self.baseY = 0;
	self.dashSlash = function () {
		if (self.slashCooldown <= 0 && self.dashCooldown <= 0 && !self.isSlashing && !self.isDashing) {
			self.isDashing = true;
			self.isSlashing = true;
			self.slashCooldown = 60; // 1 second cooldown
			self.dashCooldown = 60;
			var startX = self.x;
			var dashTargetX = self.facingDirection > 0 ? Math.min(startX + self.dashDistance, 2048 - 40) : Math.max(startX - self.dashDistance, 40);
			// Dash forward with tween
			tween(self, {
				x: dashTargetX
			}, {
				duration: self.dashDuration,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					self.isDashing = false;
				}
			});
			// Create extended slash effect during dash
			var slashEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			slashEffect.x = self.x + 75 * self.facingDirection;
			slashEffect.y = self.y - 60;
			slashEffect.alpha = 0.9;
			slashEffect.scaleX = 2.0 * self.facingDirection;
			slashEffect.scaleY = 1.5;
			// Follow player during dash
			var slashFollowInterval = LK.setInterval(function () {
				if (self.isDashing) {
					slashEffect.x = self.x + 75 * self.facingDirection;
				}
			}, 16);
			// Animate slash effect
			tween(slashEffect, {
				scaleX: 2.5,
				scaleY: 2.0,
				alpha: 0
			}, {
				duration: self.dashDuration,
				onFinish: function onFinish() {
					LK.clearInterval(slashFollowInterval);
					slashEffect.destroy();
				}
			});
			LK.getSound('slash').play();
			// Extended damage check during dash
			var damageCheckInterval = LK.setInterval(function () {
				if (self.isDashing) {
					for (var i = 0; i < enemies.length; i++) {
						var enemy = enemies[i];
						var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
						var enemyInFront = self.facingDirection > 0 ? enemy.x > self.x - 50 && enemy.x < self.x + 150 : enemy.x < self.x + 50 && enemy.x > self.x - 150;
						if (distance < self.slashRange * 1.5 && enemyInFront) {
							enemy.takeDamage(self.slashDamage * 2); // Double damage during dash
						}
					}
					// Check for enemy bullet hits during dash
					for (var j = enemyBullets.length - 1; j >= 0; j--) {
						var bullet = enemyBullets[j];
						var bulletDistance = Math.sqrt(Math.pow(bullet.x - self.x, 2) + Math.pow(bullet.y - self.y, 2));
						var bulletInFront = self.facingDirection > 0 ? bullet.x > self.x - 50 && bullet.x < self.x + 150 : bullet.x < self.x + 50 && bullet.x > self.x - 150;
						if (bulletDistance < self.slashRange * 1.5 && bulletInFront) {
							// Destroy the bullet
							bullet.destroy();
							enemyBullets.splice(j, 1);
							// Award small points for destroying bullets
							LK.setScore(LK.getScore() + 5);
						}
					}
				}
			}, 30);
			LK.setTimeout(function () {
				LK.clearInterval(damageCheckInterval);
				self.isSlashing = false;
			}, self.dashDuration);
		}
	};
	self.slash = function () {
		if (self.slashCooldown <= 0 && !self.isSlashing && !self.isDashing) {
			self.isSlashing = true;
			self.slashCooldown = 20; // 1/3 second at 60fps
			// Create slash effect
			var slashEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			slashEffect.x = self.x + 75 * self.facingDirection;
			slashEffect.y = self.y - 60;
			slashEffect.alpha = 0.8;
			slashEffect.scaleX = self.facingDirection;
			// Animate slash effect
			tween(slashEffect, {
				scaleX: 1.5,
				scaleY: 1.5,
				alpha: 0
			}, {
				duration: 200,
				onFinish: function onFinish() {
					slashEffect.destroy();
				}
			});
			LK.getSound('slash').play();
			// Check for enemy hits
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
				var enemyInRange = self.facingDirection > 0 ? enemy.x > self.x - 50 && enemy.x < self.x + self.slashRange : enemy.x < self.x + 50 && enemy.x > self.x - self.slashRange;
				if (distance < self.slashRange && enemyInRange) {
					enemy.takeDamage(self.slashDamage);
				}
			}
			// Check for enemy bullet hits
			for (var j = enemyBullets.length - 1; j >= 0; j--) {
				var bullet = enemyBullets[j];
				var bulletDistance = Math.sqrt(Math.pow(bullet.x - self.x, 2) + Math.pow(bullet.y - self.y, 2));
				var bulletInRange = self.facingDirection > 0 ? bullet.x > self.x - 50 && bullet.x < self.x + self.slashRange : bullet.x < self.x + 50 && bullet.x > self.x - self.slashRange;
				if (bulletDistance < self.slashRange && bulletInRange) {
					// Destroy the bullet
					bullet.destroy();
					enemyBullets.splice(j, 1);
					// Award small points for destroying bullets
					LK.setScore(LK.getScore() + 5);
				}
			}
			LK.setTimeout(function () {
				self.isSlashing = false;
			}, 200);
		}
	};
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.baseY = self.y;
			var jumpHeight = 200; // Jump height in pixels
			// Jump up with tween
			tween(self, {
				y: self.baseY - jumpHeight
			}, {
				duration: 400,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Fall back down
					tween(self, {
						y: self.baseY
					}, {
						duration: 400,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.isJumping = false;
						}
					});
				}
			});
		}
	};
	self.takeDamage = function (damage) {
		if (!self.invulnerable) {
			self.health -= damage;
			self.invulnerable = true;
			self.invulnerabilityTime = 120; // 2 seconds at 60fps
			// Flash effect
			LK.effects.flashObject(self, 0xff0000, 500);
			if (self.health <= 0) {
				self.health = 0;
				LK.showGameOver();
			}
		}
	};
	self.update = function () {
		// Update player image direction based on facing direction
		playerGraphics.scaleX = self.facingDirection;
		if (self.slashCooldown > 0) {
			self.slashCooldown--;
		}
		if (self.dashCooldown > 0) {
			self.dashCooldown--;
		}
		if (self.invulnerabilityTime > 0) {
			self.invulnerabilityTime--;
			if (self.invulnerabilityTime <= 0) {
				self.invulnerable = false;
			}
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -2;
	self.bobOffset = 0;
	self.update = function () {
		self.x += self.speed;
		self.bobOffset += 0.1;
		self.y += Math.sin(self.bobOffset) * 0.5;
		// Check collision with player
		if (self.intersects(player)) {
			self.collect();
		}
	};
	self.collect = function () {
		LK.getSound('powerUpSound').play();
		// Random power-up effect
		var powerType = Math.floor(Math.random() * 3);
		switch (powerType) {
			case 0:
				// Increased damage
				player.slashDamage += 1;
				break;
			case 1:
				// Wider slash range
				player.slashRange += 50;
				break;
			case 2:
				// Temporary invincibility
				player.invulnerable = true;
				player.invulnerabilityTime = 300; // 5 seconds
				break;
		}
		// Remove from powerUps array
		var index = powerUps.indexOf(self);
		if (index > -1) {
			powerUps.splice(index, 1);
		}
		self.destroy();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var enemies = [];
var powerUps = [];
var enemyBullets = [];
var enemySpawnTimer = 0;
var enemySpawnRate = 180; // Start spawning every 3 seconds
var gameTime = 0;
var healthBar;
var healthBarBg;
// Create UI elements
var scoreTxt = new Text2('Score: 0', {
	size: 60,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
// Create health bar background
healthBarBg = game.addChild(LK.getAsset('healthBarBg', {
	anchorX: 0,
	anchorY: 0
}));
healthBarBg.x = 120;
healthBarBg.y = 120;
// Create health bar
healthBar = game.addChild(LK.getAsset('healthBar', {
	anchorX: 0,
	anchorY: 0
}));
healthBar.x = 122;
healthBar.y = 122;
// Create health text
var healthTxt = new Text2('Health', {
	size: 40,
	fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 160;
game.addChild(healthTxt);
// Create background
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0
}));
background.x = 0;
background.y = 0;
// Create player
player = game.addChild(new Player());
player.x = 300;
player.y = 2732 - 150; // Near bottom of screen
// Start background music
LK.playMusic('bgmusic');
// Touch controls for movement and slashing
var isDragging = false;
var lastTouchX = 0;
var lastTouchY = 0;
var swipeThreshold = 100; // Minimum distance for swipe detection
game.down = function (x, y, obj) {
	isDragging = true;
	lastTouchX = x;
	lastTouchY = y;
	// Set facing direction based on touch position relative to player
	if (x < player.x) {
		player.facingDirection = -1; // Face left
	} else {
		player.facingDirection = 1; // Face right
	}
	player.dashSlash();
};
game.move = function (x, y, obj) {
	if (isDragging) {
		var deltaX = x - lastTouchX;
		player.x += deltaX * 0.5; // Smooth movement multiplier
		// Keep player within screen bounds
		if (player.x < 40) player.x = 40;
		if (player.x > 2048 - 40) player.x = 2048 - 40;
		lastTouchX = x;
	}
};
game.up = function (x, y, obj) {
	if (isDragging) {
		var deltaY = lastTouchY - y; // Upward swipe has positive deltaY
		var deltaX = Math.abs(x - lastTouchX);
		// Check for upward swipe (vertical movement greater than horizontal and above threshold)
		if (deltaY > swipeThreshold && deltaY > deltaX) {
			player.jump();
		}
	}
	isDragging = false;
};
// Spawn enemies
function spawnEnemy() {
	var rand = Math.random();
	var enemyType = rand < 0.5 ? 'basic' : rand < 0.8 ? 'armored' : 'shooting';
	var enemy = game.addChild(new Enemy(enemyType));
	// Randomly spawn from left or right
	var spawnFromRight = Math.random() < 0.5;
	if (spawnFromRight) {
		enemy.x = 2048 + 100; // Start off-screen right
		enemy.speed = enemy.type === 'armored' ? -3 : enemy.type === 'shooting' ? -2 : -4; // Move left
	} else {
		enemy.x = -100; // Start off-screen left
		enemy.speed = enemy.type === 'armored' ? 3 : enemy.type === 'shooting' ? 2 : 4; // Move right
	}
	enemy.y = 2732 - 150 + Math.random() * 100 - 50; // Vary height slightly
	enemies.push(enemy);
}
// Main game loop
game.update = function () {
	gameTime++;
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Update health bar
	var healthPercent = player.health / player.maxHealth;
	healthBar.width = 200 * healthPercent;
	// Spawn enemies
	enemySpawnTimer++;
	if (enemySpawnTimer >= enemySpawnRate) {
		spawnEnemy();
		enemySpawnTimer = 0;
		// Increase difficulty over time
		if (enemySpawnRate > 60) {
			// Minimum spawn rate
			enemySpawnRate -= 0.5;
		}
	}
	// Clean up off-screen enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		if (enemy.x < -100 || enemy.x > 2048 + 100) {
			enemy.destroy();
			enemies.splice(i, 1);
		}
	}
	// Clean up off-screen power-ups
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var powerUp = powerUps[i];
		if (powerUp.x < -100) {
			powerUp.destroy();
			powerUps.splice(i, 1);
		}
	}
	// Clean up off-screen enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		if (bullet.x < -100 || bullet.x > 2048 + 100) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
		}
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Enemy = Container.expand(function (type) {
	var self = Container.call(this);
	var assetName = type === 'armored' ? 'armoredEnemy' : type === 'shooting' ? 'shootingEnemy' : 'basicEnemy';
	var enemyGraphics = self.attachAsset(assetName, {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.type = type || 'basic';
	self.speed = type === 'armored' ? -3 : type === 'shooting' ? -2 : -4;
	self.maxHealth = type === 'shooting' ? 2 : 1;
	self.health = self.maxHealth;
	self.damage = type === 'armored' ? 30 : type === 'shooting' ? 25 : 20;
	self.points = type === 'armored' ? 30 : type === 'shooting' ? 25 : 10;
	// Direction tracking for all enemy types
	self.direction = self.speed > 0 ? 1 : -1; // Track current direction for all enemies
	self.lastDirection = self.direction; // Track last direction to detect changes
	// Armored enemy movement properties
	if (type === 'armored') {
		self.baseSpeed = Math.abs(self.speed); // Store base speed value
		self.direction = self.speed > 0 ? 1 : -1; // Track current direction
		self.lastX = 0; // Track last position for direction changes
		self.directionChangeTimer = 0;
		self.directionChangeInterval = 120 + Math.random() * 120; // Random interval 2-4 seconds
	}
	// Shooting properties for shooting enemies
	if (type === 'shooting') {
		self.shootTimer = 0;
		self.shootInterval = 60; // Shoot every 1 second (60 frames at 60fps)
		self.bulletsShot = 0; // Track number of bullets fired
		self.maxBullets = 1; // Maximum bullets this enemy can shoot - only one bullet per enemy
		self.shoot = function () {
			// Check if enemy has bullets remaining
			if (self.bulletsShot >= self.maxBullets) {
				return; // Don't shoot if limit reached
			}
			// Determine direction to shoot towards player
			var direction = player.x > self.x ? 1 : -1;
			var bullet = game.addChild(new EnemyBullet(direction));
			bullet.x = self.x;
			bullet.y = self.y - 40;
			enemyBullets.push(bullet);
			self.bulletsShot++; // Increment bullet count
		};
	}
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xffffff, 200);
		LK.getSound('enemyHit').play();
		if (self.health <= 0) {
			// Create main explosion effect
			var explosionEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			explosionEffect.x = self.x;
			explosionEffect.y = self.y - 40;
			explosionEffect.tint = 0xff4500; // Orange explosion color
			explosionEffect.alpha = 0.9;
			explosionEffect.scaleX = 0.5;
			explosionEffect.scaleY = 0.5;
			// Animate main explosion effect
			tween(explosionEffect, {
				scaleX: 3.0,
				scaleY: 3.0,
				alpha: 0
			}, {
				duration: 400,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					explosionEffect.destroy();
				}
			});
			// Create fragmented explosion pieces
			var fragmentCount = 6 + Math.floor(Math.random() * 4); // 6-9 fragments
			for (var f = 0; f < fragmentCount; f++) {
				var fragment = game.addChild(LK.getAsset(assetName, {
					anchorX: 0.5,
					anchorY: 0.5
				}));
				fragment.x = self.x;
				fragment.y = self.y - 40;
				fragment.tint = 0xff6600; // Darker orange for fragments
				fragment.alpha = 0.8;
				fragment.scaleX = 0.3 + Math.random() * 0.4; // Random size 0.3-0.7
				fragment.scaleY = 0.3 + Math.random() * 0.4;
				fragment.rotation = Math.random() * Math.PI * 2; // Random rotation
				// Calculate random scatter direction
				var angle = Math.PI * 2 / fragmentCount * f + (Math.random() - 0.5) * 0.8;
				var velocity = 150 + Math.random() * 100; // Random velocity 150-250
				var targetX = fragment.x + Math.cos(angle) * velocity;
				var targetY = fragment.y + Math.sin(angle) * velocity;
				// Animate fragment scatter with rotation and fade
				tween(fragment, {
					x: targetX,
					y: targetY,
					rotation: fragment.rotation + (Math.random() - 0.5) * Math.PI * 4,
					scaleX: 0,
					scaleY: 0,
					alpha: 0
				}, {
					duration: 600 + Math.random() * 400,
					// Random duration 600-1000ms
					easing: tween.easeOut,
					onFinish: function onFinish() {
						fragment.destroy();
					}
				});
			}
			// Award points
			LK.setScore(LK.getScore() + self.points);
			// Chance to drop power-up
			if (Math.random() < 0.15) {
				var powerUp = game.addChild(new PowerUp());
				powerUp.x = self.x;
				powerUp.y = self.y - 20;
				powerUps.push(powerUp);
			}
			// Remove from enemies array
			var index = enemies.indexOf(self);
			if (index > -1) {
				enemies.splice(index, 1);
			}
			self.destroy();
		}
	};
	// Initialize jumping properties
	self.baseY = 0;
	self.isJumping = false;
	self.jumpTimer = 0;
	self.jumpInterval = 150 + Math.random() * 90; // Random jump interval between 2.5-4 seconds for long jumps
	self.startJump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.baseY = self.y;
			var baseX = self.x;
			var jumpDistance = 200 + Math.random() * 150; // Long horizontal jump 200-350 pixels
			var jumpHeight = 120 + Math.random() * 80; // Higher jump 120-200 pixels
			// Jump direction based on movement direction
			var jumpDirectionX = self.speed > 0 ? jumpDistance : -jumpDistance;
			// Long jump with arc motion - jump up and forward
			tween(self, {
				y: self.baseY - jumpHeight,
				x: baseX + jumpDirectionX
			}, {
				duration: 800,
				// Longer duration for long jump
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Fall back down while continuing forward motion
					tween(self, {
						y: self.baseY
					}, {
						duration: 600,
						easing: tween.bounceOut,
						onFinish: function onFinish() {
							self.isJumping = false;
						}
					});
				}
			});
		}
	};
	self.update = function () {
		// Handle armored enemy direction changes
		if (self.type === 'armored') {
			// Initialize lastX if not set
			if (self.lastX === 0) self.lastX = self.x;
			// Check for screen boundaries and change direction
			if (self.x <= 100 && self.direction === -1 || self.x >= 1948 && self.direction === 1) {
				self.direction *= -1; // Reverse direction
				self.speed = self.baseSpeed * self.direction;
			}
			// Random direction changes
			self.directionChangeTimer++;
			if (self.directionChangeTimer >= self.directionChangeInterval) {
				self.direction *= -1; // Reverse direction
				self.speed = self.baseSpeed * self.direction;
				self.directionChangeTimer = 0;
				self.directionChangeInterval = 120 + Math.random() * 120; // Reset random interval
			}
			// Update lastX
			self.lastX = self.x;
		}
		// Update direction based on speed for all enemy types (including armored)
		self.direction = self.speed > 0 ? 1 : -1;
		// Flip enemy image based on screen position for all enemy types
		var targetScale;
		if (self.x < 1024) {
			// Left half of screen (2048/2 = 1024)
			targetScale = -1; // Face left
		} else {
			// Right half of screen
			targetScale = 1; // Face right
		}
		// Only animate if the scale needs to change
		if (enemyGraphics.scaleX !== targetScale) {
			tween(enemyGraphics, {
				scaleX: targetScale
			}, {
				duration: 200,
				easing: tween.easeOut
			});
		}
		self.x += self.speed;
		// Handle jumping
		self.jumpTimer++;
		if (self.jumpTimer >= self.jumpInterval && !self.isJumping) {
			self.startJump();
			self.jumpTimer = 0;
			self.jumpInterval = 150 + Math.random() * 90; // Reset random interval for long jumps
		}
		// Handle shooting for shooting enemies
		if (self.type === 'shooting') {
			self.shootTimer++;
			if (self.shootTimer >= self.shootInterval && self.bulletsShot < self.maxBullets) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
		// Check collision with player
		if (self.intersects(player) && !player.invulnerable) {
			player.takeDamage(self.damage);
		}
	};
	return self;
});
var EnemyBullet = Container.expand(function (direction) {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.damage = 15;
	self.direction = direction || 1; // 1 for right, -1 for left
	self.update = function () {
		self.x += self.speed * self.direction;
		// Check collision with player
		if (self.intersects(player) && !player.invulnerable) {
			player.takeDamage(self.damage);
			// Remove from enemyBullets array
			var index = enemyBullets.indexOf(self);
			if (index > -1) {
				enemyBullets.splice(index, 1);
			}
			self.destroy();
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 1.0
	});
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.slashDamage = 1;
	self.slashRange = 150;
	self.isSlashing = false;
	self.slashCooldown = 0;
	self.isDashing = false;
	self.dashCooldown = 0;
	self.dashDistance = 200;
	self.dashDuration = 300;
	self.invulnerable = false;
	self.invulnerabilityTime = 0;
	self.facingDirection = 1; // 1 for right, -1 for left
	self.isJumping = false;
	self.baseY = 0;
	self.dashSlash = function () {
		if (self.slashCooldown <= 0 && self.dashCooldown <= 0 && !self.isSlashing && !self.isDashing) {
			self.isDashing = true;
			self.isSlashing = true;
			self.slashCooldown = 60; // 1 second cooldown
			self.dashCooldown = 60;
			var startX = self.x;
			var dashTargetX = self.facingDirection > 0 ? Math.min(startX + self.dashDistance, 2048 - 40) : Math.max(startX - self.dashDistance, 40);
			// Dash forward with tween
			tween(self, {
				x: dashTargetX
			}, {
				duration: self.dashDuration,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					self.isDashing = false;
				}
			});
			// Create extended slash effect during dash
			var slashEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			slashEffect.x = self.x + 75 * self.facingDirection;
			slashEffect.y = self.y - 60;
			slashEffect.alpha = 0.9;
			slashEffect.scaleX = 2.0 * self.facingDirection;
			slashEffect.scaleY = 1.5;
			// Follow player during dash
			var slashFollowInterval = LK.setInterval(function () {
				if (self.isDashing) {
					slashEffect.x = self.x + 75 * self.facingDirection;
				}
			}, 16);
			// Animate slash effect
			tween(slashEffect, {
				scaleX: 2.5,
				scaleY: 2.0,
				alpha: 0
			}, {
				duration: self.dashDuration,
				onFinish: function onFinish() {
					LK.clearInterval(slashFollowInterval);
					slashEffect.destroy();
				}
			});
			LK.getSound('slash').play();
			// Extended damage check during dash
			var damageCheckInterval = LK.setInterval(function () {
				if (self.isDashing) {
					for (var i = 0; i < enemies.length; i++) {
						var enemy = enemies[i];
						var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
						var enemyInFront = self.facingDirection > 0 ? enemy.x > self.x - 50 && enemy.x < self.x + 150 : enemy.x < self.x + 50 && enemy.x > self.x - 150;
						if (distance < self.slashRange * 1.5 && enemyInFront) {
							enemy.takeDamage(self.slashDamage * 2); // Double damage during dash
						}
					}
					// Check for enemy bullet hits during dash
					for (var j = enemyBullets.length - 1; j >= 0; j--) {
						var bullet = enemyBullets[j];
						var bulletDistance = Math.sqrt(Math.pow(bullet.x - self.x, 2) + Math.pow(bullet.y - self.y, 2));
						var bulletInFront = self.facingDirection > 0 ? bullet.x > self.x - 50 && bullet.x < self.x + 150 : bullet.x < self.x + 50 && bullet.x > self.x - 150;
						if (bulletDistance < self.slashRange * 1.5 && bulletInFront) {
							// Destroy the bullet
							bullet.destroy();
							enemyBullets.splice(j, 1);
							// Award small points for destroying bullets
							LK.setScore(LK.getScore() + 5);
						}
					}
				}
			}, 30);
			LK.setTimeout(function () {
				LK.clearInterval(damageCheckInterval);
				self.isSlashing = false;
			}, self.dashDuration);
		}
	};
	self.slash = function () {
		if (self.slashCooldown <= 0 && !self.isSlashing && !self.isDashing) {
			self.isSlashing = true;
			self.slashCooldown = 20; // 1/3 second at 60fps
			// Create slash effect
			var slashEffect = game.addChild(LK.getAsset('slashEffect', {
				anchorX: 0.5,
				anchorY: 0.5
			}));
			slashEffect.x = self.x + 75 * self.facingDirection;
			slashEffect.y = self.y - 60;
			slashEffect.alpha = 0.8;
			slashEffect.scaleX = self.facingDirection;
			// Animate slash effect
			tween(slashEffect, {
				scaleX: 1.5,
				scaleY: 1.5,
				alpha: 0
			}, {
				duration: 200,
				onFinish: function onFinish() {
					slashEffect.destroy();
				}
			});
			LK.getSound('slash').play();
			// Check for enemy hits
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
				var enemyInRange = self.facingDirection > 0 ? enemy.x > self.x - 50 && enemy.x < self.x + self.slashRange : enemy.x < self.x + 50 && enemy.x > self.x - self.slashRange;
				if (distance < self.slashRange && enemyInRange) {
					enemy.takeDamage(self.slashDamage);
				}
			}
			// Check for enemy bullet hits
			for (var j = enemyBullets.length - 1; j >= 0; j--) {
				var bullet = enemyBullets[j];
				var bulletDistance = Math.sqrt(Math.pow(bullet.x - self.x, 2) + Math.pow(bullet.y - self.y, 2));
				var bulletInRange = self.facingDirection > 0 ? bullet.x > self.x - 50 && bullet.x < self.x + self.slashRange : bullet.x < self.x + 50 && bullet.x > self.x - self.slashRange;
				if (bulletDistance < self.slashRange && bulletInRange) {
					// Destroy the bullet
					bullet.destroy();
					enemyBullets.splice(j, 1);
					// Award small points for destroying bullets
					LK.setScore(LK.getScore() + 5);
				}
			}
			LK.setTimeout(function () {
				self.isSlashing = false;
			}, 200);
		}
	};
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.baseY = self.y;
			var jumpHeight = 200; // Jump height in pixels
			// Jump up with tween
			tween(self, {
				y: self.baseY - jumpHeight
			}, {
				duration: 400,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					// Fall back down
					tween(self, {
						y: self.baseY
					}, {
						duration: 400,
						easing: tween.easeIn,
						onFinish: function onFinish() {
							self.isJumping = false;
						}
					});
				}
			});
		}
	};
	self.takeDamage = function (damage) {
		if (!self.invulnerable) {
			self.health -= damage;
			self.invulnerable = true;
			self.invulnerabilityTime = 120; // 2 seconds at 60fps
			// Flash effect
			LK.effects.flashObject(self, 0xff0000, 500);
			if (self.health <= 0) {
				self.health = 0;
				LK.showGameOver();
			}
		}
	};
	self.update = function () {
		// Update player image direction based on facing direction
		playerGraphics.scaleX = self.facingDirection;
		if (self.slashCooldown > 0) {
			self.slashCooldown--;
		}
		if (self.dashCooldown > 0) {
			self.dashCooldown--;
		}
		if (self.invulnerabilityTime > 0) {
			self.invulnerabilityTime--;
			if (self.invulnerabilityTime <= 0) {
				self.invulnerable = false;
			}
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -2;
	self.bobOffset = 0;
	self.update = function () {
		self.x += self.speed;
		self.bobOffset += 0.1;
		self.y += Math.sin(self.bobOffset) * 0.5;
		// Check collision with player
		if (self.intersects(player)) {
			self.collect();
		}
	};
	self.collect = function () {
		LK.getSound('powerUpSound').play();
		// Random power-up effect
		var powerType = Math.floor(Math.random() * 3);
		switch (powerType) {
			case 0:
				// Increased damage
				player.slashDamage += 1;
				break;
			case 1:
				// Wider slash range
				player.slashRange += 50;
				break;
			case 2:
				// Temporary invincibility
				player.invulnerable = true;
				player.invulnerabilityTime = 300; // 5 seconds
				break;
		}
		// Remove from powerUps array
		var index = powerUps.indexOf(self);
		if (index > -1) {
			powerUps.splice(index, 1);
		}
		self.destroy();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var enemies = [];
var powerUps = [];
var enemyBullets = [];
var enemySpawnTimer = 0;
var enemySpawnRate = 180; // Start spawning every 3 seconds
var gameTime = 0;
var healthBar;
var healthBarBg;
// Create UI elements
var scoreTxt = new Text2('Score: 0', {
	size: 60,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 120;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
// Create health bar background
healthBarBg = game.addChild(LK.getAsset('healthBarBg', {
	anchorX: 0,
	anchorY: 0
}));
healthBarBg.x = 120;
healthBarBg.y = 120;
// Create health bar
healthBar = game.addChild(LK.getAsset('healthBar', {
	anchorX: 0,
	anchorY: 0
}));
healthBar.x = 122;
healthBar.y = 122;
// Create health text
var healthTxt = new Text2('Health', {
	size: 40,
	fill: 0xFFFFFF
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 160;
game.addChild(healthTxt);
// Create background
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0
}));
background.x = 0;
background.y = 0;
// Create player
player = game.addChild(new Player());
player.x = 300;
player.y = 2732 - 150; // Near bottom of screen
// Start background music
LK.playMusic('bgmusic');
// Touch controls for movement and slashing
var isDragging = false;
var lastTouchX = 0;
var lastTouchY = 0;
var swipeThreshold = 100; // Minimum distance for swipe detection
game.down = function (x, y, obj) {
	isDragging = true;
	lastTouchX = x;
	lastTouchY = y;
	// Set facing direction based on touch position relative to player
	if (x < player.x) {
		player.facingDirection = -1; // Face left
	} else {
		player.facingDirection = 1; // Face right
	}
	player.dashSlash();
};
game.move = function (x, y, obj) {
	if (isDragging) {
		var deltaX = x - lastTouchX;
		player.x += deltaX * 0.5; // Smooth movement multiplier
		// Keep player within screen bounds
		if (player.x < 40) player.x = 40;
		if (player.x > 2048 - 40) player.x = 2048 - 40;
		lastTouchX = x;
	}
};
game.up = function (x, y, obj) {
	if (isDragging) {
		var deltaY = lastTouchY - y; // Upward swipe has positive deltaY
		var deltaX = Math.abs(x - lastTouchX);
		// Check for upward swipe (vertical movement greater than horizontal and above threshold)
		if (deltaY > swipeThreshold && deltaY > deltaX) {
			player.jump();
		}
	}
	isDragging = false;
};
// Spawn enemies
function spawnEnemy() {
	var rand = Math.random();
	var enemyType = rand < 0.5 ? 'basic' : rand < 0.8 ? 'armored' : 'shooting';
	var enemy = game.addChild(new Enemy(enemyType));
	// Randomly spawn from left or right
	var spawnFromRight = Math.random() < 0.5;
	if (spawnFromRight) {
		enemy.x = 2048 + 100; // Start off-screen right
		enemy.speed = enemy.type === 'armored' ? -3 : enemy.type === 'shooting' ? -2 : -4; // Move left
	} else {
		enemy.x = -100; // Start off-screen left
		enemy.speed = enemy.type === 'armored' ? 3 : enemy.type === 'shooting' ? 2 : 4; // Move right
	}
	enemy.y = 2732 - 150 + Math.random() * 100 - 50; // Vary height slightly
	enemies.push(enemy);
}
// Main game loop
game.update = function () {
	gameTime++;
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Update health bar
	var healthPercent = player.health / player.maxHealth;
	healthBar.width = 200 * healthPercent;
	// Spawn enemies
	enemySpawnTimer++;
	if (enemySpawnTimer >= enemySpawnRate) {
		spawnEnemy();
		enemySpawnTimer = 0;
		// Increase difficulty over time
		if (enemySpawnRate > 60) {
			// Minimum spawn rate
			enemySpawnRate -= 0.5;
		}
	}
	// Clean up off-screen enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		if (enemy.x < -100 || enemy.x > 2048 + 100) {
			enemy.destroy();
			enemies.splice(i, 1);
		}
	}
	// Clean up off-screen power-ups
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var powerUp = powerUps[i];
		if (powerUp.x < -100) {
			powerUp.destroy();
			powerUps.splice(i, 1);
		}
	}
	// Clean up off-screen enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		if (bullet.x < -100 || bullet.x > 2048 + 100) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
		}
	}
};
 efek slash kepala naga petir ke depan. In-Game asset. 2d. High contrast. No shadows
 side scroller blue steel armored ninja aksi koreographi dua tangan memegang pedang ke depan In-Game asset. 2d. No shadows
 side scroller image fat orc samurai front holding big axe. In-Game asset. 2d. High contrast. No shadows
 side scroller kepala evil kelinci berapi. In-Game asset. 2d. High contrast. No shadows
 realistic 2d anime style front field old samurai palace temple with pig evil ornament at midnight. In-Game asset. 2d. High contrast. No shadows