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.3.tar.gz (69.0 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.3-py3-none-any.whl (71.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for arepy-0.5.3.tar.gz
Algorithm Hash digest
SHA256 7c4c69e7835469c481dc44daef5dfc7fce22fccc33bc8a1daa8c0f3886bdf673
MD5 b197c1e84ed976e3bea7cac4be119628
BLAKE2b-256 d61c873169c6ba117114337aeb24d6226de00253936f2b88ba7673555be7cf61

See more details on using hashes here.

Provenance

The following attestation bundles were made for arepy-0.5.3.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.3-py3-none-any.whl.

File metadata

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

File hashes

Hashes for arepy-0.5.3-py3-none-any.whl
Algorithm Hash digest
SHA256 15f86c12e3fe24e42cedb33631144831916284fbe27f43e8f1fc57ef515b347c
MD5 f62f8f8cf7aa868c06c98a6b98c76804
BLAKE2b-256 2dcd9708d87a83e62704e008d3e84f02808e3db006293f3e091b8e8678af7dce

See more details on using hashes here.

Provenance

The following attestation bundles were made for arepy-0.5.3-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