gibbon.js
Version:
Actor/Component system for use with pixi.js.
152 lines (106 loc) • 3.66 kB
text/typescript
import { Component } from '../core/component';
import { Grid } from './grid';
import { Collider2d } from '../components/collider2d';
import { EngineEvent } from '../events/engine-events';
import type { Transform } from '../core/transform';
/**
* Wraps quadtree to give access to geometric testing.
*/
export class HitDetection extends Component {
/**
* underlying quadtree that provides collision tests.
*/
//private tree: Quadtree<Indexable>;
/**
* Properties used for creating quadtree.
*/
//private treeProps: QuadtreeProps;
private grid: Grid<Collider2d>;
private _transform!: Transform;
/**
*
* @param props
* @param props.parent - parent whose children with collider2ds are detected for collisions.
* @param props.width
* @param props.height
*/
constructor(props: {
width: number, height: number,
}) {
super();
this.grid = new Grid({ width: props.width, height: props.height });
/*if (!tree) {
this.tree = tree ?? new Quadtree({
maxLevels: 5,
maxObjects: 10,
width: 100,
height: 100
});
} else if (tree instanceof Quadtree) {
this.tree = tree;
} else {
this.tree = new Quadtree(tree);
}*/
}
init() {
// Find initial colliders.
this._transform = this.actor!.transform;
const colliders = this._transform.findInChildren(Collider2d);
for (let i = colliders.length - 1; i >= 0; i--) {
this.grid.addItem(colliders[i]);
}
this.actor!.on(EngineEvent.ChildAdded, this.childAdded, this);
this.actor!.off(EngineEvent.ChildRemoved, this.childRemoved, this);
this.actor!.on(EngineEvent.ActorDestroyed, this.childRemoved, this);
}
childAdded(t: Transform) {
const collider = t.get(Collider2d);
if (collider) {
this.grid.addItem(collider);
}
}
/**
* Update collider's position in grid.
* @param collider
*/
updateItem(collider: Collider2d) {
this.grid.removeItem(collider);
this.grid.addItem(collider);
}
childRemoved(t: Transform) {
const collider = t.get(Collider2d);
if (collider) {
this.grid.removeItem(collider);
}
}
addCollider(collider: Collider2d) {
//this.tree.insert(obj);
this.grid.addItem(collider);
}
removeCollider(collider: Collider2d) {
this.grid.removeItem(collider);
}
update(delta: number) {
/**
* Updating Positions: In future might actually detect changes in colliders themselves?
*/
for (const child of this._transform) {
const collider = child.get(Collider2d);
if (collider && !collider.isStatic) {
this.grid.removeItem(collider);
this.grid.addItem(collider);
}
}
const hitResults: Array<Collider2d> = [];
for (const child of this._transform) {
const collider = child.get(Collider2d);
if (collider) {
hitResults.length = 0;
this.grid.getHits(collider, hitResults);
if (hitResults.length > 0) {
collider.actor!.emit(EngineEvent.Collision, collider, hitResults);
}
}
}
}
}