Skip to content

Commit

Permalink
feat(#44): ECS.removeEntities(world, query)
Browse files Browse the repository at this point in the history
- added method to remove entities as specified in #44
- added tests
- adding types
  • Loading branch information
chriscoderdr committed Nov 10, 2024
1 parent de9aae6 commit 9848069
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1 deletion.
37 changes: 37 additions & 0 deletions ecs.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,42 @@ export function addComponentToEntity (world, entity, componentName, componentDat
}
}

/**
* Remove entities from the world that match the given component criteria.
* @param {World} world - The world containing the entities.
* @param {string[]} componentNames - Array of component names to filter by.
* Supports 'not' filters by prefixing component names with '!'.
*/
export function removeEntities(world, componentNames) {
const entitiesToRemove = world.entities.filter((entity) => {
for (const componentName of componentNames) {
const isNotFilter = componentName.startsWith('!');
const actualComponentName = isNotFilter
? componentName.slice(1)
: componentName;

if (isNotFilter) {
// If it's a 'not' filter (prefixed with '!'), the entity should NOT have the component
if (entity[actualComponentName]) {
return false;
}
} else {
// If it's a regular filter, the entity MUST have the component
if (!entity[actualComponentName]) {
return false;
}
}
}
return true;
});

// Remove each matched entity
for (const entity of entitiesToRemove) {
removeEntity(world, entity, false); // remove immediately
}
}



/**
* Get entities from the world with all provided components. Optionally,
Expand Down Expand Up @@ -687,6 +723,7 @@ export default {
getEntities,
getEntity,
removeEntity,
removeEntities,
addSystem,
preFixedUpdate,
fixedUpdate,
Expand Down
39 changes: 39 additions & 0 deletions test/removeEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,42 @@ import tap from 'tap'

ECS.cleanup(w)
}

{
// Test removeEntities function with 'not' filter support
const w = ECS.addWorld();

const e1 = ECS.addEntity(w);
ECS.addComponent(w, e1, 'ephemeral', {});

const e2 = ECS.addEntity(w);
ECS.addComponent(w, e2, 'ephemeral', {});
ECS.addComponent(w, e2, 'health', { hp: 100 });

const e3 = ECS.addEntity(w);
ECS.addComponent(w, e3, 'transform', {});
ECS.addComponent(w, e3, 'health', { hp: 100 });

tap.equal(w.entities.length, 3, '3 entities should be present initially');

// Remove all entities with 'ephemeral' component
ECS.removeEntities(w, ['ephemeral']);
ECS.cleanup(w); // process deferred removals
tap.equal(w.entities.length, 1, 'only 1 entity should remain after removing all entities with "ephemeral"');

// Add entities again for next test
const e4 = ECS.addEntity(w);
ECS.addComponent(w, e4, 'transform', {});
ECS.addComponent(w, e4, 'ephemeral', {});

const e5 = ECS.addEntity(w);
ECS.addComponent(w, e5, 'transform', {});
ECS.addComponent(w, e5, 'health', { hp: 100 });

tap.equal(w.entities.length, 3, '3 entities should be present after adding new entities');

// Remove entities with 'transform' but not 'health'
ECS.removeEntities(w, ['transform', '!health']);
ECS.cleanup(w); // process deferred removals
tap.equal(w.entities.length, 2, '2 entities should remain after removing entities with "transform" but not "health"');
}
7 changes: 7 additions & 0 deletions types/ecs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ export function removeComponentFromEntity(world: World, entity: Entity, componen
* @returns {void} returns early if entity does not exist in world
*/
export function removeEntity(world: World, entity: Entity, deferredRemoval?: boolean): void;
/**
* Remove entities from the world that match the given component criteria.
* @param {World} world - The world containing the entities.
* @param {string[]} componentNames - Array of component names to filter by.
* Supports 'not' filters by prefixing component names with '!'.
*/
export function removeEntities(world: World, componentNames: string[]): void;
/**
* Get entities from the world with all provided components. Optionally,
* @param {World} world
Expand Down
2 changes: 1 addition & 1 deletion types/ecs.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 9848069

Please sign in to comment.