Add basic multiplayer

This commit is contained in:
schmelczerandras 2020-10-05 19:07:17 +02:00
parent 0f0a1eaf67
commit 46a48e7c15
113 changed files with 1362 additions and 754 deletions

View file

@ -0,0 +1,31 @@
import { id, CharacterBase } from 'shared';
import { ImmutableBoundingBox } from '../physics/bounds/immutable-bounding-box';
import { PhysicalGameObject } from '../physics/physical-game-object';
import { CirclePhysics } from './circle-physics';
export class CharacterPhysics extends CharacterBase implements PhysicalGameObject {
public readonly canCollide = true;
public readonly isInverted = false;
public readonly canMove = true;
constructor(head: CirclePhysics, leftFoot: CirclePhysics, rightFoot: CirclePhysics) {
super(id(), head, leftFoot, rightFoot);
}
private boundingBox?: ImmutableBoundingBox;
public getBoundingBox(): ImmutableBoundingBox {
if (!this.boundingBox) {
this.boundingBox = (this.head as CirclePhysics).boundingBox;
(this.head as CirclePhysics).boundingBox.owner = this;
}
return this.boundingBox;
}
public toJSON(): any {
const { type, id, head, leftFoot, rightFoot } = this;
return [type, id, head, leftFoot, rightFoot];
}
}

View file

@ -0,0 +1,76 @@
import { vec2 } from 'gl-matrix';
import { Circle } from 'shared';
import { BoundingBox } from '../physics/bounds/bounding-box';
import { BoundingBoxBase } from '../physics/bounds/bounding-box-base';
export class CirclePhysics implements Circle {
private _boundingBox: BoundingBox;
constructor(private _center: vec2, private _radius: number) {
this._boundingBox = new BoundingBox(null);
this.recalculateBoundingBox();
}
public get boundingBox(): BoundingBoxBase {
return this._boundingBox;
}
public get center(): vec2 {
return this._center;
}
public set center(value: vec2) {
this._center = value;
this.recalculateBoundingBox();
}
public get radius(): number {
return this._radius;
}
public set radius(value: number) {
this._radius = value;
this.recalculateBoundingBox();
}
public distance(target: vec2): number {
return vec2.distance(target, this.center) - this.radius;
}
public distanceBetween(target: CirclePhysics): number {
return vec2.distance(target.center, this.center) - this.radius - target.radius;
}
public areIntersecting(other: CirclePhysics): boolean {
return other.distance(this.center) < this.radius;
}
public isInside(other: CirclePhysics): boolean {
return other.distance(this.center) < -this.radius;
}
public getPerimeterPoints(count: number): Array<vec2> {
const result: Array<vec2> = [];
for (let i = 0; i < count; i++) {
result.push(
vec2.fromValues(
Math.cos((2 * Math.PI * i) / count) * this.radius + this.center.x,
Math.sin((2 * Math.PI * i) / count) * this.radius + this.center.y
)
);
}
return result;
}
private recalculateBoundingBox() {
this._boundingBox.xMin = this.center.x - this._radius;
this._boundingBox.xMax = this.center.x + this._radius;
this._boundingBox.yMin = this.center.y - this._radius;
this._boundingBox.yMax = this.center.y + this._radius;
}
public toJSON(): any {
const { center, radius } = this;
return { center, radius };
}
}

View file

@ -0,0 +1,36 @@
import { vec2, vec3 } from 'gl-matrix';
import { LampBase, settings, id } from 'shared';
import { ImmutableBoundingBox } from '../physics/bounds/immutable-bounding-box';
import { PhysicalGameObject } from '../physics/physical-game-object';
export class LampPhysics extends LampBase implements PhysicalGameObject {
public readonly canCollide = false;
public readonly isInverted = false;
public readonly canMove = false;
constructor(center: vec2, color: vec3, lightness: number) {
super(id(), center, color, lightness);
}
private boundingBox?: ImmutableBoundingBox;
public getBoundingBox(): ImmutableBoundingBox {
if (!this.boundingBox) {
this.boundingBox = new ImmutableBoundingBox(
this,
this.center.x - settings.lightCutoffDistance,
this.center.x + settings.lightCutoffDistance,
this.center.y - settings.lightCutoffDistance,
this.center.y + settings.lightCutoffDistance
);
}
return this.boundingBox;
}
public toJSON(): any {
const { type, id, center, color, lightness } = this;
return [type, id, center, color, lightness];
}
}

View file

@ -0,0 +1,48 @@
import { vec2 } from 'gl-matrix';
import { clamp01, mix, TunnelBase, id } from 'shared';
import { PhysicalGameObject } from '../physics/physical-game-object';
import { ImmutableBoundingBox } from '../physics/bounds/immutable-bounding-box';
export class TunnelPhysics extends TunnelBase implements PhysicalGameObject {
public readonly canCollide = true;
public readonly isInverted = true;
public readonly canMove = false;
private boundingBox?: ImmutableBoundingBox;
constructor(from: vec2, to: vec2, fromRadius: number, toRadius: number) {
super(id(), from, to, fromRadius, toRadius);
}
public distance(target: vec2): number {
const toFromDelta = vec2.subtract(vec2.create(), this.to, this.from);
const targetFromDelta = vec2.subtract(vec2.create(), target, this.from);
const h = clamp01(
vec2.dot(targetFromDelta, toFromDelta) / vec2.dot(toFromDelta, toFromDelta)
);
return (
vec2.distance(targetFromDelta, vec2.scale(vec2.create(), toFromDelta, h)) -
mix(this.fromRadius, this.toRadius, h)
);
}
public getBoundingBox(): ImmutableBoundingBox {
if (!this.boundingBox) {
const xMin = Math.min(this.from.x - this.fromRadius, this.to.x - this.toRadius);
const yMin = Math.min(this.from.y - this.fromRadius, this.to.y - this.toRadius);
const xMax = Math.max(this.from.x + this.fromRadius, this.to.x + this.toRadius);
const yMax = Math.max(this.from.y + this.fromRadius, this.to.y + this.toRadius);
this.boundingBox = new ImmutableBoundingBox(this, xMin, xMax, yMin, yMax, true);
}
return this.boundingBox;
}
public toJSON(): any {
const { type, id, from, to, fromRadius, toRadius } = this;
return [type, id, from, to, fromRadius, toRadius];
}
}