summaryrefslogtreecommitdiffstats
path: root/src/renderer/runtime/controller/collision.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/runtime/controller/collision.ts')
-rw-r--r--src/renderer/runtime/controller/collision.ts65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/renderer/runtime/controller/collision.ts b/src/renderer/runtime/controller/collision.ts
new file mode 100644
index 0000000..a44ffa4
--- /dev/null
+++ b/src/renderer/runtime/controller/collision.ts
@@ -0,0 +1,65 @@
+import { Collision } from '../model/data/collision';
+
+import { Circle } from '../math/circle';
+import { Collidable } from '../math/collision';
+import { LineSegment, Movement } from '../math/line';
+import { Point } from '../math/point';
+
+import { vec2 } from 'gl-matrix';
+
+export function mkCollision(collision: Collision[]): Collidable[] {
+ const ret: Collidable[] = [];
+
+ for (const c of collision) {
+ switch (c.type) {
+ case 'polygon':
+ if (!c.vertices.length)
+ continue;
+
+ let prev = c.vertices[c.vertices.length - 1];
+
+ for (const v of c.vertices) {
+ ret.push(LineSegment.fromPoints(vec2.clone(prev), vec2.clone(v)));
+ prev = v;
+ }
+
+ for (const v of c.vertices) {
+ ret.push(new Point(vec2.clone(v)));
+ prev = v;
+ }
+ break;
+
+ case 'circle':
+ ret.push(new Circle(vec2.clone(c.center), c.radius));
+ break;
+ }
+ }
+
+ return ret;
+}
+
+export interface CollidableGroup {
+ getTranslation(): vec2|null;
+ getCollidables(): Collidable[];
+}
+
+export function collide(collision: CollidableGroup, out: vec2, move: Movement, radius: number): boolean {
+ const t = collision.getTranslation();
+ if (t)
+ move = move.translate(vec2.negate(vec2.create(), t));
+
+ for (const c of collision.getCollidables()) {
+ if (!c.collide(out, move, radius))
+ continue;
+
+ if (vec2.squaredDistance(move.src, out) >= vec2.squaredDistance(move.src, move.dest))
+ continue;
+
+ if (t)
+ vec2.add(out, out, t);
+
+ return true;
+ }
+
+ return false;
+}