UNPKG

@dill-pixel/plugin-snap-physics

Version:

Snap Physics

86 lines (78 loc) 2.87 kB
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; } }