Queries¶
Queries are the main way systems select entities.
Filter syntax¶
The current implementation supports three forms:
Query[Entity, With[Transform, RigidBody2D]]
Query[Entity, Without[Sprite]]
Query[Entity, tuple[With[Transform], Without[Sprite]]]
The shape is always:
EntityTypeis usuallyEntityFilterTypeisWith[...],Without[...], or atuple[...]that combines both
You do not construct a Query(...) object by hand. Instead, you pass it as a type annotation on a system parameter:
At system registration time, the registry inspects these annotations and builds internal signatures for required and excluded components.
Iteration options¶
Iterate entities¶
Iterate component tuples¶
The component types you pass to iter_components(...) should match the With[...] part of the query annotation.
Iterate entities plus components¶
Here the first returned value is the Entity, and the rest follow the component types in the same order you pass them.
Preferred hot-path style¶
For gameplay loops, prefer iter_components(...) or iter_entities_components(...) over repeated entity.get_component(...) calls. The bundled movement and render systems already follow this pattern.
Ordering¶
Query iteration is deterministic: entities are yielded ordered by entity id. That makes gameplay logic, replayability, and debugging easier to reason about.
Matching rules¶
A query matches an entity when:
- all required
With[...]components are present - none of the
Without[...]components are present
Example¶
def movement_system(
query: Query[Entity, tuple[With[Transform, RigidBody2D], Without[Frozen]]],
renderer: Renderer2D,
) -> None:
delta_time = renderer.get_delta_time()
for transform, rigidbody in query.iter_components(Transform, RigidBody2D):
transform.position.x += rigidbody.velocity.x * delta_time
transform.position.y += rigidbody.velocity.y * delta_time