Arepy
An ECS python game engine using raylib.
Install / Use
/learn @Scr44gr/ArepyREADME
Arepy is a lightweight and expressive ECS game engine built in Python, designed to make building 2D games simple, fast, and enjoyable. It provides a clean API, a modern architecture, and first-class integration with Raylib and ImGui.
Features
- High-performance ECS architecture optimized for games
- Raylib integration for hardware-accelerated 2D graphics
- ImGui debugging overlay with real-time tools
- Memory-efficient component pools
- Flexible query system with
With/Withoutfilters - Simple and intuitive API design
- Fluent entity builder system
Installation
From PyPI
pip install arepy
Development Installation
git clone https://github.com/Scr44gr/arepy.git
cd arepy
pip install -e ".[testing]"
Quick Start
Basic Example – Moving Square
from arepy import ArepyEngine, Color, Rect, Renderer2D, SystemPipeline
from arepy.bundle.components import RigidBody2D, Transform
from arepy.ecs import Entities, Query, With
from arepy.math import Vec2
# Colors
WHITE = Color(255, 255, 255, 255)
RED = Color(255, 0, 0, 255)
def movement_system(query: Query[Entities, With[Transform, RigidBody2D]], renderer: Renderer2D):
delta_time = renderer.get_delta_time()
for transform, rigidbody in query.iter_components(Transform, RigidBody2D):
velocity = rigidbody.velocity
transform.position.x += velocity.x * delta_time
transform.position.y += velocity.y * delta_time
def render_system(query: Query[Entities, With[Transform]], renderer: Renderer2D):
renderer.start_frame()
renderer.clear(color=WHITE)
for transform, in query.iter_components(Transform):
renderer.draw_rectangle(
Rect(transform.position.x, transform.position.y, 50, 50),
color=RED
)
renderer.end_frame()
if __name__ == "__main__":
game = ArepyEngine(title="Arepy Example")
world = game.create_world("main_world")
entity = (world.create_entity()
.with_component(Transform(position=Vec2(0, 0)))
.with_component(RigidBody2D(velocity=Vec2(50, 10)))
.build())
world.add_system(SystemPipeline.UPDATE, movement_system)
world.add_system(SystemPipeline.RENDER, render_system)
game.set_current_world("main_world")
game.run()
Core Concepts
Entities
Lightweight identifiers that represent objects in the game world:
entity = world.create_entity()
player = (world.create_entity()
.with_component(Transform(position=Vec2(100, 100)))
.with_component(PlayerController())
.build())
empty_entity = world.create_entity().build()
Components
Pure data containers attached to entities:
from arepy.ecs import Component
class Health(Component):
def __init__(self, value: int = 100):
super().__init__()
self.value = value
self.max_value = value
class Weapon(Component):
def __init__(self, damage: int = 10, range: float = 100.0):
super().__init__()
self.damage = damage
self.range = range
Systems
Systems implement game logic:
def damage_system(query: Query[Entity, With[Health, Weapon]]):
for entity, health, weapon in query.iter_entities_components(Health, Weapon):
if health.value <= 0:
entity.kill()
Queries
Filter entities based on their components:
Query[Entity, With[Transform, Velocity]]
Query[Entity, Without[Dead]]
Query[Entity, tuple[With[Transform, Velocity], Without[Frozen]]]
Use iter_components(...) when you only need component data in the hot path:
def movement_system(
query: Query[Entity, tuple[With[Transform, Velocity], Without[Frozen]]],
renderer: Renderer2D,
) -> None:
delta_time = renderer.get_delta_time()
for transform, velocity in query.iter_components(Transform, Velocity):
transform.position.x += velocity.x * delta_time
transform.position.y += velocity.y * delta_time
Use Without[...] to exclude entities that should not be processed:
def active_projectiles_system(
query: Query[Entity, tuple[With[Transform, Velocity], Without[Destroyed]]],
) -> None:
for transform, velocity in query.iter_components(Transform, Velocity):
transform.position.x += velocity.x
transform.position.y += velocity.y
Testing
pytest # Run all tests
pytest --cov=arepy # Coverage report
pytest tests/test_registry.py -v
Contributing
We welcome contributions. Refer to the Contributing Guide.
- Fork the repository
- Create a feature branch
- Implement your changes and tests
- Ensure tests pass
- Commit and push
- Open a Pull Request
Requirements
- Python 3.11+
- Raylib 5.5.0+
- Bitarray 3.4.2+
Roadmap
- [x] Advanced query system
- [ ] Scene management
- [ ] Asset pipeline improvements
- [ ] Physics integration
- [ ] Audio system
- [ ] Networking support
- [ ] Visual editor
📄 License
This project is licensed under the MIT License – see the LICENSE file for details.
🙏 Acknowledgments
Made with ❤️ by Abrahan Gil
