tinyecs 0.3.6__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {tinyecs-0.3.6/src/tinyecs.egg-info → tinyecs-0.4.0}/PKG-INFO +1 -1
  2. {tinyecs-0.3.6 → tinyecs-0.4.0}/pyproject.toml +1 -1
  3. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/__init__.py +14 -20
  4. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/compsys.py +12 -12
  5. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/background.py +4 -4
  6. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/bouncing_sprites.py +2 -2
  7. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/example.py +6 -6
  8. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/homing-missiles.py +14 -14
  9. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/marquee.py +2 -2
  10. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/tutorial.py +37 -36
  11. {tinyecs-0.3.6 → tinyecs-0.4.0/src/tinyecs.egg-info}/PKG-INFO +1 -1
  12. {tinyecs-0.3.6 → tinyecs-0.4.0}/tests/test_tinyecs.py +19 -19
  13. {tinyecs-0.3.6 → tinyecs-0.4.0}/LICENSE +0 -0
  14. {tinyecs-0.3.6 → tinyecs-0.4.0}/README.rst +0 -0
  15. {tinyecs-0.3.6 → tinyecs-0.4.0}/setup.cfg +0 -0
  16. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/components.py +0 -0
  17. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demo.py +0 -0
  18. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs/demos/__init__.py +0 -0
  19. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs.egg-info/SOURCES.txt +0 -0
  20. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs.egg-info/dependency_links.txt +0 -0
  21. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs.egg-info/entry_points.txt +0 -0
  22. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs.egg-info/requires.txt +0 -0
  23. {tinyecs-0.3.6 → tinyecs-0.4.0}/src/tinyecs.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinyecs
3
- Version: 0.3.6
3
+ Version: 0.4.0
4
4
  Summary: The teeniest, tiniest ECS system
5
5
  Author-email: Michael Lamertz <michael.lamertz@gmail.com>
6
6
  License-Expression: MIT
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "tinyecs"
3
3
  description = "The teeniest, tiniest ECS system"
4
- version = "0.3.6"
4
+ version = "0.4.0"
5
5
  readme = "README.rst"
6
6
 
7
7
  authors = [
@@ -24,7 +24,7 @@ type DomainID = Hashable
24
24
  type Property = Hashable
25
25
  type Component = object
26
26
 
27
- type _EntityComponentsBundle = tuple[EntityID, list[Component]]
27
+ type EntityComponentsBundle = tuple[EntityID, list[Component]]
28
28
  type _OptionalProperties = Iterable[Property] | None
29
29
  type _RunSystemResult = dict[EntityID, Any]
30
30
 
@@ -32,7 +32,7 @@ type _RunSystemResult = dict[EntityID, Any]
32
32
  # The typehinting system can't work with functions using *args, **kwargs.
33
33
  # This solution comes from https://docs.python.org/3/library/typing.html#annotating-callable-objects
34
34
  class SystemFunction(Protocol):
35
- def __call__(self, dt: float, eid: EntityID, *cids: ComponentID, **kwargs: dict[str, object]) -> Any: ...
35
+ def __call__(self, eid: EntityID, *cids: ComponentID, **kwargs: dict[str, object]) -> Any: ...
36
36
 
37
37
 
38
38
  eidx = {} # entity index
@@ -480,7 +480,7 @@ def comp_of_eid(eid: EntityID, cid: ComponentID) -> Component:
480
480
  return comps_of_eid(eid, cid)[0]
481
481
 
482
482
 
483
- def eid_of_comp(comp: Component) -> set(EntityID):
483
+ def eid_of_comp(comp: Component) -> set[EntityID]:
484
484
  """Find the entity id for object comp.
485
485
 
486
486
  :param comp: The component to find the entity of
@@ -538,14 +538,12 @@ def _create_call_list(cids: tuple[ComponentID],
538
538
  return call_list
539
539
 
540
540
 
541
- def run_system(dt: float,
542
- fn: SystemFunction,
541
+ def run_system(fn: SystemFunction,
543
542
  *cids: ComponentID,
544
543
  has_properties: _OptionalProperties = None,
545
544
  **kwargs: dict[str, Any]) -> _RunSystemResult:
546
545
  """Run the system for the matching cids.
547
546
 
548
- :param dt: delta time since the last frame (miliseconds)
549
547
  :param fn: the actual system function
550
548
  :param cids: the components to run on
551
549
  :param has_properties: set of required properties
@@ -554,7 +552,7 @@ def run_system(dt: float,
554
552
  For every entity that has all the listed components, ``fn`` is run. The
555
553
  function prototype of ``fn`` is::
556
554
 
557
- def callback(dt: float, eid: EntityID, *comps: Component) -> Any
555
+ def callback(eid: EntityID, *comps: Component) -> Any
558
556
 
559
557
  The list can further be narrowed down my filtering for given properties.
560
558
 
@@ -563,17 +561,15 @@ def run_system(dt: float,
563
561
  """
564
562
 
565
563
  call_list = _create_call_list(cids, has_properties)
566
- return {eid: fn(dt, eid, *parms, **kwargs) for eid, *parms in call_list}
564
+ return {eid: fn(eid, *parms, **kwargs) for eid, *parms in call_list}
567
565
 
568
566
 
569
- def run_bulk_system(dt: float,
570
- fn: SystemFunction,
567
+ def run_bulk_system(fn: SystemFunction,
571
568
  *cids: ComponentID,
572
569
  has_properties: _OptionalProperties = None,
573
570
  **kwargs: dict[str, Any]) -> Any:
574
571
  """Run the bulk system for all entities with matching cids.
575
572
 
576
- :param dt: delta time since the last frame (miliseconds)
577
573
  :param fn: the actual system function
578
574
  :param cids: the components to run on
579
575
  :param has_properties: set of required properties
@@ -588,31 +584,29 @@ def run_bulk_system(dt: float,
588
584
 
589
585
  The prototype of ``fn`` is::
590
586
 
591
- def callback(dt: call_list: list[tuple[EntityID, list[Component]]]) -> Any
587
+ def callback(call_list: list[tuple[EntityID, list[Component]]]) -> Any
592
588
  """
593
589
 
594
590
  call_list = _create_call_list(cids, has_properties)
595
- return fn(dt, call_list, **kwargs)
591
+ return fn(call_list, **kwargs) if call_list else None
596
592
 
597
593
 
598
- def run_all_systems(dt: float) -> dict[SystemFunction, _RunSystemResult]:
594
+ def run_all_systems(**kwargs) -> dict[SystemFunction, _RunSystemResult]:
599
595
  """Run all registered systems.
600
596
 
601
- :param dt: Delta time
602
597
  :return: A dict of function as key, and the result of run_system as value
603
598
 
604
599
  This calls above run_system for all registered systems with their
605
600
  appropriate components.
606
601
  """
607
602
 
608
- return {fn: run_system(dt, fn, *comps)
603
+ return {fn: run_system(fn, *comps, **kwargs)
609
604
  for fn, comps in sidx.items()}
610
605
 
611
606
 
612
- def run_domain(dt: float, domain: DomainID) -> dict[SystemFunction, _RunSystemResult]:
607
+ def run_domain(domain: DomainID, **kwargs) -> dict[SystemFunction, _RunSystemResult]:
613
608
  """Run all systems within domain.
614
609
 
615
- :param dt: Delta time
616
610
  :return: A dict of function as key, and the result of run_system as value
617
611
 
618
612
  This is the same as run_all_systems, but limited to a specific domain.
@@ -621,7 +615,7 @@ def run_domain(dt: float, domain: DomainID) -> dict[SystemFunction, _RunSystemRe
621
615
  if domain not in didx:
622
616
  return {}
623
617
 
624
- return {fn: run_system(dt, fn, *sidx[fn])
618
+ return {fn: run_system(fn, *sidx[fn], **kwargs)
625
619
  for fn in didx[domain]}
626
620
 
627
621
 
@@ -706,7 +700,7 @@ def remove_from_archetype(eid: EntityID, cid: ComponentID | None = None) -> None
706
700
  del adict[eid]
707
701
 
708
702
 
709
- def comps_of_archetype(*cids: ComponentID, has_properties: _OptionalProperties = None) -> list[_EntityComponentsBundle]:
703
+ def comps_of_archetype(*cids: ComponentID, has_properties: _OptionalProperties = None) -> list[EntityComponentsBundle]:
710
704
  """Return the given archetype.
711
705
 
712
706
  :param cids: The cids that define the archetype.
@@ -249,12 +249,12 @@ class RSAImage:
249
249
  self.update()
250
250
 
251
251
 
252
- def dead_system(dt, eid, dead):
252
+ def dead_system(eid, dead, **kwargs):
253
253
  """Reap entities marked with a `dead` component."""
254
254
  ecs.remove_entity(eid)
255
255
 
256
256
 
257
- def deadzone_system(dt, eid, world, position, *, container):
257
+ def deadzone_system(eid, world, position, *, container, **kwargs):
258
258
  """Kill entities moving outside defined boundaries
259
259
 
260
260
  To avoid sprites flying off to infinity, a dead zone can be defined, that
@@ -284,7 +284,7 @@ def deadzone_system(dt, eid, world, position, *, container):
284
284
  ecs.remove_entity(eid)
285
285
 
286
286
 
287
- def extension_system(dt, eid, extension):
287
+ def extension_system(eid, extension, **kwargs):
288
288
  """Add additional components.
289
289
 
290
290
  Parameters:
@@ -318,29 +318,29 @@ def extension_system(dt, eid, extension):
318
318
  ecs.remove_component(eid, 'extension')
319
319
 
320
320
 
321
- def force_system(dt, eid, force, momentum):
321
+ def force_system(eid, force, momentum, *, dt, **kwargs):
322
322
  """Apply a force to a momentum"""
323
323
  momentum += force * dt
324
324
 
325
325
 
326
- def lifetime_system(dt, eid, lifetime):
326
+ def lifetime_system(eid, lifetime, **kwargs):
327
327
  """Kill an entity after a specified time"""
328
328
  if lifetime.cold():
329
329
  ecs.remove_entity(eid)
330
330
 
331
331
 
332
- def momentum_system(dt, eid, momentum, position):
332
+ def momentum_system(eid, momentum, position, *, dt):
333
333
  """Apply momentum to a position (a.k.a. "move")."""
334
334
  position += momentum * dt
335
335
 
336
336
 
337
- def mouse_system(dt, eid, mouse, position):
337
+ def mouse_system(eid, mouse, position):
338
338
  """Place the position of an entity to the mouse cursor."""
339
339
  mp = pygame.mouse.get_pos()
340
340
  position.xy = Vector2(mp)
341
341
 
342
342
 
343
- def scale_system(dt, eid, scale, momentum):
343
+ def scale_system(eid, scale, momentum, *, dt):
344
344
  """Apply friction to a momentum.
345
345
 
346
346
  In contrast to a force, which adds a directional vector to the momentum,
@@ -353,7 +353,7 @@ def scale_system(dt, eid, scale, momentum):
353
353
  friction_system = scale_system
354
354
 
355
355
 
356
- def sprite_system(dt, eid, sprite, position):
356
+ def sprite_system(eid, sprite, position, **kwargs):
357
357
  """Set the rect.center of sprite to position."""
358
358
 
359
359
  if sprite.rect:
@@ -362,7 +362,7 @@ def sprite_system(dt, eid, sprite, position):
362
362
  sprite.rect = sprite.image.get_rect(center=position)
363
363
 
364
364
 
365
- def wsad_system(dt, eid, wsad, position):
365
+ def wsad_system(eid, wsad, position, *, dt):
366
366
  """An example system to control a playear with the `wsad` keys.
367
367
 
368
368
  Given the following entity:
@@ -374,7 +374,7 @@ def wsad_system(dt, eid, wsad, position):
374
374
 
375
375
  running this system will modify the position component of the entity.
376
376
 
377
- ecs.run_system(dt, 'wsad', 'position', 'player')
377
+ ecs.run_system('wsad', 'position', 'player', dt=dt)
378
378
 
379
379
  Parameters
380
380
  ----------
@@ -396,4 +396,4 @@ def wsad_system(dt, eid, wsad, position):
396
396
  if keys[pygame.K_d]: v.x += 1
397
397
 
398
398
  # Normalize so diagonals are not faster then axis motion
399
- if v: position += v.normalize() * wsad * dt
399
+ if v: position += v.normalize() * wsad
@@ -6,11 +6,11 @@ from types import SimpleNamespace
6
6
  from pygame import Vector2
7
7
 
8
8
 
9
- def momentum_system(dt, eid, momentum, position):
9
+ def momentum_system(eid, momentum, position, *, dt):
10
10
  position += momentum * dt
11
11
 
12
12
 
13
- def border_system(dt, eid, border, position, momentum):
13
+ def border_system(eid, border, position, momentum, **kwargs):
14
14
  if position.x < 0:
15
15
  position.x = -position.x
16
16
  momentum.x = -momentum.x
@@ -25,7 +25,7 @@ def border_system(dt, eid, border, position, momentum):
25
25
  momentum.y = -momentum.y
26
26
 
27
27
 
28
- def background_system(dt, eid, background, position, surface):
28
+ def background_system(eid, background, position, surface, *, dt):
29
29
  def draw_one(angle, offset):
30
30
  v0 = Vector2(position)
31
31
  v1 = Vector2(2000, 0).rotate(angle)
@@ -81,7 +81,7 @@ def main():
81
81
 
82
82
  screen.fill('black')
83
83
 
84
- ecs.run_all_systems(dt)
84
+ ecs.run_all_systems(dt=dt)
85
85
 
86
86
  pygame.display.flip()
87
87
  clock.tick(FPS)
@@ -14,7 +14,7 @@ class Sprite(pygame.sprite.Sprite):
14
14
  self.rect = self.image.get_rect()
15
15
 
16
16
 
17
- def bounding_box_system(dt, eid, world, position, momentum):
17
+ def bounding_box_system(eid, world, position, momentum, **kwargs):
18
18
  if position.x < 0:
19
19
  position.x = -position.x
20
20
  momentum.x = -momentum.x
@@ -95,7 +95,7 @@ def main():
95
95
  screen.fill('black')
96
96
 
97
97
  group.update(dt)
98
- ecs.run_all_systems(dt)
98
+ ecs.run_all_systems(dt=dt)
99
99
 
100
100
  screen.blit(click, click_rect)
101
101
  group.draw(screen)
@@ -25,7 +25,7 @@ class Velocity:
25
25
  dy: float
26
26
 
27
27
 
28
- def motion_system(dt, eid, position, velocity):
28
+ def motion_system(eid, position, velocity, *, dt):
29
29
  # Note that assigning a new Vector to position would not make it back
30
30
  # into e.position. But since we don't change the position instance
31
31
  # itself, we're safe.
@@ -33,14 +33,14 @@ def motion_system(dt, eid, position, velocity):
33
33
  position.y += velocity.dy * dt
34
34
 
35
35
 
36
- def lifetime_system(dt, eid, lifetime):
36
+ def lifetime_system(eid, lifetime, *, dt):
37
37
  lifetime.time_left -= 1 * dt
38
38
  if lifetime.time_left <= 0:
39
39
  print(f'removing entity {eid}')
40
40
  ecs.remove_entity(eid)
41
41
 
42
42
 
43
- def render_system(dt, eid, printable):
43
+ def render_system(eid, printable):
44
44
  # the printable component contains no data at all and can be ignored,
45
45
  # but it will still be passed as a parameter.
46
46
  name, pos, velocity, lifetime = ecs.comps_of_eid(eid,
@@ -72,7 +72,7 @@ def main():
72
72
 
73
73
  ecs.run_system(1, render_system, Comps.PRINTABLE)
74
74
  for i in range(15):
75
- ecs.run_system(1, motion_system, Comps.POSITION, Comps.VELOCITY)
75
+ ecs.run_system(1, motion_system, Comps.POSITION, Comps.VELOCITY, dt=1)
76
76
  ecs.run_system(1, lifetime_system, Comps.LIFETIME)
77
77
  ecs.run_system(1, render_system, Comps.PRINTABLE)
78
78
 
@@ -105,8 +105,8 @@ def main():
105
105
 
106
106
  for i in range(15):
107
107
  # ecs.run_all_systems(1)
108
- ecs.run_domain(1, 'updates')
109
- ecs.run_domain(1, 'render')
108
+ ecs.run_domain('updates', dt=1)
109
+ ecs.run_domain('render')
110
110
 
111
111
  print(f'All entities: {ecs.eidx}')
112
112
  print(f'All components: {ecs.cidx}')
@@ -10,12 +10,12 @@ from pgcooldown import Cooldown
10
10
  from pygame import Vector2
11
11
 
12
12
 
13
- def dead_sprite_system(dt, eid, dead, sprite):
13
+ def dead_sprite_system(eid, dead, sprite):
14
14
  sprite.kill()
15
15
  ecs.remove_entity(eid)
16
16
 
17
17
 
18
- def lifetime_sprite_system(dt, eid, lifetime, sprite):
18
+ def lifetime_sprite_system(eid, lifetime, sprite):
19
19
  if lifetime.hot():
20
20
  return
21
21
  sprite.kill()
@@ -54,7 +54,7 @@ def create_shard(position, image, *groups):
54
54
  ecs.add_component(e, 'lifetime', Cooldown(random() * 0.25))
55
55
 
56
56
 
57
- def homing_missile_system(dt, eid, homing_missile, position, momentum):
57
+ def homing_missile_system(eid, homing_missile, position, momentum, *, dt):
58
58
  target_pos = ecs.comp_of_eid(homing_missile.target, 'position')
59
59
 
60
60
  target = target_pos
@@ -88,14 +88,14 @@ def homing_missile_system(dt, eid, homing_missile, position, momentum):
88
88
  momentum.rotate_ip(copysign(rotation, delta_phi))
89
89
 
90
90
 
91
- def fire_system(dt, eid, fire, position):
91
+ def fire_system(eid, fire, position):
92
92
  for i in range(fire.count):
93
93
  fire.fkt(pos=position)
94
94
 
95
95
  ecs.remove_component(eid, 'fire')
96
96
 
97
97
 
98
- def bounding_box_system(dt, eid, world, position, momentum):
98
+ def bounding_box_system(eid, world, position, momentum):
99
99
  if position.x < 0:
100
100
  position.x = -position.x
101
101
  momentum.x = -momentum.x
@@ -206,15 +206,15 @@ def main():
206
206
 
207
207
  screen.fill('black')
208
208
 
209
- ecs.run_system(dt, ecsc.mouse_system, 'mouse', 'position')
210
- ecs.run_system(dt, lifetime_sprite_system, 'lifetime', 'sprite')
211
- ecs.run_system(dt, dead_sprite_system, 'dead', 'sprite')
212
- ecs.run_system(dt, ecsc.dead_system, 'dead')
213
- ecs.run_system(dt, ecsc.momentum_system, 'momentum', 'position')
214
- ecs.run_system(dt, ecsc.sprite_system, 'sprite', 'position')
215
- ecs.run_system(dt, bounding_box_system, 'world', 'position', 'momentum')
216
- ecs.run_system(dt, homing_missile_system, 'homing_missile', 'position', 'momentum')
217
- ecs.run_system(dt, fire_system, 'fire', 'position')
209
+ ecs.run_system(ecsc.mouse_system, 'mouse', 'position')
210
+ ecs.run_system(lifetime_sprite_system, 'lifetime', 'sprite')
211
+ ecs.run_system(dead_sprite_system, 'dead', 'sprite')
212
+ ecs.run_system(ecsc.dead_system, 'dead')
213
+ ecs.run_system(ecsc.momentum_system, 'momentum', 'position', dt=dt)
214
+ ecs.run_system(ecsc.sprite_system, 'sprite', 'position')
215
+ ecs.run_system(bounding_box_system, 'world', 'position', 'momentum')
216
+ ecs.run_system(homing_missile_system, 'homing_missile', 'position', 'momentum', dt=dt)
217
+ ecs.run_system(fire_system, 'fire', 'position')
218
218
 
219
219
  screen.blit(click, click_rect)
220
220
  group.draw(screen)
@@ -10,7 +10,7 @@ from pgcooldown import Cooldown
10
10
  from pygame import Vector2
11
11
 
12
12
 
13
- def marquee_system(dt, eid, marquee, border, surface):
13
+ def marquee_system(eid, marquee, border, surface, *, dt):
14
14
  def bounce(point, momentum):
15
15
  point += momentum * dt
16
16
  if point.x < 0:
@@ -80,7 +80,7 @@ def main():
80
80
 
81
81
  screen.fill(BLACK)
82
82
 
83
- ecs.run_system(dt, marquee_system, 'marquee', 'border', 'surface')
83
+ ecs.run_system(marquee_system, 'marquee', 'border', 'surface', dt=dt)
84
84
 
85
85
  pygame.display.flip()
86
86
  clock.tick(FPS)
@@ -173,17 +173,18 @@ will be used. To run e.g. the `momentum_system`, put the following into the
173
173
  game loop:
174
174
 
175
175
  ``py
176
- ecs.run_system(dt, momentum_system, 'momentum', 'position')
176
+ ecs.run_system(momentum_system, 'momentum', 'position', dt=deltatime)
177
177
  ```
178
178
 
179
179
  When the game loop passes this call, `run_system` will find all entities that
180
180
  have both components `momentum` and `position` and pass these together with
181
- deltatime `dt` and the entity ID into the `momentum_system` function.
181
+ the entity ID into the `momentum_system` function. Remember, that kwargs can
182
+ be used to pass additional arguments from the main scope.
182
183
 
183
184
  Writing the `momentum_system` is easy:
184
185
 
185
186
  ```py
186
- def momentum_system(dt, eid, momentum, position):
187
+ def momentum_system(eid, momentum, position, *, dt):
187
188
  position += momentum * dt
188
189
  ```
189
190
 
@@ -199,7 +200,7 @@ passed in after the components. The following will be explained in the actual
199
200
  script later.
200
201
 
201
202
  ```py
202
- ecs.run_system(dt, deadzone_system, 'position', deadzone=WORLD)
203
+ ecs.run_system(deadzone_system, 'position', deadzone=WORLD)
203
204
  ```
204
205
 
205
206
  So the system is basically the `update(dt)` function in an OO driven game.
@@ -221,7 +222,7 @@ There are some alternatives still.
221
222
  program and call a single function in your game loop:
222
223
 
223
224
  ```py
224
- ecs.run_all_systems(dt)
225
+ ecs.run_all_systems(dt=dt)
225
226
  ```
226
227
 
227
228
  2. To give you a more fine grained control over what systems run together, the
@@ -241,7 +242,7 @@ method of your component. You still need that block of `run_system` or above
241
242
  shortcuts in your game loop though.
242
243
 
243
244
  ```py
244
- def call_update_system(dt, eid, component):
245
+ def call_update_system(eid, component, dt=dt):
245
246
  component.update(dt)
246
247
  ```
247
248
 
@@ -364,15 +365,15 @@ completeness:
364
365
  # addition.
365
366
  WORLD = SCREEN.scale_by(1.25)
366
367
 
367
- def momentum_system(dt, eid, momentum, position):
368
+ def momentum_system(eid, momentum, position, *, dt):
368
369
  """Add a delta time scaled momentum to the position."""
369
370
  position += momentum * dt
370
371
 
371
- def sprite_position_system(dt, eid, sprite, position):
372
+ def sprite_position_system(eid, sprite, position):
372
373
  """Apply the position to the rect of the sprite for the sprite group"""
373
374
  sprite.rect.center = position
374
375
 
375
- def deadzone_system(dt, eid, position, *, world):
376
+ def deadzone_system(eid, position, *, world):
376
377
  """Kill sprites that move off screen"""
377
378
  if world.collidepoint(position):
378
379
  return
@@ -396,7 +397,7 @@ to the entity instead of overwriting the component variable.
396
397
 
397
398
  .. code-block::
398
399
 
399
- def take_damage_system(dt, eid, health, damage):
400
+ def take_damage_system(eid, health, damage):
400
401
  ecs.add_component(eid, 'health', health - damage)
401
402
 
402
403
  For semantic reasons, tinyecs also provides `update_component`, but that's
@@ -430,9 +431,9 @@ The lines marked with `>` are additions to the game loop template all above.
430
431
  #### Running the systems
431
432
 
432
433
  ```py
433
- > ecs.run_system(dt, momentum_system, 'momentum', 'position')
434
- > ecs.run_system(dt, deadzone_system, 'position', world=WORLD)
435
- > ecs.run_system(dt, sprite_position_system, 'sprite', 'position')
434
+ > ecs.run_system(momentum_system, 'momentum', 'position', dt=dt)
435
+ > ecs.run_system(deadzone_system, 'position', world=WORLD)
436
+ > ecs.run_system(sprite_position_system, 'sprite', 'position')
436
437
 
437
438
  screen.fill('black')
438
439
 
@@ -499,17 +500,17 @@ def create_box_entity(position, sprite_group):
499
500
  ecs.add_component(e, 'sprite', DemoSprite(sprite_group))
500
501
 
501
502
 
502
- def momentum_system(dt, eid, momentum, position):
503
+ def momentum_system(eid, momentum, position, *, dt):
503
504
  """Add a delta time scaled momentum to the position."""
504
505
  position += momentum * dt
505
506
 
506
507
 
507
- def sprite_position_system(dt, eid, sprite, position):
508
+ def sprite_position_system(eid, sprite, position):
508
509
  """Apply the position to the rect of the sprite for the sprite group"""
509
510
  sprite.rect.center = position
510
511
 
511
512
 
512
- def deadzone_system(dt, eid, position, *, world):
513
+ def deadzone_system(eid, position, *, world):
513
514
  """Kill sprites that move off screen"""
514
515
  if world.collidepoint(position):
515
516
  return
@@ -538,9 +539,9 @@ while running:
538
539
  pos = pygame.mouse.get_pos()
539
540
  create_box_entity(pos, group)
540
541
 
541
- ecs.run_system(dt, momentum_system, 'momentum', 'position')
542
- ecs.run_system(dt, deadzone_system, 'position', world=WORLD)
543
- ecs.run_system(dt, sprite_position_system, 'sprite', 'position')
542
+ ecs.run_system(momentum_system, 'momentum', 'position', dt=dt)
543
+ ecs.run_system(deadzone_system, 'position', world=WORLD)
544
+ ecs.run_system(sprite_position_system, 'sprite', 'position')
544
545
 
545
546
  screen.fill('black')
546
547
 
@@ -590,12 +591,12 @@ import tinyecs.compsys as ecsc
590
591
 
591
592
  UNSTABLE! DON'T RELY ON THIS YET!
592
593
 
593
- `def dead_system(dt, eid, dead)`:
594
+ `def dead_system(eid, dead)`:
594
595
  Sometimes it is useful to not remove a sprite immediately from the system.
595
596
  Instead, you can add a component tagged e.g. 'dead', and later reap all
596
597
  entities marked with that tag.
597
598
 
598
- `def deadzone_system(dt, eid, world, position, *, container)`:
599
+ `def deadzone_system(eid, world, position, *, container)`:
599
600
 
600
601
  Basically the function created in this tutorial, with one addition.
601
602
 
@@ -608,25 +609,25 @@ import tinyecs.compsys as ecsc
608
609
 
609
610
  ecs.add_component(e, 'world', True)
610
611
 
611
- `def extension_system(dt, eid, extension)`:
612
+ `def extension_system(eid, extension)`:
612
613
  Will be removed. tinyecs installs pgcooldown as a requirement and that
613
614
  comes with the `CronD` class which does the same and more.
614
615
 
615
- `def force_system(dt, eid, force, momentum)`:
616
+ `def force_system(eid, force, momentum, *, dt)`:
616
617
  Applies (adds) a constant force to a momentum.
617
618
 
618
- `def lifetime_system(dt, eid, lifetime)`:
619
+ `def lifetime_system(eid, lifetime)`:
619
620
  Kills the entity once lifetime has run out. Expects `lifetime` to be an
620
621
  instance of `pgcooldown.Cooldown`
621
622
 
622
- `def momentum_system(dt, eid, momentum, position)`:
623
+ `def momentum_system(eid, momentum, position, *, dt)`:
623
624
  The same as we wrote in the tutorial above.
624
625
 
625
- `def mouse_system(dt, eid, mouse, position)`:
626
+ `def mouse_system(eid, mouse, position)`:
626
627
  Update a position component with the position of the mouse cursor.
627
628
 
628
- `def scale_system(dt, eid, scale, momentum)`:
629
- `def friction_system(dt, eid, scale, momentum)`:
629
+ `def scale_system(eid, scale, momentum, *, dt)`:
630
+ `def friction_system(eid, scale, momentum, *, dt)`:
630
631
  Apply friction to a momentum.
631
632
 
632
633
  In contrast to a force_system, which adds a directional vector to the
@@ -635,10 +636,10 @@ import tinyecs.compsys as ecsc
635
636
 
636
637
  `friction_system` is an alias to `scale_system`.
637
638
 
638
- `def sprite_system(dt, eid, sprite, position)`:
639
+ `def sprite_system(eid, sprite, position)`:
639
640
  The same as we wrote above, apply the position to `sprite.rect.center`.
640
641
 
641
- `def wsad_system(dt, eid, wsad, position)`:
642
+ `def wsad_system(eid, wsad, position)`:
642
643
  An example system to control a playear with the `wsad` keys.
643
644
  This was just a proof of concept, but I'm currently using it, so perhaps
644
645
  it will stay.
@@ -695,17 +696,17 @@ def create_box_entity(position, sprite_group):
695
696
  ecs.add_component(e, 'sprite', DemoSprite(sprite_group))
696
697
 
697
698
 
698
- def momentum_system(dt, eid, momentum, position):
699
+ def momentum_system(eid, momentum, position, *, dt):
699
700
  """Add a delta time scaled momentum to the position."""
700
701
  position += momentum * dt
701
702
 
702
703
 
703
- def sprite_position_system(dt, eid, sprite, position):
704
+ def sprite_position_system(eid, sprite, position):
704
705
  """Apply the position to the rect of the sprite for the sprite group"""
705
706
  sprite.rect.center = position
706
707
 
707
708
 
708
- def deadzone_system(dt, eid, position, *, world):
709
+ def deadzone_system(eid, position, *, world):
709
710
  """Kill sprites that move off screen"""
710
711
  if world.collidepoint(position):
711
712
  return
@@ -735,9 +736,9 @@ def main():
735
736
  pos = pygame.mouse.get_pos()
736
737
  create_box_entity(pos, group)
737
738
 
738
- ecs.run_system(dt, momentum_system, 'momentum', 'position')
739
- ecs.run_system(dt, deadzone_system, 'position', world=WORLD)
740
- ecs.run_system(dt, sprite_position_system, 'sprite', 'position')
739
+ ecs.run_system(momentum_system, 'momentum', 'position', dt=dt)
740
+ ecs.run_system(deadzone_system, 'position', world=WORLD)
741
+ ecs.run_system(sprite_position_system, 'sprite', 'position')
741
742
 
742
743
  screen.fill('black')
743
744
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinyecs
3
- Version: 0.3.6
3
+ Version: 0.4.0
4
4
  Summary: The teeniest, tiniest ECS system
5
5
  Author-email: Michael Lamertz <michael.lamertz@gmail.com>
6
6
  License-Expression: MIT
@@ -28,20 +28,20 @@ class Ping:
28
28
  ack: bool = False
29
29
 
30
30
 
31
- def wounding_system(dt, eid, health):
31
+ def wounding_system(eid, health, **kwargs):
32
32
  health.health -= 100
33
33
  return health.health
34
34
 
35
35
 
36
- def stats_system(dt, eid, name, health):
37
- return f'{dt=}, {eid=}, {name.name=}, {health.health=}'
36
+ def stats_system(eid, name, health, **kwargs):
37
+ return f'{eid=}, {name.name=}, {health.health=}'
38
38
 
39
39
 
40
- def ping_system(dt, eid, ping):
40
+ def ping_system(eid, ping):
41
41
  ping.ack = True
42
42
 
43
43
 
44
- def move_system(dt, eid, pos, velocity):
44
+ def move_system(eid, pos, velocity, *, dt, **kwargs):
45
45
  pos.x += velocity.dx * dt
46
46
  pos.y += velocity.dy * dt
47
47
  return (pos.x, pos.y)
@@ -161,17 +161,17 @@ def test_comps_of_eid():
161
161
 
162
162
  def test_run_system():
163
163
  e1, e2 = setup()
164
- ecs.run_system(1, wounding_system, 'health')
164
+ ecs.run_system(wounding_system, 'health')
165
165
  assert ecs.eidx[e2]['health'].health == 900
166
166
  assert ecs.cidx['health'][e2].health == 900
167
167
 
168
168
  worked = False
169
169
 
170
- def sys_no_args(dt, eid):
170
+ def sys_no_args(eid):
171
171
  nonlocal worked
172
172
  worked = True
173
173
 
174
- ecs.run_system(0, sys_no_args)
174
+ ecs.run_system(sys_no_args)
175
175
  assert worked
176
176
 
177
177
 
@@ -181,11 +181,11 @@ def test_run_bulk_system():
181
181
  eid = ecs.create_entity()
182
182
  ecs.add_component(eid, 'number', i)
183
183
 
184
- def bulk_runner(dt, call_list):
184
+ def bulk_runner(call_list):
185
185
  assert len(call_list) == 10
186
186
  return sum([i for eid, i in call_list])
187
187
 
188
- assert ecs.run_bulk_system(0, bulk_runner, 'number') == 45
188
+ assert ecs.run_bulk_system(bulk_runner, 'number') == 45
189
189
 
190
190
 
191
191
  def test_run_all_systems():
@@ -194,7 +194,7 @@ def test_run_all_systems():
194
194
  ecs.add_system(wounding_system, 'health')
195
195
  ecs.add_component(e2, 'pos', SimpleNamespace(x=100, y=200))
196
196
  ecs.add_component(e2, 'velocity', SimpleNamespace(dx=5, dy=7))
197
- res = ecs.run_all_systems(1)
197
+ res = ecs.run_all_systems(dt=1)
198
198
 
199
199
  assert ecs.eidx[e2]['pos'] == SimpleNamespace(x=105, y=207)
200
200
  assert res[move_system][e2] == (105, 207)
@@ -274,7 +274,7 @@ def test_reset():
274
274
 
275
275
 
276
276
  def test_kill_from_system():
277
- def kill_system(dt, eid, kill):
277
+ def kill_system(eid, kill):
278
278
  ecs.remove_entity(eid)
279
279
 
280
280
  ecs.reset()
@@ -286,7 +286,7 @@ def test_kill_from_system():
286
286
  ecs.add_component(e, 'kill', True)
287
287
 
288
288
  assert len(ecs.eidx) == 10
289
- ecs.run_system(1, kill_system, 'kill')
289
+ ecs.run_system(kill_system, 'kill')
290
290
  assert len(ecs.eidx) == 5
291
291
 
292
292
 
@@ -318,11 +318,11 @@ def test_run_domain():
318
318
  e = ecs.create_entity()
319
319
  ecs.add_component(e, 'ping', Ping(False))
320
320
 
321
- res = ecs.run_domain(1, 'infra')
321
+ res = ecs.run_domain('infra')
322
322
  assert ping_system in res
323
323
  assert e in res[ping_system]
324
324
 
325
- res = ecs.run_domain(1, 'non-existent')
325
+ res = ecs.run_domain('non-existent')
326
326
  assert res == {}
327
327
 
328
328
 
@@ -417,12 +417,12 @@ def test_add_to_archetype():
417
417
  # Also tests remove_from_archetype
418
418
  setup()
419
419
 
420
- def test_system(dt, eid, test):
420
+ def test_system(eid, test):
421
421
  pass
422
422
 
423
423
  e = ecs.create_entity()
424
424
  ecs.add_component(e, 'test', True)
425
- ecs.run_system(0, test_system, 'test')
425
+ ecs.run_system(test_system, 'test')
426
426
  assert e in ecs.archetype[('test',)]
427
427
 
428
428
  ecs.remove_component(e, 'test')
@@ -470,10 +470,10 @@ def test_property_get_entities():
470
470
  def test_property_run_system():
471
471
  setup_property_tests()
472
472
 
473
- def flag_system(dt, eid, comp1, comp2):
473
+ def flag_system(eid, comp1, comp2):
474
474
  ecs.add_component(eid, 'flag', True)
475
475
 
476
- ecs.run_system(0, flag_system, 'comp-1', 'comp-2', has_properties={'is-even'})
476
+ ecs.run_system(flag_system, 'comp-1', 'comp-2', has_properties={'is-even'})
477
477
  assert len(ecs.eids_by_cids('flag')) == 5
478
478
 
479
479
 
File without changes
File without changes
File without changes
File without changes