SkillAgentSearch skills...

Arepy

An ECS python game engine using raylib.

Install / Use

/learn @Scr44gr/Arepy
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <img width="450" alt="image" src="https://github.com/user-attachments/assets/f597ffbc-e4b6-4610-bc00-eaa4973e7fcf" alt="Arepy Logo"/> </p>

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

  • [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

View on GitHub
GitHub Stars13
CategoryDevelopment
Updated2d ago
Forks1

Languages

Python

Security Score

95/100

Audited on Mar 29, 2026

No findings