Skip to content
Flecs v4.1
queries/setting_variables

  • C

    View on GitHub

    1#include <setting_variables.h>
    2#include <stdio.h>
    3
    4// This example extends the component_inheritance example, and shows how
    5// we can use a single query to match units from different players and platoons
    6// by setting query variables before we iterate.
    7//
    8// The units in this example belong to a platoon, with the platoons belonging
    9// to a player.
    10
    11static const int PlayerCount = 100;
    12static const int PlatoonsPerPlayer = 3;
    13
    14int main(int argc, char *argv[]) {
    15 ecs_world_t *ecs = ecs_init_w_args(argc, argv);
    16
    17 // Unit datamodel - see component_inheritance example
    18 ECS_TAG(ecs, Unit);
    19 ecs_entity_t CombatUnit = ecs_entity(ecs, { .name = "CombatUnit" });
    20 ecs_add_pair(ecs, CombatUnit, EcsIsA, Unit);
    21 ecs_entity_t MeleeUnit = ecs_entity(ecs, { .name = "MeleeUnit" });
    22 ecs_add_pair(ecs, MeleeUnit, EcsIsA, CombatUnit);
    23 ecs_entity_t RangedUnit = ecs_entity(ecs, { .name = "RangedUnit" });
    24 ecs_add_pair(ecs, RangedUnit, EcsIsA, CombatUnit);
    25
    26 ecs_entity_t Warrior = ecs_entity(ecs, { .name = "Warrior" });
    27
    28 ecs_add_pair(ecs, Warrior, EcsIsA, MeleeUnit);
    29 ecs_entity_t Wizard = ecs_entity(ecs, { .name = "Wizard" });
    30 ecs_add_pair(ecs, Wizard, EcsIsA, RangedUnit);
    31 ecs_entity_t Marksman = ecs_entity(ecs, { .name = "Marksman" });
    32 ecs_add_pair(ecs, Marksman, EcsIsA, RangedUnit);
    33 ecs_entity_t Builder = ecs_entity(ecs, { .name = "Builder" });
    34 ecs_add_pair(ecs, Builder, EcsIsA, Unit);
    35
    36 // Player/Platoon tags
    37 ECS_TAG(ecs, Player);
    38 ECS_TAG(ecs, Platoon);
    39
    40 // Populate store with players and platoons
    41 for (int p = 0; p < PlayerCount; p ++) {
    42 ecs_entity_t player;
    43
    44 // Give first player a name so we can look it up later
    45 if (p == 0) {
    46 player = ecs_entity(ecs, { .name = "MyPlayer" });
    47 } else {
    48 player = ecs_new(ecs);
    49 }
    50
    51 // Add player tag so we can query for all players if we want to
    52 ecs_add(ecs, player, Player);
    53
    54 for (int pl = 0; pl < PlatoonsPerPlayer; pl ++) {
    55 ecs_entity_t platoon = ecs_new_w_pair(ecs, Player, player);
    56
    57 // Add platoon tag so we can query for all platoons if we want to
    58 ecs_add(ecs, platoon, Platoon);
    59
    60 // Add warriors, wizards and marksmen to the platoon
    61 ecs_entity_t warrior = ecs_new_w_id(ecs, Warrior);
    62 ecs_add_pair(ecs, warrior, Platoon, platoon);
    63
    64 ecs_entity_t marksman = ecs_new_w_id(ecs, Marksman);
    65 ecs_add_pair(ecs, marksman, Platoon, platoon);
    66
    67 ecs_entity_t wizard = ecs_new_w_id(ecs, Wizard);
    68 ecs_add_pair(ecs, wizard, Platoon, platoon);
    69 }
    70 }
    71
    72 // Create a query to find all RangedUnits for a platoon/player. The
    73 // equivalent query in the query DSL would look like this:
    74 // (Platoon, $Platoon), Player($Platoon, $Player)
    75 //
    76 // The way to read how this query is evaluated is:
    77 // - find all entities with (Platoon, *), store * in $platoon
    78 // - check if $platoon has (Player, *), store * in $player
    79 ecs_query_t *q = ecs_query(ecs, {
    80 .terms = {
    81 { .first.id = RangedUnit },
    82 { .first.id = Platoon, .second.name = "$platoon" },
    83 { .first.id = Player, .src.name = "$platoon", .second.name = "$player" }
    84 }
    85 });
    86
    87 // If we would iterate this query it would return all ranged units for all
    88 // platoons & for all players. We can limit the results to just a single
    89 // platoon or a single player setting a variable beforehand. In this example
    90 // we'll just find all platoons & ranged units for a single player.
    91
    92 int player_var = ecs_query_find_var(q, "player");
    93 int platoon_var = ecs_query_find_var(q, "platoon");
    94
    95 // Iterate query, limit the results to units of MyPlayer
    96 ecs_iter_t it = ecs_query_iter(ecs, q);
    97 ecs_iter_set_var(&it, player_var, ecs_lookup(ecs, "MyPlayer"));
    98
    99 while (ecs_query_next(&it)) {
    100 ecs_entity_t player = ecs_iter_get_var(&it, player_var);
    101 ecs_entity_t platoon = ecs_iter_get_var(&it, platoon_var);
    102 char *platoon_str = ecs_get_path(ecs, platoon);
    103 char *class_str = ecs_id_str(ecs, ecs_field_id(&it, 0));
    104
    105 for (int i = 0; i < it.count; i ++) {
    106 char *unit_str = ecs_get_path(ecs, it.entities[i]);
    107 printf("Unit %s of class %s in platoon %s for player %s\n",
    108 unit_str, class_str, platoon_str,
    109 ecs_get_name(ecs, player));
    110 ecs_os_free(unit_str);
    111 }
    112
    113 ecs_os_free(class_str);
    114 ecs_os_free(platoon_str);
    115 }
    116
    118
    119 // Output
    120 // Unit 513 of class Wizard in platoon 510 for player MyPlayer
    121 // Unit 517 of class Wizard in platoon 514 for player MyPlayer
    122 // Unit 521 of class Wizard in platoon 518 for player MyPlayer
    123 // Unit 512 of class Marksman in platoon 510 for player MyPlayer
    124 // Unit 516 of class Marksman in platoon 514 for player MyPlayer
    125 // Unit 520 of class Marksman in platoon 518 for player MyPlayer
    126
    127 return ecs_fini(ecs);
    128}
    const ecs_entity_t EcsIsA
    Used to express inheritance relationships.
    ecs_id_t ecs_entity_t
    An entity identifier.
    Definition flecs.h:395
    struct ecs_world_t ecs_world_t
    A world is the container for all ECS data and supporting features.
    Definition flecs.h:439
    ecs_entity_t ecs_new(ecs_world_t *world)
    Create new entity ID.
    ecs_entity_t ecs_new_w_id(ecs_world_t *world, ecs_id_t component)
    Create new entity with (component) ID.
    #define ecs_add_pair(world, subject, first, second)
    Add a pair to an entity.
    Definition flecs_c.h:275
    #define ecs_add(world, entity, T)
    Add a component to an entity.
    Definition flecs_c.h:271
    #define ecs_new_w_pair(world, first, second)
    Create a new entity with a pair.
    Definition flecs_c.h:256
    #define ecs_entity(world,...)
    Shorthand for creating an entity with ecs_entity_init().
    Definition flecs_c.h:188
    #define ECS_TAG(world, id)
    Declare and define a tag.
    Definition flecs_c.h:59
    #define ecs_query(world,...)
    Shorthand for creating a query with ecs_query_init().
    Definition flecs_c.h:215
    #define ecs_get_path(world, child)
    Get path from root.
    Definition flecs_c.h:594
    char * ecs_id_str(const ecs_world_t *world, ecs_id_t component)
    Convert a component ID to a string.
    ecs_id_t ecs_field_id(const ecs_iter_t *it, int8_t index)
    Return the ID matched for a field.
    void ecs_iter_set_var(ecs_iter_t *it, int32_t var_id, ecs_entity_t entity)
    Set the value for an iterator variable.
    ecs_entity_t ecs_iter_get_var(ecs_iter_t *it, int32_t var_id)
    Get the value of an iterator variable as an entity.
    ecs_entity_t ecs_lookup(const ecs_world_t *world, const char *path)
    Look up an entity by its path.
    const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
    Get the name of an entity.
    bool ecs_query_next(ecs_iter_t *it)
    Progress a query iterator.
    int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
    Find a variable index.
    void ecs_query_fini(ecs_query_t *query)
    Delete a query.
    ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
    Create a query iterator.
    int ecs_fini(ecs_world_t *world)
    Delete a world.
    ecs_world_t * ecs_init_w_args(int argc, char *argv[])
    Create a new world with arguments.
    Iterator.
    Definition flecs.h:1183
    int32_t count
    Number of entities to iterate.
    Definition flecs.h:1189
    const ecs_entity_t * entities
    Entity identifiers.
    Definition flecs.h:1190
    Queries are lists of constraints (terms) that match entities.
    Definition flecs.h:858

  • C++

    View on GitHub

    1#include <setting_variables.h>
    2#include <iostream>
    3
    4// This example extends the component_inheritance example, and shows how
    5// we can use a single query to match units from different players and platoons
    6// by setting query variables before we iterate.
    7//
    8// The units in this example belong to a platoon, with the platoons belonging
    9// to a player.
    10
    11// Unit datamodel
    12struct Unit { };
    13struct CombatUnit : Unit { };
    14struct MeleeUnit : CombatUnit { };
    15struct RangedUnit : CombatUnit { };
    16struct Warrior : MeleeUnit { };
    17struct Wizard : RangedUnit { };
    18struct Marksman : RangedUnit { };
    19
    20// Player/Platoon tags
    21struct Player { };
    22struct Platoon { };
    23
    24static const int PlayerCount = 100;
    25static const int PlatoonsPerPlayer = 3;
    26
    27int main(int, char *[]) {
    28 flecs::world ecs;
    29
    30 // See component_inheritance example
    31 ecs.component<CombatUnit>().is_a<Unit>();
    32 ecs.component<MeleeUnit>().is_a<CombatUnit>();
    33 ecs.component<RangedUnit>().is_a<CombatUnit>();
    34
    35 ecs.component<Warrior>().is_a<MeleeUnit>();
    36 ecs.component<Wizard>().is_a<RangedUnit>();
    37 ecs.component<Marksman>().is_a<RangedUnit>();
    38
    39 // Populate store with players and platoons
    40 for (int p = 0; p < PlayerCount; p ++) {
    41 flecs::entity player;
    42
    43 // Give first player a name so we can look it up later
    44 if (p == 0) {
    45 player = ecs.entity("MyPlayer");
    46 } else {
    47 player = ecs.entity();
    48 }
    49
    50 // Add player tag so we can query for all players if we want to
    51 player.add<Player>();
    52
    53 for (int pl = 0; pl < PlatoonsPerPlayer; pl ++) {
    54 flecs::entity platoon = ecs.entity().add<Player>(player);
    55
    56 // Add platoon tag so we can query for all platoons if we want to
    57 platoon.add<Platoon>();
    58
    59 // Add warriors, wizards and marksmen to the platoon
    60 ecs.entity().add<Warrior>().add<Platoon>(platoon);
    61 ecs.entity().add<Marksman>().add<Platoon>(platoon);
    62 ecs.entity().add<Wizard>().add<Platoon>(platoon);
    63 }
    64 }
    65
    66 // Create a query to find all RangedUnits for a platoon/player. The
    67 // equivalent query in the query DSL would look like this:
    68 // (Platoon, $platoon), Player($platoon, $player)
    69 //
    70 // The way to read how this query is evaluated is:
    71 // - find all entities with (Platoon, *), store * in $platoon
    72 // - check if _Platoon has (Player, *), store * in $player
    73 flecs::query<RangedUnit> q = ecs.query_builder<RangedUnit>()
    74 .with<Platoon>("$platoon")
    75 .with<Player>("$player").src("$platoon")
    76 .build();
    77
    78 // If we would iterate this query it would return all ranged units for all
    79 // platoons & for all players. We can limit the results to just a single
    80 // platoon or a single player setting a variable beforehand. In this example
    81 // we'll just find all platoons & ranged units for a single player.
    82
    83 int player_var = q.find_var("player");
    84 int platoon_var = q.find_var("platoon");
    85
    86 // Iterate query, limit the results to units of MyPlayer
    87 q.set_var(player_var, ecs.lookup("MyPlayer"))
    88 .each([&](flecs::iter& it, size_t index, RangedUnit) {
    89 flecs::entity unit = it.entity(index);
    90 std::cout << "Unit " << unit.path() << " of class "
    91 << it.id(0).str() << " in platoon "
    92 << it.get_var(platoon_var).path() << " for player "
    93 << it.get_var(player_var).path() << "\n";
    94 });
    95
    96 // Output:
    97 // Unit ::499 of class Wizard in platoon ::496 for player ::MyPlayer
    98 // Unit ::503 of class Wizard in platoon ::500 for player ::MyPlayer
    99 // Unit ::507 of class Wizard in platoon ::504 for player ::MyPlayer
    100 // Unit ::498 of class Marksman in platoon ::496 for player ::MyPlayer
    101 // Unit ::502 of class Marksman in platoon ::500 for player ::MyPlayer
    102 // Unit ::506 of class Marksman in platoon ::504 for player ::MyPlayer
    103
    104 // Try removing the set_var call, this will cause the iterator to return
    105 // all units in all platoons for all players.
    106}
    flecs::component< T > component(Args &&... args) const
    Find or register a component.
    Definition impl.hpp:11
    flecs::query_builder< Comps... > query_builder(Args &&... args) const
    Create a query builder.
    Definition impl.hpp:342
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    const Self & unit(const char *symbol, flecs::entity_t prefix=0, flecs::entity_t base=0, flecs::entity_t over=0, int32_t factor=0, int32_t power=0) const
    Make an entity a unit.
    flecs::string path(const char *sep="::", const char *init_sep="::") const
    Return the entity path.
    Entity.
    Definition entity.hpp:30
    flecs::string str() const
    Convert ID to string.
    Definition decl.hpp:128
    Class for iterating over query results.
    Definition iter.hpp:68
    flecs::id id(int8_t index) const
    Obtain the ID matched for the field.
    Definition iter.hpp:48
    flecs::entity entity(size_t row) const
    Obtain a mutable handle to the entity being iterated over.
    Definition iter.hpp:36
    flecs::entity get_var(int var_id) const
    Get value of variable by ID.
    Definition iter.hpp:128
    int32_t find_var(const char *name) const
    Find a variable by name.
    Definition impl.hpp:203
    Typed query.
    Definition impl.hpp:271
    The world.
    Definition world.hpp:129
    flecs::entity lookup(const char *name, const char *sep="::", const char *root_sep="::", bool recursive=true) const
    Lookup entity by name.
    Definition world.hpp:102