diff --git a/assets/Data/GameSettings.json b/assets/Data/GameSettings.json index 7c39dad..d672ee0 100644 --- a/assets/Data/GameSettings.json +++ b/assets/Data/GameSettings.json @@ -75,42 +75,60 @@ "moveType": "Follow", "health": 3, "damage": 1, - "speed": 60 + "speed": 60, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 }, { "id": "CircleEnemy", "moveType": "Follow", "health": 10, "damage": 1, - "speed": 25 + "speed": 25, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 }, { "id": "WaveEnemy", "moveType": "Launch", "health": 1, "damage": 2, - "speed": 390 + "speed": 390, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 }, { "id": "WaveEnemyArmor", "moveType": "Launch", "health": 7, "damage": 3, - "speed": 70 + "speed": 70, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 }, { "id": "BasicBoss", "moveType": "Follow", "health": 12, "damage": 2, - "speed": 65 + "speed": 65, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 }, { "id": "BasicCheetah", "moveType": "PeriodicFollow", "health": 5, "damage": 2, - "speed": 140 + "speed": 140, + "lifetime": -1, + "xpReward": 0, + "goldReward": 0 } ], "individualEnemySpawners": [ diff --git a/assets/Scripts/Game/Data/GameSettings.ts b/assets/Scripts/Game/Data/GameSettings.ts index 7d9b6f7..1f5039c 100644 --- a/assets/Scripts/Game/Data/GameSettings.ts +++ b/assets/Scripts/Game/Data/GameSettings.ts @@ -76,7 +76,6 @@ export class GeneralEnemySpawnerSettings { export class WaveEnemySpawnerSettings { public common = new GeneralEnemySpawnerSettings(); public enemiesToSpawn = 0; - public waveLifetime = 0; } export class CircularEnemySpawnerSettings { @@ -94,4 +93,7 @@ export class EnemySettings { public health = 0; public damage = 0; public speed = 0; + public lifetime = 0; + public xpReward = 0; + public goldReward = 0; } diff --git a/assets/Scripts/Game/Unit/Enemy/Enemy.ts b/assets/Scripts/Game/Unit/Enemy/Enemy.ts index e7285f6..63b9aa7 100644 --- a/assets/Scripts/Game/Unit/Enemy/Enemy.ts +++ b/assets/Scripts/Game/Unit/Enemy/Enemy.ts @@ -1,4 +1,5 @@ import { BoxCollider2D, Component, randomRange, Vec3, _decorator } from "cc"; +import { time } from "console"; import { ISignal } from "../../../Services/EventSystem/ISignal"; import { Signal } from "../../../Services/EventSystem/Signal"; import { EnemySettings } from "../../Data/GameSettings"; @@ -12,12 +13,17 @@ export class Enemy extends Component { @property(BoxCollider2D) public collider: BoxCollider2D; private deathEvent: Signal = new Signal(); + private lifetimeEndedEvent: Signal = new Signal(); private movementType: EnemyMovementType; - private health: UnitHealth = new UnitHealth(1); + private health: UnitHealth; private damage: number; private speedX: number; private speedY: number; + private lifetimeLeft: number; + + private xpReward: number; + private goldReward: number; public setup(position: Vec3, settings: EnemySettings): void { this.movementType = settings.moveType; @@ -25,6 +31,10 @@ export class Enemy extends Component { this.damage = settings.damage; this.speedX = randomRange(settings.speed / 2, settings.speed); this.speedY = randomRange(settings.speed / 2, settings.speed); + this.lifetimeLeft = settings.lifetime; + + this.xpReward = settings.xpReward; + this.goldReward = settings.goldReward; this.node.setWorldPosition(position); this.node.active = true; @@ -50,6 +60,10 @@ export class Enemy extends Component { return this.deathEvent; } + public get LifetimeEndedEvent(): ISignal { + return this.lifetimeEndedEvent; + } + public dealDamage(points: number): void { this.health.damage(points); if (!this.health.IsAlive) { @@ -57,11 +71,18 @@ export class Enemy extends Component { } } - public moveBy(move: Vec3, deltaTime: number): void { + public gameTick(move: Vec3, deltaTime: number): void { const newPosition: Vec3 = this.node.worldPosition; newPosition.x += move.x * this.speedX * deltaTime; newPosition.y += move.y * this.speedY * deltaTime; this.node.setWorldPosition(newPosition); + + if (0 < this.lifetimeLeft) { + this.lifetimeLeft -= deltaTime; + if (this.lifetimeLeft <= 0) { + this.lifetimeEndedEvent.trigger(this); + } + } } } diff --git a/assets/Scripts/Game/Unit/Enemy/EnemyManager.ts b/assets/Scripts/Game/Unit/Enemy/EnemyManager.ts index bd18948..bf95a56 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemyManager.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemyManager.ts @@ -63,11 +63,19 @@ export class EnemyManager extends Component { private onEnemyDied(enemy: Enemy): void { enemy.DeathEvent.off(this.onEnemyDied); + enemy.LifetimeEndedEvent.off(this.onEnemyLifetimeEnded); this.xpSpawner.spawnXp(enemy.node.worldPosition, 1); } + private onEnemyLifetimeEnded(enemy: Enemy): void { + enemy.DeathEvent.off(this.onEnemyDied); + enemy.LifetimeEndedEvent.off(this.onEnemyLifetimeEnded); + } + private onEnemyAdded(enemy: Enemy): void { enemy.DeathEvent.on(this.onEnemyDied, this); + enemy.LifetimeEndedEvent.on(this.onEnemyLifetimeEnded, this); + this.getEnemyMover(enemy).addEnemy(enemy); } diff --git a/assets/Scripts/Game/Unit/Enemy/EnemyMover/FollowTargetEnemyMover.ts b/assets/Scripts/Game/Unit/Enemy/EnemyMover/FollowTargetEnemyMover.ts index 11e6038..71a5766 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemyMover/FollowTargetEnemyMover.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemyMover/FollowTargetEnemyMover.ts @@ -6,7 +6,7 @@ export class FollowTargetEnemyMover extends EnemyMover { this.enemies.forEach((enemy) => { let direction: Vec3 = new Vec3(); direction = Vec3.subtract(direction, this.targetNode.worldPosition, enemy.node.worldPosition); - enemy.moveBy(direction.normalize(), deltaTime); + enemy.gameTick(direction.normalize(), deltaTime); }); } } diff --git a/assets/Scripts/Game/Unit/Enemy/EnemyMover/PeriodicFollowTargetEnemyMover.ts b/assets/Scripts/Game/Unit/Enemy/EnemyMover/PeriodicFollowTargetEnemyMover.ts index 4222833..927a9ca 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemyMover/PeriodicFollowTargetEnemyMover.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemyMover/PeriodicFollowTargetEnemyMover.ts @@ -30,7 +30,7 @@ export class PeriodicFollowTargetEnemyMover extends EnemyMover { if (this.enemyToFollowState.get(enemy) === EnemyFollowState.Follow) { let direction: Vec3 = new Vec3(); direction = Vec3.subtract(direction, this.targetNode.worldPosition, enemy.node.worldPosition); - enemy.moveBy(direction.normalize(), deltaTime); + enemy.gameTick(direction.normalize(), deltaTime); } } } diff --git a/assets/Scripts/Game/Unit/Enemy/EnemyMover/WaveEnemyMover.ts b/assets/Scripts/Game/Unit/Enemy/EnemyMover/WaveEnemyMover.ts index 1bf024d..2338c54 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemyMover/WaveEnemyMover.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemyMover/WaveEnemyMover.ts @@ -30,7 +30,7 @@ export class WaveEnemyMover extends EnemyMover { public gameTick(deltaTime: number): void { for (const enemyAndDirection of this.enemyToDirection) { - enemyAndDirection[0].moveBy(enemyAndDirection[1], deltaTime); + enemyAndDirection[0].gameTick(enemyAndDirection[1], deltaTime); } } } diff --git a/assets/Scripts/Game/Unit/Enemy/EnemySpawner/EnemySpawner.ts b/assets/Scripts/Game/Unit/Enemy/EnemySpawner/EnemySpawner.ts index 0580112..1ad3018 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemySpawner/EnemySpawner.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemySpawner/EnemySpawner.ts @@ -49,6 +49,7 @@ export class EnemySpawner extends Component { enemy.setup(spawnPosition, this.idToSettings.get(id)); enemy.DeathEvent.on(this.returnEnemy, this); + enemy.LifetimeEndedEvent.on(this.returnEnemy, this); this.enemyAddedEvent.trigger(enemy); @@ -57,6 +58,8 @@ export class EnemySpawner extends Component { public returnEnemy(enemy: Enemy): void { enemy.DeathEvent.off(this.returnEnemy); + enemy.LifetimeEndedEvent.off(this.returnEnemy); + this.enemyPool.return(enemy); this.enemyRemovedEvent.trigger(enemy); diff --git a/assets/Scripts/Game/Unit/Enemy/EnemySpawner/WaveEnemySpawner.ts b/assets/Scripts/Game/Unit/Enemy/EnemySpawner/WaveEnemySpawner.ts index af942c9..933e920 100644 --- a/assets/Scripts/Game/Unit/Enemy/EnemySpawner/WaveEnemySpawner.ts +++ b/assets/Scripts/Game/Unit/Enemy/EnemySpawner/WaveEnemySpawner.ts @@ -8,46 +8,20 @@ import { EnemySpawner } from "./EnemySpawner"; export class WaveEnemySpawner extends DelayedEnemySpawner { private enemiesPerWave: number; - private waveLifetime: number; private enemyId: string; private spawnTimer: GameTimer; - private waves: EnemyWave[] = []; public constructor(private enemySpawner: EnemySpawner, settings: WaveEnemySpawnerSettings) { super(settings.common.startDelay, settings.common.stopDelay); this.spawnTimer = new GameTimer(settings.common.cooldown); this.enemiesPerWave = settings.enemiesToSpawn; - this.waveLifetime = settings.waveLifetime; this.enemyId = settings.common.enemyId; } public delayedGameTick(deltaTime: number): void { this.spawnTimer.gameTick(deltaTime); - - this.tryRemoveExpiredEnemies(deltaTime); - this.trySpawnNewGroup(); - } - - private tryRemoveExpiredEnemies(deltaTime: number): void { - for (let i = this.waves.length - 1; 0 <= i; i--) { - const wave: EnemyWave = this.waves[i]; - wave.lifeTimeLeft -= deltaTime; - - if (wave.lifeTimeLeft <= 0) { - for (const enemy of wave.enemies) { - if (enemy.Health.IsAlive) { - this.enemySpawner.returnEnemy(enemy); - } - } - - this.waves.splice(i, 1); - } - } - } - - private trySpawnNewGroup(): void { if (this.spawnTimer.tryFinishPeriod()) { const defaultPosX: number = (500 + randomRange(0, 100)) * randomPositiveOrNegative(); const defaultPosY: number = randomRange(0, 500) * randomPositiveOrNegative(); @@ -62,13 +36,6 @@ export class WaveEnemySpawner extends DelayedEnemySpawner { const enemy = this.enemySpawner.spawnNewEnemy(posX, posY, this.enemyId); enemies.push(enemy); } - - this.waves.push({ enemies, lifeTimeLeft: this.waveLifetime }); } } } - -class EnemyWave { - public enemies: Enemy[]; - public lifeTimeLeft: number; -}