Skip to content

Moeblack/ECSComb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ECSComb

ECSComb is an Entity-Component-System framework for Elixir built on BEAM and ETS. It focuses on a small runtime surface:

  • ECSComb.World owns entity lifecycle and component storage.
  • ECSComb.Query provides runtime all / any / none queries.
  • ECSComb.System defines the scheduler contract.
  • ECSComb.Scheduler groups non-conflicting systems into parallel layers.
  • ECSComb.TickLoop drives the world at a fixed tick rate.

Design Highlights

  • ETS-backed storage with public named tables and direct read access
  • Entity IDs use {index, generation} to reject stale references
  • Components are plain structs with no macros or registration
  • System ordering is inferred from declared read/write sets
  • Runtime add/remove of systems is supported between ticks

Quick Example

defmodule Demo.Position do
  defstruct [:x, :y]
end

defmodule Demo.Velocity do
  defstruct [:dx, :dy]
end

defmodule Demo.MoveSystem do
  @behaviour ECSComb.System

  alias ECSComb.Query
  alias ECSComb.World
  alias Demo.Position
  alias Demo.Velocity

  @impl true
  def access do
    %{reads: [Position, Velocity], writes: [Position]}
  end

  @impl true
  def run(world) do
    Query.select(world, all: [Position, Velocity])
    |> Enum.each(fn entity_id ->
      {:ok, %Position{x: x, y: y}} = World.get(world, entity_id, Position)
      {:ok, %Velocity{dx: dx, dy: dy}} = World.get(world, entity_id, Velocity)
      :ok = World.put(world, entity_id, %Position{x: x + dx, y: y + dy})
    end)

    :ok
  end
end

{:ok, world} = ECSComb.World.start_link()
{:ok, entity_id} = ECSComb.World.spawn_entity(world)

:ok = ECSComb.World.put(world, entity_id, %Demo.Position{x: 0, y: 0})
:ok = ECSComb.World.put(world, entity_id, %Demo.Velocity{dx: 1, dy: 1})

scheduler =
  ECSComb.Scheduler.new()
  |> ECSComb.Scheduler.add_system(Demo.MoveSystem)
  |> ECSComb.Scheduler.build_graph()

{:ok, tick_loop} =
  ECSComb.TickLoop.start_link(
    world: world,
    scheduler: scheduler,
    tick_rate: 20
  )

Process.sleep(120)
{:ok, %Demo.Position{x: x, y: y}} = ECSComb.World.get(world, entity_id, Demo.Position)
IO.inspect({x, y}, label: "updated position")

:ok = ECSComb.TickLoop.stop(tick_loop)

Test Coverage

The project includes tests for:

  • Entity lifecycle and component CRUD
  • Transactions, name indexes, and concurrent reads/writes
  • Query filtering and indexed lookup correctness
  • Behaviour validation for systems
  • Scheduler conflict detection, graph layering, and parallel execution
  • Tick timing, cron callbacks, and end-to-end runtime integration

Status

Implemented and covered by mix test.

About

A BEAM/ETS Entity-Component-System framework with fixed ticks and parallel system scheduling

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages