mirror of
https://github.com/MartinKral/Slash-The-Hordes
synced 2024-12-26 11:48:54 +00:00
Enemy spawners
This commit is contained in:
parent
772a5cc7e0
commit
8aa7ee6f2e
@ -59,7 +59,6 @@ export class GameBootstrapper extends Component {
|
|||||||
this.player.node,
|
this.player.node,
|
||||||
settings.player.haloLauncher
|
settings.player.haloLauncher
|
||||||
);
|
);
|
||||||
this.haloProjectileLauncher.upgrade();
|
|
||||||
|
|
||||||
this.horizontalProjectileLauncher = new WaveProjectileLauncher(
|
this.horizontalProjectileLauncher = new WaveProjectileLauncher(
|
||||||
this.horizontalProjectileLauncherComponent,
|
this.horizontalProjectileLauncherComponent,
|
||||||
@ -67,7 +66,6 @@ export class GameBootstrapper extends Component {
|
|||||||
[new Vec2(-1, 0), new Vec2(1, 0)],
|
[new Vec2(-1, 0), new Vec2(1, 0)],
|
||||||
settings.player.horizontalLauncher
|
settings.player.horizontalLauncher
|
||||||
);
|
);
|
||||||
this.horizontalProjectileLauncher.upgrade();
|
|
||||||
|
|
||||||
this.diagonalProjectileLauncher = new WaveProjectileLauncher(
|
this.diagonalProjectileLauncher = new WaveProjectileLauncher(
|
||||||
this.diagonalProjectileLauncherComponent,
|
this.diagonalProjectileLauncherComponent,
|
||||||
@ -75,7 +73,6 @@ export class GameBootstrapper extends Component {
|
|||||||
[new Vec2(-0.5, -0.5), new Vec2(0.5, -0.5)],
|
[new Vec2(-0.5, -0.5), new Vec2(0.5, -0.5)],
|
||||||
settings.player.diagonalLauncher
|
settings.player.diagonalLauncher
|
||||||
);
|
);
|
||||||
this.diagonalProjectileLauncher.upgrade();
|
|
||||||
|
|
||||||
new PlayerProjectileCollisionSystem([this.haloProjectileLauncher, this.horizontalProjectileLauncher, this.diagonalProjectileLauncher]);
|
new PlayerProjectileCollisionSystem([this.haloProjectileLauncher, this.horizontalProjectileLauncher, this.diagonalProjectileLauncher]);
|
||||||
|
|
||||||
|
22
assets/Scripts/Game/Unit/Enemy/CircularEnemySpawner.ts
Normal file
22
assets/Scripts/Game/Unit/Enemy/CircularEnemySpawner.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { GameTimer } from "../../../Services/GameTimer";
|
||||||
|
import { roundToOneDecimal } from "../../../Services/Utils/MathUtils";
|
||||||
|
import { EnemySpawner } from "./EnemySpawner";
|
||||||
|
import { EnemyType } from "./EnemyType";
|
||||||
|
|
||||||
|
export class CircularEnemySpawner {
|
||||||
|
private spawnTimer: GameTimer = new GameTimer(10);
|
||||||
|
public constructor(private enemySpawner: EnemySpawner, private enemiesToSpawn: number, private enemyType: EnemyType) {}
|
||||||
|
public gameTick(deltaTime: number): void {
|
||||||
|
this.spawnTimer.gameTick(deltaTime);
|
||||||
|
|
||||||
|
if (this.spawnTimer.tryFinishPeriod()) {
|
||||||
|
const angle: number = (2 * Math.PI) / this.enemiesToSpawn;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.enemiesToSpawn; i++) {
|
||||||
|
const posX: number = roundToOneDecimal(Math.sin(angle * i)) * 500;
|
||||||
|
const posY: number = roundToOneDecimal(Math.cos(angle * i)) * 500;
|
||||||
|
this.enemySpawner.spawnNewEnemy(posX, posY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "2e8e236a-fcdd-4995-aaff-be8802488d8c",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { UnitHealth } from "../UnitHealth";
|
|||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass("Enemy")
|
@ccclass("Enemy")
|
||||||
export class Enemy extends Component implements IDamageDealing {
|
export class Enemy extends Component {
|
||||||
@property(BoxCollider2D) public collider: BoxCollider2D;
|
@property(BoxCollider2D) public collider: BoxCollider2D;
|
||||||
|
|
||||||
private health: UnitHealth = new UnitHealth(1);
|
private health: UnitHealth = new UnitHealth(1);
|
||||||
@ -15,7 +15,7 @@ export class Enemy extends Component implements IDamageDealing {
|
|||||||
|
|
||||||
public setup(position: Vec3): void {
|
public setup(position: Vec3): void {
|
||||||
this.health = new UnitHealth(1);
|
this.health = new UnitHealth(1);
|
||||||
this.speed = randomRange(0.5, 1);
|
this.speed = randomRange(40, 90);
|
||||||
this.node.setWorldPosition(position);
|
this.node.setWorldPosition(position);
|
||||||
this.node.active = true;
|
this.node.active = true;
|
||||||
}
|
}
|
||||||
@ -51,7 +51,3 @@ export class Enemy extends Component implements IDamageDealing {
|
|||||||
this.node.setWorldPosition(newPosition);
|
this.node.setWorldPosition(newPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDamageDealing {
|
|
||||||
Damage: number;
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { Component, Node, _decorator } from "cc";
|
import { Component, Node, _decorator } from "cc";
|
||||||
import { XPSpawner } from "../../XP/XPSpawner";
|
import { XPSpawner } from "../../XP/XPSpawner";
|
||||||
|
import { CircularEnemySpawner } from "./CircularEnemySpawner";
|
||||||
import { Enemy } from "./Enemy";
|
import { Enemy } from "./Enemy";
|
||||||
import { EnemyMover } from "./EnemyMover";
|
import { EnemyMover } from "./EnemyMover";
|
||||||
import { EnemySpawner } from "./EnemySpawner";
|
import { EnemySpawner } from "./EnemySpawner";
|
||||||
|
import { EnemyType } from "./EnemyType";
|
||||||
|
import { InvididualEnemySpawner as IndividualEnemySpawner } from "./InvididualEnemySpawner";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass("EnemyManager")
|
@ccclass("EnemyManager")
|
||||||
@ -12,30 +15,39 @@ export class EnemyManager extends Component {
|
|||||||
|
|
||||||
private enemyMover: EnemyMover;
|
private enemyMover: EnemyMover;
|
||||||
|
|
||||||
|
private individualEnemySpawner: IndividualEnemySpawner;
|
||||||
|
private circularEnemySpawner: CircularEnemySpawner;
|
||||||
|
|
||||||
public init(targetNode: Node): void {
|
public init(targetNode: Node): void {
|
||||||
this.enemyMover = new EnemyMover(targetNode);
|
this.enemyMover = new EnemyMover(targetNode);
|
||||||
|
|
||||||
this.enemySpawner.init(targetNode);
|
this.enemySpawner.init(targetNode);
|
||||||
this.enemySpawner.EnemyAddedEvent.on(this.onEnemyAdded, this);
|
this.enemySpawner.EnemyAddedEvent.on(this.onEnemyAdded, this);
|
||||||
|
this.enemySpawner.enemyRemovedEvent.on(this.onRemoveEnemy, this);
|
||||||
|
|
||||||
|
this.individualEnemySpawner = new IndividualEnemySpawner(this.enemySpawner, EnemyType.Basic);
|
||||||
|
this.circularEnemySpawner = new CircularEnemySpawner(this.enemySpawner, 20, EnemyType.Basic);
|
||||||
|
|
||||||
this.xpSpawner.init();
|
this.xpSpawner.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public gameTick(deltaTime: number): void {
|
public gameTick(deltaTime: number): void {
|
||||||
this.enemySpawner.gameTick(deltaTime);
|
this.individualEnemySpawner.gameTick(deltaTime);
|
||||||
|
this.circularEnemySpawner.gameTick(deltaTime);
|
||||||
this.enemyMover.gameTick(deltaTime);
|
this.enemyMover.gameTick(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEnemyAdded(enemy: Enemy): void {
|
private onEnemyAdded(enemy: Enemy): void {
|
||||||
enemy.DeathEvent.on(this.onEnemyDied, this);
|
enemy.DeathEvent.on(this.onEnemyDied, this);
|
||||||
|
|
||||||
this.enemyMover.addEnemy(enemy);
|
this.enemyMover.addEnemy(enemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEnemyDied(enemy: Enemy): void {
|
private onEnemyDied(enemy: Enemy): void {
|
||||||
enemy.DeathEvent.off(this.onEnemyDied);
|
enemy.DeathEvent.off(this.onEnemyDied);
|
||||||
|
|
||||||
this.xpSpawner.spawnXp(enemy.node.worldPosition, 1);
|
this.xpSpawner.spawnXp(enemy.node.worldPosition, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onRemoveEnemy(enemy: Enemy): void {
|
||||||
this.enemyMover.removeEnemy(enemy);
|
this.enemyMover.removeEnemy(enemy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class EnemyMover {
|
|||||||
this.enemies.forEach((enemy) => {
|
this.enemies.forEach((enemy) => {
|
||||||
let direction: Vec3 = new Vec3();
|
let direction: Vec3 = new Vec3();
|
||||||
direction = Vec3.subtract(direction, this.targetNode.worldPosition, enemy.node.worldPosition);
|
direction = Vec3.subtract(direction, this.targetNode.worldPosition, enemy.node.worldPosition);
|
||||||
enemy.moveBy(direction.multiplyScalar(deltaTime).normalize());
|
enemy.moveBy(direction.normalize().multiplyScalar(deltaTime));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Component, Prefab, randomRange, Vec3, _decorator, Node } from "cc";
|
import { Component, Node, Prefab, Vec3, _decorator } from "cc";
|
||||||
import { ISignal } from "../../../Services/EventSystem/ISignal";
|
import { ISignal } from "../../../Services/EventSystem/ISignal";
|
||||||
import { Signal } from "../../../Services/EventSystem/Signal";
|
import { Signal } from "../../../Services/EventSystem/Signal";
|
||||||
import { GameTimer } from "../../../Services/GameTimer";
|
|
||||||
import { ObjectPool } from "../../../Services/ObjectPool";
|
import { ObjectPool } from "../../../Services/ObjectPool";
|
||||||
|
|
||||||
import { Enemy } from "./Enemy";
|
import { Enemy } from "./Enemy";
|
||||||
@ -12,34 +11,30 @@ export class EnemySpawner extends Component {
|
|||||||
@property(Prefab) private enemies: Prefab[] = [];
|
@property(Prefab) private enemies: Prefab[] = [];
|
||||||
|
|
||||||
public enemyAddedEvent: Signal<Enemy> = new Signal<Enemy>();
|
public enemyAddedEvent: Signal<Enemy> = new Signal<Enemy>();
|
||||||
|
public enemyRemovedEvent: Signal<Enemy> = new Signal<Enemy>();
|
||||||
|
|
||||||
private enemyPool: ObjectPool<Enemy>;
|
private enemyPool: ObjectPool<Enemy>;
|
||||||
private spawnTimer: GameTimer;
|
|
||||||
|
|
||||||
private targetNode: Node;
|
private targetNode: Node;
|
||||||
|
|
||||||
public init(targetNode: Node): void {
|
public init(targetNode: Node): void {
|
||||||
this.targetNode = targetNode;
|
this.targetNode = targetNode;
|
||||||
this.enemyPool = new ObjectPool(this.enemies[0], this.node, 5, "Enemy");
|
this.enemyPool = new ObjectPool(this.enemies[0], this.node, 50, "Enemy");
|
||||||
this.spawnTimer = new GameTimer(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public gameTick(deltaTime: number): void {
|
|
||||||
this.spawnTimer.gameTick(deltaTime);
|
|
||||||
if (this.spawnTimer.tryFinishPeriod()) {
|
|
||||||
this.spawnNewEnemy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get EnemyAddedEvent(): ISignal<Enemy> {
|
public get EnemyAddedEvent(): ISignal<Enemy> {
|
||||||
return this.enemyAddedEvent;
|
return this.enemyAddedEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private spawnNewEnemy(): void {
|
public get EnemyRemovedEvent(): ISignal<Enemy> {
|
||||||
|
return this.enemyRemovedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public spawnNewEnemy(positionX: number, positionY: number): void {
|
||||||
const enemy = this.enemyPool.borrow();
|
const enemy = this.enemyPool.borrow();
|
||||||
const spawnPosition = new Vec3();
|
const spawnPosition = new Vec3();
|
||||||
spawnPosition.x = this.targetNode.worldPosition.x + randomRange(-300, 300);
|
spawnPosition.x = this.targetNode.worldPosition.x + positionX;
|
||||||
spawnPosition.y = this.targetNode.worldPosition.y + randomRange(-800, 800);
|
spawnPosition.y = this.targetNode.worldPosition.y + positionY;
|
||||||
enemy.setup(spawnPosition);
|
enemy.setup(spawnPosition);
|
||||||
|
|
||||||
enemy.DeathEvent.on(this.returnEnemyToPool, this);
|
enemy.DeathEvent.on(this.returnEnemyToPool, this);
|
||||||
@ -50,5 +45,7 @@ export class EnemySpawner extends Component {
|
|||||||
private returnEnemyToPool(enemy: Enemy): void {
|
private returnEnemyToPool(enemy: Enemy): void {
|
||||||
enemy.DeathEvent.off(this.returnEnemyToPool);
|
enemy.DeathEvent.off(this.returnEnemyToPool);
|
||||||
this.enemyPool.return(enemy);
|
this.enemyPool.return(enemy);
|
||||||
|
|
||||||
|
this.enemyRemovedEvent.trigger(enemy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
assets/Scripts/Game/Unit/Enemy/EnemyType.ts
Normal file
3
assets/Scripts/Game/Unit/Enemy/EnemyType.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export enum EnemyType {
|
||||||
|
Basic = "Basic"
|
||||||
|
}
|
9
assets/Scripts/Game/Unit/Enemy/EnemyType.ts.meta
Normal file
9
assets/Scripts/Game/Unit/Enemy/EnemyType.ts.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "8db8a72b-543d-4566-8900-7701372634e3",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
18
assets/Scripts/Game/Unit/Enemy/InvididualEnemySpawner.ts
Normal file
18
assets/Scripts/Game/Unit/Enemy/InvididualEnemySpawner.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { randomRange } from "cc";
|
||||||
|
import { GameTimer } from "../../../Services/GameTimer";
|
||||||
|
import { randomPositiveOrNegative } from "../../../Services/Utils/MathUtils";
|
||||||
|
import { EnemySpawner } from "./EnemySpawner";
|
||||||
|
import { EnemyType } from "./EnemyType";
|
||||||
|
|
||||||
|
export class InvididualEnemySpawner {
|
||||||
|
private spawnTimer: GameTimer = new GameTimer(1);
|
||||||
|
public constructor(private enemySpawner: EnemySpawner, enemyType: EnemyType) {}
|
||||||
|
public gameTick(deltaTime: number): void {
|
||||||
|
this.spawnTimer.gameTick(deltaTime);
|
||||||
|
if (this.spawnTimer.tryFinishPeriod()) {
|
||||||
|
const posX: number = randomRange(300, 600) * randomPositiveOrNegative();
|
||||||
|
const posY: number = randomRange(300, 600) * randomPositiveOrNegative();
|
||||||
|
this.enemySpawner.spawnNewEnemy(posX, posY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.23",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "46674857-f5ad-4112-8b5d-c19879117904",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
export function roundToOneDecimal(num: number): number {
|
export function roundToOneDecimal(num: number): number {
|
||||||
return Math.round(num * 10) / 10;
|
return Math.round(num * 10) / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function randomPositiveOrNegative(): number {
|
||||||
|
return Math.random() < 0.5 ? 1 : -1;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user