the-world-engine
Version:
three.js based, unity like game engine for browser
292 lines (291 loc) • 10.3 kB
JavaScript
import { Vector2 } from "three/src/Three";
export class Physics2DProcessor {
yi=null;
Pi=8;
Ti=3;
Ii=true;
xi=null;
Mi=null;
Ni=new Map;
Oi=null;
Bi=null;
applyPhysicsSettings(t) {
if (!t.loader) return;
this.Oi = t.loader;
this.Mi = new this.Oi.World(new this.Oi.Vec2(0, -9.81));
const i = class extends this.Oi.ContactListener {
Li;
ji;
qi;
Hi;
constructor(t) {
super();
this.Li = t;
this.ji = new this.Li.Oi.Collision2DPool;
this.qi = new this.Li.Oi.TriggerEventPool;
this.Hi = new this.Li.Oi.CollisionEventPool;
}
BeginContact(t) {
const i = t.GetFixtureA().GetUserData();
const s = t.GetFixtureB().GetUserData();
if (i.isTrigger || s.isTrigger) {
this.qi.insert(0, i, s);
} else {
if (this.Li.reuseCollisionCallbacks) {
const e = this.ji.getInstance();
e.setData(t);
this.Hi.insert(0, i, s, e, this.ji);
} else {
const e = new this.Li.Oi.Collision2D;
e.setData(t);
this.Hi.insert(0, i, s, e);
}
}
}
EndContact(t) {
const i = t.GetFixtureA().GetUserData();
const s = t.GetFixtureB().GetUserData();
if (i.isTrigger || s.isTrigger) {
this.qi.insert(2, i, s);
} else {
if (this.Li.reuseCollisionCallbacks) {
const e = this.ji.getInstance();
e.setData(t);
this.Hi.insert(2, i, s, e, this.ji);
} else {
const e = new this.Li.Oi.Collision2D;
e.setData(t);
this.Hi.insert(2, i, s, e);
}
}
}
PreSolve(t, i) {
const s = t.GetFixtureA().GetUserData();
const e = t.GetFixtureB().GetUserData();
if (s.isTrigger || e.isTrigger) {
this.qi.insert(1, s, e);
} else {
if (this.Li.reuseCollisionCallbacks) {
const i = this.ji.getInstance();
i.setData(t);
this.Hi.insert(1, s, e, i, this.ji);
} else {
const i = new this.Li.Oi.Collision2D;
i.setData(t);
this.Hi.insert(1, s, e, i);
}
}
}
onTriggerInvoke() {
this.qi.invoke();
}
onCollisionInvoke() {
this.Hi.invoke();
}
};
const s = new i(this);
this.Bi = s;
this.Mi.SetContactListener(s);
if (t.gravity) this.Mi?.SetGravity(t.gravity);
if (t.defaultMaterial) this.yi = t.defaultMaterial.clone();
if (t.velocityIterations) this.Pi = t.velocityIterations;
if (t.positionIterations) this.Ti = t.positionIterations;
if (t.queriesHitTriggers) this.Ii = t.queriesHitTriggers;
if (t.reuseCollisionCallbacks) this.reuseCollisionCallbacks = t.reuseCollisionCallbacks;
if (t.collisionLayerMaskMatrix) {
this.xi = new this.Oi.CollisionLayerMaskConverter(t.collisionLayerMaskMatrix);
} else {
this.xi = new this.Oi.CollisionLayerMaskConverter({
default: {
default: true
}
});
}
this.Ri = new this.Oi.RayCastOneCallback(this);
this.Ai = new this.Oi.RayCastFilterCallback;
}
update(t) {
if (!this.Mi) return;
{
let t = this.Mi.GetBodyList();
while (t) {
const i = t;
t = t.GetNext();
const s = i.GetUserData();
const e = s.gameObject.transform;
const r = e.position;
const o = e.eulerAngles;
const h = i.GetPosition();
const n = i.GetAngle();
if (r.x !== h.x || r.y !== h.y) {
i.SetPosition(r);
i.SetAwake(true);
}
if (o.z !== n) {
i.SetAngle(o.z);
i.SetAwake(true);
}
}
}
this.Mi.Step(t, this.Pi, this.Ti);
{
let t = this.Mi.GetBodyList();
while (t) {
const i = t;
t = t.GetNext();
const s = i.GetUserData();
const e = s.gameObject.transform;
e.position.x = i.GetPosition().x;
e.position.y = i.GetPosition().y;
e.eulerAngles.z = i.GetAngle();
}
}
this.Bi.onTriggerInvoke();
this.Bi.onCollisionInvoke();
}
addRigidBody(t, i, s) {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
let e = this.Ni.get(t);
if (!e) {
e = new this.Oi.PhysicsObject2D(t, this.Mi.CreateBody(s), (() => this.Ni.delete(t)));
this.Ni.set(t, e);
return e.addRigidBody(i);
} else {
const t = e.addRigidBody(i);
const r = t.body;
r.SetType(s.type);
r.SetPosition(s.position);
r.SetAngle(s.angle);
r.SetLinearVelocity(s.linearVelocity);
r.SetAngularVelocity(s.angularVelocity);
r.SetLinearDamping(s.linearDamping);
r.SetAngularDamping(s.angularDamping);
r.SetSleepingAllowed(s.allowSleep);
r.SetAwake(s.awake);
r.SetFixedRotation(s.fixedRotation);
r.SetBullet(s.bullet);
r.SetEnabled(s.enabled);
r.SetUserData(s.userData);
r.SetGravityScale(s.gravityScale);
return t;
}
}
removeRigidBody(t) {
const i = this.Ni.get(t);
if (!i) throw new Error("PhysicsObject2D not found");
i.removeRigidBody();
}
Fi(t) {
const i = new this.Oi.BodyDef;
i.type = this.Oi.BodyType.b2_kinematicBody;
i.position.x = t.transform.position.x;
i.position.y = t.transform.position.y;
i.angle = t.transform.eulerAngles.z;
return i;
}
addCollider(t, i) {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
let s = this.Ni.get(t);
if (!s) {
s = new this.Oi.PhysicsObject2D(t, this.Mi.CreateBody(this.Fi(t)), (() => this.Ni.delete(t)));
}
this.Ni.set(t, s);
return s.addCollider(i);
}
removeCollider(t, i, s) {
const e = this.Ni.get(t);
if (!e) throw new Error("PhysicsObject2D not found");
e.removeCollider(i, s);
}
get physicsLoader() {
return this.Oi;
}
get gravity() {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
const t = this.Mi.GetGravity();
return new Vector2(t.x, t.y);
}
set gravity(t) {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
this.Mi.SetGravity(new this.Oi.Vec2(t.x, t.y));
}
get defaultMaterial() {
return this.yi;
}
get velocityIterations() {
return this.Pi;
}
set velocityIterations(t) {
this.Pi = t;
}
get positionIterations() {
return this.Ti;
}
set positionIterations(t) {
this.Ti = t;
}
get maxLinearCorrection() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.maxLinearCorrection;
}
get maxAngularCorrection() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.maxAngularCorrection;
}
get maxTranslationSpeed() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.maxTranslation;
}
get maxRotationSpeed() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.maxRotation;
}
get baumgarteScale() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.baumgarte;
}
get baumgarteTimeOfImpactScale() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.toiBaumgarte;
}
get timeToSleep() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.timeToSleep;
}
get linearSleepTolerance() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.linearSleepTolerance;
}
get angularSleepTolerance() {
if (!this.Oi) throw new Error("Physics2D is not loaded.");
return this.Oi.angularSleepTolerance;
}
get queriesHitTriggers() {
return this.Ii;
}
set queriesHitTriggers(t) {
this.Ii = t;
}
reuseCollisionCallbacks=true;
get collisionLayerMask() {
return this.xi;
}
static _raycastEndPoint=new Vector2;
Ri=null;
Ai=null;
raycastOne(t, i, s, e = Number.POSITIVE_INFINITY, r = 4294967295, o = Number.NEGATIVE_INFINITY, h = Number.POSITIVE_INFINITY) {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
if (!s) s = new this.Oi.RaycastHit2D;
const n = Physics2DProcessor._raycastEndPoint.copy(i).multiplyScalar(e === Number.POSITIVE_INFINITY ? 1e7 : e).add(t);
this.Ri.setRaycastData(s, t, r, o, h);
this.Mi.RayCast(this.Ri, t, n);
return this.Ri.hit ? s : null;
}
raycast(t, i, s, e, r = Number.POSITIVE_INFINITY) {
if (!this.Mi) throw new Error("Physics2D is not loaded.");
const o = Physics2DProcessor._raycastEndPoint.copy(i).multiplyScalar(r === Number.POSITIVE_INFINITY ? 1e7 : r).add(t);
this.Ai.setRaycastData(e, t, s);
this.Mi.RayCast(this.Ai, t, o);
return this.Ai.hitCount;
}
}