74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
import { vec2 } from 'gl-matrix';
|
|
import { CommandReceiver, Circle, PlayerInformation, CharacterTeam } from 'shared';
|
|
import { PhysicalContainer } from '../physics/containers/physical-container';
|
|
import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle';
|
|
import { isCircleIntersecting } from '../physics/functions/is-circle-intersecting';
|
|
import { PlayerCharacterPhysical } from '../objects/player-character-physical';
|
|
import { PlayerContainer } from './player-container';
|
|
|
|
export abstract class PlayerBase extends CommandReceiver {
|
|
public character?: PlayerCharacterPhysical | null;
|
|
public center: vec2 = vec2.create();
|
|
|
|
protected sumKills = 0;
|
|
protected sumDeaths = 0;
|
|
|
|
constructor(
|
|
protected readonly playerInfo: PlayerInformation,
|
|
protected readonly playerContainer: PlayerContainer,
|
|
protected readonly objectContainer: PhysicalContainer,
|
|
public readonly team: CharacterTeam,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
protected createCharacter(preferredCenter: vec2) {
|
|
this.character = new PlayerCharacterPhysical(
|
|
this.playerInfo.name.slice(0, 20),
|
|
this.sumKills,
|
|
this.sumDeaths,
|
|
this.team,
|
|
this.objectContainer,
|
|
this.findEmptyPositionForPlayer(preferredCenter),
|
|
);
|
|
|
|
this.objectContainer.addObject(this.character);
|
|
}
|
|
|
|
public abstract step(deltaTimeInSeconds: number): void;
|
|
|
|
protected findEmptyPositionForPlayer(preferredCenter: vec2): vec2 {
|
|
if (!preferredCenter) {
|
|
preferredCenter = vec2.create();
|
|
}
|
|
|
|
let rotation = 0;
|
|
let radius = 0;
|
|
for (;;) {
|
|
const playerPosition = vec2.fromValues(
|
|
radius * Math.cos(rotation) + preferredCenter.x,
|
|
radius * Math.sin(rotation) + preferredCenter.y,
|
|
);
|
|
|
|
const playerBoundingCircle = new Circle(
|
|
playerPosition,
|
|
PlayerCharacterPhysical.boundRadius,
|
|
);
|
|
|
|
const playerBoundingBox = getBoundingBoxOfCircle(playerBoundingCircle);
|
|
const possibleIntersectors = this.objectContainer.findIntersecting(
|
|
playerBoundingBox,
|
|
);
|
|
if (!isCircleIntersecting(playerBoundingCircle, possibleIntersectors)) {
|
|
return playerPosition;
|
|
}
|
|
|
|
rotation += Math.PI / 8;
|
|
radius += 30;
|
|
}
|
|
}
|
|
|
|
public destroy() {
|
|
this.character?.kill();
|
|
}
|
|
}
|