User prompt
perbaiki asset background tidak muncul
User prompt
tambah asset background jadi sembilan asset. background berubah rubah setiap permainan awal muncul
User prompt
musuh mati berputar putar saat ditembak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'var bgRock1 = gameContainer.addChild(LK.getAsset('bgRock1', {' Line Number: 490
User prompt
add 7 background asset
User prompt
buat swipe kearah target untuk menembak
User prompt
buat aturan tap hanya untuk berjalan
User prompt
rubah aturan. tap layar ke target untuk bergerak. swipe untuk menembak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
player bisa berbalik kekanan dan kiri
User prompt
player bisa bergerak kekanan dan kekiri juga ke atas dan bawa tanpa haru berputar
User prompt
bua animasi bulat merah meledak saat enemy mati ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
perbaiki untuk karakter orc yang bolak balik jangan tiba tiba menghilang
User prompt
buat animasi untuk orc yang menunggu terlihat seperi meloncat loncat ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hilangkan bercak bercak pada background
User prompt
buat animasi ledakkan merah saat orc mati ditembak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make player control to swipe dan hold
User prompt
fix background music ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix lag game play
User prompt
make background detailed and sharp
User prompt
add background
User prompt
player bisa berbalik ke kanan, bisa berbalik ke kiri, bisa berbalik ke atas, bisa berbalik ke bawah ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat musuh menyerang player berulang saat bertemu ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat peluru player menyebar tiga penjuru didepan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
musuh mencoba mendekat saat melihat player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
player ada kemampuan auto target musub ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.direction = {
		x: 0,
		y: 0
	};
	self.lifetime = 0;
	self.maxLifetime = 120; // 2 seconds at 60fps
	self.update = function () {
		self.x += self.direction.x * self.speed;
		self.y += self.direction.y * self.speed;
		self.lifetime++;
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: 0xFFFFFF
	});
	self.speed = 1;
	self.health = 2;
	self.attackRange = 40;
	self.attackCooldown = 0;
	self.attackInterval = 60; // Attack every second at 60fps
	self.patrolDirection = Math.random() > 0.5 ? 1 : -1; // Random initial direction
	self.patrolAxis = Math.random() > 0.5 ? 'x' : 'y'; // Random patrol axis (horizontal or vertical)
	self.patrolDistance = CELL_SIZE * 3; // Patrol 3 cells distance
	self.startPosition = {
		x: 0,
		y: 0
	}; // Will be set when enemy is placed
	self.isMoving = false;
	self.lastPlayerDistance = Infinity;
	self.startPatrol = function () {
		if (self.isMoving) return;
		self.isMoving = true;
		var targetX = self.x;
		var targetY = self.y;
		// Calculate target position based on patrol axis
		if (self.patrolAxis === 'x') {
			targetX = self.startPosition.x + self.patrolDirection * self.patrolDistance;
		} else {
			targetY = self.startPosition.y + self.patrolDirection * self.patrolDistance;
		}
		// Check if target position is valid
		if (canMoveTo(targetX, targetY)) {
			// Store the original position for safe restoration
			var originalX = self.x;
			var originalY = self.y;
			// Move to target position using tween
			tween(self, {
				x: targetX,
				y: targetY
			}, {
				duration: 2000,
				easing: tween.linear,
				onFinish: function onFinish() {
					// Ensure enemy is at a valid position after movement
					if (!canMoveTo(self.x, self.y)) {
						// If somehow ended up in invalid position, restore to original
						self.x = originalX;
						self.y = originalY;
					}
					self.isMoving = false;
					self.patrolDirection *= -1; // Reverse direction
				}
			});
		} else {
			// If can't move in current direction, reverse immediately
			self.isMoving = false;
			self.patrolDirection *= -1;
		}
	};
	self.update = function () {
		// Add bouncing animation when enemy is not moving (idle/waiting state)
		if (!self.isMoving) {
			if (!self.bounceTimer) self.bounceTimer = 0;
			self.bounceTimer++;
			// Create a subtle bouncing effect
			var bounceOffset = Math.sin(self.bounceTimer * 0.15) * 2;
			// Use current position as base instead of startPosition to avoid conflicts
			var baseY = self.startPosition.y;
			self.y = baseY + bounceOffset;
		} else {
			// Reset bounce timer when moving to ensure smooth transitions
			self.bounceTimer = 0;
		}
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		var detectionRange = CELL_SIZE * 4; // Enemy can see player from 4 cells away
		// Check if player is within detection range and line of sight (optimized - check every 10 frames)
		var canSeePlayer = false;
		if (distance < detectionRange) {
			// Only do expensive line of sight calculation every 10 frames
			if (!self.losCheckTimer) self.losCheckTimer = 0;
			self.losCheckTimer++;
			if (self.losCheckTimer >= 10 || !self.hasOwnProperty('lastCanSeePlayer')) {
				self.losCheckTimer = 0;
				// Simple line of sight check - check if there are walls between enemy and player
				var steps = Math.ceil(distance / 40); // Reduced precision from 20 to 40
				var stepX = dx / steps;
				var stepY = dy / steps;
				self.lastCanSeePlayer = true;
				for (var step = 1; step < steps; step++) {
					var checkX = self.x + stepX * step;
					var checkY = self.y + stepY * step;
					if (!canMoveTo(checkX, checkY)) {
						self.lastCanSeePlayer = false;
						break;
					}
				}
			}
			canSeePlayer = self.lastCanSeePlayer;
		} else {
			canSeePlayer = self.lastCanSeePlayer;
		}
		// If can see player and not in attack range, move towards player
		if (canSeePlayer && distance > self.attackRange) {
			if (!self.isMoving) {
				self.isMoving = true;
				// Stop current patrol movement
				tween.stop(self);
				// Calculate next position towards player (one cell at a time)
				var moveDistance = CELL_SIZE;
				var normalizedDx = dx / distance;
				var normalizedDy = dy / distance;
				var targetX = self.x + normalizedDx * moveDistance;
				var targetY = self.y + normalizedDy * moveDistance;
				// Try to move towards player, prioritize the axis with larger distance
				if (Math.abs(dx) > Math.abs(dy)) {
					// Try horizontal movement first
					var horizontalTarget = self.x + (dx > 0 ? moveDistance : -moveDistance);
					if (canMoveTo(horizontalTarget, self.y)) {
						targetX = horizontalTarget;
						targetY = self.y;
					} else if (canMoveTo(self.x, self.y + (dy > 0 ? moveDistance : -moveDistance))) {
						// If horizontal blocked, try vertical
						targetX = self.x;
						targetY = self.y + (dy > 0 ? moveDistance : -moveDistance);
					} else {
						// Can't move towards player
						targetX = self.x;
						targetY = self.y;
					}
				} else {
					// Try vertical movement first
					var verticalTarget = self.y + (dy > 0 ? moveDistance : -moveDistance);
					if (canMoveTo(self.x, verticalTarget)) {
						targetX = self.x;
						targetY = verticalTarget;
					} else if (canMoveTo(self.x + (dx > 0 ? moveDistance : -moveDistance), self.y)) {
						// If vertical blocked, try horizontal
						targetX = self.x + (dx > 0 ? moveDistance : -moveDistance);
						targetY = self.y;
					} else {
						// Can't move towards player
						targetX = self.x;
						targetY = self.y;
					}
				}
				// Move towards calculated target
				if (targetX !== self.x || targetY !== self.y) {
					// Store current position for safety
					var safeX = self.x;
					var safeY = self.y;
					tween(self, {
						x: targetX,
						y: targetY
					}, {
						duration: 1000,
						easing: tween.linear,
						onFinish: function onFinish() {
							// Validate final position
							if (!canMoveTo(self.x, self.y)) {
								self.x = safeX;
								self.y = safeY;
							}
							self.isMoving = false;
						}
					});
				} else {
					self.isMoving = false;
				}
			}
		} else if (!canSeePlayer) {
			// Start patrol movement if not already moving and can't see player
			if (!self.isMoving) {
				self.startPatrol();
			}
		}
		// Attack player if in range
		if (distance < self.attackRange) {
			// Stop patrolling when in attack range
			if (!self.lastPlayerDistance || self.lastPlayerDistance >= self.attackRange) {
				tween.stop(self);
				self.isMoving = false;
			}
			// Continuously attack while in range
			if (self.attackCooldown <= 0) {
				// Perform melee attack
				playerHealth--;
				LK.effects.flashObject(player, 0xFF0000, 500);
				// Visual attack feedback - enemy briefly grows and turns red
				tween(self, {
					tint: 0xFF0000,
					scaleX: 1.3,
					scaleY: 1.3
				}, {
					duration: 200,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Return to normal appearance
						tween(self, {
							tint: 0xFFFFFF,
							scaleX: 1,
							scaleY: 1
						}, {
							duration: 200,
							easing: tween.easeOut
						});
					}
				});
				// Reset attack cooldown
				self.attackCooldown = self.attackInterval;
			}
		}
		// Update attack cooldown
		if (self.attackCooldown > 0) {
			self.attackCooldown--;
		}
		self.lastPlayerDistance = distance;
	};
	return self;
});
var Ore = Container.expand(function () {
	var self = Container.call(this);
	var oreGraphics = self.attachAsset('ore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.value = 1;
	self.bobTimer = 0;
	self.baseY = self.y;
	self.update = function () {
		self.bobTimer++;
		self.y = self.baseY + Math.sin(self.bobTimer * 0.1) * 3;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2C1810
});
/**** 
* Game Code
****/ 
// Game constants
var MAZE_WIDTH = 13;
var MAZE_HEIGHT = 17;
var CELL_SIZE = 80;
var MAZE_OFFSET_X = (2048 - MAZE_WIDTH * CELL_SIZE) / 2;
var MAZE_OFFSET_Y = 100;
// Game variables
var maze = [];
var player;
var enemies = [];
var ores = [];
var bullets = [];
var playerHealth = 3;
var oreCollected = 0;
var oreTarget = 10;
var level = 1;
var exit;
var gameContainer;
// UI elements
var healthText = new Text2('Health: 3', {
	size: 60,
	fill: 0xFF4444
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
var oreText = new Text2('Ore: 0/10', {
	size: 60,
	fill: 0xFFD700
});
oreText.anchor.set(0.5, 0);
LK.gui.top.addChild(oreText);
var levelText = new Text2('Level: 1', {
	size: 60,
	fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
LK.gui.topRight.addChild(levelText);
// Initialize maze array
function initializeMaze() {
	maze = [];
	for (var y = 0; y < MAZE_HEIGHT; y++) {
		maze[y] = [];
		for (var x = 0; x < MAZE_WIDTH; x++) {
			maze[y][x] = 1; // 1 = wall, 0 = floor
		}
	}
}
// Simple maze generation using recursive backtracking
function generateMaze() {
	initializeMaze();
	var stack = [];
	var startX = 1;
	var startY = 1;
	maze[startY][startX] = 0;
	stack.push({
		x: startX,
		y: startY
	});
	while (stack.length > 0) {
		var current = stack[stack.length - 1];
		var neighbors = [];
		// Check all four directions
		var directions = [{
			x: 0,
			y: -2
		}, {
			x: 2,
			y: 0
		}, {
			x: 0,
			y: 2
		}, {
			x: -2,
			y: 0
		}];
		for (var i = 0; i < directions.length; i++) {
			var nx = current.x + directions[i].x;
			var ny = current.y + directions[i].y;
			if (nx > 0 && nx < MAZE_WIDTH - 1 && ny > 0 && ny < MAZE_HEIGHT - 1 && maze[ny][nx] === 1) {
				neighbors.push({
					x: nx,
					y: ny,
					dir: directions[i]
				});
			}
		}
		if (neighbors.length > 0) {
			var chosen = neighbors[Math.floor(Math.random() * neighbors.length)];
			// Remove wall between current and chosen
			maze[current.y + chosen.dir.y / 2][current.x + chosen.dir.x / 2] = 0;
			maze[chosen.y][chosen.x] = 0;
			stack.push(chosen);
		} else {
			stack.pop();
		}
	}
}
// Create visual maze
function createMazeVisual() {
	gameContainer = game.addChild(new Container());
	for (var y = 0; y < MAZE_HEIGHT; y++) {
		for (var x = 0; x < MAZE_WIDTH; x++) {
			var cellX = MAZE_OFFSET_X + x * CELL_SIZE;
			var cellY = MAZE_OFFSET_Y + y * CELL_SIZE;
			if (maze[y][x] === 1) {
				// Wall
				var wall = LK.getAsset('wall', {
					x: cellX,
					y: cellY
				});
				gameContainer.addChild(wall);
			} else {
				// Floor
				var floor = LK.getAsset('floor', {
					x: cellX,
					y: cellY
				});
				gameContainer.addChild(floor);
			}
		}
	}
}
// Place ore in maze
function placeOre() {
	var oreCount = oreTarget + Math.floor(level / 2);
	var placed = 0;
	while (placed < oreCount) {
		var x = Math.floor(Math.random() * MAZE_WIDTH);
		var y = Math.floor(Math.random() * MAZE_HEIGHT);
		if (maze[y][x] === 0 && (x !== 1 || y !== 1)) {
			var ore = gameContainer.addChild(new Ore());
			ore.x = MAZE_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
			ore.y = MAZE_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
			ore.baseY = ore.y;
			ores.push(ore);
			placed++;
		}
	}
}
// Place enemies in maze
function placeEnemies() {
	var enemyCount = 3 + level;
	var placed = 0;
	while (placed < enemyCount) {
		var x = Math.floor(Math.random() * MAZE_WIDTH);
		var y = Math.floor(Math.random() * MAZE_HEIGHT);
		if (maze[y][x] === 0 && (x !== 1 || y !== 1) && Math.sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1)) > 5) {
			var enemy = gameContainer.addChild(new Enemy());
			enemy.x = MAZE_OFFSET_X + x * CELL_SIZE + CELL_SIZE / 2;
			enemy.y = MAZE_OFFSET_Y + y * CELL_SIZE + CELL_SIZE / 2;
			enemy.startPosition.x = enemy.x;
			enemy.startPosition.y = enemy.y;
			enemies.push(enemy);
			placed++;
		}
	}
}
// Place exit
function placeExit() {
	// Find a position far from start
	var placed = false;
	while (!placed) {
		var x = Math.floor(Math.random() * MAZE_WIDTH);
		var y = Math.floor(Math.random() * MAZE_HEIGHT);
		if (maze[y][x] === 0 && Math.sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1)) > 10) {
			exit = gameContainer.addChild(LK.getAsset('exit', {
				x: MAZE_OFFSET_X + x * CELL_SIZE,
				y: MAZE_OFFSET_Y + y * CELL_SIZE
			}));
			placed = true;
		}
	}
}
// Removed createDetailedBackground function to eliminate background spots/patches
// Check if position is valid for movement
function canMoveTo(x, y) {
	var mazeX = Math.floor((x - MAZE_OFFSET_X) / CELL_SIZE);
	var mazeY = Math.floor((y - MAZE_OFFSET_Y) / CELL_SIZE);
	if (mazeX < 0 || mazeX >= MAZE_WIDTH || mazeY < 0 || mazeY >= MAZE_HEIGHT) {
		return false;
	}
	return maze[mazeY][mazeX] === 0;
}
// Initialize level
function initializeLevel() {
	// Clear existing game objects
	if (gameContainer) {
		gameContainer.destroy();
	}
	enemies = [];
	ores = [];
	bullets = [];
	oreCollected = 0;
	// Add detailed background
	var background = game.addChild(LK.getAsset('background', {
		x: 0,
		y: 0,
		width: 2048,
		height: 2732
	}));
	// Create detailed background elements
	// createDetailedBackground(); // Removed to eliminate background spots
	// Generate new maze
	generateMaze();
	createMazeVisual();
	// Create player
	player = gameContainer.addChild(LK.getAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: MAZE_OFFSET_X + 1 * CELL_SIZE + CELL_SIZE / 2,
		y: MAZE_OFFSET_Y + 1 * CELL_SIZE + CELL_SIZE / 2
	}));
	// Place game objects
	placeOre();
	placeEnemies();
	placeExit();
	// Update UI
	updateUI();
}
// Update UI
function updateUI() {
	healthText.setText('Health: ' + playerHealth);
	oreText.setText('Ore: ' + oreCollected + '/' + oreTarget);
	levelText.setText('Level: ' + level);
}
// Shooting system
var dragNode = null;
var shootCooldown = 0;
function shoot(targetX, targetY) {
	if (shootCooldown > 0) return;
	// Limit maximum bullets to prevent lag
	if (bullets.length >= 15) return;
	var dx = targetX - player.x;
	var dy = targetY - player.y;
	var distance = Math.sqrt(dx * dx + dy * dy);
	if (distance < 50) return; // Don't shoot if too close
	// Calculate base direction
	var baseDirectionX = dx / distance;
	var baseDirectionY = dy / distance;
	// Create three bullets with spread angles
	var spreadAngles = [-0.3, 0, 0.3]; // Left, center, right (in radians, about 17 degrees each side)
	for (var i = 0; i < spreadAngles.length; i++) {
		var angle = Math.atan2(baseDirectionY, baseDirectionX) + spreadAngles[i];
		var bullet = gameContainer.addChild(new Bullet());
		bullet.x = player.x;
		bullet.y = player.y;
		bullet.direction.x = Math.cos(angle);
		bullet.direction.y = Math.sin(angle);
		bullets.push(bullet);
	}
	shootCooldown = 15; // Quarter second cooldown
	LK.getSound('shoot').play();
}
// Main game loop
game.update = function () {
	if (shootCooldown > 0) shootCooldown--;
	// Handle hold movement
	if (isTracking && !isHolding) {
		var currentTime = Date.now();
		var holdTime = currentTime - holdStartTime;
		// Check if we should start hold movement
		if (holdTime >= holdThreshold) {
			var dx = swipeEnd.x - swipeStart.x;
			var dy = swipeEnd.y - swipeStart.y;
			var swipeDistance = Math.sqrt(dx * dx + dy * dy);
			// Only start hold if not moving much (stationary hold)
			if (swipeDistance < swipeThreshold) {
				isHolding = true;
				lastHoldMoveTime = currentTime;
				// Determine hold direction based on player center to touch position
				var holdDx = swipeStart.x - player.x;
				var holdDy = swipeStart.y - player.y;
				var holdDistance = Math.sqrt(holdDx * holdDx + holdDy * holdDy);
				if (holdDistance > 30) {
					// Must be reasonable distance from center
					if (Math.abs(holdDx) > Math.abs(holdDy)) {
						// Horizontal hold movement
						holdDirection.x = holdDx > 0 ? 1 : -1;
						holdDirection.y = 0;
					} else {
						// Vertical hold movement
						holdDirection.x = 0;
						holdDirection.y = holdDy > 0 ? 1 : -1;
					}
				}
			}
		}
	}
	// Process hold movement
	if (isHolding && !isPlayerMoving) {
		var currentTime = Date.now();
		if (currentTime - lastHoldMoveTime >= holdMoveInterval) {
			var moveX = holdDirection.x * playerSpeed;
			var moveY = holdDirection.y * playerSpeed;
			var newX = player.x + moveX;
			var newY = player.y + moveY;
			// Try to move in hold direction
			if (canMoveTo(newX, player.y) && holdDirection.x !== 0) {
				// Flip player sprite based on hold movement direction
				if (holdDirection.x > 0) {
					// Moving right - face right (normal)
					player.scaleX = 1;
				} else {
					// Moving left - face left (flipped)
					player.scaleX = -1;
				}
				isPlayerMoving = true;
				tween(player, {
					x: newX
				}, {
					duration: 120,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						isPlayerMoving = false;
					}
				});
				lastHoldMoveTime = currentTime;
			} else if (canMoveTo(player.x, newY) && holdDirection.y !== 0) {
				isPlayerMoving = true;
				tween(player, {
					y: newY
				}, {
					duration: 120,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						isPlayerMoving = false;
					}
				});
				lastHoldMoveTime = currentTime;
			}
		}
	}
	// Update bullets
	for (var i = bullets.length - 1; i >= 0; i--) {
		var bullet = bullets[i];
		// Check bullet lifetime
		if (bullet.lifetime >= bullet.maxLifetime) {
			bullet.destroy();
			bullets.splice(i, 1);
			continue;
		}
		// Check wall collision
		if (!canMoveTo(bullet.x, bullet.y)) {
			bullet.destroy();
			bullets.splice(i, 1);
			continue;
		}
		// Check enemy collision (optimized - only check every other frame for performance)
		var hitEnemy = false;
		if (LK.ticks % 2 === 0 || bullet.lifetime < 10) {
			// Always check new bullets
			for (var j = enemies.length - 1; j >= 0; j--) {
				if (bullet.intersects(enemies[j])) {
					enemies[j].health--;
					LK.getSound('enemyHit').play();
					if (enemies[j].health <= 0) {
						// Create red circular explosion animation
						var dyingEnemy = enemies[j];
						var explosionX = dyingEnemy.x;
						var explosionY = dyingEnemy.y;
						// Create red explosion circle
						var explosion = gameContainer.addChild(LK.getAsset('bullet', {
							anchorX: 0.5,
							anchorY: 0.5,
							x: explosionX,
							y: explosionY,
							scaleX: 0.1,
							scaleY: 0.1,
							tint: 0xFF0000
						}));
						// Animate explosion circle expanding and fading
						tween(explosion, {
							scaleX: 8,
							scaleY: 8,
							alpha: 0
						}, {
							duration: 500,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								explosion.destroy();
							}
						});
						// Create enemy death animation
						tween(dyingEnemy, {
							tint: 0xFF0000,
							scaleX: 1.5,
							scaleY: 1.5
						}, {
							duration: 150,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								// Second stage: Continue growing while fading to dark red
								tween(dyingEnemy, {
									tint: 0x800000,
									scaleX: 2.5,
									scaleY: 2.5,
									alpha: 0.7
								}, {
									duration: 200,
									easing: tween.easeOut,
									onFinish: function onFinish() {
										// Final stage: Fade out completely
										tween(dyingEnemy, {
											alpha: 0,
											scaleX: 3,
											scaleY: 3
										}, {
											duration: 200,
											easing: tween.easeIn,
											onFinish: function onFinish() {
												dyingEnemy.destroy();
											}
										});
									}
								});
							}
						});
						enemies.splice(j, 1);
					}
					bullet.destroy();
					bullets.splice(i, 1);
					hitEnemy = true;
					break;
				}
			}
		}
		if (hitEnemy) continue;
	}
	// Check ore collection
	for (var i = ores.length - 1; i >= 0; i--) {
		if (player.intersects(ores[i])) {
			oreCollected++;
			LK.getSound('oreCollect').play();
			ores[i].destroy();
			ores.splice(i, 1);
			updateUI();
		}
	}
	// Check exit condition
	if (exit && player.intersects(exit) && oreCollected >= oreTarget) {
		level++;
		oreTarget += 2;
		initializeLevel();
		return;
	}
	// Check game over
	if (playerHealth <= 0) {
		LK.showGameOver();
		return;
	}
	// Check win condition (survive 10 levels)
	if (level > 10) {
		LK.showYouWin();
		return;
	}
};
// Swipe and hold-based movement system
var swipeStart = {
	x: 0,
	y: 0
};
var swipeEnd = {
	x: 0,
	y: 0
};
var isTracking = false;
var playerSpeed = 80; // Full cell movement
var swipeThreshold = 50; // Minimum distance for swipe detection
var lastMoveTime = 0;
var moveDelay = 200; // Delay between moves in milliseconds
var isPlayerMoving = false;
// Hold movement system
var isHolding = false;
var holdStartTime = 0;
var holdThreshold = 300; // Time to distinguish between tap and hold (ms)
var holdMoveInterval = 150; // Interval between moves while holding
var lastHoldMoveTime = 0;
var holdDirection = {
	x: 0,
	y: 0
};
game.down = function (x, y, obj) {
	swipeStart.x = x;
	swipeStart.y = y;
	isTracking = true;
	holdStartTime = Date.now();
	isHolding = false;
};
game.move = function (x, y, obj) {
	if (isTracking) {
		swipeEnd.x = x;
		swipeEnd.y = y;
	}
};
game.up = function (x, y, obj) {
	if (!isTracking) return;
	isTracking = false;
	isHolding = false; // Stop hold movement
	var dx = swipeEnd.x - swipeStart.x;
	var dy = swipeEnd.y - swipeStart.y;
	var swipeDistance = Math.sqrt(dx * dx + dy * dy);
	var holdTime = Date.now() - holdStartTime;
	// Check if this was a hold operation
	if (holdTime >= holdThreshold && swipeDistance < swipeThreshold) {
		// This was a hold, don't process as tap or swipe
		return;
	}
	// Check if swipe is long enough
	if (swipeDistance >= swipeThreshold) {
		// Long swipe - shoot in that direction
		shoot(x, y);
		return;
	}
	// Short tap - move towards target position
	// Prevent too frequent moves and simultaneous movements
	var currentTime = Date.now();
	if (currentTime - lastMoveTime < moveDelay || isPlayerMoving) return;
	// Calculate direction from player to tap position
	var dx = x - player.x;
	var dy = y - player.y;
	var distance = Math.sqrt(dx * dx + dy * dy);
	if (distance < 50) return; // Don't move if tapped too close to player
	// Determine movement direction (one cell at a time)
	var moveX = 0;
	var moveY = 0;
	if (Math.abs(dx) > Math.abs(dy)) {
		// Move horizontally towards tap
		moveX = dx > 0 ? playerSpeed : -playerSpeed;
	} else {
		// Move vertically towards tap
		moveY = dy > 0 ? playerSpeed : -playerSpeed;
	}
	// Calculate new position
	var newX = player.x + moveX;
	var newY = player.y + moveY;
	// Check if movement is valid and animate smoothly
	if (canMoveTo(newX, player.y) && Math.abs(moveX) > 0) {
		// Flip player sprite based on movement direction
		if (moveX > 0) {
			// Moving right - face right (normal)
			player.scaleX = 1;
		} else {
			// Moving left - face left (flipped)
			player.scaleX = -1;
		}
		isPlayerMoving = true;
		tween(player, {
			x: newX
		}, {
			duration: 150,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				isPlayerMoving = false;
			}
		});
		lastMoveTime = currentTime;
	} else if (canMoveTo(player.x, newY) && Math.abs(moveY) > 0) {
		isPlayerMoving = true;
		tween(player, {
			y: newY
		}, {
			duration: 150,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				isPlayerMoving = false;
			}
		});
		lastMoveTime = currentTime;
	}
};
// Initialize the first level
initializeLevel();
// Start background music
LK.playMusic('1dwarftheme'); ===================================================================
--- original.js
+++ change.js
@@ -782,24 +782,30 @@
 		// This was a hold, don't process as tap or swipe
 		return;
 	}
 	// Check if swipe is long enough
-	if (swipeDistance < swipeThreshold) {
-		// Short tap - shoot in that direction without rotating player
+	if (swipeDistance >= swipeThreshold) {
+		// Long swipe - shoot in that direction
 		shoot(x, y);
 		return;
 	}
+	// Short tap - move towards target position
 	// Prevent too frequent moves and simultaneous movements
 	var currentTime = Date.now();
 	if (currentTime - lastMoveTime < moveDelay || isPlayerMoving) return;
-	// Determine swipe direction
+	// Calculate direction from player to tap position
+	var dx = x - player.x;
+	var dy = y - player.y;
+	var distance = Math.sqrt(dx * dx + dy * dy);
+	if (distance < 50) return; // Don't move if tapped too close to player
+	// Determine movement direction (one cell at a time)
 	var moveX = 0;
 	var moveY = 0;
 	if (Math.abs(dx) > Math.abs(dy)) {
-		// Horizontal swipe
+		// Move horizontally towards tap
 		moveX = dx > 0 ? playerSpeed : -playerSpeed;
 	} else {
-		// Vertical swipe
+		// Move vertically towards tap
 		moveY = dy > 0 ? playerSpeed : -playerSpeed;
 	}
 	// Calculate new position
 	var newX = player.x + moveX;
:quality(85)/https://cdn.frvr.ai/68984acb9130fe3d08eaa4ee.png%3F3) 
 2d sprites old dwarf hold shootgun. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68984c459130fe3d08eaa501.png%3F3) 
 2d chibi green evil underground fat ork. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6899388890392925e1067aff.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/68993a410833c71e7122a4a0.png%3F3) 
 2d golds ors brigh stone. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/689a8d1040a79ff68e47997d.png%3F3) 
 2d cave tunnel corridor. In-Game asset. 2d. High contrast. No shadows