User prompt
update the bazooka chance instruction since its changed
User prompt
remove the previous bazooka instruction
User prompt
update bazooka instruction
User prompt
every difficulty have their own enemy speed
User prompt
every difficult have their own bazooka chance
User prompt
add scream for NPC deaths
User prompt
add scream for deaths
User prompt
every difficulty have their own opening cutscene โช๐ก Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the enemy and the boss more shapes like the player and NPC but their color is still red
User prompt
make the boss appear at 00:00 for testing and bullet one hit to boss for testing
User prompt
add winning music
User prompt
make a song for cutscene
User prompt
add a picture at the cutscene describe what happens at the cutscene
User prompt
remove the "tap anywhere to continue" button at cutscene but appear it after the cutscene done
User prompt
add cutscene after difficulty selection about the survivors found gun and knife and bazooka and add skip button for it โช๐ก Consider importing and using the following plugins: @upit/tween.v1
User prompt
make their head yellow
User prompt
make their color to be yellow โช๐ก Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix their hea bruh
User prompt
make the player and NPC shapes more like human
User prompt
make the player bullet targeting enemy
User prompt
make the bullet focus at enemy
User prompt
when shooting, only one shoot per NPC for shoot at the enemy
User prompt
NPC have 30 ammo for the start of the game
User prompt
reset the NPC ammo value
User prompt
ok testing done, put the boss at 06:00 again
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var AmmoBox = Container.expand(function () { var self = Container.call(this); var ammoGraphics = self.attachAsset('ammoBox', { anchorX: 0.5, anchorY: 0.5 }); self.ammoAmount = 15; self.lifetime = 600; // 10 seconds at 60fps self.update = function () { self.lifetime--; // Pulsing effect ammoGraphics.alpha = 0.7 + Math.sin(self.lifetime * 0.2) * 0.3; if (self.lifetime <= 0) { return true; // Should be removed } return false; }; return self; }); var Bazooka = Container.expand(function () { var self = Container.call(this); var bazookaGraphics = self.attachAsset('bazooka', { anchorX: 0.5, anchorY: 0.5 }); self.ammo = 5; self.maxAmmo = 5; self.cooldown = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Reset bazooka usage flag usingBazooka = false; // Always ready to fire pulsing effect bazookaGraphics.alpha = 0.8 + Math.sin(LK.ticks * 0.2) * 0.2; }; self.down = function (x, y, obj) { self.fireBazooka(); }; self.fireBazooka = function () { // Find nearest enemy to target first var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } // Target boss if no enemies or boss is closer if (boss) { var dx = boss.x - self.x; var dy = boss.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!nearestEnemy || distance < nearestDistance) { nearestEnemy = boss; nearestDistance = distance; } } // Create bullet var bullet = new BazookaBullet(); bullet.x = self.x; bullet.y = self.y; if (nearestEnemy) { // Target the enemy var dx = nearestEnemy.x - self.x; var dy = nearestEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.directionX = dx / distance; bullet.directionY = dy / distance; } } else { // No enemy found - fire randomly var randomAngle = Math.random() * Math.PI * 2; bullet.directionX = Math.cos(randomAngle); bullet.directionY = Math.sin(randomAngle); } // Practice mode: 100% normal firing behavior if (selectedGameMode === 4) { bazookaBullets.push(bullet); game.addChild(bullet); // Play bazooka sound LK.getSound('bazookaShoot').play(); // Flash effect LK.effects.flashObject(self, 0xff8800, 300); // Set bazooka usage flag usingBazooka = true; return; } // Get difficulty-based bazooka chances for other modes var bazookaChances = [{ target: 0.85, blank: 0.12, explode: 0.03 }, // Easy: 85% target, 12% blank, 3% explode { target: 0.75, blank: 0.15, explode: 0.10 }, // Normal: 75% target, 15% blank, 10% explode { target: 0.65, blank: 0.20, explode: 0.15 }, // Hard: 65% target, 20% blank, 15% explode { target: 0.50, blank: 0.25, explode: 0.25 }, // Nightmare: 50% target, 25% blank, 25% explode { target: 0.30, blank: 0.30, explode: 0.40 } // Impossible: 30% target, 30% blank, 40% explode ]; var chances = bazookaChances[selectedDifficulty - 1]; // Random outcome based on difficulty var randomOutcome = Math.random(); if (randomOutcome < chances.explode) { // Self-explosion and death // Create explosion at bazooka position var explosion = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5 }); explosion.x = self.x; explosion.y = self.y; explosion.alpha = 0.8; game.addChild(explosion); // Animate explosion tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Play explosion sound LK.getSound('explosion').play(); // Kill player if (player) { player.takeDamage(player.health); // Deal enough damage to kill } // Flash effect LK.effects.flashObject(self, 0xff0000, 300); // Set bazooka usage flag usingBazooka = true; return; } else if (randomOutcome < chances.explode + chances.blank) { // Blank ammo (do nothing) // Play a different sound or visual effect for blank LK.getSound('bazookaShoot').play(); // Flash effect with different color LK.effects.flashObject(self, 0x888888, 300); // Create blank ammo text var blankText = new Text2('blank ammo, try again', { size: 40, fill: 0xffffff }); blankText.anchor.set(0.5, 0.5); blankText.x = self.x; blankText.y = self.y - 60; game.addChild(blankText); // Fade out blank text after 2 seconds tween(blankText, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { blankText.destroy(); } }); // Set bazooka usage flag usingBazooka = true; return; } // Normal behavior - fire bazooka bazookaBullets.push(bullet); game.addChild(bullet); // Play bazooka sound LK.getSound('bazookaShoot').play(); // Flash effect LK.effects.flashObject(self, 0xff8800, 300); // Set bazooka usage flag usingBazooka = true; }; self.addAmmo = function (amount) { self.ammo = Math.min(self.maxAmmo, self.ammo + amount); }; return self; }); var BazookaBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bazookaBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 200; self.explosionRadius = 300; self.directionX = 0; self.directionY = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Remove if out of bounds if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { return true; // Should be removed } return false; }; self.explode = function () { // Create explosion visual effect var explosion = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5 }); explosion.x = self.x; explosion.y = self.y; explosion.alpha = 0.8; game.addChild(explosion); // Animate explosion tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Play explosion sound LK.getSound('explosion').play(); // Damage all enemies in radius for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.explosionRadius) { enemy.takeDamage(self.damage); } } // Damage boss if in radius if (boss) { var dx = boss.x - self.x; var dy = boss.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.explosionRadius) { boss.takeDamage(self.damage); } } }; return self; }); var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3, tint: 0x800080 }); var headGraphics = self.attachAsset('head', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -50, scaleX: 3, scaleY: 3, tint: 0x800080 }); self.addChild(headGraphics); // Apply difficulty-based boss health values var difficultyBossHealth = [50000, 100000, 150000, 200000, 300000]; // Easy, Normal, Hard, Nightmare, Impossible var bossHealth = difficultyBossHealth[selectedDifficulty - 1]; self.health = bossHealth; self.maxHealth = bossHealth; self.speed = 4; self.damage = 50; self.attackCooldown = 0; self.lastX = 0; self.lastY = 0; self.lastPlayerDistance = 1000; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.attackCooldown > 0) { self.attackCooldown--; } // Find nearest NPC first, then player var targetEntity = null; var nearestDistance = Infinity; // Check NPCs first (priority targets) for (var k = 0; k < npcs.length; k++) { var npc = npcs[k]; var dx = npc.x - self.x; var dy = npc.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; targetEntity = npc; } } // If no NPCs found or player is closer, target player if (player) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!targetEntity || distance < nearestDistance) { nearestDistance = distance; targetEntity = player; } } // Move towards target entity if (targetEntity) { var dx = targetEntity.x - self.x; var dy = targetEntity.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack if close enough var currentDistance = distance; if (currentDistance < 100 && self.attackCooldown <= 0) { // Practice mode: boss does no damage if (selectedGameMode === 4) { // No damage in practice mode } else { targetEntity.takeDamage(self.damage); } self.attackCooldown = 60; } self.lastPlayerDistance = currentDistance; } }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { return true; // Boss died } return false; }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; self.damage = 100; // Ensure one-hit kills self.directionX = 0; self.directionY = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Remove if out of bounds if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { return true; // Should be removed } return false; }; return self; }); var CutsceneScreen = Container.expand(function () { var self = Container.call(this); // Dark background var background = self.attachAsset('menuBackground', { x: 0, y: 0 }); // Blood moon effect in top right var moon = self.attachAsset('moonGlow', { x: 1600, y: 300, alpha: 0.7, anchorX: 0.5, anchorY: 0.5 }); // Difficulty-specific content var difficultyTitles = ['THE FIRST DISCOVERY', // Easy 'THE ARSENAL AWAKENS', // Normal 'WEAPONS OF DESPERATION', // Hard 'TOOLS OF THE DAMNED', // Nightmare 'INSTRUMENTS OF MADNESS' // Impossible ]; var difficultyStories = ['The survivors found a well-stocked military cache...\n\nBasic weapons lay ready for untrained hands:', // Easy 'The survivors searched through the abandoned military base...\n\nThey found weapons that could turn the tide:', // Normal 'Desperate survivors ransacked the decimated armory...\n\nOnly scraps of military hardware remained:', // Hard 'In the blood-soaked ruins of the command center...\n\nCursed weapons whispered promises of power:', // Nightmare 'Deep in the hellish depths of the facility...\n\nEldritch armaments pulsed with dark energy:' // Impossible ]; var difficultyColors = [0x00FF00, // Easy - Green 0xFFFF00, // Normal - Yellow 0xFF8800, // Hard - Orange 0xFF0000, // Nightmare - Red 0x660066 // Impossible - Purple ]; // Get difficulty-specific content var selectedTitle = difficultyTitles[selectedDifficulty - 1] || difficultyTitles[1]; var selectedStory = difficultyStories[selectedDifficulty - 1] || difficultyStories[1]; var selectedColor = difficultyColors[selectedDifficulty - 1] || difficultyColors[1]; // Title var titleText = new Text2(selectedTitle, { size: 100, fill: selectedColor, align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; self.addChild(titleText); // Story text var storyText = new Text2(selectedStory, { size: 60, fill: 0xFFFFFF, align: 'center' }); storyText.anchor.set(0.5, 0.5); storyText.x = 1024; storyText.y = 800; self.addChild(storyText); // Weapon icons and descriptions var gunIcon = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, x: 400, y: 1200, scaleX: 3, scaleY: 3 }); // Difficulty-specific weapon descriptions var difficultyGunTexts = ['TRAINING RIFLE\nStable and reliable', // Easy 'ASSAULT RIFLE\nAuto-targeting bullets', // Normal 'DAMAGED RIFLE\nUnstable but functional', // Hard 'CURSED RIFLE\nFeeds on enemy souls', // Nightmare 'VOID RIFLE\nChannels cosmic horror' // Impossible ]; var difficultyKnifeTexts = ['UTILITY KNIFE\nBasic close combat', // Easy 'COMBAT KNIFE\nClose quarters combat', // Normal 'RUSTED BLADE\nDull but deadly', // Hard 'BLOODTHIRSTY BLADE\nThirsts for carnage', // Nightmare 'ELDRITCH DAGGER\nCuts through reality' // Impossible ]; var difficultyBazookaTexts = ['PRACTICE LAUNCHER\nSafe explosive training', // Easy 'BAZOOKA\nExplosive devastation', // Normal 'BROKEN LAUNCHER\nUnpredictable explosions', // Hard 'DEMON CANNON\nInfernal destruction', // Nightmare 'REALITY SHATTER\nBreaks space and time' // Impossible ]; var difficultyFinalTexts = ['With proper training weapons, they felt ready\nfor the coming challenge...', // Easy 'Armed with these weapons, they prepared\nfor the nightmare ahead...', // Normal 'With broken tools and desperate hope,\nthey faced impossible odds...', // Hard 'Wielding cursed instruments of war,\nthey embraced their dark fate...', // Nightmare 'Bearing eldritch weapons of madness,\nthey prepared to shatter reality itself...' // Impossible ]; var selectedGunText = difficultyGunTexts[selectedDifficulty - 1] || difficultyGunTexts[1]; var selectedKnifeText = difficultyKnifeTexts[selectedDifficulty - 1] || difficultyKnifeTexts[1]; var selectedBazookaText = difficultyBazookaTexts[selectedDifficulty - 1] || difficultyBazookaTexts[1]; var selectedFinalText = difficultyFinalTexts[selectedDifficulty - 1] || difficultyFinalTexts[1]; var gunText = new Text2(selectedGunText, { size: 50, fill: 0xFFFF00, align: 'center' }); gunText.anchor.set(0.5, 0.5); gunText.x = 400; gunText.y = 1350; self.addChild(gunText); var knifeIcon = self.attachAsset('knife', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, scaleX: 2, scaleY: 2 }); var knifeText = new Text2(selectedKnifeText, { size: 50, fill: 0xC0C0C0, align: 'center' }); knifeText.anchor.set(0.5, 0.5); knifeText.x = 1024; knifeText.y = 1350; self.addChild(knifeText); var bazookaIcon = self.attachAsset('bazooka', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 1200, scaleX: 1.5, scaleY: 1.5 }); var bazookaText = new Text2(selectedBazookaText, { size: 50, fill: 0xFF8800, align: 'center' }); bazookaText.anchor.set(0.5, 0.5); bazookaText.x = 1648; bazookaText.y = 1350; self.addChild(bazookaText); // Final story text var finalText = new Text2(selectedFinalText, { size: 55, fill: 0xFFFFFF, align: 'center' }); finalText.anchor.set(0.5, 0.5); finalText.x = 1024; finalText.y = 1700; self.addChild(finalText); // Skip button var skipButton = new Text2('[SKIP]', { size: 60, fill: 0xFF6666, align: 'center' }); skipButton.anchor.set(1, 0); skipButton.x = -50; skipButton.y = 100; LK.gui.topRight.addChild(skipButton); // Continue text (initially hidden) var continueText = new Text2('TAP ANYWHERE TO CONTINUE', { size: 45, fill: 0xCCCCCC, align: 'center' }); continueText.anchor.set(0.5, 0.5); continueText.x = 1024; continueText.y = 2200; continueText.alpha = 0; // Initially hidden self.addChild(continueText); // Animation timer self.animationTimer = 0; self.animationPhase = 0; // 0=fade in title, 1=show story, 2=show weapons, 3=show final self.update = function () { self.animationTimer++; // Pulsing effects if (continueText.alpha > 0) { continueText.alpha = 0.5 + Math.sin(self.animationTimer * 0.1) * 0.3; } // Difficulty-specific moon effects var baseMoonAlpha = 0.5 + Math.sin(self.animationTimer * 0.05) * 0.2; moon.alpha = baseMoonAlpha; // Change moon tint based on difficulty var difficultyMoonTints = [0x8b1538, // Easy - Default red 0x8b1538, // Normal - Default red 0xFF4400, // Hard - Darker red 0x660000, // Nightmare - Deep red 0x330033 // Impossible - Purple ]; moon.tint = difficultyMoonTints[selectedDifficulty - 1] || 0x8b1538; // Add extra effects for higher difficulties if (selectedDifficulty >= 4) { moon.scaleX = 1.0 + Math.sin(self.animationTimer * 0.1) * 0.1; moon.scaleY = 1.0 + Math.sin(self.animationTimer * 0.1) * 0.1; } skipButton.alpha = 0.7 + Math.sin(self.animationTimer * 0.08) * 0.3; // Weapon icon animations with difficulty-specific effects if (self.animationPhase >= 2) { // Base animations gunIcon.rotation += 0.02; knifeIcon.y = 1200 + Math.sin(self.animationTimer * 0.1) * 10; bazookaIcon.scaleX = 1.5 + Math.sin(self.animationTimer * 0.08) * 0.1; bazookaIcon.scaleY = 1.5 + Math.sin(self.animationTimer * 0.08) * 0.1; // Difficulty-specific effects if (selectedDifficulty >= 4) { // Nightmare and Impossible // Add pulsing tint effects for higher difficulties var pulseStrength = Math.sin(self.animationTimer * 0.15) * 0.3; gunIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100; knifeIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100; bazookaIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100; } if (selectedDifficulty === 5) { // Impossible - add reality distortion var distortion = Math.sin(self.animationTimer * 0.2) * 5; gunIcon.x = 400 + distortion; knifeIcon.x = 1024 + distortion; bazookaIcon.x = 1648 + distortion; } } // Auto-advance cutscene phases if (self.animationTimer === 120) { // 2 seconds self.animationPhase = 1; tween(storyText, { alpha: 1 }, { duration: 1000 }); } else if (self.animationTimer === 300) { // 5 seconds self.animationPhase = 2; tween(gunIcon, { alpha: 1 }, { duration: 800 }); tween(gunText, { alpha: 1 }, { duration: 800 }); tween(knifeIcon, { alpha: 1 }, { duration: 1000 }); tween(knifeText, { alpha: 1 }, { duration: 1000 }); tween(bazookaIcon, { alpha: 1 }, { duration: 1200 }); tween(bazookaText, { alpha: 1 }, { duration: 1200 }); } else if (self.animationTimer === 480) { // 8 seconds self.animationPhase = 3; tween(finalText, { alpha: 1 }, { duration: 1000 }); } else if (self.animationTimer === 660) { // 11 seconds - show continue text after all animations complete tween(continueText, { alpha: 1 }, { duration: 1000 }); } }; // Initially hide elements that will fade in storyText.alpha = 0; gunIcon.alpha = 0; gunText.alpha = 0; knifeIcon.alpha = 0; knifeText.alpha = 0; bazookaIcon.alpha = 0; bazookaText.alpha = 0; finalText.alpha = 0; // Handle skip and continue self.down = function (x, y, obj) { // Check if skip button was clicked var skipPos = LK.gui.topRight.toLocal({ x: x, y: y }); if (skipPos.x >= skipButton.x - 100 && skipPos.x <= skipButton.x + 50 && skipPos.y >= skipButton.y && skipPos.y <= skipButton.y + 80) { // Skip button clicked self.destroy(); skipButton.destroy(); startGameWithModeAndDifficulty(selectedGameMode, selectedDifficulty); return; } // Regular continue tap self.destroy(); skipButton.destroy(); startGameWithModeAndDifficulty(selectedGameMode, selectedDifficulty); }; return self; }); var DifficultySelectionScreen = Container.expand(function () { var self = Container.call(this); // Dark background var background = self.attachAsset('menuBackground', { x: 0, y: 0 }); // Blood moon effect in top right var moon = self.attachAsset('moonGlow', { x: 1600, y: 300, alpha: 0.7, anchorX: 0.5, anchorY: 0.5 }); // Main title var titleText = new Text2('CHOOSE DIFFICULTY', { size: 80, fill: 0xFF4444, align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 500; self.addChild(titleText); // Practice Mode var practiceText = new Text2('PRACTICE', { size: 60, fill: 0x00FFFF, align: 'center' }); practiceText.anchor.set(0.5, 0.5); practiceText.x = 1024; practiceText.y = 750; self.addChild(practiceText); var practiceDesc = new Text2('Learn the game with no pressure', { size: 50, fill: 0xCCCCCC, align: 'center' }); practiceDesc.anchor.set(0.5, 0.5); practiceDesc.x = 1024; practiceDesc.y = 830; self.addChild(practiceDesc); // Easy var easyText = new Text2('EASY', { size: 60, fill: 0x00FF00, align: 'center' }); easyText.anchor.set(0.5, 0.5); easyText.x = 1024; easyText.y = 1000; self.addChild(easyText); var easyDesc = new Text2('Slower enemies, more resources', { size: 50, fill: 0xCCCCCC, align: 'center' }); easyDesc.anchor.set(0.5, 0.5); easyDesc.x = 1024; easyDesc.y = 1080; self.addChild(easyDesc); // Normal var normalText = new Text2('NORMAL', { size: 60, fill: 0xFFFF00, align: 'center' }); normalText.anchor.set(0.5, 0.5); normalText.x = 1024; normalText.y = 1250; self.addChild(normalText); var normalDesc = new Text2('Balanced challenge', { size: 50, fill: 0xCCCCCC, align: 'center' }); normalDesc.anchor.set(0.5, 0.5); normalDesc.x = 1024; normalDesc.y = 1330; self.addChild(normalDesc); // Hard var hardText = new Text2('HARD', { size: 60, fill: 0xFF8800, align: 'center' }); hardText.anchor.set(0.5, 0.5); hardText.x = 1024; hardText.y = 1500; self.addChild(hardText); var hardDesc = new Text2('Faster enemies, less resources', { size: 50, fill: 0xCCCCCC, align: 'center' }); hardDesc.anchor.set(0.5, 0.5); hardDesc.x = 1024; hardDesc.y = 1580; self.addChild(hardDesc); // Nightmare var nightmareText = new Text2('NIGHTMARE', { size: 60, fill: 0xFF0000, align: 'center' }); nightmareText.anchor.set(0.5, 0.5); nightmareText.x = 1024; nightmareText.y = 1750; self.addChild(nightmareText); var nightmareDesc = new Text2('For the truly insane', { size: 50, fill: 0xCCCCCC, align: 'center' }); nightmareDesc.anchor.set(0.5, 0.5); nightmareDesc.x = 1024; nightmareDesc.y = 1830; self.addChild(nightmareDesc); // Impossible var impossibleText = new Text2('IMPOSSIBLE', { size: 60, fill: 0x660066, align: 'center' }); impossibleText.anchor.set(0.5, 0.5); impossibleText.x = 1024; impossibleText.y = 2000; self.addChild(impossibleText); var impossibleDesc = new Text2('Death awaits all who dare', { size: 50, fill: 0xCCCCCC, align: 'center' }); impossibleDesc.anchor.set(0.5, 0.5); impossibleDesc.x = 1024; impossibleDesc.y = 2080; self.addChild(impossibleDesc); // Selection instruction var selectText = new Text2('TAP TO SELECT DIFFICULTY', { size: 40, fill: 0xFF6666, align: 'center' }); selectText.anchor.set(0.5, 0.5); selectText.x = 1024; selectText.y = 2300; self.addChild(selectText); // Pulsing effect self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; selectText.alpha = 0.5 + Math.sin(self.pulseTimer) * 0.3; moon.alpha = 0.5 + Math.sin(self.pulseTimer * 0.5) * 0.2; }; // Handle difficulty selection self.down = function (x, y, obj) { var selectedDifficulty = 2; // Default to normal if (y > 700 && y < 900) { // Practice mode - set to easy difficulty but with practice mode flag selectedGameMode = 4; selectedDifficulty = 1; self.destroy(); showCutscene(); return; } else if (y > 950 && y < 1150) { selectedDifficulty = 1; // Easy } else if (y > 1200 && y < 1400) { selectedDifficulty = 2; // Normal } else if (y > 1450 && y < 1650) { selectedDifficulty = 3; // Hard } else if (y > 1700 && y < 1900) { selectedDifficulty = 4; // Nightmare } else if (y > 1950 && y < 2150) { selectedDifficulty = 5; // Impossible } // Store difficulty for cutscene to use window.selectedDifficulty = selectedDifficulty; self.destroy(); showCutscene(); }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, tint: 0xff0000 }); var headGraphics = self.attachAsset('head', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -50, tint: 0xff0000 }); self.addChild(headGraphics); self.health = 50; // Will be one-shot by 100 damage bullets self.speed = 8; self.damage = 20; self.attackCooldown = 0; self.lastX = 0; self.lastY = 0; self.lastPlayerDistance = 1000; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.attackCooldown > 0) { self.attackCooldown--; } // Find nearest NPC first, then player var targetEntity = null; var nearestDistance = Infinity; // Check NPCs first (priority targets) for (var k = 0; k < npcs.length; k++) { var npc = npcs[k]; var dx = npc.x - self.x; var dy = npc.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; targetEntity = npc; } } // If no NPCs found or player is closer, target player if (player) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!targetEntity || distance < nearestDistance) { nearestDistance = distance; targetEntity = player; } } // Move towards target entity if (targetEntity) { var dx = targetEntity.x - self.x; var dy = targetEntity.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack if close enough var currentDistance = distance; if (currentDistance < 50 && self.attackCooldown <= 0) { // Practice mode: enemies do no damage if (selectedGameMode === 4) { // No damage in practice mode } else { targetEntity.takeDamage(self.damage); } self.attackCooldown = 60; } self.lastPlayerDistance = currentDistance; } }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { return true; // Enemy died } return false; }; return self; }); var HealthPack = Container.expand(function () { var self = Container.call(this); var healthGraphics = self.attachAsset('healthPack', { anchorX: 0.5, anchorY: 0.5 }); self.healAmount = 30; self.lifetime = 600; // 10 seconds at 60fps self.update = function () { self.lifetime--; // Pulsing effect healthGraphics.alpha = 0.7 + Math.sin(self.lifetime * 0.2) * 0.3; if (self.lifetime <= 0) { return true; // Should be removed } return false; }; return self; }); var MenuScreen = Container.expand(function () { var self = Container.call(this); // Dark background var background = self.attachAsset('menuBackground', { x: 0, y: 0 }); // Blood moon effect in top right var moon = self.attachAsset('moonGlow', { x: 1600, y: 300, alpha: 0.7, anchorX: 0.5, anchorY: 0.5 }); // Blood splatter decorations var splatter1 = self.attachAsset('bloodSplatter', { x: 200, y: 500, alpha: 0.6, anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 1.2 }); var splatter2 = self.attachAsset('bloodSplatter', { x: 1700, y: 1800, alpha: 0.4, anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 0.7 }); // Main title var titleText = new Text2('NIGHT OF THE\nMASSACRE 3', { size: 120, fill: 0xFF4444, align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; self.addChild(titleText); // Subtitle var subtitleText = new Text2('BLOOD MOON RISING', { size: 60, fill: 0xFFFFFF, align: 'center' }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 1000; self.addChild(subtitleText); // Start instruction var startText = new Text2('TAP ANYWHERE TO BEGIN', { size: 40, fill: 0xCCCCCC, align: 'center' }); startText.anchor.set(0.5, 0.5); startText.x = 1024; startText.y = 1800; self.addChild(startText); // Pulsing effect for start text self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; startText.alpha = 0.5 + Math.sin(self.pulseTimer) * 0.3; // Subtle moon glow animation moon.alpha = 0.5 + Math.sin(self.pulseTimer * 0.5) * 0.2; }; // Handle tap to start self.down = function (x, y, obj) { // Transition to game (this will be handled by destroying menu and starting game) self.destroy(); startGame(); }; return self; }); var ModeSelectionScreen = Container.expand(function () { var self = Container.call(this); // Dark background var background = self.attachAsset('menuBackground', { x: 0, y: 0 }); // Blood moon effect in top right var moon = self.attachAsset('moonGlow', { x: 1600, y: 300, alpha: 0.7, anchorX: 0.5, anchorY: 0.5 }); // Main title var titleText = new Text2('CHOOSE YOUR NIGHTMARE', { size: 80, fill: 0xFF4444, align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; self.addChild(titleText); // Mode 1 - Classic Survival var mode1Text = new Text2('CLASSIC SURVIVAL', { size: 60, fill: 0xFFFFFF, align: 'center' }); mode1Text.anchor.set(0.5, 0.5); mode1Text.x = 1024; mode1Text.y = 1000; self.addChild(mode1Text); var mode1Desc = new Text2('Survive until dawn with limited resources', { size: 50, fill: 0xCCCCCC, align: 'center' }); mode1Desc.anchor.set(0.5, 0.5); mode1Desc.x = 1024; mode1Desc.y = 1080; self.addChild(mode1Desc); // Mode 2 - Endless Nightmare var mode2Text = new Text2('ENDLESS NIGHTMARE', { size: 60, fill: 0xFFFFFF, align: 'center' }); mode2Text.anchor.set(0.5, 0.5); mode2Text.x = 1024; mode2Text.y = 1300; self.addChild(mode2Text); var mode2Desc = new Text2('Face endless waves of increasing horror', { size: 50, fill: 0xCCCCCC, align: 'center' }); mode2Desc.anchor.set(0.5, 0.5); mode2Desc.x = 1024; mode2Desc.y = 1380; self.addChild(mode2Desc); // Mode 3 - Blood Eclipse var mode3Text = new Text2('BLOOD ECLIPSE', { size: 60, fill: 0xFFFFFF, align: 'center' }); mode3Text.anchor.set(0.5, 0.5); mode3Text.x = 1024; mode3Text.y = 1600; self.addChild(mode3Text); var mode3Desc = new Text2('Ultimate challenge with eclipse phases', { size: 50, fill: 0xCCCCCC, align: 'center' }); mode3Desc.anchor.set(0.5, 0.5); mode3Desc.x = 1024; mode3Desc.y = 1680; self.addChild(mode3Desc); // Back instruction var backText = new Text2('TAP TO SELECT MODE', { size: 40, fill: 0xFF6666, align: 'center' }); backText.anchor.set(0.5, 0.5); backText.x = 1024; backText.y = 2200; self.addChild(backText); // Pulsing effect self.pulseTimer = 0; self.update = function () { self.pulseTimer += 0.1; backText.alpha = 0.5 + Math.sin(self.pulseTimer) * 0.3; moon.alpha = 0.5 + Math.sin(self.pulseTimer * 0.5) * 0.2; }; // Handle mode selection self.down = function (x, y, obj) { selectedGameMode = 1; // Default to Classic Survival if (y > 1200 && y < 1400) { selectedGameMode = 2; // Endless Nightmare } else if (y > 1500 && y < 1700) { selectedGameMode = 3; // Blood Eclipse } self.destroy(); showDifficultySelection(); }; return self; }); var NPC = Container.expand(function () { var self = Container.call(this); var npcGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, tint: 0xffff00 }); var headGraphics = self.attachAsset('head', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -50, tint: 0xffff00 }); self.addChild(headGraphics); var knifeGraphics = self.attachAsset('knife', { anchorX: 0.5, anchorY: 1.0, x: 25, y: -10 }); // Apply difficulty-based health values var difficultyHealthValues = [120, 80, 60, 40, 25]; // Easy, Normal, Hard, Nightmare, Impossible var baseHealth = difficultyHealthValues[selectedDifficulty - 1]; self.health = baseHealth; self.maxHealth = baseHealth; // Apply difficulty-based speed values - more difficult = slower NPCs var difficultySpeedValues = [8, 6, 4, 2, 0.8]; // Easy, Normal, Hard, Nightmare, Impossible (0.1X speed) self.speed = difficultySpeedValues[selectedDifficulty - 1]; self.ammo = 30; // NPCs start with limited ammo self.maxAmmo = 25; // Maximum ammo NPCs can carry self.shootCooldown = 0; self.meleeRange = 60; // Range for knife attacks // Apply difficulty-based knife damage - harder difficulty = less knife damage var difficultyKnifeDamage = [120, 80, 60, 40, 20]; // Easy, Normal, Hard, Nightmare, Impossible self.meleeDamage = difficultyKnifeDamage[selectedDifficulty - 1]; self.meleeAttackCooldown = 0; // Cooldown for melee attacks self.shotAtEnemies = []; // Track which enemies this NPC has already shot at self.lastX = 0; self.lastY = 0; self.lastPlayerDistance = 1000; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.meleeAttackCooldown > 0) { self.meleeAttackCooldown--; } // Find nearest enemy to move towards var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } // Also consider boss if (boss) { var dx = boss.x - self.x; var dy = boss.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!nearestEnemy || distance < nearestDistance) { nearestEnemy = boss; nearestDistance = distance; } } // Calculate repulsion force from other NPCs to maintain distance var repulsionX = 0; var repulsionY = 0; var minNPCDistance = 80; // Minimum distance to maintain from other NPCs for (var k = 0; k < npcs.length; k++) { var otherNPC = npcs[k]; if (otherNPC !== self) { var dx = self.x - otherNPC.x; var dy = self.y - otherNPC.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < minNPCDistance && distance > 0) { // Apply repulsion force (stronger when closer) var repulsionStrength = (minNPCDistance - distance) / minNPCDistance; repulsionX += dx / distance * repulsionStrength * 3; repulsionY += dy / distance * repulsionStrength * 3; } } } // Move towards nearest enemy if (nearestEnemy && nearestDistance > 100) { var dx = nearestEnemy.x - self.x; var dy = nearestEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Combine enemy attraction with NPC repulsion var moveX = dx / distance * self.speed + repulsionX; var moveY = dy / distance * self.speed + repulsionY; self.x += moveX; self.y += moveY; } } else if (repulsionX !== 0 || repulsionY !== 0) { // If no enemy target, just apply repulsion self.x += repulsionX; self.y += repulsionY; } // Keep NPC in bounds if (self.x < 40) self.x = 40; if (self.x > 2008) self.x = 2008; if (self.y < 40) self.y = 40; if (self.y > 2692) self.y = 2692; // Try melee attack first if enemy is close enough var meleeTargetFound = false; if (self.meleeAttackCooldown <= 0) { // Check for enemies in melee range for (var m = 0; m < enemies.length; m++) { var enemy = enemies[m]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.meleeRange) { // Practice mode: NPCs do no damage if (selectedGameMode === 4) { // No damage in practice mode } else { enemy.takeDamage(self.meleeDamage); } LK.effects.flashObject(self, 0xffffff, 200); self.meleeAttackCooldown = 45; // Slower than shooting meleeTargetFound = true; break; } } // Check boss in melee range if (!meleeTargetFound && boss) { var dx = boss.x - self.x; var dy = boss.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.meleeRange) { // Practice mode: NPCs do no damage if (selectedGameMode === 4) { // No damage in practice mode } else { boss.takeDamage(self.meleeDamage); } LK.effects.flashObject(self, 0xffffff, 200); self.meleeAttackCooldown = 45; meleeTargetFound = true; } } } // Auto-shoot at enemies if no melee target and have ammo if (!meleeTargetFound && self.shootCooldown <= 0) { self.shootAtEnemies(); } }; self.shootAtEnemies = function () { // Find nearest enemy that hasn't been shot at yet var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Check if this NPC has already shot at this enemy var alreadyShot = false; for (var s = 0; s < self.shotAtEnemies.length; s++) { if (self.shotAtEnemies[s] === enemy) { alreadyShot = true; break; } } if (!alreadyShot) { var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } } // Also consider boss if not shot at yet if (boss) { var alreadyShotAtBoss = false; for (var s = 0; s < self.shotAtEnemies.length; s++) { if (self.shotAtEnemies[s] === boss) { alreadyShotAtBoss = true; break; } } if (!alreadyShotAtBoss) { var dx = boss.x - self.x; var dy = boss.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (!nearestEnemy || distance < nearestDistance) { nearestEnemy = boss; nearestDistance = distance; } } } // Shoot at nearest enemy only if we have ammo and haven't shot at this enemy yet if (nearestEnemy && self.ammo > 0) { var bullet = new NPCBullet(); bullet.x = self.x; bullet.y = self.y; var dx = nearestEnemy.x - self.x; var dy = nearestEnemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.directionX = dx / distance; bullet.directionY = dy / distance; } npcBullets.push(bullet); game.addChild(bullet); self.ammo--; // Consume ammo self.shootCooldown = 30; // Slower than player // Mark this enemy as shot at self.shotAtEnemies.push(nearestEnemy); LK.getSound('shoot').play(); } }; self.addAmmo = function (amount) { self.ammo = Math.min(self.maxAmmo, self.ammo + amount); }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { return true; // NPC died } return false; }; return self; }); var NPCBullet = Container.expand(function () { var self = Container.call(this); // Difficulty-based bullet properties var difficultyAssets = ['npcBulletEasy', 'npcBulletNormal', 'npcBulletHard', 'npcBulletNightmare', 'npcBulletImpossible']; var difficultyProps = [{ speed: 10, damage: 80, color: 0x00ff88 }, // Easy: slower, less damage { speed: 12, damage: 100, color: 0x88ff00 }, // Normal: standard { speed: 14, damage: 120, color: 0xffaa00 }, // Hard: faster, more damage { speed: 16, damage: 140, color: 0xff4400 }, // Nightmare: fastest, most damage { speed: 18, damage: 160, color: 0x660066 } // Impossible: insanely fast, devastating damage ]; var props = difficultyProps[selectedDifficulty - 1]; var assetId = difficultyAssets[selectedDifficulty - 1]; var bulletGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.speed = props.speed; self.damage = props.damage; self.directionX = 0; self.directionY = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Remove if out of bounds if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { return true; // Should be removed } return false; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var headGraphics = self.attachAsset('head', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -50, tint: 0xffff00 }); self.addChild(headGraphics); self.health = 100; self.maxHealth = 100; self.ammo = 30; self.maxAmmo = 30; self.speed = 8; self.shootCooldown = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.shootCooldown > 0) { self.shootCooldown--; } // Keep player in bounds if (self.x < 40) self.x = 40; if (self.x > 2008) self.x = 2008; if (self.y < 40) self.y = 40; if (self.y > 2692) self.y = 2692; }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xff0000, 500); }; self.heal = function (amount) { self.health = Math.min(self.maxHealth, self.health + amount); }; self.addAmmo = function (amount) { self.ammo = Math.min(self.maxAmmo, self.ammo + amount); }; self.canShoot = function () { return self.ammo > 0 && self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { self.ammo--; self.shootCooldown = 15; return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0400ff }); /**** * Game Code ****/ var menuScreen = null; var modeSelectionScreen = null; var difficultySelectionScreen = null; var cutsceneScreen = null; var gameStarted = false; var selectedGameMode = 1; var selectedDifficulty = 2; // 1=easy, 2=normal, 3=hard, 4=nightmare // Game variables var player = null; var enemies = []; var bullets = []; var npcBullets = []; var bazookaBullets = []; var bazooka = null; var healthPacks = []; var ammoBoxes = []; var boss = null; var bossSpawned = false; var bossDied = false; var npcs = []; var gameTimer = 0; var enemySpawnTimer = 0; var waveNumber = 1; var enemiesKilled = 0; var survivalTime = 0; var eclipsePhase = 0; // 0=normal, 1=blood moon, 2=eclipse var eclipseTimer = 0; var usingBazooka = false; // UI elements var healthText = null; var ammoText = null; var waveText = null; var timeText = null; var eclipseText = null; var bossHealthText = null; var bazookaInstructionText = null; function startGame() { // Show mode selection screen instead of starting game directly showModeSelection(); } function showMenu() { if (!menuScreen) { menuScreen = new MenuScreen(); game.addChild(menuScreen); LK.playMusic('menumusic'); } } function showModeSelection() { if (!modeSelectionScreen) { modeSelectionScreen = new ModeSelectionScreen(); game.addChild(modeSelectionScreen); LK.playMusic('menumusic'); } } function showDifficultySelection() { if (!difficultySelectionScreen) { difficultySelectionScreen = new DifficultySelectionScreen(); game.addChild(difficultySelectionScreen); LK.playMusic('menumusic'); } } function showCutscene() { if (!cutsceneScreen) { cutsceneScreen = new CutsceneScreen(); game.addChild(cutsceneScreen); LK.playMusic('cutscenemusic'); } } function startGameWithMode(mode) { selectedGameMode = mode; gameStarted = true; initializeGame(); } function startGameWithModeAndDifficulty(mode, difficulty) { selectedGameMode = mode; selectedDifficulty = difficulty; gameStarted = true; initializeGame(); } function initializeGame() { // Clear game state enemies = []; bullets = []; npcBullets = []; bazookaBullets = []; healthPacks = []; ammoBoxes = []; npcs = []; boss = null; bossSpawned = false; bossDied = false; gameTimer = 0; enemySpawnTimer = 0; waveNumber = 1; enemiesKilled = 0; survivalTime = 0; eclipsePhase = 0; eclipseTimer = 0; // Reset NPC ammo for existing NPCs (though npcs array is cleared above) for (var i = 0; i < npcs.length; i++) { npcs[i].ammo = 20; // Reset to starting ammo value } // Create player player = new Player(); player.x = 1024; player.y = 1366; game.addChild(player); // Create bazooka bazooka = new Bazooka(); bazooka.x = 1024; bazooka.y = 2000; game.addChild(bazooka); // Create UI healthText = new Text2('Health: 100', { size: 40, fill: 0x00ff00 }); healthText.x = 150; healthText.y = 150; LK.gui.topLeft.addChild(healthText); ammoText = new Text2('Ammo: 30', { size: 40, fill: 0xffff00 }); ammoText.x = 150; ammoText.y = 200; LK.gui.topLeft.addChild(ammoText); timeText = new Text2('Time: 0:00', { size: 40, fill: 0xffffff }); timeText.anchor.set(1, 0); timeText.x = -50; timeText.y = 150; LK.gui.topRight.addChild(timeText); if (selectedGameMode === 3) { eclipseText = new Text2('Phase: Normal', { size: 40, fill: 0xff6666 }); eclipseText.anchor.set(1, 0); eclipseText.x = -50; eclipseText.y = 200; LK.gui.topRight.addChild(eclipseText); } // Spawn 10 NPCs at game start for (var i = 0; i < 10; i++) { spawnNPC(); } // Create bazooka instruction text bazookaInstructionText = new Text2('BAZOOKA, CLICK TO LAUNCH', { size: 50, fill: 0xffaa00 }); bazookaInstructionText.anchor.set(0.5, 0); bazookaInstructionText.x = bazooka.x; bazookaInstructionText.y = bazooka.y + 30; game.addChild(bazookaInstructionText); // Create bazooka description text with difficulty-based percentages var bazookaChances = [{ target: 85, blank: 12, explode: 3 }, // Easy { target: 75, blank: 15, explode: 10 }, // Normal { target: 65, blank: 20, explode: 15 }, // Hard { target: 50, blank: 25, explode: 25 }, // Nightmare { target: 30, blank: 30, explode: 40 } // Impossible ]; var chances = bazookaChances[selectedDifficulty - 1]; var bazookaDescriptionText; if (selectedGameMode === 4) { // Practice mode: 100% guaranteed targeting bazookaDescriptionText = new Text2('100% GUARANTEED TARGET ENEMY', { size: 40, fill: 0x00ff00 }); } else { bazookaDescriptionText = new Text2(chances.target + '% target enemy, ' + chances.blank + '% blank ammo, ' + chances.explode + '% self explode', { size: 40, fill: 0xffcc66 }); } bazookaDescriptionText.anchor.set(0.5, 0); bazookaDescriptionText.x = bazooka.x; bazookaDescriptionText.y = bazooka.y + 80; game.addChild(bazookaDescriptionText); // Fade out instruction text after 3 seconds tween(bazookaInstructionText, { alpha: 0 }, { duration: 3000, onFinish: function onFinish() { if (bazookaInstructionText) { bazookaInstructionText.destroy(); bazookaInstructionText = null; } } }); // Fade out description text after 3 seconds tween(bazookaDescriptionText, { alpha: 0 }, { duration: 3000, onFinish: function onFinish() { if (bazookaDescriptionText) { bazookaDescriptionText.destroy(); bazookaDescriptionText = null; } } }); // Start background music LK.playMusic('bgmusic'); } function spawnEnemy() { var enemy = new Enemy(); // Spawn from random edge var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top enemy.x = Math.random() * 2048; enemy.y = -30; break; case 1: // Right enemy.x = 2078; enemy.y = Math.random() * 2732; break; case 2: // Bottom enemy.x = Math.random() * 2048; enemy.y = 2762; break; case 3: // Left enemy.x = -30; enemy.y = Math.random() * 2732; break; } // Apply difficulty-based health, speed and damage values var difficultyMultipliers = [{ health: 35, // Easy: 35 health speed: 0.8, damage: 0.7 }, // Easy { health: 50, // Normal: 50 health (default) speed: 1.0, damage: 1.0 }, // Normal { health: 75, // Hard: 75 health speed: 1.2, damage: 1.3 }, // Hard { health: 100, // Nightmare: 100 health speed: 1.4, damage: 1.6 }, // Nightmare { health: 150, // Impossible: 150 health speed: 4.0, damage: 2.0 } // Impossible: maximum challenge with insane speed ]; var multiplier = difficultyMultipliers[selectedDifficulty - 1]; enemy.health = multiplier.health; enemy.speed *= multiplier.speed; enemy.damage = Math.floor(enemy.damage * multiplier.damage); // Practice mode adjustments - make enemies very weak for learning if (selectedGameMode === 4) { enemy.health = 25; // Very low health enemy.speed *= 0.5; // Half speed enemy.damage = 5; // Very low damage } // Adjust enemy stats based on mode and wave if (selectedGameMode === 2) { // Endless Nightmare enemy.health += waveNumber * 10; enemy.speed += waveNumber * 0.3; enemy.damage += waveNumber * 5; } else if (selectedGameMode === 3) { // Blood Eclipse enemy.health += waveNumber * 15; enemy.speed += waveNumber * 0.5; enemy.damage += waveNumber * 8; if (eclipsePhase === 1) { // Blood moon enemy.health *= 1.5; enemy.speed *= 1.3; } else if (eclipsePhase === 2) { // Eclipse enemy.health *= 2; enemy.speed *= 1.5; enemy.damage *= 1.5; } } enemies.push(enemy); game.addChild(enemy); } function spawnHealthPack() { var healthPack = new HealthPack(); healthPack.x = 100 + Math.random() * 1848; healthPack.y = 100 + Math.random() * 2532; healthPacks.push(healthPack); game.addChild(healthPack); } function spawnAmmoBox() { var ammoBox = new AmmoBox(); ammoBox.x = 100 + Math.random() * 1848; ammoBox.y = 100 + Math.random() * 2532; ammoBoxes.push(ammoBox); game.addChild(ammoBox); } function spawnNPC() { var npc = new NPC(); // Spawn near player but not too close var angle = Math.random() * Math.PI * 2; var distance = 150 + Math.random() * 100; // 150-250 pixels from player npc.x = player.x + Math.cos(angle) * distance; npc.y = player.y + Math.sin(angle) * distance; // Keep in bounds if (npc.x < 40) npc.x = 40; if (npc.x > 2008) npc.x = 2008; if (npc.y < 40) npc.y = 40; if (npc.y > 2692) npc.y = 2692; npcs.push(npc); game.addChild(npc); } function spawnBoss() { boss = new Boss(); boss.x = 1024; boss.y = 100; bossSpawned = true; game.addChild(boss); // Create boss health UI bossHealthText = new Text2('BOSS: 100000 / 100000', { size: 50, fill: 0xff0000 }); bossHealthText.anchor.set(0.5, 0); LK.gui.top.addChild(bossHealthText); } function fireBullet(targetX, targetY) { if (player && player.shoot() && !usingBazooka) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y; // Auto-target nearest enemy or boss var targetEntity = null; var nearestDistance = Infinity; // Check boss first (highest priority) if (boss) { var dx = boss.x - player.x; var dy = boss.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); targetEntity = boss; nearestDistance = distance; } // Check enemies for closer targets for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - player.x; var dy = enemy.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; targetEntity = enemy; } } // Set bullet direction var dx, dy, distance; if (targetEntity) { // Target the nearest enemy or boss dx = targetEntity.x - player.x; dy = targetEntity.y - player.y; } else { // No targets, use tap location as fallback dx = targetX - player.x; dy = targetY - player.y; } distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { bullet.directionX = dx / distance; bullet.directionY = dy / distance; } bullets.push(bullet); game.addChild(bullet); // Play shooting sound LK.getSound('shoot').play(); } } function updateGameMode() { gameTimer++; survivalTime = Math.floor(gameTimer / 60); // Spawn boss at 06:00 (6 minutes) - but not in endless nightmare mode // Only spawn if boss hasn't been spawned yet, hasn't died yet, and no victory screen is showing if (survivalTime >= 360 && !bossSpawned && !bossDied && selectedGameMode !== 2 && boss === null) { spawnBoss(); } // Mode specific logic if (selectedGameMode === 1) { // Classic Survival // Win condition: survive 5 minutes if (survivalTime >= 300) { LK.showYouWin(); return; } // Spawn enemies based on time if (gameTimer % Math.max(30, 120 - survivalTime) === 0 && !bossDied) { spawnEnemy(); } // Spawn resources occasionally (adjusted by difficulty) var resourceMultipliers = [0.7, 1.0, 1.4, 2.0, 3.0]; // Easy, Normal, Hard, Nightmare, Impossible var resourceDelay = resourceMultipliers[selectedDifficulty - 1]; if (gameTimer % Math.floor(600 * resourceDelay) === 0) spawnHealthPack(); if (gameTimer % Math.floor(900 * resourceDelay) === 0) spawnAmmoBox(); // NPCs already spawned at game start - no additional spawning needed } else if (selectedGameMode === 2) { // Endless Nightmare // New wave every 30 seconds var newWave = Math.floor(survivalTime / 30) + 1; if (newWave > waveNumber) { waveNumber = newWave; } // Spawn enemies more frequently as waves progress var spawnRate = Math.max(10, 60 - waveNumber * 3); if (gameTimer % spawnRate === 0 && !bossDied) { spawnEnemy(); } // Spawn resources based on wave (adjusted by difficulty) var resourceMultipliers = [0.7, 1.0, 1.4, 2.0, 3.0]; // Easy, Normal, Hard, Nightmare, Impossible var resourceDelay = resourceMultipliers[selectedDifficulty - 1]; if (gameTimer % Math.floor((600 - waveNumber * 20) * resourceDelay) === 0) spawnHealthPack(); if (gameTimer % Math.floor((900 - waveNumber * 30) * resourceDelay) === 0) spawnAmmoBox(); // NPCs already spawned at game start - no additional spawning needed } else if (selectedGameMode === 3) { // Blood Eclipse eclipseTimer++; // Eclipse phases: 90s normal, 60s blood moon, 30s eclipse, repeat var cycleTime = eclipseTimer % (180 * 60); // 3 minutes cycle if (cycleTime < 90 * 60) { eclipsePhase = 0; // Normal } else if (cycleTime < 150 * 60) { eclipsePhase = 1; // Blood moon } else { eclipsePhase = 2; // Eclipse } // Spawn rate increases with phase var spawnRate = [60, 30, 15][eclipsePhase]; if (gameTimer % spawnRate === 0 && !bossDied) { spawnEnemy(); } // Resources spawn less during eclipse phases (adjusted by difficulty) var resourceRate = [600, 800, 1200][eclipsePhase]; var resourceMultipliers = [0.7, 1.0, 1.4, 2.0, 3.0]; // Easy, Normal, Hard, Nightmare, Impossible var adjustedRate = Math.floor(resourceRate * resourceMultipliers[selectedDifficulty - 1]); if (gameTimer % adjustedRate === 0) spawnHealthPack(); if (gameTimer % Math.floor(adjustedRate * 1.5) === 0) spawnAmmoBox(); // NPCs already spawned at game start - no additional spawning needed } else if (selectedGameMode === 4) { // Practice Mode // Very slow enemy spawning for learning if (gameTimer % 300 === 0 && !bossDied) { // Every 5 seconds spawnEnemy(); } // Frequent resource spawning to help learning if (gameTimer % 300 === 0) spawnHealthPack(); if (gameTimer % 450 === 0) spawnAmmoBox(); // No win condition - practice indefinitely // No boss spawning in practice mode } } function updateUI() { if (healthText) { healthText.setText('Health: ' + player.health); healthText.fill = player.health > 30 ? 0x00ff00 : 0xff0000; } if (ammoText) { ammoText.setText('Ammo: ' + player.ammo); ammoText.fill = player.ammo > 5 ? 0xffff00 : 0xff0000; } if (timeText) { var minutes = Math.floor(survivalTime / 60); var seconds = survivalTime % 60; timeText.setText('Time: ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds); } if (eclipseText && selectedGameMode === 3) { var phases = ['Normal', 'Blood Moon', 'Eclipse']; eclipseText.setText('Phase: ' + phases[eclipsePhase]); eclipseText.fill = [0xffffff, 0xff6666, 0x660000][eclipsePhase]; } if (bossHealthText && boss) { bossHealthText.setText('BOSS: ' + boss.health + ' / ' + boss.maxHealth); } } // Show menu on game start showMenu(); game.down = function (x, y, obj) { if (gameStarted && player) { fireBullet(x, y); } }; game.move = function (x, y, obj) { if (gameStarted && player) { player.x = x; player.y = y; } }; game.update = function () { if (!gameStarted) { return; } if (!player) return; // Update game mode logic updateGameMode(); // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].update(); // Check if enemy should be removed if (enemies[i].health <= 0) { var destroyedEnemy = enemies[i]; // Clean up shot tracking for all NPCs for (var n = 0; n < npcs.length; n++) { for (var s = npcs[n].shotAtEnemies.length - 1; s >= 0; s--) { if (npcs[n].shotAtEnemies[s] === destroyedEnemy) { npcs[n].shotAtEnemies.splice(s, 1); } } } destroyedEnemy.destroy(); enemies.splice(i, 1); enemiesKilled++; } } // Update NPCs for (var i = npcs.length - 1; i >= 0; i--) { var npc = npcs[i]; npc.update(); // Check if NPC died if (npc.health <= 0) { npc.destroy(); npcs.splice(i, 1); continue; } // Check NPC-enemy collisions (enemies can attack NPCs) for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; var dx = enemy.x - npc.x; var dy = enemy.y - npc.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 50 && enemy.attackCooldown <= 0) { // Practice mode: enemies do no damage to NPCs if (selectedGameMode === 4) { // No damage in practice mode } else { npc.takeDamage(enemy.damage); } enemy.attackCooldown = 60; break; } } // Check NPC-boss collision if (boss) { var dx = boss.x - npc.x; var dy = boss.y - npc.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100 && boss.attackCooldown <= 0) { // Practice mode: boss does no damage to NPCs if (selectedGameMode === 4) { // No damage in practice mode } else { npc.takeDamage(boss.damage); } boss.attackCooldown = 60; } } } // Update boss if (boss) { boss.update(); // Check if boss died if (boss.health <= 0) { // Clean up shot tracking for boss from all NPCs for (var n = 0; n < npcs.length; n++) { for (var s = npcs[n].shotAtEnemies.length - 1; s >= 0; s--) { if (npcs[n].shotAtEnemies[s] === boss) { npcs[n].shotAtEnemies.splice(s, 1); } } } boss.destroy(); boss = null; bossSpawned = false; bossDied = true; // Kill all remaining enemies for (var k = enemies.length - 1; k >= 0; k--) { enemies[k].destroy(); enemies.splice(k, 1); } if (bossHealthText) { bossHealthText.destroy(); bossHealthText = null; } // Show victory screen for 10 seconds before game over var victoryText = new Text2('YOU SURVIVED THIRD NIGHT,\nHOPE YOU DIDNT DEAD AT THE FOURTH NIGHT', { size: 80, fill: 0x00ff00, align: 'center' }); victoryText.anchor.set(0.5, 0.5); victoryText.x = 1024; victoryText.y = 1366; game.addChild(victoryText); // Play winning music LK.playMusic('winmusic'); // Fade in the victory text victoryText.alpha = 0; tween(victoryText, { alpha: 1 }, { duration: 1000 }); // Wait 10 seconds then show game over tween({}, {}, { duration: 10000, onFinish: function onFinish() { LK.showGameOver(); } }); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; var shouldRemove = bullet.update(); if (shouldRemove) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check bullet-enemy collisions for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j])) { var enemyDied = enemies[j].takeDamage(bullet.damage); bullet.destroy(); bullets.splice(i, 1); if (enemyDied) { enemies[j].destroy(); enemies.splice(j, 1); enemiesKilled++; } break; } } // Check bullet-boss collision if (boss && bullet.intersects(boss)) { var bossKilled = boss.takeDamage(bullet.damage); bullet.destroy(); bullets.splice(i, 1); if (bossKilled) { boss.destroy(); boss = null; bossSpawned = false; bossDied = true; // Kill all remaining enemies for (var k = enemies.length - 1; k >= 0; k--) { enemies[k].destroy(); enemies.splice(k, 1); } if (bossHealthText) { bossHealthText.destroy(); bossHealthText = null; } // Show victory screen for 10 seconds before game over var victoryText = new Text2('YOU SURVIVED THIRD NIGHT,\nHOPE YOU DIDNT DEAD AT THE FOURTH NIGHT', { size: 80, fill: 0x00ff00, align: 'center' }); victoryText.anchor.set(0.5, 0.5); victoryText.x = 1024; victoryText.y = 1366; game.addChild(victoryText); // Play winning music LK.playMusic('winmusic'); // Fade in the victory text victoryText.alpha = 0; tween(victoryText, { alpha: 1 }, { duration: 1000 }); // Wait 10 seconds then show game over tween({}, {}, { duration: 10000, onFinish: function onFinish() { LK.showGameOver(); } }); } break; } } // Update NPC bullets for (var i = npcBullets.length - 1; i >= 0; i--) { var bullet = npcBullets[i]; var shouldRemove = bullet.update(); if (shouldRemove) { bullet.destroy(); npcBullets.splice(i, 1); continue; } // Check NPC bullet-enemy collisions for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j])) { var enemyDied = enemies[j].takeDamage(bullet.damage); bullet.destroy(); npcBullets.splice(i, 1); if (enemyDied) { enemies[j].destroy(); enemies.splice(j, 1); enemiesKilled++; } break; } } // Check NPC bullet-boss collision if (boss && bullet.intersects(boss)) { var bossKilled = boss.takeDamage(bullet.damage); bullet.destroy(); npcBullets.splice(i, 1); if (bossKilled) { boss.destroy(); boss = null; bossSpawned = false; bossDied = true; // Kill all remaining enemies for (var k = enemies.length - 1; k >= 0; k--) { enemies[k].destroy(); enemies.splice(k, 1); } if (bossHealthText) { bossHealthText.destroy(); bossHealthText = null; } // Show victory screen for 10 seconds before game over var victoryText = new Text2('YOU SURVIVED THIRD NIGHT,\nHOPE YOU DIDNT DEAD AT THE FOURTH NIGHT', { size: 80, fill: 0x00ff00, align: 'center' }); victoryText.anchor.set(0.5, 0.5); victoryText.x = 1024; victoryText.y = 1366; game.addChild(victoryText); // Play winning music LK.playMusic('winmusic'); // Fade in the victory text victoryText.alpha = 0; tween(victoryText, { alpha: 1 }, { duration: 1000 }); // Wait 10 seconds then show game over tween({}, {}, { duration: 10000, onFinish: function onFinish() { LK.showGameOver(); } }); } break; } } // Update bazooka bullets for (var i = bazookaBullets.length - 1; i >= 0; i--) { var bullet = bazookaBullets[i]; var shouldRemove = bullet.update(); if (shouldRemove) { bullet.explode(); bullet.destroy(); bazookaBullets.splice(i, 1); continue; } // Check bazooka bullet-enemy collisions for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j])) { bullet.explode(); bullet.destroy(); bazookaBullets.splice(i, 1); break; } } // Check bazooka bullet-boss collision if (boss && bullet.intersects(boss)) { bullet.explode(); bullet.destroy(); bazookaBullets.splice(i, 1); break; } } // Update bazooka if (bazooka) { bazooka.update(); } // Update health packs for (var i = healthPacks.length - 1; i >= 0; i--) { var pack = healthPacks[i]; var shouldRemove = pack.update(); if (shouldRemove) { pack.destroy(); healthPacks.splice(i, 1); continue; } // Check player collision if (player.intersects(pack)) { player.heal(pack.healAmount); LK.getSound('heal').play(); pack.destroy(); healthPacks.splice(i, 1); } } // Update ammo boxes for (var i = ammoBoxes.length - 1; i >= 0; i--) { var box = ammoBoxes[i]; var shouldRemove = box.update(); if (shouldRemove) { box.destroy(); ammoBoxes.splice(i, 1); continue; } var collected = false; // Check player collision first (priority) if (player.intersects(box)) { player.addAmmo(box.ammoAmount); LK.getSound('ammo').play(); box.destroy(); ammoBoxes.splice(i, 1); collected = true; } // Check NPC collisions if not collected by player and NPC needs ammo if (!collected) { for (var k = 0; k < npcs.length; k++) { var npc = npcs[k]; if (npc.intersects(box) && npc.ammo < npc.maxAmmo - 5) { // NPCs only take if they really need ammo (leave some for player) npc.addAmmo(Math.floor(box.ammoAmount * 0.6)); // NPCs get 60% of ammo amount LK.getSound('ammo').play(); box.destroy(); ammoBoxes.splice(i, 1); collected = true; break; } } } } // Update UI updateUI(); };
===================================================================
--- original.js
+++ change.js
@@ -413,20 +413,55 @@
alpha: 0.7,
anchorX: 0.5,
anchorY: 0.5
});
+ // Difficulty-specific content
+ var difficultyTitles = ['THE FIRST DISCOVERY',
+ // Easy
+ 'THE ARSENAL AWAKENS',
+ // Normal
+ 'WEAPONS OF DESPERATION',
+ // Hard
+ 'TOOLS OF THE DAMNED',
+ // Nightmare
+ 'INSTRUMENTS OF MADNESS' // Impossible
+ ];
+ var difficultyStories = ['The survivors found a well-stocked military cache...\n\nBasic weapons lay ready for untrained hands:',
+ // Easy
+ 'The survivors searched through the abandoned military base...\n\nThey found weapons that could turn the tide:',
+ // Normal
+ 'Desperate survivors ransacked the decimated armory...\n\nOnly scraps of military hardware remained:',
+ // Hard
+ 'In the blood-soaked ruins of the command center...\n\nCursed weapons whispered promises of power:',
+ // Nightmare
+ 'Deep in the hellish depths of the facility...\n\nEldritch armaments pulsed with dark energy:' // Impossible
+ ];
+ var difficultyColors = [0x00FF00,
+ // Easy - Green
+ 0xFFFF00,
+ // Normal - Yellow
+ 0xFF8800,
+ // Hard - Orange
+ 0xFF0000,
+ // Nightmare - Red
+ 0x660066 // Impossible - Purple
+ ];
+ // Get difficulty-specific content
+ var selectedTitle = difficultyTitles[selectedDifficulty - 1] || difficultyTitles[1];
+ var selectedStory = difficultyStories[selectedDifficulty - 1] || difficultyStories[1];
+ var selectedColor = difficultyColors[selectedDifficulty - 1] || difficultyColors[1];
// Title
- var titleText = new Text2('THE DISCOVERY', {
+ var titleText = new Text2(selectedTitle, {
size: 100,
- fill: 0xFF4444,
+ fill: selectedColor,
align: 'center'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
self.addChild(titleText);
// Story text
- var storyText = new Text2('The survivors searched through the abandoned military base...\n\nThey found weapons that could turn the tide:', {
+ var storyText = new Text2(selectedStory, {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
@@ -442,9 +477,54 @@
y: 1200,
scaleX: 3,
scaleY: 3
});
- var gunText = new Text2('ASSAULT RIFLE\nAuto-targeting bullets', {
+ // Difficulty-specific weapon descriptions
+ var difficultyGunTexts = ['TRAINING RIFLE\nStable and reliable',
+ // Easy
+ 'ASSAULT RIFLE\nAuto-targeting bullets',
+ // Normal
+ 'DAMAGED RIFLE\nUnstable but functional',
+ // Hard
+ 'CURSED RIFLE\nFeeds on enemy souls',
+ // Nightmare
+ 'VOID RIFLE\nChannels cosmic horror' // Impossible
+ ];
+ var difficultyKnifeTexts = ['UTILITY KNIFE\nBasic close combat',
+ // Easy
+ 'COMBAT KNIFE\nClose quarters combat',
+ // Normal
+ 'RUSTED BLADE\nDull but deadly',
+ // Hard
+ 'BLOODTHIRSTY BLADE\nThirsts for carnage',
+ // Nightmare
+ 'ELDRITCH DAGGER\nCuts through reality' // Impossible
+ ];
+ var difficultyBazookaTexts = ['PRACTICE LAUNCHER\nSafe explosive training',
+ // Easy
+ 'BAZOOKA\nExplosive devastation',
+ // Normal
+ 'BROKEN LAUNCHER\nUnpredictable explosions',
+ // Hard
+ 'DEMON CANNON\nInfernal destruction',
+ // Nightmare
+ 'REALITY SHATTER\nBreaks space and time' // Impossible
+ ];
+ var difficultyFinalTexts = ['With proper training weapons, they felt ready\nfor the coming challenge...',
+ // Easy
+ 'Armed with these weapons, they prepared\nfor the nightmare ahead...',
+ // Normal
+ 'With broken tools and desperate hope,\nthey faced impossible odds...',
+ // Hard
+ 'Wielding cursed instruments of war,\nthey embraced their dark fate...',
+ // Nightmare
+ 'Bearing eldritch weapons of madness,\nthey prepared to shatter reality itself...' // Impossible
+ ];
+ var selectedGunText = difficultyGunTexts[selectedDifficulty - 1] || difficultyGunTexts[1];
+ var selectedKnifeText = difficultyKnifeTexts[selectedDifficulty - 1] || difficultyKnifeTexts[1];
+ var selectedBazookaText = difficultyBazookaTexts[selectedDifficulty - 1] || difficultyBazookaTexts[1];
+ var selectedFinalText = difficultyFinalTexts[selectedDifficulty - 1] || difficultyFinalTexts[1];
+ var gunText = new Text2(selectedGunText, {
size: 50,
fill: 0xFFFF00,
align: 'center'
});
@@ -459,9 +539,9 @@
y: 1200,
scaleX: 2,
scaleY: 2
});
- var knifeText = new Text2('COMBAT KNIFE\nClose quarters combat', {
+ var knifeText = new Text2(selectedKnifeText, {
size: 50,
fill: 0xC0C0C0,
align: 'center'
});
@@ -476,9 +556,9 @@
y: 1200,
scaleX: 1.5,
scaleY: 1.5
});
- var bazookaText = new Text2('BAZOOKA\nExplosive devastation', {
+ var bazookaText = new Text2(selectedBazookaText, {
size: 50,
fill: 0xFF8800,
align: 'center'
});
@@ -486,9 +566,9 @@
bazookaText.x = 1648;
bazookaText.y = 1350;
self.addChild(bazookaText);
// Final story text
- var finalText = new Text2('Armed with these weapons, they prepared\nfor the nightmare ahead...', {
+ var finalText = new Text2(selectedFinalText, {
size: 55,
fill: 0xFFFFFF,
align: 'center'
});
@@ -525,16 +605,52 @@
// Pulsing effects
if (continueText.alpha > 0) {
continueText.alpha = 0.5 + Math.sin(self.animationTimer * 0.1) * 0.3;
}
- moon.alpha = 0.5 + Math.sin(self.animationTimer * 0.05) * 0.2;
+ // Difficulty-specific moon effects
+ var baseMoonAlpha = 0.5 + Math.sin(self.animationTimer * 0.05) * 0.2;
+ moon.alpha = baseMoonAlpha;
+ // Change moon tint based on difficulty
+ var difficultyMoonTints = [0x8b1538,
+ // Easy - Default red
+ 0x8b1538,
+ // Normal - Default red
+ 0xFF4400,
+ // Hard - Darker red
+ 0x660000,
+ // Nightmare - Deep red
+ 0x330033 // Impossible - Purple
+ ];
+ moon.tint = difficultyMoonTints[selectedDifficulty - 1] || 0x8b1538;
+ // Add extra effects for higher difficulties
+ if (selectedDifficulty >= 4) {
+ moon.scaleX = 1.0 + Math.sin(self.animationTimer * 0.1) * 0.1;
+ moon.scaleY = 1.0 + Math.sin(self.animationTimer * 0.1) * 0.1;
+ }
skipButton.alpha = 0.7 + Math.sin(self.animationTimer * 0.08) * 0.3;
- // Weapon icon animations
+ // Weapon icon animations with difficulty-specific effects
if (self.animationPhase >= 2) {
+ // Base animations
gunIcon.rotation += 0.02;
knifeIcon.y = 1200 + Math.sin(self.animationTimer * 0.1) * 10;
bazookaIcon.scaleX = 1.5 + Math.sin(self.animationTimer * 0.08) * 0.1;
bazookaIcon.scaleY = 1.5 + Math.sin(self.animationTimer * 0.08) * 0.1;
+ // Difficulty-specific effects
+ if (selectedDifficulty >= 4) {
+ // Nightmare and Impossible
+ // Add pulsing tint effects for higher difficulties
+ var pulseStrength = Math.sin(self.animationTimer * 0.15) * 0.3;
+ gunIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100;
+ knifeIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100;
+ bazookaIcon.tint = 0xFF0000 + Math.floor(pulseStrength * 255) * 0x010100;
+ }
+ if (selectedDifficulty === 5) {
+ // Impossible - add reality distortion
+ var distortion = Math.sin(self.animationTimer * 0.2) * 5;
+ gunIcon.x = 400 + distortion;
+ knifeIcon.x = 1024 + distortion;
+ bazookaIcon.x = 1648 + distortion;
+ }
}
// Auto-advance cutscene phases
if (self.animationTimer === 120) {
// 2 seconds