|
Pico Headers
|
A pure and simple ECS written in C99. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>
Go to the source code of this file.
Classes | |
| struct | ecs_entity_t |
| An entity handle. More... | |
| struct | ecs_comp_t |
| A component handle. More... | |
| struct | ecs_system_t |
| A system handle. More... | |
Macros | |
| #define | ECS_ID_TYPE uint64_t |
| Determine ID type. | |
| #define | ECS_MASK_TYPE uint64_t |
| Determine mask type. | |
Typedefs | |
| typedef struct ecs_s | ecs_t |
| ECS context. | |
| typedef ECS_ID_TYPE | ecs_id_t |
| ID used for entity and components. | |
| typedef ECS_MASK_TYPE | ecs_mask_t |
| Type for value used in system matching. | |
| typedef int32_t | ecs_ret_t |
| Return code for system callback and calling functions. | |
| typedef struct ecs_entity_t | ecs_entity_t |
| An entity handle. | |
| typedef struct ecs_comp_t | ecs_comp_t |
| A component handle. | |
| typedef struct ecs_system_t | ecs_system_t |
| A system handle. | |
| typedef void(* | ecs_constructor_fn) (ecs_t *ecs, ecs_entity_t entity, void *comp_ptr, void *args) |
| Called when a component is created (via ecs_add) | |
| typedef void(* | ecs_destructor_fn) (ecs_t *ecs, ecs_entity_t entity, void *comp_ptr) |
| Called when a component is destroyed (via ecs_remove or ecs_destroy) | |
| typedef ecs_ret_t(* | ecs_system_fn) (ecs_t *ecs, ecs_entity_t *entities, size_t entity_count, void *udata) |
| System callback. | |
| typedef void(* | ecs_added_fn) (ecs_t *ecs, ecs_entity_t entity, void *udata) |
| Called when an entity is added to a system. | |
| typedef void(* | ecs_removed_fn) (ecs_t *ecs, ecs_entity_t entity, void *udata) |
| Called when an entity is removed from a system. | |
Functions | |
| bool | ecs_is_invalid_entity (ecs_entity_t entity) |
| Returns true if the entity is invalid and false otherwise. | |
| ecs_entity_t | ecs_invalid_entity () |
| Returns an invalid entity. | |
| ecs_t * | ecs_new (size_t entity_count, void *mem_ctx) |
| Creates an ECS context. | |
| void | ecs_free (ecs_t *ecs) |
| Destroys an ECS context. | |
| void | ecs_reset (ecs_t *ecs) |
| Removes all entities from the ECS, preserving systems and components. | |
| ecs_comp_t | ecs_define_component (ecs_t *ecs, size_t size, ecs_constructor_fn constructor, ecs_destructor_fn destructor) |
| Defines a component. | |
| ecs_system_t | ecs_define_system (ecs_t *ecs, ecs_mask_t mask, ecs_system_fn system_cb, ecs_added_fn add_cb, ecs_removed_fn remove_cb, void *udata) |
| Defines a system. | |
| void | ecs_require_component (ecs_t *ecs, ecs_system_t sys, ecs_comp_t comp) |
| Entities are processed by the target system if they have all of the the components required by the system. | |
| void | ecs_exclude_component (ecs_t *ecs, ecs_system_t sys, ecs_comp_t comp) |
| Excludes entities having the specified component from being added to the target system. | |
| void | ecs_enable_system (ecs_t *ecs, ecs_system_t sys) |
| Enables a system. | |
| void | ecs_disable_system (ecs_t *ecs, ecs_system_t sys) |
| Disables a system. | |
| void | ecs_set_system_callbacks (ecs_t *ecs, ecs_system_t sys, ecs_system_fn system_cb, ecs_added_fn add_cb, ecs_removed_fn remove_cb) |
| Updates the callbacks for an existing system. | |
| void | ecs_set_system_udata (ecs_t *ecs, ecs_system_t sys, void *udata) |
| Sets the user data for a system. | |
| void * | ecs_get_system_udata (ecs_t *ecs, ecs_system_t sys) |
| Gets the user data from a system. | |
| void | ecs_set_system_mask (ecs_t *ecs, ecs_system_t sys, ecs_mask_t mask) |
| Sets the system's mask. | |
| ecs_mask_t | ecs_get_system_mask (ecs_t *ecs, ecs_system_t sys) |
| Returns the system mask. | |
| size_t | ecs_get_system_entity_count (ecs_t *ecs, ecs_system_t sys) |
| Returns the number of entities assigned to the specified system. | |
| ecs_entity_t | ecs_create (ecs_t *ecs) |
| Creates an entity. | |
| bool | ecs_is_ready (ecs_t *ecs, ecs_entity_t entity) |
| Returns true if the entity is currently active and has not been queued for destruction. | |
| bool | ecs_has (ecs_t *ecs, ecs_entity_t entity, ecs_comp_t comp) |
| Test if entity has the specified component. | |
| void * | ecs_add (ecs_t *ecs, ecs_entity_t entity, ecs_comp_t comp, void *args) |
| Adds a component instance to an entity. | |
| void * | ecs_get (ecs_t *ecs, ecs_entity_t entity, ecs_comp_t comp) |
| Gets a component instance associated with an entity. | |
| void | ecs_destroy (ecs_t *ecs, ecs_entity_t entity) |
| Destroys an entity. | |
| void | ecs_remove (ecs_t *ecs, ecs_entity_t entity, ecs_comp_t comp) |
| Removes a component instance from an entity. | |
| void | ecs_queue_destroy (ecs_t *ecs, ecs_entity_t entity) |
| Queues an entity for destruction after the current system returns. | |
| void | ecs_queue_remove (ecs_t *ecs, ecs_entity_t entity, ecs_comp_t comp) |
| Queues a component for removal from the specified entity. | |
| ecs_ret_t | ecs_run_system (ecs_t *ecs, ecs_system_t sys, ecs_mask_t mask) |
| Update an individual system. | |
| ecs_ret_t | ecs_run_systems (ecs_t *ecs, ecs_mask_t mask) |
| Updates all systems. | |
A pure and simple ECS written in C99.
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 is 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 defining a new system!
Please see the examples and unit tests for more details.
Version 3.0 is a major departure from 2.4. Here is a short guide to help make the leap to 3.0.
ecs_define_system calls, for example, ecs_define_system(ecs, 0, ...)ecs_run_system(ctx, sys, 0) and/or ecs_run_systems(ctx, 0)If you encounter any difficultlies with any of these steps and/or your project doesn't compile once you're finished, please submit an issue.
Masks are a new feature in 3.0. Systems to are assigned to categories (using a bitmask) at definition and then can selectively invoke those systems at runtime (also using a bitmask).
Note that passing 0 into ecs_define_system means the system matches all categories.
If ecs_system_t sys = ecs_define_system(ecs, (1 << 0) | (1 << 1), ...) Then,
This will run sys:
ecs_run_system(ecs, sys, (1 << 0) | (1 << 1));
And so will this,
ecs_run_system(ecs, sys, (1 << 1));
But this will not,
ecs_run_system(ecs, sys, (1 << 3));
Nor will this:
ecs_run_system(ecs, sys, 0);
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.
The ctx parameter is sometimes used by custom allocators
Must be defined before PICO_ECS_IMPLEMENTATION
| #define ECS_ID_TYPE uint64_t |
Determine ID type.
| #define ECS_MASK_TYPE uint64_t |
Determine mask type.
| typedef struct ecs_s ecs_t |
ECS context.
| typedef ECS_ID_TYPE ecs_id_t |
ID used for entity and components.
| typedef ECS_MASK_TYPE ecs_mask_t |
Type for value used in system matching.
| typedef int32_t ecs_ret_t |
Return code for system callback and calling functions.
| typedef struct ecs_entity_t ecs_entity_t |
An entity handle.
| typedef struct ecs_comp_t ecs_comp_t |
A component handle.
| typedef struct ecs_system_t ecs_system_t |
A system handle.
| typedef void(* ecs_constructor_fn) (ecs_t *ecs, ecs_entity_t entity, void *comp_ptr, void *args) |
Called when a component is created (via ecs_add)
| ecs | The ECS context |
| entity | The entity being constructed |
| ptr | The pointer to the component |
| typedef void(* ecs_destructor_fn) (ecs_t *ecs, ecs_entity_t entity, void *comp_ptr) |
Called when a component is destroyed (via ecs_remove or ecs_destroy)
| ecs | The ECS context |
| entity | The entity being destoryed |
| ptr | The pointer to the component |
| typedef ecs_ret_t(* ecs_system_fn) (ecs_t *ecs, ecs_entity_t *entities, size_t entity_count, void *udata) |
System callback.
Systems implement the core logic of an ECS by manipulating entities and components.
| ecs | The ECS context |
| entities | An array of entities managed by the system |
| entity_count | The number of entities in the array |
| udata | The user data associated with the system |
| typedef void(* ecs_added_fn) (ecs_t *ecs, ecs_entity_t entity, void *udata) |
Called when an entity is added to a system.
| ecs | The ECS context |
| entity | The entity being added |
| udata | The user data passed to the callback |
| typedef void(* ecs_removed_fn) (ecs_t *ecs, ecs_entity_t entity, void *udata) |
Called when an entity is removed from a system.
| ecs | The ECS context |
| entity | The enitty being removed |
| udata | The user data passed to the callback |
| bool ecs_is_invalid_entity | ( | ecs_entity_t | entity | ) |
Returns true if the entity is invalid and false otherwise.
| ecs_entity_t ecs_invalid_entity | ( | ) |
Returns an invalid entity.
| ecs_t * ecs_new | ( | size_t | entity_count, |
| void * | mem_ctx | ||
| ) |
Creates an ECS context.
| entity_count | The inital number of entities to pre-allocated |
| mem_ctx | A context for a custom allocator |
| void ecs_free | ( | ecs_t * | ecs | ) |
Destroys an ECS context.
| ecs | The ECS context |
| void ecs_reset | ( | ecs_t * | ecs | ) |
Removes all entities from the ECS, preserving systems and components.
| ecs_comp_t ecs_define_component | ( | ecs_t * | ecs, |
| size_t | size, | ||
| ecs_constructor_fn | constructor, | ||
| ecs_destructor_fn | destructor | ||
| ) |
Defines a component.
Defines a component with the specfied size in bytes. Components define the game state (usually contained within structs) and are manipulated by systems.
| ecs | The ECS context |
| size | The number of bytes to allocate for each component instance |
| constructor | Called when a component is created (disabled if NULL) |
| destructor | Called when a component is destroyed (disabled if NULL) |
| udata | Data passed to callbacks (can be NULL) |
| ecs_system_t ecs_define_system | ( | ecs_t * | ecs, |
| ecs_mask_t | mask, | ||
| ecs_system_fn | system_cb, | ||
| ecs_added_fn | add_cb, | ||
| ecs_removed_fn | remove_cb, | ||
| void * | udata | ||
| ) |
Defines a system.
Defines a system with the specified parameters. Systems contain the core logic of a game by manipulating game state as defined by components.
| ecs | The ECS context |
| mask | Bitmask that determines which categories the system belongs to. A value of 0 matches all categories |
| system_cb | Callback that is fired every update |
| add_cb | Called when an entity is added to the system (can be NULL) |
| remove_cb | Called when an entity is removed from the system (can be NULL) |
| udata | The user data passed to the callbacks |
| void ecs_require_component | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| ecs_comp_t | comp | ||
| ) |
Entities are processed by the target system if they have all of the the components required by the system.
| ecs | The ECS context |
| sys | The target system |
| comp | A component to require |
| void ecs_exclude_component | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| ecs_comp_t | comp | ||
| ) |
Excludes entities having the specified component from being added to the target system.
| ecs | The ECS context |
| sys | The target system |
| comp | A component to exclude |
| void ecs_enable_system | ( | ecs_t * | ecs, |
| ecs_system_t | sys | ||
| ) |
Enables a system.
| ecs | The ECS context |
| sys_id | The specified system |
| void ecs_disable_system | ( | ecs_t * | ecs, |
| ecs_system_t | sys | ||
| ) |
Disables a system.
| ecs | The ECS context |
| sys | The specified system |
| void ecs_set_system_callbacks | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| ecs_system_fn | system_cb, | ||
| ecs_added_fn | add_cb, | ||
| ecs_removed_fn | remove_cb | ||
| ) |
Updates the callbacks for an existing system.
| ecs | The ECS context |
| sys | The system |
| system_cb | Callback that is fired every update |
| add_cb | Called when an entity is added to the system (can be NULL) |
| remove_cb | Called when an entity is removed from the system (can be NULL) |
| void ecs_set_system_udata | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| void * | udata | ||
| ) |
Sets the user data for a system.
| ecs | The ECS context |
| sys | The system |
| udata | The user data to set |
| void * ecs_get_system_udata | ( | ecs_t * | ecs, |
| ecs_system_t | sys | ||
| ) |
Gets the user data from a system.
| ecs | The ECS context |
| sys | The system |
| void ecs_set_system_mask | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| ecs_mask_t | mask | ||
| ) |
Sets the system's mask.
| ecs | The ECS context |
| sys | The system |
| mask | The mask to set |
| ecs_mask_t ecs_get_system_mask | ( | ecs_t * | ecs, |
| ecs_system_t | sys | ||
| ) |
Returns the system mask.
| ecs | The ECS context |
| sys | The system |
| size_t ecs_get_system_entity_count | ( | ecs_t * | ecs, |
| ecs_system_t | sys | ||
| ) |
Returns the number of entities assigned to the specified system.
| ecs_entity_t ecs_create | ( | ecs_t * | ecs | ) |
Creates an entity.
| ecs | The ECS context |
| bool ecs_is_ready | ( | ecs_t * | ecs, |
| ecs_entity_t | entity | ||
| ) |
Returns true if the entity is currently active and has not been queued for destruction.
| ecs | The ECS context |
| entity | The target entity |
| bool ecs_has | ( | ecs_t * | ecs, |
| ecs_entity_t | entity, | ||
| ecs_comp_t | comp | ||
| ) |
Test if entity has the specified component.
| ecs | The ECS context |
| entity | The entity |
| comp | The component |
| void * ecs_add | ( | ecs_t * | ecs, |
| ecs_entity_t | entity, | ||
| ecs_comp_t | comp, | ||
| void * | args | ||
| ) |
Adds a component instance to an entity.
| ecs | The ECS context |
| entity | The entity |
| comp | The component |
| void * ecs_get | ( | ecs_t * | ecs, |
| ecs_entity_t | entity, | ||
| ecs_comp_t | comp | ||
| ) |
Gets a component instance associated with an entity.
| ecs | The ECS context |
| entity | The entity |
| comp | The component |
| void ecs_destroy | ( | ecs_t * | ecs, |
| ecs_entity_t | entity | ||
| ) |
Destroys an entity.
Destroys an entity, releasing resources and returning it to the pool.
WARNING: This function may change the order of a system's entity array. It should be used with caution. A better option in most circumstances is to use the ecs_queue_destroy function, which destroys the entity after the system has finished executing.
| ecs | The ECS context |
| entity | The entity to destroy |
| void ecs_remove | ( | ecs_t * | ecs, |
| ecs_entity_t | entity, | ||
| ecs_comp_t | comp | ||
| ) |
Removes a component instance from an entity.
WARNING: This function may change the order of a system's entity array. It should be used with caution. A better option in most circumstances is to use the ecs_queue_remove function, which removes the component after the system has finished executing.
| ecs | The ECS context |
| entity | The entity |
| comp | The component |
| void ecs_queue_destroy | ( | ecs_t * | ecs, |
| ecs_entity_t | entity | ||
| ) |
Queues an entity for destruction after the current system returns.
Queued entities are destroyed after the curent iteration.
| ecs | The ECS context |
| entity | The entity to destroy |
| void ecs_queue_remove | ( | ecs_t * | ecs, |
| ecs_entity_t | entity, | ||
| ecs_comp_t | comp | ||
| ) |
Queues a component for removal from the specified entity.
Queued entity/component pairs that will be deleted after the current system returns.
| ecs | The ECS context |
| entity | The entity that has the component |
| comp | The component to remove |
| ecs_ret_t ecs_run_system | ( | ecs_t * | ecs, |
| ecs_system_t | sys, | ||
| ecs_mask_t | mask | ||
| ) |
Update an individual system.
Calls system logic on required components, but not excluded ones.
| ecs | The ECS context |
| sys | The system to update |
| mask | Bitmask that determines which systems run based on category. |
| ecs_ret_t ecs_run_systems | ( | ecs_t * | ecs, |
| ecs_mask_t | mask | ||
| ) |
Updates all systems.
Calls ecs_run_system on all components in order of system definition. In many cases it is better to call ecs_run_system as needed.
| ecs | The ECS context |
| mask | Bitmask that determines which systems run based on category. |