119 lines
4.7 KiB
TypeScript
Raw Normal View History

2022-12-20 15:17:57 +01:00
import { _decorator, Component, Prefab, Vec2, Vec3 } from "cc";
2023-01-09 11:09:06 +01:00
import { Empty } from "../../../Menu/ModalWindows/Upgrades/UpgradesModalWindow";
import { ISignal } from "../../../Services/EventSystem/ISignal";
import { Signal } from "../../../Services/EventSystem/Signal";
import { ObjectPool } from "../../../Services/ObjectPool";
import { getDegreeAngleFromDirection } from "../../../Services/Utils/MathUtils";
import { IProjectileLauncherSignaler } from "../IProjectileLauncherSignaler";
import { Projectile } from "../Projectile";
import { ProjectileCollision } from "../ProjectileCollision";
2022-11-30 09:37:09 +01:00
const { ccclass, property } = _decorator;
@ccclass("ProjectileLauncher")
2022-12-22 12:08:00 +01:00
export class ProjectileLauncher extends Component implements IProjectileLauncherSignaler {
2022-11-30 09:37:09 +01:00
@property(Prefab) private projectilePrefab: Prefab;
2022-12-22 12:08:00 +01:00
private projectileCollisionEvent = new Signal<ProjectileCollision>();
2022-12-30 15:19:32 +01:00
private projectileLaunchedEvent = new Signal();
2022-12-20 15:17:57 +01:00
private projectileDamage: number;
private projectilePierces: number;
2022-11-30 11:44:20 +01:00
private projectileLifetime: number;
2022-12-20 15:17:57 +01:00
private projectileSpeed: number;
private projectilePool: ObjectPool<Projectile>;
2022-11-30 09:37:09 +01:00
private projectiles: Projectile[] = [];
private directions: Vec2[] = [];
private expireTimes: number[] = [];
private currentTime = 0;
2022-11-30 11:44:20 +01:00
public get ProjectileCollisionEvent(): ISignal<ProjectileCollision> {
return this.projectileCollisionEvent;
}
2022-12-22 12:08:00 +01:00
public get ProjectileLaunchedEvent(): ISignal {
2022-12-30 15:19:32 +01:00
return this.projectileLaunchedEvent;
2022-12-22 12:08:00 +01:00
}
2022-12-20 15:17:57 +01:00
public init(projectileLifetime: number, projectileSpeed: number, projectileDamage: number, projectilePierces: number): void {
this.projectileLifetime = projectileLifetime;
this.projectileSpeed = projectileSpeed;
this.projectileDamage = projectileDamage;
this.projectilePierces = projectilePierces;
2022-11-30 11:44:20 +01:00
2022-11-30 09:37:09 +01:00
this.projectilePool = new ObjectPool<Projectile>(this.projectilePrefab, this.node, 6, "Projectile");
}
2022-12-20 15:17:57 +01:00
public gameTick(deltaTime: number): void {
2022-11-30 09:37:09 +01:00
this.currentTime += deltaTime;
this.tryRemoveExpiredProjectiles();
this.moveAllProjectiles(deltaTime);
}
2022-12-20 15:17:57 +01:00
public fireProjectiles(startPosition: Vec3, fireDirections: Vec2[]): void {
for (const direction of fireDirections) {
this.fireProjectile(startPosition, direction);
2022-11-30 09:37:09 +01:00
}
}
2022-12-20 14:37:26 +01:00
private fireProjectile(startPosition: Vec3, direction: Vec2): void {
2022-12-21 11:30:21 +01:00
direction = direction.normalize();
2022-11-30 09:37:09 +01:00
const projectile: Projectile = this.projectilePool.borrow();
2022-12-30 15:19:32 +01:00
projectile.setup(this.projectileDamage, this.projectilePierces, getDegreeAngleFromDirection(direction.x, direction.y));
2022-12-20 14:37:26 +01:00
projectile.node.setWorldPosition(startPosition);
2022-11-30 09:37:09 +01:00
projectile.node.active = true;
2022-11-30 11:44:20 +01:00
projectile.ContactBeginEvent.on(this.onProjectileCollision, this);
2022-12-13 11:58:40 +01:00
projectile.PiercesDepletedEvent.on(this.onPiercesDepleted, this);
2022-11-30 09:37:09 +01:00
this.projectiles.push(projectile);
this.directions.push(direction);
this.expireTimes.push(this.currentTime + this.projectileLifetime);
2022-12-22 12:08:00 +01:00
2022-12-30 15:19:32 +01:00
this.projectileLaunchedEvent.trigger();
2022-11-30 09:37:09 +01:00
}
private tryRemoveExpiredProjectiles(): void {
for (let i = 0; i < this.projectiles.length; i++) {
if (this.currentTime < this.expireTimes[i]) break; // the oldest particles are at the start of the array
2022-11-30 11:44:20 +01:00
const projectile: Projectile = this.projectiles[i];
2022-12-13 11:58:40 +01:00
this.removeProjectile(projectile, i);
2022-11-30 09:37:09 +01:00
i--; // Check the same index
}
}
2022-12-13 11:58:40 +01:00
private onPiercesDepleted(projectile: Projectile): void {
const index = this.projectiles.indexOf(projectile);
if (index === -1) {
throw new Error("Projectile not found!");
}
this.removeProjectile(projectile, index);
}
private removeProjectile(projectile: Projectile, index: number): void {
projectile.ContactBeginEvent.off(this.onProjectileCollision);
projectile.PiercesDepletedEvent.off(this.onPiercesDepleted);
this.projectilePool.return(projectile);
this.projectiles.splice(index, 1);
this.directions.splice(index, 1);
this.expireTimes.splice(index, 1);
}
2022-11-30 09:37:09 +01:00
private moveAllProjectiles(deltaTime: number): void {
for (let i = 0; i < this.projectiles.length; i++) {
const newPosition: Vec3 = this.projectiles[i].node.worldPosition;
2022-12-20 15:17:57 +01:00
newPosition.x += this.directions[i].x * deltaTime * this.projectileSpeed;
newPosition.y += this.directions[i].y * deltaTime * this.projectileSpeed;
2022-11-30 09:37:09 +01:00
this.projectiles[i].node.setWorldPosition(newPosition);
}
}
2022-11-30 11:44:20 +01:00
private onProjectileCollision(projectlieCollision: ProjectileCollision): void {
this.projectileCollisionEvent.trigger(projectlieCollision);
}
2022-11-30 09:37:09 +01:00
}