User prompt
Raider bullets are traveling the wrong way.
User prompt
Increase raider bullet speed to 75% of hero
User prompt
Have the raiders left and right side alternate firing.
User prompt
Let's update the Raider values to move further onto the road and add scaling for tilt effect: self.entryPhase = true; self.speed = 3; self.rotationSpeed = 0.05; self.horizontalSpeed = 6; // Add scaling properties self.maxTilt = 0.3; // How much to scale for tilt effect self.baseScale = 1; // Normal scale // Modify the update function to include scaling and move further in self.update = function () { if (self.entryPhase) { if (self.spawnSide === 'left') { self.x += self.horizontalSpeed; raiderGraphics.rotation = Math.min(raiderGraphics.rotation + self.rotationSpeed, 0); // Scale for tilt effect raiderGraphics.scale.x = self.baseScale - self.maxTilt; if (self.x >= 600) { // Move further onto road self.entryPhase = false; raiderGraphics.scale.x = self.baseScale; } } else { self.x -= self.horizontalSpeed; raiderGraphics.rotation = Math.max(raiderGraphics.rotation - self.rotationSpeed, 0); // Scale for tilt effect raiderGraphics.scale.x = self.baseScale - self.maxTilt; if (self.x <= 1448) { // 2048 - 600 self.entryPhase = false; raiderGraphics.scale.x = self.baseScale; } } } else { self.y += self.speed; } // Keep the rest of your update code };
User prompt
Let's update the Raider class to handle the entry movement. Add these properties and modify the update function: self.entryPhase = true; // Track if we're still in entry animation self.speed = 3; self.rotationSpeed = 0.05; self.horizontalSpeed = 6; // Faster horizontal movement during entry // Modify the update function self.update = function () { if (self.entryPhase) { // Entry movement if (self.spawnSide === 'left') { self.x += self.horizontalSpeed; raiderGraphics.rotation = Math.min(raiderGraphics.rotation + self.rotationSpeed, 0); if (self.x >= 200) { // Stop entry when reached reasonable play area self.entryPhase = false; } } else { self.x -= self.horizontalSpeed; raiderGraphics.rotation = Math.max(raiderGraphics.rotation - self.rotationSpeed, 0); if (self.x <= 1848) { // 2048 - 200 self.entryPhase = false; } } } else { // Normal downward movement after entry self.y += self.speed; } // Keep the rest of your update code (shooting, destruction, etc.) };
User prompt
In the raider case in DifficultyManager, add the spawn side info: case 'raider': enemy = new Raider(); var spawnSide = Math.random() < 0.5; enemy.x = spawnSide ? -100 : 2148; enemy.y = Math.random() * (2732 * 0.3); enemy.spawnSide = spawnSide ? 'left' : 'right'; // Tell Raider which side it spawned from break;
User prompt
Update just the spawn position code in the raider case: case 'raider': enemy = new Raider(); enemy.x = Math.random() < 0.5 ? -100 : 2148; // Either left or right of screen enemy.y = Math.random() * (2732 * 0.3); // Random height in top 30% break;
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'obj2.x')' in or related to this line: 'var dx = obj1.x - obj2.x;' Line Number: 1162
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'obj.width')' in or related to this line: 'var width = obj.width;' Line Number: 1148
User prompt
// Add to game.init - test spawn var testRaider = new Raider(); testRaider.x = -200; // Far left testRaider.y = 100; game.addChild(testRaider);
User prompt
In the difficulty manager // After the switch, change this code: enemy.HitPoints *= self.getEnemyStrength(); // Only set default spawn position for non-raiders if (enemyType !== 'raider') { enemy.x = self.getSpawnX(); enemy.y = -enemy.height; } enemies.push(enemy); game.addChild(enemy); self.activeEnemies++;
Code edit (2 edits merged)
Please save this source code
User prompt
Update the raider case in spawnEnemy: case 'raider': enemy = new Raider(); var spawnSide = Math.random() < 0.5 ? 'left' : 'right'; if (spawnSide === 'left') { enemy.x = -200; // Use explicit pixel value } else { enemy.x = 2248; // 2048 + 200 } enemy.y = Math.random() * (2732 * 0.3); // Random height in top 30% enemy.spawnSide = spawnSide; break;
User prompt
Update the raider case in spawnEnemy: case 'raider': enemy = new Raider(); var spawnSide = Math.random() < 0.5 ? 'left' : 'right'; enemy.y = -enemy.height; // Still spawn at top for now if (spawnSide === 'left') { enemy.x = -enemy.width; } else { enemy.x = 2048 + enemy.width; } enemy.spawnSide = spawnSide; // Pass this to Raider for movement break;
User prompt
Update the raider case in DifficultyManager's spawnEnemy: case 'raider': enemy = new Raider(); enemy.x = self.getSpawnX(); enemy.y = -enemy.height; break;
User prompt
Let's also add this to updateSpawnQuota method to make sure it's copying the raider values: ``` self.updateSpawnQuota = function() { var pattern = self.wavePatterns[self.currentDifficulty] || self.wavePatterns[5]; self.spawnQuota.drones = pattern.drones; self.spawnQuota.bruisers = pattern.bruisers; self.spawnQuota.blasters = pattern.blasters; self.spawnQuota.raiders = pattern.raiders; }; ``` Let me know if they start spawning after these changes.
User prompt
Update getNextEnemyType in DifficultyManager: self.getNextEnemyType = function() { // Check drones first if (self.spawnQuota.drones > 0) { self.spawnQuota.drones--; return 'drone'; } // Then bruisers if (self.spawnQuota.bruisers > 0) { self.spawnQuota.bruisers--; return 'bruiser'; } // Then raiders if (self.spawnQuota.raiders > 0) { self.spawnQuota.raiders--; return 'raider'; } // Finally blasters if (self.spawnQuota.blasters > 0) { self.spawnQuota.blasters--; return 'blaster'; } return null; };
Code edit (2 edits merged)
Please save this source code
User prompt
Now let's clean up the drone case in spawnEnemy. Replace the current drone case with this simpler version: case 'drone': var redDroneChance = Math.min(self.currentDifficulty * 0.1, 0.3); if (Math.random() < redDroneChance) { enemy = new RedDrone(); } else { enemy = new Drone(); } break;
User prompt
Now let's update spawnEnemy in DifficultyManager to handle the raiders case. Add this to the switch statement after the other enemy cases: case 'raider': enemy = new Raider(); // Spawn from sides in top 30% of screen var spawnSide = Math.random() < 0.5 ? 'left' : 'right'; enemy.y = -enemy.height + Math.random() * (2732 * 0.3); if (spawnSide === 'left') { enemy.x = -enemy.width; } else { enemy.x = 2048 + enemy.width; } break;
User prompt
Let's start with updating the wave patterns in DifficultyManager. Add 'raiders' to the patterns: self.wavePatterns = { 1: { drones: 5, bruisers: 0, blasters: 0, raiders: 0 }, 2: { drones: 8, bruisers: 0, blasters: 0, raiders: 0 }, 3: { drones: 8, bruisers: 1, blasters: 0, raiders: 1 }, 4: { drones: 10, bruisers: 1, blasters: 1, raiders: 2 }, 5: { drones: 12, bruisers: 2, blasters: 1, raiders: 2 } };
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: RaiderBullet' in or related to this line: 'var leftShot = new RaiderBullet();' Line Number: 780
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: Drone2' in or related to this line: 'enemy = new Drone2();' Line Number: 375
User prompt
First, let's rename and modify the drone2 class to match our original vision: var Raider = Container.expand(function () { var self = Container.call(this); var raiderGraphics = self.attachAsset('BotBiker', { anchorX: 0.5, anchorY: 0.5 }); // Raider specific properties self.HitPoints = 5; self.speed = 3; self.shootInterval = 60; self.lastShotTime = 0; self.entryPhase = true; self.spawnSide = Math.random() < 0.5 ? 'left' : 'right'; // Set initial rotation based on spawn side raiderGraphics.rotation = self.spawnSide === 'left' ? -Math.PI/4 : Math.PI/4; self.update = function () { if (self.entryPhase) { // Entry animation if (self.spawnSide === 'left') { self.x += self.speed * 2; raiderGraphics.rotation = Math.min(raiderGraphics.rotation + 0.05, 0); } else { self.x -= self.speed * 2; raiderGraphics.rotation = Math.max(raiderGraphics.rotation - 0.05, 0); } // Check if entry is complete if ((self.spawnSide === 'left' && raiderGraphics.rotation >= 0) || (self.spawnSide === 'right' && raiderGraphics.rotation <= 0)) { self.entryPhase = false; } } else { // Normal movement after entry self.y += self.speed; // Shooting logic if (LK.ticks - self.lastShotTime > self.shootInterval) { self.shoot(); self.lastShotTime = LK.ticks; } } // Keep collision handling if (CollisionManager.checkCollision(self, hero)) { // [Keep existing collision code] } // Keep destruction logic if (self.HitPoints <= 0) { // [Keep existing destruction code] } else if (self.y > 2732) { // [Keep existing out-of-bounds code] } }; self.shoot = function () { var leftShot = new RaiderBullet(); leftShot.x = self.x - raiderGraphics.width / 4; leftShot.y = self.y + raiderGraphics.height / 2; game.addChild(leftShot); var rightShot = new RaiderBullet(); rightShot.x = self.x + raiderGraphics.width / 4; rightShot.y = self.y + raiderGraphics.height / 2; game.addChild(rightShot); }; });
/**** * Classes ****/ // Blaster class representing a shooting enemy var Blaster = Container.expand(function () { var self = Container.call(this); var blasterGraphics = self.attachAsset('Blaster', { anchorX: 0.5, anchorY: 0.5 }); self.HitPoints = 10; self.speed = 3; // Laser attack properties self.laserMechanic = new LaserMechanic(self, 60, 30, 30); // charge, fire, slide durations self.nextAttackTime = LK.ticks + randomRange(180, 300); // 3-5 seconds initial delay function randomRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } self.update = function () { // Update laser mechanic self.laserMechanic.update(); // Check if it's time for a laser attack if (LK.ticks >= self.nextAttackTime && !self.laserMechanic.isCharging && !self.laserMechanic.isFiring && !self.laserMechanic.isSliding && !self.laserMechanic.attackComplete) { self.laserMechanic.startCharge(); } // Handle movement based on state if (self.laserMechanic.isCharging) { // Only rotate to track player during charge var directionX = hero.x - self.x; var directionY = hero.y - self.y; blasterGraphics.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; } else if (self.laserMechanic.isFiring || self.laserMechanic.isSliding) { // No movement during firing and sliding return; } else { // Normal movement when not attacking // Track player position var directionX = hero.x - self.x; var directionY = hero.y - self.y; var distance = Math.sqrt(directionX * directionX + directionY * directionY); if (distance > 0) { self.x += directionX / distance * self.speed; self.y += directionY / distance * self.speed; blasterGraphics.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; } // Set next attack time after sliding is done if (self.laserMechanic.isAttackComplete()) { self.laserMechanic.resetAttack(); self.nextAttackTime = LK.ticks + randomRange(300, 480); } } // Destroy if out of screen if (CollisionManager.checkCollision(self, hero)) { // Handle collision with hero if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { hero.shieldGraphics.tint = 0xFFFFFF; if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; } } // Destroy the enemy generateEnemyPieces(self, BlasterPiece, ['BlasterBottomPiece', 'BlasterLeftPiece', 'BlasterRightPiece']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } if (self.HitPoints <= 0) { // Create blaster pieces upon destruction generateEnemyPieces(self, BlasterPiece, ['BlasterBottomPiece', 'BlasterLeftPiece', 'BlasterRightPiece']); // Check if there's an active laser beam if (self.laserMechanic.laserBeam) { // Detach and slide the laser beam self.laserMechanic.detachBeam(); } self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); difficultyManager.onEnemyDestroyed(); } } }; }); // BlasterPiece class for blaster destruction effect var BlasterPiece = Container.expand(function (assetType) { var self = Container.call(this); var pieceGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5, alpha: 1 // Ensure pieces are fully visible on spawn }); self.speedX = (Math.random() - 0.5) * 12; // Random horizontal speed to move outwards self.speedY = (Math.random() - 0.5) * 12; // Random vertical speed to move outwards self.alphaDecay = 0.02; // Rate at which the piece fades out self.update = function () { self.x += self.speedX; self.y += self.speedY; pieceGraphics.rotation += Math.random() * 0.1 - 0.05; // Add slight random rotation pieceGraphics.alpha -= self.alphaDecay; if (pieceGraphics.alpha <= 0) { self.destroy(); } }; }); var BombBlast = Container.expand(function () { var self = Container.call(this); var blastGraphics = self.attachAsset('BombBlast', { anchorX: 0.5, anchorY: 0.5 }); self.scaleX = 0.1; self.scaleY = 0.1; self.update = function () { self.scaleX += 0.5; self.scaleY += 0.5; blastGraphics.scale.x = self.scaleX; blastGraphics.scale.y = self.scaleY; if (self.scaleX >= 10) { self.destroy(); } }; }); // Bruiser class representing a tougher enemy var Bruiser = Container.expand(function () { var self = Container.call(this); var bruiserGraphics = self.attachAsset('Bruiser', { anchorX: 0.5, anchorY: 0.5 }); self.HitPoints = 20; // Double the hit points for Bruiser self.speed = 5; self.update = function () { // Implement mechanical stomping movement if (LK.ticks % 80 < 20) { bruiserGraphics.scale.x = 1.1; bruiserGraphics.scale.y = 0.9; bruiserGraphics.rotation = 0.1; // Tilt right } else if (LK.ticks % 80 < 40) { bruiserGraphics.scale.x = 1.0; bruiserGraphics.scale.y = 1.0; bruiserGraphics.rotation = 0; } else if (LK.ticks % 80 < 60) { bruiserGraphics.scale.x = 1.1; bruiserGraphics.scale.y = 0.9; bruiserGraphics.rotation = -0.1; // Tilt left } else { bruiserGraphics.scale.x = 1.0; bruiserGraphics.scale.y = 1.0; bruiserGraphics.rotation = 0; } // Move downwards only during tilt phases if (LK.ticks % 80 < 20 || LK.ticks % 80 >= 40 && LK.ticks % 80 < 60) { // Check for nearby enemies and adjust path to avoid collisions var nearbyEnemy = enemies.find(function (enemy) { return enemy !== self && Math.abs(enemy.x - self.x) < 100 && Math.abs(enemy.y - self.y) < 100; }); if (nearbyEnemy) { self.x += (self.x < nearbyEnemy.x ? -1 : 1) * self.speed; // Move away from the nearby enemy } else { self.y += self.speed; } } if (CollisionManager.checkCollision(self, hero)) { // Handle collision with hero if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { hero.shieldGraphics.tint = 0xFFFFFF; if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; } } // Destroy the enemy generateEnemyPieces(self, BruiserPiece, ['BruiserCenterPart', 'BruiserLeftPart', 'BruiserRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } if (self.HitPoints <= 0) { // Create bruiser pieces upon destruction generateEnemyPieces(self, BruiserPiece, ['BruiserCenterPart', 'BruiserLeftPart', 'BruiserRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); difficultyManager.onEnemyDestroyed(); } } }; }); // BruiserPiece class for bruiser destruction effect var BruiserPiece = Container.expand(function (assetType) { var self = Container.call(this); var pieceGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.speedX = -Math.random() * 6 + 3; // Switch direction of horizontal speed self.speedY = Math.random() * 4 - 2; // Random vertical speed self.alphaDecay = 0.02; // Rate at which the piece fades out self.update = function () { self.x += self.speedX; self.y += self.speedY; pieceGraphics.rotation += Math.random() * 0.1 - 0.05; // Add slight random rotation pieceGraphics.alpha -= self.alphaDecay; if (pieceGraphics.alpha <= 0) { self.destroy(); } }; }); var DifficultyManager = Container.expand(function () { var self = Container.call(this); self.currentDifficulty = 1; self.activeEnemies = 0; self.maxEnemies = 12; self.roadStartX = 2048 * 0.21; self.roadWidth = 2048 * 0.55; // Wave patterns for different difficulty levels self.wavePatterns = { 1: { drones: 5, bruisers: 0, blasters: 0, raiders: 2 }, 2: { drones: 8, bruisers: 0, blasters: 0, raiders: 2 }, 3: { drones: 8, bruisers: 1, blasters: 0, raiders: 1 }, 4: { drones: 10, bruisers: 1, blasters: 1, raiders: 2 }, 5: { drones: 12, bruisers: 2, blasters: 1, raiders: 2 } }; // Spawn quota to track needed spawns self.spawnQuota = { drones: 0, bruisers: 0, blasters: 0, raiders: 0 }; self.update = function () { if (LK.ticks % 60 === 0 && self.canSpawnEnemy()) { var enemyType = self.getNextEnemyType(); if (enemyType) { self.spawnEnemy(enemyType); } } }; self.updateDifficulty = function (powerLevel) { self.currentDifficulty = Math.floor(powerLevel * 1.5); }; self.getSpawnX = function () { return self.roadStartX + Math.random() * self.roadWidth; }; self.getEnemyStrength = function () { // Every 2 levels of difficulty increases enemy HP var healthBonus = Math.floor(self.currentDifficulty / 2); return Math.max(1, healthBonus); }; self.updateSpawnQuota = function () { var pattern = self.wavePatterns[self.currentDifficulty] || self.wavePatterns[5]; self.spawnQuota.drones = pattern.drones; self.spawnQuota.bruisers = pattern.bruisers; self.spawnQuota.blasters = pattern.blasters; self.spawnQuota.raiders = pattern.raiders; }; self.canSpawnEnemy = function () { return self.activeEnemies < self.maxEnemies; }; self.spawnEnemy = function (enemyType) { if (!self.canSpawnEnemy()) { return; } var enemy; switch (enemyType) { case 'drone': var redDroneChance = Math.min(self.currentDifficulty * 0.1, 0.3); if (Math.random() < redDroneChance) { enemy = new RedDrone(); } else { enemy = new Drone(); } break; case 'bruiser': enemy = new Bruiser(); break; case 'blaster': enemy = new Blaster(); break; case 'raider': enemy = new Raider(); var spawnSide = Math.random() < 0.5 ? 'left' : 'right'; if (spawnSide === 'left') { enemy.x = -200; // Use explicit pixel value } else { enemy.x = 2248; // 2048 + 200 } enemy.y = Math.random() * (2732 * 0.3); // Random height in top 30% enemy.spawnSide = spawnSide; break; default: return; } // Increase enemy HP based on difficulty enemy.HitPoints *= self.getEnemyStrength(); enemy.x = self.getSpawnX(); enemy.y = -enemy.height; enemies.push(enemy); game.addChild(enemy); self.activeEnemies++; }; self.getNextEnemyType = function () { // Check drones first if (self.spawnQuota.drones > 0) { self.spawnQuota.drones--; return 'drone'; } // Then bruisers if (self.spawnQuota.bruisers > 0) { self.spawnQuota.bruisers--; return 'bruiser'; } // Then raiders if (self.spawnQuota.raiders > 0) { self.spawnQuota.raiders--; return 'raider'; } // Finally blasters if (self.spawnQuota.blasters > 0) { self.spawnQuota.blasters--; return 'blaster'; } return null; }; self.onEnemyDestroyed = function () { self.activeEnemies--; if (self.spawnQuota.drones === 0 && self.spawnQuota.bruisers === 0 && self.spawnQuota.blasters === 0) { self.updateSpawnQuota(); } }; }); // Enemy class representing the enemy robots var Drone = Container.expand(function () { var self = Container.call(this); var droneGraphics = self.attachAsset('Drone', { anchorX: 0.5, anchorY: 0.5 }); self.HitPoints = 3; self.randomOffset = Math.random() * 100; // Random timing for each drone self.speed = 2.75; self.update = function () { // Add robotic hover effects // Check for nearby enemies and adjust path to avoid collisions var nearbyEnemy = enemies.find(function (enemy) { return enemy !== self && Math.abs(enemy.x - self.x) < 100 && Math.abs(enemy.y - self.y) < 100; }); if (nearbyEnemy) { self.x += (self.x < nearbyEnemy.x ? -1 : 1) * self.speed; // Move away from the nearby enemy } else { self.y += self.speed * (Math.random() > 0.1 ? 1 : 0); // Brief pauses in downward movement } self.x += Math.sin(LK.ticks / 10 + self.randomOffset) * 2; // Small jerky side-to-side movements if (Math.random() > 0.95) { self.x += Math.random() * 4 - 2; // Quick position corrections } // Pulse effect on hit if (self.pulseEffect) { droneGraphics.scale.x = 1.2; droneGraphics.scale.y = 1.2; self.pulseEffect = false; } else { droneGraphics.scale.x = 1.0; droneGraphics.scale.y = 1.0; } if (CollisionManager.checkCollision(self, hero)) { // Handle collision with hero if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { hero.shieldGraphics.tint = 0xFFFFFF; if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; } } // Destroy the enemy generateEnemyPieces(self, DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } if (self.HitPoints <= 0) { // Create drone pieces upon destruction generateEnemyPieces(self, DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); difficultyManager.onEnemyDestroyed(); } } }; }); // DronePiece class for drone destruction effect var DronePiece = Container.expand(function (assetType) { var self = Container.call(this); var pieceGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.speedX = Math.random() * 6 - 3; // Increased random horizontal speed self.speedY = Math.random() * 4 - 2; // Random vertical speed self.alphaDecay = 0.02; // Rate at which the piece fades out self.update = function () { self.x += self.speedX; self.y += self.speedY; pieceGraphics.rotation += Math.random() * 0.1 - 0.05; // Add slight random rotation pieceGraphics.alpha -= self.alphaDecay; if (pieceGraphics.alpha <= 0) { self.destroy(); } }; }); // Dust class for dust particles var Dust = Container.expand(function () { var self = Container.call(this); var dustGraphics = self.attachAsset('Dust', { anchorX: 0.5, anchorY: 0.5 }); dustGraphics.alpha = 0.75; self.speed = Math.random() * 3 + 1; self.rotationSpeed = Math.random() * 0.02 - 0.01; // Random rotation speed between -0.01 and 0.01 self.direction = Math.random() * Math.PI * 0.5; self.update = function () { self.y += self.speed; self.x += Math.sin(self.direction) * self.speed; // Add slight X travel based on direction self.rotation += self.rotationSpeed; // Add rotation dustGraphics.alpha -= 0.01; // fade out at a medium pace if (self.y > 2732 || dustGraphics.alpha <= 0) { self.destroy(); } }; }); // Assets will be automatically created and loaded by the LK engine based on their usage in the code. // Hero class representing the player's spaceship var Hero = Container.expand(function () { var self = Container.call(this); self.prevX = self.x; // Initialize prevX with the current x position var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.soldierCloneCount = 0; // Initialize soldier clone count self.shielded = false; // Initialize shielded state self.shieldLevel = 0; // Initialize shield level self.shieldGraphics = null; // Placeholder for shield asset self.update = function () { if (self.shielded && self.shieldGraphics) { self.shieldGraphics.rotation += 0.01; // Rotate shield slowly // Adjust shield size to cover hero asset var scaleFactor = Math.max(heroGraphics.width / self.shieldGraphics.width, heroGraphics.height / self.shieldGraphics.height); self.shieldGraphics.scale.x = scaleFactor; self.shieldGraphics.scale.y = scaleFactor; // Update shield tint based on shield level self.shieldGraphics.tint = 0xFFFFFF; // Reset tint to default if (self.shieldLevel === 2) { self.shieldGraphics.tint = 0xFFFF00; // Yellow tint } else if (self.shieldLevel === 3) { self.shieldGraphics.tint = 0xFF0000; // Red tint } } if (self.y > 2375) { self.y -= self.speed; } // Add rotation based on movement direction if (self.x > self.prevX) { self.rotation += Math.PI / 180 * 1; // Rotate 1 degree to the right if (self.rotation > Math.PI / 180 * 5) { self.rotation = Math.PI / 180 * 5; } } else if (self.x < self.prevX) { self.rotation -= Math.PI / 180 * 1; // Rotate 1 degree to the left if (self.rotation < Math.PI / 180 * -5) { self.rotation = Math.PI / 180 * -5; } } else { if (self.rotation > 0) { self.rotation -= Math.PI / 180 * 1; if (self.rotation < 0) { self.rotation = 0; } } else if (self.rotation < 0) { self.rotation += Math.PI / 180 * 1; if (self.rotation > 0) { self.rotation = 0; } } } self.prevX = self.x; // Store the current x position for the next frame // Removed pulsing scale effect for hero self.scale.x = 1.0; }; // Method to handle shooting self.shootBehavior = powerUpManager.defaultBehavior; // Set initial behavior // Method to handle shooting self.shoot = function () { self.shootBehavior.call(self); }; }); // Bullet class for hero's bullets var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet1', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.Type = 'standard'; // Default type for bullets self.Power = powerUpManager.currentPowerLevel || 1; // Initialize power level from PowerUpManager self.update = function () { // Move in direction of rotation self.y += Math.cos(self.rotation) * self.speed; self.x += Math.sin(self.rotation) * self.speed; // Adjust out-of-bounds check for angled movement if (self.y < 0 || self.x < 0 || self.x > 2048) { self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } } }; self.updateVisual = function () { if (bulletGraphics) { self.removeChild(bulletGraphics); } var assetId = 'heroBullet' + self.Power; console.log("Loading bullet asset: " + assetId); bulletGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; }); // PowerUp class for handling power-up movement and collection var PowerUp = Container.expand(function (assetType) { var self = Container.call(this); var powerUpGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; // Speed at which the power-up moves down the screen self.update = function () { self.y += self.speed; // Check if the power-up is collected by the hero if (self.intersects(hero)) { switch (assetType) { case 'SoldierCloneIcon': difficultyManager.updateDifficulty(hero.soldierCloneCount + 1); difficultyManager.updateSpawnQuota(); if (soldierClones.length < 6) { // Array to track which positions are taken var takenPositions = soldierClones.map(function (clone) { return clone.offset; }); // Find first available position var positions = [-160, 160, -320, 320, -480, 480]; var newOffset = null; for (var i = 0; i < positions.length; i++) { if (!takenPositions.includes(positions[i])) { newOffset = positions[i]; break; } } if (newOffset !== null) { hero.soldierCloneCount++; var newClone = new SoldierClone(); newClone.offset = newOffset; newClone.x = hero.x + newOffset; newClone.y = hero.y; newClone.zIndex = hero.zIndex - 1; soldierClones.push(newClone); backgroundContainer.addChild(newClone); } } break; case 'WeaponPowerIcon': powerUpManager.currentPowerLevel = Math.min(powerUpManager.currentPowerLevel + 1, 4); console.log("Power up collected. New level: " + powerUpManager.currentPowerLevel); difficultyManager.updateDifficulty(powerUpManager.currentPowerLevel); difficultyManager.updateSpawnQuota(); break; case 'ShieldIcon': if (!hero.shielded) { hero.shielded = true; hero.shieldGraphics = hero.attachAsset('heroShield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 // Set opacity to 50% }); } hero.shieldLevel = Math.min(hero.shieldLevel + 1, 3); // Increase shield level to a max of 3 // Change shield tint based on shield level hero.shieldGraphics.tint = 0xFFFFFF; // Reset tint to default if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; // Yellow tint } else if (hero.shieldLevel === 3) { hero.shieldGraphics.tint = 0xFF0000; // Red tint } break; case 'BombIcon': powerUpManager.switchPowerUp(PowerUpTypes.BOMB); powerUpManager.bombBehavior(); break; } hero.shootBehavior = powerUpManager.getCurrentPowerBehavior(); soldierClones.forEach(function (clone) { clone.shootBehavior = hero.shootBehavior; }); self.destroy(); } // Destroy if out of screen if (self.y > 2732) { self.destroy(); } }; }); var Raider = Container.expand(function () { var self = Container.call(this); var raiderGraphics = self.attachAsset('BotBiker', { anchorX: 0.5, anchorY: 0.5 }); // Raider specific properties self.HitPoints = 5; self.speed = 3; self.shootInterval = 60; self.lastShotTime = 0; self.entryPhase = true; self.spawnSide = Math.random() < 0.5 ? 'left' : 'right'; // Set initial rotation based on spawn side raiderGraphics.rotation = self.spawnSide === 'left' ? -Math.PI / 4 : Math.PI / 4; self.update = function () { if (self.entryPhase) { // Entry animation if (self.spawnSide === 'left') { self.x += self.speed * 2; raiderGraphics.rotation = Math.min(raiderGraphics.rotation + 0.05, 0); } else { self.x -= self.speed * 2; raiderGraphics.rotation = Math.max(raiderGraphics.rotation - 0.05, 0); } // Check if entry is complete if (self.spawnSide === 'left' && raiderGraphics.rotation >= 0 || self.spawnSide === 'right' && raiderGraphics.rotation <= 0) { self.entryPhase = false; } } else { // Normal movement after entry self.y += self.speed; // Shooting logic if (LK.ticks - self.lastShotTime > self.shootInterval) { self.shoot(); self.lastShotTime = LK.ticks; } } // Keep collision handling if (CollisionManager.checkCollision(self, hero)) { // [Keep existing collision code] } // Keep destruction logic if (self.HitPoints <= 0) { // [Keep existing destruction code] } else if (self.y > 2732) { // [Keep existing out-of-bounds code] } }; self.shoot = function () { var leftShot = new RaiderBullet(); leftShot.x = self.x - raiderGraphics.width / 4; leftShot.y = self.y + raiderGraphics.height / 2; game.addChild(leftShot); var rightShot = new RaiderBullet(); rightShot.x = self.x + raiderGraphics.width / 4; rightShot.y = self.y + raiderGraphics.height / 2; game.addChild(rightShot); }; }); var RaiderBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet1', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); } }; }); // RailingLeft class for the scrolling left railing var RailingLeft = Container.expand(function (assetType) { var self = Container.call(this); var railingGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0 }); self.speed = 2; self.update = function () { self.y += self.speed; if (self.y >= 2732) { self.y = -2732; } }; }); // RailingRight class for the scrolling right railing var RailingRight = Container.expand(function (assetType) { var self = Container.call(this); var railingGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0 }); self.speed = 2; self.update = function () { self.y += self.speed; if (self.y >= 2732) { self.y = -2732; } }; }); var RedDrone = Container.expand(function () { var self = Container.call(this); var droneGraphics = self.attachAsset('Drone', { anchorX: 0.5, anchorY: 0.5 }); // Apply red tint to graphics droneGraphics.tint = 0xFF0000; // Set aggressive properties self.HitPoints = 3; self.randomOffset = Math.random() * 100; self.speed = 4; // Faster than regular drone self.update = function () { if (hero) { // Chase the hero if (self.x < hero.x) { self.x += self.speed; } else if (self.x > hero.x) { self.x -= self.speed; } self.y += self.speed; } // Keep pulse effect from base drone if (self.pulseEffect) { droneGraphics.scale.x = 1.2; droneGraphics.scale.y = 1.2; self.pulseEffect = false; } else { droneGraphics.scale.x = 1.0; droneGraphics.scale.y = 1.0; } // Copy collision checks from base Drone if (CollisionManager.checkCollision(self, hero)) { if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { hero.shieldGraphics.tint = 0xFFFFFF; if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; } } generateEnemyPieces(self, DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } if (self.HitPoints <= 0) { generateEnemyPieces(self, DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); difficultyManager.onEnemyDestroyed(); } } else if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); difficultyManager.onEnemyDestroyed(); } } }; }); // RoadScroll class for the scrolling road var RoadScroll = Container.expand(function (assetType) { var self = Container.call(this); var roadGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0 }); if (assetType === 'CityBackgroundHD') { self.speed = 1; } else { self.speed = 2; } self.update = function () { self.y += self.speed; if (self.y >= 2732) { self.y = -2732; } }; }); // SoldierClone class representing a clone of the player's character var SoldierClone = Container.expand(function () { var self = Container.call(this); self.side = null; // 'left' or 'right' var cloneGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7, scaleX: 0.75, scaleY: 0.75 }); self.health = 1; self.isImmune = false; self.offset = 0; // Store initial offset from hero self.update = function () { self.y = hero.y; // Maintain x offset from hero self.x = hero.x + self.offset; // Only check collisions once per frame if (!self.isImmune && LK.ticks > self.lastCollisionFrame) { for (var i = 0; i < enemies.length; i++) { if (CollisionManager.checkCollision(self, enemies[i])) { self.lastCollisionFrame = LK.ticks; self.destroy(); return; } } } // Auto-fire like the player self.shoot(); }; self.destroy = function () { // Remove bullets associated with this clone for (var i = heroBullets.length - 1; i >= 0; i--) { if (heroBullets[i].x === self.x && heroBullets[i].y === self.y - self.height / 2) { heroBullets[i].destroy(); heroBullets.splice(i, 1); } } if (self.side === 'right') { // Only make clones on the same side immune soldierClones.forEach(function (clone) { if (clone.side === 'right') { clone.isImmune = true; LK.setTimeout(function () { clone.isImmune = false; }, 150); } }); } else { // Same for left side soldierClones.forEach(function (clone) { if (clone.side === 'left') { clone.isImmune = true; LK.setTimeout(function () { clone.isImmune = false; }, 150); } }); } // Update soldier clone count and array var index = soldierClones.indexOf(self); if (index > -1) { soldierClones.splice(index, 1); hero.soldierCloneCount--; } // Call original destroy method Container.prototype.destroy.call(self); }; // Method to handle shooting self.shoot = function () { if (LK.ticks % 18 == 0) { // Match hero's fire rate var newBullet = new HeroBullet(); // Use the same bullet type as the hero newBullet.x = self.x; // Create bullets at the clone's current position newBullet.y = self.y - self.height / 2; newBullet.Power = heroBullets.length > 0 ? heroBullets[0].Power : 1; // Match hero's bullet power newBullet.updateVisual(); // Update bullet visuals based on power heroBullets.push(newBullet); // Add the new bullets to the game's bullet array game.addChild(newBullet); } }; }); // TitleScreen class for the title screen var TitleScreen = Container.expand(function () { var self = Container.call(this); // Attach game logo var logo = self.attachAsset('GameLogoHD', { anchorX: 0.5, anchorY: 0.5 }); logo.x = 2048 / 2; logo.y = 2732 / 2 - 200; // Attach play button var playButton = self.attachAsset('PlayButton', { anchorX: 0.5, anchorY: 0.5 }); playButton.x = 2048 / 2; playButton.y = logo.y + logo.height / 2 + playButton.height / 2 + 50; // Event handler for play button playButton.down = function (x, y, obj) { isTitle = false; isStarted = true; self.destroy(); startGame(); }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 //Init game with black background }); /**** * Game Code ****/ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) { return t; } var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) { return i; } throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function generateEnemyPieces(enemy, pieceClass, pieceTypes) { pieceTypes.forEach(function (pieceType, index) { var piece = new pieceClass(pieceType); piece.x = enemy.x + (index - 1) * 40; // Spread pieces horizontally piece.y = enemy.y; game.addChild(piece); }); } var CollisionManager = { // Remove the fixed collision data and simplify checkCollision: function checkCollision(obj1, obj2) { // Always use circle collision with calculated radii return this.circleCollision(obj1, obj2); }, getObjectRadius: function getObjectRadius(obj) { var width = obj.width; var height = obj.height; // Adjust multiplier to tune collision size return Math.min(width, height) * 0.4; // Keep logging to help with tuning console.log(obj.constructor.name + ' collision radius:', 'sprite size:', width, height, 'collision size:', Math.min(width, height) * 0.4); }, circleCollision: function circleCollision(obj1, obj2) { var radius1 = this.getObjectRadius(obj1); var radius2 = this.getObjectRadius(obj2); var dx = obj1.x - obj2.x; var dy = obj1.y - obj2.y; var distance = Math.sqrt(dx * dx + dy * dy); return distance < radius1 + radius2; } }; var PowerUpTypes = { DEFAULT: 'DEFAULT', SOLDIER_CLONE: 'SOLDIER_CLONE', SHIELD: 'SHIELD', WEAPON_POWER: 'WEAPON_POWER', BOMB: 'BOMB' // Add bomb type }; // PowerUpManager class to manage power-ups // Initialize the city background for parallax effect var PowerUpManager = function PowerUpManager() { this.currentPowerUp = PowerUpTypes.DEFAULT; this.currentPowerLevel = 1; // Initialize power level to default value this.switchPowerUp = function (newPowerUp) { if (PowerUpTypes[newPowerUp]) { this.currentPowerUp = newPowerUp; } }; this.getCurrentPowerBehavior = function () { switch (this.currentPowerUp) { case PowerUpTypes.SOLDIER_CLONE: return this.soldierCloneBehavior; case PowerUpTypes.BOMB: return this.bombBehavior; default: return this.defaultBehavior; } }; this.defaultBehavior = function () { var bullet = new HeroBullet(); bullet.x = hero.x; bullet.y = hero.y - hero.height / 2; bullet.Power = powerUpManager.currentPowerLevel || 1; // Use saved power level from PowerUpManager bullet.updateVisual(); // Update the visual after setting power heroBullets.push(bullet); game.addChild(bullet); console.log("Created bullet with power: " + bullet.Power); }; this.soldierCloneBehavior = function () { // Soldier clone behavior // Removed clone spawning logic }; this.bombBehavior = function () { var blast = new BombBlast(); blast.x = 1024; blast.y = 1366; blast.zIndex = 2000; // Ensure BombBlast is on a visible layer game.addChild(blast); // Kill enemies for (var i = 0; i < enemies.length; i++) { if (enemies[i] && enemies[i].y > 0) { enemies[i].HitPoints = 0; } } // Flash effect after blast is created LK.setTimeout(function () { var flash = new Container(); var flashGraphics = flash.attachAsset('whitePixel', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 30 }); flash.x = game.width / 2; flash.y = game.height / 2; flash.alpha = 0.8; game.addChild(flash); LK.setTimeout(function () { flash.destroy(); }, 100); }, 100); // Screen shake var originalX = game.x; var shakeAmount = 30; // Increase shake intensity var shakeDuration = 100; // Increase shake duration game.x += shakeAmount; LK.setTimeout(function () { game.x -= shakeAmount * 2; LK.setTimeout(function () { game.x += shakeAmount; LK.setTimeout(function () { game.x -= shakeAmount * 2; LK.setTimeout(function () { game.x += shakeAmount; LK.setTimeout(function () { game.x = originalX; }, shakeDuration); }, shakeDuration); }, shakeDuration); }, shakeDuration); }, shakeDuration); }; }; // PowerUpTypes enum/constants var PowerUpTypes = { DEFAULT: 'DEFAULT', LASER_BEAM: 'LASER_BEAM', ROCKETS: 'ROCKETS', DRONE: 'DRONE', SOLDIER_CLONE: 'SOLDIER_CLONE', SHIELD: 'SHIELD', // Add shield power-up type WEAPON_POWER: 'WEAPON_POWER' }; var LaserMechanic = function LaserMechanic(origin, chargeDuration, fireDuration, slideOffDuration) { this.origin = origin; this.chargeDuration = chargeDuration; this.fireDuration = fireDuration; this.slideOffDuration = slideOffDuration; // State tracking this.isCharging = false; this.isFiring = false; this.isSliding = false; // Timing this.chargeStartTime = null; this.fireStartTime = null; this.slideStartTime = null; // Flag to indicate attack completion this.attackComplete = false; // Assets this.chargeEffect = null; this.laserBeam = null; var index = activeLaserBeams.indexOf(this); if (index > -1) { activeLaserBeams.splice(index, 1); } // Method to start charging LaserMechanic.prototype.startCharge = function () { if (this.isCharging || this.isFiring || this.isSliding) { return; } this.isCharging = true; this.chargeStartTime = LK.ticks; // Create charge effect this.chargeEffect = LK.getAsset('LaserCharge', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5, scale: { x: 0.5, y: 0.5 } }); if (this.origin) { this.chargeEffect.y += this.origin.height * 0.1; // Move charge effect down by 10% of origin's height this.origin.addChild(this.chargeEffect); } }; // Target this.targetX = null; this.targetY = null; // Method to update charge progress LaserMechanic.prototype.updateCharge = function () { if (!this.isCharging) { return; } var chargeProgress = (LK.ticks - this.chargeStartTime) / this.chargeDuration; // Update charge effect this.chargeEffect.alpha = 0.5 + chargeProgress * 0.5; // Fade in this.chargeEffect.scale.x = 0.5 + chargeProgress * 1.5; // Grow outward this.chargeEffect.scale.y = 0.5 + chargeProgress * 1.5; // Capture target position at 2/3 through charge if (chargeProgress >= 0.67 && !this.targetX) { this.targetX = hero.x; this.targetY = hero.y; } // Check if charge is complete if (chargeProgress >= 1) { if (this.origin && this.chargeEffect) { this.origin.removeChild(this.chargeEffect); } this.chargeEffect = null; this.isCharging = false; this.startFiring(); // Add this line to transition to firing phase } }; }; var cityBackground1 = game.addChild(new RoadScroll('CityBackgroundHD')); var cityBackground2 = game.addChild(new RoadScroll('CityBackgroundHD')); cityBackground1.x = 2048 / 2; cityBackground2.x = 2048 / 2; cityBackground1.y = 0; cityBackground2.y = -2732; // Initialize the road instances var road1 = game.addChild(new RoadScroll('Road')); var road2 = game.addChild(new RoadScroll('Road2')); road2.x = 2048 / 2; road1.x = 2048 / 2; road1.y = 0; road2.y = -2732; // Initialize the left railing instances var railingLeft1 = game.addChild(new RailingLeft('RailingStart')); var railingLeft2 = game.addChild(new RailingLeft('RailingEnd')); railingLeft1.x = 2048 * 0.16; railingLeft2.x = 2048 * 0.16; railingLeft1.y = 0; railingLeft2.y = -2732; // Initialize the right railing instances var railingRight1 = game.addChild(new RailingRight('RailingEnd')); var railingRight2 = game.addChild(new RailingRight('RailingStart')); railingRight1.x = 2048 * 0.81; // Moved left by 3% railingRight2.x = 2048 * 0.81; // Moved left by 3% railingRight1.y = 0; railingRight2.y = -2732; // Initialize game state variables var isTitle = true; var isStarted = false; // Initialize title screen if (isTitle) { var titleScreen = game.addChild(new TitleScreen()); } // Initialize variables var backgroundContainer; var hero; var enemies = []; var heroBullets = []; var soldierClones = []; var powerUpManager = new PowerUpManager(); // Initialize powerUpManager powerUpManager.currentPowerLevel = 1; // Track current power level at start // Function to start the game function startGame() { // Initialize background container backgroundContainer = new Container(); game.addChild(backgroundContainer); difficultyManager = new DifficultyManager(); difficultyManager.updateSpawnQuota(); // Initialize hero hero = game.addChild(new Hero()); hero.soldierCloneCount = soldierClones.length; // Set initial soldier clone count hero.x = 2048 / 2; hero.y = 2732 + hero.height; // Initialize enemies, bullets, and laser beams arrays enemies = []; heroBullets = []; activeLaserBeams = []; hero.shootBehavior = powerUpManager.getCurrentPowerBehavior().bind(hero); } // Function to handle game updates game.update = function () { soldierClones.forEach(function (clone) { clone.shootBehavior = hero.shootBehavior; }); cityBackground1.update(); cityBackground2.update(); // Update the road instances road1.update(); road2.update(); // Update the left railing instances railingLeft1.update(); railingLeft2.update(); // Update the right railing instances railingRight1.update(); railingRight2.update(); if (isStarted) { if (dragNode) { hero.x = dragNode.x; hero.y = dragNode.y; } // Update enemies if (!enemies) { return; } // Ensure enemies array is initialized for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i]) { enemies[i].update(); } if (enemies[i] && CollisionManager.checkCollision(enemies[i], hero)) { if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { // Update shield tint based on new shield level hero.shieldGraphics.tint = 0xFFFFFF; // Reset tint to default if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; // Yellow tint } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; // White tint } } // Destroy enemy into pieces if (enemies[i] instanceof Drone) { generateEnemyPieces(enemies[i], DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); } else if (enemies[i] instanceof Bruiser) { generateEnemyPieces(enemies[i], BruiserPiece, ['BruiserCenterPart', 'BruiserLeftPart', 'BruiserRightPart']); } else if (enemies[i] instanceof Blaster) { generateEnemyPieces(enemies[i], BlasterPiece, ['BlasterBottomPiece', 'BlasterLeftPiece', 'BlasterRightPiece']); } enemies[i].destroy(); enemies.splice(i, 1); difficultyManager.onEnemyDestroyed(); } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } } // Update active laser beams for (var l = activeLaserBeams.length - 1; l >= 0; l--) { activeLaserBeams[l].update(); if (activeLaserBeams[l].isAttackComplete()) { if (activeLaserBeams[l].laserBeam) { activeLaserBeams[l].laserBeam.destroy(); } activeLaserBeams.splice(l, 1); } } difficultyManager.update(); // Update hero bullets for (var j = heroBullets.length - 1; j >= 0; j--) { heroBullets[j].update(); for (var k = enemies.length - 1; k >= 0; k--) { if (heroBullets[j] && CollisionManager.checkCollision(heroBullets[j], enemies[k]) && enemies[k].y > 0) { enemies[k].HitPoints -= heroBullets[j].Power; // Apply an increased push back effect if (!(enemies[k] instanceof Bruiser)) { enemies[k].y -= 12; // Push the drone upwards slightly more } enemies[k].pulseEffect = true; // Trigger pulse effect // Removed tracerTail reference heroBullets[j].destroy(); heroBullets.splice(j, 1); if (enemies[k].HitPoints <= 0) { if (enemies[k] instanceof Drone || enemies[k] instanceof RedDrone) { generateEnemyPieces(enemies[k], DronePiece, ['DroneCenterPart', 'DroneLeftPart', 'DroneRightPart']); } else if (enemies[k] instanceof Bruiser) { generateEnemyPieces(enemies[k], BruiserPiece, ['BruiserCenterPart', 'BruiserLeftPart', 'BruiserRightPart']); } else if (enemies[k] instanceof Blaster) { generateEnemyPieces(enemies[k], BlasterPiece, ['BlasterBottomPiece', 'BlasterLeftPiece', 'BlasterRightPiece']); } enemies[k].destroy(); enemies.splice(k, 1); difficultyManager.onEnemyDestroyed(); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); } break; } } } // Fire bullets using current power-up behavior if (LK.ticks % 18 == 0) { if (hero && hero.shootBehavior) { hero.shootBehavior(); } } // Generate dust particles in sync with player pulsing if (LK.ticks % 24 == 0) { var newDust = new Dust(); newDust.x = hero.x - hero.width / 4; // Move dust spawn position right half as much as the last move newDust.y = hero.y + hero.height / 2 * 0.93; // Move dust spawn point up 3% more game.addChild(newDust); } else if (LK.ticks % 24 == 12) { var newDust = new Dust(); newDust.x = hero.x + hero.width / 4; // Create another dust spawn point an equal distance in from the right of the player asset newDust.y = hero.y + hero.height / 2 * 0.93; // Move dust spawn point up 3% more game.addChild(newDust); } } }; // Handle touch input for hero movement var dragNode = null; game.down = function (x, y, obj) { if (isStarted) { dragNode = { x: hero.x, y: hero.y }; // Add a tilt-back effect during initial movement hero.rotation = x > hero.x ? Math.PI / 180 * -1 : Math.PI / 180 * 1; } }; game.move = function (x, y, obj) { if (isStarted && dragNode) { // Add a slight delay to the drag control to make the player feel like it has more weight dragNode.x += (x - dragNode.x) * 0.1; dragNode.y = hero.y; // Lock the y position to the hero's initial y position } }; game.up = function (x, y, obj) { dragNode = null; }; // Display score var scoreTxt = new Text2('0', { size: 150, fill: "#ffffff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.setText(LK.getScore()); LaserMechanic.prototype.startFiring = function () { if (!this.origin || !this.targetX || !this.targetY || this.isFiring) { return; } this.isFiring = true; this.fireStartTime = LK.ticks; // Create laser beam this.laserBeam = LK.getAsset('LaserBeam', { anchorX: 0.5, anchorY: 0, scaleX: 1, // Normal width scaleY: 5 // Make it long }); game.addChild(this.laserBeam); activeLaserBeams.push(this); // Position at origin if (this.origin) { this.laserBeam.x = this.origin.x; this.laserBeam.y = this.origin.y; } // Calculate direction to target var directionX = this.targetX - this.laserBeam.x; var directionY = this.targetY - this.laserBeam.y; // Set rotation this.laserBeam.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; }; LaserMechanic.prototype.updateFiring = function () { if (!this.isFiring) { return; } var fireProgress = (LK.ticks - this.fireStartTime) / this.fireDuration; if (fireProgress <= 1) { // Stretch the laser this.laserBeam.scaleY += (20 - this.laserBeam.scaleY) * 0.1; // Keep beam pinned to origin this.laserBeam.x = this.origin.x; this.laserBeam.y = this.origin.y; // Check collision with hero if (CollisionManager.checkCollision(this.laserBeam, hero)) { if (hero.shielded) { hero.shieldLevel -= 1; if (hero.shieldLevel <= 0) { hero.shielded = false; if (hero.shieldGraphics) { hero.shieldGraphics.destroy(); hero.shieldGraphics = null; } } else { hero.shieldGraphics.tint = 0xFFFFFF; if (hero.shieldLevel === 2) { hero.shieldGraphics.tint = 0xFFFF00; } else if (hero.shieldLevel === 1) { hero.shieldGraphics.tint = 0xFFFFFF; } } } else { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } else { for (var i = soldierClones.length - 1; i >= 0; i--) { var clone = soldierClones[i]; if (CollisionManager.checkCollision(this.laserBeam, clone)) { clone.destroy(); break; } } } } else { // Transition to sliding phase this.isFiring = false; this.startSliding(); } }; LaserMechanic.prototype.startSliding = function () { this.isSliding = true; this.slideStartTime = LK.ticks; this.origin = null; // Detach laser from Blaster origin // Calculate slide direction to move away from the origin point var directionX = -Math.sin(this.laserBeam.rotation); var directionY = Math.cos(this.laserBeam.rotation); this.slideDirection = { x: directionX, y: directionY }; }; LaserMechanic.prototype.updateSliding = function () { if (!this.isSliding || !this.laserBeam) { return; } var slideProgress = (LK.ticks - this.slideStartTime) / this.slideOffDuration; if (slideProgress <= 1) { // Move the beam off screen this.laserBeam.x += this.slideDirection.x * 20; this.laserBeam.y += this.slideDirection.y * 20; } else { // Clean up if (this.laserBeam) { game.removeChild(this.laserBeam); this.laserBeam = null; } this.isSliding = false; this.slideDirection = null; this.attackComplete = true; if (this.origin) { this.origin.laserMechanic.attackComplete = true; } } }; // Method to reset attack states LaserMechanic.prototype.resetAttack = function () { this.isCharging = false; this.isFiring = false; this.isSliding = false; this.targetX = null; this.targetY = null; this.attackComplete = false; return true; }; LaserMechanic.prototype.update = function () { if (this.isCharging) { this.updateCharge(); } else if (this.isFiring) { this.updateFiring(); } else if (this.isSliding || this.laserBeam) { this.updateSliding(); } }; // Method to check if the attack sequence is complete LaserMechanic.prototype.isAttackComplete = function () { return this.attackComplete; }; LaserMechanic.prototype.detachBeam = function () { if (this.laserBeam) { // Detach laser from origin this.origin = null; // Force laser into sliding phase this.startSliding(); } };
===================================================================
--- original.js
+++ change.js
@@ -262,15 +262,15 @@
1: {
drones: 5,
bruisers: 0,
blasters: 0,
- raiders: 1
+ raiders: 2
},
2: {
drones: 8,
bruisers: 0,
blasters: 0,
- raiders: 1
+ raiders: 2
},
3: {
drones: 8,
bruisers: 1,
View of a futuristic soldier from directly overhead. White armor with blue glowing cyberpunk details. Holding weapon forward.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
The lights of a futuristic city in the dark at night. Very high above it looking straight down like from an airplane or a map. Background for an endlessly scrolling game.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A big button that say Play to start playing a game. Use neon cyberpunk style.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Overhead view. A hovering robot with a tapered midsection with two bulky arms with claw like hands and a giant red “eye” on top of its body. Looking straight down. Cyberpunk, black with red glowing highlights.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Overhead view. A heavily armored attack robot. Two arms with large gauntlet type fists. Four large red glowing eyes. Three distinct parts, body and two arms. Symmetrical design. Birds Eye view above them looking down on their head. Simple shapes. Low detail. Cyberpunk, black with red glowing highlights.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A red glowing line. Bright red core with subtle outer glow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A blue transparent dome type shield. Simple graphics. Low details. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A ring of nuclear fire seen from overhead. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A thin robot with goggles riding a hover-bike. Twin blaster guns mounted on front. Top down view. Birds Eye view. Cyberpunk with red glowing highlights... Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Battle drone, circular. White with blue glowing highlights. Birds Eye view from overhead. Cyberpunk. Simple shapes.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
GameTheme
Music
TitleTheme
Music
HeroBlaster
Sound effect
Explosion
Sound effect
PowerUp
Sound effect
CloneSoldier
Sound effect
WeaponPowerUp
Sound effect
Drone
Sound effect
BinaryStorm
Sound effect
LaserCharge
Sound effect
LaserFire
Sound effect
BruiserStomp
Sound effect
RaiderSwoop
Sound effect
ShieldLevelUp
Sound effect
HeroHit
Sound effect
HeroScream
Sound effect