KEG
KEG is an Engine for Games. More specifically, it is a small, typed, archetype-based ECS for Python 3.12 and newer.
KEG does not require components to inherit from anything. A dataclass will do. So will any other arbitrary object, although please exercise some judgment.
from dataclasses import dataclass
from keg import World
@dataclass(slots=True)
class Position:
x: float
y: float
@dataclass(slots=True)
class Velocity:
x: float
y: float
world = World()
player = world.spawn(
Position(10.0, 20.0),
Velocity(4.0, -2.0),
)
for entities, positions, velocities in world.query(Position, Velocity):
for row in range(len(entities)):
position = positions[row]
velocity = velocities[row]
position.x += velocity.x
position.y += velocity.y
Queries return columns
A query yields one batch per matching archetype. Each batch contains the entity IDs followed by the requested component columns, in request order:
for entities, positions, velocities in world.query(Position, Velocity):
...
The sequences in a batch are aligned: entities[row], positions[row], and
velocities[row] all belong to the same entity. They expose KEG's underlying
column storage and should be treated as read-only. The component objects remain
yours to mutate.
This avoids manufacturing a tuple for every entity merely to take it apart again in a hot loop. Queries are precisely typed for up to sixteen component types.
An entity may contain at most one component of each exact runtime type. Component inheritance has no special meaning to KEG.
Structural changes
Spawning and despawning entities, or adding and removing components, can move entities between archetypes. KEG applies those operations immediately during ordinary use and defers them automatically while a query is being iterated. The pending changes are committed after the last active query finishes.
You can request the same behaviour explicitly when applying a batch of changes:
with world.defer_structural_changes():
projectile = world.spawn(Position(0.0, 0.0))
world.add_component(projectile, Velocity(12.0, 3.0))
Pending entities and components remain accessible through get_component()
and set_component(), while queries continue to see the committed archetype
layout until the changes are flushed.
Queries release their structural guard when exhausted or explicitly closed. If
you retain a query iterator and stop consuming it early, whether through
break or an exception in surrounding code, call its close() method so
pending structural work can be committed. Do not rely on garbage collection.
Installation
KEG currently has no runtime dependencies:
python -m pip install keg-engine
Example
The bouncing-balls example uses Kivy to exercise a small position and velocity system in a real update loop:
git clone https://github.com/Cheaterman/KEG.git
cd KEG
python -m pip install -e '.[examples]'
python examples/bouncing_balls/main.py
License
KEG is distributed under the MIT license.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file keg_engine-0.2.1.tar.gz.
File metadata
- Download URL: keg_engine-0.2.1.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
848a6c5126ec1e7acfe720ba4649778c4c428c44defe2c54e922b54ad10d86db
|
|
| MD5 |
fce5a9116b703b07af382c7e74829a2d
|
|
| BLAKE2b-256 |
b9ab62ee85a9897aa21a933de874637ed2fc69f125838e4991c89d61704893b0
|
File details
Details for the file keg_engine-0.2.1-py3-none-any.whl.
File metadata
- Download URL: keg_engine-0.2.1-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed037ebaf90b7053b07decab6e6e646926868d56d7060df917e085a1f1ae0426
|
|
| MD5 |
7c7b1b19d03d0fd19e4d5b297a020fd4
|
|
| BLAKE2b-256 |
e347a6edb78ff879ec8b33f51f0ae490f362dc5cc6ac891eb850dfa00e0e8acf
|