Moving Circles#

https://github.com/lukasturcani/xecs/blob/master/examples/moving_circles/moving_circles.py

import numpy as np
import xecs as xx
from xecs_pygame import Circle, PyGamePlugin, Rectangle


class Velocity(xx.Component):
    value: xx.Vec2


class Params(xx.Resource):
    num_circles: int
    max_position: float
    max_velocity: float
    generator: np.random.Generator
    time_step: xx.Duration


def main() -> None:
    app = xx.RealTimeApp(num_entities=30)
    app.add_plugin(PyGamePlugin())
    num_circles = 20
    params = Params(
        num_circles=num_circles,
        max_position=400,
        max_velocity=50,
        generator=np.random.default_rng(9),
        time_step=xx.Duration.from_millis(16),
    )
    app.add_resource(params)
    app.add_startup_system(spawn_circles)
    app.add_system(move_circles, params.time_step)
    app.add_pool(xx.Transform2.create_pool(num_circles + 1))
    app.add_pool(Velocity.create_pool(num_circles))
    app.add_pool(Circle.create_pool(num_circles))
    app.add_pool(Rectangle.create_pool(1))
    app.run()


def spawn_circles(
    params: Params,
    world: xx.World,
    commands: xx.Commands,
) -> None:
    transformi, velocityi, _ = commands.spawn(
        components=(xx.Transform2, Velocity, Circle),
        num=params.num_circles,
    )
    world.get_view(xx.Transform2, transformi).fill_random(
        params.generator,
        max_translation=(params.max_position, params.max_position),
    )
    world.get_view(Velocity, velocityi).value.fill(
        params.generator.random((2, params.num_circles), dtype=np.float32)
        * params.max_velocity
    )

    _, rectanglei = commands.spawn(
        components=(xx.Transform2, Rectangle),
        num=1,
    )
    rectangle = world.get_view(Rectangle, rectanglei)
    rectangle.length_x.fill(params.max_position)
    rectangle.length_y.fill(params.max_position)
    rectangle.width.fill(1)


def move_circles(
    params: Params,
    query: xx.Query[tuple[xx.Transform2, Velocity]],
) -> None:
    (transform, velocity) = query.result()
    transform.translation += velocity.value * (
        params.time_step.as_nanos() / 1e9
    )
    velocity.value.x[transform.translation.x > params.max_position] *= -1
    velocity.value.y[transform.translation.y > params.max_position] *= -1
    velocity.value.x[transform.translation.x < 0] *= -1
    velocity.value.y[transform.translation.y < 0] *= -1


if __name__ == "__main__":
    main()