refactor: decouple entity from body
This commit is contained in:
parent
23c7a77e5b
commit
caf69e3333
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user