Aller au contenu

Référence API

Cette page est une carte de l’API, pas un second tutoriel. Lisez le démarrage rapide et les manuels pour comprendre les concepts ; utilisez cette page pour trouver l’opération publique et son équivalent dans les deux langages.

Tous les exemples utilisent le header de distribution public. Le runtime utilise C17 et le wrapper typé C++20.

#include <siecs.h>

Un seul monde est actif par processus. Initialisez-le avant d’enregistrer des types ou de créer des handles, puis finalisez-le lorsque les systèmes et outils n’en ont plus besoin.

ecs_init();
ecs_progress();
ecs_run_phase(EcsOnUpdate);
ecs_quit();
ecs_fini();
Besoin API C API C++
Limiter la cadence ecs_init_w_features() ecs::init({ .target_fps = 60 })
Exécuter tous les systèmes ecs_progress() ecs::progress()
Exécuter une phase ecs_run_phase() ecs::run_phase()
Arrêter une boucle ecs_quit() ecs::quit()

Le monde possède les entités, registres de composants, ressources, requêtes, systèmes, observateurs et modules. Les handles ne le possèdent pas et ne doivent pas lui survivre.

Une entité est une identité ; les composants sont les données typées qui lui sont attachées. Les opérations courantes sont les suivantes :

ecs_entity_t player = ecs_new();
ecs_set(player, Position, { .x = 1.0f, .y = 2.0f });
if (ecs_has(player, Position)) {
Position *position = ecs_get(player, Position);
position->x += 1.0f;
}
ecs_remove(player, Position);
ecs_kill(player);
Opération C C++
Créer ecs_new(), ecs_new_no_reuse() entity::create(), create_no_reuse()
Tester la validité ecs_is_alive() entity::is_alive()
Ajouter/retirer ecs_add(), ecs_remove() entity::add<T>(), remove<T>()
Tester la présence ecs_has() entity::has<T>()
Lire, obligatoire ecs_get() entity::get<T>()
Lire, nullable ecs_try_get() entity::try_get<T>()
Écrire ecs_set() entity::set()
Détruire ecs_kill() entity::kill()
Désactiver ecs_add(entity, Disabled) entity::disable()

En C, enregistrez les déclarations typées une fois par monde avec ECS_COMPONENT_REGISTER(). Les types C++ natifs s’enregistrent au premier usage typé. Le code générique peut utiliser les fonctions _cid (ecs_get_cid, ecs_set_cid, ecs_add_cid, ecs_remove_cid) et ecs::component<T>().

Les requêtes correspondent aux tables d’archétypes et exposent chaque table correspondante sous forme de lot. Conservez un identifiant ou un query_handle pour les traitements répétés.

ecs_query_id_t moving = ecs_query({
.components = { ecs_inout(Position), ecs_in(Velocity) },
});
ecs_iter_t it = ecs_query_iter(moving);
while (ecs_iter_next(&it)) {
Position *positions = ecs_field(&it, 0);
const Velocity *velocities = ecs_field(&it, 1);
for (uint32_t i = 0; i < it.count; i++) {
positions[i].x += velocities[i].x;
}
}
ecs_query_fini(moving);
Correspondance ou accès C C++
Lecture obligatoire ecs_in(T) require<T>()
Écriture obligatoire ecs_out(T), ecs_inout(T) paramètre non const
Lecture/écriture optionnelle ecs_in_optional(T), ecs_inout_optional(T) optional<T>()
Inclure/exclure sans champ ecs_filter(T), ecs_not(T) require<T>(), exclude<T>()
Présence d’une relation ecs_rel(R), ecs_rel_opt(R) with_relation<R>()
Cible exacte ecs_to(R, target) to<R>(target)
Profondeur ecs_depth(R, depth) depth<R>(depth)
Lecture héritée ecs_up(T, R) up<T, R>()

Les champs sont numérotés dans l’ordre de déclaration ; les filtres et termes de relations ne consomment pas d’index de composant. ecs_field_kind() distingue les champs possédés, partagés et absents. Les pointeurs de champs sont empruntés et ne doivent pas survivre à une mutation structurelle.

Utilisez ecs_query_each() pour un scan ponctuel en C. Un identifiant C est libéré avec ecs_query_fini() ; un query_handle C++ libère automatiquement son identifiant.

Un système est une requête persistante attachée à une phase. ecs_progress() exécute les systèmes activés dans l’ordre des phases ; .after ou .after() ordonne les systèmes d’une même phase.

static void move_system(ecs_iter_t *it) {
Position *position = ecs_field(it, 0);
const Velocity *velocity = ecs_field(it, 1);
for (uint32_t i = 0; i < it->count; i++) {
position[i].x += velocity[i].x;
}
}
ecs_system({
.name = "Move",
.phase = EcsOnUpdate,
.query = { .components = { ecs_inout(Position), ecs_in(Velocity) } },
.callback = move_system,
});
Opération C C++
Toutes les phases ecs_progress() ecs::progress()
Une phase ecs_run_phase() ecs::run_phase()
Un système ecs_run_system() ecs::run_system()
Activer/désactiver ecs_system_enable(), ecs_system_disable() ecs::enable_system(), disable_system()
Phase ecs_phase_t EcsOnUpdate, EcsPostUpdate, etc.

Une mutation structurelle pendant l’itération peut déplacer une entité et invalider les pointeurs du lot courant. Utilisez la mutation différée lorsque la modification doit attendre la fin de la portée de commande.

Une ressource est une valeur typée unique par monde. Elle n’est pas un composant d’entité et ne devient pas un champ de requête.

ecs_set_resource(Time, { .dt = 1.0f / 60.0f });
const Time *time = ecs_get_resource_read(Time);

Utilisez ecs_try_get_resource() ou ecs::try_resource<T>() lorsque l’absence est valide. Les fonctions C par identifiant utilisent le registre séparé ecs_resource_t : ecs_resource_init, ecs_resource_find, ecs_resource_rid, ecs_try_resource_rid, ecs_has_resource_rid et ecs_remove_resource_rid.

Les relations relient une source à une cible. ChildOf fournit la hiérarchie et IsA l’héritage depuis une base abstraite.

ecs_relate(child, ChildOf, parent);
ecs_entity_t current_parent = ecs_target(child, ChildOf);
ecs_add(base, Abstract);
ecs_is_a(instance, base);

Enregistrez une relation personnalisée avec ECS_RELATION_DECLARE/DEFINE/REGISTER ou ecs::relation<T>(). Le mode de stockage détermine les termes valides : ecs_to pour ByTarget, ecs_depth pour ByDepth et ecs_rel pour tester la présence.

Les observateurs réagissent à EcsOnAdd, EcsOnRemove, EcsOnSet, aux transitions de relations ou à un événement personnalisé. Leurs payloads sont empruntés pendant le callback.

static void on_position_set(ecs_observer_event_t *event) {
const Position *position = event->trigger_data;
log_position(event->entity, position);
}
ecs_observer({
.on = EcsOnSet,
.query = { .components = { ecs_in(Position) } },
.callback = on_position_set,
});

Utilisez ecs_observer_trigger() ou ecs::trigger<T>() pour un événement personnalisé. Les événements de relation portent old_target et new_target dans ecs_relation_event_t.

Les modules regroupent des enregistrements et peuvent activer ou désactiver les systèmes et observateurs capturés. Les imports sont idempotents dans le monde actif ; les premières propriétés fournies sont conservées.

ECS_MODULE_DECLARE(physics, { float gravity; });
ECS_MODULE_DEFINE(physics);
void physics_import(const physics_props_t *props) {
(void)props;
ecs_system({ .name = "Move", .callback = move_system });
}
ecs_module_id_t Physics = ECS_MODULE_IMPORT(physics, { .gravity = 9.81f });
ecs_module_disable(Physics);
Famille Types C publics Types C++ publics
Entité ecs_entity_t ecs::entity
Composant ecs_component_t, ecs_component_desc_t ecs::component<T>, ecs::component_hooks<T>
Ressource ecs_resource_t, ecs_resource_desc_t ecs::resource_handle<T>, ecs::res<T>
Requête ecs_query_id_t, ecs_query_desc_t, ecs_iter_t ecs::query, ecs::query_handle
Système ecs_system_id_t, ecs_system_desc_t, ecs_phase_t ecs::system
Observateur ecs_observer_id_t, ecs_observer_desc_t, ecs_observer_event_t ecs::observer<T>, ecs::observer_event
Module ecs_module_id_t, ecs_module_desc_t ecs::module_ref<T>
Relation ecs_relation_id_t, ecs_relation_desc_t ecs::relation<T>

Pour les préconditions, règles de propriété, champs partagés, politiques de suppression et garanties de version, consultez la stabilité de l’API et le manuel concerné. Les headers publics restent l’autorité finale pour les surcharges et la disposition exacte des descripteurs.