Skip to main content

An ECS python game engine with Raylib

Project description

image

CI Docs Upload Python Package codecov PyPI package Python versions License: MIT

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 / Without filters
  • 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()

Demo


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.

  1. Fork the repository
  2. Create a feature branch
  3. Implement your changes and tests
  4. Ensure tests pass
  5. Commit and push
  6. Open a Pull Request

Requirements

  • Python 3.11+
  • Raylib 5.5.0+
  • Bitarray 3.4.2+

Roadmap

  • 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

arepy-0.5.1.tar.gz (69.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

arepy-0.5.1-py3-none-any.whl (72.1 kB view details)

Uploaded Python 3

File details

Details for the file arepy-0.5.1.tar.gz.

File metadata

  • Download URL: arepy-0.5.1.tar.gz
  • Upload date:
  • Size: 69.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for arepy-0.5.1.tar.gz
Algorithm Hash digest
SHA256 cfdf445503d5a4e61d50647444d6813f63854ce0c547328832766958be2347e3
MD5 a207a7b143fe2a20463c64ae5d772fb2
BLAKE2b-256 c76f27e932a59f67d0ef6c5364f9ef0f81f3694f3140dafb00deb2b616121f28

See more details on using hashes here.

Provenance

The following attestation bundles were made for arepy-0.5.1.tar.gz:

Publisher: python-publish.yml on Scr44gr/arepy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file arepy-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: arepy-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 72.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for arepy-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cba4c115aaf1711d2f6e9563a33a682fcbdf096b5057163a80764f09ea18d209
MD5 6c9afb67ea7c65a6b0858a68fde5c3ea
BLAKE2b-256 4a5f1290f165861d80e25321951b7ec0ad384244aebce17cb2b7b6224eddec60

See more details on using hashes here.

Provenance

The following attestation bundles were made for arepy-0.5.1-py3-none-any.whl:

Publisher: python-publish.yml on Scr44gr/arepy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page