User prompt
remove the old route when new created
User prompt
When the knife button is pressed, draw a route that shows the shortest distance between the enemy and the player, and display the effect where that route meets the player's asset. the knife meets the enemy in the middle of asset. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a knife throw button. enemies take damage when knife hits them. knives are limited to 5 for each level ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When the knife button is pressed, draw a route that shows the shortest distance between the enemy and the player, and display the effect where that route meets the player's asset. remove the same thing with attack button attack button only creates punch effect not any route effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a knife throw button and do this when new button is pressed. also enemies take damage when knife hits them. knives are limited to 5 for each level ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When the attack button is pressed, draw a route that shows the shortest distance between the enemy and the player, and display the effect where that route meets the player's asset. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
move the movement keys away from each other and prevent them from intersecting with each other
User prompt
Show a warning with an arrow on the side where the enemy is. As you move forward, the warning will change from transparent to visible and when the enemy becomes visible on the screen, the warning will disappear. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add collision to player and mobs. they collide and They don't interfere with each other.
User prompt
make all buttons bigger and add an asset for each of them
User prompt
It should move when the movement keys are hold, not when clicked.
User prompt
add buttons for all directions to move the player, add a attack button, increase attacks range
User prompt
game is not wave based. game is level based with each level contains different type and number of enemies. you move the player and the playable map is not limited with the visble screen camera follows the char as the char moves. enemies roam randomly and starts to attack the pkayer once they sees it
Code edit (1 edits merged)
Please save this source code
User prompt
Pixel Hero Adventure
Initial prompt
a pixel game like dan the man
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.collectTimer = 0; self.update = function () { // Auto-collect after short delay self.collectTimer++; if (self.collectTimer > 30) { // 0.5 seconds self.collect(); } // Spin animation coinGraphics.rotation += 0.1; }; self.collect = function () { LK.getSound('coin').play(); // Remove from coins array for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === self) { coins.splice(i, 1); break; } } self.destroy(); }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 1.0 }); self.health = 2; self.speed = 1; self.attackCooldown = 0; self.fromLeft = true; self.lastX = 0; self.lastY = 0; self.update = function () { var distanceToHero = Math.sqrt(Math.pow(self.x - hero.x, 2) + Math.pow(self.y - hero.y, 2)); var canSeeHero = distanceToHero < 300; // Line of sight range if (canSeeHero) { // Chase hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { var newX = self.x + dx / distance * self.speed; var newY = self.y + dy / distance * self.speed; // Check collision with other enemies before moving var wouldCollide = false; for (var i = 0; i < enemies.length; i++) { var otherEnemy = enemies[i]; if (otherEnemy === self) continue; // Skip self var edx = newX - otherEnemy.x; var edy = newY - otherEnemy.y; var edistance = Math.sqrt(edx * edx + edy * edy); if (edistance < 70) { // Collision threshold between enemies wouldCollide = true; break; } } // Only move if no collision would occur if (!wouldCollide) { self.lastX = self.x; self.lastY = self.y; self.x = newX; self.y = newY; } // Face direction of movement enemyGraphics.scaleX = dx > 0 ? 1 : -1; } // Attack hero if close enough if (distanceToHero < 100 && self.attackCooldown <= 0) { hero.takeDamage(); self.attackCooldown = 120; // 2 seconds at 60fps } } else { // Roam randomly if (!self.roamDirection || Math.random() < 0.01) { self.roamDirection = { x: (Math.random() - 0.5) * 2, y: (Math.random() - 0.5) * 2 }; } var newX = self.x + self.roamDirection.x * self.speed * 0.5; var newY = self.y + self.roamDirection.y * self.speed * 0.5; // Check collision with other enemies before roaming var wouldCollide = false; for (var i = 0; i < enemies.length; i++) { var otherEnemy = enemies[i]; if (otherEnemy === self) continue; // Skip self var edx = newX - otherEnemy.x; var edy = newY - otherEnemy.y; var edistance = Math.sqrt(edx * edx + edy * edy); if (edistance < 70) { // Collision threshold between enemies wouldCollide = true; break; } } // Keep within level bounds and check collisions if (!wouldCollide && newX > 100 && newX < currentLevelData.width - 100) { self.lastX = self.x; self.x = newX; enemyGraphics.scaleX = self.roamDirection.x > 0 ? 1 : -1; } if (!wouldCollide && newY > 1800 && newY < 2200) { self.lastY = self.y; self.y = newY; } } if (self.attackCooldown > 0) { self.attackCooldown--; } }; self.takeDamage = function () { self.health--; LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { // Drop coin var coin = game.addChild(new Coin()); coin.x = self.x; coin.y = self.y; // Add score and combo var baseScore = 10; var comboMultiplier = Math.floor(hero.comboCount / 5) + 1; var finalScore = baseScore * comboMultiplier; LK.setScore(LK.getScore() + finalScore); hero.addCombo(); // Remove from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); updateScoreDisplay(); }; return self; }); var EnemyWarning = Container.expand(function () { var self = Container.call(this); self.targetEnemy = null; self.direction = 'left'; // 'left', 'right', 'up', 'down' self.warningGraphics = null; self.lastAlpha = 0; self.isVisible = false; self.setDirection = function (direction) { if (self.warningGraphics) { self.warningGraphics.destroy(); } var assetName = 'warningArrow' + direction.charAt(0).toUpperCase() + direction.slice(1); self.warningGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.direction = direction; }; self.update = function () { if (!self.targetEnemy || !self.warningGraphics) return; // Check if enemy is still alive var enemyExists = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self.targetEnemy) { enemyExists = true; break; } } if (!enemyExists) { self.hide(); return; } // Calculate distance from hero to enemy var distanceToHero = Math.sqrt(Math.pow(self.targetEnemy.x - hero.x, 2) + Math.pow(self.targetEnemy.y - hero.y, 2)); // Check if enemy is visible on screen var enemyScreenX = self.targetEnemy.x - camera.x; var enemyScreenY = self.targetEnemy.y - camera.y; var isOnScreen = enemyScreenX >= -100 && enemyScreenX <= 2148 && enemyScreenY >= -100 && enemyScreenY <= 2832; if (isOnScreen) { self.hide(); return; } // Calculate warning opacity based on distance (closer = more visible) var maxDistance = 800; var minDistance = 300; var targetAlpha = 0; if (distanceToHero <= maxDistance) { var normalizedDistance = Math.max(0, Math.min(1, (maxDistance - distanceToHero) / (maxDistance - minDistance))); targetAlpha = normalizedDistance * 0.8; } // Smooth alpha transition if (Math.abs(targetAlpha - self.lastAlpha) > 0.01) { tween.stop(self.warningGraphics, { alpha: true }); tween(self.warningGraphics, { alpha: targetAlpha }, { duration: 200 }); self.lastAlpha = targetAlpha; } // Position warning at screen edge var screenCenterX = 1024; var screenCenterY = 1366; var dx = self.targetEnemy.x - hero.x; var dy = self.targetEnemy.y - hero.y; if (Math.abs(dx) > Math.abs(dy)) { // Horizontal warning if (dx > 0) { self.setDirection('right'); self.x = screenCenterX + 900; self.y = screenCenterY + Math.max(-600, Math.min(600, dy * 0.5)); } else { self.setDirection('left'); self.x = screenCenterX - 900; self.y = screenCenterY + Math.max(-600, Math.min(600, dy * 0.5)); } } else { // Vertical warning if (dy > 0) { self.setDirection('down'); self.x = screenCenterX + Math.max(-800, Math.min(800, dx * 0.5)); self.y = screenCenterY + 1200; } else { self.setDirection('up'); self.x = screenCenterX + Math.max(-800, Math.min(800, dx * 0.5)); self.y = screenCenterY - 1200; } } }; self.hide = function () { if (self.warningGraphics && self.warningGraphics.alpha > 0) { tween.stop(self.warningGraphics, { alpha: true }); tween(self.warningGraphics, { alpha: 0 }, { duration: 300 }); self.lastAlpha = 0; } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 1.0 }); self.maxHealth = 5; self.health = self.maxHealth; self.isAttacking = false; self.invulnerable = false; self.damageBoost = false; self.comboCount = 0; self.lastX = 0; self.lastY = 0; self.attack = function (targetX) { if (self.isAttacking) return; self.isAttacking = true; // Face direction of attack if (targetX < self.x) { heroGraphics.scaleX = -1; } else { heroGraphics.scaleX = 1; } // Attack animation tween(heroGraphics, { scaleY: 1.2 }, { duration: 100 }); tween(heroGraphics, { scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { self.isAttacking = false; } }); // Create punch effect var effect = game.addChild(LK.getAsset('punchEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 })); effect.x = self.x + heroGraphics.scaleX * 80; effect.y = self.y - 80; tween(effect, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 200, onFinish: function onFinish() { effect.destroy(); } }); LK.getSound('punch').play(); }; self.takeDamage = function () { if (self.invulnerable) return; self.health--; self.comboCount = 0; // Flash red when hit LK.effects.flashObject(self, 0xff0000, 500); // Temporary invulnerability self.invulnerable = true; LK.setTimeout(function () { self.invulnerable = false; }, 1000); LK.getSound('hit').play(); updateHealthDisplay(); if (self.health <= 0) { LK.showGameOver(); } }; self.heal = function () { if (self.health < self.maxHealth) { self.health++; updateHealthDisplay(); } }; self.addCombo = function () { self.comboCount++; }; self.move = function (direction) { var speed = 5; var newX = self.x; var newY = self.y; if (direction === 'left' && self.x > 100) { newX = self.x - speed; heroGraphics.scaleX = -1; } else if (direction === 'right' && self.x < currentLevelData.width - 100) { newX = self.x + speed; heroGraphics.scaleX = 1; } else if (direction === 'up' && self.y > 1800) { newY = self.y - speed; } else if (direction === 'down' && self.y < 2200) { newY = self.y + speed; } // Check collision with enemies before moving var wouldCollide = false; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = newX - enemy.x; var dy = newY - enemy.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 80) { // Collision threshold wouldCollide = true; break; } } // Only move if no collision would occur if (!wouldCollide) { self.lastX = self.x; self.lastY = self.y; self.x = newX; self.y = newY; } // Update camera target camera.targetX = self.x - 1024; camera.targetY = self.y - 1366; // Clamp camera to level bounds camera.targetX = Math.max(0, Math.min(camera.targetX, currentLevelData.width - 2048)); camera.targetY = Math.max(0, Math.min(camera.targetY, currentLevelData.height - 2732)); }; return self; }); var Knife = Container.expand(function () { var self = Container.call(this); var knifeGraphics = self.attachAsset('knife', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.directionX = 0; self.directionY = 0; self.lastX = 0; self.lastY = 0; self.setDirection = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.directionX = dx / distance; self.directionY = dy / distance; } // Rotate knife to face direction knifeGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2; }; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Check collision with enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var dx = self.x - enemy.x; var dy = self.y - enemy.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 60) { enemy.takeDamage(); self.destroy(); // Remove from knives array for (var j = knives.length - 1; j >= 0; j--) { if (knives[j] === self) { knives.splice(j, 1); break; } } return; } } // Remove if off screen var screenX = self.x - camera.x; var screenY = self.y - camera.y; if (screenX < -100 || screenX > 2148 || screenY < -100 || screenY > 2832) { self.destroy(); // Remove from knives array for (var j = knives.length - 1; j >= 0; j--) { if (knives[j] === self) { knives.splice(j, 1); break; } } } }; function throwKnife(targetX, targetY) { if (knifeCount <= 0) return; var knife = game.addChild(new Knife()); knife.x = hero.x; knife.y = hero.y - 80; knife.setDirection(targetX, targetY); knives.push(knife); knifeCount--; updateScoreDisplay(); LK.getSound('knifeThrow').play(); } // Knife button event handler knifeButton.down = function (x, y, obj) { if (knifeCount > 0) { var nearestEnemy = findNearestEnemy(hero.x, hero.y); if (nearestEnemy) { throwKnife(nearestEnemy.x, nearestEnemy.y); } else { // Throw in hero's facing direction var facingDirection = hero.getChildAt(0).scaleX > 0 ? 1 : -1; throwKnife(hero.x + facingDirection * 300, hero.y); } } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'health'; // 'health', 'invulnerable', 'damage' self.lifetime = 600; // 10 seconds self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.expire(); } // Check collision with hero if (self.intersects(hero)) { self.collect(); } // Pulse animation var scale = 1 + Math.sin(LK.ticks * 0.2) * 0.2; powerupGraphics.scaleX = scale; powerupGraphics.scaleY = scale; }; self.collect = function () { LK.getSound('powerup').play(); if (self.type === 'health') { hero.heal(); } else if (self.type === 'invulnerable') { hero.invulnerable = true; LK.setTimeout(function () { hero.invulnerable = false; }, 5000); } else if (self.type === 'damage') { hero.damageBoost = true; LK.setTimeout(function () { hero.damageBoost = false; }, 5000); } // Remove from powerups array for (var i = powerups.length - 1; i >= 0; i--) { if (powerups[i] === self) { powerups.splice(i, 1); break; } } self.destroy(); }; self.expire = function () { // Remove from powerups array for (var i = powerups.length - 1; i >= 0; i--) { if (powerups[i] === self) { powerups.splice(i, 1); break; } } self.destroy(); }; return self; }); var RouteDisplay = Container.expand(function () { var self = Container.call(this); self.routeSegments = []; self.routeEffect = null; self.isVisible = false; self.showRoute = function (startX, startY, endX, endY) { self.hideRoute(); // Calculate route direction and distance var dx = endX - startX; var dy = endY - startY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance === 0) return; // Create route segments along the line var segments = Math.floor(distance / 20); // One segment every 20 pixels var stepX = dx / segments; var stepY = dy / segments; for (var i = 0; i < segments; i++) { var segment = self.addChild(LK.getAsset('routeLine', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 })); segment.x = startX + stepX * i; segment.y = startY + stepY * i; // Rotate segment to align with route direction segment.rotation = Math.atan2(dy, dx); self.routeSegments.push(segment); // Animate segment appearance tween(segment, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 800, onFinish: function onFinish() { if (segment.parent) { segment.destroy(); } } }); } // Create effect at player position self.routeEffect = self.addChild(LK.getAsset('routeEffect', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 })); self.routeEffect.x = startX; self.routeEffect.y = startY; // Animate effect tween(self.routeEffect, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { if (self.routeEffect && self.routeEffect.parent) { self.routeEffect.destroy(); self.routeEffect = null; } } }); self.isVisible = true; // Auto-hide after duration LK.setTimeout(function () { self.hideRoute(); }, 1000); }; self.hideRoute = function () { // Clear existing route segments for (var i = self.routeSegments.length - 1; i >= 0; i--) { if (self.routeSegments[i].parent) { self.routeSegments[i].destroy(); } } self.routeSegments = []; // Clear route effect if (self.routeEffect && self.routeEffect.parent) { self.routeEffect.destroy(); self.routeEffect = null; } self.isVisible = false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Game variables var hero; var enemies = []; var coins = []; var powerups = []; var enemyWarnings = []; var knives = []; var knifeCount = 5; var routeDisplay; var currentLevel = 1; var levelComplete = false; var hearts = []; // Movement state tracking var movementState = { left: false, right: false, up: false, down: false }; // Camera system var camera = { x: 0, y: 0, targetX: 0, targetY: 0, smoothing: 0.1 }; // Level configuration var levels = [{ enemies: [{ type: 'basic', count: 3 }], width: 4096, height: 2732 }, { enemies: [{ type: 'basic', count: 5 }, { type: 'strong', count: 2 }], width: 5120, height: 2732 }, { enemies: [{ type: 'basic', count: 7 }, { type: 'strong', count: 3 }, { type: 'fast', count: 2 }], width: 6144, height: 2732 }]; var currentLevelData = levels[0]; // UI Elements var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); scoreText.x = 150; scoreText.y = 50; LK.gui.topLeft.addChild(scoreText); var levelText = new Text2('Level: 1', { size: 80, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 50; var comboText = new Text2('Combo: 0x', { size: 60, fill: 0xFFFF00 }); comboText.anchor.set(1, 0); LK.gui.topRight.addChild(comboText); comboText.x = -50; comboText.y = 120; var knifeText = new Text2('Knives: 5', { size: 60, fill: 0x8e44ad }); knifeText.anchor.set(1, 0); LK.gui.topRight.addChild(knifeText); knifeText.x = -50; knifeText.y = 190; // Create movement and attack buttons var leftButton = LK.getAsset('leftButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); leftButton.x = 120; leftButton.y = -250; LK.gui.bottomLeft.addChild(leftButton); var rightButton = LK.getAsset('rightButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); rightButton.x = 400; rightButton.y = -250; LK.gui.bottomLeft.addChild(rightButton); var upButton = LK.getAsset('upButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); upButton.x = 260; upButton.y = -380; LK.gui.bottomLeft.addChild(upButton); var downButton = LK.getAsset('downButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); downButton.x = 260; downButton.y = -120; LK.gui.bottomLeft.addChild(downButton); var attackButton = LK.getAsset('attackButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); attackButton.x = -150; attackButton.y = -200; LK.gui.bottomRight.addChild(attackButton); var knifeButton = LK.getAsset('knifeButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); knifeButton.x = -150; knifeButton.y = -380; LK.gui.bottomRight.addChild(knifeButton); // Create hero hero = game.addChild(new Hero()); hero.x = 1024; // Center of screen hero.y = 2200; // Near bottom // Create route display routeDisplay = game.addChild(new RouteDisplay()); // Create health display function updateHealthDisplay() { // Remove existing hearts for (var i = hearts.length - 1; i >= 0; i--) { hearts[i].destroy(); } hearts = []; // Create new hearts for (var i = 0; i < hero.health; i++) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); heart.x = 200 + i * 80; heart.y = 200; LK.gui.topLeft.addChild(heart); hearts.push(heart); } } function updateScoreDisplay() { scoreText.setText('Score: ' + LK.getScore()); var comboMultiplier = Math.floor(hero.comboCount / 5) + 1; comboText.setText('Combo: ' + comboMultiplier + 'x'); knifeText.setText('Knives: ' + knifeCount); } function initializeLevel() { // Clear existing enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } enemies = []; // Clear existing warnings for (var i = enemyWarnings.length - 1; i >= 0; i--) { enemyWarnings[i].destroy(); } enemyWarnings = []; // Clear existing knives for (var i = knives.length - 1; i >= 0; i--) { knives[i].destroy(); } knives = []; // Reset knife count for new level knifeCount = 5; currentLevelData = levels[currentLevel - 1] || levels[levels.length - 1]; levelComplete = false; // Spawn enemies for this level for (var j = 0; j < currentLevelData.enemies.length; j++) { var enemyGroup = currentLevelData.enemies[j]; for (var k = 0; k < enemyGroup.count; k++) { spawnEnemy(enemyGroup.type); } } levelText.setText('Level: ' + currentLevel); } function spawnEnemy(type) { var enemy = game.addChild(new Enemy()); // Random spawn position within level bounds enemy.x = 200 + Math.random() * (currentLevelData.width - 400); enemy.y = 1900 + Math.random() * 200; // Set enemy properties based on type if (type === 'basic') { enemy.health = 2; enemy.speed = 1; } else if (type === 'strong') { enemy.health = 4; enemy.speed = 0.8; enemy.getChildAt(0).tint = 0x8b4513; // Brown tint } else if (type === 'fast') { enemy.health = 1; enemy.speed = 2; enemy.getChildAt(0).tint = 0x00ff00; // Green tint } enemies.push(enemy); } function spawnPowerUp() { var powerup = game.addChild(new PowerUp()); powerup.x = 500 + Math.random() * 1048; // Random x position powerup.y = 2000; // Above ground level // Random powerup type var types = ['health', 'invulnerable', 'damage']; powerup.type = types[Math.floor(Math.random() * types.length)]; // Color by type var powerupGraphics = powerup.getChildAt(0); if (powerup.type === 'health') { powerupGraphics.tint = 0x00ff00; // Green } else if (powerup.type === 'invulnerable') { powerupGraphics.tint = 0x0088ff; // Blue } else if (powerup.type === 'damage') { powerupGraphics.tint = 0xff8800; // Orange } powerups.push(powerup); } function findNearestEnemy(x, y) { var nearest = null; var shortestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - x, 2) + Math.pow(enemy.y - y, 2)); if (distance < shortestDistance) { shortestDistance = distance; nearest = enemy; } } return nearest; } function updateEnemyWarnings() { // Remove warnings for dead enemies for (var i = enemyWarnings.length - 1; i >= 0; i--) { var warning = enemyWarnings[i]; var enemyExists = false; for (var j = 0; j < enemies.length; j++) { if (enemies[j] === warning.targetEnemy) { enemyExists = true; break; } } if (!enemyExists) { warning.destroy(); enemyWarnings.splice(i, 1); } } // Create warnings for new enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var hasWarning = false; for (var j = 0; j < enemyWarnings.length; j++) { if (enemyWarnings[j].targetEnemy === enemy) { hasWarning = true; break; } } if (!hasWarning) { var warning = LK.gui.center.addChild(new EnemyWarning()); warning.targetEnemy = enemy; warning.setDirection('left'); enemyWarnings.push(warning); } } } // Initialize UI updateHealthDisplay(); updateScoreDisplay(); // Initialize first level initializeLevel(); // Set initial camera position camera.targetX = hero.x - 1024; camera.targetY = hero.y - 1366; camera.x = camera.targetX; camera.y = camera.targetY; // Button event handlers leftButton.down = function (x, y, obj) { movementState.left = true; }; leftButton.up = function (x, y, obj) { movementState.left = false; }; rightButton.down = function (x, y, obj) { movementState.right = true; }; rightButton.up = function (x, y, obj) { movementState.right = false; }; upButton.down = function (x, y, obj) { movementState.up = true; }; upButton.up = function (x, y, obj) { movementState.up = false; }; downButton.down = function (x, y, obj) { movementState.down = true; }; downButton.up = function (x, y, obj) { movementState.down = false; }; attackButton.down = function (x, y, obj) { if (!hero.isAttacking) { var nearestEnemy = findNearestEnemy(hero.x, hero.y); if (nearestEnemy) { // Show route from enemy to player routeDisplay.showRoute(nearestEnemy.x, nearestEnemy.y, hero.x, hero.y); hero.attack(nearestEnemy.x); // Check if attack hits with increased range var distanceToEnemy = Math.sqrt(Math.pow(hero.x - nearestEnemy.x, 2) + Math.pow(hero.y - nearestEnemy.y, 2)); if (distanceToEnemy < 250) { // Increased from 150 to 250 var damage = hero.damageBoost ? 2 : 1; for (var i = 0; i < damage; i++) { nearestEnemy.takeDamage(); } } } else { // Attack in hero's facing direction hero.attack(hero.x + (hero.getChildAt(0).scaleX > 0 ? 100 : -100)); } } }; // Game input (fallback for screen taps outside buttons) game.down = function (x, y, obj) { // Convert screen coordinates to world coordinates var worldX = x + camera.x; var worldY = y + camera.y; // Check if tap is for movement or attack var distanceToHero = Math.sqrt(Math.pow(worldX - hero.x, 2) + Math.pow(worldY - hero.y, 2)); if (distanceToHero > 200) { // Movement - move toward tap position var dx = worldX - hero.x; var dy = worldY - hero.y; if (Math.abs(dx) > Math.abs(dy)) { hero.move(dx > 0 ? 'right' : 'left'); } else { hero.move(dy > 0 ? 'down' : 'up'); } } else { // Attack if (!hero.isAttacking) { var nearestEnemy = findNearestEnemy(worldX, worldY); if (nearestEnemy) { // Show route from enemy to player routeDisplay.showRoute(nearestEnemy.x, nearestEnemy.y, hero.x, hero.y); hero.attack(nearestEnemy.x); // Check if attack hits with increased range var distanceToEnemy = Math.sqrt(Math.pow(hero.x - nearestEnemy.x, 2) + Math.pow(hero.y - nearestEnemy.y, 2)); if (distanceToEnemy < 250) { // Increased from 150 to 250 var damage = hero.damageBoost ? 2 : 1; for (var i = 0; i < damage; i++) { nearestEnemy.takeDamage(); } } } else { // Attack in direction of tap hero.attack(worldX); } } } }; // Main game loop game.update = function () { // Handle continuous movement based on button states if (movementState.left) { hero.move('left'); } if (movementState.right) { hero.move('right'); } if (movementState.up) { hero.move('up'); } if (movementState.down) { hero.move('down'); } // Update camera position smoothly camera.x += (camera.targetX - camera.x) * camera.smoothing; camera.y += (camera.targetY - camera.y) * camera.smoothing; // Apply camera position to game game.x = -camera.x; game.y = -camera.y; // Update all game objects for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemy.update(); } for (var i = coins.length - 1; i >= 0; i--) { coins[i].update(); } for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].update(); } // Update knives for (var i = knives.length - 1; i >= 0; i--) { knives[i].update(); } // Update enemy warnings updateEnemyWarnings(); for (var i = 0; i < enemyWarnings.length; i++) { enemyWarnings[i].update(); } // Check for level completion if (!levelComplete && enemies.length === 0) { levelComplete = true; currentLevel++; if (currentLevel <= levels.length) { // Start next level after delay LK.setTimeout(function () { initializeLevel(); }, 2000); } else { // Game completed LK.showYouWin(); } } };
===================================================================
--- original.js
+++ change.js
@@ -390,8 +390,94 @@
camera.targetY = Math.max(0, Math.min(camera.targetY, currentLevelData.height - 2732));
};
return self;
});
+var Knife = Container.expand(function () {
+ var self = Container.call(this);
+ var knifeGraphics = self.attachAsset('knife', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 8;
+ self.directionX = 0;
+ self.directionY = 0;
+ self.lastX = 0;
+ self.lastY = 0;
+ self.setDirection = function (targetX, targetY) {
+ var dx = targetX - self.x;
+ var dy = targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ self.directionX = dx / distance;
+ self.directionY = dy / distance;
+ }
+ // Rotate knife to face direction
+ knifeGraphics.rotation = Math.atan2(dy, dx) + Math.PI / 2;
+ };
+ self.update = function () {
+ self.lastX = self.x;
+ self.lastY = self.y;
+ self.x += self.directionX * self.speed;
+ self.y += self.directionY * self.speed;
+ // Check collision with enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ var dx = self.x - enemy.x;
+ var dy = self.y - enemy.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 60) {
+ enemy.takeDamage();
+ self.destroy();
+ // Remove from knives array
+ for (var j = knives.length - 1; j >= 0; j--) {
+ if (knives[j] === self) {
+ knives.splice(j, 1);
+ break;
+ }
+ }
+ return;
+ }
+ }
+ // Remove if off screen
+ var screenX = self.x - camera.x;
+ var screenY = self.y - camera.y;
+ if (screenX < -100 || screenX > 2148 || screenY < -100 || screenY > 2832) {
+ self.destroy();
+ // Remove from knives array
+ for (var j = knives.length - 1; j >= 0; j--) {
+ if (knives[j] === self) {
+ knives.splice(j, 1);
+ break;
+ }
+ }
+ }
+ };
+ function throwKnife(targetX, targetY) {
+ if (knifeCount <= 0) return;
+ var knife = game.addChild(new Knife());
+ knife.x = hero.x;
+ knife.y = hero.y - 80;
+ knife.setDirection(targetX, targetY);
+ knives.push(knife);
+ knifeCount--;
+ updateScoreDisplay();
+ LK.getSound('knifeThrow').play();
+ }
+ // Knife button event handler
+ knifeButton.down = function (x, y, obj) {
+ if (knifeCount > 0) {
+ var nearestEnemy = findNearestEnemy(hero.x, hero.y);
+ if (nearestEnemy) {
+ throwKnife(nearestEnemy.x, nearestEnemy.y);
+ } else {
+ // Throw in hero's facing direction
+ var facingDirection = hero.getChildAt(0).scaleX > 0 ? 1 : -1;
+ throwKnife(hero.x + facingDirection * 300, hero.y);
+ }
+ }
+ };
+ return self;
+});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
@@ -552,8 +638,10 @@
var enemies = [];
var coins = [];
var powerups = [];
var enemyWarnings = [];
+var knives = [];
+var knifeCount = 5;
var routeDisplay;
var currentLevel = 1;
var levelComplete = false;
var hearts = [];
@@ -628,8 +716,16 @@
comboText.anchor.set(1, 0);
LK.gui.topRight.addChild(comboText);
comboText.x = -50;
comboText.y = 120;
+var knifeText = new Text2('Knives: 5', {
+ size: 60,
+ fill: 0x8e44ad
+});
+knifeText.anchor.set(1, 0);
+LK.gui.topRight.addChild(knifeText);
+knifeText.x = -50;
+knifeText.y = 190;
// Create movement and attack buttons
var leftButton = LK.getAsset('leftButton', {
anchorX: 0.5,
anchorY: 0.5,
@@ -669,8 +765,16 @@
});
attackButton.x = -150;
attackButton.y = -200;
LK.gui.bottomRight.addChild(attackButton);
+var knifeButton = LK.getAsset('knifeButton', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.9
+});
+knifeButton.x = -150;
+knifeButton.y = -380;
+LK.gui.bottomRight.addChild(knifeButton);
// Create hero
hero = game.addChild(new Hero());
hero.x = 1024; // Center of screen
hero.y = 2200; // Near bottom
@@ -698,8 +802,9 @@
function updateScoreDisplay() {
scoreText.setText('Score: ' + LK.getScore());
var comboMultiplier = Math.floor(hero.comboCount / 5) + 1;
comboText.setText('Combo: ' + comboMultiplier + 'x');
+ knifeText.setText('Knives: ' + knifeCount);
}
function initializeLevel() {
// Clear existing enemies
for (var i = enemies.length - 1; i >= 0; i--) {
@@ -710,8 +815,15 @@
for (var i = enemyWarnings.length - 1; i >= 0; i--) {
enemyWarnings[i].destroy();
}
enemyWarnings = [];
+ // Clear existing knives
+ for (var i = knives.length - 1; i >= 0; i--) {
+ knives[i].destroy();
+ }
+ knives = [];
+ // Reset knife count for new level
+ knifeCount = 5;
currentLevelData = levels[currentLevel - 1] || levels[levels.length - 1];
levelComplete = false;
// Spawn enemies for this level
for (var j = 0; j < currentLevelData.enemies.length; j++) {
@@ -935,8 +1047,12 @@
}
for (var i = powerups.length - 1; i >= 0; i--) {
powerups[i].update();
}
+ // Update knives
+ for (var i = knives.length - 1; i >= 0; i--) {
+ knives[i].update();
+ }
// Update enemy warnings
updateEnemyWarnings();
for (var i = 0; i < enemyWarnings.length; i++) {
enemyWarnings[i].update();