the-world-engine
Version:
three.js based, unity like game engine for browser
334 lines (330 loc) • 9.74 kB
JavaScript
import { Vector2 } from "three/src/Three";
import { EventContainer } from "../../collection/EventContainer";
import { Pathfinder } from "../ai/pathfind/Pathfinder";
import { Directable, Direction } from "../helper/Directable";
export class PlayerGridMovementController extends Directable {
disallowMultipleComponent=true;
dh=8;
gh=1;
wh=1;
Cr=[];
Ph=.5;
Ch=new Vector2;
Dh=new Vector2;
Mh=new Vector2;
Th=new Vector2;
Ah=new EventContainer;
Vh=new EventContainer;
Er=null;
Ir=null;
Ih=false;
bh=null;
yh=0;
kh=null;
Eh=new Vector2;
Wh=true;
xh=new Vector2;
Gh=new Vector2;
start() {
this.Ir = new Pathfinder(this.Cr, this.wh * this.Ph, this.gh * this.Ph);
const t = this.transform;
const i = t.position;
i.x = this.Ch.x + this.Th.x * this.wh;
i.y = this.Ch.y + this.Th.y * this.gh;
this.Dh.set(t.localPosition.x, t.localPosition.y);
const s = t.parent;
if (s) this.Eh.set(s.position.x, s.position.y);
}
update() {
this.kh?.();
if (this.Wh) {
this.Hh();
}
this.Kh();
this.Lh();
}
Hh() {
if (this.isMoving) {
this.Rh();
return;
}
const t = this.engine.input.map;
const i = this.Dh;
if (t.get("w") || t.get("ArrowUp")) {
this.direction = Direction.Up;
if (this.Sh(i.x, i.y + this.gh)) return;
this.Mh.set(i.x, i.y + this.gh);
this.Uh();
this.isMoving = true;
} else if (t.get("s") || t.get("ArrowDown")) {
this.direction = Direction.Down;
if (this.Sh(i.x, i.y - this.gh)) return;
this.Mh.set(i.x, i.y - this.gh);
this.Uh();
this.isMoving = true;
} else if (t.get("a") || t.get("ArrowLeft")) {
this.direction = Direction.Left;
if (this.Sh(i.x - this.wh, i.y)) return;
this.Mh.set(i.x - this.wh, i.y);
this.Uh();
this.isMoving = true;
} else if (t.get("d") || t.get("ArrowRight")) {
this.direction = Direction.Right;
if (this.Sh(i.x + this.wh, i.y)) return;
this.Mh.set(i.x + this.wh, i.y);
this.Uh();
this.isMoving = true;
}
}
Fh(t) {
const i = this.engine.input.map;
if (i.get("w") || i.get("ArrowUp")) {
this.direction = Direction.Up;
if (this.Sh(t.x, t.y + this.gh)) return false;
this.Mh.set(t.x, t.y + this.gh);
this.Uh();
return true;
} else if (i.get("s") || i.get("ArrowDown")) {
this.direction = Direction.Down;
if (this.Sh(t.x, t.y - this.gh)) return false;
this.Mh.set(t.x, t.y - this.gh);
this.Uh();
return true;
} else if (i.get("a") || i.get("ArrowLeft")) {
this.direction = Direction.Left;
if (this.Sh(t.x - this.wh, t.y)) return false;
this.Mh.set(t.x - this.wh, t.y);
this.Uh();
return true;
} else if (i.get("d") || i.get("ArrowRight")) {
this.direction = Direction.Right;
if (this.Sh(t.x + this.wh, t.y)) return false;
this.Mh.set(t.x + this.wh, t.y);
this.Uh();
return true;
}
return false;
}
Uh() {
this.Ah.invoke(Math.floor((this.Mh.x - this.Ch.x) / this.wh), Math.floor((this.Mh.y - this.Ch.y) / this.gh));
}
Oh() {
this.Vh.invoke(Math.floor((this.Dh.x - this.Ch.x) / this.wh), Math.floor((this.Dh.y - this.Ch.y) / this.gh));
}
Rh() {
const t = this.engine.input.map;
if (t.get("w") || t.get("ArrowUp")) {
this.Ih = false;
} else if (t.get("s") || t.get("ArrowDown")) {
this.Ih = false;
} else if (t.get("a") || t.get("ArrowLeft")) {
this.Ih = false;
} else if (t.get("d") || t.get("ArrowRight")) {
this.Ih = false;
}
}
Kh() {
if (!this.Ih) return;
const t = this.transform;
const i = this.xh.set(t.localPosition.x, t.localPosition.y);
const s = this.bh[this.yh];
const e = s.distanceTo(i);
if (e < this.dh * this.engine.time.deltaTime) {
this.yh += 1;
if (this.yh >= this.bh.length) {
this.Ih = false;
return;
} else {
this.Oh();
}
}
if (this.Sh(s.x, s.y)) {
this.Ih = false;
return;
}
if (this.Mh.equals(this.bh[this.yh])) return;
this.Mh.copy(this.bh[this.yh]);
this.Uh();
const h = this.bh[this.yh - 1].x;
const r = this.bh[this.yh - 1].y;
const n = this.bh[this.yh].x;
const o = this.bh[this.yh].y;
if (r < o) {
this.direction = Direction.Up;
} else if (r > o) {
this.direction = Direction.Down;
} else if (h < n) {
this.direction = Direction.Right;
} else if (h > n) {
this.direction = Direction.Left;
}
this.isMoving = true;
}
Lh() {
if (!this.isMoving) return;
const t = this.transform;
const i = this.xh.set(t.localPosition.x, t.localPosition.y);
let s = i.distanceTo(this.Mh);
const e = this.dh * this.engine.time.deltaTime;
if (s < e) {
if (this.Fh(this.Mh)) {
s = i.distanceTo(this.Mh);
this.Oh();
}
}
const h = this.Gh.copy(this.Mh).sub(i).normalize();
if (s < e) {
this.isMoving = false;
this.Dh.copy(this.Mh);
t.localPosition.x = this.Dh.x;
t.localPosition.y = this.Dh.y;
this.Oh();
} else {
h.multiplyScalar(e);
this.gameObject.transform.localPosition.x += h.x;
this.gameObject.transform.localPosition.y += h.y;
}
}
Sh(t, i) {
t += this.Eh.x;
i += this.Eh.y;
const s = this.Cr;
for (let e = 0; e < s.length; ++e) {
if (s[e].checkCollision(t, i, this.Ph, this.Ph)) {
return true;
}
}
return false;
}
zh=-1;
Bh=new Vector2;
jh=.3;
Tr=t => {
if (t.button !== 0) return;
this.Ih = false;
const i = this.engine.time.unscaledTime;
if (i - this.zh < this.jh) {
if (this.Bh.equals(t.gridPosition)) {
this.qh(t);
this.zh = -1;
}
} else {
this.zh = i;
this.Bh.copy(t.gridPosition);
}
};
qh(t) {
if (this.Ih) {
this.Ih = false;
this.kh = () => {
this.tryStartPathfind(t.gridPosition);
};
return;
}
this.kh = () => {
this.tryStartPathfind(t.gridPosition);
};
}
tryStartPathfind(t) {
if (this.Ih) return false;
this.kh = null;
const i = this.bh = this.Ir.findPath(this.positionInGrid, t);
if (!i || i.length <= 1) return false;
for (let t = 0; t < i.length; ++t) {
const s = i[t];
s.x = s.x * this.wh + this.Ch.x;
s.y = s.y * this.gh + this.Ch.y;
}
this.yh = 1;
this.isMoving = true;
this.Ih = true;
return true;
}
cancelPathfind() {
this.Ih = false;
}
get onMoveToTarget() {
return this.Ah;
}
get onMovedToTarget() {
return this.Vh;
}
teleport(t) {
this.isMoving = false;
this.Ih = false;
this.Dh.copy(t).multiplyScalar(this.wh).add(this.Ch);
this.Mh.copy(this.Dh);
this.transform.localPosition.x = this.Dh.x;
this.transform.localPosition.y = this.Dh.y;
this.Uh();
this.Oh();
}
get speed() {
return this.dh;
}
set speed(t) {
this.dh = t;
}
get gridCenter() {
return this.Ch;
}
set gridCenter(t) {
this.Ch.copy(t);
}
get gridCellHeight() {
return this.gh;
}
set gridCellHeight(t) {
this.gh = t;
}
get gridCellWidth() {
return this.wh;
}
set gridCellWidth(t) {
this.wh = t;
}
set initPosition(t) {
this.Th.copy(t);
}
set gridPointer(t) {
if (this.Er) {
this.Er.onPointerDown.removeListener(this.Tr);
}
this.Er = t;
if (this.Er) {
this.Er.onPointerDown.addListener(this.Tr);
}
}
get gridPointer() {
return this.Er;
}
addCollideMap(t) {
this.Cr.push(t);
this.Ir?.addCollideMap(t);
}
removeCollideMap(t) {
const i = this.Cr.indexOf(t);
if (i >= 0) {
this.Cr.splice(i, 1);
this.Ir?.removeCollideMap(t);
}
}
removeAllCollideMaps() {
this.Cr.length = 0;
this.Ir?.removeAllCollideMaps();
}
setGridInfoFromCollideMap(t) {
this.wh = t.gridCellWidth;
this.gh = t.gridCellHeight;
this.Ch.set(t.gridCenterX, t.gridCenterY);
}
get positionInGrid() {
return new Vector2(Math.floor((this.transform.localPosition.x - this.Ch.x) / this.wh), Math.floor((this.transform.localPosition.y - this.Ch.y) / this.gh));
}
get receiveKeyboardInput() {
return this.Wh;
}
set receiveKeyboardInput(t) {
this.Wh = t;
}
}