feat: Collider
This commit is contained in:
parent
8bdd0f27b6
commit
b227b69855
51
packages/entity/traits/collider.js
Normal file
51
packages/entity/traits/collider.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import {compose} from '@avocado/core';
|
||||
import {StateProperty, Trait} from '../trait';
|
||||
|
||||
const decorate = compose(
|
||||
StateProperty('isCheckingCollisions'),
|
||||
);
|
||||
|
||||
export class Collider extends decorate(Trait) {
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
collidesWithGroups: [
|
||||
'default',
|
||||
],
|
||||
collisionGroup: 'default',
|
||||
}
|
||||
}
|
||||
|
||||
static defaultState() {
|
||||
return {
|
||||
isCheckingCollisions: true,
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this._collisionGroup = this.params.get('collisionGroup');
|
||||
this._collidesWithGroups = this.params.get('collidesWithGroups').toJS();
|
||||
}
|
||||
|
||||
get collisionGroup() {
|
||||
return this._collisionGroup;
|
||||
}
|
||||
|
||||
get collidesWithGroups() {
|
||||
return this._collidesWithGroups;
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
collidesWith: (entity) => {
|
||||
if (!entity.is('collider')) {
|
||||
return false;
|
||||
}
|
||||
const collisionGroup = entity.collisionGroup();
|
||||
return -1 !== this._collidesWithGroups.indexOf(collisionGroup);
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ export class Physical extends decorate(Trait) {
|
|||
if (world) {
|
||||
const body = world.createBody(this.entity.shape);
|
||||
world.associateBodyWithEntity(body, this.entity);
|
||||
body.setCollisionForEntity(this.entity);
|
||||
world.addBody(body);
|
||||
this._body = body;
|
||||
if (this.entity.container) {
|
||||
|
|
|
@ -8,6 +8,20 @@ import { Rectangle } from '../../math';
|
|||
|
||||
export class Body extends AbstractBody {
|
||||
|
||||
static collisionCategory(group) {
|
||||
if (!('filterCategoryBit' in this)) {
|
||||
this.filterCategoryBit = 0;
|
||||
}
|
||||
if (!('filterCategories' in this)) {
|
||||
this.filterCategories = {};
|
||||
}
|
||||
if (!this.filterCategories[group]) {
|
||||
this.filterCategories[group] = 1 << this.filterCategoryBit;
|
||||
this.filterCategoryBit += 1;
|
||||
}
|
||||
return this.filterCategories[group];
|
||||
}
|
||||
|
||||
static lookupBody(matterBody) {
|
||||
if (this.bodies) {
|
||||
return this.bodies.get(matterBody);
|
||||
|
@ -98,6 +112,29 @@ export class Body extends AbstractBody {
|
|||
});
|
||||
}
|
||||
|
||||
setCollision(category, mask, group = 0) {
|
||||
MatterBody.set(this.matterBody, 'collisionFilter', {
|
||||
category,
|
||||
group,
|
||||
mask,
|
||||
});
|
||||
}
|
||||
|
||||
setCollisionForEntity(entity) {
|
||||
if (entity.is('collider')) {
|
||||
const ctor = this.constructor;
|
||||
const category = ctor.collisionCategory(entity.collisionGroup);
|
||||
let mask = 0;
|
||||
for (const group of entity.collidesWithGroups) {
|
||||
mask = mask | ctor.collisionCategory(group);
|
||||
}
|
||||
this.setCollision(category, mask);
|
||||
}
|
||||
else {
|
||||
this.setCollision(0, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
get static() {
|
||||
return this.matterBody.isStatic;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user