Refactor
This commit is contained in:
parent
b774357807
commit
57d7009342
39 changed files with 203 additions and 250 deletions
|
|
@ -67,8 +67,8 @@ export const createWorld = (objectContainer: PhysicalContainer, worldRadius: num
|
|||
}
|
||||
}
|
||||
}
|
||||
console.log('Generated planet count', objects.length);
|
||||
console.log('Generated light count', lights.length);
|
||||
console.info('Generated planet count', objects.length);
|
||||
console.info('Generated light count', lights.length);
|
||||
|
||||
[...objects, ...lights].forEach((o) => objectContainer.addObject(o));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export class GameServer {
|
|||
const commands: Array<Command> = deserialize(json);
|
||||
commands.forEach((c) => player.sendCommand(c));
|
||||
} catch (e) {
|
||||
console.log('Error while processing command', e);
|
||||
console.error('Error while processing command', e);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -169,16 +169,16 @@ export class GameServer {
|
|||
|
||||
if (this.deltaTimes.length > framesBetweenDeltaTimeCalculation) {
|
||||
this.deltaTimes.sort((a, b) => a - b);
|
||||
console.log(
|
||||
console.info(
|
||||
`Median physics time: ${this.deltaTimes[
|
||||
Math.floor(framesBetweenDeltaTimeCalculation / 2)
|
||||
].toFixed(2)} ms`,
|
||||
);
|
||||
console.log(
|
||||
console.info(
|
||||
'Tail times: ',
|
||||
this.deltaTimes.slice(-20).map((v) => `${(v * 1000).toFixed(2)} ms`),
|
||||
);
|
||||
console.log(
|
||||
console.info(
|
||||
`Memory used: ${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`,
|
||||
);
|
||||
this.deltaTimes = [];
|
||||
|
|
|
|||
|
|
@ -28,19 +28,19 @@ const gameServer = new GameServer(io, options);
|
|||
|
||||
app.use(
|
||||
cors({
|
||||
origin: (origin, callback) => {
|
||||
origin: (_, callback) => {
|
||||
callback(null, true);
|
||||
},
|
||||
credentials: true,
|
||||
}),
|
||||
);
|
||||
|
||||
app.get(serverInformationEndpoint, (req, res) => {
|
||||
app.get(serverInformationEndpoint, (_, res) => {
|
||||
res.json(gameServer.serverInfo);
|
||||
});
|
||||
|
||||
server.listen(options.port, () => {
|
||||
console.log(`server started at http://localhost:${options.port}`);
|
||||
console.info(`Server started on port ${options.port}`);
|
||||
});
|
||||
|
||||
gameServer.start();
|
||||
|
|
|
|||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import { BoundingBoxBase } from '../bounding-boxes/bounding-box-base';
|
||||
|
||||
import { BoundingBoxList } from './bounding-box-list';
|
||||
import { BoundingBoxTree } from './bounding-box-tree';
|
||||
|
||||
import { Physical } from '../physicals/physical';
|
||||
import { StaticPhysical } from '../physicals/static-physical';
|
||||
import { DynamicPhysical } from '../physicals/dynamic-physical';
|
||||
import { GeneratesPoints, generatesPoints } from '../../objects/generates-points';
|
||||
import {
|
||||
GeneratesPoints,
|
||||
generatesPoints,
|
||||
} from '../../objects/capabilities/generates-points';
|
||||
import { timeDependent } from '../../objects/capabilities/time-dependent';
|
||||
|
||||
export class PhysicalContainer {
|
||||
private isTreeInitialized = false;
|
||||
|
|
@ -40,7 +42,7 @@ export class PhysicalContainer {
|
|||
}
|
||||
|
||||
public stepObjects(deltaTime: number) {
|
||||
this.objects.forEach((o) => o.step(deltaTime));
|
||||
this.objects.forEach((o) => timeDependent(o) && o.step(deltaTime));
|
||||
}
|
||||
|
||||
public resetRemoteCalls() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { exertsForce } from '../../objects/capabilities/exerts-force';
|
||||
import { Physical } from '../physicals/physical';
|
||||
|
||||
export const forceAtPosition = (position: vec2, objects: Array<Physical>) =>
|
||||
objects.reduce(
|
||||
(sum: vec2, o: Physical) =>
|
||||
!o.canMove ? vec2.add(sum, sum, o.getForce(position)) : sum,
|
||||
exertsForce(o) ? vec2.add(sum, sum, o.getForce(position)) : sum,
|
||||
vec2.create(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Circle, GameObject, rotate90Deg } from 'shared';
|
||||
import { CirclePhysical } from '../../objects/circle-physical';
|
||||
import { reactsToCollision } from './reacts-to-collision';
|
||||
import { reactsToCollision } from '../../objects/capabilities/reacts-to-collision';
|
||||
import { evaluateSdf } from './evaluate-sdf';
|
||||
import { Physical } from '../physicals/physical';
|
||||
|
||||
|
|
@ -11,10 +11,8 @@ export const moveCircle = (
|
|||
possibleIntersectors: Array<Physical>,
|
||||
ignoreCollision = false,
|
||||
): {
|
||||
realDelta: vec2;
|
||||
hitSurface: boolean;
|
||||
normal?: vec2;
|
||||
tangent?: vec2;
|
||||
hitObject?: GameObject;
|
||||
} => {
|
||||
const direction = vec2.clone(delta);
|
||||
|
|
@ -78,16 +76,10 @@ export const moveCircle = (
|
|||
]);
|
||||
const normal = vec2.fromValues(dx, dy);
|
||||
vec2.normalize(normal, normal);
|
||||
const rotatedNormal = rotate90Deg(normal);
|
||||
return {
|
||||
realDelta: delta,
|
||||
hitSurface: true,
|
||||
normal,
|
||||
hitObject: intersecting?.gameObject,
|
||||
tangent:
|
||||
vec2.dot(rotatedNormal, delta) < 0
|
||||
? vec2.scale(rotatedNormal, rotatedNormal, -1)
|
||||
: rotatedNormal,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +89,6 @@ export const moveCircle = (
|
|||
vec2.add(circle.center, circle.center, delta);
|
||||
|
||||
return {
|
||||
realDelta: delta,
|
||||
hitSurface: false,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,5 +9,4 @@ export interface PhysicalBase {
|
|||
readonly gameObject: GameObject;
|
||||
|
||||
distance(target: vec2): number;
|
||||
step(deltaTime: number): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { PhysicalBase } from './physical-base';
|
||||
import { ImmutableBoundingBox } from '../bounding-boxes/immutable-bounding-box';
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
export interface StaticPhysical extends PhysicalBase {
|
||||
readonly canMove: false;
|
||||
readonly boundingBox: ImmutableBoundingBox;
|
||||
|
||||
getForce(target: vec2): vec2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import {
|
||||
PlayerInformation,
|
||||
CharacterTeam,
|
||||
settings,
|
||||
Circle,
|
||||
Random,
|
||||
MoveActionCommand,
|
||||
CharacterTeam,
|
||||
} from 'shared';
|
||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||
import { PlayerContainer } from './player-container';
|
||||
import { PlayerBase } from './player-base';
|
||||
import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle';
|
||||
import { PlayerCharacterPhysical } from '../objects/player-character-physical';
|
||||
import { CharacterPhysical } from '../objects/character-physical';
|
||||
import { PlanetPhysical } from '../objects/planet-physical';
|
||||
import { Physical } from '../physics/physicals/physical';
|
||||
|
||||
|
|
@ -98,22 +98,18 @@ export class NPC extends PlayerBase {
|
|||
|
||||
private findNearCharactersSorted(
|
||||
nearObjects: Array<Physical>,
|
||||
): Array<{ character: PlayerCharacterPhysical; distance: number }> {
|
||||
): Array<{ character: CharacterPhysical; distance: number }> {
|
||||
const characters = Array.from(
|
||||
new Set(
|
||||
nearObjects.filter(
|
||||
(o) =>
|
||||
o.gameObject instanceof PlayerCharacterPhysical &&
|
||||
o.gameObject !== this.character,
|
||||
o.gameObject instanceof CharacterPhysical && o.gameObject !== this.character,
|
||||
),
|
||||
),
|
||||
).map((c) => ({
|
||||
character: c.gameObject,
|
||||
distance: vec2.distance(
|
||||
this.center,
|
||||
(c.gameObject as PlayerCharacterPhysical).center,
|
||||
),
|
||||
})) as Array<{ character: PlayerCharacterPhysical; distance: number }>;
|
||||
distance: vec2.distance(this.center, (c.gameObject as CharacterPhysical).center),
|
||||
})) as Array<{ character: CharacterPhysical; distance: number }>;
|
||||
|
||||
characters.sort((a, b) => a.distance - b.distance);
|
||||
|
||||
|
|
@ -139,12 +135,10 @@ export class NPC extends PlayerBase {
|
|||
const nearObjects = this.objectContainer.findIntersecting(observableArea);
|
||||
|
||||
const enemies = nearObjects.filter(
|
||||
(o) =>
|
||||
o.gameObject instanceof PlayerCharacterPhysical &&
|
||||
o.gameObject.team !== this.team,
|
||||
(o) => o.gameObject instanceof CharacterPhysical && o.gameObject.team !== this.team,
|
||||
);
|
||||
if (enemies.length > 0) {
|
||||
return (enemies[0].gameObject as PlayerCharacterPhysical).center;
|
||||
return (enemies[0].gameObject as CharacterPhysical).center;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { CommandReceiver, Circle, PlayerInformation, CharacterTeam } from 'share
|
|||
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 { CharacterPhysical } from '../objects/character-physical';
|
||||
import { PlayerContainer } from './player-container';
|
||||
|
||||
export abstract class PlayerBase extends CommandReceiver {
|
||||
public character?: PlayerCharacterPhysical | null;
|
||||
public character?: CharacterPhysical | null;
|
||||
public center: vec2 = vec2.create();
|
||||
|
||||
protected sumKills = 0;
|
||||
|
|
@ -23,7 +23,7 @@ export abstract class PlayerBase extends CommandReceiver {
|
|||
}
|
||||
|
||||
protected createCharacter(preferredCenter: vec2) {
|
||||
this.character = new PlayerCharacterPhysical(
|
||||
this.character = new CharacterPhysical(
|
||||
this.playerInfo.name.slice(0, 20),
|
||||
this.sumKills,
|
||||
this.sumDeaths,
|
||||
|
|
@ -52,7 +52,7 @@ export abstract class PlayerBase extends CommandReceiver {
|
|||
|
||||
const playerBoundingCircle = new Circle(
|
||||
playerPosition,
|
||||
PlayerCharacterPhysical.boundRadius,
|
||||
CharacterPhysical.boundRadius,
|
||||
);
|
||||
|
||||
const playerBoundingBox = getBoundingBoxOfCircle(playerBoundingCircle);
|
||||
|
|
@ -69,6 +69,6 @@ export abstract class PlayerBase extends CommandReceiver {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
this.character?.kill();
|
||||
this.character?.onDie();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
TransportEvents,
|
||||
SetAspectRatioActionCommand,
|
||||
calculateViewArea,
|
||||
SecondaryActionCommand,
|
||||
settings,
|
||||
PlayerInformation,
|
||||
CharacterTeam,
|
||||
|
|
@ -26,18 +25,15 @@ import {
|
|||
} from 'shared';
|
||||
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||
import { PlayerCharacterPhysical } from '../objects/player-character-physical';
|
||||
import { CharacterPhysical } from '../objects/character-physical';
|
||||
import { PlayerContainer } from './player-container';
|
||||
import { PlayerBase } from './player-base';
|
||||
import { DeltaTimeCalculator } from '../helper/delta-time-calculator';
|
||||
|
||||
export class Player extends PlayerBase {
|
||||
// default, until the clients sends its real value
|
||||
private aspectRatio: number = 16 / 9;
|
||||
private isActive = true;
|
||||
|
||||
private objectsPreviouslyInViewArea: Array<GameObject> = [];
|
||||
private pingDeltaTime = new DeltaTimeCalculator();
|
||||
private _latency?: number;
|
||||
|
||||
protected commandExecutors: CommandExecutors = {
|
||||
[SetAspectRatioActionCommand.type]: (v: SetAspectRatioActionCommand) =>
|
||||
|
|
@ -57,31 +53,10 @@ export class Player extends PlayerBase {
|
|||
private readonly socket: SocketIO.Socket,
|
||||
) {
|
||||
super(playerInfo, playerContainer, objectContainer, team);
|
||||
|
||||
this.createCharacter();
|
||||
|
||||
socket.on(
|
||||
TransportEvents.Pong,
|
||||
() => (this._latency = this.pingDeltaTime.getNextDeltaTimeInSeconds()),
|
||||
);
|
||||
|
||||
this.measureLatency();
|
||||
this.step(0);
|
||||
}
|
||||
|
||||
public measureLatency() {
|
||||
this.pingDeltaTime.getNextDeltaTimeInSeconds(true);
|
||||
this.socket.emit(TransportEvents.Ping);
|
||||
|
||||
if (this.isActive) {
|
||||
setTimeout(this.measureLatency.bind(this), 10000);
|
||||
}
|
||||
}
|
||||
|
||||
public get latency(): number | undefined {
|
||||
return this._latency;
|
||||
}
|
||||
|
||||
protected createCharacter() {
|
||||
const preferredCenter = this.playerContainer.players.find(
|
||||
(p) => p.character?.isAlive && p.team === this.team,
|
||||
|
|
@ -191,7 +166,7 @@ export class Player extends PlayerBase {
|
|||
const playersInViewArea = this.objectContainer
|
||||
.findIntersecting(bb)
|
||||
.map((o) => o.gameObject)
|
||||
.filter((g) => g instanceof PlayerCharacterPhysical);
|
||||
.filter((g) => g instanceof CharacterPhysical);
|
||||
|
||||
const otherPlayers = this.playerContainer.players.filter(
|
||||
(p) => p.character?.isAlive && playersInViewArea.indexOf(p.character!) < 0,
|
||||
|
|
@ -222,6 +197,5 @@ export class Player extends PlayerBase {
|
|||
|
||||
public destroy() {
|
||||
super.destroy();
|
||||
this.isActive = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
minlength="1"
|
||||
maxlength="20"
|
||||
placeholder=" "
|
||||
id="playerName"
|
||||
name="playerName"
|
||||
id="name"
|
||||
name="name"
|
||||
type="text"
|
||||
/>
|
||||
<label for="playerName">Choose a name</label>
|
||||
<label for="name">Choose a name</label>
|
||||
</div>
|
||||
|
||||
<div id="server-container"></div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {
|
|||
LampBase,
|
||||
overrideDeserialization,
|
||||
PlanetBase,
|
||||
PlayerCharacterBase,
|
||||
CharacterBase,
|
||||
ProjectileBase,
|
||||
} from 'shared';
|
||||
import { LampView } from './scripts/objects/lamp-view';
|
||||
|
|
@ -17,9 +17,9 @@ import '../static/favicons/favicon-32x32.png';
|
|||
import '../static/favicons/favicon.ico';
|
||||
import { LandingPageBackground } from './scripts/landing-page-background';
|
||||
import { JoinFormHandler } from './scripts/join-form-handler';
|
||||
import { handleFullScreen } from './scripts/handle-full-screen';
|
||||
import { handleFullScreen } from './scripts/helper/handle-full-screen';
|
||||
import { Game } from './scripts/game';
|
||||
import { PlayerCharacterView } from './scripts/objects/player-character-view';
|
||||
import { CharacterView } from './scripts/objects/character-view';
|
||||
import { handleInsights } from './scripts/handle-insights';
|
||||
import { getInsightsFromRenderer } from './scripts/get-insights-from-renderer';
|
||||
import { Renderer } from 'sdf-2d';
|
||||
|
|
@ -32,12 +32,13 @@ import { VibrationHandler } from './scripts/vibration-handler';
|
|||
|
||||
glMatrix.setMatrixArrayType(Array);
|
||||
|
||||
overrideDeserialization(PlayerCharacterBase, PlayerCharacterView);
|
||||
overrideDeserialization(CharacterBase, CharacterView);
|
||||
overrideDeserialization(PlanetBase, PlanetView);
|
||||
overrideDeserialization(LampBase, LampView);
|
||||
overrideDeserialization(ProjectileBase, ProjectileView);
|
||||
|
||||
const landingUI = document.querySelector('#landing-ui') as HTMLElement;
|
||||
const nameInput = document.querySelector('#name') as HTMLInputElement;
|
||||
const joinGameForm = document.querySelector('#join-game-form') as HTMLFormElement;
|
||||
const serverContainer = document.querySelector('#server-container') as HTMLElement;
|
||||
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
|
||||
|
|
@ -114,6 +115,11 @@ const main = async () => {
|
|||
try {
|
||||
let game: Game;
|
||||
|
||||
const storedUserName = localStorage?.getItem('userName');
|
||||
if (storedUserName) {
|
||||
nameInput.value = JSON.parse(storedUserName);
|
||||
}
|
||||
|
||||
const firstClickListener = () => {
|
||||
SoundHandler.initialize(
|
||||
() => {
|
||||
|
|
@ -166,6 +172,9 @@ const main = async () => {
|
|||
hide(spinner);
|
||||
|
||||
const playerDecision = await joinHandler.getPlayerDecision();
|
||||
|
||||
localStorage?.setItem('userName', JSON.stringify(playerDecision.name));
|
||||
|
||||
if (!history.state) {
|
||||
history.pushState(true, '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { CommandGenerator, PrimaryActionCommand, SecondaryActionCommand } from '
|
|||
import { Game } from '../game';
|
||||
|
||||
export class MouseListener extends CommandGenerator {
|
||||
constructor(private readonly game: Game) {
|
||||
constructor(private target: HTMLElement, private readonly game: Game) {
|
||||
super();
|
||||
|
||||
addEventListener('mousedown', this.mouseDownListener);
|
||||
addEventListener('contextmenu', this.contextMenuListener);
|
||||
target.addEventListener('mousedown', this.mouseDownListener);
|
||||
target.addEventListener('contextmenu', this.contextMenuListener);
|
||||
}
|
||||
|
||||
private mouseDownListener = (event: MouseEvent) => {
|
||||
|
|
@ -32,7 +32,7 @@ export class MouseListener extends CommandGenerator {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
removeEventListener('mousedown', this.mouseDownListener);
|
||||
removeEventListener('contextmenu', this.contextMenuListener);
|
||||
this.target.removeEventListener('mousedown', this.mouseDownListener);
|
||||
this.target.removeEventListener('contextmenu', this.contextMenuListener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Renderer, renderNoise } from 'sdf-2d';
|
||||
import {
|
||||
CircleLight,
|
||||
FilteringOptions,
|
||||
Renderer,
|
||||
renderNoise,
|
||||
runAnimation,
|
||||
WrapOptions,
|
||||
} from 'sdf-2d';
|
||||
import {
|
||||
deserialize,
|
||||
TransportEvents,
|
||||
|
|
@ -9,22 +16,23 @@ import {
|
|||
clamp,
|
||||
UpdateGameState,
|
||||
GameEndCommand,
|
||||
CharacterTeam,
|
||||
ServerAnnouncement,
|
||||
GameStartCommand,
|
||||
CommandReceiver,
|
||||
CommandExecutors,
|
||||
Command,
|
||||
settings,
|
||||
} from 'shared';
|
||||
import io from 'socket.io-client';
|
||||
import { KeyboardListener } from './commands/keyboard-listener';
|
||||
import { MouseListener } from './commands/mouse-listener';
|
||||
import { TouchListener } from './commands/touch-listener';
|
||||
import { CommandSocket } from './commands/command-socket';
|
||||
import { startAnimation } from './start-animation';
|
||||
import { PlayerDecision } from './join-form-handler';
|
||||
import { GameObjectContainer } from './objects/game-object-container';
|
||||
import parser from 'socket.io-msgpack-parser';
|
||||
import { BlobShape } from './shapes/blob-shape';
|
||||
import { PlanetShape } from './shapes/planet-shape';
|
||||
|
||||
export class Game extends CommandReceiver {
|
||||
public gameObjects = new GameObjectContainer(this);
|
||||
|
|
@ -59,8 +67,8 @@ export class Game extends CommandReceiver {
|
|||
this.progressBar.appendChild(this.redPlanetCountElement);
|
||||
|
||||
this.keyboardListener = new KeyboardListener();
|
||||
this.mouseListener = new MouseListener(this);
|
||||
this.touchListener = new TouchListener(this.overlay, this.overlay, this);
|
||||
this.mouseListener = new MouseListener(this.canvas, this);
|
||||
this.touchListener = new TouchListener(this.canvas, this.overlay, this);
|
||||
}
|
||||
|
||||
private initialize() {
|
||||
|
|
@ -111,9 +119,7 @@ export class Game extends CommandReceiver {
|
|||
|
||||
this.isBetweenGames = false;
|
||||
|
||||
this.socket.emit(TransportEvents.PlayerJoining, {
|
||||
name: this.playerDecision.playerName,
|
||||
} as PlayerInformation);
|
||||
this.socket.emit(TransportEvents.PlayerJoining, this.playerDecision);
|
||||
}
|
||||
|
||||
protected defaultCommandExecutor(c: Command) {
|
||||
|
|
@ -200,7 +206,35 @@ export class Game extends CommandReceiver {
|
|||
|
||||
this.initialize();
|
||||
|
||||
await startAnimation(this.canvas, this.gameLoop.bind(this), noiseTexture);
|
||||
await runAnimation(
|
||||
this.canvas,
|
||||
[
|
||||
PlanetShape.descriptor,
|
||||
BlobShape.descriptor,
|
||||
{
|
||||
...CircleLight.descriptor,
|
||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 16],
|
||||
},
|
||||
],
|
||||
this.gameLoop.bind(this),
|
||||
{
|
||||
shadowTraceCount: 16,
|
||||
paletteSize: settings.palette.length,
|
||||
colorPalette: settings.palette,
|
||||
enableHighDpiRendering: true,
|
||||
lightCutoffDistance: settings.lightCutoffDistance,
|
||||
textures: {
|
||||
noiseTexture: {
|
||||
source: noiseTexture,
|
||||
overrides: {
|
||||
maxFilter: FilteringOptions.LINEAR,
|
||||
wrapS: WrapOptions.MIRRORED_REPEAT,
|
||||
wrapT: WrapOptions.MIRRORED_REPEAT,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
this.socket.close();
|
||||
this.overlay.innerHTML = '';
|
||||
this.keyboardListener.destroy();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { SoundHandler, Sounds } from './sound-handler';
|
||||
import { SoundHandler, Sounds } from '../sound-handler';
|
||||
|
||||
export const handleFullScreen = (
|
||||
minimizeButton: HTMLElement,
|
||||
|
|
@ -5,7 +5,7 @@ import parser from 'socket.io-msgpack-parser';
|
|||
import { SoundHandler, Sounds } from './sound-handler';
|
||||
|
||||
export type PlayerDecision = {
|
||||
playerName: string;
|
||||
name: string;
|
||||
server: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import {
|
||||
CircleLight,
|
||||
compile,
|
||||
FilteringOptions,
|
||||
hsl,
|
||||
NoisyPolygonFactory,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Renderer } from 'sdf-2d';
|
|||
import {
|
||||
Circle,
|
||||
Id,
|
||||
PlayerCharacterBase,
|
||||
CharacterBase,
|
||||
CharacterTeam,
|
||||
settings,
|
||||
UpdateProperty,
|
||||
|
|
@ -14,7 +14,7 @@ import { SoundHandler, Sounds } from '../sound-handler';
|
|||
import { VibrationHandler } from '../vibration-handler';
|
||||
import { ViewObject } from './view-object';
|
||||
|
||||
export class PlayerCharacterView extends PlayerCharacterBase implements ViewObject {
|
||||
export class CharacterView extends CharacterBase implements ViewObject {
|
||||
private shape: BlobShape;
|
||||
private nameElement: HTMLElement = document.createElement('div');
|
||||
private statsElement: HTMLElement = document.createElement('div');
|
||||
|
|
@ -81,7 +81,7 @@ export class PlayerCharacterView extends PlayerCharacterBase implements ViewObje
|
|||
}
|
||||
}
|
||||
|
||||
public kill() {
|
||||
public onDie() {
|
||||
if (this.isMainCharacter) {
|
||||
VibrationHandler.vibrate(150);
|
||||
}
|
||||
|
|
@ -11,12 +11,12 @@ import {
|
|||
} from 'shared';
|
||||
import { Game } from '../game';
|
||||
import { Camera } from './camera';
|
||||
import { PlayerCharacterView } from './player-character-view';
|
||||
import { CharacterView } from './character-view';
|
||||
import { ViewObject } from './view-object';
|
||||
|
||||
export class GameObjectContainer extends CommandReceiver {
|
||||
protected objects: Map<Id, ViewObject> = new Map();
|
||||
public player!: PlayerCharacterView;
|
||||
public player!: CharacterView;
|
||||
public camera!: Camera;
|
||||
|
||||
protected commandExecutors: CommandExecutors = {
|
||||
|
|
@ -25,7 +25,7 @@ export class GameObjectContainer extends CommandReceiver {
|
|||
this.deleteObject(this.camera.id);
|
||||
}
|
||||
|
||||
this.player = c.character as PlayerCharacterView;
|
||||
this.player = c.character as CharacterView;
|
||||
this.player.isMainCharacter = true;
|
||||
|
||||
this.camera = new Camera(this.game);
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
import {
|
||||
CircleLight,
|
||||
FilteringOptions,
|
||||
Renderer,
|
||||
runAnimation,
|
||||
WrapOptions,
|
||||
} from 'sdf-2d';
|
||||
import { settings } from 'shared';
|
||||
import { BlobShape } from './shapes/blob-shape';
|
||||
import { PlanetShape } from './shapes/planet-shape';
|
||||
|
||||
export const startAnimation = async (
|
||||
canvas: HTMLCanvasElement,
|
||||
draw: (r: Renderer, current: number, delta: number) => boolean,
|
||||
noiseTexture: TexImageSource,
|
||||
): Promise<void> =>
|
||||
await runAnimation(
|
||||
canvas,
|
||||
[
|
||||
PlanetShape.descriptor,
|
||||
BlobShape.descriptor,
|
||||
{
|
||||
...CircleLight.descriptor,
|
||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 16],
|
||||
},
|
||||
],
|
||||
draw,
|
||||
{
|
||||
shadowTraceCount: 16,
|
||||
paletteSize: settings.palette.length,
|
||||
colorPalette: settings.palette,
|
||||
enableHighDpiRendering: true,
|
||||
lightCutoffDistance: settings.lightCutoffDistance,
|
||||
textures: {
|
||||
noiseTexture: {
|
||||
source: noiseTexture,
|
||||
overrides: {
|
||||
maxFilter: FilteringOptions.LINEAR,
|
||||
wrapS: WrapOptions.MIRRORED_REPEAT,
|
||||
wrapT: WrapOptions.MIRRORED_REPEAT,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { PlayerCharacterBase } from '../../objects/types/player-character-base';
|
||||
import { CharacterBase } from '../../objects/types/character-base';
|
||||
import { serializable } from '../../serialization/serializable';
|
||||
import { Command } from '../command';
|
||||
|
||||
@serializable
|
||||
export class CreatePlayerCommand extends Command {
|
||||
public constructor(public readonly character: PlayerCharacterBase) {
|
||||
public constructor(public readonly character: CharacterBase) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { CharacterTeam } from '../../objects/types/character-team';
|
||||
import { CharacterTeam } from '../../objects/types/character-base';
|
||||
import { serializable } from '../../serialization/serializable';
|
||||
import { Command } from '../command';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Id } from '../../communication/id';
|
||||
import { CharacterTeam } from '../../objects/types/character-team';
|
||||
import { CharacterTeam } from '../../objects/types/character-base';
|
||||
import { serializable } from '../../serialization/serializable';
|
||||
import { Command } from '../command';
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,6 @@ export class Circle {
|
|||
return vec2.distance(this.center, target) - this.radius;
|
||||
}
|
||||
|
||||
public distanceBetween(target: Circle): number {
|
||||
return vec2.distance(target.center, this.center) - this.radius - target.radius;
|
||||
}
|
||||
|
||||
public toArray(): Array<any> {
|
||||
return [this.center, this.radius];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ export * from './serialization/serialize';
|
|||
export * from './serialization/serializes-to';
|
||||
export * from './serialization/serializable';
|
||||
export * from './serialization/override-deserialization';
|
||||
export * from './objects/types/character-team';
|
||||
export * from './objects/types/player-character-base';
|
||||
export * from './objects/types/character-base';
|
||||
export * from './objects/types/lamp-base';
|
||||
export * from './objects/types/planet-base';
|
||||
export * from './objects/types/projectile-base';
|
||||
|
|
|
|||
|
|
@ -2,10 +2,15 @@ import { Id } from '../../communication/id';
|
|||
import { Circle } from '../../helper/circle';
|
||||
import { serializable } from '../../serialization/serializable';
|
||||
import { GameObject } from '../game-object';
|
||||
import { CharacterTeam } from './character-team';
|
||||
|
||||
export enum CharacterTeam {
|
||||
decla = 'decla',
|
||||
neutral = 'neutral',
|
||||
red = 'red',
|
||||
}
|
||||
|
||||
@serializable
|
||||
export class PlayerCharacterBase extends GameObject {
|
||||
export class CharacterBase extends GameObject {
|
||||
constructor(
|
||||
id: Id,
|
||||
public name: string,
|
||||
|
|
@ -26,7 +31,7 @@ export class PlayerCharacterBase extends GameObject {
|
|||
this.health = health;
|
||||
}
|
||||
|
||||
public kill() {}
|
||||
public onDie() {}
|
||||
|
||||
public setKillCount(killCount: number) {
|
||||
this.killCount = killCount;
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
export enum CharacterTeam {
|
||||
decla = 'decla',
|
||||
neutral = 'neutral',
|
||||
red = 'red',
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@ import { vec2 } from 'gl-matrix';
|
|||
import { settings } from '../../settings';
|
||||
import { serializable } from '../../serialization/serializable';
|
||||
import { GameObject } from '../game-object';
|
||||
import { CharacterTeam } from './character-team';
|
||||
import { Id } from '../../communication/id';
|
||||
import { CharacterTeam } from './character-base';
|
||||
|
||||
@serializable
|
||||
export class ProjectileBase extends GameObject {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { rgb255 } from './helper/rgb255';
|
||||
import { CharacterTeam } from './objects/types/character-team';
|
||||
import { CharacterTeam } from './objects/types/character-base';
|
||||
|
||||
const declaColor = rgb255(64, 105, 165);
|
||||
const neutralColor = rgb255(82, 165, 64);
|
||||
|
|
@ -19,6 +19,7 @@ export const settings = {
|
|||
worldRadius: 10000,
|
||||
objectsOnCircleLength: 0.002,
|
||||
planetEdgeCount: 7,
|
||||
playerKillPoint: 10,
|
||||
takeControlTimeInSeconds: 4,
|
||||
loseControlTimeInSeconds: 24,
|
||||
planetPointGenerationInterval: 1.5,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue