Update physics

This commit is contained in:
schmelczerandras 2020-10-02 15:12:30 +02:00
commit d9d8d03c36
27 changed files with 445 additions and 550 deletions

View file

@ -1,31 +1,30 @@
import { vec3 } from 'gl-matrix';
import { CircleLight, compile, Flashlight, Renderer } from 'sdf-2d';
import { vec2 } from 'gl-matrix';
import { CircleLight, compile, Flashlight, InvertedTunnel, Renderer } from 'sdf-2d';
import { CommandBroadcaster } from './commands/command-broadcaster';
import { RenderCommand } from './graphics/commands/render';
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
import { prettyPrint } from './helper/pretty-print';
import { rgb } from './helper/rgb';
import { IGame } from './i-game';
import { KeyboardListener } from './input/keyboard-listener';
import { MouseListener } from './input/mouse-listener';
import { TouchListener } from './input/touch-listener';
import { GameObject } from './objects/game-object';
import { Objects } from './objects/objects';
import { Camera } from './objects/types/camera';
import { Character } from './objects/types/character';
import { createDungeon } from './objects/world/create-dungeon';
import { BoundingBoxBase } from './physics/bounds/bounding-box-base';
import { MoveToCommand } from './physics/commands/move-to';
import { StepCommand } from './physics/commands/step';
import { TeleportToCommand } from './physics/commands/teleport-to';
import { Physics } from './physics/physics';
import { BoundingBoxBase } from './shapes/bounding-box-base';
import { CircleShape } from './shapes/types/circle-shape';
import { TunnelShape } from './shapes/types/tunnel-shape';
import { settings } from './settings';
import { BlobShape } from './shapes/types/blob-shape';
export class Game implements IGame {
public readonly objects = new Objects();
public readonly physics = new Physics();
public readonly camera = new Camera();
private previousTime?: DOMHighResTimeStamp = null;
private previousFpsValues: Array<number> = [];
private character: Character;
private renderer: Renderer;
private rendererPromise: Promise<Renderer>;
@ -34,8 +33,6 @@ export class Game implements IGame {
constructor() {
const canvas: HTMLCanvasElement = document.querySelector('canvas#main');
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
new CommandBroadcaster(
[
new KeyboardListener(document.body),
@ -48,16 +45,16 @@ export class Game implements IGame {
this.rendererPromise = compile(
canvas,
[
CircleShape.descriptor,
TunnelShape.descriptor,
InvertedTunnel.descriptor,
Flashlight.descriptor,
BlobShape.descriptor,
CircleLight.descriptor,
],
[
vec3.fromValues(0, 0, 0),
vec3.fromValues(224 / 255, 96 / 255, 126 / 255),
vec3.fromValues(119 / 255, 173 / 255, 120 / 255),
]
{
shadowTraceCount: 12,
paletteSize: 10,
enableStopwatch: true,
}
);
this.initializeScene();
this.physics.start();
@ -67,16 +64,22 @@ export class Game implements IGame {
this.renderer = await this.rendererPromise;
this.renderer.setRuntimeSettings({
isWorldInverted: true,
ambientLight: vec3.fromValues(0.35, 0.1, 0.45),
shadowLength: 300,
ambientLight: rgb(0.35, 0.1, 0.45),
colorPalette: [
rgb(0.4, 1, 0.6),
rgb(1, 1, 0),
rgb(0.3, 1, 1),
rgb(0.3, 1, 1),
rgb(0.3, 1, 1),
rgb(0.3, 1, 1),
rgb(0.3, 1, 1),
],
enableHighDpiRendering: false,
lightCutoffDistance: settings.lightCutoffDistance,
});
requestAnimationFrame(this.gameLoop.bind(this));
}
public addObject(o: GameObject) {
this.objects.addObject(o);
}
public get viewArea(): BoundingBoxBase {
return this.camera.viewArea;
}
@ -86,51 +89,38 @@ export class Game implements IGame {
}
private initializeScene() {
const start = createDungeon(this.objects, this.physics);
createDungeon(this.objects, this.physics);
//createDungeon(this.objects, this.physics);
this.character = new Character(this);
// this.physics.addDynamicBoundingBox(this.character.boundingBox);
this.addObject(this.character);
this.addObject(this.camera);
let pos: any = localStorage.getItem('character-position');
pos = pos ? JSON.parse(pos) : start.from;
this.character = new Character(this.physics, this);
this.objects.addObject(this.character);
this.objects.addObject(this.camera);
let pos: any = localStorage.getItem('characterPosition');
pos = pos ? JSON.parse(pos) : vec2.fromValues(0, 0);
this.character.sendCommand(new TeleportToCommand(pos));
}
private handleVisibilityChange() {
if (!document.hidden) {
this.previousTime = null;
}
}
private deltaTimeCalculator = new DeltaTimeCalculator();
private gameLoop(time: DOMHighResTimeStamp) {
if (this.previousTime === null) {
this.previousTime = time;
}
const deltaTime = time - this.previousTime;
this.previousTime = time;
const deltaTime = this.deltaTimeCalculator.getNextDeltaTime(time);
this.objects.sendCommand(new StepCommand(deltaTime));
this.camera.sendCommand(new MoveToCommand(this.character.position));
this.camera.sendCommand(new RenderCommand(this.renderer));
const shouldBeDrawn = this.physics
.findIntersecting(this.camera.viewArea)
.map((b) => b.shape?.gameObject);
.map((b) => b.owner);
for (const object of shouldBeDrawn) {
object?.sendCommand(new RenderCommand(this.renderer));
}
this.character.sendCommand(new RenderCommand(this.renderer));
this.renderer.renderDrawables();
this.overlay.innerText = prettyPrint(this.renderer.insights);
localStorage.setItem('character-position', JSON.stringify(this.character.position));
localStorage.setItem('characterPosition', JSON.stringify(this.character.position));
requestAnimationFrame(this.gameLoop.bind(this));
}
}

View file

@ -1,5 +0,0 @@
export const exponentialDecay = (
accumulator: number,
nextValue: number,
biasOfNextValue: number
) => accumulator * (1 - biasOfNextValue) + nextValue * biasOfNextValue;

View file

@ -1,29 +0,0 @@
export const getCombinations = (values: Array<Array<number>>): Array<Array<number>> => {
if (!values.every((a) => a.length > 0)) {
return [];
}
const result: Array<Array<number>> = [];
const counters = values.map((_) => 0);
const increaseCounter = (i: number) => {
if (i >= counters.length) {
return false;
}
counters[i]++;
if (counters[i] >= values[i].length) {
counters[i] = 0;
return increaseCounter(i + 1);
}
return true;
};
do {
result.push(values.map((v, i) => v[counters[i]]));
} while (increaseCounter(0));
return result;
};

View file

@ -0,0 +1,3 @@
import { vec3 } from 'gl-matrix';
export const rgb = (r: number, g: number, b: number): vec3 => vec3.fromValues(r, g, b);

View file

@ -0,0 +1,4 @@
import { vec3 } from 'gl-matrix';
export const rgb255 = (r: number, g: number, b: number): vec3 =>
vec3.fromValues(r / 255, g / 255, b / 255);

View file

@ -1,29 +0,0 @@
export const waitWhileFalse = (body: () => boolean): Promise<void> => {
let resolveOnDone: () => void;
let rejectOnDone: (e: Error) => void;
const onDone = new Promise<void>((resolve, reject) => {
resolveOnDone = resolve;
rejectOnDone = reject;
});
const waiter = () => {
let success: boolean;
try {
success = body();
} catch (e) {
rejectOnDone(e);
return;
}
if (success) {
resolveOnDone();
} else {
requestAnimationFrame(waiter);
}
};
waiter();
return onDone;
};

View file

@ -1,8 +1,6 @@
import { GameObject } from './objects/game-object';
import { BoundingBoxBase } from './shapes/bounding-box-base';
import { BoundingBoxBase } from './physics/bounds/bounding-box-base';
export interface IGame {
addObject(o: GameObject): void;
readonly viewArea: BoundingBoxBase;
findIntersecting(box: BoundingBoxBase): Array<BoundingBoxBase>;
}

View file

@ -2,8 +2,8 @@ import { vec2 } from 'gl-matrix';
import { RenderCommand } from '../../graphics/commands/render';
import { CursorMoveCommand } from '../../input/commands/cursor-move-command';
import { ZoomCommand } from '../../input/commands/zoom';
import { BoundingBox } from '../../physics/bounds/bounding-box';
import { MoveToCommand } from '../../physics/commands/move-to';
import { BoundingBox } from '../../shapes/bounding-box';
import { GameObject } from '../game-object';
export class Camera extends GameObject {

View file

@ -1,41 +1,61 @@
import { vec2, vec3 } from 'gl-matrix';
import { vec2 } from 'gl-matrix';
import { Flashlight } from 'sdf-2d';
import { RenderCommand } from '../../graphics/commands/render';
import { rgb } from '../../helper/rgb';
import { IGame } from '../../i-game';
import { KeyDownCommand } from '../../input/commands/key-down';
import { KeyUpCommand } from '../../input/commands/key-up';
import { SwipeCommand } from '../../input/commands/swipe';
import { BoundingBoxBase } from '../../physics/bounds/bounding-box-base';
import { BoundingCircle } from '../../physics/bounds/bounding-circle';
import { StepCommand } from '../../physics/commands/step';
import { TeleportToCommand } from '../../physics/commands/teleport-to';
import { IShape } from '../../shapes/i-shape';
import { DynamicPhysicalObject } from '../../physics/dynamic-physical-object';
import { Physics } from '../../physics/physics';
import { BlobShape } from '../../shapes/types/blob-shape';
import { GameObject } from '../game-object';
export class Character extends GameObject {
export class Character extends DynamicPhysicalObject {
protected head: BoundingCircle;
protected leftFoot: BoundingCircle;
protected rightFoot: BoundingCircle;
private keysDown: Set<string> = new Set();
private light = new Flashlight(
vec2.create(),
vec3.fromValues(1, 0.6, 0.45),
1.5,
vec2.fromValues(0, 0),
rgb(1, 0.6, 0.45),
0.5,
vec2.fromValues(-1, 0)
);
private shape = new BlobShape(vec2.create());
private shape = new BlobShape();
private boundingCircle = new BoundingCircle(this, vec2.create(), 50);
private center = vec2.create();
private static speed = 1.5;
constructor(private game: IGame) {
super();
constructor(physics: Physics, private game: IGame) {
super(physics, true);
this.addCommandExecutor(RenderCommand, this.draw.bind(this));
this.addCommandExecutor(TeleportToCommand, (c) => this.setPosition(c.position));
this.addCommandExecutor(KeyDownCommand, (c) => this.keysDown.add(c.key));
this.addCommandExecutor(KeyUpCommand, (c) => this.keysDown.delete(c.key));
this.addCommandExecutor(StepCommand, this.stepHandler.bind(this));
this.addCommandExecutor(SwipeCommand, (c) => {
this.tryMoving(vec2.multiply(vec2.create(), c.delta, this.game.viewArea.size));
});
this.head = new BoundingCircle(this, this.center, 50);
this.leftFoot = new BoundingCircle(this, this.center, 50);
this.rightFoot = new BoundingCircle(this, this.center, 50);
this.shape.setCircles([this.head, this.leftFoot, this.rightFoot]);
this.addToPhysics();
}
public get position(): vec2 {
return this.shape.center;
public distance(target: vec2): number {
return this.shape.minDistance(target);
}
private draw(c: RenderCommand) {
@ -43,73 +63,24 @@ export class Character extends GameObject {
c.renderer.addDrawable(this.light);
}
private tryMoving(delta: vec2, isFirstIteration = true) {
const maxStep = 2;
if (vec2.length(delta) > maxStep) {
let steppedDelta = vec2.normalize(vec2.create(), delta);
vec2.scale(steppedDelta, steppedDelta, maxStep - 0.001);
for (let i = 0; i <= vec2.length(delta) / maxStep - 1; i++) {
this.tryMoving(vec2.clone(steppedDelta), isFirstIteration);
}
steppedDelta = vec2.normalize(vec2.create(), delta);
vec2.scale(steppedDelta, steppedDelta, vec2.length(delta) % maxStep);
this.tryMoving(vec2.clone(steppedDelta), isFirstIteration);
return;
}
const nextShape = this.shape.clone();
vec2.add(nextShape.center, nextShape.center, delta);
const nextNearShapes = this.getNearShapesTo(nextShape);
if (nextNearShapes.length && nextNearShapes[0].distance < 0) {
this.setPosition(nextShape.center);
} else {
if (!isFirstIteration) {
return;
}
const currentNearShapes = this.getNearShapesTo(this.shape);
const intersecting = nextNearShapes
.filter(
(n) =>
currentNearShapes.find((c) => c.shape === n.shape && c.distance <= 0) !==
undefined
)
.sort((e) => Math.abs(e.distance));
if (intersecting.length < 1) {
return;
}
const normal = intersecting[0].shape.normal(this.shape.center);
const maxDistance = intersecting.reduce((p, c) => (p.distance > c.distance ? p : c))
.distance;
vec2.add(delta, delta, vec2.scale(vec2.create(), normal, -maxDistance - 2));
this.tryMoving(delta, false);
}
public get position(): vec2 {
return this.center;
}
private getNearShapesTo(shape: BlobShape): Array<{ shape: IShape; distance: number }> {
return this.game
.findIntersecting(shape.boundingBox)
.filter((b) => b.shape)
.map((b) => ({
shape: b.shape,
// TODO: fix this
distance: b.shape.minDistance(shape.center) + shape.radius - 20,
}))
.sort((e) => e.distance);
public getBoundingCircles(): Array<BoundingCircle> {
return [this.boundingCircle];
}
public getBoundingBox(): BoundingBoxBase {
return this.head.boundingBox;
}
private tryMoving(delta: vec2) {
this.physics.tryMovingDynamicCircle(this.head, delta);
}
private setPosition(value: vec2) {
this.shape.position = value;
//this.head.center = value;
this.light.center = vec2.add(vec2.create(), value, vec2.fromValues(50, -40));
}

View file

@ -1,21 +1,40 @@
import { vec2, vec3 } from 'gl-matrix';
import { CircleLight } from 'sdf-2d';
import { RenderCommand } from '../../graphics/commands/render';
import { BoundingBoxBase } from '../../physics/bounds/bounding-box-base';
import { ImmutableBoundingBox } from '../../physics/bounds/immutable-bounding-box';
import { MoveToCommand } from '../../physics/commands/move-to';
import { GameObject } from '../game-object';
import { PhysicalObject } from '../../physics/physical-object';
import { Physics } from '../../physics/physics';
import { settings } from '../../settings';
export class Lamp extends GameObject {
export class Lamp extends PhysicalObject {
private light: CircleLight;
constructor(center: vec2, color: vec3, lightness: number) {
super();
constructor(center: vec2, color: vec3, lightness: number, physics: Physics) {
super(physics, false);
this.light = new CircleLight(center, color, lightness);
this.addToPhysics();
this.addCommandExecutor(RenderCommand, this.draw.bind(this));
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
}
public distance(target: vec2): number {
return this.light.minDistance(target);
}
public getBoundingBox(): BoundingBoxBase {
return new ImmutableBoundingBox(
this,
this.light.center.x - settings.lightCutoffDistance,
this.light.center.x + settings.lightCutoffDistance,
this.light.center.y - settings.lightCutoffDistance,
this.light.center.y + settings.lightCutoffDistance
);
}
private draw(c: RenderCommand) {
c.renderer.addDrawable(this.light);
}

View file

@ -1,26 +1,52 @@
import { vec2 } from 'gl-matrix';
import { RenderCommand } from '../../graphics/commands/render';
import { BoundingBoxBase } from '../../physics/bounds/bounding-box-base';
import { ImmutableBoundingBox } from '../../physics/bounds/immutable-bounding-box';
import { Physics } from '../../physics/physics';
import { StaticPhysicalObject } from '../../physics/static-physical-object';
import { TunnelShape } from '../../shapes/types/tunnel-shape';
import { GameObject } from '../game-object';
export class Tunnel extends GameObject {
export class Tunnel extends StaticPhysicalObject {
private shape: TunnelShape;
constructor(
physics: Physics,
public readonly from: vec2,
from: vec2,
to: vec2,
fromRadius: number,
toRadius: number
) {
super();
super(physics, true);
this.shape = new TunnelShape(from, to, fromRadius, toRadius);
this.addToPhysics();
this.shape = new TunnelShape(from, to, fromRadius, toRadius, this);
physics.addStaticBoundingBox(this.shape.boundingBox);
this.addCommandExecutor(RenderCommand, this.draw.bind(this));
}
public distance(target: vec2): number {
return this.shape.minDistance(target);
}
public getBoundingBox(): BoundingBoxBase {
const xMin = Math.min(
this.shape.from.x - this.shape.fromRadius,
this.shape.to.x - this.shape.toRadius
);
const yMin = Math.min(
this.shape.from.y - this.shape.fromRadius,
this.shape.to.y - this.shape.toRadius
);
const xMax = Math.max(
this.shape.from.x + this.shape.fromRadius,
this.shape.to.x + this.shape.toRadius
);
const yMax = Math.max(
this.shape.from.y + this.shape.fromRadius,
this.shape.to.y + this.shape.toRadius
);
return new ImmutableBoundingBox(this, xMin, xMax, yMin, yMax, true);
}
private draw(c: RenderCommand) {
c.renderer.addDrawable(this.shape);
}

View file

@ -1,14 +1,15 @@
import { vec2 } from 'gl-matrix';
import { vec2, vec3 } from 'gl-matrix';
import { Random } from '../../helper/random';
import { Physics } from '../../physics/physics';
import { Objects } from '../objects';
import { Lamp } from '../types/lamp';
import { Tunnel } from '../types/tunnel';
export const createDungeon = (objects: Objects, physics: Physics): Tunnel => {
export const createDungeon = (objects: Objects, physics: Physics) => {
let previousRadius = 350;
let previousEnd = vec2.create();
let first: Tunnel;
let tunnelsCountSinceLastLight = 0;
for (let i = 0; i < 500000; i += 500) {
const deltaHeight = (Random.getRandom() - 0.5) * 2000;
@ -24,30 +25,24 @@ export const createDungeon = (objects: Objects, physics: Physics): Tunnel => {
currentToRadius
);
if (!first) {
first = tunnel;
}
objects.addObject(tunnel);
/* if (deltaHeight > 0 && Random.getRandom() > 0.8) {
if (++tunnelsCountSinceLastLight > 3 && Random.getRandom() > 0.6) {
objects.addObject(
new Lamp(
currentEnd,
Random.getRandom() * 20 + 30,
vec3.scale(
vec3.normalize(
vec3.create(),
vec3.normalize(vec3.create(), vec3.fromValues(0.5, 0.1, 0.8)),
Random.getRandom() * 0.5 + 0.5
vec3.fromValues(Random.getRandom(), 0, Random.getRandom())
),
1
0.5,
physics
)
);
} */
tunnelsCountSinceLastLight = 0;
}
previousEnd = currentEnd;
previousRadius = currentToRadius;
}
return first;
};

View file

@ -0,0 +1,62 @@
import { vec2 } from 'gl-matrix';
import { PhysicalObject } from '../physical-object';
export abstract class BoundingBoxBase {
constructor(
public readonly owner: PhysicalObject,
protected _xMin: number = 0,
protected _xMax: number = 0,
protected _yMin: number = 0,
protected _yMax: number = 0,
public readonly isInverted = false
) {}
public get 0(): number {
return this._xMin;
}
public get 1(): number {
return this._xMax;
}
public get 2(): number {
return this._yMin;
}
public get 3(): number {
return this._yMax;
}
public get xMin(): number {
return this._xMin;
}
public get xMax(): number {
return this._xMax;
}
public get yMin(): number {
return this._yMin;
}
public get yMax(): number {
return this._yMax;
}
public get topLeft(): vec2 {
return vec2.fromValues(this._xMin, this._yMax);
}
public get size(): vec2 {
return vec2.fromValues(this._xMax - this._xMin, this._yMax - this._yMin);
}
public intersects(other: BoundingBoxBase): boolean {
return (
this._xMin < other._xMax &&
this._xMax > other._xMin &&
this._yMin < other._yMax &&
this._yMax > other._yMin
);
}
}

View file

@ -0,0 +1,65 @@
import { vec2 } from 'gl-matrix';
import { BoundingBoxBase } from './bounding-box-base';
import { ImmutableBoundingBox } from './immutable-bounding-box';
export class BoundingBox extends BoundingBoxBase {
public get xMin(): number {
return this._xMin;
}
public set xMin(value: number) {
this._xMin = value;
}
public set xMax(value: number) {
this._xMax = value;
}
public get xMax(): number {
return this._xMax;
}
public set yMin(value: number) {
this._yMin = value;
}
public get yMin(): number {
return this._yMin;
}
public set yMax(value: number) {
this._yMax = value;
}
public get yMax(): number {
return this._yMax;
}
public get topLeft(): vec2 {
return vec2.fromValues(this._xMin, this._yMax);
}
public set topLeft(value: vec2) {
this._xMin = value.x;
this._yMax = value.y;
}
public set size(value: vec2) {
this._xMax = this.xMin + value.x;
this._yMin = this.yMax - value.y;
}
public get size(): vec2 {
return vec2.fromValues(this._xMax - this._xMin, this._yMax - this._yMin);
}
public cloneAsImmutable(): ImmutableBoundingBox {
return new ImmutableBoundingBox(
this.owner,
this.xMin,
this.xMax,
this.yMin,
this.yMax
);
}
}

View file

@ -0,0 +1,67 @@
import { vec2 } from 'gl-matrix';
import { PhysicalObject } from '../physical-object';
import { BoundingBox } from './bounding-box';
import { BoundingBoxBase } from './bounding-box-base';
export class BoundingCircle {
private _boundingBox: BoundingBox;
constructor(public readonly owner, private _center: vec2, private _radius: number) {
this._boundingBox = new BoundingBox(owner);
this.recalculateBoundingBox();
}
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 areIntersecting(other: PhysicalObject): boolean {
return other.distance(this.center) < this.radius;
}
public isInside(other: PhysicalObject): 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;
}
public get boundingBox(): BoundingBoxBase {
return this._boundingBox;
}
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;
}
}

View file

@ -0,0 +1,3 @@
import { BoundingBoxBase } from './bounding-box-base';
export class ImmutableBoundingBox extends BoundingBoxBase {}

View file

@ -1,4 +1,4 @@
import { BoundingBoxBase } from '../../shapes/bounding-box-base';
import { BoundingBoxBase } from '../bounds/bounding-box-base';
export class BoundingBoxList {
constructor(private boundingBoxes: Array<BoundingBoxBase> = []) {}

View file

@ -1,12 +1,10 @@
// source: https://github.com/ubilabs/kd-tree-javascript/blob/master/kdTree.js
import { ImmutableBoundingBox } from '../../shapes/immutable-bounding-box';
import { ImmutableBoundingBox } from '../bounds/immutable-bounding-box';
class Node {
public left?: Node = null;
public right?: Node = null;
constructor(public rectangle: ImmutableBoundingBox, public parent: Node) {}
}

View file

@ -0,0 +1,10 @@
import { BoundingCircle } from './bounds/bounding-circle';
import { PhysicalObject } from './physical-object';
export abstract class DynamicPhysicalObject extends PhysicalObject {
public abstract getBoundingCircles(): Array<BoundingCircle>;
protected addToPhysics() {
super.addToPhysics(true);
}
}

View file

@ -0,0 +1,21 @@
import { vec2 } from 'gl-matrix';
import { GameObject } from '../objects/game-object';
import { BoundingBoxBase } from './bounds/bounding-box-base';
import { Physics } from './physics';
export abstract class PhysicalObject extends GameObject {
public abstract getBoundingBox(): BoundingBoxBase;
public abstract distance(target: vec2): number;
constructor(protected physics: Physics, public readonly canCollide: boolean) {
super();
}
protected addToPhysics(isDynamic = false) {
if (isDynamic) {
this.physics.addDynamicBoundingBox(this.getBoundingBox());
} else {
this.physics.addStaticBoundingBox(this.getBoundingBox());
}
}
}

Some files were not shown because too many files have changed in this diff Show more