Add enemy missle projectiles for wave 3 with new sound effect and updated shooting logic

This commit implements enemy missle projectiles for wave 3 enemies, including:
- Added new 'missle' audio file and loaded it in GameScene
- Created enemyMissles physics group for tracking missle projectiles
- Updated game waves configuration to include wave 3 with special enemies (texture 3)
- Modified enemy spawning logic to handle missle capability for wave 3 enemies
- Implemented enemyMissle() method that creates two directional missles that later home in on player
- Adjusted enemy shooting logic to differentiate between regular bullets and missles based on texture
- Added collision detection between player and missles
- Updated wave-specific properties handling for new enemy types

The changes enable a new challenging gameplay element in wave 3 where enemies can launch homing missle projectiles.
This commit is contained in:
Brian Fertig 2025-08-06 19:54:42 -06:00
parent eb01c3d89c
commit c93e599556
4 changed files with 77 additions and 16 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
assets/sounds/missle.mp3 Normal file

Binary file not shown.

Binary file not shown.

View File

@ -11,6 +11,7 @@ export class GameScene extends Phaser.Scene {
// Enemy bullets group // Enemy bullets group
this.enemyBullets = null; this.enemyBullets = null;
this.enemyMissles = null;
// Game state // Game state
this.score = 0; this.score = 0;
@ -39,6 +40,11 @@ export class GameScene extends Phaser.Scene {
waveNumber: 2, waveNumber: 2,
time: 40000, time: 40000,
enemyTypes: [2] // Special enemies in wave 3 enemyTypes: [2] // Special enemies in wave 3
},
{
waveNumber: 3,
time: 60000,
enemyTypes: [3] // Special enemies in wave 3
} }
]; ];
} }
@ -75,6 +81,7 @@ export class GameScene extends Phaser.Scene {
this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3'); this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3');
this.load.audio('next-wave', 'assets/sounds/next-wave.mp3'); this.load.audio('next-wave', 'assets/sounds/next-wave.mp3');
this.load.audio('thruster', 'assets/sounds/thruster.mp3'); this.load.audio('thruster', 'assets/sounds/thruster.mp3');
this.load.audio('missle', 'assets/sounds/missle.mp3');
// Load Fonts // Load Fonts
this.load.font('Space', 'assets/space-age.otf'); this.load.font('Space', 'assets/space-age.otf');
@ -98,11 +105,13 @@ export class GameScene extends Phaser.Scene {
this.bullets = this.physics.add.group(); this.bullets = this.physics.add.group();
this.enemyBullets = this.physics.add.group(); this.enemyBullets = this.physics.add.group();
this.enemies = this.physics.add.group(); this.enemies = this.physics.add.group();
this.enemyMissles = this.physics.add.group();
// Setup collision detection // Setup collision detection
this.physics.add.overlap(this.bullets, this.enemies, this.hitEnemy, null, this); this.physics.add.overlap(this.bullets, this.enemies, this.hitEnemy, null, this);
this.physics.add.overlap(this.player.sprite, this.enemies, this.hitPlayer, null, this); this.physics.add.overlap(this.player.sprite, this.enemies, this.hitPlayer, null, this);
this.physics.add.overlap(this.player.sprite, this.enemyBullets, this.hitPlayer, null, this); this.physics.add.overlap(this.player.sprite, this.enemyBullets, this.hitPlayer, null, this);
this.physics.add.overlap(this.player.sprite, this.enemyMissles, this.hitPlayer, null, this);
// Start enemy spawning // Start enemy spawning
this.time.addEvent({ this.time.addEvent({
@ -287,14 +296,6 @@ export class GameScene extends Phaser.Scene {
fontFamily: 'Space, Arial' fontFamily: 'Space, Arial'
}); });
// Create game title
// this.titleText = this.add.text(300, 50, 'Zenith Vector', {
// fontSize: '40px',
// fill: '#00ffcc',
// fontFamily: 'Arial',
// align: 'center'
// });
// this.titleText.setOrigin(0.5);
this.titleText = this.add.image(500, 50, 'logo').setScale(.3).setOrigin(0.5).postFX.addGlow(); this.titleText = this.add.image(500, 50, 'logo').setScale(.3).setOrigin(0.5).postFX.addGlow();
} }
@ -339,9 +340,6 @@ export class GameScene extends Phaser.Scene {
const speed = Phaser.Math.Between(50, 150); const speed = Phaser.Math.Between(50, 150);
enemy.setVelocityY(speed); enemy.setVelocityY(speed);
// Add some rotation for visual effect
//enemy.setRotation(Phaser.Math.FloatBetween(-0.2, 0.2));
// Apply wave-specific properties // Apply wave-specific properties
this.applyWaveProperties(enemy, texture); this.applyWaveProperties(enemy, texture);
} }
@ -353,14 +351,16 @@ export class GameScene extends Phaser.Scene {
// Wave 1: Basic enemies (no shooting) // Wave 1: Basic enemies (no shooting)
if (this.currentWave === 0) { if (this.currentWave === 0) {
enemy.canShoot = false; enemy.canShoot = false;
enemy.canMissle = false;
if (enemy.shootTimer) { if (enemy.shootTimer) {
enemy.shootTimer.remove(); enemy.shootTimer.remove();
enemy.shootTimer = null; enemy.shootTimer = null;
} }
} }
// Wave 2: Enemies that can shoot // Wave 2: Enemies that can shoot
else if (this.currentWave >= 1 && texture > 0) { else if (this.currentWave >= 1 && texture > 0 && texture <= 2) {
enemy.canShoot = true; enemy.canShoot = true;
enemy.canMissle = false;
// Only set up shooting timer if it doesn't exist yet // Only set up shooting timer if it doesn't exist yet
if (!enemy.shootTimer) { if (!enemy.shootTimer) {
enemy.shootTimer = this.time.addEvent({ enemy.shootTimer = this.time.addEvent({
@ -371,6 +371,19 @@ export class GameScene extends Phaser.Scene {
}); });
} }
} }
// Wave 3: Enemies with missles
else if (this.currentWave >= 3 && texture === 3) {
enemy.canMissle = true;
// Only set up shooting timer if it doesn't exist yet
if (!enemy.missleTimer) {
enemy.missleTimer = this.time.addEvent({
delay: Phaser.Math.Between(1000, 3000),
callback: () => this.enemyMissle(enemy, texture),
callbackScope: this,
loop: true
});
}
}
} }
hitEnemy(bullet, enemy) { hitEnemy(bullet, enemy) {
@ -484,9 +497,8 @@ export class GameScene extends Phaser.Scene {
// Only shoot if enemy can shoot and isn't destroyed // Only shoot if enemy can shoot and isn't destroyed
if (!enemy.canShoot || !enemy.active) return; if (!enemy.canShoot || !enemy.active) return;
console.log(texture);
// Check if this is wave 3 and enemy has texture 2 (special shooting) // Check if this is wave 3 and enemy has texture 2 (special shooting)
if (this.currentWave >= 2 && enemy.waveNumber >= 2 && texture >= 2) { if (this.currentWave >= 2 && enemy.waveNumber >= 2 && texture === 2) {
// Shoot toward player // Shoot toward player
const angle = Phaser.Math.Angle.Between( const angle = Phaser.Math.Angle.Between(
enemy.x, enemy.x,
@ -500,7 +512,7 @@ export class GameScene extends Phaser.Scene {
bullet.setVelocityX(Math.cos(angle) * speed); bullet.setVelocityX(Math.cos(angle) * speed);
bullet.setVelocityY(Math.sin(angle) * speed); bullet.setVelocityY(Math.sin(angle) * speed);
bullet.setScale(1.5); bullet.setScale(1.5);
} else { } else if (texture === 1) {
// Regular straight-down shooting // Regular straight-down shooting
const bullet = this.enemyBullets.create(enemy.x, enemy.y, 'enemyBullet'); const bullet = this.enemyBullets.create(enemy.x, enemy.y, 'enemyBullet');
bullet.setVelocityY(300); // Move straight down at 200px/s bullet.setVelocityY(300); // Move straight down at 200px/s
@ -511,6 +523,55 @@ export class GameScene extends Phaser.Scene {
this.sound.play('enemy-shoot'); this.sound.play('enemy-shoot');
} }
enemyMissle(enemy, texture) {
// Only shoot if enemy can shoot and isn't destroyed
if (!enemy.canMissle || !enemy.active) return;
// Check if this is wave 3 and enemy has texture 2 (special shooting)
if (this.currentWave >= 3 && enemy.waveNumber >= 3 && texture >= 3) {
const missle1 = this.enemyMissles.create(enemy.x, enemy.y, 'enemy-sprite', 30);
const missle2 = this.enemyMissles.create(enemy.x, enemy.y, 'enemy-sprite', 30);
// Initial velocity
missle1.setVelocityX(-100).setVelocityY(200).setAngle(45).setScale(.5);
missle2.setVelocityX(100).setVelocityY(200).setAngle(-45).setScale(.5);
// After 500ms, change direction towards player and increase speed
this.time.delayedCall(500, () => {
if (missle1 && missle1.active) {
const angle = Phaser.Math.Angle.Between(
missle1.x,
missle1.y,
this.player.sprite.x,
this.player.sprite.y
);
// Increase velocity to 300 and change direction
missle1.setVelocityX(Math.cos(angle) * 300);
missle1.setVelocityY(Math.sin(angle) * 300);
missle1.setAngle(Phaser.Math.RadToDeg(angle)-90);
}
if (missle2 && missle2.active) {
const angle = Phaser.Math.Angle.Between(
missle2.x,
missle2.y,
this.player.sprite.x,
this.player.sprite.y
);
// Increase velocity to 300 and change direction
missle2.setVelocityX(Math.cos(angle) * 300);
missle2.setVelocityY(Math.sin(angle) * 300);
missle2.setAngle(Phaser.Math.RadToDeg(angle)-90);
}
});
}
// Sound effect for enemy shooting
this.sound.play('missle');
}
checkEnemiesOffScreen() { checkEnemiesOffScreen() {
// Destroy enemies that have gone below the screen // Destroy enemies that have gone below the screen
this.enemies.children.iterate((enemy) => { this.enemies.children.iterate((enemy) => {