UNPKG

blob2d

Version:

Typed Modular 2D Game Engine for Web

76 lines (65 loc) 2.19 kB
import {TAnyEntity} from '../../types'; import {arrayRemove} from '../../utils/array'; import {detectEntityCollision} from './entityCollisions'; import {ICollisionsGroup, TCollisionDynamicResponse} from './types'; export class CollisionsDynamicGroup<A extends TAnyEntity, B extends TAnyEntity> implements ICollisionsGroup<A | B> { public readonly type = 'dynamic'; public readonly entitiesA: A[]; public readonly entitiesB: B[]; protected response: TCollisionDynamicResponse<A, B>; constructor( entitiesA: A[], entitiesB: B[], response: TCollisionDynamicResponse<A, B> ) { this.entitiesA = [...entitiesA]; this.entitiesB = [...entitiesB]; this.response = response; } resolve(deltaTime: number): void { const {entitiesA, entitiesB, response} = this; // it is optimized for the first subgroup, // which often has only one element if (entitiesA.length > 1) { for (let i = 0; i < entitiesA.length; i++) { const entity = entitiesA[i]; // bypass loop for one element if (entitiesB.length > 1) { for (let j = 0; j < entitiesB.length; j++) { detectEntityCollision(entity, entitiesB[j], deltaTime, response); } } else { detectEntityCollision(entity, entitiesB[0], deltaTime, response); } } } else { // a single entity collision const entity = entitiesA[0]; // bypass loop for one element if (entitiesB.length > 1) { for (let j = 0; j < entitiesB.length; j++) { detectEntityCollision(entity, entitiesB[j], deltaTime, response); } } else { detectEntityCollision(entity, entitiesB[0], deltaTime, response); } } } removeChild(child: A | B): boolean { return ( arrayRemove(this.entitiesA, child) || arrayRemove(this.entitiesB, child) ); } validate(): void { if (this.entitiesA.length < 1 || this.entitiesB.length < 1) { throw new Error( 'A dynamic collisions group requires at least one entity from each subgroup.' ); } } destroy(): void { this.entitiesA.length = 0; this.entitiesB.length = 0; } }