blob2d
Version:
Typed Modular 2D Game Engine for Web
76 lines (65 loc) • 2.19 kB
text/typescript
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;
}
}