summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2018-11-04 22:02:19 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2018-11-04 22:42:25 +0100
commit6a02ea105a4e15e9f36a5b2d7d0a26169164fb1d (patch)
tree69fedbb9c6daf53bf5942beab3dbb9bc14726340 /src
parent34d7b2197bc0e5f40a1e36b3fb8838abf91d4d6c (diff)
downloadrpgedit-6a02ea105a4e15e9f36a5b2d7d0a26169164fb1d.tar
rpgedit-6a02ea105a4e15e9f36a5b2d7d0a26169164fb1d.zip
Fix rounding issues in collision handling
Diffstat (limited to 'src')
-rw-r--r--src/controller/gamecontext.ts49
-rw-r--r--src/math/line.ts45
2 files changed, 55 insertions, 39 deletions
diff --git a/src/controller/gamecontext.ts b/src/controller/gamecontext.ts
index cda47a5..295872d 100644
--- a/src/controller/gamecontext.ts
+++ b/src/controller/gamecontext.ts
@@ -6,7 +6,7 @@ import { loadMap } from '../view/map';
import { Renderer } from '../view/renderer/renderer';
import { SpriteView } from '../view/sprite';
-import { LineSegment } from '../math/line';
+import { LineSegment, Movement } from '../math/line';
import { getJSON } from '../util';
import { vec2 } from 'gl-matrix';
@@ -40,10 +40,25 @@ export class GameContext {
private readonly entityMovement: vec2 = vec2.create();
private readonly walls: LineSegment[] = [
- new LineSegment(vec2.fromValues(1, 1), vec2.fromValues(1, 0), 10),
- new LineSegment(vec2.fromValues(11, 1), vec2.fromValues(0, 1), 10),
- new LineSegment(vec2.fromValues(11, 11), vec2.fromValues(-1, 0), 10),
- new LineSegment(vec2.fromValues(1, 11), vec2.fromValues(0, -1), 10),
+ LineSegment.fromPoints(vec2.fromValues(1, 1), vec2.fromValues(11, 1)),
+
+ LineSegment.fromPoints(vec2.fromValues(11, 1), vec2.fromValues(11, 5)),
+ LineSegment.fromPoints(vec2.fromValues(11, 5), vec2.fromValues(12, 5)),
+ LineSegment.fromPoints(vec2.fromValues(12, 5), vec2.fromValues(12, 7)),
+ LineSegment.fromPoints(vec2.fromValues(12, 7), vec2.fromValues(11, 7)),
+ LineSegment.fromPoints(vec2.fromValues(11, 7), vec2.fromValues(11, 11)),
+
+ LineSegment.fromPoints(vec2.fromValues(11, 11), vec2.fromValues(7, 11)),
+ LineSegment.fromPoints(vec2.fromValues(7, 11), vec2.fromValues(7, 12)),
+ LineSegment.fromPoints(vec2.fromValues(7, 12), vec2.fromValues(5, 12)),
+ LineSegment.fromPoints(vec2.fromValues(5, 12), vec2.fromValues(5, 11)),
+ LineSegment.fromPoints(vec2.fromValues(5, 11), vec2.fromValues(1, 11)),
+
+ LineSegment.fromPoints(vec2.fromValues(1, 11), vec2.fromValues(1, 7)),
+ LineSegment.fromPoints(vec2.fromValues(1, 7), vec2.fromValues(0, 7)),
+ LineSegment.fromPoints(vec2.fromValues(0, 7), vec2.fromValues(0, 5)),
+ LineSegment.fromPoints(vec2.fromValues(0, 5), vec2.fromValues(1, 5)),
+ LineSegment.fromPoints(vec2.fromValues(1, 5), vec2.fromValues(1, 1)),
];
private constructor(
@@ -70,34 +85,32 @@ export class GameContext {
}
private updateStep(): void {
- let move = new LineSegment(this.entityPos, this.entityMovement, this.speed);
- const p = vec2.create();
+ const dest = vec2.scaleAndAdd(vec2.create(), this.entityPos, this.entityMovement, this.speed);
+ const dest2 = vec2.create();
let rescan = true;
while (rescan) {
rescan = false;
- for (const w of this.walls) {
- if (!w.collidesMove(move))
- continue;
+ if (vec2.equals(dest, this.entityPos))
+ return;
- move.getP2(p);
- w.projectPoint(p, p);
+ const move = new Movement(this.entityPos, dest);
- const move2 = LineSegment.fromPoints(this.entityPos, p);
- if (move2.l === 0)
- return;
+ for (const w of this.walls) {
+ if (!w.collidesMove(dest2, move))
+ continue;
- if (!move.equals(move2)) {
- move = move2;
+ if (!vec2.exactEquals(dest, dest2)) {
+ vec2.copy(dest, dest2);
rescan = true;
break;
}
}
}
- move.getP2(this.entityPos);
+ vec2.copy(this.entityPos, dest);
}
private update(time: number): void {
diff --git a/src/math/line.ts b/src/math/line.ts
index 98e126b..902c9b6 100644
--- a/src/math/line.ts
+++ b/src/math/line.ts
@@ -37,9 +37,23 @@ export class Line {
const d2 = d / crossz(this.v, l2.v);
return vec2.scaleAndAdd(out, l2.p, l2.v, d2);
}
+}
+
+export class Movement {
+ public readonly v: vec2;
- public equals(l2: Line): boolean {
- return vec2.equals(this.p, l2.p) && vec2.equals(this.v, l2.v);
+ constructor(
+ public readonly p1: vec2,
+ public readonly p2: vec2,
+ ) {
+ this.v = vec2.sub(vec2.create(), p2, p1);
+ }
+
+ public intersectLine(out: vec2, l: Line): vec2 {
+ const vp = vec2.sub(vec2.create(), l.p, this.p1);
+ const d = crossz(vp, this.v);
+ const d2 = d / crossz(this.v, l.v);
+ return vec2.scaleAndAdd(out, l.p, l.v, d2);
}
}
@@ -69,30 +83,19 @@ export class LineSegment extends Line {
return (d >= 0 && d <= this.l);
}
- public collidesLine(l2: Line): boolean {
- const x = this.intersectLine(vec2.create(), l2);
- return this.collidesPoint(x);
- }
-
- public collidesLineSegment(l2: LineSegment): boolean {
- const x = this.intersectLine(vec2.create(), l2);
- if (!this.collidesPoint(x))
- return false;
- if (!l2.collidesPoint(x))
+ public collidesMove(out: vec2, move: Movement): boolean {
+ if (this.distancePoint(move.p1) < 0)
return false;
- return true;
- }
+ if (this.distancePoint(move.p2) >= 0)
+ return false;
- public collidesMove(move: LineSegment): boolean {
- if (!this.collidesLineSegment(move))
+ const x = move.intersectLine(vec2.create(), this);
+ if (!this.collidesPoint(x))
return false;
- const p2 = move.getP2(vec2.create());
- return this.distancePoint(p2) < 0;
- }
+ this.projectPoint(out, move.p2);
- public equals(l2: LineSegment): boolean {
- return super.equals(l2) && this.l === l2.l;
+ return true;
}
}