RECS: A Reactive ECS Framework for High-Performance Simulations in Julia

If you’re interested, I alredy updated the syntax and optimized performances. Here is now the form of a typical run!:

using RECS

# This will create a new component
# And set boilerplates for us
# The constructor is just the name passed here plus the suffix "Component"
@component Health begin
    hp::Int
end

@component Transform begin
    x::Float32
    y::Float32
end

@component Physic begin
    velocity::Float32
end

# We create a system
@system PhysicSystem begin
    delta::Float32
end
@system RenderSystem

# The system's internal logic
# Each system should have one
function RECS.run!(world, sys::PhysicSystem, data)

    E = world[sys] # First we get some sort of wrapper for ease of use
    indices::Vector{Int} = data.value # The indices of the matching entities
    L = length(indices)

    # Next we get the components
    transforms = E.Transform
    physics = E.Physic

    # We will just work on the x axis
    # Type unstability has been fixed, no more need to specify the types
    x_pos = transforms.x
    velo = physics.velocity
    dt::Float32 = sys.delta

    @inbounds for i in indices
        x_pos[i] += velo[i]*dt
    end
end

function RECS.run!(_, ::RenderSystem, pos) # Here `pos` is the transform_data we returned in the PhysicSystem `run!`
    for i in eachindex(pos)
        t = pos[i]
        println("Rendering entity at position ($(t.x), $(t.y))")
    end
end

ecs = ECSManager()

physic_sys = PhysicSystem(1/60)
render_sys = RenderSystem()

subscribe!(ecs, physic_sys, (TransformComponent, PhysicComponent))
listen_to(physic_sys,render_sys)

# Creating 3 entity
# We pass as keywork argument the component of the entity
e1 = create_entity!(ecs; Health = HealthComponent(100), Transform = TransformComponent(1.0,2.0))
e2 = create_entity!(ecs; Health = HealthComponent(50), Transform = TransformComponent(-5.0,0.0), Physic = PhysicComponent(1.0))
e3 = create_entity!(ecs; Health = HealthComponent(50), Transform = TransformComponent(-5.0,0.0), Physic = PhysicComponent(1.0))

# We launch the system. Internally, it's creating an asynchronous task
run_system!(physic_sys)
run_system!(render_sys)

N = 3

for i in 1:N
    println("FRAME $i")

    # We dispatch data and each system will execute his `run!` function
    dispatch_data(ecs)
    yield()
    sleep(0.016)
end
3 Likes