Pico Libraries
Macros | Typedefs | Functions
pico_ecs.h File Reference

A pure and simple ECS written in C99. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Include dependency graph for pico_ecs.h:

Go to the source code of this file.

Macros

#define ECS_NULL   ((ecs_id_t)-1)
 NULL/invalid/undefined value. More...
 
#define ECS_DT_TYPE   double
 Determine delta-time type. More...
 

Typedefs

typedef struct ecs_s ecs_t
 ECS context. More...
 
typedef uint32_t ecs_id_t
 ID used for entity and components. More...
 
typedef int8_t ecs_ret_t
 Return code for update callback and calling functions. More...
 
typedef ECS_DT_TYPE ecs_dt_t
 
typedef void(* ecs_constructor_fn) (ecs_t *ecs, ecs_id_t entity_id, void *ptr, void *args)
 Called when a component is created (via ecs_add) More...
 
typedef void(* ecs_destructor_fn) (ecs_t *ecs, ecs_id_t entity_id, void *ptr)
 Called when a component is destroyed (via ecs_remove or ecs_destroy) More...
 
typedef ecs_ret_t(* ecs_system_fn) (ecs_t *ecs, ecs_id_t *entities, int entity_count, ecs_dt_t dt, void *udata)
 System update callback. More...
 
typedef void(* ecs_added_fn) (ecs_t *ecs, ecs_id_t entity_id, void *udata)
 Called when an entity is added to a system. More...
 
typedef void(* ecs_removed_fn) (ecs_t *ecs, ecs_id_t entity_id, void *udata)
 Called when an entity is removed from a system. More...
 

Functions

ecs_tecs_new (size_t entity_count, void *mem_ctx)
 Creates an ECS instance. More...
 
void ecs_free (ecs_t *ecs)
 Destroys an ECS instance. More...
 
void ecs_reset (ecs_t *ecs)
 Removes all entities from the ECS, preserving systems and components. More...
 
ecs_id_t ecs_register_component (ecs_t *ecs, size_t size, ecs_constructor_fn constructor, ecs_destructor_fn destructor)
 Registers a component. More...
 
ecs_id_t ecs_register_system (ecs_t *ecs, ecs_system_fn system_cb, ecs_added_fn add_cb, ecs_removed_fn remove_cb, void *udata)
 Registers a system. More...
 
void ecs_require_component (ecs_t *ecs, ecs_id_t sys_id, ecs_id_t comp_id)
 Determines which components are available to the specified system. More...
 
void ecs_exclude_component (ecs_t *ecs, ecs_id_t sys_id, ecs_id_t comp_id)
 Excludes entities having the specified component from being added to the target system. More...
 
void ecs_enable_system (ecs_t *ecs, ecs_id_t sys_id)
 Enables a system. More...
 
void ecs_disable_system (ecs_t *ecs, ecs_id_t sys_id)
 Disables a system. More...
 
ecs_id_t ecs_create (ecs_t *ecs)
 Creates an entity. More...
 
bool ecs_is_ready (ecs_t *ecs, ecs_id_t entity_id)
 Returns true if the entity is currently active. More...
 
void ecs_destroy (ecs_t *ecs, ecs_id_t entity_id)
 Destroys an entity. More...
 
bool ecs_has (ecs_t *ecs, ecs_id_t entity_id, ecs_id_t comp_id)
 Test if entity has the specified component. More...
 
void * ecs_add (ecs_t *ecs, ecs_id_t entity_id, ecs_id_t comp_id, void *args)
 Adds a component instance to an entity. More...
 
void * ecs_get (ecs_t *ecs, ecs_id_t entity_id, ecs_id_t comp_id)
 Gets a component instance associated with an entity. More...
 
void ecs_remove (ecs_t *ecs, ecs_id_t entity_id, ecs_id_t comp_id)
 Removes a component instance from an entity. More...
 
void ecs_queue_destroy (ecs_t *ecs, ecs_id_t entity_id)
 Queues an entity for destruction at the end of system execution. More...
 
void ecs_queue_remove (ecs_t *ecs, ecs_id_t entity_id, ecs_id_t comp_id)
 Queues a component for removable. More...
 
ecs_ret_t ecs_update_system (ecs_t *ecs, ecs_id_t sys_id, ecs_dt_t dt)
 Update an individual system. More...
 
ecs_ret_t ecs_update_systems (ecs_t *ecs, ecs_dt_t dt)
 Updates all systems. More...
 

Detailed Description

A pure and simple ECS written in C99.


Licensing information at end of header

Features:

Summary:

This library implements an ECS (Entity-Component-System). Entities (sometimes called game objects) are defined by their components. For example, an entity might have position, sprite, and physics components. Systems operate on the components of entities that match the system's requirements. Entities are matched to systems based upon which components they have and also the system's matching crieria.

In the above example, a sprite renderer system would match entities having poition and sprite components. The system would send the appropriate geometry and texture ID to the game's graphics API.

Traditional game engines tightly couple state with logic. For example, in C++ a game object typically has its own update method that operates on that state. They also usually rely heavily on inheritance.

If the state specified by the class changes this could ripple through the class, and perhaps subclasses as well. It could well be that the class no longer belongs in the existing class hierarchy forcing even more revisions. It could even be true that a class doesn't neatly fit into the inheritance tree at all.

An ECS solves these problems while also granting more flexibility in general. In an ECS there is a clear separation between data (components) and logic (systems), which makes it possible to build complex simulations with fewer assumptions about how that data will be used. In an ECS it effortless to change functionality, by either adding or removing components from entities, and/or by changing system requirements. Adding new logic is also simple as well, just register a new system!

Please see the examples and unit tests for more details.

Usage:

To use this library in your project, add the following

#define PICO_ECS_IMPLEMENTATION #include "pico_ecs.h"

to a source file (once), then simply include the header normally.

Constants:

Must be defined before PICO_ECS_IMPLEMENTATION

Todo:

Macro Definition Documentation

◆ ECS_NULL

#define ECS_NULL   ((ecs_id_t)-1)

NULL/invalid/undefined value.

◆ ECS_DT_TYPE

#define ECS_DT_TYPE   double

Determine delta-time type.

Typedef Documentation

◆ ecs_t

typedef struct ecs_s ecs_t

ECS context.

◆ ecs_id_t

typedef uint32_t ecs_id_t

ID used for entity and components.

◆ ecs_ret_t

typedef int8_t ecs_ret_t

Return code for update callback and calling functions.

◆ ecs_dt_t

◆ ecs_constructor_fn

typedef void(* ecs_constructor_fn) (ecs_t *ecs, ecs_id_t entity_id, void *ptr, void *args)

Called when a component is created (via ecs_add)

Parameters
ecsThe ECS instance
entity_idThe entity being constructed
ptrThe pointer to the component
udataThe user data passed to the callback

◆ ecs_destructor_fn

typedef void(* ecs_destructor_fn) (ecs_t *ecs, ecs_id_t entity_id, void *ptr)

Called when a component is destroyed (via ecs_remove or ecs_destroy)

Parameters
ecsThe ECS instance
entity_idThe entity being destoryed
ptrThe pointer to the component
udataThe user data passed to the callback

◆ ecs_system_fn

typedef ecs_ret_t(* ecs_system_fn) (ecs_t *ecs, ecs_id_t *entities, int entity_count, ecs_dt_t dt, void *udata)

System update callback.

Systems implement the core logic of an ECS by manipulating entities and components.

Parameters
ecsThe ECS instance
entitiesAn array of entity IDs managed by the system
entity_countThe number of entities in the array
dtThe time delta
udataThe user data associated with the system

◆ ecs_added_fn

typedef void(* ecs_added_fn) (ecs_t *ecs, ecs_id_t entity_id, void *udata)

Called when an entity is added to a system.

Parameters
ecsThe ECS instance
entity_idThe enitty being added
udataThe user data passed to the callback

◆ ecs_removed_fn

typedef void(* ecs_removed_fn) (ecs_t *ecs, ecs_id_t entity_id, void *udata)

Called when an entity is removed from a system.

Parameters
ecsThe ECS instance
entity_idThe enitty being removed
udataThe user data passed to the callback

Function Documentation

◆ ecs_new()

ecs_t* ecs_new ( size_t  entity_count,
void *  mem_ctx 
)

Creates an ECS instance.

Parameters
entity_countThe inital number of pooled entities
mem_ctxThe Context for a custom allocator
Returns
An ECS instance or NULL if out of memory

◆ ecs_free()

void ecs_free ( ecs_t ecs)

Destroys an ECS instance.

Parameters
ecsThe ECS instance

◆ ecs_reset()

void ecs_reset ( ecs_t ecs)

Removes all entities from the ECS, preserving systems and components.

◆ ecs_register_component()

ecs_id_t ecs_register_component ( ecs_t ecs,
size_t  size,
ecs_constructor_fn  constructor,
ecs_destructor_fn  destructor 
)

Registers a component.

Registers a component with the specfied size in bytes. Components define the game state (usually contained within structs) and are manipulated by systems.

Parameters
ecsThe ECS instance
sizeThe number of bytes to allocate for each component instance
constructorCalled when a component is created (disabled if NULL)
destructorCalled when a component is destroyed (disabled if NULL)
udataData passed to callbacks (can be NULL)
Returns
The component's ID

◆ ecs_register_system()

ecs_id_t ecs_register_system ( ecs_t ecs,
ecs_system_fn  system_cb,
ecs_added_fn  add_cb,
ecs_removed_fn  remove_cb,
void *  udata 
)

Registers a system.

Registers a system with the specified parameters. Systems contain the core logic of a game by manipulating game state as defined by components.

Parameters
ecsThe ECS instance
system_cbCallback that is fired every update
add_cbCalled when an entity is added to the system (can be NULL)
remove_cbCalled when an entity is removed from the system (can be NULL)
udataThe user data passed to the callbacks
Returns
The system's ID

◆ ecs_require_component()

void ecs_require_component ( ecs_t ecs,
ecs_id_t  sys_id,
ecs_id_t  comp_id 
)

Determines which components are available to the specified system.

Parameters
ecsThe ECS instance
sys_idThe target system ID
comp_idThe component ID

◆ ecs_exclude_component()

void ecs_exclude_component ( ecs_t ecs,
ecs_id_t  sys_id,
ecs_id_t  comp_id 
)

Excludes entities having the specified component from being added to the target system.

Parameters
ecsThe ECS instance
sys_idThe target system ID
comp_idThe component ID tp exclude

◆ ecs_enable_system()

void ecs_enable_system ( ecs_t ecs,
ecs_id_t  sys_id 
)

Enables a system.

Parameters
ecsThe ECS instance
sys_idThe specified system ID

◆ ecs_disable_system()

void ecs_disable_system ( ecs_t ecs,
ecs_id_t  sys_id 
)

Disables a system.

Parameters
ecsThe ECS instance
sys_idThe specified system ID

◆ ecs_create()

ecs_id_t ecs_create ( ecs_t ecs)

Creates an entity.

Parameters
ecsThe ECS instance
Returns
The new entity ID

◆ ecs_is_ready()

bool ecs_is_ready ( ecs_t ecs,
ecs_id_t  entity_id 
)

Returns true if the entity is currently active.

Parameters
ecsThe ECS instance
entity_idThe target entity

◆ ecs_destroy()

void ecs_destroy ( ecs_t ecs,
ecs_id_t  entity_id 
)

Destroys an entity.

Destroys an entity, releasing resources and returning it to the pool.

Parameters
ecsThe ECS instance
entity_idThe ID of the entity to destroy

◆ ecs_has()

bool ecs_has ( ecs_t ecs,
ecs_id_t  entity_id,
ecs_id_t  comp_id 
)

Test if entity has the specified component.

Parameters
ecsThe ECS instance
entity_idThe entity ID
comp_idThe component ID
Returns
True if the entity has the component

◆ ecs_add()

void* ecs_add ( ecs_t ecs,
ecs_id_t  entity_id,
ecs_id_t  comp_id,
void *  args 
)

Adds a component instance to an entity.

Parameters
ecsThe ECS instance
entity_idThe entity ID
comp_idThe component ID
Returns
The component instance

◆ ecs_get()

void* ecs_get ( ecs_t ecs,
ecs_id_t  entity_id,
ecs_id_t  comp_id 
)

Gets a component instance associated with an entity.

Parameters
ecsThe ECS instance
entity_idThe entity ID
comp_idThe component ID
Returns
The component instance

◆ ecs_remove()

void ecs_remove ( ecs_t ecs,
ecs_id_t  entity_id,
ecs_id_t  comp_id 
)

Removes a component instance from an entity.

Parameters
ecsThe ECS instance
entity_idThe entity ID
comp_idThe component ID

◆ ecs_queue_destroy()

void ecs_queue_destroy ( ecs_t ecs,
ecs_id_t  entity_id 
)

Queues an entity for destruction at the end of system execution.

Queued entities are destroyed after the curent iteration.

Parameters
ecsThe ECS instance
entity_idThe ID of the entity to destroy

◆ ecs_queue_remove()

void ecs_queue_remove ( ecs_t ecs,
ecs_id_t  entity_id,
ecs_id_t  comp_id 
)

Queues a component for removable.

Queued entity/component pairs that will be deleted after the current system returns

Parameters
ecsThe ECS instance
entity_idThe ID of the entity that has the component
comp_idThe component to remove

◆ ecs_update_system()

ecs_ret_t ecs_update_system ( ecs_t ecs,
ecs_id_t  sys_id,
ecs_dt_t  dt 
)

Update an individual system.

This function should be called once per frame.

Parameters
ecsThe ECS instance
sys_idThe system to update
dtThe time delta

◆ ecs_update_systems()

ecs_ret_t ecs_update_systems ( ecs_t ecs,
ecs_dt_t  dt 
)

Updates all systems.

This function should be called once per frame.

Parameters
ecsThe ECS instance
dtThe time delta