Tower Defense Game - Major Update
- Refactored level system from Level1 to Level with improved camera controls (zoom/pan) - Enhanced tower management with new animations and firing mechanics - Updated enemy configurations with increased health, damage, and drop rates - Implemented comprehensive UI interface with tower selection and resource management - Added wave progression system with multiple enemy types and spawn scheduling - Improved visual effects including glowing cores, particle effects, and animated gold drops - Integrated new assets including font files, spritesheets, and interface elements This update transforms the basic tower defense game into a more polished experience with enhanced gameplay mechanics, better visuals, and improved user interface.
|
After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 887 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 192 KiB |
|
|
@ -0,0 +1,111 @@
|
|||
import { WaveManager } from '../support/waveManager.js';
|
||||
import { TowerManager } from '../support/towerManager.js';
|
||||
|
||||
export class Level extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'Level' });
|
||||
}
|
||||
|
||||
init(data) {
|
||||
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.tilemapTiledJSON('level1', 'assets/level1.json');
|
||||
this.load.image('terrain', 'assets/terrain.png');
|
||||
this.load.spritesheet('basic-enemies', 'assets/basic-enemies.png', {
|
||||
frameWidth: 50,
|
||||
frameHeight: 50
|
||||
});
|
||||
this.load.spritesheet('towers', 'assets/towers.png', {
|
||||
frameHeight: 150,
|
||||
frameWidth: 150
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
this.levelMap = this.make.tilemap({ key: 'level1' });
|
||||
const terrainTiles = this.levelMap.addTilesetImage('terrain', 'terrain');
|
||||
this.mainLayer = this.levelMap.createLayer('main', terrainTiles)
|
||||
.setCollisionByProperty({ collides: true });
|
||||
this.platformsLayer = this.levelMap.createLayer('platforms', terrainTiles);
|
||||
|
||||
// Add camera zoom functionality
|
||||
this.cameras.main.setBounds(0, 0, 2000, 2000);
|
||||
this.addControls();
|
||||
|
||||
this.waveManager = new WaveManager(this, 1, 1);
|
||||
this.towerManager = new TowerManager(this);
|
||||
|
||||
this.scene.launch('UIScene');
|
||||
this.UIScene = this.scene.get('UIScene');
|
||||
|
||||
this.enemies = this.physics.add.group();
|
||||
this.towers = this.physics.add.group();
|
||||
|
||||
this.towerManager.createTower('gun', 2, 1);
|
||||
this.towerManager.createTower('gun', 4, 2);
|
||||
|
||||
this.physics.add.collider(this.enemies, this.mainLayer);
|
||||
this.physics.add.collider(this.enemies, this.platformsLayer);
|
||||
}
|
||||
|
||||
gridToLocation(num, offset = 0) {
|
||||
return num * 200 + 100 + offset;
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
this.waveManager.update(time, delta);
|
||||
this.towerManager.update(time, delta);
|
||||
}
|
||||
|
||||
addControls() {
|
||||
this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY) => {
|
||||
const zoomSpeed = 0.1;
|
||||
if (deltaY < 0) {
|
||||
// Zoom in
|
||||
this.cameras.main.zoom += zoomSpeed;
|
||||
} else if (deltaY > 0) {
|
||||
// Zoom out
|
||||
this.cameras.main.zoom -= zoomSpeed;
|
||||
}
|
||||
|
||||
// Limit zoom range to prevent extreme zoom levels
|
||||
this.cameras.main.zoom = Phaser.Math.Clamp(this.cameras.main.zoom, 0.5, 2);
|
||||
|
||||
// Zoom toward mouse position
|
||||
const worldPoint = this.input.activePointer.positionToCamera(this.cameras.main);
|
||||
this.cameras.main.centerOn(worldPoint.x, worldPoint.y);
|
||||
});
|
||||
|
||||
// Add camera panning functionality
|
||||
this.input.on('pointerdown', (pointer) => {
|
||||
if (pointer.button === 0) { // Left mouse button
|
||||
this.isPanning = true;
|
||||
this.panStartX = pointer.x;
|
||||
this.panStartY = pointer.y;
|
||||
}
|
||||
});
|
||||
|
||||
this.input.on('pointermove', (pointer) => {
|
||||
if (this.isPanning && pointer.isDown) {
|
||||
const dx = pointer.x - this.panStartX;
|
||||
const dy = pointer.y - this.panStartY;
|
||||
|
||||
// Pan the camera
|
||||
this.cameras.main.scrollX -= dx;
|
||||
this.cameras.main.scrollY -= dy;
|
||||
|
||||
// Update start position for next move
|
||||
this.panStartX = pointer.x;
|
||||
this.panStartY = pointer.y;
|
||||
}
|
||||
});
|
||||
|
||||
this.input.on('pointerup', (pointer) => {
|
||||
if (pointer.button === 0) { // Left mouse button
|
||||
this.isPanning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
import { WaveManager } from '../support/waveManager.js';
|
||||
import { TowerManager } from '../support/towerManager.js';
|
||||
|
||||
export class Level1 extends Phaser.Scene {
|
||||
constructor() {
|
||||
super({ key: 'Level1' });
|
||||
}
|
||||
|
||||
init(data) {
|
||||
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.tilemapTiledJSON('level1', 'assets/level1.json');
|
||||
this.load.image('terrain', 'assets/terrain.png');
|
||||
this.load.spritesheet('basic-enemies', 'assets/basic-enemies.png', {
|
||||
frameWidth: 50,
|
||||
frameHeight: 50
|
||||
});
|
||||
this.load.spritesheet('towers', 'assets/towers.png', {
|
||||
frameHeight: 100,
|
||||
frameWidth: 100
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
this.levelMap = this.make.tilemap({ key: 'level1' });
|
||||
const terrainTiles = this.levelMap.addTilesetImage('terrain', 'terrain');
|
||||
this.mainLayer = this.levelMap.createLayer('main', terrainTiles)
|
||||
.setCollisionByProperty({ collides: true });
|
||||
this.platformsLayer = this.levelMap.createLayer('platforms', terrainTiles);
|
||||
|
||||
this.waveManager = new WaveManager(this, 1, 1);
|
||||
this.towerManager = new TowerManager(this);
|
||||
|
||||
this.enemies = this.physics.add.group();
|
||||
this.towers = this.physics.add.group();
|
||||
|
||||
this.towerManager.createTower('gun', 2, 1);
|
||||
this.towerManager.createTower('gun', 4, 2);
|
||||
|
||||
this.physics.add.collider(this.enemies, this.mainLayer);
|
||||
this.physics.add.collider(this.enemies, this.platformsLayer);
|
||||
}
|
||||
|
||||
gridToLocation(num, offset = 0) {
|
||||
return num * 200 + 100 + offset;
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
this.waveManager.update(time, delta);
|
||||
this.towerManager.update(time, delta);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { Level1 } from './levels/level1.js';
|
||||
import { Level } from './levels/level.js';
|
||||
import { UIScene } from './uiScene.js';
|
||||
|
||||
const GAME_CONFIG = {
|
||||
type: Phaser.AUTO,
|
||||
|
|
@ -12,7 +13,8 @@ const GAME_CONFIG = {
|
|||
parent: 'game-container',
|
||||
backgroundColor: '#bb7432ff',
|
||||
scene: [
|
||||
Level1
|
||||
Level,
|
||||
UIScene
|
||||
],
|
||||
physics: {
|
||||
default: 'arcade',
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ export const ENEMIES_CONFIG = {
|
|||
'dropHigh': 2
|
||||
},
|
||||
'basic2': {
|
||||
'spread': 0,
|
||||
'health': 50,
|
||||
'fullHealth': 50,
|
||||
'spread': 25,
|
||||
'health': 100,
|
||||
'fullHealth': 100,
|
||||
'speedLow': 45,
|
||||
'speedHigh': 55,
|
||||
'spriteStart': 0,
|
||||
'spriteStart': 10,
|
||||
'spriteSheet': 'basic-enemies',
|
||||
'dropLow': 1,
|
||||
'dropHigh': 2
|
||||
'dropLow': 5,
|
||||
'dropHigh': 10
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
import { TOWERS_CONFIG } from './towerConfig.js';
|
||||
|
||||
export class InterfaceManager {
|
||||
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.gold = 100;
|
||||
this.cores = 20;
|
||||
this.interfaceOpen = false;
|
||||
|
||||
this.paintInterface();
|
||||
}
|
||||
|
||||
paintInterface() {
|
||||
this.intTop = this.scene.add.image(1300, -50, 'intTop').setOrigin(0.5).setScrollFactor(0);
|
||||
this.intCore = this.scene.add.sprite(1320, 60, 'towers', 9).setScale(.50).setOrigin(0.5).setScrollFactor(0).setAlpha(0);
|
||||
|
||||
// Add gold text display
|
||||
this.goldText = this.scene.add.text(1200, 25, `${this.gold}`, {
|
||||
fontFamily: 'neuropol, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ffd900ff',
|
||||
stroke: '#c48f00ff',
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 5,
|
||||
offsetY: 5,
|
||||
color: '#000000',
|
||||
blur: 5,
|
||||
stroke: false,
|
||||
fill: true
|
||||
}
|
||||
}).setScrollFactor(0).setAlpha(0);
|
||||
|
||||
this.coreText = this.scene.add.text(1350, 25, `${this.cores}`, {
|
||||
fontFamily: 'neuropol, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#00eeffff',
|
||||
stroke: '#2a338aff',
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 5,
|
||||
offsetY: 5,
|
||||
color: '#000000',
|
||||
blur: 5,
|
||||
stroke: false,
|
||||
fill: true
|
||||
}
|
||||
}).setScrollFactor(0).setAlpha(0);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.intTop,
|
||||
y: 50,
|
||||
duration: 2000,
|
||||
delay: 2000,
|
||||
ease: 'Back.easeOut',
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: [this.coreText, this.goldText, this.intCore],
|
||||
angle: 360,
|
||||
alpha: 1,
|
||||
duration: 1000,
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: this.intCore,
|
||||
angle: 360,
|
||||
duration: 5000,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.intMain = this.scene.add.image(800, 1300, 'intMain').setOrigin(0.5).setScrollFactor(0);
|
||||
// NOTE ^^ Fully up is at Y 475
|
||||
|
||||
// Add gold text display
|
||||
this.interfaceText = this.scene.add.text(800, 850, `Click to Open`, {
|
||||
fontFamily: 'neuropol, arial',
|
||||
fontSize: '36px',
|
||||
fill: '#ff5353ff',
|
||||
stroke: '#581a1aff',
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 5,
|
||||
offsetY: 5,
|
||||
color: '#000000',
|
||||
blur: 5,
|
||||
stroke: false,
|
||||
fill: true
|
||||
}
|
||||
}).setOrigin(0.5).setScrollFactor(0).setAlpha(0);
|
||||
|
||||
this.upLeft = this.scene.add.image(650, 850, 'redArrow').setOrigin(0.5).setScale(0.25).setAlpha(0);
|
||||
this.upRight = this.scene.add.image(950, 850, 'redArrow').setOrigin(0.5).setScale(0.25).setAlpha(0);
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.intMain,
|
||||
y: 1150,
|
||||
duration: 2000,
|
||||
delay: 2000,
|
||||
ease: 'Back.easeOut',
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: [this.interfaceText, this.upLeft, this.upRight],
|
||||
alpha: 1,
|
||||
duration: 1000,
|
||||
onComplete: () => {
|
||||
this.scene.tweens.add({
|
||||
targets: [this.upLeft, this.upRight],
|
||||
y: { from: 860, to: 840},
|
||||
duration: 2000,
|
||||
repeat: -1
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.interfaceUp = this.scene.add.rectangle(800, 840, 800, 120, 0x000000, 0).setOrigin(0.5);
|
||||
this.interfaceUp.setInteractive();
|
||||
this.interfaceUp.on('pointerdown', () => {
|
||||
if (!this.interfaceOpen) {
|
||||
this.openInterface();
|
||||
this.interfaceOpen = true;
|
||||
// Disable further clicks
|
||||
this.interfaceUp.disableInteractive();
|
||||
} else {
|
||||
this.closeInterface();
|
||||
this.interfaceOpen = false;
|
||||
this.interfaceUp.disableInteractive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openInterface() {
|
||||
this.upLeft.setAlpha(0).setRotation(Math.PI);
|
||||
this.upRight.setAlpha(0).setRotation(Math.PI);
|
||||
this.interfaceText.setAlpha(0).setText('Click to Close');
|
||||
this.scene.tweens.add({
|
||||
targets: this.intMain,
|
||||
y: {from: 1150, to: 475},
|
||||
duration: 500,
|
||||
ease: 'Quant',
|
||||
onComplete: () => {
|
||||
this.upLeft.setAlpha(1);
|
||||
this.upRight.setAlpha(1);
|
||||
this.interfaceText.setAlpha(1);
|
||||
this.interfaceUp.setInteractive();
|
||||
this.showTowers();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closeInterface() {
|
||||
this.upLeft.setAlpha(0).setRotation(0);
|
||||
this.upRight.setAlpha(0).setRotation(0);
|
||||
this.interfaceText.setAlpha(0).setText('Click to Open');
|
||||
this.towerDisplay.destroy();
|
||||
this.scene.tweens.add({
|
||||
targets: this.intMain,
|
||||
y: {from: 475, to: 1150},
|
||||
duration: 500,
|
||||
ease: 'Quant',
|
||||
onComplete: () => {
|
||||
this.upLeft.setAlpha(1);
|
||||
this.upRight.setAlpha(1);
|
||||
this.interfaceText.setAlpha(1);
|
||||
this.interfaceUp.setInteractive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showTowers() {
|
||||
this.towerDisplay = this.scene.add.container();
|
||||
this.gridAdd(0, 0, 'Gatlin Gun', 100, 'gun');
|
||||
this.gridAdd(0, 1, 'Flamethrower', 150, 'gun');
|
||||
this.gridAdd(1, 0, 'Laser', 200, 'gun');
|
||||
this.gridAdd(1, 1, 'Cannon', 200, 'gun');
|
||||
}
|
||||
|
||||
gridAdd(x, y, text, cost, type) {
|
||||
const xAdd = 325;
|
||||
const yAdd = 375;
|
||||
const startX = (x * 225) + xAdd;
|
||||
const startY = (y * 225) + yAdd;
|
||||
|
||||
const slot = this.scene.add.container();
|
||||
slot.props = {
|
||||
cost: cost
|
||||
}
|
||||
|
||||
const slotBack = this.scene.add.rectangle(startX, startY, 200, 200, 0xAAAAAA, 0.5)
|
||||
.setOrigin(0.5)
|
||||
.setScrollFactor(0);
|
||||
slot.add(slotBack);
|
||||
slotBack.setInteractive();
|
||||
|
||||
// Add gold text display
|
||||
const slotText = this.scene.add.text(startX-95, startY+75, `${text}`, {
|
||||
fontFamily: 'neuropol, arial',
|
||||
fontSize: '25px',
|
||||
fill: '#ffffffff',
|
||||
stroke: '#5f4719ff',
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 2,
|
||||
offsetY: 2,
|
||||
color: '#000000',
|
||||
blur: 5,
|
||||
stroke: false,
|
||||
fill: true
|
||||
}
|
||||
}).setOrigin(0).setScrollFactor(0);
|
||||
slot.add(slotText);
|
||||
|
||||
// Add gold text display
|
||||
const slotCost = this.scene.add.text(startX+100, startY-100, `Gold: ${cost}`, {
|
||||
fontFamily: 'neuropol, arial',
|
||||
fontSize: '25px',
|
||||
fill: '#ffd900ff',
|
||||
stroke: '#c48f00ff',
|
||||
strokeThickness: 2,
|
||||
shadow: {
|
||||
offsetX: 2,
|
||||
offsetY: 2,
|
||||
color: '#000000',
|
||||
blur: 5,
|
||||
stroke: false,
|
||||
fill: true
|
||||
}
|
||||
}).setOrigin(1, 0).setScrollFactor(0);
|
||||
slot.add(slotCost);
|
||||
|
||||
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);
|
||||
|
||||
this.towerDisplay.add(slot);
|
||||
this.updateTowerAvail();
|
||||
}
|
||||
|
||||
updateTowerAvail() {
|
||||
if (this.interfaceOpen === true && this.towerDisplay) {
|
||||
this.towerDisplay.iterate((slot) => {
|
||||
// Not Enough Gold
|
||||
if (slot.props.cost > this.gold) {
|
||||
slot.iterate((child) => {
|
||||
if (child.type === 'Rectangle') {
|
||||
child.disableInteractive();
|
||||
child.setFillStyle(0x333333);
|
||||
} else {
|
||||
child.setTint(0x888888);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Is Enough Gold
|
||||
else {
|
||||
slot.iterate((child) => {
|
||||
if (child.type === 'Rectangle') {
|
||||
child.setInteractive();
|
||||
child.setFillStyle(0xAAAAAA);
|
||||
} else {
|
||||
child.setTint(0xFFFFFF);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -9,15 +9,15 @@ export const TOWERS_CONFIG = {
|
|||
'range': 275
|
||||
},
|
||||
'level2': {
|
||||
'dmgLow': 12,
|
||||
'dmgHigh': 33,
|
||||
'dmgLow': 15,
|
||||
'dmgHigh': 35,
|
||||
'rate': 1500,
|
||||
'duration': 750,
|
||||
'range': 300
|
||||
},
|
||||
'level3': {
|
||||
'dmgLow': 15,
|
||||
'dmgHigh': 35,
|
||||
'dmgLow': 25,
|
||||
'dmgHigh': 50,
|
||||
'rate': 1000,
|
||||
'duration': 1000,
|
||||
'range': 325
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export class TowerManager {
|
|||
const posX = this.scene.gridToLocation(x);
|
||||
const posY = this.scene.gridToLocation(y);
|
||||
|
||||
const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7);
|
||||
const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart);
|
||||
tower.props = {
|
||||
'type': type,
|
||||
|
|
@ -25,7 +26,6 @@ export class TowerManager {
|
|||
const uniqueId = Phaser.Math.Between(100000, 999999);
|
||||
tower.id = uniqueId;
|
||||
|
||||
tower.setScale(1.5);
|
||||
this.scene.towers.add(tower);
|
||||
|
||||
// Draw range circle
|
||||
|
|
@ -44,8 +44,27 @@ export class TowerManager {
|
|||
end: 1,
|
||||
}),
|
||||
frameRate: 15,
|
||||
duration: 500,
|
||||
repeat: 1,
|
||||
repeat: 5,
|
||||
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
|
||||
});
|
||||
}
|
||||
|
|
@ -102,7 +121,7 @@ export class TowerManager {
|
|||
return current.props.distanceTraveled > max.props.distanceTraveled ? current : max;
|
||||
});
|
||||
|
||||
this.followTarget(tower, furthestEnemy);
|
||||
this.following[tower.id] = furthestEnemy.props.id;
|
||||
this.attackTarget(tower, furthestEnemy);
|
||||
|
||||
this.lastFired[tower.id] = time;
|
||||
|
|
@ -110,11 +129,6 @@ export class TowerManager {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
followTarget(tower, enemy) {
|
||||
this.following[tower.id] = enemy.props.id;
|
||||
}
|
||||
|
||||
attackTarget(tower, enemy) {
|
||||
// Tower Properties
|
||||
const type = tower.props.type;
|
||||
|
|
@ -126,7 +140,10 @@ export class TowerManager {
|
|||
const dmgLow = config.dmgLow;
|
||||
const dmgHigh = config.dmgHigh;
|
||||
|
||||
tower.play(`${type}-${level}-fire`, true);
|
||||
const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
|
||||
tower.rotation = angle;
|
||||
|
||||
tower.play(`${type}-${level}-fire`, { duration: 500 });
|
||||
|
||||
// Calculate damage (random between low and high)
|
||||
const damage = Phaser.Math.Between(dmgLow, dmgHigh);
|
||||
|
|
@ -152,8 +169,8 @@ export class TowerManager {
|
|||
// Create health bar container
|
||||
const healthBar = this.scene.add.container(enemy.x, barY);
|
||||
|
||||
// Background bar (gray)
|
||||
const background = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0x808080);
|
||||
// Background bar (red)
|
||||
const background = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0xe83829);
|
||||
|
||||
// Health fill (green)
|
||||
const healthFill = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0x00ff00);
|
||||
|
|
@ -185,7 +202,43 @@ export class TowerManager {
|
|||
const type = enemy.props.type;
|
||||
const sprite = enemy.texture.key;
|
||||
const firstFrame = enemy.texture.firstFrame;
|
||||
const id = enemy.props.id;
|
||||
const velocX = enemy.body.velocity.x;
|
||||
const velocY = enemy.body.velocity.y;
|
||||
|
||||
// Add some Gold
|
||||
const drop = Phaser.Math.Between(ENEMIES_CONFIG[type].dropLow, ENEMIES_CONFIG[type].dropHigh) * 5;
|
||||
|
||||
// Show the Gold
|
||||
const cashDrop = this.scene.add.image(dieX, dieY, 'gold').setScale(0.5);
|
||||
const angle = Phaser.Math.Angle.Between(tower.x, tower.y, dieX, dieY);
|
||||
|
||||
// Calculate end position (100px away from original position in the calculated direction)
|
||||
const endX = dieX + Math.cos(angle) * 50;
|
||||
const endY = dieY + Math.sin(angle) * 50;
|
||||
|
||||
// Animate the cash drop moving to the new position
|
||||
this.scene.tweens.add({
|
||||
targets: cashDrop,
|
||||
x: endX,
|
||||
y: endY,
|
||||
duration: 500,
|
||||
ease: 'Bounce',
|
||||
onComplete: () => {
|
||||
cashDrop.postFX.addGlow();
|
||||
this.scene.tweens.add({
|
||||
targets: cashDrop,
|
||||
x: 1300,
|
||||
y: 100,
|
||||
alpha: 0,
|
||||
duration: 500,
|
||||
onComplete: () => {
|
||||
cashDrop.destroy();
|
||||
this.scene.UIScene.addGold(drop);
|
||||
this.scene.UIScene.interfaceManager.updateTowerAvail();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
enemy.destroy();
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@ export const WAVE_CONFIG = {
|
|||
},
|
||||
2: {
|
||||
begin: 15,
|
||||
basic1: 20
|
||||
basic1: 5,
|
||||
basic2: 2
|
||||
},
|
||||
3: {
|
||||
begin: 30,
|
||||
basic1: 5
|
||||
basic1: 4,
|
||||
basic2: 3
|
||||
}
|
||||
},
|
||||
// Wave
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export class WaveManager {
|
|||
|
||||
this.waveTimer = 0;
|
||||
this.waveScheduleStartTime();
|
||||
this.placeCore();
|
||||
}
|
||||
|
||||
waveScheduleStartTime() {
|
||||
|
|
@ -33,6 +34,28 @@ export class WaveManager {
|
|||
this.waveScheduleStartTime();
|
||||
}
|
||||
|
||||
placeCore() {
|
||||
this.scene.add.sprite(this.scene.gridToLocation(this.endX), this.scene.gridToLocation(this.endY), 'towers', 8);
|
||||
const rotatingCore = this.scene.add.sprite(this.scene.gridToLocation(this.endX), this.scene.gridToLocation(this.endY), 'towers', 9);
|
||||
const glowingCore = this.scene.add.sprite(this.scene.gridToLocation(this.endX), this.scene.gridToLocation(this.endY), 'towers', 19).setAlpha(0);
|
||||
this.scene.tweens.add({
|
||||
targets: rotatingCore,
|
||||
duration: 5000,
|
||||
angle: 360,
|
||||
alpha: [0.5, 1, 0.5],
|
||||
repeat: -1,
|
||||
yoyo: false
|
||||
});
|
||||
this.scene.tweens.add({
|
||||
targets: glowingCore,
|
||||
duration: 5000,
|
||||
alpha: .4,
|
||||
scale: 2,
|
||||
repeat: -1,
|
||||
yoyo: true
|
||||
});
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
// Handle Enemy Pathing
|
||||
this.scene.enemies.children.iterate((enemy) => {
|
||||
|
|
@ -149,6 +172,12 @@ export class WaveManager {
|
|||
const enemy = new Enemies(this.scene, 'basic1', this.spawnX, this.spawnY, this.path);
|
||||
}
|
||||
}
|
||||
if (this.scheduleInfo.hasOwnProperty('basic2')) {
|
||||
console.log('Spawn',this.scheduleInfo.basic2,'Basic2 enemies');
|
||||
for (let e = 0; e < this.scheduleInfo.basic2; e++) {
|
||||
const enemy = new Enemies(this.scene, 'basic2', this.spawnX, this.spawnY, this.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
makePath() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import { InterfaceManager } from './support/interfaceManager.js';
|
||||
|
||||
export class UIScene extends Phaser.Scene {
|
||||
|
||||
constructor() {
|
||||
super({ key: 'UIScene' });
|
||||
}
|
||||
|
||||
init(data) {
|
||||
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.font('neuropol', 'assets/NEUROPOL.ttf');
|
||||
this.load.image('intMain', 'assets/intMain.png');
|
||||
this.load.image('redArrow', 'assets/redArrow.png');
|
||||
this.load.image('intTop', 'assets/intTop.png');
|
||||
this.load.image('gold', 'assets/gold.png');
|
||||
}
|
||||
|
||||
create() {
|
||||
this.interfaceManager = new InterfaceManager(this);
|
||||
this.levelScene = this.scene.get('Level');
|
||||
this.cameras.main.setBounds(0, 0, 1600, 900);
|
||||
}
|
||||
|
||||
update(time, delta) {
|
||||
this.interfaceManager.update(time, delta);
|
||||
}
|
||||
|
||||
addGold(amount) {
|
||||
this.interfaceManager.gold += amount;
|
||||
this.updateGold();
|
||||
}
|
||||
|
||||
updateGold() {
|
||||
this.interfaceManager.goldText.setText(`${this.interfaceManager.gold}`);
|
||||
}
|
||||
}
|
||||