UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

200 lines (195 loc) 5.91 kB
import { Vector2 } from "three/src/Three"; import { Filter, FixtureDef, WorldManifold } from "../../../../box2d.ts/build/index"; import { Component } from "../../../hierarchy_object/Component"; import { ContactPoint2D } from "../../../physics/2d/ContactPoint2D"; import { PhysicsMaterial2D } from "../../../physics/2d/PhysicsMaterial2D"; export class Collider2D extends Component { fl=null; yl=1; wl=null; xl=false; Za=new Vector2; Oo=null; onEnable() { this.Cl(); this.fl.body.SetAwake(true); } onDisable() { this.fl?.body.SetAwake(true); this.Fl(); } onDestroy() { this.wl?.onChanged.removeListener(this.updateFixturesMaterialInfo); } Cl() { if (this.fl) return; this.fl = this.engine.physics2DProcessor.addCollider(this.gameObject, this); const t = this.createShapes(); for (let i = 0; i < t.length; ++i) { const s = t[i]; const e = new FixtureDef; e.userData = this; e.density = this.yl; e.isSensor = this.xl; e.shape = s; this.fl.add(e); } this.updateFixturesMaterialInfo(); this.updateFixturesFilter(); this.fl.physicObject.rigidbody?.updateMass(); } Fl() { if (this.fl) { this.engine.physics2DProcessor.removeCollider(this.gameObject, this, this.fl); this.fl.physicObject.rigidbody?.updateMass(); this.fl = null; } } updateFixture() { if (this.fl) { this.Fl(); this.Cl(); this.fl.body.SetAwake(true); } } static _filterBuffer=new Filter; updateFixturesFilter() { if (!this.fl) return; const t = Collider2D._filterBuffer; const i = this.fl.physicObject; const s = i.rigidbody; let e; if (this.Oo) { e = this.Oo; } else { if (s) { e = s.layer; } else { e = 1; } } t.categoryBits = e; if (s && !s.simulated) { t.maskBits = 0; } else { t.maskBits = this.engine.physics.collisionLayerMask.getMaskFromLayer(e); } this.fl.foreachFixture((i => i.SetFilterData(t))); } updateFixturesMaterialInfo=() => { if (this.fl) { let t = null; if (this.wl) { t = this.wl; } else if (this.fl) { const i = this.fl.physicObject.sharedMaterial; if (i) t = i; } if (!t) t = new PhysicsMaterial2D; this.fl.foreachFixture((i => { i.SetFriction(t.friction); i.SetRestitution(t.bounciness); })); } }; createShapes() { throw new Error("You should not use Collider2D directly but one of its subclasses. e.g. BoxCollider2D"); } get density() { return this.yl; } set density(t) { if (this.fl) { const t = this.fl.physicObject; if (t && t.rigidbody && !t.rigidbody.useAutoMass) { throw new Error("You cannot change the density of a collider when the rigid body is not using auto mass."); } } this.yl = t; if (this.fl) { this.fl.foreachFixture((i => i.SetDensity(t))); } } get material() { return this.wl; } set material(t) { if (t) { if (!this.wl) { this.wl = new PhysicsMaterial2D(t.friction, t.bounciness); this.wl.onChanged.addListener(this.updateFixturesMaterialInfo); } else { this.wl.copy(t); } } else { this.wl?.onChanged.removeListener(this.updateFixturesMaterialInfo); this.wl = null; } this.updateFixturesMaterialInfo(); } get isTrigger() { return this.xl; } set isTrigger(t) { this.xl = t; if (this.fl) { this.fl.foreachFixture((i => i.SetSensor(t))); } } get offset() { return this.Za; } set offset(t) { this.Za.copy(t); this.updateFixture(); } getLayerToName() { return this.Oo ? this.engine.physics.collisionLayerMask.layerToName(this.Oo) : null; } setLayerFromName(t) { this.Oo = t ? this.engine.physics.collisionLayerMask.nameToLayer(t) : null; this.updateFixturesFilter(); } get layer() { return this.Oo; } set layer(t) { this.Oo = t; this.updateFixturesFilter(); } getThisOrRigidBodyLayerToName() { if (this.Oo) { return this.engine.physics.collisionLayerMask.layerToName(this.Oo); } else { return this.fl?.physicObject.rigidbody?.getLayerToName() ?? "default"; } } getThisOrRigidBodyLayer() { if (this.Oo) { return this.Oo; } else { return this.fl?.physicObject.rigidbody?.layer ?? 1; } } fi=new WorldManifold; getContacts(t) { if (!this.fl) return 0; let i = 0; let s = this.fl.body.GetContactList(); while (s) { const e = s; s = s.next; if (!this.fl.contains(e.contact.GetFixtureA()) && !this.fl.contains(e.contact.GetFixtureB())) { continue; } const r = e.contact.GetManifold(); for (let s = 0; s < r.pointCount; ++s) { if (!t[i]) t[i] = new ContactPoint2D; e.contact.GetWorldManifold(this.fi); t[i].setData(e.contact, r.points[s], this.fi.normal, this.fi.points[s], this.fi.separations[s]); i += 1; } } return i; } }