feat: more dynamic collision semantics
This commit is contained in:
parent
226a71f065
commit
63fdbab66a
|
@ -36,9 +36,16 @@ export class World extends AbstractWorld {
|
|||
const {bodyA, bodyB} = pair;
|
||||
const entityA = this.entities.get(Body.lookupBody(bodyA));
|
||||
const entityB = this.entities.get(Body.lookupBody(bodyB));
|
||||
if (entityA && entityB) {
|
||||
entityA.emit(eventName, entityB);
|
||||
entityB.emit(eventName, entityA);
|
||||
if (
|
||||
entityA && entityA.is('collider')
|
||||
&& entityB && entityB.is('collider')
|
||||
) {
|
||||
if (entityA.collidesWith(entityB)) {
|
||||
entityA.emit(eventName, entityB);
|
||||
}
|
||||
if (entityB.collidesWith(entityA)) {
|
||||
entityB.emit(eventName, entityA);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {behaviorItemFromJSON, createContext} from '@avocado/behavior';
|
||||
import {compose} from '@avocado/core';
|
||||
import {StateProperty, Trait} from '@avocado/entity';
|
||||
|
||||
|
@ -12,6 +13,8 @@ export class Collider extends decorate(Trait) {
|
|||
collidesWithGroups: [
|
||||
'default',
|
||||
],
|
||||
collisionEndActions: undefined,
|
||||
collisionStartActions: undefined,
|
||||
collisionGroup: 'default',
|
||||
isSensor: false,
|
||||
}
|
||||
|
@ -29,8 +32,10 @@ export class Collider extends decorate(Trait) {
|
|||
|
||||
constructor(entity, params, state) {
|
||||
super(entity, params, state);
|
||||
this._collisionActions = [];
|
||||
this._collisionGroup = this.params.collisionGroup;
|
||||
this._collidesWithGroups = this.params.collidesWithGroups;
|
||||
this._doesNotCollideWith = [];
|
||||
this._isCollidingWith = [];
|
||||
this._isSensor = this.params.isSensor;
|
||||
}
|
||||
|
@ -55,6 +60,22 @@ export class Collider extends decorate(Trait) {
|
|||
return this._isSensor;
|
||||
}
|
||||
|
||||
pushActionBundle(paramActions, other) {
|
||||
const actions = behaviorItemFromJSON(paramActions);
|
||||
const context = createContext();
|
||||
context.set('entity', this.entity);
|
||||
context.set('other', other);
|
||||
const bundle = {
|
||||
actions,
|
||||
context,
|
||||
};
|
||||
this._collisionActions.push(bundle);
|
||||
actions.once('actionsFinished', () => {
|
||||
const index = this._collisionActions.indexOf(bundle);
|
||||
this._collisionActions.splice(index, 1);
|
||||
});
|
||||
}
|
||||
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
|
@ -62,6 +83,9 @@ export class Collider extends decorate(Trait) {
|
|||
const index = this._isCollidingWith.indexOf(other);
|
||||
if (-1 !== index) {
|
||||
this._isCollidingWith.splice(index, 1);
|
||||
if (this.params.collisionEndActions) {
|
||||
this.pushActionBundle(this.params.collisionEndActions, other);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,6 +93,9 @@ export class Collider extends decorate(Trait) {
|
|||
const index = this._isCollidingWith.indexOf(other);
|
||||
if (-1 === index) {
|
||||
this._isCollidingWith.push(other);
|
||||
if (this.params.collisionStartActions) {
|
||||
this.pushActionBundle(this.params.collisionStartActions, other);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -83,10 +110,17 @@ export class Collider extends decorate(Trait) {
|
|||
return {
|
||||
|
||||
collidesWith: (entity) => {
|
||||
const collisionGroup = entity.collisionGroup();
|
||||
if (-1 !== this._doesNotCollideWith.indexOf(entity)) {
|
||||
return false;
|
||||
}
|
||||
const collisionGroup = entity.collisionGroup;
|
||||
return -1 !== this._collidesWithGroups.indexOf(collisionGroup);
|
||||
},
|
||||
|
||||
doesNotCollideWith: (entity) => {
|
||||
return !this.entity.collidesWith(entity);
|
||||
},
|
||||
|
||||
releaseAllCollisions: () => {
|
||||
for (let i = 0; i < this._isCollidingWith.length; i++) {
|
||||
const entity = this._isCollidingWith[i];
|
||||
|
@ -95,6 +129,28 @@ export class Collider extends decorate(Trait) {
|
|||
this._isCollidingWith = [];
|
||||
},
|
||||
|
||||
setDoesCollideWith: (entity) => {
|
||||
const index = this._doesNotCollideWith.indexOf(entity);
|
||||
if (-1 !== index) {
|
||||
this._doesNotCollideWith.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
setDoesNotCollideWith: (entity) => {
|
||||
if (-1 === this._doesNotCollideWith.indexOf(entity)) {
|
||||
this._doesNotCollideWith.push(entity);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
if (AVOCADO_SERVER) {
|
||||
for (let i = 0; i < this._collisionActions.length; ++i) {
|
||||
const {actions, context} = this._collisionActions[i];
|
||||
actions.tick(context, elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user