the-world-engine
Version:
three.js based, unity like game engine for browser
82 lines (78 loc) • 2.71 kB
JavaScript
import { b2Controller } from "./b2_controller.js";
import { b2Vec2 } from "../common/b2_math.js";
import { b2_epsilon } from "../common/b2_settings.js";
import { b2Color } from "../common/b2_draw.js";
export class b2BuoyancyController extends b2Controller {
constructor() {
super(...arguments);
this.normal = new b2Vec2(0, 1);
this.offset = 0;
this.density = 0;
this.velocity = new b2Vec2(0, 0);
this.linearDrag = 0;
this.angularDrag = 0;
this.useDensity = false;
this.useWorldGravity = true;
this.gravity = new b2Vec2(0, 0);
}
Step(t) {
if (!this.m_bodyList) {
return;
}
if (this.useWorldGravity) {
this.gravity.Copy(this.m_bodyList.body.GetWorld().GetGravity());
}
for (let t = this.m_bodyList; t; t = t.nextBody) {
const s = t.body;
if (!s.IsAwake()) {
continue;
}
const i = new b2Vec2;
const o = new b2Vec2;
let e = 0;
let n = 0;
for (let t = s.GetFixtureList(); t; t = t.m_next) {
const h = new b2Vec2;
const c = t.GetShape().ComputeSubmergedArea(this.normal, this.offset, s.GetTransform(), h);
e += c;
i.x += c * h.x;
i.y += c * h.y;
let r = 0;
if (this.useDensity) {
r = t.GetDensity();
} else {
r = 1;
}
n += c * r;
o.x += c * h.x * r;
o.y += c * h.y * r;
}
i.x /= e;
i.y /= e;
o.x /= n;
o.y /= n;
if (e < b2_epsilon) {
continue;
}
const h = this.gravity.Clone().SelfNeg();
h.SelfMul(this.density * e);
s.ApplyForce(h, o);
const c = s.GetLinearVelocityFromWorldPoint(i, new b2Vec2);
c.SelfSub(this.velocity);
c.SelfMul(-this.linearDrag * e);
s.ApplyForce(c, i);
s.ApplyTorque(-s.GetInertia() / s.GetMass() * e * s.GetAngularVelocity() * this.angularDrag);
}
}
Draw(t) {
const s = 100;
const i = new b2Vec2;
const o = new b2Vec2;
i.x = this.normal.x * this.offset + this.normal.y * s;
i.y = this.normal.y * this.offset - this.normal.x * s;
o.x = this.normal.x * this.offset - this.normal.y * s;
o.y = this.normal.y * this.offset + this.normal.x * s;
const e = new b2Color(0, 0, .8);
t.DrawSegment(i, o, e);
}
}