refactor: decouple entity from body

This commit is contained in:
cha0s 2019-03-24 00:43:07 -05:00
parent 23c7a77e5b
commit caf69e3333

View File

@ -14,12 +14,11 @@ const decorate = compose(
class BodyBase {
constructor(entity) {
constructor(shape) {
this.force = [0, 0];
this.impulse = [0, 0];
this.contacts = I.Set();
this.entity = entity;
this.shape = entity.shape;
this.shape = shape;
}
get aabb() {
@ -36,29 +35,19 @@ class BodyBase {
}
export class Body extends decorate(BodyBase) {
constructor(entity) {
super(entity);
this.position = entity.position;
}
}
export class Body extends decorate(BodyBase) {}
export class World {
constructor() {
this.bodies = [];
this.entities = [];
this.entities = new Map();
this.quadTree = new QuadTree();
this.quadTreeNodes = new WeakMap();
this.quadTreeNodes = new Map();
}
addBody(body) {
this.bodies.push(body);
if (body.entity) {
this.entities.push(body.entity);
}
// Add to quad tree.
this.addQuadTreeNodes(body);
body.on('positionChanged', () => {
@ -90,7 +79,10 @@ export class World {
}
createBodyForEntity(entity) {
return new Body(entity);
const body = new Body(entity.shape);
body.position = entity.position;
this.entities.set(body, entity);
return body;
}
removeBody(body) {
@ -98,13 +90,7 @@ export class World {
if (-1 === index) {
return;
}
if (body.entity) {
const entities = this.entities;
const entityIndex = entities.indexOf(body.entity);
if (-1 !== entityIndex) {
entities.splice(entityIndex, 1);
}
}
this.entities.delete(body);
this.removeQuadTreeNodes(body);
this.bodies.splice(index, 1);
}
@ -121,7 +107,7 @@ export class World {
tick(elapsed) {
// Apply.
for (const entity of this.entities) {
for (const entity of this.entities.values()) {
const body = entity.body;
const translation = Vector.add(
Vector.scale(body.impulse, elapsed),
@ -132,7 +118,7 @@ export class World {
// Contact checks.
const allContacts = new Map();
const checkedSoFar = new Map();
for (const entity of this.entities) {
for (const entity of this.entities.values()) {
const body = entity.body;
// Find bodies in AABB.
const aabb = body.aabb;
@ -149,8 +135,8 @@ export class World {
const checkSet = new Set();
checkedSoFar.set(entity, checkSet);
for (const otherBody of otherBodies) {
if (otherBody.entity) {
const otherEntity = otherBody.entity;
const otherEntity = this.entities.get(otherBody);
if (otherEntity) {
// Only one check per pair.
const otherCheckSet = checkedSoFar.get(otherEntity);
if (otherCheckSet) {
@ -173,7 +159,7 @@ export class World {
otherContacts = otherContacts.add(entity);
allContacts.set(otherEntity, otherContacts);
// Mark as checked.
checkSet.add(otherBody.entity);
checkSet.add(otherEntity);
}
}
if (!allContacts.get(entity)) {
@ -181,7 +167,7 @@ export class World {
}
}
// Report collisions.
for (const entity of this.entities) {
for (const entity of this.entities.values()) {
const oldContacts = entity.body.contacts;
const newContacts = allContacts.get(entity);
for (const contact of newContacts.values()) {
@ -197,7 +183,7 @@ export class World {
entity.body.contacts = newContacts;
}
// Super rudimentary resolving.
for (const entity of this.entities) {
for (const entity of this.entities.values()) {
const body = entity.body;
// Contact? Undo impulse.
const contacts = body.contacts;
@ -227,12 +213,12 @@ export class World {
}
}
// Drop transforms.
for (const {body} of this.entities) {
for (const {body} of this.entities.values()) {
body.force = [0, 0];
body.impulse = [0, 0];
}
// Propagate position updates.
for (const entity of this.entities) {
for (const entity of this.entities.values()) {
entity.position = entity.body.position;
}
}