Add Flak Cannon tower with AOE functionality, upgrade animations, and sound effects
This commit introduces a new Flak Cannon tower type with: - Complete tower configuration including cost, damage stats, and range for all 3 levels - Visual upgrades with rotating mid-sections for level 2/3 - Sound effects (flak.mp3) for firing and explosions - AOE shot mechanics that fire multiple projectiles in a spread pattern - Rotation handling to prevent conflicts with tower aiming logic The flak cannon uses a unique firing pattern where it shoots multiple projectiles in different directions within its AOE radius, creating an explosion effect. The upgrade system adds visual elements like rotating mid-sections and changes sprite textures for each level.
This commit is contained in:
parent
f843aee85f
commit
7976c35bfd
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 656 KiB After Width: | Height: | Size: 824 KiB |
Binary file not shown.
|
|
@ -17,10 +17,10 @@ export class Level extends Phaser.Scene {
|
|||
}
|
||||
|
||||
init(data) {
|
||||
console.log('Selected level:', data.level);
|
||||
console.log('Player name:', data.playerName);
|
||||
this.level = data.level;
|
||||
this.playerName = data.playerName;
|
||||
if (data.level && data.playerName) {
|
||||
this.level = data.level;
|
||||
this.playerName = data.playerName;
|
||||
}
|
||||
}
|
||||
|
||||
preload() {
|
||||
|
|
@ -61,6 +61,7 @@ export class Level extends Phaser.Scene {
|
|||
this.load.audio('portal', 'assets/sounds/portal.mp3');
|
||||
this.load.audio('laser', 'assets/sounds/laser.mp3');
|
||||
this.load.audio('upgrade', 'assets/sounds/upgrade.mp3');
|
||||
this.load.audio('flak', 'assets/sounds/flak.mp3');
|
||||
|
||||
// Music
|
||||
this.load.audio('level-bg1', 'assets/music/level-bg1.mp3');
|
||||
|
|
|
|||
|
|
@ -254,8 +254,8 @@ export class InterfaceManager {
|
|||
const tower = TOWERS_CONFIG[type];
|
||||
this.gridAdd(x, y, tower.name, tower.cost, type);
|
||||
x++;
|
||||
if (x > 6) {
|
||||
y = 2;
|
||||
if (x > 4) {
|
||||
y = 1;
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,5 +175,39 @@ export const TOWERS_CONFIG = {
|
|||
'aoe': 225,
|
||||
'anim': 'none'
|
||||
}
|
||||
},'flak': {
|
||||
'name': 'Flak Cannon',
|
||||
'cost': 700,
|
||||
'spriteStart': 50,
|
||||
'dmgType': 'aoe',
|
||||
'level1': {
|
||||
'dmgLow': 5,
|
||||
'dmgHigh': 10,
|
||||
'rate': 350,
|
||||
'duration': 350,
|
||||
'range': 300,
|
||||
'aoe': 300,
|
||||
'anim': 'none'
|
||||
},
|
||||
'level2': {
|
||||
'cost': 1400,
|
||||
'dmgLow': 6,
|
||||
'dmgHigh': 11,
|
||||
'rate': 300,
|
||||
'duration': 300,
|
||||
'range': 350,
|
||||
'aoe': 350,
|
||||
'anim': 'none'
|
||||
},
|
||||
'level3': {
|
||||
'cost': 2800,
|
||||
'dmgLow': 7,
|
||||
'dmgHigh': 12,
|
||||
'rate': 250,
|
||||
'duration': 250,
|
||||
'range': 375,
|
||||
'aoe': 375,
|
||||
'anim': 'none'
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -36,6 +36,15 @@ export class TowerManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (type === 'flak') {
|
||||
this.scene.tweens.add({
|
||||
targets: tower,
|
||||
angle: 360,
|
||||
duration: 10000,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
|
||||
tower.towerBase = towerBase;
|
||||
|
||||
// Generate unique ID for enemy
|
||||
|
|
@ -189,6 +198,27 @@ export class TowerManager {
|
|||
this.scene.sound.play('upgrade');
|
||||
if (tower.props.type === 'icbm') {
|
||||
tower.towerBase.setTexture('towers', 29+tower.props.level);
|
||||
} else if (tower.props.type === 'flak') {
|
||||
if (newLevel === 'level2') {
|
||||
const towerMid = this.scene.add.sprite(tower.x, tower.y, 'towers', 51).setDepth(12);
|
||||
this.scene.tweens.add({
|
||||
targets: towerMid,
|
||||
angle: -360,
|
||||
duration: 12000,
|
||||
repeat: -1
|
||||
});
|
||||
tower.towerMid = towerMid;
|
||||
}
|
||||
if (newLevel === 'level3') {
|
||||
const towerMid = this.scene.add.sprite(tower.x, tower.y, 'towers', 52).setDepth(13);
|
||||
this.scene.tweens.add({
|
||||
targets: towerMid,
|
||||
angle: 360,
|
||||
duration: 6000,
|
||||
repeat: -1
|
||||
});
|
||||
tower.towerMid = towerMid;
|
||||
}
|
||||
} else {
|
||||
tower.setTexture('towers', TOWERS_CONFIG[tower.props.type][newLevel].sprite);
|
||||
}
|
||||
|
|
@ -209,7 +239,7 @@ export class TowerManager {
|
|||
if (this.following.hasOwnProperty(tower.id)) {
|
||||
this.scene.enemies.children.iterate((enemy) => {
|
||||
if (this.following[tower.id] === enemy.props.id
|
||||
&& type !== 'icbm')
|
||||
&& type !== 'icbm' && type !=='flak')
|
||||
{
|
||||
// Rotate tower to face the enemy
|
||||
const angle = Phaser.Math.Angle.Between(towerX, towerY, enemy.x, enemy.y);
|
||||
|
|
@ -368,7 +398,9 @@ export class TowerManager {
|
|||
const dmgHigh = config.dmgHigh;
|
||||
|
||||
const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
|
||||
tower.rotation = angle;
|
||||
if (type !== 'flak') {
|
||||
tower.rotation = angle;
|
||||
}
|
||||
|
||||
if (type === 'cannon') {
|
||||
this.scene.sound.play('cannon');
|
||||
|
|
@ -416,15 +448,51 @@ export class TowerManager {
|
|||
|
||||
}
|
||||
|
||||
if (type === 'flak') {
|
||||
const shotAmt = Math.floor((400 - config.rate) / 50);
|
||||
for (let i = 1; i <= shotAmt; i++) {
|
||||
const shotAngle = Phaser.Math.Between(0, 360);
|
||||
const shotDistance = Phaser.Math.Between(0, config.aoe);
|
||||
const shotX = tower.x + Math.cos(shotAngle) * shotDistance;
|
||||
const shotY = tower.y + Math.sin(shotAngle) * shotDistance;
|
||||
const shotType = Phaser.Math.Between(53,55);
|
||||
const shotDelay = i*100;
|
||||
this.scene.time.delayedCall(shotDelay, () => {
|
||||
const shot = this.scene.add.sprite(tower.x, tower.y, 'towers', shotType);
|
||||
this.scene.tweens.add({
|
||||
targets: shot,
|
||||
x: shotX,
|
||||
y: shotY,
|
||||
angle: Phaser.Math.Between(0, 180),
|
||||
duration: 2000,
|
||||
onComplete: () => {
|
||||
// Limit the times this sound plays to not overwhelm speakers
|
||||
if (i === 1) {
|
||||
this.scene.sound.play('flak');
|
||||
}
|
||||
shot.setTexture('towers', Phaser.Math.Between(56,57)).setScale(.4).setAlpha(.8);
|
||||
this.scene.tweens.add({
|
||||
targets: shot,
|
||||
angle: Phaser.Math.Between(-90, 90),
|
||||
alpha: .3,
|
||||
scale: 1,
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
shot.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate damage (random between low and high)
|
||||
const damage = Phaser.Math.Between(dmgLow, dmgHigh);
|
||||
|
||||
// Get AOE distance
|
||||
const aoeDistance = config.aoe;
|
||||
|
||||
// Apply damage to all enemies in range
|
||||
const enemiesInRange = this.scene.enemies.getChildren().filter(e => {
|
||||
return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= aoeDistance;
|
||||
return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= config.aoe;
|
||||
});
|
||||
|
||||
enemiesInRange.forEach(targetEnemy => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue