User prompt
Health kits should arrive more frequently, bullets should arrive more frequently, and enemies should arrive slower and less frequently.
User prompt
Let the background be World War I
User prompt
Make the background appear faded
User prompt
Background is Forest war
User prompt
Background is war arena
User prompt
Make the Background in a battlefield style location
User prompt
hp text to upper left
User prompt
move the hp text to the right
User prompt
Separate hp text from score text
User prompt
Asker figürü ekle
Code edit (1 edits merged)
Please save this source code
User prompt
Iron Valor: Warfront Assault
Initial prompt
Game Title: Iron Valor: Warfront Assault 🔥 Description: Lock and load, soldier! Step into the boots of elite commando Captain Rhea Morgan in Iron Valor: Warfront Assault — a high-octane 2D military action game that drops you into the frontlines of a futuristic global conflict. Lead a tactical strike team behind enemy lines, destroy war machines, liberate zones, and uncover the dark truth behind a global AI conspiracy. Whether you're storming desert outposts, battling in snow-covered trenches, or sneaking through enemy bunkers, every mission tests your reflexes, tactics, and courage. 🪖 Key Features: 🔫 Intense 2D War Combat Classic run-and-gun action combined with modern tactical mechanics. Shoot, dodge, throw grenades, and control dron 🎯 Squ Command up to 3 AI soldiers: issue orders like “Hold Positio Upgrade your team with different roles: Medic, Heavy Gunner, Sniper, and more. 💥 Epic Boss Battles Face heavily armored tanks, mech walkers, and flying war drones in multi-phase boss fights. 🛠️ Base and Weapon Upgrades Collect intel and resources to upgrade your base, unlock weapons, and craft gear. Choose from over 25 unique weapons: assault rifles, RPGs, flamethrowers, and EMP launchers. 🌍 Diverse Battle Zones Campaign mode spans 6 war-torn regions: Jungle, Desert, Snowfield, Ruins, Cyber City, and The Final Fortress. Each environment features unique enemies and environmental hazards (mines, gas, falling debris). 🎮 Offline & Controller Support Fully playable offline. Optimized for touch controls & external controllers. 🎖️ Story Summary: In the near future, the world has collapsed into chaos. Mega-corporations and AI armies rule the continents. The last hope for humanity lies with a rogue special ops team led by Captain Morgan, operating from a hidden resistance base. Your mission: destroy Project Vulture, a weaponized AI threatening to wipe out every living human.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Enemy: Drone var Drone = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('drone', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 1; self.shootCooldown = 0; self.update = function () { self.x -= 8; }; return self; }); // Enemy bullet var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGfx = self.attachAsset('bullet_enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -18; self.update = function () { self.x += self.speed; }; return self; }); // Explosion effect var Explosion = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); // Animate fade out tween(gfx, { alpha: 0 }, { duration: 400, easing: tween.linear, onFinish: function onFinish() { self.destroy(); } }); return self; }); // Squad member: Chapter2 J var J = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('j', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 4; self.role = 'j'; self.shootCooldown = 0; self.update = function () {}; return self; }); // Laser bullet for J var LaserBullet = Container.expand(function () { var self = Container.call(this); var laserGfx = self.attachAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, width: 40, height: 12, color: 0xff00ff, shape: 'box' }); self.speed = 32; self.update = function () { self.x += self.speed; }; return self; }); // Squad member: Medic var Medic = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('medic', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 3; self.role = 'medic'; self.update = function () {}; return self; }); // Player bullet var PlayerBullet = Container.expand(function (assetOverride) { var self = Container.call(this); var assetId = assetOverride || 'bullet_player'; var bulletGfx = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.speed = 32; self.update = function () { self.x += self.speed; }; return self; }); // Powerup: Ammo var PowerupAmmo = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('powerup_ammo', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x -= 6; }; return self; }); // Powerup: Health var PowerupHealth = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('powerup_health', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x -= 6; }; return self; }); // Captain Rhea Morgan (player) var Rhea = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('rhea', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 5; self.shootCooldown = 0; self.update = function () {}; return self; }); // Squad member: Chapter2 S var S = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('s', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 4; self.role = 's'; self.shootCooldown = 0; self.update = function () {}; return self; }); // Squad member: Sniper var Sniper = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('sniper', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 2; self.role = 'sniper'; self.shootCooldown = 0; self.update = function () {}; return self; }); // Enemy: Tank (mini-boss) var Tank = Container.expand(function () { var self = Container.call(this); var gfx = self.attachAsset('tank', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 10; self.shootCooldown = 0; self.update = function () { self.x -= 4; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222831 }); /**** * Game Code ****/ // World War I background image var battlefieldBg = LK.getAsset('ww1_bg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.35 }); game.addChild(battlefieldBg); // Track if chapter 2 background has been swapped var chapter2BgSwapped = false; // Play music // Main character: Captain Rhea Morgan // Squad member: Medic // Squad member: Sniper // Enemy: Drone // Enemy: Tank // Bullet: Player // Bullet: Enemy // Powerup: Health // Powerup: Ammo // Explosion effect // Sound effects // Music LK.playMusic('battle_theme'); // Game state variables var rhea, medic, sniper; var mh2; // Track mh2 globally for chapter 2 var squad = []; var playerBullets = []; var enemyBullets = []; var enemies = []; var powerups = []; var explosions = []; var score = 0; var resources = 0; var gameOver = false; var youWin = false; var dragNode = null; var lastTouchX = 0, lastTouchY = 0; // Used to block all spawns and shooting during boss warning var bossWarningActive = false; // Used to pause enemy/powerup spawn at start of Chapter 2 var chapter2PauseTicks = 0; // Track if chapter 2 has started var chapter2Started = false; // UI var scoreTxt = new Text2('0', { size: 100, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var hpTxt = new Text2('HP: 5', { size: 70, fill: 0xFF5252 }); // Move HP text to the upper left, avoiding the top left 100x100 px reserved area hpTxt.anchor.set(0, 0); hpTxt.x = 110; // 10px right of reserved area hpTxt.y = 10; LK.gui.topLeft.addChild(hpTxt); var resourceTxt = new Text2('Res: 0', { size: 70, fill: 0xFFD600 }); resourceTxt.anchor.set(1, 0); LK.gui.topRight.addChild(resourceTxt); // Initialize player and squad rhea = new Rhea(); rhea.x = 400; rhea.y = 2732 / 2; game.addChild(rhea); medic = new Medic(); medic.x = rhea.x - 120; medic.y = rhea.y + 120; game.addChild(medic); sniper = new Sniper(); sniper.x = rhea.x - 120; sniper.y = rhea.y - 120; game.addChild(sniper); squad = [rhea, medic, sniper]; // Helper: spawn enemy function spawnEnemy() { // Only spawn J and S as enemies in Chapter 2 (never ch2) if (chapter2Started) { // If bossSpawned, do not spawn any more enemies (only mh2 is allowed) if (typeof bossSpawned !== "undefined" && bossSpawned) { return; } // Alternate between J and S, but skip J if bossSpawned var enemy; if (LK.ticks % 2 === 0) { enemy = new J(); enemy.x = 2048 + 120; enemy.y = 300 + Math.floor(Math.random() * (2732 - 600)); enemy.direction = -1; enemy.shootCooldown = 40; enemy.lastX = enemy.x; } else { enemy = new S(); enemy.x = -120; enemy.y = 300 + Math.floor(Math.random() * (2732 - 600)); enemy.direction = 1; enemy.lastX = enemy.x; } // Prevent spawning ch2 as an enemy in chapter 2 if (enemy && enemy.children && enemy.children.length > 0 && enemy.children[0].assetId === 'ch2') { // Do not add ch2 as an enemy } else { enemies.push(enemy); game.addChild(enemy); } } else { var type = LK.ticks % 300 === 0 ? 'tank' : 'drone'; var enemy; if (type === 'drone') { enemy = new Drone(); enemy.x = 2048 + 60; enemy.y = 300 + Math.floor(Math.random() * (2732 - 600)); } else { enemy = new Tank(); enemy.x = 2048 + 120; enemy.y = 400 + Math.floor(Math.random() * (2732 - 800)); } enemies.push(enemy); game.addChild(enemy); } } // Helper: spawn powerup function spawnPowerup() { // In chapter 2, further increase chance of health powerup if (typeof bossSpawned !== "undefined" && bossSpawned) { // No powerups after boss appears return; } var healthChance = chapter2Started ? 0.92 : 0.5; // Increased to 92% in chapter 2 var type = Math.random() < healthChance ? 'health' : 'ammo'; var powerup; if (type === 'health') { powerup = new PowerupHealth(); } else { powerup = new PowerupAmmo(); } powerup.x = 2048 + 60; powerup.y = 300 + Math.floor(Math.random() * (2732 - 600)); powerups.push(powerup); game.addChild(powerup); } // Helper: fire player bullet function firePlayerBullet(from) { // Use ma2 asset for player bullet in Chapter 2, otherwise use default var bullet; if (chapter2Started) { bullet = new PlayerBullet('ma2'); } else { bullet = new PlayerBullet(); } bullet.x = from.x + 70; bullet.y = from.y; // Stronger sniper: sniper bullets do more damage if (from.role === 'sniper') { bullet.damage = 6; } else if (chapter2Started && from === rhea) { bullet.damage = 6; // Increase main character's weapon damage in chapter 2 } else { bullet.damage = 3; } playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot_player').play(); } // Helper: fire enemy bullet function fireEnemyBullet(from) { var bullet = new EnemyBullet(); bullet.x = from.x - 70; bullet.y = from.y; enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot_enemy').play(); } // Helper: show explosion function showExplosion(x, y) { var exp = new Explosion(); exp.x = x; exp.y = y; explosions.push(exp); game.addChild(exp); LK.getSound('explosion').play(); } // Helper: update UI function updateUI() { scoreTxt.setText(score); hpTxt.setText('HP: ' + rhea.hp); resourceTxt.setText('Res: ' + resources); } // Handle dragging Rhea (player) function handleMove(x, y, obj) { if (dragNode) { // Clamp to game area var minY = 120, maxY = 2732 - 120; dragNode.y = Math.max(minY, Math.min(maxY, y)); lastTouchX = x; lastTouchY = y; } } game.move = handleMove; game.down = function (x, y, obj) { // Only allow dragging Rhea if (!gameOver && !youWin) { if (Math.abs(x - rhea.x) < 120 && Math.abs(y - rhea.y) < 120) { dragNode = rhea; handleMove(x, y, obj); } } }; game.up = function (x, y, obj) { dragNode = null; }; // Main game update loop game.update = function () { if (gameOver || youWin) return; // Player auto-fire if ( // Only allow auto-fire if not in chapter 2 pause, or if chapter 2 hasn't started yet, or if not in chapter 2 (!chapter2Started || typeof chapter2PauseTicks !== "undefined" && chapter2PauseTicks === 0 // Block auto-fire during boss warning ) && !bossWarningActive) { if (rhea.shootCooldown > 0) rhea.shootCooldown--; if (rhea.shootCooldown === 0) { firePlayerBullet(rhea); rhea.shootCooldown = 10; } // Sniper auto-fire (slower) if (sniper.shootCooldown > 0) sniper.shootCooldown--; if (sniper.shootCooldown === 0) { firePlayerBullet(sniper); sniper.shootCooldown = 30; } } // Medic follows Rhea medic.x += (rhea.x - 120 - medic.x) * 0.15; medic.y += (rhea.y + 120 - medic.y) * 0.15; // Sniper follows Rhea sniper.x += (rhea.x - 120 - sniper.x) * 0.15; sniper.y += (rhea.y - 120 - sniper.y) * 0.15; // Spawn enemies if (typeof chapter2PauseTicks !== "undefined" && chapter2PauseTicks > 0) { chapter2PauseTicks--; } else if (!bossWarningActive) { // Block all spawns during boss warning // Only spawn if not in chapter2 pause or boss warning if (LK.ticks % 120 === 0) { spawnEnemy(); } // Spawn powerups if (chapter2Started) { // In chapter 2, spawn powerups more often (every 90 ticks) if (LK.ticks % 90 === 0) { spawnPowerup(); } } else { if (LK.ticks % 180 === 0) { spawnPowerup(); } } } // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); // Remove if off screen if (b.x > 2048 + 60) { b.destroy(); playerBullets.splice(i, 1); continue; } // Hit enemy for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; if (b.intersects(e)) { var dmg = typeof b.damage === "number" ? b.damage : 3; e.hp -= dmg; showExplosion(b.x, b.y); b.destroy(); playerBullets.splice(i, 1); if (e.hp <= 0) { showExplosion(e.x, e.y); score += e instanceof Tank ? 10 : 2; resources += e instanceof Tank ? 5 : 1; e.destroy(); enemies.splice(j, 1); } updateUI(); break; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var b = enemyBullets[i]; b.update(); if (b.x < -60) { b.destroy(); enemyBullets.splice(i, 1); continue; } // Hit squad for (var j = 0; j < squad.length; j++) { var s = squad[j]; if (b.intersects(s)) { // If mh2 fired this bullet, do more damage (enemy bullet collision) if (mh2 && b.parent === mh2) { s.hp -= mh2.damage || 6; } else { s.hp--; } showExplosion(b.x, b.y); b.destroy(); enemyBullets.splice(i, 1); if (s.hp <= 0) { showExplosion(s.x, s.y); if (s === rhea) { // Game over gameOver = true; LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else { s.destroy(); squad.splice(j, 1); } } updateUI(); break; } } } // Laser bullets from J for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; if (b instanceof LaserBullet) { b.update(); // Remove if off screen if (b.x > 2048 + 60) { b.destroy(); playerBullets.splice(i, 1); continue; } // Hit squad (including Rhea) for (var j = 0; j < squad.length; j++) { var s = squad[j]; if (b.intersects(s)) { s.hp -= 2; // Laser does 2 damage showExplosion(b.x, b.y); b.destroy(); playerBullets.splice(i, 1); if (s.hp <= 0) { showExplosion(s.x, s.y); if (s === rhea) { // Game over gameOver = true; LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else { s.destroy(); squad.splice(j, 1); } } updateUI(); break; } } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; // Special movement for J and S in chapter 2 if (e.role === 'j' && chapter2Started) { // J moves left until near player, then stops if (typeof e.lastX === "undefined") e.lastX = e.x; if (e.x > rhea.x + 300) { e.x -= 12; } // J fires laser continuously at player from the beginning of chapter 2 if (e.shootCooldown > 0) e.shootCooldown--; if (e.shootCooldown === 0) { // If mh2 is present, fire at mh2, otherwise fire at Rhea var target = rhea; if (typeof mh2 !== "undefined" && mh2 && mh2.parent) { target = mh2; } var laser = new LaserBullet(); laser.x = e.x - 60; laser.y = e.y; // Calculate direction vector from J to target var dx = target.x - e.x; var dy = target.y - e.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist === 0) dist = 1; laser.dirX = dx / dist; laser.dirY = dy / dist; laser.speed = 32; // Override update to move toward target laser.update = function () { this.x += this.dirX * this.speed; this.y += this.dirY * this.speed; }; playerBullets.push(laser); game.addChild(laser); e.shootCooldown = 18; // J fires every 18 ticks (slower fire rate) } e.lastX = e.x; } else if (e.role === 's' && chapter2Started) { // S moves right until near player, then stops if (typeof e.lastX === "undefined") e.lastX = e.x; if (e.x < rhea.x - 300) { e.x += 12; } e.lastX = e.x; } else { e.update(); } // Remove if off screen if (e.role !== 'j' && e.role !== 's' && (e.x < -200 || e.x > 2048 + 200)) { e.destroy(); enemies.splice(i, 1); continue; } // Enemy fire (for non-J/S enemies) if ((!e.role || e.role !== 'j' && e.role !== 's') && e.shootCooldown !== undefined) { if (e.shootCooldown > 0) e.shootCooldown--; if (e.shootCooldown === 0) { // Only fire if on screen if (e.x < 2048 && e.x > 0) { fireEnemyBullet(e); e.shootCooldown = e instanceof Tank ? 30 : 60; } } } // Collide with player if (e.intersects(rhea)) { // If mh2, do more damage if (mh2 && e === mh2) { rhea.hp -= mh2.damage || 6; } else { rhea.hp -= 2; } showExplosion(e.x, e.y); e.destroy(); enemies.splice(i, 1); if (rhea.hp <= 0) { gameOver = true; LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } updateUI(); } } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { var p = powerups[i]; p.update(); if (p.x < -60) { p.destroy(); powerups.splice(i, 1); continue; } // Pickup by player if (p.intersects(rhea)) { if (p instanceof PowerupHealth) { rhea.hp = Math.min(rhea.hp + 2, 7); } else if (p instanceof PowerupAmmo) { // For MVP, just increase resources resources += 2; } LK.getSound('pickup').play(); p.destroy(); powerups.splice(i, 1); updateUI(); } } // Chapter 2 trigger and Win condition if (typeof chapter2Started === "undefined") { chapter2Started = false; } // --- BOSS WARNING & MH2 SPAWN LOGIC FOR CHAPTER 2 --- // Track boss warning and boss spawn state if (typeof bossWarningShown === "undefined") bossWarningShown = false; if (typeof bossSpawned === "undefined") bossSpawned = false; if (typeof bossWarningOverlay === "undefined") bossWarningOverlay = null; if (typeof bossWarningTimer === "undefined") bossWarningTimer = 0; // Show boss warning at 40 points in chapter 2, only once if (chapter2Started && score >= 40 && !bossWarningShown) { // Show overlay message bossWarningOverlay = new Container(); var bossWarnBg = LK.getAsset('centerCircle', { width: 2048, height: 2732, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 1 }); bossWarningOverlay.addChild(bossWarnBg); var bossWarnTxt = new Text2('THE BOSS IS COMING', { size: 180, fill: 0xFFD700, font: "Impact, 'Arial Black', Tahoma" }); bossWarnTxt.anchor.set(0.5, 0.5); bossWarnTxt.x = 2048 / 2; bossWarnTxt.y = 2732 / 2; bossWarningOverlay.addChild(bossWarnTxt); game.addChild(bossWarningOverlay); bossWarningShown = true; bossWarningTimer = 120; // Show for 2 seconds (120 ticks) // Block all spawns and shooting until boss appears bossWarningActive = true; } // Remove boss warning overlay after timer, and spawn mh2 if not already spawned if (bossWarningShown && bossWarningOverlay && bossWarningTimer > 0) { bossWarningTimer--; if (bossWarningTimer === 0) { if (bossWarningOverlay && bossWarningOverlay.parent) { bossWarningOverlay.parent.removeChild(bossWarningOverlay); bossWarningOverlay.destroy(); } bossWarningOverlay = null; // Unblock spawns and shooting bossWarningActive = false; // Spawn mh2 as boss if not already spawned if (!bossSpawned) { // Remove all J, S, and any other enemies except mh2 from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] && (enemies[i].role === 'j' || enemies[i].role === 's' || enemies[i] !== mh2)) { enemies[i].destroy(); enemies.splice(i, 1); } } bossSpawned = true; allowJSpawning = false; // Spawn mh2 at boss position (center right) mh2 = LK.getAsset('mh2', { anchorX: 0.5, anchorY: 0.5 }); mh2.x = 2048 - 200; mh2.y = 2732 / 2; mh2.hp = 30; mh2.damage = 12; // Very high damage mh2.lastX = mh2.x; mh2.lastY = mh2.y; mh2.shootCooldown = 30; // Boss fires every 30 ticks mh2.dir = 1; mh2.update = function () { if (typeof this.lastY === "undefined") this.lastY = this.y; this.y += this.dir * 8; if (this.y > 2732 - 200) this.dir = -1; if (this.y < 200) this.dir = 1; this.lastY = this.y; // Boss shooting logic if (typeof this.shootCooldown === "undefined") this.shootCooldown = 30; if (this.shootCooldown > 0) this.shootCooldown--; if (this.shootCooldown === 0) { // Fire a burst of 3 bullets in a spread for (var i = -1; i <= 1; i++) { var bullet = new EnemyBullet(); bullet.x = this.x - 70; bullet.y = this.y + i * 40; bullet.speed = -24; bullet.update = function (angle) { return function () { this.x += this.speed; this.y += angle * 8; }; }(i); enemyBullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot_enemy').play(); this.shootCooldown = 30; } }; // Add boss to enemies for collision/damage logic enemies.push(mh2); game.addChild(mh2); } } } // --- END BOSS LOGIC --- if (!chapter2Started && score >= 30) { chapter2Started = true; // Play S2 as background music in chapter 2 LK.playMusic('s2'); // Swap background to bf2 for chapter 2 if (!chapter2BgSwapped) { var bf2Bg = LK.getAsset('bf2', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.5 }); // Remove old background if (battlefieldBg && battlefieldBg.parent) { battlefieldBg.parent.removeChild(battlefieldBg); } game.addChildAt(bf2Bg, 0); // Add at bottom chapter2BgSwapped = true; } // Change Rhea's asset to ch2 for chapter 2 (main character is now ch2) if (rhea && rhea.children && rhea.children.length > 0) { // Remove old asset var oldGfx = rhea.children[0]; rhea.removeChild(oldGfx); // Add new ch2 asset var newGfx = rhea.attachAsset('ch2', { anchorX: 0.5, anchorY: 0.5 }); // Optionally update rhea's role/assetId for clarity rhea.role = 'ch2'; rhea.assetId = 'ch2'; } chapter2PauseTicks = 120; // 2 seconds at 60fps // Remove medic and sniper from squad and game if (medic && medic.parent) { medic.parent.removeChild(medic); medic.destroy(); } if (sniper && sniper.parent) { sniper.parent.removeChild(sniper); sniper.destroy(); } // Remove medic and sniper from squad array for (var i = squad.length - 1; i >= 0; i--) { if (squad[i] === medic || squad[i] === sniper) { squad.splice(i, 1); } } // Remove medic, sniper, and any ch2 from enemies array if present for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === medic || enemies[i] === sniper || enemies[i].children && enemies[i].children.length > 0 && enemies[i].children[0].assetId === 'ch2') { enemies[i].destroy(); enemies.splice(i, 1); } } // In chapter 2, set attackers to be J and S only (handled in spawnEnemy) // Create a black overlay var chapter2Overlay = new Container(); var blackBg = LK.getAsset('centerCircle', { width: 2048, height: 2732, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 1 }); chapter2Overlay.addChild(blackBg); // Show chapter 2 message var chapter2Txt = new Text2('Chapter 2: Firestorm Rising', { size: 120, fill: 0x00BFFF, font: "Impact, 'Arial Black', Tahoma" }); chapter2Txt.anchor.set(0.5, 0.5); chapter2Txt.x = 2048 / 2; chapter2Txt.y = 2732 / 2; chapter2Overlay.addChild(chapter2Txt); game.addChild(chapter2Overlay); // Fade out the overlay and message after 2 seconds tween(chapter2Overlay, { alpha: 0 }, { duration: 2000, easing: tween.linear, onFinish: function onFinish() { chapter2Overlay.destroy(); } }); // Remove all non-J/S/ch2 enemies from the field at the start of Chapter 2 for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; // Remove any enemy that is not 'j' or 's' or is a ch2 (since player is ch2 now) if (!(e.role === 'j' || e.role === 's') || e !== rhea && e.children && e.children.length > 0 && e.children[0].assetId === 'ch2') { e.destroy(); enemies.splice(i, 1); } } // Remove J and S spawn logic after boss warning, only allow mh2 to appear after warning // (No J or S spawn, only mh2 will appear after boss warning) if (bossSpawned) { // Remove all squad members except Rhea (main character) for (var i = squad.length - 1; i >= 0; i--) { if (squad[i] !== rhea) { if (squad[i].parent) squad[i].parent.removeChild(squad[i]); squad[i].destroy(); squad.splice(i, 1); } } // Remove all enemies except mh2 for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] !== mh2) { enemies[i].destroy(); enemies.splice(i, 1); } } // Block all spawns except mh2 (no-op, as mh2 is already spawned) } } // Game over when mh2 (boss) is defeated in chapter 2 if (bossSpawned && mh2 && typeof mh2.hp === "number" && mh2.hp <= 0) { gameOver = true; LK.effects.flashScreen(0x000000, 1000); var bossDefeatedTxt = new Text2('New Boss of the Game', { size: 180, fill: 0xFFD700, font: "Impact, 'Arial Black', Tahoma" }); bossDefeatedTxt.anchor.set(0.5, 0.5); bossDefeatedTxt.x = 2048 / 2; bossDefeatedTxt.y = 2732 / 2; game.addChild(bossDefeatedTxt); // End game after a short delay to show the message LK.setTimeout(function () { LK.showGameOver(); }, 1600); return; } // Win condition: score threshold if (score >= 50) { youWin = true; LK.effects.flashScreen(0x00ff00, 1000); // Show 'You are a Real Player' as a gesture var playerTxt = new Text2('You are a Real Player', { size: 140, fill: 0xFFD700, font: "Impact, 'Arial Black', Tahoma" }); playerTxt.anchor.set(0.5, 0.5); playerTxt.x = 2048 / 2; playerTxt.y = 2732 / 2; game.addChild(playerTxt); LK.showYouWin(); return; } }; // Initial UI update updateUI();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy: Drone
var Drone = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('drone', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 1;
self.shootCooldown = 0;
self.update = function () {
self.x -= 8;
};
return self;
});
// Enemy bullet
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('bullet_enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -18;
self.update = function () {
self.x += self.speed;
};
return self;
});
// Explosion effect
var Explosion = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
// Animate fade out
tween(gfx, {
alpha: 0
}, {
duration: 400,
easing: tween.linear,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
// Squad member: Chapter2 J
var J = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('j', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 4;
self.role = 'j';
self.shootCooldown = 0;
self.update = function () {};
return self;
});
// Laser bullet for J
var LaserBullet = Container.expand(function () {
var self = Container.call(this);
var laserGfx = self.attachAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
width: 40,
height: 12,
color: 0xff00ff,
shape: 'box'
});
self.speed = 32;
self.update = function () {
self.x += self.speed;
};
return self;
});
// Squad member: Medic
var Medic = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('medic', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 3;
self.role = 'medic';
self.update = function () {};
return self;
});
// Player bullet
var PlayerBullet = Container.expand(function (assetOverride) {
var self = Container.call(this);
var assetId = assetOverride || 'bullet_player';
var bulletGfx = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 32;
self.update = function () {
self.x += self.speed;
};
return self;
});
// Powerup: Ammo
var PowerupAmmo = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('powerup_ammo', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x -= 6;
};
return self;
});
// Powerup: Health
var PowerupHealth = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('powerup_health', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x -= 6;
};
return self;
});
// Captain Rhea Morgan (player)
var Rhea = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('rhea', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 5;
self.shootCooldown = 0;
self.update = function () {};
return self;
});
// Squad member: Chapter2 S
var S = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('s', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 4;
self.role = 's';
self.shootCooldown = 0;
self.update = function () {};
return self;
});
// Squad member: Sniper
var Sniper = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('sniper', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 2;
self.role = 'sniper';
self.shootCooldown = 0;
self.update = function () {};
return self;
});
// Enemy: Tank (mini-boss)
var Tank = Container.expand(function () {
var self = Container.call(this);
var gfx = self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 10;
self.shootCooldown = 0;
self.update = function () {
self.x -= 4;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222831
});
/****
* Game Code
****/
// World War I background image
var battlefieldBg = LK.getAsset('ww1_bg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
alpha: 0.35
});
game.addChild(battlefieldBg);
// Track if chapter 2 background has been swapped
var chapter2BgSwapped = false;
// Play music
// Main character: Captain Rhea Morgan
// Squad member: Medic
// Squad member: Sniper
// Enemy: Drone
// Enemy: Tank
// Bullet: Player
// Bullet: Enemy
// Powerup: Health
// Powerup: Ammo
// Explosion effect
// Sound effects
// Music
LK.playMusic('battle_theme');
// Game state variables
var rhea, medic, sniper;
var mh2; // Track mh2 globally for chapter 2
var squad = [];
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerups = [];
var explosions = [];
var score = 0;
var resources = 0;
var gameOver = false;
var youWin = false;
var dragNode = null;
var lastTouchX = 0,
lastTouchY = 0;
// Used to block all spawns and shooting during boss warning
var bossWarningActive = false;
// Used to pause enemy/powerup spawn at start of Chapter 2
var chapter2PauseTicks = 0;
// Track if chapter 2 has started
var chapter2Started = false;
// UI
var scoreTxt = new Text2('0', {
size: 100,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var hpTxt = new Text2('HP: 5', {
size: 70,
fill: 0xFF5252
});
// Move HP text to the upper left, avoiding the top left 100x100 px reserved area
hpTxt.anchor.set(0, 0);
hpTxt.x = 110; // 10px right of reserved area
hpTxt.y = 10;
LK.gui.topLeft.addChild(hpTxt);
var resourceTxt = new Text2('Res: 0', {
size: 70,
fill: 0xFFD600
});
resourceTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(resourceTxt);
// Initialize player and squad
rhea = new Rhea();
rhea.x = 400;
rhea.y = 2732 / 2;
game.addChild(rhea);
medic = new Medic();
medic.x = rhea.x - 120;
medic.y = rhea.y + 120;
game.addChild(medic);
sniper = new Sniper();
sniper.x = rhea.x - 120;
sniper.y = rhea.y - 120;
game.addChild(sniper);
squad = [rhea, medic, sniper];
// Helper: spawn enemy
function spawnEnemy() {
// Only spawn J and S as enemies in Chapter 2 (never ch2)
if (chapter2Started) {
// If bossSpawned, do not spawn any more enemies (only mh2 is allowed)
if (typeof bossSpawned !== "undefined" && bossSpawned) {
return;
}
// Alternate between J and S, but skip J if bossSpawned
var enemy;
if (LK.ticks % 2 === 0) {
enemy = new J();
enemy.x = 2048 + 120;
enemy.y = 300 + Math.floor(Math.random() * (2732 - 600));
enemy.direction = -1;
enemy.shootCooldown = 40;
enemy.lastX = enemy.x;
} else {
enemy = new S();
enemy.x = -120;
enemy.y = 300 + Math.floor(Math.random() * (2732 - 600));
enemy.direction = 1;
enemy.lastX = enemy.x;
}
// Prevent spawning ch2 as an enemy in chapter 2
if (enemy && enemy.children && enemy.children.length > 0 && enemy.children[0].assetId === 'ch2') {
// Do not add ch2 as an enemy
} else {
enemies.push(enemy);
game.addChild(enemy);
}
} else {
var type = LK.ticks % 300 === 0 ? 'tank' : 'drone';
var enemy;
if (type === 'drone') {
enemy = new Drone();
enemy.x = 2048 + 60;
enemy.y = 300 + Math.floor(Math.random() * (2732 - 600));
} else {
enemy = new Tank();
enemy.x = 2048 + 120;
enemy.y = 400 + Math.floor(Math.random() * (2732 - 800));
}
enemies.push(enemy);
game.addChild(enemy);
}
}
// Helper: spawn powerup
function spawnPowerup() {
// In chapter 2, further increase chance of health powerup
if (typeof bossSpawned !== "undefined" && bossSpawned) {
// No powerups after boss appears
return;
}
var healthChance = chapter2Started ? 0.92 : 0.5; // Increased to 92% in chapter 2
var type = Math.random() < healthChance ? 'health' : 'ammo';
var powerup;
if (type === 'health') {
powerup = new PowerupHealth();
} else {
powerup = new PowerupAmmo();
}
powerup.x = 2048 + 60;
powerup.y = 300 + Math.floor(Math.random() * (2732 - 600));
powerups.push(powerup);
game.addChild(powerup);
}
// Helper: fire player bullet
function firePlayerBullet(from) {
// Use ma2 asset for player bullet in Chapter 2, otherwise use default
var bullet;
if (chapter2Started) {
bullet = new PlayerBullet('ma2');
} else {
bullet = new PlayerBullet();
}
bullet.x = from.x + 70;
bullet.y = from.y;
// Stronger sniper: sniper bullets do more damage
if (from.role === 'sniper') {
bullet.damage = 6;
} else if (chapter2Started && from === rhea) {
bullet.damage = 6; // Increase main character's weapon damage in chapter 2
} else {
bullet.damage = 3;
}
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot_player').play();
}
// Helper: fire enemy bullet
function fireEnemyBullet(from) {
var bullet = new EnemyBullet();
bullet.x = from.x - 70;
bullet.y = from.y;
enemyBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot_enemy').play();
}
// Helper: show explosion
function showExplosion(x, y) {
var exp = new Explosion();
exp.x = x;
exp.y = y;
explosions.push(exp);
game.addChild(exp);
LK.getSound('explosion').play();
}
// Helper: update UI
function updateUI() {
scoreTxt.setText(score);
hpTxt.setText('HP: ' + rhea.hp);
resourceTxt.setText('Res: ' + resources);
}
// Handle dragging Rhea (player)
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to game area
var minY = 120,
maxY = 2732 - 120;
dragNode.y = Math.max(minY, Math.min(maxY, y));
lastTouchX = x;
lastTouchY = y;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow dragging Rhea
if (!gameOver && !youWin) {
if (Math.abs(x - rhea.x) < 120 && Math.abs(y - rhea.y) < 120) {
dragNode = rhea;
handleMove(x, y, obj);
}
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
if (gameOver || youWin) return;
// Player auto-fire
if (
// Only allow auto-fire if not in chapter 2 pause, or if chapter 2 hasn't started yet, or if not in chapter 2
(!chapter2Started || typeof chapter2PauseTicks !== "undefined" && chapter2PauseTicks === 0
// Block auto-fire during boss warning
) && !bossWarningActive) {
if (rhea.shootCooldown > 0) rhea.shootCooldown--;
if (rhea.shootCooldown === 0) {
firePlayerBullet(rhea);
rhea.shootCooldown = 10;
}
// Sniper auto-fire (slower)
if (sniper.shootCooldown > 0) sniper.shootCooldown--;
if (sniper.shootCooldown === 0) {
firePlayerBullet(sniper);
sniper.shootCooldown = 30;
}
}
// Medic follows Rhea
medic.x += (rhea.x - 120 - medic.x) * 0.15;
medic.y += (rhea.y + 120 - medic.y) * 0.15;
// Sniper follows Rhea
sniper.x += (rhea.x - 120 - sniper.x) * 0.15;
sniper.y += (rhea.y - 120 - sniper.y) * 0.15;
// Spawn enemies
if (typeof chapter2PauseTicks !== "undefined" && chapter2PauseTicks > 0) {
chapter2PauseTicks--;
} else if (!bossWarningActive) {
// Block all spawns during boss warning
// Only spawn if not in chapter2 pause or boss warning
if (LK.ticks % 120 === 0) {
spawnEnemy();
}
// Spawn powerups
if (chapter2Started) {
// In chapter 2, spawn powerups more often (every 90 ticks)
if (LK.ticks % 90 === 0) {
spawnPowerup();
}
} else {
if (LK.ticks % 180 === 0) {
spawnPowerup();
}
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Remove if off screen
if (b.x > 2048 + 60) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Hit enemy
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
var dmg = typeof b.damage === "number" ? b.damage : 3;
e.hp -= dmg;
showExplosion(b.x, b.y);
b.destroy();
playerBullets.splice(i, 1);
if (e.hp <= 0) {
showExplosion(e.x, e.y);
score += e instanceof Tank ? 10 : 2;
resources += e instanceof Tank ? 5 : 1;
e.destroy();
enemies.splice(j, 1);
}
updateUI();
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var b = enemyBullets[i];
b.update();
if (b.x < -60) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Hit squad
for (var j = 0; j < squad.length; j++) {
var s = squad[j];
if (b.intersects(s)) {
// If mh2 fired this bullet, do more damage (enemy bullet collision)
if (mh2 && b.parent === mh2) {
s.hp -= mh2.damage || 6;
} else {
s.hp--;
}
showExplosion(b.x, b.y);
b.destroy();
enemyBullets.splice(i, 1);
if (s.hp <= 0) {
showExplosion(s.x, s.y);
if (s === rhea) {
// Game over
gameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else {
s.destroy();
squad.splice(j, 1);
}
}
updateUI();
break;
}
}
}
// Laser bullets from J
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
if (b instanceof LaserBullet) {
b.update();
// Remove if off screen
if (b.x > 2048 + 60) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Hit squad (including Rhea)
for (var j = 0; j < squad.length; j++) {
var s = squad[j];
if (b.intersects(s)) {
s.hp -= 2; // Laser does 2 damage
showExplosion(b.x, b.y);
b.destroy();
playerBullets.splice(i, 1);
if (s.hp <= 0) {
showExplosion(s.x, s.y);
if (s === rhea) {
// Game over
gameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else {
s.destroy();
squad.splice(j, 1);
}
}
updateUI();
break;
}
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
// Special movement for J and S in chapter 2
if (e.role === 'j' && chapter2Started) {
// J moves left until near player, then stops
if (typeof e.lastX === "undefined") e.lastX = e.x;
if (e.x > rhea.x + 300) {
e.x -= 12;
}
// J fires laser continuously at player from the beginning of chapter 2
if (e.shootCooldown > 0) e.shootCooldown--;
if (e.shootCooldown === 0) {
// If mh2 is present, fire at mh2, otherwise fire at Rhea
var target = rhea;
if (typeof mh2 !== "undefined" && mh2 && mh2.parent) {
target = mh2;
}
var laser = new LaserBullet();
laser.x = e.x - 60;
laser.y = e.y;
// Calculate direction vector from J to target
var dx = target.x - e.x;
var dy = target.y - e.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) dist = 1;
laser.dirX = dx / dist;
laser.dirY = dy / dist;
laser.speed = 32;
// Override update to move toward target
laser.update = function () {
this.x += this.dirX * this.speed;
this.y += this.dirY * this.speed;
};
playerBullets.push(laser);
game.addChild(laser);
e.shootCooldown = 18; // J fires every 18 ticks (slower fire rate)
}
e.lastX = e.x;
} else if (e.role === 's' && chapter2Started) {
// S moves right until near player, then stops
if (typeof e.lastX === "undefined") e.lastX = e.x;
if (e.x < rhea.x - 300) {
e.x += 12;
}
e.lastX = e.x;
} else {
e.update();
}
// Remove if off screen
if (e.role !== 'j' && e.role !== 's' && (e.x < -200 || e.x > 2048 + 200)) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy fire (for non-J/S enemies)
if ((!e.role || e.role !== 'j' && e.role !== 's') && e.shootCooldown !== undefined) {
if (e.shootCooldown > 0) e.shootCooldown--;
if (e.shootCooldown === 0) {
// Only fire if on screen
if (e.x < 2048 && e.x > 0) {
fireEnemyBullet(e);
e.shootCooldown = e instanceof Tank ? 30 : 60;
}
}
}
// Collide with player
if (e.intersects(rhea)) {
// If mh2, do more damage
if (mh2 && e === mh2) {
rhea.hp -= mh2.damage || 6;
} else {
rhea.hp -= 2;
}
showExplosion(e.x, e.y);
e.destroy();
enemies.splice(i, 1);
if (rhea.hp <= 0) {
gameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
updateUI();
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (p.x < -60) {
p.destroy();
powerups.splice(i, 1);
continue;
}
// Pickup by player
if (p.intersects(rhea)) {
if (p instanceof PowerupHealth) {
rhea.hp = Math.min(rhea.hp + 2, 7);
} else if (p instanceof PowerupAmmo) {
// For MVP, just increase resources
resources += 2;
}
LK.getSound('pickup').play();
p.destroy();
powerups.splice(i, 1);
updateUI();
}
}
// Chapter 2 trigger and Win condition
if (typeof chapter2Started === "undefined") {
chapter2Started = false;
}
// --- BOSS WARNING & MH2 SPAWN LOGIC FOR CHAPTER 2 ---
// Track boss warning and boss spawn state
if (typeof bossWarningShown === "undefined") bossWarningShown = false;
if (typeof bossSpawned === "undefined") bossSpawned = false;
if (typeof bossWarningOverlay === "undefined") bossWarningOverlay = null;
if (typeof bossWarningTimer === "undefined") bossWarningTimer = 0;
// Show boss warning at 40 points in chapter 2, only once
if (chapter2Started && score >= 40 && !bossWarningShown) {
// Show overlay message
bossWarningOverlay = new Container();
var bossWarnBg = LK.getAsset('centerCircle', {
width: 2048,
height: 2732,
color: 0x000000,
shape: 'box',
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1
});
bossWarningOverlay.addChild(bossWarnBg);
var bossWarnTxt = new Text2('THE BOSS IS COMING', {
size: 180,
fill: 0xFFD700,
font: "Impact, 'Arial Black', Tahoma"
});
bossWarnTxt.anchor.set(0.5, 0.5);
bossWarnTxt.x = 2048 / 2;
bossWarnTxt.y = 2732 / 2;
bossWarningOverlay.addChild(bossWarnTxt);
game.addChild(bossWarningOverlay);
bossWarningShown = true;
bossWarningTimer = 120; // Show for 2 seconds (120 ticks)
// Block all spawns and shooting until boss appears
bossWarningActive = true;
}
// Remove boss warning overlay after timer, and spawn mh2 if not already spawned
if (bossWarningShown && bossWarningOverlay && bossWarningTimer > 0) {
bossWarningTimer--;
if (bossWarningTimer === 0) {
if (bossWarningOverlay && bossWarningOverlay.parent) {
bossWarningOverlay.parent.removeChild(bossWarningOverlay);
bossWarningOverlay.destroy();
}
bossWarningOverlay = null;
// Unblock spawns and shooting
bossWarningActive = false;
// Spawn mh2 as boss if not already spawned
if (!bossSpawned) {
// Remove all J, S, and any other enemies except mh2 from enemies array
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] && (enemies[i].role === 'j' || enemies[i].role === 's' || enemies[i] !== mh2)) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
bossSpawned = true;
allowJSpawning = false;
// Spawn mh2 at boss position (center right)
mh2 = LK.getAsset('mh2', {
anchorX: 0.5,
anchorY: 0.5
});
mh2.x = 2048 - 200;
mh2.y = 2732 / 2;
mh2.hp = 30;
mh2.damage = 12; // Very high damage
mh2.lastX = mh2.x;
mh2.lastY = mh2.y;
mh2.shootCooldown = 30; // Boss fires every 30 ticks
mh2.dir = 1;
mh2.update = function () {
if (typeof this.lastY === "undefined") this.lastY = this.y;
this.y += this.dir * 8;
if (this.y > 2732 - 200) this.dir = -1;
if (this.y < 200) this.dir = 1;
this.lastY = this.y;
// Boss shooting logic
if (typeof this.shootCooldown === "undefined") this.shootCooldown = 30;
if (this.shootCooldown > 0) this.shootCooldown--;
if (this.shootCooldown === 0) {
// Fire a burst of 3 bullets in a spread
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = this.x - 70;
bullet.y = this.y + i * 40;
bullet.speed = -24;
bullet.update = function (angle) {
return function () {
this.x += this.speed;
this.y += angle * 8;
};
}(i);
enemyBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot_enemy').play();
this.shootCooldown = 30;
}
};
// Add boss to enemies for collision/damage logic
enemies.push(mh2);
game.addChild(mh2);
}
}
}
// --- END BOSS LOGIC ---
if (!chapter2Started && score >= 30) {
chapter2Started = true;
// Play S2 as background music in chapter 2
LK.playMusic('s2');
// Swap background to bf2 for chapter 2
if (!chapter2BgSwapped) {
var bf2Bg = LK.getAsset('bf2', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
alpha: 0.5
});
// Remove old background
if (battlefieldBg && battlefieldBg.parent) {
battlefieldBg.parent.removeChild(battlefieldBg);
}
game.addChildAt(bf2Bg, 0); // Add at bottom
chapter2BgSwapped = true;
}
// Change Rhea's asset to ch2 for chapter 2 (main character is now ch2)
if (rhea && rhea.children && rhea.children.length > 0) {
// Remove old asset
var oldGfx = rhea.children[0];
rhea.removeChild(oldGfx);
// Add new ch2 asset
var newGfx = rhea.attachAsset('ch2', {
anchorX: 0.5,
anchorY: 0.5
});
// Optionally update rhea's role/assetId for clarity
rhea.role = 'ch2';
rhea.assetId = 'ch2';
}
chapter2PauseTicks = 120; // 2 seconds at 60fps
// Remove medic and sniper from squad and game
if (medic && medic.parent) {
medic.parent.removeChild(medic);
medic.destroy();
}
if (sniper && sniper.parent) {
sniper.parent.removeChild(sniper);
sniper.destroy();
}
// Remove medic and sniper from squad array
for (var i = squad.length - 1; i >= 0; i--) {
if (squad[i] === medic || squad[i] === sniper) {
squad.splice(i, 1);
}
}
// Remove medic, sniper, and any ch2 from enemies array if present
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] === medic || enemies[i] === sniper || enemies[i].children && enemies[i].children.length > 0 && enemies[i].children[0].assetId === 'ch2') {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
// In chapter 2, set attackers to be J and S only (handled in spawnEnemy)
// Create a black overlay
var chapter2Overlay = new Container();
var blackBg = LK.getAsset('centerCircle', {
width: 2048,
height: 2732,
color: 0x000000,
shape: 'box',
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
alpha: 1
});
chapter2Overlay.addChild(blackBg);
// Show chapter 2 message
var chapter2Txt = new Text2('Chapter 2: Firestorm Rising', {
size: 120,
fill: 0x00BFFF,
font: "Impact, 'Arial Black', Tahoma"
});
chapter2Txt.anchor.set(0.5, 0.5);
chapter2Txt.x = 2048 / 2;
chapter2Txt.y = 2732 / 2;
chapter2Overlay.addChild(chapter2Txt);
game.addChild(chapter2Overlay);
// Fade out the overlay and message after 2 seconds
tween(chapter2Overlay, {
alpha: 0
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
chapter2Overlay.destroy();
}
});
// Remove all non-J/S/ch2 enemies from the field at the start of Chapter 2
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
// Remove any enemy that is not 'j' or 's' or is a ch2 (since player is ch2 now)
if (!(e.role === 'j' || e.role === 's') || e !== rhea && e.children && e.children.length > 0 && e.children[0].assetId === 'ch2') {
e.destroy();
enemies.splice(i, 1);
}
}
// Remove J and S spawn logic after boss warning, only allow mh2 to appear after warning
// (No J or S spawn, only mh2 will appear after boss warning)
if (bossSpawned) {
// Remove all squad members except Rhea (main character)
for (var i = squad.length - 1; i >= 0; i--) {
if (squad[i] !== rhea) {
if (squad[i].parent) squad[i].parent.removeChild(squad[i]);
squad[i].destroy();
squad.splice(i, 1);
}
}
// Remove all enemies except mh2
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i] !== mh2) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
// Block all spawns except mh2 (no-op, as mh2 is already spawned)
}
}
// Game over when mh2 (boss) is defeated in chapter 2
if (bossSpawned && mh2 && typeof mh2.hp === "number" && mh2.hp <= 0) {
gameOver = true;
LK.effects.flashScreen(0x000000, 1000);
var bossDefeatedTxt = new Text2('New Boss of the Game', {
size: 180,
fill: 0xFFD700,
font: "Impact, 'Arial Black', Tahoma"
});
bossDefeatedTxt.anchor.set(0.5, 0.5);
bossDefeatedTxt.x = 2048 / 2;
bossDefeatedTxt.y = 2732 / 2;
game.addChild(bossDefeatedTxt);
// End game after a short delay to show the message
LK.setTimeout(function () {
LK.showGameOver();
}, 1600);
return;
}
// Win condition: score threshold
if (score >= 50) {
youWin = true;
LK.effects.flashScreen(0x00ff00, 1000);
// Show 'You are a Real Player' as a gesture
var playerTxt = new Text2('You are a Real Player', {
size: 140,
fill: 0xFFD700,
font: "Impact, 'Arial Black', Tahoma"
});
playerTxt.anchor.set(0.5, 0.5);
playerTxt.x = 2048 / 2;
playerTxt.y = 2732 / 2;
game.addChild(playerTxt);
LK.showYouWin();
return;
}
};
// Initial UI update
updateUI();
soldier character. In-Game asset. 2d. High contrast. No shadows
Enemy robot. In-Game asset. 2d. High contrast. No shadows
Let the tank face left. In-Game asset. 2d. High contrast. No shadows
Sniper soldier. In-Game asset. 2d. High contrast. No shadows
Medic Soldier. In-Game asset. 2d. High contrast. No shadows
Health. In-Game asset. 2d. High contrast. No shadows
Ammo. In-Game asset. 2d. High contrast. No shadows
bullet enemy. In-Game asset. 2d. High contrast. No shadows
smile bullet to the right. In-Game asset. 2d. High contrast. No shadows
explosion effect. In-Game asset. 2d. High contrast. No shadows
dron enemy. In-Game asset. 2d. High contrast. No shadows
technological soldier. In-Game asset. 2d. High contrast. No shadows
just laser. In-Game asset. 2d. High contrast. No shadows
technological enemy. In-Game asset. 2d. High contrast. No shadows