Système d'entités et de composants #1

Merged
tipragot merged 9 commits from ecs-system into main 2023-10-23 14:04:18 +00:00
Showing only changes of commit e9076fa726 - Show all commits

32
ecs.py
View file

@ -3,42 +3,42 @@ from typing import Iterator
class World: class World:
def __init__(self): def __init__(self):
self.to_apply: set[Entity] = set() self._to_apply: set[Entity] = set()
self.entities: set[Entity] = set() self._entities: set[Entity] = set()
self.mapping: dict[type, set[Entity]] = {} self._mapping: dict[type, set[Entity]] = {}
def create_entity(self, *components): def create_entity(self, *components):
return Entity(self, *components) return Entity(self, *components)
def remove_entity(self, entity: 'Entity'): def remove_entity(self, entity: 'Entity'):
entity._deleted = True entity._deleted = True
self.to_apply.add(entity) self._to_apply.add(entity)
def apply(self): def apply(self):
for entity in self.to_apply: for entity in self._to_apply:
if entity._deleted: if entity._deleted:
self.entities.remove(entity) self._entities.remove(entity)
for component_type in entity._components: for component_type in entity._components:
self.mapping[component_type].remove(entity) self._mapping[component_type].remove(entity)
else: else:
self.entities.add(entity) self._entities.add(entity)
for component_type, component in entity._to_apply: for component_type, component in entity._to_apply:
if component is None: if component is None:
del entity._components[component_type] del entity._components[component_type]
self.mapping[component_type].remove(entity) self._mapping[component_type].remove(entity)
else: else:
entity._components[component_type] = component entity._components[component_type] = component
self.mapping.setdefault(component_type, set()).add(entity) self._mapping.setdefault(component_type, set()).add(entity)
entity._to_apply.clear() entity._to_apply.clear()
def query(self, *needed: type, without: tuple[type] = []) -> Iterator['Entity']: def query(self, *needed: type, without: tuple[type] = []) -> Iterator['Entity']:
if not needed: if not needed:
for entity in self.entities: for entity in self._entities:
if all(without_type not in entity for without_type in without): if all(without_type not in entity for without_type in without):
yield entity yield entity
else: else:
for entity in self.mapping.get(needed[0], set()): for entity in self._mapping.get(needed[0], set()):
if all(entity in self.mapping.get(component_type, set()) for component_type in needed[1:]) and \ if all(entity in self._mapping.get(component_type, set()) for component_type in needed[1:]) and \
all(without_type not in entity for without_type in without): all(without_type not in entity for without_type in without):
yield entity yield entity
@ -48,18 +48,18 @@ class Entity:
self._to_apply: list[tuple[type, object]] = [(type(component), component) for component in components] self._to_apply: list[tuple[type, object]] = [(type(component), component) for component in components]
self._components: dict[type, object] = {} self._components: dict[type, object] = {}
self._deleted = False self._deleted = False
self._world.to_apply.add(self) self._world._to_apply.add(self)
def set(self, *components): def set(self, *components):
for component in components: for component in components:
self._to_apply.append((type(component), component)) self._to_apply.append((type(component), component))
self._world.to_apply.add(self) self._world._to_apply.add(self)
def remove(self, *component_types: type): def remove(self, *component_types: type):
for component_type in component_types: for component_type in component_types:
if component_type in self._components: if component_type in self._components:
self._to_apply.append((component_type, None)) self._to_apply.append((component_type, None))
self._world.to_apply.add(self) self._world._to_apply.add(self)
def __getitem__(self, component_type: type) -> object: def __getitem__(self, component_type: type) -> object:
return self._components[component_type] return self._components[component_type]