Coverage for src/gncpy/game_engine/entities.py: 0%
63 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-13 06:15 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-13 06:15 +0000
1"""Defines game entities and a manager class."""
4class Entity:
5 """Elements in a game.
7 These should not be created or deleted directly, the manager class should
8 be used instead.
9 """
11 __slots__ = ("_active", "_id", "_tag", "_components")
13 def __init__(self, e_id, tag):
14 """Initialize an object.
16 This should not be called outside of the :class:`.EntityManager` class.
18 Parameters
19 ----------
20 e_id : int
21 Unique ID number for the entity.
22 tag : string
23 Type of entity.
24 """
25 self._active = True
26 self._id = e_id
27 self._tag = tag
29 self._components = {}
31 @property
32 def active(self):
33 """Flag indicating if the entity is alive."""
34 return self._active
36 @property
37 def tag(self):
38 """Read only tag of for the entity."""
39 return self._tag
41 @property
42 def id(self):
43 """Read only unique id of the entity."""
44 return self._id
46 def destroy(self):
47 """Handles destruction of the entity."""
48 self._active = False
50 def has_component(self, comp):
51 """Returns true if the entity has the given component.
53 Parameters
54 ----------
55 comp : object
56 Component class from :mod:`gncpy.game_engine.components`.
58 Returns
59 -------
60 bool
61 Flag indicating if the entity has the component.
62 """
63 return comp.__name__ in self._components
65 def get_component(self, comp):
66 """Returns a reference to the given component.
68 This assumes the component exists.
70 Parameters
71 ----------
72 comp : object
73 Component class from :mod:`gncpy.game_engine.components`.
75 Returns
76 -------
77 object
78 reference to a class instance from :mod:`gncpy.game_engine.components`.
79 """
80 return self._components[comp.__name__]
82 def add_component(self, comp, **kwargs):
83 """Adds a component to the entity.
85 Parameters
86 ----------
87 comp : class constructor
88 Component class constructor from :mod:`gncpy.game_engine.components`.
89 **kwargs : dict, optional
90 Additional arguments to pass to the constructor.
92 Returns
93 -------
94 component : object
95 Reference to the new component class.
96 """
97 component = comp(**kwargs)
98 self._components[comp.__name__] = component
99 return component
102class EntityManager:
103 """Handles creation and deletion of entities."""
105 __slots__ = ("_entities", "_entities_to_add", "_entity_map", "_total_entities")
107 def __init__(self):
108 self._entities = []
109 self._entities_to_add = []
110 self._entity_map = {}
111 self._total_entities = 0
113 def _remove_dead_entities(self, vec):
114 e_to_rm = []
115 for ii, e in enumerate(vec):
116 if not e.active:
117 e_to_rm.append(ii)
119 for ii in e_to_rm[::-1]:
120 del vec[ii]
122 def update(self):
123 """Updates the list of entities.
125 Should be called once per timestep. Adds new entities to the list and
126 and removes dead ones.
127 """
128 for e in self._entities_to_add:
129 self._entities.append(e)
130 if e.tag not in self._entity_map:
131 self._entity_map[e.tag] = []
132 self._entity_map[e.tag].append(e)
133 self._entities_to_add = []
135 self._remove_dead_entities(self._entities)
137 for tag, ev in self._entity_map.items():
138 self._remove_dead_entities(ev)
140 def add_entity(self, tag):
141 """Creates a new entity.
143 The entity is queued to be added. It is not part of the entity list
144 until after the update function has been called.
146 Parameters
147 ----------
148 tag : string
149 Tag to identify the type of entity.
151 Returns
152 -------
153 e : :class:`.Entity`
154 Reference to the created entity.
155 """
156 self._total_entities += 1
157 e = Entity(self._total_entities, tag)
158 self._entities_to_add.append(e)
160 return e
162 def get_entities(self, tag=None):
163 """Return a list of references to entities.
165 Can also get all entities with a given tag. Note that changing entities
166 returned by this function modifies the entities managed by this class.
168 Parameters
169 ----------
170 tag : string, optional
171 If provided only return entities with this tag. The default is None.
173 Returns
174 -------
175 list
176 Each element is an :class:`.Entity`.
177 """
178 if tag is None:
179 return self._entities
180 else:
181 if tag in self._entity_map:
182 return self._entity_map[tag]
183 else:
184 return []
186 def get_entity_ids(self, tag=None):
187 """Return a list of the entity ids.
189 Parameters
190 ----------
191 tag : string, optional
192 If provided only return ids for entities with this tag. The default
193 is None.
195 Returns
196 -------
197 list
198 Each element is an entity id.
199 """
200 return [e.id for e in self.get_entities(tag=tag)]