User prompt
In LaserMechanic's updateSliding method: When the laser beam is cleaned up (sliding complete): - Add a method called resetAttack() that: * Clears all states (isCharging, isFiring, isSliding) * Sets targetX and targetY back to null * Returns true when done ``` Then: ``` In the Blaster's update: If LaserMechanic.resetAttack() returns true: - Set nextAttackTime to current ticks + random(300,480) - Allow normal movement to resume
User prompt
In the LaserMechanic class: Add a flag to indicate when a complete sequence has finished (after sliding) Add a method called isAttackComplete() that returns true when done ``` Then: ``` In the Blaster's update: When LaserMechanic.isAttackComplete() is true: - Set nextAttackTime to current ticks + random(300,480) - Reset any attack flags
User prompt
If a Blaster is destroyed while firing the laser needs to slide off screen and be destroyed.
User prompt
In LaserMechanic's startSliding method, reverse the slide direction: Change the direction calculation to slide away from the origin point instead of toward it ``` Then, let's fix the continuous firing by adjusting the Blaster's timing: ``` In the Blaster class: - After a laser attack completes (when sliding is done), set nextAttackTime to current ticks plus random delay - The random delay should be between 300-480 ticks (5-8 seconds)
User prompt
Modify LaserMechanic's startFiring method to just create a basic laser beam: - Set scaleX to 1 (normal width) - Set scaleY to 5 (make it long) - Position it at the origin (self.origin)
User prompt
```javascript 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); this.chargeEffect.scale.x = 0.5 + (chargeProgress * 1.5); 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) { this.origin.removeChild(this.chargeEffect); this.chargeEffect = null; this.isCharging = false; this.startFiring(); // Add this line to transition to firing phase } }; ``` Let's also verify the firing related code is correct: ```javascript LaserMechanic.prototype.startFiring = function() { if (!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, scaleY: 0.1 // Start small and stretch }); game.addChild(this.laserBeam); // Position at 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; };
User prompt
Update the Blaster class to: - Initialize LaserMechanic - Handle attack timing - Control movement during laser phases - Handle cleanup on destroy Here's the updated Blaster class: ``` ```javascript var Blaster = Container.expand(function () { var self = Container.call(this); var blasterGraphics = self.attachAsset('Blaster', { anchorX: 0.5, anchorY: 0.5 }); // Basic properties self.HitPoints = 5; self.speed = 2; // Laser attack properties self.laserMechanic = new LaserMechanic(self, 60, 30, 30); // charge, fire, slide durations self.nextAttackTime = LK.ticks + randomRange(300, 480); // 5-8 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.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 // Check for nearby enemies and adjust path 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 downward self.y += self.speed; // Set next attack time when current attack completes if (!self.nextAttackTime) { self.nextAttackTime = LK.ticks + randomRange(300, 480); } } // Destroy if out of screen if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; // Override destroy to handle cleanup var originalDestroy = self.destroy; self.destroy = function() { // If we're in the middle of an attack sequence, let the laser mechanic finish if (self.laserMechanic.laserBeam) { self.laserMechanic.isFiring = false; self.laserMechanic.startSliding(); } originalDestroy.call(self); }; });
User prompt
Implement the firing phase with these requirements: - Start firing method - Laser beam stretching - Transition to sliding phase - Position and rotation calculations Add these methods to LaserMechanic: ``` ```javascript LaserMechanic.prototype.startFiring = function() { if (!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, scaleY: 0.1 // Start small and stretch }); game.addChild(this.laserBeam); // Position at 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; } else { // Transition to sliding phase this.isFiring = false; this.startSliding(); } }; LaserMechanic.prototype.startSliding = function() { this.isSliding = true; this.slideStartTime = LK.ticks; // Calculate slide direction (same as beam direction) var directionX = Math.sin(this.laserBeam.rotation); var directionY = -Math.cos(this.laserBeam.rotation); this.slideDirection = { x: directionX, y: directionY }; }; ``` And let's add the slide update: ```javascript LaserMechanic.prototype.updateSliding = function() { if (!this.isSliding) 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 game.removeChild(this.laserBeam); this.laserBeam = null; this.isSliding = false; this.slideDirection = null; } }; ``` Finally, add a main update method to handle all states: ```javascript LaserMechanic.prototype.update = function() { if (this.isCharging) { this.updateCharge(); } else if (this.isFiring) { this.updateFiring(); } else if (this.isSliding) { this.updateSliding(); } };
User prompt
Implement the charge phase with these requirements: - Create startCharge() method to initiate charging - Add charge effect animation - Track charge progress - Capture target position at specific point during charge - Clean up charge effect when done Here's the code to add to LaserMechanic: ``` ```javascript 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 } }); this.origin.addChild(this.chargeEffect); }; 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) { this.origin.removeChild(this.chargeEffect); this.chargeEffect = null; this.isCharging = false; // We'll add the call to start firing in the next step } };
User prompt
Create a LaserMechanic class that will manage the laser firing sequence: - Initialize with parameters for: * origin (the firing entity) * chargeDuration (how long the charge phase lasts) * fireDuration (how long the laser stays connected to origin) * slideOffDuration (how long it takes laser to slide off screen) - Add state tracking variables: * isCharging * isFiring * isSliding * chargeStartTime * fireStartTime * slideStartTime * targetPosition (where the laser will fire) Basic structure: ``` ```javascript var LaserMechanic = function(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; // Assets this.chargeEffect = null; this.laserBeam = null; // Target this.targetX = null; this.targetY = null; };
User prompt
Remove all laser charging and firing code from Blaster
User prompt
Remove blaster bullet class
User prompt
Remove the stop moving code for Blaster on laser firing.
User prompt
```javascript var LaserMechanic = function LaserMechanic(origin, chargeDuration, fireDuration, direction) { this.origin = origin; this.chargeDuration = chargeDuration; this.fireDuration = fireDuration; this.direction = direction; this.chargeStartTime = null; this.fireStartTime = null; this.laserCharge = null; this.laser = null; this.isCharging = false; this.isFiring = false; this.targetX = null; this.targetY = null; }; LaserMechanic.prototype.chargeLaser = function () { if (!this.isCharging) { this.isCharging = true; this.chargeStartTime = LK.ticks; // Create charge effect this.laserCharge = LK.getAsset('LaserCharge', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); this.origin.addChild(this.laserCharge); } // Calculate charge progress var chargeProgress = (LK.ticks - this.chargeStartTime) / this.chargeDuration; // Capture target position at 2/3 through charge if (chargeProgress >= 0.67 && !this.targetX) { this.targetX = hero.x; this.targetY = hero.y; } // Update charge effect this.laserCharge.alpha = 1; this.laserCharge.scale.x = 1 + chargeProgress * 3; this.laserCharge.scale.y = 1 - chargeProgress * 0.5; // Check if charge is complete if (chargeProgress >= 1) { this.origin.removeChild(this.laserCharge); this.laserCharge = null; this.isCharging = false; this.fireLaser(); } }; LaserMechanic.prototype.fireLaser = function () { if (!this.isFiring) { this.isFiring = true; this.fireStartTime = LK.ticks; // Create laser beam this.laser = LK.getAsset('LaserBeam', { anchorX: 0.5, anchorY: 0 }); game.addChild(this.laser); // Position laser this.laser.x = this.origin.x; this.laser.y = this.origin.y; // Calculate direction to target var directionX = this.targetX - this.laser.x; var directionY = this.targetY - this.laser.y; var magnitude = Math.sqrt(directionX * directionX + directionY * directionY); directionX /= magnitude; directionY /= magnitude; // Set rotation this.laser.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; } // Update laser var fireProgress = (LK.ticks - this.fireStartTime) / this.fireDuration; // Grow the laser if (fireProgress <= 0.3) { // Use first 30% of fire duration to grow this.laser.scale.y += 0.2; } // Check if firing is complete if (fireProgress >= 1) { game.removeChild(this.laser); this.laser = null; this.isFiring = false; this.targetX = null; this.targetY = null; } }; ``` And modify the Blaster class update to use it properly: ```javascript self.update = function () { // Start charging when appropriate distance from hero var distanceToHero = Math.sqrt( Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2) ); if (distanceToHero < 400 && !self.laserMechanic.isCharging && !self.laserMechanic.isFiring) { self.laserMechanic.chargeLaser(); } // Update laser if firing if (self.laserMechanic.isCharging) { self.laserMechanic.chargeLaser(); } else if (self.laserMechanic.isFiring) { self.laserMechanic.fireLaser(); } else { // Normal movement code... } // Rest of update code... };
User prompt
```javascript LaserMechanic.prototype.chargeLaser = function () { if (!this.laserCharge) { this.laserCharge = LK.getAsset('LaserCharge', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75, x: 0, // Relative to origin y: 0 }); this.origin.addChild(this.laserCharge); this.chargeStartTime = LK.ticks; } // Rest of the charging code... };
User prompt
Please fix the bug: 'TypeError: null is not an object (evaluating 'this.laser.x')' in or related to this line: 'this.laser.x += directionX * 20;' Line Number: 505
User prompt
Add this: ```javascript LaserMechanic.prototype.fireLaser = function () { // Create the laser beam this.laser = LK.getAsset('LaserBeam', { anchorX: 0.5, anchorY: 0 }); // Add laser to the game world instead of the origin object game.addChild(this.laser); // Add to game instead of origin // Set initial position (in world coordinates) this.laser.x = this.origin.x; this.laser.y = this.origin.y; // Calculate direction to target var directionX = this.targetX - this.laser.x; var directionY = this.targetY - this.laser.y; var magnitude = Math.sqrt(directionX * directionX + directionY * directionY); // Normalize direction directionX /= magnitude; directionY /= magnitude; // Set rotation this.laser.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; var startTime = LK.ticks; // Store start time this.laser.update = function () { var elapsed = LK.ticks - startTime; if (elapsed < this.fireDuration) { // Growing phase this.laser.scale.y += 0.2; } else { // Movement phase this.laser.x += directionX * 20; this.laser.y += directionY * 20; // Cleanup when off screen if (this.laser.x < 0 || this.laser.x > 2048 || this.laser.y < 0 || this.laser.y > 2732) { game.removeChild(this.laser); this.laser = null; } } }.bind(this); };
User prompt
The laser charge is happening in the right point of origin but the laser is not firing from the same point. Debug.
User prompt
When the laser is fired it should pin the start of the laser beam asset to the assignment point of origin and stretch the other side for the defined length of time and the defined speed.
User prompt
Create a class that encapsulates the laser charging and firing of the blaster class with room for parameters to be defined such as point of origin, length of charge and length and direction of firing. The point is to have a charge and fire mechanic that can be called for other enemies and the player.
User prompt
Add bruiser spawns to the game
User prompt
Put the laser charge and firing sequence in its own class so that it can be called for other classes. It should allow a point of origin to be defined during the initialization of its class
User prompt
The random rotation on enemy pieces should not lead to stuttering. If it rotates in one direction it should keep rotating in that direction.
User prompt
All of the pieces of the Blaster should move outwards, away from each other.
User prompt
Also increase the chance for the bottom piece to move downwards.
/**** * 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 = 5; // Moderate hit points for Blaster self.speed = 2; // Reduced speed for Blaster self.shootInterval = 60; // Interval for shooting bullets self.laserMechanic = new LaserMechanic(self, 90, 120, { x: 0, y: 1 }); self.chargeLaser = function () { self.laserMechanic.chargeLaser(); }; self.fireLaser = function () { self.laserMechanic.fireLaser(); }; self.update = function () { // Start charging when appropriate distance from hero var distanceToHero = Math.sqrt(Math.pow(hero.x - self.x, 2) + Math.pow(hero.y - self.y, 2)); if (distanceToHero < 400 && !self.laserMechanic.isCharging && !self.laserMechanic.isFiring) { self.laserMechanic.chargeLaser(); } // Update laser if firing if (self.laserMechanic.isCharging) { self.laserMechanic.chargeLaser(); } else if (self.laserMechanic.isFiring) { self.laserMechanic.fireLaser(); } else { // Normal movement code... // 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 { // Calculate direction towards hero var directionX = hero.x - self.x; var directionY = hero.y - self.y; var magnitude = Math.sqrt(directionX * directionX + directionY * directionY); directionX /= magnitude; directionY /= magnitude; // Move towards the hero self.x += directionX * self.speed; self.y += directionY * self.speed; // Swivel Blaster to face the hero blasterGraphics.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; } } // Destroy if out of screen if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; }); // BlasterBullet class for blaster's bullets var BlasterBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; // Speed of the bullet self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; }); // 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(); } }; }); // 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 = 10; // Higher hit points for Bruiser self.speed = 4; // Increased speed for Bruiser 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 (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; }); // 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(); } }; }); // 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.25; 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 (self.y > 2732) { self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; }); // 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.update = function () { 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 // Add scale change to simulate footsteps if (LK.ticks % 24 < 12) { self.scale.x = 1.02; } else { self.scale.x = 0.98; } }; }); // Bullet class for hero's bullets var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.Type = 'standard'; // Default type for bullets self.Power = 1; // Default power level for bullets self.update = function () { self.y += self.speed; if (self.y < 0) { self.destroy(); var index = heroBullets.indexOf(self); if (index > -1) { heroBullets.splice(index, 1); } } }; }); // 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; } }; }); // 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; } }; }); // 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 ****/ // Initialize the city background for parallax effect // LaserMechanic class for handling laser charging and firing var LaserMechanic = function LaserMechanic(origin, chargeDuration, fireDuration, direction) { this.origin = origin; this.chargeDuration = chargeDuration; this.fireDuration = fireDuration; this.direction = direction; this.chargeStartTime = null; this.fireStartTime = null; this.laserCharge = null; this.laser = null; this.isCharging = false; this.isFiring = false; this.targetX = null; this.targetY = null; }; LaserMechanic.prototype.chargeLaser = function () { if (!this.isCharging) { this.isCharging = true; this.chargeStartTime = LK.ticks; // Create charge effect this.laserCharge = LK.getAsset('LaserCharge', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); this.origin.addChild(this.laserCharge); } // Calculate charge progress var chargeProgress = (LK.ticks - this.chargeStartTime) / this.chargeDuration; // Capture target position at 2/3 through charge if (chargeProgress >= 0.67 && !this.targetX) { this.targetX = hero.x; this.targetY = hero.y; } // Update charge effect this.laserCharge.alpha = 1; this.laserCharge.scale.x = 1 + chargeProgress * 3; this.laserCharge.scale.y = 1 - chargeProgress * 0.5; // Check if charge is complete if (chargeProgress >= 1) { this.origin.removeChild(this.laserCharge); this.laserCharge = null; this.isCharging = false; this.fireLaser(); } }; LaserMechanic.prototype.fireLaser = function () { if (!this.isFiring) { this.isFiring = true; this.fireStartTime = LK.ticks; // Create laser beam this.laser = LK.getAsset('LaserBeam', { anchorX: 0.5, anchorY: 0 }); game.addChild(this.laser); // Position laser this.laser.x = this.origin.x; this.laser.y = this.origin.y; // Calculate direction to target var directionX = this.targetX - this.laser.x; var directionY = this.targetY - this.laser.y; var magnitude = Math.sqrt(directionX * directionX + directionY * directionY); directionX /= magnitude; directionY /= magnitude; // Set rotation this.laser.rotation = Math.atan2(directionY, directionX) - Math.PI / 2; } // Update laser var fireProgress = (LK.ticks - this.fireStartTime) / this.fireDuration; // Grow the laser if (fireProgress <= 0.3) { // Use first 30% of fire duration to grow this.laser.scale.y += 0.2; } // Check if firing is complete if (fireProgress >= 1) { game.removeChild(this.laser); this.laser = null; this.isFiring = false; this.targetX = null; this.targetY = null; } }; 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()); } // Function to start the game function startGame() { // Initialize hero hero = game.addChild(new Hero()); hero.x = 2048 / 2; hero.y = 2732 + hero.height; // Initialize enemies and bullets arrays enemies = []; heroBullets = []; } // Initialize variables var hero; var enemies = []; var heroBullets = []; // Function to handle game updates game.update = function () { // Update the city background instances for parallax effect 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] && enemies[i].intersects(hero)) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } // 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].intersects(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 heroBullets[j].destroy(); heroBullets.splice(j, 1); if (enemies[k].HitPoints <= 0) { if (enemies[k] instanceof Drone) { // Create drone pieces upon destruction var centerPiece = new DronePiece('DroneCenterPart'); centerPiece.x = enemies[k].x; centerPiece.y = enemies[k].y; game.addChild(centerPiece); var leftPiece = new DronePiece('DroneLeftPart'); leftPiece.x = enemies[k].x - 40; // Increase spread leftPiece.y = enemies[k].y; game.addChild(leftPiece); var rightPiece = new DronePiece('DroneRightPart'); rightPiece.x = enemies[k].x + 40; // Increase spread rightPiece.y = enemies[k].y; game.addChild(rightPiece); } else if (enemies[k] instanceof Bruiser) { // Create bruiser pieces upon destruction var centerPiece = new BruiserPiece('BruiserCenterPart'); centerPiece.x = enemies[k].x; centerPiece.y = enemies[k].y; game.addChild(centerPiece); var leftPiece = new BruiserPiece('BruiserLeftPart'); leftPiece.x = enemies[k].x - 40; // Increase spread leftPiece.y = enemies[k].y; var rightPiece = new BruiserPiece('BruiserRightPart'); rightPiece.x = enemies[k].x + 40; // Increase spread rightPiece.y = enemies[k].y; leftPiece.speedX = -Math.abs(leftPiece.speedX) * 1.5; // Increase force for left piece rightPiece.speedX = Math.abs(rightPiece.speedX) * 1.5; // Increase force for right piece game.addChild(leftPiece); game.addChild(rightPiece); } else if (enemies[k] instanceof Blaster) { // Create blaster pieces upon destruction var bottomPiece = new BlasterPiece('BlasterBottomPiece'); bottomPiece.x = enemies[k].x; bottomPiece.y = enemies[k].y; game.addChild(bottomPiece); var leftPiece = new BlasterPiece('BlasterLeftPiece'); leftPiece.x = enemies[k].x - 40; // Increase spread leftPiece.y = enemies[k].y; game.addChild(leftPiece); var rightPiece = new BlasterPiece('BlasterRightPiece'); rightPiece.x = enemies[k].x + 40; // Increase spread rightPiece.y = enemies[k].y; game.addChild(rightPiece); } enemies[k].destroy(); enemies.splice(k, 1); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); } break; } } } // Initialize charge-up phase for Blaster if (LK.ticks % 480 == 0) { // Begin charge sequence sooner // Every 10 seconds enemies.forEach(function (enemy) { if (enemy instanceof Blaster) { enemy.chargeUp = true; } }); } if (LK.ticks % 240 == 0) { var newBruiser = new Bruiser(); newBruiser.x = 2048 * 0.21 + Math.random() * (2048 * 0.55); // Adjusted x position within the Road area with 5% margin newBruiser.y = -newBruiser.height; // Start just outside the top of the screen enemies.push(newBruiser); game.addChild(newBruiser); } if (LK.ticks % 240 == 0) { var newBlaster = new Blaster(); newBlaster.x = 2048 * 0.21 + Math.random() * (2048 * 0.55); // Adjusted x position within the Road area with 5% margin newBlaster.y = -newBlaster.height; // Start just outside the top of the screen enemies.push(newBlaster); game.addChild(newBlaster); } // Fire bullets if (LK.ticks % 18 == 0) { var newBullet = new HeroBullet(); newBullet.x = hero.x; newBullet.y = hero.y - hero.height / 2; heroBullets.push(newBullet); game.addChild(newBullet); } // 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()); // Create blaster pieces upon destruction for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] instanceof Blaster && enemies[i].y > 2732) { var bottomPiece = new BlasterPiece('BlasterBottomPiece'); bottomPiece.x = enemies[i].x; bottomPiece.y = enemies[i].y; game.addChild(bottomPiece); var leftPiece = new BlasterPiece('BlasterLeftPiece'); leftPiece.x = enemies[i].x - 40; // Increase spread leftPiece.y = enemies[i].y; game.addChild(leftPiece); var rightPiece = new BlasterPiece('BlasterRightPiece'); rightPiece.x = enemies[i].x + 40; // Increase spread rightPiece.y = enemies[i].y; game.addChild(rightPiece); } }
===================================================================
--- original.js
+++ change.js
@@ -46,15 +46,11 @@
var directionY = hero.y - self.y;
var magnitude = Math.sqrt(directionX * directionX + directionY * directionY);
directionX /= magnitude;
directionY /= magnitude;
- // Move towards the hero, but stop movement during laser firing
- if (!self.chargeUp && !self.laserCharge && !self.laser && !self.laserFiring) {
- self.x += directionX * self.speed;
- if (!self.laserFiring) {
- self.y += directionY * self.speed;
- }
- }
+ // Move towards the hero
+ self.x += directionX * self.speed;
+ self.y += directionY * self.speed;
// Swivel Blaster to face the hero
blasterGraphics.rotation = Math.atan2(directionY, directionX) - Math.PI / 2;
}
}
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