@dill-pixel/plugin-snap-physics
Version:
Snap Physics
86 lines (78 loc) • 2.87 kB
text/typescript
import { Application } from 'dill-pixel';
import { Actor } from './Actor';
import { Entity } from './Entity';
import { System } from './System';
import { Collision, EntityType } from './types';
import { checkCollision } from './utils';
export class Sensor<T = any, A extends Application = Application> extends Actor<T, A> {
type = 'Sensor';
isSensor = true;
isColliding = false;
/**
* Types of entities that can pass through this sensor without triggering a collision
* All actors by default, so sensors can still be pushed by and ride on solids,
* but we don't check collisions with other actors in the moveX and moveY methods
* You can call "resolveAllCollisions" to still resolve collisions for actors,
* but not have this sensor be "pushed" by them
*/
passThroughTypes: EntityType[] = ['Actor', 'Player'];
getCollideables<T extends Entity = Entity>(): Set<T> {
return System.getNearbyEntities<T>(this, 'actor') as Set<T>;
}
added() {
System.addSensor(this);
}
removed() {
System.removeSensor(this);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fixedUpdate(_deltaTime?: number) {
this.activeCollisions = this.resolveAllCollisions() || [];
this.isColliding = this.activeCollisions ? this.activeCollisions.length > 0 : false;
}
/**
* Resolve all collisions for this sensor
* ignores passThroughTypes
*/
resolveAllCollisions(): null | Collision[] {
const collisions = [];
// Iterate through all solids in the level to check for collisions
for (const entity of this.getCollideables()) {
if (!entity.isCollideable) {
continue;
}
const collisionResult = checkCollision(this.getBoundingBox(), entity.getBoundingBox(), this, entity);
if (collisionResult) {
collisions.push(collisionResult);
}
if (collisionResult) {
System.collide(collisionResult);
// if the collision resolver returns true,
// we should stop and return this collision
// this will stop actor movement if returned
if (System.resolveCollision(collisionResult)) {
collisions.push(collisionResult);
}
}
}
return collisions.length ? collisions : null;
}
getOuterCollisions(collideables = this.getCollideables()) {
const outerBoundingBox = this.getOuterBoundingBox();
if (!outerBoundingBox) {
// Logger.error(this.type, 'has no outer bounding box. Returning empty array.');
return [];
}
const collisions: Collision[] = [];
for (const entity of collideables) {
if (!entity.isCollideable) {
continue;
}
const collisionResult = checkCollision(outerBoundingBox, entity.getBoundingBox(), this, entity);
if (collisionResult) {
collisions.push(collisionResult);
}
}
return collisions;
}
}