diff --git a/assets/towers.png b/assets/towers.png index e855b34..dfc834b 100644 Binary files a/assets/towers.png and b/assets/towers.png differ diff --git a/assets/towers.psd b/assets/towers.psd index daf399d..abfdf3c 100644 Binary files a/assets/towers.psd and b/assets/towers.psd differ diff --git a/src/support/enemies.js b/src/support/enemies.js index 86fac7a..6346640 100644 --- a/src/support/enemies.js +++ b/src/support/enemies.js @@ -35,13 +35,13 @@ export class Enemies { // Create Animations if (this.type.indexOf('basic') === 0) { this.createAnim('side', ENEMIES_CONFIG[this.type].spriteStart, ENEMIES_CONFIG[this.type].spriteStart+2); - this.createAnim('up', ENEMIES_CONFIG[this.type].spriteStart+6, ENEMIES_CONFIG[this.type].spriteStart+8); + this.createAnim('up', ENEMIES_CONFIG[this.type].spriteStart+6, ENEMIES_CONFIG[this.type].spriteStart+7); this.createAnim('down', ENEMIES_CONFIG[this.type].spriteStart+3, ENEMIES_CONFIG[this.type].spriteStart+5); this.createAnim('die', ENEMIES_CONFIG[this.type].spriteStart+8, ENEMIES_CONFIG[this.type].spriteStart+9, 0); } if (this.type.indexOf('advanced') === 0) { this.createAnim('side', ENEMIES_CONFIG[this.type].spriteStart+3, ENEMIES_CONFIG[this.type].spriteStart+5); - this.createAnim('up', ENEMIES_CONFIG[this.type].spriteStart+6, ENEMIES_CONFIG[this.type].spriteStart+7); + this.createAnim('up', ENEMIES_CONFIG[this.type].spriteStart+6, ENEMIES_CONFIG[this.type].spriteStart+8); this.createAnim('down', ENEMIES_CONFIG[this.type].spriteStart, ENEMIES_CONFIG[this.type].spriteStart+2); this.createAnim('die', ENEMIES_CONFIG[this.type].spriteStart+8, ENEMIES_CONFIG[this.type].spriteStart+9, 0); } diff --git a/src/support/interfaceManager.js b/src/support/interfaceManager.js index 319d8ff..eea17b1 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 = 150; + this.gold = 1150; this.cores = 20; this.interfaceOpen = false; this.selectedTower = false; @@ -315,16 +315,28 @@ 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) + .setScrollFactor(0); + slot.add(towerBase); - const towerBase = this.scene.add.sprite(startX, startY, 'towers', 7) - .setOrigin(0.5) - .setScrollFactor(0); - slot.add(towerBase); + const towerTop = this.scene.add.sprite(startX, startY, 'towers', TOWERS_CONFIG[type].spriteStart+3) + .setOrigin(0.5) + .setScrollFactor(0); + slot.add(towerTop); + } else { + const towerBase = this.scene.add.sprite(startX, startY, 'towers', 7) + .setOrigin(0.5) + .setScrollFactor(0); + slot.add(towerBase); - const towerTop = this.scene.add.sprite(startX, startY, 'towers', TOWERS_CONFIG[type].spriteStart) - .setOrigin(0.5) - .setScrollFactor(0); - slot.add(towerTop); + const towerTop = this.scene.add.sprite(startX, startY, 'towers', TOWERS_CONFIG[type].spriteStart) + .setOrigin(0.5) + .setScrollFactor(0); + slot.add(towerTop); + } this.towerDisplay.add(slot); this.updateTowerAvail(); @@ -382,17 +394,31 @@ export class InterfaceManager { repeat: -1 }); - const towerBase = this.scene.add.sprite(0, 0, 'towers', 7) - .setOrigin(0.5) - .setScrollFactor(0) - .setTint(0xa32a00); - this.selectedTower.add(towerBase); - - const towerTop = this.scene.add.sprite(0, 0, 'towers', TOWERS_CONFIG[type].spriteStart) - .setOrigin(0.5) - .setScrollFactor(0) - .setTint(0xa32a00); - this.selectedTower.add(towerTop); + if (type === 'icbm') { + const towerBase = this.scene.add.sprite(0, 0, 'towers', TOWERS_CONFIG[type].spriteStart) + .setOrigin(0.5) + .setScrollFactor(0) + .setTint(0xa32a00); + this.selectedTower.add(towerBase); + + const towerTop = this.scene.add.sprite(0, 0, 'towers', TOWERS_CONFIG[type].spriteStart+3) + .setOrigin(0.5) + .setScrollFactor(0) + .setTint(0xa32a00); + this.selectedTower.add(towerTop); + } else { + const towerBase = this.scene.add.sprite(0, 0, 'towers', 7) + .setOrigin(0.5) + .setScrollFactor(0) + .setTint(0xa32a00); + this.selectedTower.add(towerBase); + + const towerTop = this.scene.add.sprite(0, 0, 'towers', TOWERS_CONFIG[type].spriteStart) + .setOrigin(0.5) + .setScrollFactor(0) + .setTint(0xa32a00); + this.selectedTower.add(towerTop); + } towerInteractive.on('pointerdown', () => { this.placeTower(type); diff --git a/src/support/towerAnims.js b/src/support/towerAnims.js new file mode 100644 index 0000000..62f97d3 --- /dev/null +++ b/src/support/towerAnims.js @@ -0,0 +1,76 @@ +export class TowerAnims { + + constructor(scene) { + this.scene = scene; + + this.createAnims(); + } + + createAnims() { + this.scene.anims.create({ + key: 'gunfire', + frames: this.scene.anims.generateFrameNumbers('ammo', { + start:0, + end:2 + }), + framerate: 15, + repeat: -1 + }); + this.scene.anims.create({ + key: 'gun-level1-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 1, + end: 0, + }), + frameRate: 15, + repeat: -1, + }); + this.scene.anims.create({ + key: 'gun-level2-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 3, + end: 2, + }), + frameRate: 15, + repeat: -1, + }); + this.scene.anims.create({ + key: 'gun-level3-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 5, + end: 4, + }), + frameRate: 15, + repeat: -1, + yoyo: true + }); + this.scene.anims.create({ + key: 'cannon-level1-fire', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 11, + end: 10 + }), + frameRate: 5, + repeat: 0 + }); + this.scene.anims.create({ + key: 'flamethrower', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 23, + end:25 + }), + framerate: 4, + repeat: -1 + }); + this.scene.anims.create({ + key: 'icbmExplosion', + frames: this.scene.anims.generateFrameNumbers('towers', { + start: 34, + end: 37, + framerate: 4, + }), + framerate: 4, + repeat: -1 + }) + } +} \ No newline at end of file diff --git a/src/support/towerConfig.js b/src/support/towerConfig.js index 9a654a1..612701b 100644 --- a/src/support/towerConfig.js +++ b/src/support/towerConfig.js @@ -9,7 +9,8 @@ export const TOWERS_CONFIG = { 'dmgHigh': 30, 'rate': 2000, 'duration': 500, - 'range': 300 + 'range': 300, + 'anim': 'gun-level1-fire' }, 'level2': { 'sprite': 2, @@ -18,7 +19,8 @@ export const TOWERS_CONFIG = { 'dmgHigh': 35, 'rate': 1500, 'duration': 750, - 'range': 350 + 'range': 350, + 'anim': 'gun-level2-fire' }, 'level3': { 'sprite': 4, @@ -27,7 +29,8 @@ export const TOWERS_CONFIG = { 'dmgHigh': 50, 'rate': 1000, 'duration': 1000, - 'range': 400 + 'range': 400, + 'anim': 'gun-level3-fire' } }, 'cannon': { @@ -42,6 +45,7 @@ export const TOWERS_CONFIG = { 'duration': 200, 'range': 400, 'aoe': 50, + 'anim': 'cannon-level1-fire' }, 'level2': { 'sprite': 12, @@ -52,6 +56,7 @@ export const TOWERS_CONFIG = { 'duration': 500, 'range': 450, 'aoe': 25, + 'anim': 'cannon-level1-fire' }, 'level3': { 'sprite': 14, @@ -62,6 +67,7 @@ export const TOWERS_CONFIG = { 'duration': 500, 'range': 500, 'aoe': 25, + 'anim': 'cannon-level1-fire' } }, 'flame': { @@ -76,6 +82,7 @@ export const TOWERS_CONFIG = { 'duration': 1000, 'range': 300, 'aoe': 100, + 'anim': 'flamethrower' }, 'level2': { 'sprite': 21, @@ -86,6 +93,7 @@ export const TOWERS_CONFIG = { 'duration': 1000, 'range': 350, 'aoe': 100, + 'anim': 'flamethrower' }, 'level3': { 'sprite': 22, @@ -96,6 +104,42 @@ export const TOWERS_CONFIG = { 'duration': 1000, 'range': 400, 'aoe': 100, + 'anim': 'flamethrower' + } + }, + 'icbm': { + 'name': 'ICBM Launcher', + 'cost': 500, + 'spriteStart': 30, + 'dmgType': 'aoe', + 'level1': { + 'dmgLow': 40, + 'dmgHigh': 50, + 'rate': 10000, + 'duration': 2000, + 'range': 800, + 'aoe': 250, + 'anim': 'none' + }, + 'level2': { + 'cost': 1000, + 'dmgLow': 40, + 'dmgHigh': 50, + 'rate': 8000, + 'duration': 2000, + 'range': 800, + 'aoe': 250, + 'anim': 'none' + }, + 'level3': { + 'cost': 2000, + 'dmgLow': 50, + 'dmgHigh': 60, + 'rate': 5000, + 'duration': 2000, + 'range': 800, + 'aoe': 250, + 'anim': 'none' } } } \ No newline at end of file diff --git a/src/support/towerManager.js b/src/support/towerManager.js index 41e54b3..d851d8c 100644 --- a/src/support/towerManager.js +++ b/src/support/towerManager.js @@ -1,5 +1,6 @@ import { ENEMIES_CONFIG } from './enemiesConfig.js'; import { TOWERS_CONFIG } from './towerConfig.js'; +import { TowerAnims } from './towerAnims.js'; export class TowerManager { @@ -10,7 +11,7 @@ export class TowerManager { this.selectedTower = null; this.upgradeCost = null; - this.createAnims(); + this.towerAnims = new TowerAnims(scene); // Add global click handler to close upgrade menu this.scene.input.on('pointerdown', (pointer) => { @@ -23,12 +24,23 @@ export class TowerManager { createTower(type, x, y) { const posX = this.scene.gridToLocation(x); const posY = this.scene.gridToLocation(y); + let towerBase; + let tower; - const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7).setDepth(10); - const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(11); - tower.props = { - 'type': type, - 'level': 1 + if (type === 'icbm') { + towerBase = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(10); + tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart+3).setDepth(11); + tower.props = { + 'type': type, + 'level': 1 + } + } else { + towerBase = this.scene.add.sprite(posX, posY, 'towers', 7).setDepth(10); + tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart).setDepth(11); + tower.props = { + 'type': type, + 'level': 1 + } } // Generate unique ID for enemy @@ -39,7 +51,6 @@ export class TowerManager { tower.setInteractive(); tower.on('pointerdown', () => { if (!this.selectedTower) { - console.log('CLICK'); this.upgradeMenu(tower); } }); @@ -188,11 +199,13 @@ export class TowerManager { if (this.following.hasOwnProperty(tower.id)) { this.scene.enemies.children.iterate((enemy) => { - if (this.following[tower.id] === enemy.props.id) { - // Rotate tower to face the enemy - const angle = Phaser.Math.Angle.Between(towerX, towerY, enemy.x, enemy.y); - tower.rotation = angle; - } + if (this.following[tower.id] === enemy.props.id + && type !== 'icbm') + { + // Rotate tower to face the enemy + const angle = Phaser.Math.Angle.Between(towerX, towerY, enemy.x, enemy.y); + tower.rotation = angle; + } }); } @@ -229,10 +242,14 @@ export class TowerManager { this.following[tower.id] = furthestEnemy.props.id; const dmgType = TOWERS_CONFIG[tower.props.type].dmgType; - if (dmgType === 'aoe') { - this.aoeAttackTarget(tower, furthestEnemy); + if (tower.props.type === 'icbm') { + this.icbmAttackTarget(tower, furthestEnemy); } else { - this.attackTarget(tower, furthestEnemy); + if (dmgType === 'aoe') { + this.aoeAttackTarget(tower, furthestEnemy); + } else { + this.attackTarget(tower, furthestEnemy); + } } this.lastFired[tower.id] = time; @@ -259,8 +276,11 @@ export class TowerManager { const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y); tower.rotation = angle; - - tower.play(`${type}-${level}-fire`, { 'duration': duration }); + + const vid = tower.play(config.anim); + this.scene.time.delayedCall(config.duration, () => { + vid.stop(); + }); // Calculate damage (random between low and high) const damage = Phaser.Math.Between(dmgLow, dmgHigh); @@ -362,6 +382,70 @@ export class TowerManager { }); } + icbmAttackTarget(tower, enemy) { + // Tower Properties + const type = tower.props.type; + const level = 'level'+tower.props.level; + const config = TOWERS_CONFIG[type][level]; + const duration = TOWERS_CONFIG[type][level].duration; + + if (!config) return; + + const dmgLow = config.dmgLow; + const dmgHigh = config.dmgHigh; + + const fireMissle = this.scene.add.sprite(tower.x, tower.y, 'towers', 33).setDepth(12); + tower.setVisible(false); + + this.scene.tweens.add({ + targets: fireMissle, + x: fireMissle.x, + y: fireMissle.y - 1200, + duration: 2000, + ease: 'Cubic.easeIn', + onComplete: () => { + fireMissle.setFlipY(true); + fireMissle.x = enemy.x; + this.scene.tweens.add({ + targets: fireMissle, + x: enemy.x, + y: enemy.y, + duration: 500, + ease: 'Cubic.easeIn', + onComplete: () => { + fireMissle.destroy(); + tower.setVisible(true); + const damage = Phaser.Math.Between(dmgLow, dmgHigh); + const aoeDistance = config.aoe; + const enemiesInRange = this.scene.enemies.getChildren().filter(e => { + return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= aoeDistance; + }); + const explosion = this.scene.add.sprite(enemy.x, enemy.y, 'towers', 34).setDepth(12); + explosion.play('icbmExplosion'); + this.scene.tweens.add({ + targets:explosion, + duration: 1000, + scale: 3, + alpha: .2, + onComplete: () => { + explosion.destroy(); + } + }); + enemiesInRange.forEach(targetEnemy => { + targetEnemy.props.health -= damage; + + if (targetEnemy.props.health > 0) { + this.createHealthBar(targetEnemy); + } else { + this.destroyEnemy(targetEnemy, tower); + } + }); + } + }); + } + }); + } + createHealthBar(enemy) { const barWidth = 30; const barHeight = 5; @@ -465,64 +549,4 @@ export class TowerManager { this.following[tower.id] = null; } - createAnims() { - this.scene.anims.create({ - key: 'gunfire', - frames: this.scene.anims.generateFrameNumbers('ammo', { - start:0, - end:2 - }), - framerate: 15, - repeat: -1 - }); - this.scene.anims.create({ - key: 'gun-level1-fire', - frames: this.scene.anims.generateFrameNumbers('towers', { - start: 0, - end: 1, - }), - frameRate: 15, - repeat: 6, - yoyo: true - }); - this.scene.anims.create({ - key: 'gun-level2-fire', - frames: this.scene.anims.generateFrameNumbers('towers', { - start: 2, - end: 3, - }), - frameRate: 15, - repeat: 10, - yoyo: true - }); - this.scene.anims.create({ - key: 'gun-level3-fire', - frames: this.scene.anims.generateFrameNumbers('towers', { - start: 4, - end: 5, - }), - frameRate: 15, - repeat: 15, - yoyo: true - }); - this.scene.anims.create({ - key: 'cannon-level1-fire', - frames: this.scene.anims.generateFrameNumbers('towers', { - start: 11, - end: 10 - }), - frameRate: 5, - repeat: 0 - }); - this.scene.anims.create({ - key: 'flamethrower', - frames: this.scene.anims.generateFrameNumbers('towers', { - start: 23, - end:25 - }), - framerate: 4, - repeat: -1 - }) - } - } \ No newline at end of file