the-world-engine
Version:
three.js based, unity like game engine for browser
114 lines (112 loc) • 3.12 kB
JavaScript
import { Vector2 } from "three/src/Three";
import { PathNode } from "./PathNode";
export class Pathfinder {
ol;
nl;
ll;
Cr;
constructor(t, e = .5, i = .5, o = 1e3) {
this.Cr = t?.slice() ?? [];
this.ol = e;
this.nl = i;
this.ll = o;
}
addCollideMap(t) {
this.Cr.push(t);
}
removeCollideMap(t) {
const e = this.Cr.indexOf(t);
if (e >= 0) {
this.Cr.splice(e, 1);
}
}
removeAllCollideMaps() {
this.Cr.length = 0;
}
findPath(t, e) {
const i = new PathNode(t.x, t.y);
const o = new PathNode(e.x, e.y);
if (this.Sh(i.x, i.y)) return null;
if (this.Sh(o.x, o.y)) return null;
const r = [];
const n = [];
i.gCost = 0;
i.hCost = this.al(i, o);
i.calculateFCost();
r.push(i);
let s = 0;
while (r.length > 0 && s < this.ll) {
s += 1;
const t = this.cl(r);
if (t.equals(o)) {
return this.ul(t);
}
r.splice(r.indexOf(t), 1);
n.push(t);
const e = this.dl(t);
for (let i = 0; i < e.length; ++i) {
const s = e[i];
if (n.find((t => t.equals(s))) !== undefined) continue; else {
s.gCost = Number.MAX_VALUE;
s.calculateFCost();
s.previousNode = null;
}
if (this.Sh(s.x, s.y)) {
n.push(s);
continue;
}
const h = t.gCost + this.al(t, s);
if (h < s.gCost) {
s.previousNode = t;
s.gCost = h;
s.hCost = this.al(s, o);
s.calculateFCost();
if (r.find((t => t.equals(s))) === undefined) {
r.push(s);
}
}
}
}
return null;
}
dl(t) {
const e = [];
e.push(new PathNode(t.x, t.y - 1));
e.push(new PathNode(t.x + 1, t.y));
e.push(new PathNode(t.x, t.y + 1));
e.push(new PathNode(t.x - 1, t.y));
return e;
}
ul(t) {
const e = [];
let i = t;
while (i.previousNode) {
e.push(new Vector2(i.x, i.y));
i = i.previousNode;
}
e.push(new Vector2(i.x, i.y));
return e.reverse();
}
al(t, e) {
return Math.abs(t.x - e.x) + Math.abs(t.y - e.y);
}
cl(t) {
let e = t[0];
for (let i = 1; i < t.length; ++i) {
if (t[i].fCost < e.fCost) {
e = t[i];
}
}
return e;
}
Sh(t, e) {
const i = this.Cr;
for (let o = 0; o < i.length; ++o) {
const r = i[o];
if (r.checkCollision(t * r.gridCellWidth + r.gridCenterX, e * r.gridCellHeight + r.gridCenterY, this.ol, this.nl)) {
return true;
}
}
return false;
}
}