User prompt
scoreboard koy düşman öldürdükçe artsın karakter ölünce sıfırlansın ve
User prompt
durduk yere ölüyorum fixle
User prompt
ana karakter patlamalardan ve üstünde doğan düşmanlardan etilenmesin ve her düşman patlamasın arada random olarak çıksın
User prompt
git gide düşmanları hızlandır ve toplu düşman yerlerinde bir düşman öldüğü zaman patlayıp etrafındakileri de patlatsın ana karakterimizi de tek vuruşta ölecek şekilde ayarlama biraz daha kaçabilecek canımız olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ateş hızıyla düşmanlar doğru orantılı olacak
User prompt
hala ateş edildikçe canları azamıyor düşmanların
User prompt
oyun çöktü bu kadar fazla düşman yapma
User prompt
düşmanların hızını ilk başlangıçta düşür sonradan da her ölen bir düşman sonunda yeni +1 düşman spawn olup karakteri kovalamaya başlasın. Bu durum ilerledikçe mermilerin atış hızı yavaş yavaş hızlanacak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşmanların canı %100 ile başlayacak her mermi isabet ettiğinde %25 azlacak
User prompt
mermi isabet ettikçe canı azalsın isityorum isabet ediyor canları gitmiyor
User prompt
mermi isabet edince düşmanın canı azalmıyor
User prompt
ateş edildikçe ateş edilen düşmanın canı azamaya başlaşın ilk mermi dokunmasından sonra ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşmanlar farklı yerlerden gelecek ve ana karakter en yakına ateş edecek merminin gittiğini de efekt olarak görmek istiyorum ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yakın uzak farket etmez silahla ateş edecek ana karakter ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşmanlara ateş edecek ana karakter ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
düşmanlar üstümüze gelmeye devam edecek sadece otomatik düşmanlara ateş edecek ve ateş efekti çıkacak onlar da bize ateş etsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
bir de otomatik ateş etsin her kaçtığımızda ve düşmanlar da aynı yerden gelmek yerine random hareket etsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
tamam mouse la hareket ettirmek yerine bastığımız yere gitsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Arena Clash PvP
Initial prompt
Basit bir 2D web tabanlı arena PvP oyunu yap. Oyuncular yukarı, aşağı, sola, sağa hareket edebilsin. Her oyuncunun canı olsun. Saldırı yapabilsinler. Biri ölünce birkaç saniye sonra yeniden doğsun. Oyun HTML5 ve JavaScript ile tarayıcıda çalışsın.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('attackEffect', { anchorX: 0.5, anchorY: 0.5 }); bulletGraphics.scaleX = 0.5; bulletGraphics.scaleY = 0.5; // Set bullet speed based on boost status self.speed = bulletSpeedBoostTimer > 0 ? baseBulletSpeed * 1.5 : baseBulletSpeed; self.targetX = 0; self.targetY = 0; self.damage = 0; self.isPlayerBullet = true; self.targetEnemy = null; // Specific enemy this bullet is targeting self.update = function () { // Check for direct collision with enemies/player regardless of distance if (self.isPlayerBullet) { // Only check collision with the specific target enemy if (self.targetEnemy && !self.targetEnemy.isRespawning && !self.targetEnemy.destroyed && self.intersects(self.targetEnemy)) { self.targetEnemy.takeDamage(self.damage); self.destroy(); return; } } else { // Enemy bullet hitting player if (!player.isRespawning && self.intersects(player)) { player.takeDamage(self.damage); self.destroy(); return; } } var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If reached target position, destroy bullet if (distance < self.speed) { self.destroy(); return; } // Move towards target var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; // Remove if out of bounds if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) { self.destroy(); } }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -60 }); var healthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -60 }); self.maxHealth = 30; // Reduced health for faster kills like Vampire Survivors self.health = 30; self.speed = 2; self.attackRange = 120; self.attackDamage = 8; // Higher damage but less health overall self.attackCooldown = 0; self.isRespawning = false; self.respawnTimer = 0; self.aiTimer = 0; self.spawnImmunityTimer = 0; // Prevents attacking immediately after spawn self.targetX = 0; self.targetY = 0; self.takeDamage = function (damage) { if (self.isRespawning || self.health <= 0) return; // Don't take damage if already dead // Vampire Survivors style damage - each hit does significant damage but not instant kill self.health -= damage; if (self.health < 0) self.health = 0; self.updateHealthBar(); // Flash red when taking damage tween(enemyGraphics, { tint: 0xFF0000 }, { duration: 200, onFinish: function onFinish() { tween(enemyGraphics, { tint: 0xFFFFFF }, { duration: 200 }); } }); if (self.health <= 0) { self.die(); } LK.getSound('hit').play(); }; self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; healthBar.scaleX = healthPercent; if (healthPercent > 0.6) { healthBar.tint = 0x00FF00; } else if (healthPercent > 0.3) { healthBar.tint = 0xFFFF00; } else { healthBar.tint = 0xFF0000; } }; self.die = function () { self.isRespawning = true; self.respawnTimer = 180; // 3 seconds at 60fps enemyGraphics.visible = false; healthBar.visible = false; healthBarBg.visible = false; // Move enemy far off-screen during respawn to prevent collision issues self.x = -1000; self.y = -1000; // Increment killed count and spawn new enemy only if under limit enemiesKilled++; score++; scoreText.setText('Score: ' + score); if (enemies.length < maxEnemies) { spawnNewEnemy(); } }; self.respawn = function () { self.health = self.maxHealth; // Set position first before making visible self.x = 300 + Math.random() * 1400; self.y = 400 + Math.random() * 1800; // Reset spawn immunity self.spawnImmunityTimer = 60; // 1 second of spawn immunity // Then update state and make visible self.isRespawning = false; self.respawnTimer = 0; enemyGraphics.visible = true; enemyGraphics.alpha = 1; healthBar.visible = true; healthBarBg.visible = true; self.updateHealthBar(); LK.getSound('respawn').play(); }; self.attack = function () { if (self.attackCooldown > 0 || self.isRespawning || self.spawnImmunityTimer > 0) return; self.attackCooldown = 120; // 2 second cooldown if (!player.isRespawning) { // Create bullet projectile towards player var bullet = game.addChild(new Bullet()); bullet.x = self.x; bullet.y = self.y; bullet.targetX = player.x; bullet.targetY = player.y; bullet.damage = self.attackDamage; bullet.isPlayerBullet = false; bullets.push(bullet); } // Create attack effect var attackEffect = LK.getAsset('attackEffect', { anchorX: 0.5, anchorY: 0.5 }); attackEffect.x = self.x; attackEffect.y = self.y; attackEffect.alpha = 0.7; attackEffect.tint = 0xFF4444; attackEffect.scaleX = 0.8; attackEffect.scaleY = 0.8; game.addChild(attackEffect); // Scale and fade out attack effect tween(attackEffect, { scaleX: 1.2, scaleY: 1.2, alpha: 0 }, { duration: 200, onFinish: function onFinish() { attackEffect.destroy(); } }); LK.getSound('attack').play(); }; self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } if (self.spawnImmunityTimer > 0) { self.spawnImmunityTimer--; // Flash during spawn immunity period if (self.spawnImmunityTimer % 10 < 5) { enemyGraphics.alpha = 0.7; } else { enemyGraphics.alpha = 1; } } if (self.isRespawning) { self.respawnTimer--; if (self.respawnTimer <= 0) { self.respawn(); } return; } // Chase player AI - move towards player and attack when close if (!player.isRespawning) { var dx = player.x - self.x; var dy = player.y - self.y; var playerDistance = Math.sqrt(dx * dx + dy * dy); // Move towards player with speed multiplier var currentSpeed = self.speed * enemySpeedMultiplier; if (playerDistance > currentSpeed) { // Create a formation around the player instead of direct chase // Update AI timer for random movement changes self.aiTimer++; if (self.aiTimer >= 60) { // Change direction every second self.aiTimer = 0; // Calculate a preferred distance from player (spread enemies out) var preferredDistance = 180 + Math.random() * 120; // 180-300 pixels from player // If too close to preferred distance, move in a circular pattern if (playerDistance < preferredDistance + 50) { // Move in circular pattern around player var circleAngle = Math.atan2(dy, dx) + (Math.random() - 0.5) * Math.PI; // Add large random offset var moveX = Math.cos(circleAngle) * currentSpeed * 0.7; // Slower circular movement var moveY = Math.sin(circleAngle) * currentSpeed * 0.7; } else { // Generate random offset angle (-60 to +60 degrees) for wider spread var offsetAngle = (Math.random() - 0.5) * Math.PI / 1.5; // ±60 degrees in radians var baseAngle = Math.atan2(dy, dx); var newAngle = baseAngle + offsetAngle; var moveX = Math.cos(newAngle) * currentSpeed * 0.8; // Slightly slower approach var moveY = Math.sin(newAngle) * currentSpeed * 0.8; } } else { // Use stored movement direction with slight randomness var moveX = dx / playerDistance * currentSpeed * 0.9; var moveY = dy / playerDistance * currentSpeed * 0.9; } self.x += moveX; self.y += moveY; } // Attack if close enough to player if (playerDistance <= self.attackRange) { self.attack(); } } // Check collision with other enemies and push away if overlapping for (var e = 0; e < enemies.length; e++) { var otherEnemy = enemies[e]; if (otherEnemy !== self && !otherEnemy.isRespawning && !self.isRespawning) { var dx = otherEnemy.x - self.x; var dy = otherEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var minDistance = 120; // Reduced minimum distance to allow enemies closer together if (distance < minDistance && distance > 0) { // Calculate push direction (away from other enemy) with reduced force var pushStrength = (minDistance - distance) * 1.2; // Reduced push force var pushX = -(dx / distance) * pushStrength; var pushY = -(dy / distance) * pushStrength; // Apply moderate push force to separate enemies self.x += pushX; self.y += pushY; // Also apply counter-force to the other enemy for better separation otherEnemy.x += dx / distance * pushStrength * 0.5; otherEnemy.y += dy / distance * pushStrength * 0.5; } } } // Keep enemy in bounds if (self.x < 150) self.x = 150; if (self.x > 1898) self.x = 1898; if (self.y < 150) self.y = 150; if (self.y > 2582) self.y = 2582; }; return self; }); var HealthPack = Container.expand(function () { var self = Container.call(this); var healthPackGraphics = self.attachAsset('healthPack', { anchorX: 0.5, anchorY: 0.5 }); self.healAmount = 25; // Heal amount (50% of max health for new system) self.lifetime = 600; // 10 seconds at 60fps // Pulse animation for visibility var pulseDirection = 1; var pulseSpeed = 0.02; self.update = function () { // Pulse animation healthPackGraphics.scaleX += pulseDirection * pulseSpeed; healthPackGraphics.scaleY += pulseDirection * pulseSpeed; if (healthPackGraphics.scaleX > 1.3 || healthPackGraphics.scaleX < 0.8) { pulseDirection *= -1; } // Reduce lifetime self.lifetime--; if (self.lifetime <= 0) { self.destroy(); } // Check collision with player if (!player.isRespawning && self.intersects(player)) { // Heal player var oldHealth = player.health; player.health = Math.min(player.maxHealth, player.health + self.healAmount); player.updateHealthBar(); // Give immunity for 2 seconds player.immunityTimer = 120; // Increase bullet speed for 3 seconds bulletSpeedBoostTimer = 180; // 3 seconds at 60fps // Visual effect tween(healthPackGraphics, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); LK.getSound('heal').play(); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var healthBarBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -60 }); var healthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -60 }); self.maxHealth = 50; // Reduced health like Vampire Survivors self.health = 50; self.speed = 8; self.attackRange = 100; self.attackDamage = 15; // Balanced damage for new health system self.attackCooldown = 0; self.isRespawning = false; self.respawnTimer = 0; self.immunityTimer = 0; // Immunity period after respawn self.takeDamage = function (damage, source) { if (self.isRespawning || self.immunityTimer > 0) return; // Prevent damage from explosions and enemy spawning if (source === 'explosion' || source === 'spawn') { return; } self.health -= damage; if (self.health < 0) self.health = 0; self.updateHealthBar(); // Flash red when taking damage tween(playerGraphics, { tint: 0xFF0000 }, { duration: 200, onFinish: function onFinish() { tween(playerGraphics, { tint: 0xFFFFFF }, { duration: 200 }); } }); if (self.health <= 0) { self.die(); } LK.getSound('hit').play(); }; self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; healthBar.scaleX = healthPercent; if (healthPercent > 0.6) { healthBar.tint = 0x00FF00; } else if (healthPercent > 0.3) { healthBar.tint = 0xFFFF00; } else { healthBar.tint = 0xFF0000; } }; self.die = function () { // Show game over screen which will reset the game LK.showGameOver(); }; self.respawn = function () { self.health = self.maxHealth; self.isRespawning = false; self.respawnTimer = 0; playerGraphics.alpha = 1; healthBar.visible = true; healthBarBg.visible = true; self.updateHealthBar(); // Respawn at center position since map is reset self.x = 500; self.y = 1000; // Add brief immunity period after respawn self.immunityTimer = 180; // 3 seconds of immunity // Spawn initial enemies after map reset for (var i = 0; i < 3; i++) { spawnNewEnemy(); } LK.getSound('respawn').play(); }; // Vampire Survivors style automatic shooting - no manual attack method needed self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } if (self.immunityTimer > 0) { self.immunityTimer--; // Flash during immunity period if (self.immunityTimer % 10 < 5) { playerGraphics.alpha = 0.5; } else { playerGraphics.alpha = 1; } } if (self.isRespawning) { self.respawnTimer--; if (self.respawnTimer <= 0) { self.respawn(); } return; } // Vampire Survivors style automatic continuous shooting if (self.attackCooldown <= 0) { // Find closest enemy within range var closestEnemy = null; var closestDistance = Infinity; var maxRange = 400; // Maximum shooting range for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (!enemy.isRespawning) { var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2)); if (distance < closestDistance && distance <= maxRange) { closestDistance = distance; closestEnemy = enemy; } } } if (closestEnemy) { // Set attack cooldown based on fire rate var baseFireRate = 30; // Base frames between shots (faster than before) var fireRateReduction = Math.min(fireRateBoostLevel * 2, baseFireRate * 0.4); self.attackCooldown = baseFireRate - fireRateReduction; // Create bullet projectile var bullet = game.addChild(new Bullet()); bullet.x = self.x; bullet.y = self.y; bullet.targetX = closestEnemy.x; bullet.targetY = closestEnemy.y; bullet.damage = self.attackDamage; bullet.isPlayerBullet = true; bullet.targetEnemy = closestEnemy; bullets.push(bullet); // Create muzzle flash effect var attackEffect = LK.getAsset('attackEffect', { anchorX: 0.5, anchorY: 0.5 }); attackEffect.x = self.x; attackEffect.y = self.y; attackEffect.alpha = 0.7; attackEffect.tint = 0x4499FF; attackEffect.scaleX = 0.6; attackEffect.scaleY = 0.6; game.addChild(attackEffect); // Scale and fade out attack effect tween(attackEffect, { scaleX: 1.0, scaleY: 1.0, alpha: 0 }, { duration: 150, onFinish: function onFinish() { attackEffect.destroy(); } }); LK.getSound('attack').play(); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ // Create arena background var arena = game.addChild(LK.getAsset('arena', { anchorX: 0.5, anchorY: 0.5 })); arena.x = 2048 / 2; arena.y = 2732 / 2; // Game variables var player; var enemies = []; var bullets = []; var moveUp = false; var moveDown = false; var moveLeft = false; var moveRight = false; var targetX = 0; var targetY = 0; var isMovingToTarget = false; var enemiesKilled = 0; var score = 0; var baseFireRate = 30; // Base attack cooldown - Vampire Survivors style faster firing var currentFireRate = 30; var fireRateBoostLevel = 0; // Tracks fire rate improvements var maxEnemies = 8; // Base maximum number of enemies allowed var enemySpeedMultiplier = 1.0; // Gradually increases enemy speed var explosionRadius = 150; // Radius for chain explosions var difficultyLevel = 0; // Current difficulty level var lastDifficultyScore = 0; // Score at last difficulty increase var healthPacks = []; var lastHealthPackSpawn = 0; var bulletSpeedBoostTimer = 0; // Timer for bullet speed boost var baseBulletSpeed = 15; // Base bullet speed var enemySpawnTimer = 0; // Timer for continuous enemy spawning var baseSpawnInterval = 120; // Base spawn interval (2 seconds at 60fps) var nextHealthRestoreScore = 1000; // Score threshold for next health restore var hasRestoredHealthAtThreshold = false; // Track if health was restored at current threshold // Start main music LK.playMusic('Main'); // Initialize music state tracking game.main1Playing = false; game.main3Playing = false; game.randomMusicPlaying = false; // Create player player = game.addChild(new Player()); player.x = 500; player.y = 1000; // Function to spawn new enemy from off-screen edges (Vampire Survivors style) function spawnNewEnemy() { var enemy = game.addChild(new Enemy()); // Choose random edge to spawn from (off-screen) var spawnSide = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left var spawnOffset = Math.random(); // Random position along edge (0% to 100%) // Spawn outside visible area for true Vampire Survivors effect var offScreenDistance = 100; // Distance outside visible area switch (spawnSide) { case 0: // Top edge - spawn above screen enemy.x = spawnOffset * 2048; enemy.y = -offScreenDistance; break; case 1: // Right edge - spawn to the right of screen enemy.x = 2048 + offScreenDistance; enemy.y = spawnOffset * 2732; break; case 2: // Bottom edge - spawn below screen enemy.x = spawnOffset * 2048; enemy.y = 2732 + offScreenDistance; break; case 3: // Left edge - spawn to the left of screen enemy.x = -offScreenDistance; enemy.y = spawnOffset * 2732; break; } // Give new enemies a brief spawn immunity to prevent instant collision damage enemy.spawnImmunityTimer = 60; // 1 second of spawn immunity enemy.targetX = enemy.x; enemy.targetY = enemy.y; enemies.push(enemy); } // Initial enemies will be spawned by the continuous spawning system // No need for initial spawn - let the timer handle it // UI Elements var instructionText = new Text2('Tap to move - Auto attack enemies nearby', { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); LK.gui.top.addChild(instructionText); instructionText.y = 100; // Score display var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFD700 }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 150; var dragNode = null; var lastTouchTime = 0; // Touch controls game.down = function (x, y, obj) { if (player.isRespawning) return; // Keep target position in bounds targetX = Math.max(150, Math.min(1898, x)); targetY = Math.max(150, Math.min(2582, y)); // Stop any current movement tween tween.stop(player, { x: true, y: true }); // Calculate distance for duration (closer = faster) var distance = Math.sqrt(Math.pow(targetX - player.x, 2) + Math.pow(targetY - player.y, 2)); var duration = Math.max(200, Math.min(1000, distance * 2)); // 200ms to 1000ms based on distance isMovingToTarget = true; // Tween player to target position tween(player, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut, onFinish: function onFinish() { isMovingToTarget = false; } }); }; game.move = function (x, y, obj) { // No drag movement needed - player moves via tween to clicked position }; game.up = function (x, y, obj) { // No action needed - player auto-attacks when moving }; // Main game loop game.update = function () { // Vampire Survivors style continuous enemy spawning enemySpawnTimer++; var currentSpawnInterval = Math.max(30, baseSpawnInterval - Math.floor(score / 50) * 10); // Faster spawning as score increases if (enemySpawnTimer >= currentSpawnInterval && enemies.length < maxEnemies + difficultyLevel) { spawnNewEnemy(); enemySpawnTimer = 0; // Reset spawn timer } // Music transitions based on score if (score >= 100 && score < 500) { // Play main1 music from score 100 to 500 if (!game.main1Playing) { LK.stopMusic(); LK.playMusic('main1'); game.main1Playing = true; } } else if (score >= 500 && score < 1500) { // Play main2 music from score 500 to 1500 if (game.main1Playing) { LK.stopMusic(); LK.playMusic('main2'); game.main1Playing = false; } } else if (score >= 1500 && score < 3000) { // Play main3 music from score 1500 to 3000 if (game.main1Playing || !game.main3Playing) { LK.stopMusic(); LK.playMusic('main3'); game.main1Playing = false; game.main3Playing = true; } } else if (score >= 3000) { // Random music rotation every 2000 points after 3000 var musicThreshold = 3000 + Math.floor((score - 3000) / 2000) * 2000; if (score >= musicThreshold && score < musicThreshold + 50 && !game.randomMusicPlaying) { // Choose random music var musicTracks = ['main1', 'Main', 'main2', 'main3']; var randomTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)]; LK.stopMusic(); LK.playMusic(randomTrack); game.main1Playing = false; game.main3Playing = false; game.randomMusicPlaying = true; } else if (score >= musicThreshold + 50) { game.randomMusicPlaying = false; } } // Update bullet speed boost timer if (bulletSpeedBoostTimer > 0) { bulletSpeedBoostTimer--; } // Check for fire rate boost every 100 kills var newFireRateBoostLevel = Math.floor(enemiesKilled / 100); if (newFireRateBoostLevel > fireRateBoostLevel) { fireRateBoostLevel = newFireRateBoostLevel; // Visual feedback for fire rate increase LK.effects.flashScreen(0x0099FF, 300); // Blue flash to indicate fire rate boost } // Check for difficulty increase every 25 points if (score - lastDifficultyScore >= 25) { difficultyLevel++; lastDifficultyScore = score; // Systematic enemy speed progression based on score ranges if (score <= 100) { // Early game: minimal speed increase enemySpeedMultiplier = 1.0 + score * 0.005; // Max 1.5x at score 100 } else if (score <= 200) { // Mid game: moderate increase enemySpeedMultiplier = 1.5 + (score - 100) * 0.003; // 1.5x to 1.8x } else if (score <= 400) { // Late game: controlled increase enemySpeedMultiplier = 1.8 + (score - 200) * 0.002; // 1.8x to 2.2x } else { // End game: capped maximum speed enemySpeedMultiplier = Math.min(2.5, 2.2 + (score - 400) * 0.001); // Max 2.5x speed } // Spawn additional enemies based on difficulty level var enemiesToSpawn = Math.min(2, difficultyLevel); // Spawn 1-2 enemies per difficulty increase for (var d = 0; d < enemiesToSpawn && enemies.length < maxEnemies + difficultyLevel; d++) { spawnNewEnemy(); } // Visual feedback for difficulty increase LK.effects.flashScreen(0x00FF00, 500); // Green flash to indicate difficulty increase } // Health restore system - restore health at score milestones (1000, 2000, 3000, etc.) if (score >= nextHealthRestoreScore && !hasRestoredHealthAtThreshold) { // Restore player health to full player.health = player.maxHealth; player.updateHealthBar(); // Set flag to prevent multiple restores at same threshold hasRestoredHealthAtThreshold = true; // Set next threshold nextHealthRestoreScore += 1000; // Visual feedback for health restore LK.effects.flashScreen(0x00FF99, 800); // Green-cyan flash for health restore } // Reset health restore flag when score increases past threshold if (score >= nextHealthRestoreScore - 1000 && score < nextHealthRestoreScore) { hasRestoredHealthAtThreshold = false; } // Spawn health pack when player health is low (below 25%) if (player.health < player.maxHealth * 0.25 && LK.ticks - lastHealthPackSpawn > 300 && // 5 second cooldown healthPacks.length === 0) { // Only one health pack at a time var healthPack = game.addChild(new HealthPack()); // Spawn at random location healthPack.x = 300 + Math.random() * 1400; healthPack.y = 400 + Math.random() * 1800; healthPacks.push(healthPack); lastHealthPackSpawn = LK.ticks; } // Update all game objects player.update(); for (var i = 0; i < enemies.length; i++) { enemies[i].update(); } // Update health packs and clean up destroyed ones for (var i = healthPacks.length - 1; i >= 0; i--) { var healthPack = healthPacks[i]; if (healthPack.destroyed) { healthPacks.splice(i, 1); } else { healthPack.update(); } } // Update bullets and clean up destroyed ones for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.destroyed === true || !bullet.parent) { bullets.splice(i, 1); } else { bullet.update(); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('attackEffect', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.scaleX = 0.5;
bulletGraphics.scaleY = 0.5;
// Set bullet speed based on boost status
self.speed = bulletSpeedBoostTimer > 0 ? baseBulletSpeed * 1.5 : baseBulletSpeed;
self.targetX = 0;
self.targetY = 0;
self.damage = 0;
self.isPlayerBullet = true;
self.targetEnemy = null; // Specific enemy this bullet is targeting
self.update = function () {
// Check for direct collision with enemies/player regardless of distance
if (self.isPlayerBullet) {
// Only check collision with the specific target enemy
if (self.targetEnemy && !self.targetEnemy.isRespawning && !self.targetEnemy.destroyed && self.intersects(self.targetEnemy)) {
self.targetEnemy.takeDamage(self.damage);
self.destroy();
return;
}
} else {
// Enemy bullet hitting player
if (!player.isRespawning && self.intersects(player)) {
player.takeDamage(self.damage);
self.destroy();
return;
}
}
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If reached target position, destroy bullet
if (distance < self.speed) {
self.destroy();
return;
}
// Move towards target
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Remove if out of bounds
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.destroy();
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -60
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -60
});
self.maxHealth = 30; // Reduced health for faster kills like Vampire Survivors
self.health = 30;
self.speed = 2;
self.attackRange = 120;
self.attackDamage = 8; // Higher damage but less health overall
self.attackCooldown = 0;
self.isRespawning = false;
self.respawnTimer = 0;
self.aiTimer = 0;
self.spawnImmunityTimer = 0; // Prevents attacking immediately after spawn
self.targetX = 0;
self.targetY = 0;
self.takeDamage = function (damage) {
if (self.isRespawning || self.health <= 0) return; // Don't take damage if already dead
// Vampire Survivors style damage - each hit does significant damage but not instant kill
self.health -= damage;
if (self.health < 0) self.health = 0;
self.updateHealthBar();
// Flash red when taking damage
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
if (self.health <= 0) {
self.die();
}
LK.getSound('hit').play();
};
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBar.scaleX = healthPercent;
if (healthPercent > 0.6) {
healthBar.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
healthBar.tint = 0xFFFF00;
} else {
healthBar.tint = 0xFF0000;
}
};
self.die = function () {
self.isRespawning = true;
self.respawnTimer = 180; // 3 seconds at 60fps
enemyGraphics.visible = false;
healthBar.visible = false;
healthBarBg.visible = false;
// Move enemy far off-screen during respawn to prevent collision issues
self.x = -1000;
self.y = -1000;
// Increment killed count and spawn new enemy only if under limit
enemiesKilled++;
score++;
scoreText.setText('Score: ' + score);
if (enemies.length < maxEnemies) {
spawnNewEnemy();
}
};
self.respawn = function () {
self.health = self.maxHealth;
// Set position first before making visible
self.x = 300 + Math.random() * 1400;
self.y = 400 + Math.random() * 1800;
// Reset spawn immunity
self.spawnImmunityTimer = 60; // 1 second of spawn immunity
// Then update state and make visible
self.isRespawning = false;
self.respawnTimer = 0;
enemyGraphics.visible = true;
enemyGraphics.alpha = 1;
healthBar.visible = true;
healthBarBg.visible = true;
self.updateHealthBar();
LK.getSound('respawn').play();
};
self.attack = function () {
if (self.attackCooldown > 0 || self.isRespawning || self.spawnImmunityTimer > 0) return;
self.attackCooldown = 120; // 2 second cooldown
if (!player.isRespawning) {
// Create bullet projectile towards player
var bullet = game.addChild(new Bullet());
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = player.x;
bullet.targetY = player.y;
bullet.damage = self.attackDamage;
bullet.isPlayerBullet = false;
bullets.push(bullet);
}
// Create attack effect
var attackEffect = LK.getAsset('attackEffect', {
anchorX: 0.5,
anchorY: 0.5
});
attackEffect.x = self.x;
attackEffect.y = self.y;
attackEffect.alpha = 0.7;
attackEffect.tint = 0xFF4444;
attackEffect.scaleX = 0.8;
attackEffect.scaleY = 0.8;
game.addChild(attackEffect);
// Scale and fade out attack effect
tween(attackEffect, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
attackEffect.destroy();
}
});
LK.getSound('attack').play();
};
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.spawnImmunityTimer > 0) {
self.spawnImmunityTimer--;
// Flash during spawn immunity period
if (self.spawnImmunityTimer % 10 < 5) {
enemyGraphics.alpha = 0.7;
} else {
enemyGraphics.alpha = 1;
}
}
if (self.isRespawning) {
self.respawnTimer--;
if (self.respawnTimer <= 0) {
self.respawn();
}
return;
}
// Chase player AI - move towards player and attack when close
if (!player.isRespawning) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var playerDistance = Math.sqrt(dx * dx + dy * dy);
// Move towards player with speed multiplier
var currentSpeed = self.speed * enemySpeedMultiplier;
if (playerDistance > currentSpeed) {
// Create a formation around the player instead of direct chase
// Update AI timer for random movement changes
self.aiTimer++;
if (self.aiTimer >= 60) {
// Change direction every second
self.aiTimer = 0;
// Calculate a preferred distance from player (spread enemies out)
var preferredDistance = 180 + Math.random() * 120; // 180-300 pixels from player
// If too close to preferred distance, move in a circular pattern
if (playerDistance < preferredDistance + 50) {
// Move in circular pattern around player
var circleAngle = Math.atan2(dy, dx) + (Math.random() - 0.5) * Math.PI; // Add large random offset
var moveX = Math.cos(circleAngle) * currentSpeed * 0.7; // Slower circular movement
var moveY = Math.sin(circleAngle) * currentSpeed * 0.7;
} else {
// Generate random offset angle (-60 to +60 degrees) for wider spread
var offsetAngle = (Math.random() - 0.5) * Math.PI / 1.5; // ±60 degrees in radians
var baseAngle = Math.atan2(dy, dx);
var newAngle = baseAngle + offsetAngle;
var moveX = Math.cos(newAngle) * currentSpeed * 0.8; // Slightly slower approach
var moveY = Math.sin(newAngle) * currentSpeed * 0.8;
}
} else {
// Use stored movement direction with slight randomness
var moveX = dx / playerDistance * currentSpeed * 0.9;
var moveY = dy / playerDistance * currentSpeed * 0.9;
}
self.x += moveX;
self.y += moveY;
}
// Attack if close enough to player
if (playerDistance <= self.attackRange) {
self.attack();
}
}
// Check collision with other enemies and push away if overlapping
for (var e = 0; e < enemies.length; e++) {
var otherEnemy = enemies[e];
if (otherEnemy !== self && !otherEnemy.isRespawning && !self.isRespawning) {
var dx = otherEnemy.x - self.x;
var dy = otherEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = 120; // Reduced minimum distance to allow enemies closer together
if (distance < minDistance && distance > 0) {
// Calculate push direction (away from other enemy) with reduced force
var pushStrength = (minDistance - distance) * 1.2; // Reduced push force
var pushX = -(dx / distance) * pushStrength;
var pushY = -(dy / distance) * pushStrength;
// Apply moderate push force to separate enemies
self.x += pushX;
self.y += pushY;
// Also apply counter-force to the other enemy for better separation
otherEnemy.x += dx / distance * pushStrength * 0.5;
otherEnemy.y += dy / distance * pushStrength * 0.5;
}
}
}
// Keep enemy in bounds
if (self.x < 150) self.x = 150;
if (self.x > 1898) self.x = 1898;
if (self.y < 150) self.y = 150;
if (self.y > 2582) self.y = 2582;
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthPackGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.healAmount = 25; // Heal amount (50% of max health for new system)
self.lifetime = 600; // 10 seconds at 60fps
// Pulse animation for visibility
var pulseDirection = 1;
var pulseSpeed = 0.02;
self.update = function () {
// Pulse animation
healthPackGraphics.scaleX += pulseDirection * pulseSpeed;
healthPackGraphics.scaleY += pulseDirection * pulseSpeed;
if (healthPackGraphics.scaleX > 1.3 || healthPackGraphics.scaleX < 0.8) {
pulseDirection *= -1;
}
// Reduce lifetime
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
}
// Check collision with player
if (!player.isRespawning && self.intersects(player)) {
// Heal player
var oldHealth = player.health;
player.health = Math.min(player.maxHealth, player.health + self.healAmount);
player.updateHealthBar();
// Give immunity for 2 seconds
player.immunityTimer = 120;
// Increase bullet speed for 3 seconds
bulletSpeedBoostTimer = 180; // 3 seconds at 60fps
// Visual effect
tween(healthPackGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('heal').play();
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -60
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -60
});
self.maxHealth = 50; // Reduced health like Vampire Survivors
self.health = 50;
self.speed = 8;
self.attackRange = 100;
self.attackDamage = 15; // Balanced damage for new health system
self.attackCooldown = 0;
self.isRespawning = false;
self.respawnTimer = 0;
self.immunityTimer = 0; // Immunity period after respawn
self.takeDamage = function (damage, source) {
if (self.isRespawning || self.immunityTimer > 0) return;
// Prevent damage from explosions and enemy spawning
if (source === 'explosion' || source === 'spawn') {
return;
}
self.health -= damage;
if (self.health < 0) self.health = 0;
self.updateHealthBar();
// Flash red when taking damage
tween(playerGraphics, {
tint: 0xFF0000
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerGraphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
if (self.health <= 0) {
self.die();
}
LK.getSound('hit').play();
};
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBar.scaleX = healthPercent;
if (healthPercent > 0.6) {
healthBar.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
healthBar.tint = 0xFFFF00;
} else {
healthBar.tint = 0xFF0000;
}
};
self.die = function () {
// Show game over screen which will reset the game
LK.showGameOver();
};
self.respawn = function () {
self.health = self.maxHealth;
self.isRespawning = false;
self.respawnTimer = 0;
playerGraphics.alpha = 1;
healthBar.visible = true;
healthBarBg.visible = true;
self.updateHealthBar();
// Respawn at center position since map is reset
self.x = 500;
self.y = 1000;
// Add brief immunity period after respawn
self.immunityTimer = 180; // 3 seconds of immunity
// Spawn initial enemies after map reset
for (var i = 0; i < 3; i++) {
spawnNewEnemy();
}
LK.getSound('respawn').play();
};
// Vampire Survivors style automatic shooting - no manual attack method needed
self.update = function () {
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
if (self.immunityTimer > 0) {
self.immunityTimer--;
// Flash during immunity period
if (self.immunityTimer % 10 < 5) {
playerGraphics.alpha = 0.5;
} else {
playerGraphics.alpha = 1;
}
}
if (self.isRespawning) {
self.respawnTimer--;
if (self.respawnTimer <= 0) {
self.respawn();
}
return;
}
// Vampire Survivors style automatic continuous shooting
if (self.attackCooldown <= 0) {
// Find closest enemy within range
var closestEnemy = null;
var closestDistance = Infinity;
var maxRange = 400; // Maximum shooting range
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (!enemy.isRespawning) {
var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2));
if (distance < closestDistance && distance <= maxRange) {
closestDistance = distance;
closestEnemy = enemy;
}
}
}
if (closestEnemy) {
// Set attack cooldown based on fire rate
var baseFireRate = 30; // Base frames between shots (faster than before)
var fireRateReduction = Math.min(fireRateBoostLevel * 2, baseFireRate * 0.4);
self.attackCooldown = baseFireRate - fireRateReduction;
// Create bullet projectile
var bullet = game.addChild(new Bullet());
bullet.x = self.x;
bullet.y = self.y;
bullet.targetX = closestEnemy.x;
bullet.targetY = closestEnemy.y;
bullet.damage = self.attackDamage;
bullet.isPlayerBullet = true;
bullet.targetEnemy = closestEnemy;
bullets.push(bullet);
// Create muzzle flash effect
var attackEffect = LK.getAsset('attackEffect', {
anchorX: 0.5,
anchorY: 0.5
});
attackEffect.x = self.x;
attackEffect.y = self.y;
attackEffect.alpha = 0.7;
attackEffect.tint = 0x4499FF;
attackEffect.scaleX = 0.6;
attackEffect.scaleY = 0.6;
game.addChild(attackEffect);
// Scale and fade out attack effect
tween(attackEffect, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0
}, {
duration: 150,
onFinish: function onFinish() {
attackEffect.destroy();
}
});
LK.getSound('attack').play();
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
// Create arena background
var arena = game.addChild(LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5
}));
arena.x = 2048 / 2;
arena.y = 2732 / 2;
// Game variables
var player;
var enemies = [];
var bullets = [];
var moveUp = false;
var moveDown = false;
var moveLeft = false;
var moveRight = false;
var targetX = 0;
var targetY = 0;
var isMovingToTarget = false;
var enemiesKilled = 0;
var score = 0;
var baseFireRate = 30; // Base attack cooldown - Vampire Survivors style faster firing
var currentFireRate = 30;
var fireRateBoostLevel = 0; // Tracks fire rate improvements
var maxEnemies = 8; // Base maximum number of enemies allowed
var enemySpeedMultiplier = 1.0; // Gradually increases enemy speed
var explosionRadius = 150; // Radius for chain explosions
var difficultyLevel = 0; // Current difficulty level
var lastDifficultyScore = 0; // Score at last difficulty increase
var healthPacks = [];
var lastHealthPackSpawn = 0;
var bulletSpeedBoostTimer = 0; // Timer for bullet speed boost
var baseBulletSpeed = 15; // Base bullet speed
var enemySpawnTimer = 0; // Timer for continuous enemy spawning
var baseSpawnInterval = 120; // Base spawn interval (2 seconds at 60fps)
var nextHealthRestoreScore = 1000; // Score threshold for next health restore
var hasRestoredHealthAtThreshold = false; // Track if health was restored at current threshold
// Start main music
LK.playMusic('Main');
// Initialize music state tracking
game.main1Playing = false;
game.main3Playing = false;
game.randomMusicPlaying = false;
// Create player
player = game.addChild(new Player());
player.x = 500;
player.y = 1000;
// Function to spawn new enemy from off-screen edges (Vampire Survivors style)
function spawnNewEnemy() {
var enemy = game.addChild(new Enemy());
// Choose random edge to spawn from (off-screen)
var spawnSide = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left
var spawnOffset = Math.random(); // Random position along edge (0% to 100%)
// Spawn outside visible area for true Vampire Survivors effect
var offScreenDistance = 100; // Distance outside visible area
switch (spawnSide) {
case 0:
// Top edge - spawn above screen
enemy.x = spawnOffset * 2048;
enemy.y = -offScreenDistance;
break;
case 1:
// Right edge - spawn to the right of screen
enemy.x = 2048 + offScreenDistance;
enemy.y = spawnOffset * 2732;
break;
case 2:
// Bottom edge - spawn below screen
enemy.x = spawnOffset * 2048;
enemy.y = 2732 + offScreenDistance;
break;
case 3:
// Left edge - spawn to the left of screen
enemy.x = -offScreenDistance;
enemy.y = spawnOffset * 2732;
break;
}
// Give new enemies a brief spawn immunity to prevent instant collision damage
enemy.spawnImmunityTimer = 60; // 1 second of spawn immunity
enemy.targetX = enemy.x;
enemy.targetY = enemy.y;
enemies.push(enemy);
}
// Initial enemies will be spawned by the continuous spawning system
// No need for initial spawn - let the timer handle it
// UI Elements
var instructionText = new Text2('Tap to move - Auto attack enemies nearby', {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
instructionText.y = 100;
// Score display
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFD700
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 150;
var dragNode = null;
var lastTouchTime = 0;
// Touch controls
game.down = function (x, y, obj) {
if (player.isRespawning) return;
// Keep target position in bounds
targetX = Math.max(150, Math.min(1898, x));
targetY = Math.max(150, Math.min(2582, y));
// Stop any current movement tween
tween.stop(player, {
x: true,
y: true
});
// Calculate distance for duration (closer = faster)
var distance = Math.sqrt(Math.pow(targetX - player.x, 2) + Math.pow(targetY - player.y, 2));
var duration = Math.max(200, Math.min(1000, distance * 2)); // 200ms to 1000ms based on distance
isMovingToTarget = true;
// Tween player to target position
tween(player, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
isMovingToTarget = false;
}
});
};
game.move = function (x, y, obj) {
// No drag movement needed - player moves via tween to clicked position
};
game.up = function (x, y, obj) {
// No action needed - player auto-attacks when moving
};
// Main game loop
game.update = function () {
// Vampire Survivors style continuous enemy spawning
enemySpawnTimer++;
var currentSpawnInterval = Math.max(30, baseSpawnInterval - Math.floor(score / 50) * 10); // Faster spawning as score increases
if (enemySpawnTimer >= currentSpawnInterval && enemies.length < maxEnemies + difficultyLevel) {
spawnNewEnemy();
enemySpawnTimer = 0; // Reset spawn timer
}
// Music transitions based on score
if (score >= 100 && score < 500) {
// Play main1 music from score 100 to 500
if (!game.main1Playing) {
LK.stopMusic();
LK.playMusic('main1');
game.main1Playing = true;
}
} else if (score >= 500 && score < 1500) {
// Play main2 music from score 500 to 1500
if (game.main1Playing) {
LK.stopMusic();
LK.playMusic('main2');
game.main1Playing = false;
}
} else if (score >= 1500 && score < 3000) {
// Play main3 music from score 1500 to 3000
if (game.main1Playing || !game.main3Playing) {
LK.stopMusic();
LK.playMusic('main3');
game.main1Playing = false;
game.main3Playing = true;
}
} else if (score >= 3000) {
// Random music rotation every 2000 points after 3000
var musicThreshold = 3000 + Math.floor((score - 3000) / 2000) * 2000;
if (score >= musicThreshold && score < musicThreshold + 50 && !game.randomMusicPlaying) {
// Choose random music
var musicTracks = ['main1', 'Main', 'main2', 'main3'];
var randomTrack = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.stopMusic();
LK.playMusic(randomTrack);
game.main1Playing = false;
game.main3Playing = false;
game.randomMusicPlaying = true;
} else if (score >= musicThreshold + 50) {
game.randomMusicPlaying = false;
}
}
// Update bullet speed boost timer
if (bulletSpeedBoostTimer > 0) {
bulletSpeedBoostTimer--;
}
// Check for fire rate boost every 100 kills
var newFireRateBoostLevel = Math.floor(enemiesKilled / 100);
if (newFireRateBoostLevel > fireRateBoostLevel) {
fireRateBoostLevel = newFireRateBoostLevel;
// Visual feedback for fire rate increase
LK.effects.flashScreen(0x0099FF, 300); // Blue flash to indicate fire rate boost
}
// Check for difficulty increase every 25 points
if (score - lastDifficultyScore >= 25) {
difficultyLevel++;
lastDifficultyScore = score;
// Systematic enemy speed progression based on score ranges
if (score <= 100) {
// Early game: minimal speed increase
enemySpeedMultiplier = 1.0 + score * 0.005; // Max 1.5x at score 100
} else if (score <= 200) {
// Mid game: moderate increase
enemySpeedMultiplier = 1.5 + (score - 100) * 0.003; // 1.5x to 1.8x
} else if (score <= 400) {
// Late game: controlled increase
enemySpeedMultiplier = 1.8 + (score - 200) * 0.002; // 1.8x to 2.2x
} else {
// End game: capped maximum speed
enemySpeedMultiplier = Math.min(2.5, 2.2 + (score - 400) * 0.001); // Max 2.5x speed
}
// Spawn additional enemies based on difficulty level
var enemiesToSpawn = Math.min(2, difficultyLevel); // Spawn 1-2 enemies per difficulty increase
for (var d = 0; d < enemiesToSpawn && enemies.length < maxEnemies + difficultyLevel; d++) {
spawnNewEnemy();
}
// Visual feedback for difficulty increase
LK.effects.flashScreen(0x00FF00, 500); // Green flash to indicate difficulty increase
}
// Health restore system - restore health at score milestones (1000, 2000, 3000, etc.)
if (score >= nextHealthRestoreScore && !hasRestoredHealthAtThreshold) {
// Restore player health to full
player.health = player.maxHealth;
player.updateHealthBar();
// Set flag to prevent multiple restores at same threshold
hasRestoredHealthAtThreshold = true;
// Set next threshold
nextHealthRestoreScore += 1000;
// Visual feedback for health restore
LK.effects.flashScreen(0x00FF99, 800); // Green-cyan flash for health restore
}
// Reset health restore flag when score increases past threshold
if (score >= nextHealthRestoreScore - 1000 && score < nextHealthRestoreScore) {
hasRestoredHealthAtThreshold = false;
}
// Spawn health pack when player health is low (below 25%)
if (player.health < player.maxHealth * 0.25 && LK.ticks - lastHealthPackSpawn > 300 &&
// 5 second cooldown
healthPacks.length === 0) {
// Only one health pack at a time
var healthPack = game.addChild(new HealthPack());
// Spawn at random location
healthPack.x = 300 + Math.random() * 1400;
healthPack.y = 400 + Math.random() * 1800;
healthPacks.push(healthPack);
lastHealthPackSpawn = LK.ticks;
}
// Update all game objects
player.update();
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
// Update health packs and clean up destroyed ones
for (var i = healthPacks.length - 1; i >= 0; i--) {
var healthPack = healthPacks[i];
if (healthPack.destroyed) {
healthPacks.splice(i, 1);
} else {
healthPack.update();
}
}
// Update bullets and clean up destroyed ones
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.destroyed === true || !bullet.parent) {
bullets.splice(i, 1);
} else {
bullet.update();
}
}
};
bullet. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Face. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
face. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
green hearth. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Grey gound . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat