Update physics
This commit is contained in:
parent
1b7dee4be0
commit
d9d8d03c36
30 changed files with 447 additions and 552 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue