Add basic multiplayer
This commit is contained in:
parent
0f0a1eaf67
commit
46a48e7c15
113 changed files with 1362 additions and 754 deletions
31
backend/src/objects/character-physics.ts
Normal file
31
backend/src/objects/character-physics.ts
Normal 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];
|
||||
}
|
||||
}
|
||||
76
backend/src/objects/circle-physics.ts
Normal file
76
backend/src/objects/circle-physics.ts
Normal 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 };
|
||||
}
|
||||
}
|
||||
36
backend/src/objects/lamp-physics.ts
Normal file
36
backend/src/objects/lamp-physics.ts
Normal 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];
|
||||
}
|
||||
}
|
||||
48
backend/src/objects/tunnel-physics.ts
Normal file
48
backend/src/objects/tunnel-physics.ts
Normal 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];
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue