Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/excaliburjs/Excalibur. 🎮 Your friendly TypeScript 2D game engine for the web 🗡️ excaliburjs.com
excalibur excaliburjs game-development game-engine game-framework gamedev games html5-canvas typescript
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241import * as ex from '@excalibur';
class FakeComponentA extends ex.Component {}class FakeComponentB extends ex.Component {}class FakeComponentC extends ex.Component {}
describe('A QueryManager', () => { it('exists', () => { expect(ex.QueryManager).toBeDefined(); });
it('can be created', () => { const queryManager = new ex.QueryManager(new ex.World(null)); expect(queryManager).not.toBeNull(); });
it('can create queries for entities', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addComponent(new FakeComponentA()); entity1.addComponent(new FakeComponentB());
const entity2 = new ex.Entity(); entity2.addComponent(new FakeComponentA());
world.entityManager.addEntity(entity1); world.entityManager.addEntity(entity2);
// Query for all entities that have type A components const queryA = world.query([FakeComponentA]); // Query for all entities that have type A & B components const queryAB = world.query([FakeComponentA, FakeComponentB]);
expect(queryA.getEntities(), 'Both entities have component A').toEqual([entity1, entity2]); expect(queryAB.getEntities(), 'Only entity1 has both A+B').toEqual([entity1]);
// Queries update if component change entity2.addComponent(new FakeComponentB()); expect(queryAB.getEntities(), 'Now both entities have A+B').toEqual([entity1, entity2]);
// Queries update if components change entity2.removeComponent(FakeComponentB, true); expect(queryAB.getEntities(), 'Component force removed from entity, only entity1 A+B').toEqual([entity1]);
// Queries are deferred by default, so queries will update after removals entity1.removeComponent(FakeComponentB); expect(queryAB.getEntities(), 'Deferred removal, component is still part of entity1').toEqual([entity1]); entity1.processComponentRemoval(); expect(queryAB.getEntities(), 'No entities should match').toEqual([]); });
it('can add entities to queries', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addComponent(new FakeComponentA()); entity1.addComponent(new FakeComponentB());
const entity2 = new ex.Entity(); entity2.addComponent(new FakeComponentA()); entity2.addComponent(new FakeComponentB());
const queryAB = world.query([FakeComponentA, FakeComponentB]); expect(queryAB.getEntities()).toEqual([]);
world.queryManager.addEntity(entity1); expect(queryAB.getEntities()).toEqual([entity1]);
world.queryManager.addEntity(entity2); expect(queryAB.getEntities()).toEqual([entity1, entity2]); });
it('can add entities to tag queries', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addTag('A'); entity1.addTag('B');
const entity2 = new ex.Entity(); entity2.addTag('A'); entity2.addTag('B');
const queryAB = world.queryTags(['A', 'B']); expect(queryAB.getEntities()).toEqual([]);
world.queryManager.addEntity(entity1); expect(queryAB.getEntities()).toEqual([entity1]);
world.queryManager.addEntity(entity2); expect(queryAB.getEntities()).toEqual([entity1, entity2]); });
it('can remove entities from queries', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addComponent(new FakeComponentA()); entity1.addComponent(new FakeComponentB());
const entity2 = new ex.Entity(); entity2.addComponent(new FakeComponentA()); entity2.addComponent(new FakeComponentB());
const queryAB = world.query([FakeComponentA, FakeComponentB]); world.queryManager.addEntity(entity1); world.queryManager.addEntity(entity2); expect(queryAB.getEntities()).toEqual([entity1, entity2]);
world.queryManager.removeEntity(entity1); expect(queryAB.getEntities()).toEqual([entity2]);
world.queryManager.removeEntity(entity2); expect(queryAB.getEntities()).toEqual([]); });
it('can remove entities from tag queries', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addTag('A'); entity1.addTag('B');
const entity2 = new ex.Entity(); entity2.addTag('A'); entity2.addTag('B');
const queryAB = world.queryTags(['A', 'B']); world.queryManager.addEntity(entity1); world.queryManager.addEntity(entity2); expect(queryAB.getEntities()).toEqual([entity1, entity2]);
world.queryManager.removeEntity(entity1); expect(queryAB.getEntities()).toEqual([entity2]);
world.queryManager.removeEntity(entity2); expect(queryAB.getEntities()).toEqual([]); });
it('can update queries when a component is removed', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addComponent(new FakeComponentA()); entity1.addComponent(new FakeComponentB());
const entity2 = new ex.Entity(); entity2.addComponent(new FakeComponentA()); entity2.addComponent(new FakeComponentB());
const queryAB = world.query([FakeComponentA, FakeComponentB]); world.queryManager.addEntity(entity1); world.queryManager.addEntity(entity2);
expect(queryAB.getEntities()).toEqual([entity1, entity2]);
const removed = entity1.get(FakeComponentA); entity1.removeComponent(FakeComponentA); world.queryManager.removeComponent(entity1, removed);
expect(queryAB.getEntities()).toEqual([entity2]); });
it('can update tag queries when a component is removed', () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addTag('A'); entity1.addTag('B');
const entity2 = new ex.Entity(); entity2.addTag('A'); entity2.addTag('B');
const queryAB = world.queryTags(['A', 'B']); world.queryManager.addEntity(entity1); world.queryManager.addEntity(entity2);
expect(queryAB.getEntities()).toEqual([entity1, entity2]);
entity1.removeTag('A'); world.queryManager.removeTag(entity1, 'A');
expect(queryAB.getEntities()).toEqual([entity2]); });
it("removing components unrelated to the query doesn't remove the entity", () => { const world = new ex.World(null); const entity1 = new ex.Entity(); entity1.addComponent(new FakeComponentA()); entity1.addComponent(new FakeComponentB()); entity1.addComponent(new FakeComponentC());
const entity2 = new ex.Entity(); entity2.addComponent(new FakeComponentA()); entity2.addComponent(new FakeComponentB());
const queryAB = world.query([FakeComponentA, FakeComponentB]); world.queryManager.addEntity(entity1); world.queryManager.addEntity(entity2);
expect(queryAB.getEntities()).toEqual([entity1, entity2]);
const removed = entity1.get(FakeComponentC); entity1.removeComponent(FakeComponentC); world.queryManager.removeComponent(entity1, removed);
expect(queryAB.getEntities()).toEqual([entity1, entity2]); });
it('will be notified when entity components are added', () => new Promise<void>((done) => { const world = new ex.World(null); const entity = new ex.Entity(); world.add(entity);
const componentA = new FakeComponentA(); const query = world.query([FakeComponentA]); query.entityAdded$.subscribe((e) => { expect(e).toBe(entity); expect(e.get(FakeComponentA)).toBe(componentA); done(); });
entity.addComponent(componentA); }));
it('will be notified when entity components are removed', () => new Promise<void>((done) => { const world = new ex.World(null); const entity = new ex.Entity(); world.add(entity); const componentA = new FakeComponentA(); entity.addComponent(componentA);
const query = world.query([FakeComponentA]); query.entityRemoved$.subscribe((e) => { expect(e).toBe(entity); expect(e.get(FakeComponentA)).toBe(componentA); done(); });
entity.removeComponent(FakeComponentA); entity.processComponentRemoval(); }));});