Refactor
This commit is contained in:
parent
b774357807
commit
57d7009342
39 changed files with 203 additions and 250 deletions
7
backend/src/objects/capabilities/exerts-force.ts
Normal file
7
backend/src/objects/capabilities/exerts-force.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
export interface ExertsForce {
|
||||
getForce(target: vec2): vec2;
|
||||
}
|
||||
|
||||
export const exertsForce = (a: any): a is ExertsForce => a && 'getForce' in a;
|
||||
8
backend/src/objects/capabilities/reacts-to-collision.ts
Normal file
8
backend/src/objects/capabilities/reacts-to-collision.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { GameObject } from 'shared';
|
||||
|
||||
export interface ReactsToCollision {
|
||||
onCollision(other: GameObject): void;
|
||||
}
|
||||
|
||||
export const reactsToCollision = (a: any): a is ReactsToCollision =>
|
||||
a && 'onCollision' in a;
|
||||
5
backend/src/objects/capabilities/time-dependent.ts
Normal file
5
backend/src/objects/capabilities/time-dependent.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export interface TimeDependent {
|
||||
step(deltaTimeInSeconds: number): void;
|
||||
}
|
||||
|
||||
export const timeDependent = (a: any): a is TimeDependent => a && 'step' in a;
|
||||
|
|
@ -7,7 +7,7 @@ import {
|
|||
last,
|
||||
GameObject,
|
||||
Circle,
|
||||
PlayerCharacterBase,
|
||||
CharacterBase,
|
||||
CharacterTeam,
|
||||
PropertyUpdatesForObject,
|
||||
UpdateProperty,
|
||||
|
|
@ -21,12 +21,14 @@ import { interpolateAngles } from '../helper/interpolate-angles';
|
|||
import { forceAtPosition } from '../physics/functions/force-at-position';
|
||||
import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle';
|
||||
import { PlanetPhysical } from './planet-physical';
|
||||
import { ReactsToCollision } from '../physics/functions/reacts-to-collision';
|
||||
import { ReactsToCollision } from './capabilities/reacts-to-collision';
|
||||
import { TimeDependent } from './capabilities/time-dependent';
|
||||
import { GeneratesPoints } from './capabilities/generates-points';
|
||||
|
||||
@serializesTo(PlayerCharacterBase)
|
||||
export class PlayerCharacterPhysical
|
||||
extends PlayerCharacterBase
|
||||
implements DynamicPhysical, ReactsToCollision {
|
||||
@serializesTo(CharacterBase)
|
||||
export class CharacterPhysical
|
||||
extends CharacterBase
|
||||
implements DynamicPhysical, ReactsToCollision, TimeDependent, GeneratesPoints {
|
||||
public readonly canCollide = true;
|
||||
public readonly canMove = true;
|
||||
|
||||
|
|
@ -44,32 +46,32 @@ export class PlayerCharacterPhysical
|
|||
vec2.create(),
|
||||
vec2.add(
|
||||
vec2.create(),
|
||||
PlayerCharacterPhysical.desiredHeadOffset,
|
||||
PlayerCharacterPhysical.desiredLeftFootOffset,
|
||||
CharacterPhysical.desiredHeadOffset,
|
||||
CharacterPhysical.desiredLeftFootOffset,
|
||||
),
|
||||
PlayerCharacterPhysical.desiredRightFootOffset,
|
||||
CharacterPhysical.desiredRightFootOffset,
|
||||
),
|
||||
1 / 3,
|
||||
);
|
||||
|
||||
private static readonly headOffset = vec2.subtract(
|
||||
vec2.create(),
|
||||
PlayerCharacterPhysical.desiredHeadOffset,
|
||||
PlayerCharacterPhysical.centerOfMass,
|
||||
CharacterPhysical.desiredHeadOffset,
|
||||
CharacterPhysical.centerOfMass,
|
||||
);
|
||||
private static readonly leftFootOffset = vec2.subtract(
|
||||
vec2.create(),
|
||||
PlayerCharacterPhysical.desiredLeftFootOffset,
|
||||
PlayerCharacterPhysical.centerOfMass,
|
||||
CharacterPhysical.desiredLeftFootOffset,
|
||||
CharacterPhysical.centerOfMass,
|
||||
);
|
||||
private static readonly rightFootOffset = vec2.subtract(
|
||||
vec2.create(),
|
||||
PlayerCharacterPhysical.desiredRightFootOffset,
|
||||
PlayerCharacterPhysical.centerOfMass,
|
||||
CharacterPhysical.desiredRightFootOffset,
|
||||
CharacterPhysical.centerOfMass,
|
||||
);
|
||||
|
||||
public static readonly boundRadius =
|
||||
(PlayerCharacterPhysical.headRadius + PlayerCharacterPhysical.feetRadius * 2) * 2;
|
||||
(CharacterPhysical.headRadius + CharacterPhysical.feetRadius * 2) * 2;
|
||||
|
||||
private timeSinceDying = 0;
|
||||
private isDestroyed = false;
|
||||
|
|
@ -102,20 +104,20 @@ export class PlayerCharacterPhysical
|
|||
) {
|
||||
super(id(), name, killCount, deathCount, team, settings.playerMaxHealth);
|
||||
this.head = new CirclePhysical(
|
||||
vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.headOffset),
|
||||
PlayerCharacterPhysical.headRadius,
|
||||
vec2.add(vec2.create(), startPosition, CharacterPhysical.headOffset),
|
||||
CharacterPhysical.headRadius,
|
||||
this,
|
||||
container,
|
||||
);
|
||||
this.leftFoot = new CirclePhysical(
|
||||
vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.leftFootOffset),
|
||||
PlayerCharacterPhysical.feetRadius,
|
||||
vec2.add(vec2.create(), startPosition, CharacterPhysical.leftFootOffset),
|
||||
CharacterPhysical.feetRadius,
|
||||
this,
|
||||
container,
|
||||
);
|
||||
this.rightFoot = new CirclePhysical(
|
||||
vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.rightFootOffset),
|
||||
PlayerCharacterPhysical.feetRadius,
|
||||
vec2.add(vec2.create(), startPosition, CharacterPhysical.rightFootOffset),
|
||||
CharacterPhysical.feetRadius,
|
||||
this,
|
||||
container,
|
||||
);
|
||||
|
|
@ -125,12 +127,29 @@ export class PlayerCharacterPhysical
|
|||
|
||||
this.bound = new CirclePhysical(
|
||||
vec2.create(),
|
||||
PlayerCharacterPhysical.boundRadius,
|
||||
CharacterPhysical.boundRadius,
|
||||
this,
|
||||
container,
|
||||
);
|
||||
}
|
||||
|
||||
private hasGeneratedPoints = false;
|
||||
public getPoints(): { decla: number; red: number } {
|
||||
if (!this.isAlive && !this.hasGeneratedPoints) {
|
||||
this.hasGeneratedPoints = true;
|
||||
const decla = this.team === CharacterTeam.decla ? 0 : settings.playerKillPoint;
|
||||
const red = this.team === CharacterTeam.red ? 0 : settings.playerKillPoint;
|
||||
return {
|
||||
decla,
|
||||
red,
|
||||
};
|
||||
}
|
||||
return {
|
||||
decla: 0,
|
||||
red: 0,
|
||||
};
|
||||
}
|
||||
|
||||
public get isAlive(): boolean {
|
||||
return !this.isDestroyed;
|
||||
}
|
||||
|
|
@ -154,7 +173,7 @@ export class PlayerCharacterPhysical
|
|||
this.health -= other.strength;
|
||||
this.remoteCall('setHealth', this.health);
|
||||
if (this.health <= 0 && this.isAlive) {
|
||||
this.kill();
|
||||
this.onDie();
|
||||
other.originator.addKill();
|
||||
}
|
||||
}
|
||||
|
|
@ -231,8 +250,8 @@ export class PlayerCharacterPhysical
|
|||
}
|
||||
|
||||
private animateScaling(q: number) {
|
||||
this.head.radius = PlayerCharacterPhysical.headRadius * q;
|
||||
this.leftFoot.radius = this.rightFoot.radius = PlayerCharacterPhysical.feetRadius * q;
|
||||
this.head.radius = CharacterPhysical.headRadius * q;
|
||||
this.leftFoot.radius = this.rightFoot.radius = CharacterPhysical.feetRadius * q;
|
||||
}
|
||||
|
||||
public getPropertyUpdates(): PropertyUpdatesForObject {
|
||||
|
|
@ -325,7 +344,7 @@ export class PlayerCharacterPhysical
|
|||
getBoundingBoxOfCircle(
|
||||
new Circle(
|
||||
this.center,
|
||||
PlayerCharacterPhysical.boundRadius + settings.maxGravityDistance,
|
||||
CharacterPhysical.boundRadius + settings.maxGravityDistance,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -407,25 +426,19 @@ export class PlayerCharacterPhysical
|
|||
this.springMove(
|
||||
this.leftFoot,
|
||||
center,
|
||||
PlayerCharacterPhysical.leftFootOffset,
|
||||
CharacterPhysical.leftFootOffset,
|
||||
deltaTime,
|
||||
3000,
|
||||
);
|
||||
this.springMove(
|
||||
this.rightFoot,
|
||||
center,
|
||||
PlayerCharacterPhysical.rightFootOffset,
|
||||
CharacterPhysical.rightFootOffset,
|
||||
deltaTime,
|
||||
3000,
|
||||
);
|
||||
|
||||
this.springMove(
|
||||
this.head,
|
||||
center,
|
||||
PlayerCharacterPhysical.headOffset,
|
||||
deltaTime,
|
||||
7000,
|
||||
);
|
||||
this.springMove(this.head, center, CharacterPhysical.headOffset, deltaTime, 7000);
|
||||
}
|
||||
|
||||
private springMove(
|
||||
|
|
@ -462,7 +475,7 @@ export class PlayerCharacterPhysical
|
|||
}
|
||||
|
||||
private stepBodyPart(part: CirclePhysical, deltaTime: number) {
|
||||
const { hitObject } = part.step2(deltaTime);
|
||||
const { hitObject } = part.stepManually(deltaTime);
|
||||
if (hitObject instanceof PlanetPhysical) {
|
||||
this.secondsSinceOnSurface = 0;
|
||||
this.currentPlanet = hitObject;
|
||||
|
|
@ -477,9 +490,9 @@ export class PlayerCharacterPhysical
|
|||
);
|
||||
}
|
||||
|
||||
public kill() {
|
||||
public onDie() {
|
||||
this.isDestroyed = true;
|
||||
this.remoteCall('kill');
|
||||
this.remoteCall('onDie');
|
||||
}
|
||||
|
||||
private destroy() {
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Circle, GameObject, serializesTo, settings } from 'shared';
|
||||
import { PhysicalBase } from '../physics/physicals/physical-base';
|
||||
import { Circle, GameObject, serializesTo } from 'shared';
|
||||
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
||||
import { BoundingBoxBase } from '../physics/bounding-boxes/bounding-box-base';
|
||||
import { moveCircle } from '../physics/functions/move-circle';
|
||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||
import { DynamicPhysical } from '../physics/physicals/dynamic-physical';
|
||||
import {
|
||||
ReactsToCollision,
|
||||
reactsToCollision,
|
||||
} from '../physics/functions/reacts-to-collision';
|
||||
import { ReactsToCollision, reactsToCollision } from './capabilities/reacts-to-collision';
|
||||
|
||||
@serializesTo(Circle)
|
||||
export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollision {
|
||||
|
|
@ -17,8 +13,9 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio
|
|||
readonly canMove = true;
|
||||
|
||||
public velocity = vec2.create();
|
||||
public lastNormal = vec2.fromValues(0, 1);
|
||||
|
||||
private _boundingBox: BoundingBox;
|
||||
public lastNormal = vec2.fromValues(1, 0);
|
||||
|
||||
constructor(
|
||||
private _center: vec2,
|
||||
|
|
@ -67,18 +64,6 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio
|
|||
return vec2.distance(target, this.center) - this.radius;
|
||||
}
|
||||
|
||||
public distanceBetween(target: Circle): number {
|
||||
return vec2.distance(target.center, this.center) - this.radius - target.radius;
|
||||
}
|
||||
|
||||
public areIntersecting(other: PhysicalBase): boolean {
|
||||
return other.distance(this.center) < this.radius;
|
||||
}
|
||||
|
||||
public isInside(other: PhysicalBase): boolean {
|
||||
return other.distance(this.center) < -this.radius;
|
||||
}
|
||||
|
||||
private recalculateBoundingBox() {
|
||||
this._boundingBox.xMin = this.center.x - this._radius;
|
||||
this._boundingBox.xMax = this.center.x + this._radius;
|
||||
|
|
@ -94,9 +79,7 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio
|
|||
);
|
||||
}
|
||||
|
||||
public step(_: number) {}
|
||||
|
||||
public step2(
|
||||
public stepManually(
|
||||
deltaTimeInSeconds: number,
|
||||
): { hitObject: GameObject | undefined; velocity: vec2 } {
|
||||
let delta = vec2.scale(vec2.create(), this.velocity, deltaTimeInSeconds);
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@ export class LampPhysical extends LampBase implements StaticPhysical {
|
|||
return this;
|
||||
}
|
||||
|
||||
public getForce(_: vec2): vec2 {
|
||||
return vec2.create();
|
||||
}
|
||||
|
||||
public step(deltaTime: number): void {}
|
||||
|
||||
public distance(target: vec2): number {
|
||||
return vec2.distance(this.center, target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import {
|
|||
clamp,
|
||||
clamp01,
|
||||
id,
|
||||
rotate90Deg,
|
||||
rotateMinus90Deg,
|
||||
serializesTo,
|
||||
settings,
|
||||
PlanetBase,
|
||||
|
|
@ -14,12 +12,14 @@ import {
|
|||
|
||||
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
||||
import { StaticPhysical } from '../physics/physicals/static-physical';
|
||||
import { GeneratesPoints } from './generates-points';
|
||||
import { ExertsForce } from './capabilities/exerts-force';
|
||||
import { GeneratesPoints } from './capabilities/generates-points';
|
||||
import { TimeDependent } from './capabilities/time-dependent';
|
||||
|
||||
@serializesTo(PlanetBase)
|
||||
export class PlanetPhysical
|
||||
extends PlanetBase
|
||||
implements StaticPhysical, GeneratesPoints {
|
||||
implements StaticPhysical, GeneratesPoints, ExertsForce, TimeDependent {
|
||||
public readonly canCollide = true;
|
||||
public readonly canMove = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-boundi
|
|||
import { CirclePhysical } from './circle-physical';
|
||||
import { DynamicPhysical } from '../physics/physicals/dynamic-physical';
|
||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||
import { PlanetPhysical } from './planet-physical';
|
||||
import { ReactsToCollision } from '../physics/functions/reacts-to-collision';
|
||||
import { PlayerCharacterPhysical } from './player-character-physical';
|
||||
import { ReactsToCollision } from './capabilities/reacts-to-collision';
|
||||
import { CharacterPhysical } from './character-physical';
|
||||
import { moveCircle } from '../physics/functions/move-circle';
|
||||
import { TimeDependent } from './capabilities/time-dependent';
|
||||
|
||||
@serializesTo(ProjectileBase)
|
||||
export class ProjectilePhysical
|
||||
extends ProjectileBase
|
||||
implements DynamicPhysical, ReactsToCollision {
|
||||
implements DynamicPhysical, ReactsToCollision, TimeDependent {
|
||||
public readonly canCollide = true;
|
||||
public readonly canMove = true;
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ export class ProjectilePhysical
|
|||
public strength: number,
|
||||
team: CharacterTeam,
|
||||
private velocity: vec2,
|
||||
public readonly originator: PlayerCharacterPhysical,
|
||||
public readonly originator: CharacterPhysical,
|
||||
readonly container: PhysicalContainer,
|
||||
) {
|
||||
super(id(), center, radius, team, strength);
|
||||
|
|
@ -60,7 +60,7 @@ export class ProjectilePhysical
|
|||
while (wasCollision) {
|
||||
const intersecting = this.container
|
||||
.findIntersecting(this.boundingBox)
|
||||
.filter((g) => g instanceof PlayerCharacterPhysical && g.team === this.team);
|
||||
.filter((g) => g instanceof CharacterPhysical && g.team === this.team);
|
||||
const { hitSurface } = moveCircle(this.object, delta, intersecting, true);
|
||||
wasCollision = hitSurface;
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ export class ProjectilePhysical
|
|||
|
||||
public onCollision(other: GameObject) {
|
||||
if (
|
||||
!(other instanceof PlayerCharacterPhysical && other.team === this.team) &&
|
||||
!(other instanceof CharacterPhysical && other.team === this.team) &&
|
||||
this.bounceCount++ === settings.projectileMaxBounceCount
|
||||
) {
|
||||
this.destroy();
|
||||
|
|
@ -115,7 +115,7 @@ export class ProjectilePhysical
|
|||
}
|
||||
|
||||
vec2.copy(this.object.velocity, this.velocity);
|
||||
const { velocity } = this.object.step2(deltaTime);
|
||||
const { velocity } = this.object.stepManually(deltaTime);
|
||||
vec2.copy(this.velocity, velocity);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue