diff --git a/assets/advanced-enemies.png b/assets/advanced-enemies.png index 65efce5..3e79b5d 100644 Binary files a/assets/advanced-enemies.png and b/assets/advanced-enemies.png differ diff --git a/assets/advanced-enemies.psd b/assets/advanced-enemies.psd index 9e8735b..5ec8169 100644 Binary files a/assets/advanced-enemies.psd and b/assets/advanced-enemies.psd differ diff --git a/assets/basic-enemies.png b/assets/basic-enemies.png index e0db7a8..a8d9315 100644 Binary files a/assets/basic-enemies.png and b/assets/basic-enemies.png differ diff --git a/assets/basic-enemies.psd b/assets/basic-enemies.psd index 72b6bb4..efd8057 100644 Binary files a/assets/basic-enemies.psd and b/assets/basic-enemies.psd differ diff --git a/assets/music/level-bg1.mp3 b/assets/music/level-bg1.mp3 new file mode 100644 index 0000000..dc4ef18 Binary files /dev/null and b/assets/music/level-bg1.mp3 differ diff --git a/assets/music/level-bg2.mp3 b/assets/music/level-bg2.mp3 new file mode 100644 index 0000000..41c9195 Binary files /dev/null and b/assets/music/level-bg2.mp3 differ diff --git a/assets/sounds/cannon.mp3 b/assets/sounds/cannon.mp3 new file mode 100644 index 0000000..c29cc0b Binary files /dev/null and b/assets/sounds/cannon.mp3 differ diff --git a/assets/sounds/coin.mp3 b/assets/sounds/coin.mp3 new file mode 100644 index 0000000..9104940 Binary files /dev/null and b/assets/sounds/coin.mp3 differ diff --git a/assets/sounds/coinWoosh.mp3 b/assets/sounds/coinWoosh.mp3 new file mode 100644 index 0000000..e54922e Binary files /dev/null and b/assets/sounds/coinWoosh.mp3 differ diff --git a/assets/sounds/flamethrower.mp3 b/assets/sounds/flamethrower.mp3 new file mode 100644 index 0000000..68eead3 Binary files /dev/null and b/assets/sounds/flamethrower.mp3 differ diff --git a/assets/sounds/gatling-gun.mp3 b/assets/sounds/gatling-gun.mp3 new file mode 100644 index 0000000..c3c8b91 Binary files /dev/null and b/assets/sounds/gatling-gun.mp3 differ diff --git a/assets/sounds/interfaceOpen.mp3 b/assets/sounds/interfaceOpen.mp3 new file mode 100644 index 0000000..01913b1 Binary files /dev/null and b/assets/sounds/interfaceOpen.mp3 differ diff --git a/assets/sounds/laser.mp3 b/assets/sounds/laser.mp3 new file mode 100644 index 0000000..d860246 Binary files /dev/null and b/assets/sounds/laser.mp3 differ diff --git a/assets/sounds/nextWave.mp3 b/assets/sounds/nextWave.mp3 new file mode 100644 index 0000000..633afa7 Binary files /dev/null and b/assets/sounds/nextWave.mp3 differ diff --git a/assets/sounds/portal.mp3 b/assets/sounds/portal.mp3 new file mode 100644 index 0000000..264eb42 Binary files /dev/null and b/assets/sounds/portal.mp3 differ diff --git a/assets/sounds/rocket-explosion.mp3 b/assets/sounds/rocket-explosion.mp3 new file mode 100644 index 0000000..a2525e1 Binary files /dev/null and b/assets/sounds/rocket-explosion.mp3 differ diff --git a/assets/sounds/rocket-launch.mp3 b/assets/sounds/rocket-launch.mp3 new file mode 100644 index 0000000..64be842 Binary files /dev/null and b/assets/sounds/rocket-launch.mp3 differ diff --git a/assets/sounds/towerPlace.mp3 b/assets/sounds/towerPlace.mp3 new file mode 100644 index 0000000..3fcd759 Binary files /dev/null and b/assets/sounds/towerPlace.mp3 differ diff --git a/assets/sounds/upgrade.mp3 b/assets/sounds/upgrade.mp3 new file mode 100644 index 0000000..b80caed Binary files /dev/null and b/assets/sounds/upgrade.mp3 differ diff --git a/assets/towers.png b/assets/towers.png index dfc834b..474d911 100644 Binary files a/assets/towers.png and b/assets/towers.png differ diff --git a/assets/towers.psd b/assets/towers.psd index abfdf3c..dd62de3 100644 Binary files a/assets/towers.psd and b/assets/towers.psd differ diff --git a/src/levels/level.js b/src/levels/level.js index a320133..cbd18bd 100644 --- a/src/levels/level.js +++ b/src/levels/level.js @@ -31,6 +31,24 @@ export class Level extends Phaser.Scene { frameHeight: 150, frameWidth: 150 }); + + // Sound FX + this.load.audio('rocket-launch', 'assets/sounds/rocket-launch.mp3'); + this.load.audio('rocket-explosion', 'assets/sounds/rocket-explosion.mp3'); + this.load.audio('cannon', 'assets/sounds/cannon.mp3'); + this.load.audio('flamethrower', 'assets/sounds/flamethrower.mp3'); + this.load.audio('gatling-gun', 'assets/sounds/gatling-gun.mp3'); + this.load.audio('interfaceOpen', 'assets/sounds/interfaceOpen.mp3'); + this.load.audio('nextWave', 'assets/sounds/nextWave.mp3'); + this.load.audio('towerPlace', 'assets/sounds/towerPlace.mp3'); + this.load.audio('coin', 'assets/sounds/coin.mp3'); + this.load.audio('coinWoosh', 'assets/sounds/coinWoosh.mp3'); + this.load.audio('portal', 'assets/sounds/portal.mp3'); + this.load.audio('laser', 'assets/sounds/laser.mp3'); + this.load.audio('upgrade', 'assets/sounds/upgrade.mp3'); + + // Music + this.load.audio('level-bg1', 'assets/music/level-bg1.mp3'); } create() { @@ -53,6 +71,10 @@ export class Level extends Phaser.Scene { this.enemies = this.physics.add.group(); this.towers = this.physics.add.group(); + this.bgMusic = this.sound.add('level-bg1', { volume: 1 }); + this.bgMusic.loop = true; + this.bgMusic.play(); + this.physics.add.collider(this.enemies, this.mainLayer); this.physics.add.collider(this.enemies, this.platformsLayer); } diff --git a/src/support/enemies.js b/src/support/enemies.js index 6346640..9bc9d55 100644 --- a/src/support/enemies.js +++ b/src/support/enemies.js @@ -29,8 +29,22 @@ export class Enemies { // Randomize Spawn Time a bit this.scene.time.delayedCall(Phaser.Math.Between(this.spawnRange.low, this.spawnRange.high), () => { + // Spawn Portal + this.scene.sound.play('portal'); + const portal = this.scene.add.sprite(spawnX, spawnY, ENEMIES_CONFIG[this.type].spriteSheet, 90).setAlpha(1).setScale(2).setDepth(8); + this.scene.tweens.add({ + targets: portal, + scale: .5, + alpha: .4, + angle: 270, + duration: 1000, + onComplete: () => { + portal.destroy(); + } + }); + // Create enemy and store reference - const enemy = this.scene.add.sprite(spawnX, spawnY, ENEMIES_CONFIG[this.type].spriteSheet, ENEMIES_CONFIG[this.type].spriteStart); + const enemy = this.scene.add.sprite(spawnX, spawnY, ENEMIES_CONFIG[this.type].spriteSheet, ENEMIES_CONFIG[this.type].spriteStart).setDepth(10); // Create Animations if (this.type.indexOf('basic') === 0) { diff --git a/src/support/interfaceManager.js b/src/support/interfaceManager.js index eea17b1..ad14745 100644 --- a/src/support/interfaceManager.js +++ b/src/support/interfaceManager.js @@ -4,7 +4,7 @@ export class InterfaceManager { constructor(scene) { this.scene = scene; - this.gold = 1150; + this.gold = 150; this.cores = 20; this.interfaceOpen = false; this.selectedTower = false; @@ -204,6 +204,7 @@ export class InterfaceManager { } openInterface() { + this.scene.sound.play('interfaceOpen'); this.interfaceOpen = true; this.scene.levelScene.allowPan = false; this.upLeft.setAlpha(0).setRotation(Math.PI); @@ -315,7 +316,7 @@ export class InterfaceManager { } }).setOrigin(1, 0).setScrollFactor(0); slot.add(slotCost); - console.log(type); + if (type === 'icbm') { const towerBase = this.scene.add.sprite(startX, startY, 'towers', TOWERS_CONFIG[type].spriteStart) .setOrigin(0.5) @@ -430,6 +431,7 @@ export class InterfaceManager { placeTower(type) { if (this.selectedTower.safe === true) { + this.scene.sound.play('towerPlace'); //Bring up Next Wave on first tower: if (this.scene.levelScene.towers.countActive() === 0) { this.showNextWave(); diff --git a/src/support/towerAnims.js b/src/support/towerAnims.js index 62f97d3..bd18a1d 100644 --- a/src/support/towerAnims.js +++ b/src/support/towerAnims.js @@ -53,6 +53,24 @@ export class TowerAnims { frameRate: 5, repeat: 0 }); + this.scene.anims.create({ + key: 'cannon-level2-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 13, + end: 12 + }), + frameRate: 5, + repeat: 0 + }); + this.scene.anims.create({ + key: 'cannon-level3-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 15, + end: 14 + }), + frameRate: 5, + repeat: 0 + }); this.scene.anims.create({ key: 'flamethrower', frames: this.scene.anims.generateFrameNumbers('towers', { @@ -71,6 +89,6 @@ export class TowerAnims { }), framerate: 4, repeat: -1 - }) + }); } } \ No newline at end of file diff --git a/src/support/towerConfig.js b/src/support/towerConfig.js index 612701b..723a046 100644 --- a/src/support/towerConfig.js +++ b/src/support/towerConfig.js @@ -44,7 +44,7 @@ export const TOWERS_CONFIG = { 'rate': 2500, 'duration': 200, 'range': 400, - 'aoe': 50, + 'aoe': 55, 'anim': 'cannon-level1-fire' }, 'level2': { @@ -55,7 +55,7 @@ export const TOWERS_CONFIG = { 'rate': 2500, 'duration': 500, 'range': 450, - 'aoe': 25, + 'aoe': 60, 'anim': 'cannon-level1-fire' }, 'level3': { @@ -66,7 +66,7 @@ export const TOWERS_CONFIG = { 'rate': 2500, 'duration': 500, 'range': 500, - 'aoe': 25, + 'aoe': 65, 'anim': 'cannon-level1-fire' } }, @@ -118,7 +118,7 @@ export const TOWERS_CONFIG = { 'rate': 10000, 'duration': 2000, 'range': 800, - 'aoe': 250, + 'aoe': 200, 'anim': 'none' }, 'level2': { @@ -128,7 +128,7 @@ export const TOWERS_CONFIG = { 'rate': 8000, 'duration': 2000, 'range': 800, - 'aoe': 250, + 'aoe': 210, 'anim': 'none' }, 'level3': { @@ -138,8 +138,42 @@ export const TOWERS_CONFIG = { 'rate': 5000, 'duration': 2000, 'range': 800, - 'aoe': 250, + 'aoe': 225, 'anim': 'none' } + }, + 'laser': { + 'name': 'Laser Cannon', + 'cost': 200, + 'spriteStart': 40, + 'dmgType': 'direct', + 'level1': { + 'dmgLow': 5, + 'dmgHigh': 10, + 'rate': 500, + 'duration': 500, + 'range': 350, + 'anim': 'laser-level1-fire' + }, + 'level2': { + 'sprite': 42, + 'cost': 400, + 'dmgLow': 8, + 'dmgHigh': 16, + 'rate': 500, + 'duration': 500, + 'range': 375, + 'anim': 'laser-level2-fire' + }, + 'level3': { + 'sprite': 44, + 'cost': 800, + 'dmgLow': 10, + 'dmgHigh': 20, + 'rate': 500, + 'duration': 500, + 'range': 400, + 'anim': 'laser-level3-fire' + } } } \ No newline at end of file diff --git a/src/support/towerManager.js b/src/support/towerManager.js index d851d8c..7c7a546 100644 --- a/src/support/towerManager.js +++ b/src/support/towerManager.js @@ -24,6 +24,7 @@ export class TowerManager { createTower(type, x, y) { const posX = this.scene.gridToLocation(x); const posY = this.scene.gridToLocation(y); + const towerContainer = this.scene.add.container(); let towerBase; let tower; @@ -43,6 +44,11 @@ export class TowerManager { } } + tower.towerBase = towerBase; + + towerContainer.add(towerBase); + towerContainer.add(tower); + // Generate unique ID for enemy const uniqueId = Phaser.Math.Between(100000, 999999); tower.id = uniqueId; @@ -68,7 +74,7 @@ export class TowerManager { const currentLevel = `level${tower.props.level}`; const nextLevel = currentLevel === 'level3' ? 'level3' : `level${tower.props.level + 1}`; - this.upgradeDetails = this.scene.add.container(); + this.upgradeDetails = this.scene.add.container().setDepth(18); const rangeCircle = this.scene.add.circle(tower.x, tower.y, TOWERS_CONFIG[tower.props.type][currentLevel].range, 0xc009900, 0.2) .setOrigin(0.5) @@ -114,7 +120,7 @@ export class TowerManager { }).setDepth(13).setAlpha(0).setInteractive(); this.upgradeDetails.add(this.upgradeText); - if (currentLevel === 'level3') upgradeText.setText('Max Upgrade').disableInteractive(); + if (currentLevel === 'level3') this.upgradeText.setText('Max Upgrade').disableInteractive(); const upgradeCancelText = this.scene.add.text(tower.x +175, tower.y + 25, `Cancel`, { fontFamily: 'neuropol, arial', @@ -182,7 +188,12 @@ export class TowerManager { if (tower.props.level === 3) return; tower.props.level++; const newLevel = `level${tower.props.level}` - tower.setTexture('towers', TOWERS_CONFIG[tower.props.type][newLevel].sprite); + this.scene.sound.play('upgrade'); + if (tower.props.type === 'icbm') { + tower.towerBase.setTexture('towers', 29+tower.props.level); + } else { + tower.setTexture('towers', TOWERS_CONFIG[tower.props.type][newLevel].sprite); + } this.scene.UIScene.removeGold(TOWERS_CONFIG[tower.props.type][newLevel].cost); } @@ -276,11 +287,54 @@ export class TowerManager { const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y); tower.rotation = angle; - - const vid = tower.play(config.anim); - this.scene.time.delayedCall(config.duration, () => { - vid.stop(); - }); + + if (type === 'gun') { + const gunSound = this.scene.sound.add('gatling-gun'); + gunSound.play(); + + const vid = tower.play(config.anim); + this.scene.time.delayedCall(config.duration, () => { + vid.stop(); + gunSound.stop(); + }); + } + + if (type === 'laser') { + // Create laser beam effect + const laserBeam = this.scene.add.graphics(); + laserBeam.lineStyle(3, 0x00ff00, 1); // 3px wide, bright green, full opacity + + // Draw line from tower to enemy + const projDistance = 60; + const projX = tower.x + Math.cos(angle) * projDistance; + const projY = tower.y + Math.sin(angle) * projDistance; + laserBeam.beginPath(); + laserBeam.moveTo(projX, projY); + laserBeam.lineTo(enemy.x, enemy.y); + laserBeam.strokePath(); + + this.scene.sound.play('laser'); + + // Fade out effect over duration + this.scene.tweens.add({ + targets: laserBeam, + alpha: 0, + duration: config.duration, + ease: 'Linear', + onComplete: () => { + laserBeam.destroy(); + } + }); + + // Reset tower texture after duration + let currentFrame = 40; + if (tower.props.level === 2) currentFrame = 42; + if (tower.props.level === 3) currentFrame = 44; + tower.setTexture('towers', currentFrame+1); + this.scene.time.delayedCall(config.duration, () => { + tower.setTexture('towers', currentFrame); + }); + } // Calculate damage (random between low and high) const damage = Phaser.Math.Between(dmgLow, dmgHigh); @@ -319,6 +373,7 @@ export class TowerManager { tower.rotation = angle; if (type === 'cannon') { + this.scene.sound.play('cannon'); const projDistance = 50; const projX = tower.x + Math.cos(angle) * projDistance; const projY = tower.y + Math.sin(angle) * projDistance; @@ -348,6 +403,8 @@ export class TowerManager { const projectile = this.scene.add.sprite(projX, projY, 'towers', 23).setScale(1.5).setAlpha(.5); projectile.rotation = angle; projectile.play(`flamethrower`); + const flameSound = this.scene.sound.add('flamethrower'); + flameSound.play(); this.scene.tweens.add({ targets: projectile, x: proj2X, @@ -355,6 +412,7 @@ export class TowerManager { duration:1000, onComplete: () => { projectile.destroy(); + flameSound.stop(); } }); @@ -397,6 +455,7 @@ export class TowerManager { const fireMissle = this.scene.add.sprite(tower.x, tower.y, 'towers', 33).setDepth(12); tower.setVisible(false); + this.scene.sound.play('rocket-launch'); this.scene.tweens.add({ targets: fireMissle, x: fireMissle.x, @@ -415,6 +474,7 @@ export class TowerManager { onComplete: () => { fireMissle.destroy(); tower.setVisible(true); + this.scene.sound.play('rocket-explosion'); const damage = Phaser.Math.Between(dmgLow, dmgHigh); const aoeDistance = config.aoe; const enemiesInRange = this.scene.enemies.getChildren().filter(e => { @@ -508,6 +568,7 @@ export class TowerManager { const cam = this.scene.cameras.main; // Animate the cash drop moving to the new position + this.scene.sound.play('coinWoosh', { volume: 2 }); this.scene.tweens.add({ targets: cashDrop, x: endX, @@ -523,6 +584,7 @@ export class TowerManager { alpha: 0, duration: 500, onComplete: () => { + this.scene.sound.play('coin'); cashDrop.destroy(); this.scene.UIScene.addGold(drop); this.scene.UIScene.interfaceManager.updateTowerAvail(); diff --git a/src/support/waveConfig.js b/src/support/waveConfig.js index fb9d4e7..fb7b0b6 100644 --- a/src/support/waveConfig.js +++ b/src/support/waveConfig.js @@ -98,12 +98,34 @@ export const WAVE_CONFIG = { }, 4: { begin: 35, - basic1: 15 + basic1: 25 }, 5: { begin: 40, advanced1: 1 } + }, + //Wave + 6: { + //Schedule + 1: { + begin: 0, + basic2: 10, + advanced2: 1 + }, + 2: { + begin: 15, + basic1: 20, + }, + 3: { + begin: 25, + basic3: 6, + advanced1: 1 + }, + 4: { + begin: 35, + advanced2: 1 + } } } } \ No newline at end of file diff --git a/src/support/waveManager.js b/src/support/waveManager.js index 1859386..a9368ed 100644 --- a/src/support/waveManager.js +++ b/src/support/waveManager.js @@ -29,6 +29,7 @@ export class WaveManager { nextWave() { // Next Wave will be started in the interfaceManager + this.scene.sound.play('nextWave', { volume: 2 }); if (this.waveActive === true) { this.wave++; this.waveTimer = 0;