Movement improvements

This commit is contained in:
Martin 2022-12-12 12:04:31 +01:00
parent f7b345ef93
commit 2077c2e1c8
9 changed files with 92 additions and 14 deletions

View File

@ -56,5 +56,6 @@ export class WaveEnemySpawnerSettings {
public cooldown = 0; public cooldown = 0;
public enemiesPerWave = 0; public enemiesPerWave = 0;
public waveLifetime = 0; public waveLifetime = 0;
public moveType = "";
public enemyType = ""; public enemyType = "";
} }

View File

@ -94,7 +94,8 @@ export class Game extends Component {
this.gameUI.init(this.player); this.gameUI.init(this.player);
this.gamePauser.resume(); this.gamePauser.resume();
await delay(10000); // while not dead
await delay(100000);
this.gamePauser.pause(); this.gamePauser.pause();
Game.instance = null; Game.instance = null;
return 1; return 1;

View File

@ -5,6 +5,7 @@ import { Enemy } from "./Enemy";
import { EnemyMovementType } from "./EnemyMovementType"; import { EnemyMovementType } from "./EnemyMovementType";
import { EnemyMover } from "./EnemyMover/EnemyMover"; import { EnemyMover } from "./EnemyMover/EnemyMover";
import { FollowTargetEnemyMover } from "./EnemyMover/FollowTargetEnemyMover"; import { FollowTargetEnemyMover } from "./EnemyMover/FollowTargetEnemyMover";
import { PeriodicFollowTargetEnemyMover } from "./EnemyMover/PeriodicFollowTargetEnemyMover";
import { WaveEnemyMover } from "./EnemyMover/WaveEnemyMover"; import { WaveEnemyMover } from "./EnemyMover/WaveEnemyMover";
import { CircularEnemySpawner } from "./EnemySpawner/CircularEnemySpawner"; import { CircularEnemySpawner } from "./EnemySpawner/CircularEnemySpawner";
import { EnemySpawner } from "./EnemySpawner/EnemySpawner"; import { EnemySpawner } from "./EnemySpawner/EnemySpawner";
@ -30,12 +31,13 @@ export class EnemyManager extends Component {
this.enemySpawner.EnemyAddedEvent.on(this.onEnemyAdded, this); this.enemySpawner.EnemyAddedEvent.on(this.onEnemyAdded, this);
this.enemySpawner.enemyRemovedEvent.on(this.onRemoveEnemy, this); this.enemySpawner.enemyRemovedEvent.on(this.onRemoveEnemy, this);
this.individualEnemySpawner = new IndividualEnemySpawner(this.enemySpawner, EnemyType.Basic); this.individualEnemySpawner = new IndividualEnemySpawner(this.enemySpawner, EnemyMovementType.Follow, EnemyType.Basic);
this.circularEnemySpawner = new CircularEnemySpawner(this.enemySpawner, 30, EnemyType.Basic); this.circularEnemySpawner = new CircularEnemySpawner(this.enemySpawner, 30, EnemyMovementType.Follow, EnemyType.Basic);
this.waveEnemySpawner = new WaveEnemySpawner(this.enemySpawner, settings.waveEnemySpawner); this.waveEnemySpawner = new WaveEnemySpawner(this.enemySpawner, settings.waveEnemySpawner);
this.movementTypeToMover.set(EnemyMovementType.Follow, new FollowTargetEnemyMover(targetNode)); this.movementTypeToMover.set(EnemyMovementType.Follow, new FollowTargetEnemyMover(targetNode));
this.movementTypeToMover.set(EnemyMovementType.Launch, new WaveEnemyMover(targetNode)); this.movementTypeToMover.set(EnemyMovementType.Launch, new WaveEnemyMover(targetNode));
this.movementTypeToMover.set(EnemyMovementType.PeriodicFollow, new PeriodicFollowTargetEnemyMover(targetNode, 5, 5));
this.xpSpawner.init(); this.xpSpawner.init();
} }
@ -50,16 +52,16 @@ export class EnemyManager extends Component {
} }
} }
private onEnemyAdded(enemy: Enemy): void {
enemy.DeathEvent.on(this.onEnemyDied, this);
this.getEnemyMover(enemy).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 onEnemyAdded(enemy: Enemy): void {
enemy.DeathEvent.on(this.onEnemyDied, this);
this.getEnemyMover(enemy).addEnemy(enemy);
}
private onRemoveEnemy(enemy: Enemy): void { private onRemoveEnemy(enemy: Enemy): void {
this.getEnemyMover(enemy).removeEnemy(enemy); this.getEnemyMover(enemy).removeEnemy(enemy);
} }

View File

@ -1,4 +1,5 @@
export enum EnemyMovementType { export enum EnemyMovementType {
Follow, Follow = "Follow",
Launch PeriodicFollow = "PeriodicFollow",
Launch = "Launch"
} }

View File

@ -0,0 +1,57 @@
import { Node, Vec3 } from "cc";
import { Enemy } from "../Enemy";
import { EnemyMover } from "./EnemyMover";
export class PeriodicFollowTargetEnemyMover extends EnemyMover {
private enemyToFollowState: Map<Enemy, EnemyFollowState> = new Map<Enemy, EnemyFollowState>();
private enemyToStateTimeLeft: Map<Enemy, number> = new Map<Enemy, number>();
public constructor(targetNode: Node, private followTime: number, private waitTime: number) {
super(targetNode);
}
public addEnemy(enemy: Enemy): void {
this.setEnemyFollowState(enemy, EnemyFollowState.Follow, this.followTime);
super.addEnemy(enemy);
}
public removeEnemy(enemy: Enemy): void {
super.removeEnemy(enemy);
}
public gameTick(deltaTime: number): void {
for (const enemy of this.enemies) {
const stateTimeLeft: number = this.enemyToStateTimeLeft.get(enemy) - deltaTime;
if (stateTimeLeft <= 0) {
this.switchEnemyFollowState(enemy);
} else {
this.enemyToStateTimeLeft.set(enemy, stateTimeLeft);
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);
}
}
}
}
private switchEnemyFollowState(enemy: Enemy): void {
const followState: EnemyFollowState = this.enemyToFollowState.get(enemy);
if (followState === EnemyFollowState.Follow) {
this.setEnemyFollowState(enemy, EnemyFollowState.Wait, this.waitTime);
} else if (followState === EnemyFollowState.Wait) {
this.setEnemyFollowState(enemy, EnemyFollowState.Follow, this.followTime);
}
}
private setEnemyFollowState(enemy: Enemy, followState: EnemyFollowState, stateTimeLeft: number): void {
this.enemyToFollowState.set(enemy, followState);
this.enemyToStateTimeLeft.set(enemy, stateTimeLeft);
}
}
export enum EnemyFollowState {
Follow,
Wait
}

View File

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "02c4b3ec-3f77-485d-a539-32564ed5d63b",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@ -6,7 +6,12 @@ import { EnemySpawner } from "./EnemySpawner";
export class CircularEnemySpawner { export class CircularEnemySpawner {
private spawnTimer: GameTimer = new GameTimer(10); private spawnTimer: GameTimer = new GameTimer(10);
public constructor(private enemySpawner: EnemySpawner, private enemiesToSpawn: number, private enemyType: EnemyType) {} public constructor(
private enemySpawner: EnemySpawner,
private enemiesToSpawn: number,
private movementType: EnemyMovementType,
private enemyType: EnemyType
) {}
public gameTick(deltaTime: number): void { public gameTick(deltaTime: number): void {
this.spawnTimer.gameTick(deltaTime); this.spawnTimer.gameTick(deltaTime);
@ -16,7 +21,7 @@ export class CircularEnemySpawner {
for (let i = 0; i < this.enemiesToSpawn; i++) { for (let i = 0; i < this.enemiesToSpawn; i++) {
const posX: number = roundToOneDecimal(Math.sin(angle * i)) * 500; const posX: number = roundToOneDecimal(Math.sin(angle * i)) * 500;
const posY: number = roundToOneDecimal(Math.cos(angle * i)) * 500; const posY: number = roundToOneDecimal(Math.cos(angle * i)) * 500;
this.enemySpawner.spawnNewEnemy(posX, posY, EnemyMovementType.Follow); this.enemySpawner.spawnNewEnemy(posX, posY, this.movementType);
} }
} }
} }

View File

@ -8,14 +8,14 @@ import { EnemySpawner } from "./EnemySpawner";
export class IndividualEnemySpawner { export class IndividualEnemySpawner {
private spawnTimer: GameTimer = new GameTimer(1); private spawnTimer: GameTimer = new GameTimer(1);
public constructor(private enemySpawner: EnemySpawner, private enemyType: EnemyType) {} public constructor(private enemySpawner: EnemySpawner, private movementType: EnemyMovementType, private enemyType: EnemyType) {}
public gameTick(deltaTime: number): void { public gameTick(deltaTime: number): void {
this.spawnTimer.gameTick(deltaTime); this.spawnTimer.gameTick(deltaTime);
if (this.spawnTimer.tryFinishPeriod()) { if (this.spawnTimer.tryFinishPeriod()) {
const posX: number = randomRange(300, 600) * randomPositiveOrNegative(); const posX: number = randomRange(300, 600) * randomPositiveOrNegative();
const posY: number = randomRange(300, 600) * randomPositiveOrNegative(); const posY: number = randomRange(300, 600) * randomPositiveOrNegative();
this.enemySpawner.spawnNewEnemy(posX, posY, EnemyMovementType.Follow); this.enemySpawner.spawnNewEnemy(posX, posY, this.movementType);
} }
} }
} }

View File

@ -10,6 +10,7 @@ import { EnemySpawner } from "./EnemySpawner";
export class WaveEnemySpawner { export class WaveEnemySpawner {
private enemiesPerWave: number; private enemiesPerWave: number;
private waveLifetime: number; private waveLifetime: number;
private moveType: EnemyMovementType;
private enemyType: EnemyType; private enemyType: EnemyType;
private spawnTimer: GameTimer; private spawnTimer: GameTimer;
@ -19,6 +20,7 @@ export class WaveEnemySpawner {
this.spawnTimer = new GameTimer(settings.cooldown); this.spawnTimer = new GameTimer(settings.cooldown);
this.enemiesPerWave = settings.enemiesPerWave; this.enemiesPerWave = settings.enemiesPerWave;
this.waveLifetime = settings.waveLifetime; this.waveLifetime = settings.waveLifetime;
this.moveType = <EnemyMovementType>settings.moveType;
this.enemyType = <EnemyType>settings.enemyType; this.enemyType = <EnemyType>settings.enemyType;
} }