|
1 | 1 | #include <component_inheritance.h> |
2 | 2 | #include <stdio.h> |
3 | 3 |
|
4 | | -// This example shows how queries can be used to match simple inheritance trees. |
| 4 | +// This example shows how queries can match components that derive from a base |
| 5 | +// component through the IsA relationship. A query for the base component |
| 6 | +// matches all entities that have a derived component, and can read the members |
| 7 | +// that are inherited from the base. See the tag_inheritance example for |
| 8 | +// inheritance trees built from tags instead of components. |
5 | 9 |
|
6 | | -int main(int argc, char *argv[]) { |
7 | | - ecs_world_t *ecs = ecs_init_w_args(argc, argv); |
| 10 | +// Buf is the base component. HealthBuf and ManaBuf derive from it, so they |
| 11 | +// start with the same members as Buf (the base layout is a prefix of the |
| 12 | +// derived layout). |
| 13 | +typedef struct { |
| 14 | + float value; |
| 15 | +} Buf; |
| 16 | + |
| 17 | +typedef struct { |
| 18 | + float value; |
| 19 | +} HealthBuf; |
8 | 20 |
|
9 | | - // Use convenience macros to create simple hierarchy of unit types. |
10 | | - // This macro call: |
11 | | - // ECS_ENTITY(ecs, CombatUnit, (IsA, Unit)) |
12 | | - // |
13 | | - // is the same as these C statements: |
14 | | - // ecs_entity_t CombatUnit = ecs_new_entity("CombatUnit"); |
15 | | - // ecs_add_pair(ecs, CombatUnit, EcsIsA, Unit); |
| 21 | +typedef struct { |
| 22 | + float value; |
| 23 | +} ManaBuf; |
16 | 24 |
|
17 | | - ECS_TAG(ecs, Unit); |
18 | | - ECS_ENTITY(ecs, CombatUnit, (IsA, Unit)); |
19 | | - ECS_ENTITY(ecs, MeleeUnit, (IsA, CombatUnit)); |
20 | | - ECS_ENTITY(ecs, RangedUnit, (IsA, CombatUnit)); |
| 25 | +int main(int argc, char *argv[]) { |
| 26 | + ecs_world_t *ecs = ecs_init_w_args(argc, argv); |
21 | 27 |
|
22 | | - ECS_ENTITY(ecs, Warrior, (IsA, MeleeUnit)); |
23 | | - ECS_ENTITY(ecs, Wizard, (IsA, RangedUnit)); |
24 | | - ECS_ENTITY(ecs, Marksman, (IsA, RangedUnit)); |
25 | | - ECS_ENTITY(ecs, Builder, (IsA, Unit)); |
| 28 | + ECS_COMPONENT(ecs, Buf); |
| 29 | + ECS_COMPONENT(ecs, HealthBuf); |
| 30 | + ECS_COMPONENT(ecs, ManaBuf); |
26 | 31 |
|
27 | | - // Create a few units |
28 | | - ecs_entity_t warrior_1 = ecs_entity(ecs, { .name = "warrior_1" }); |
29 | | - ecs_add(ecs, warrior_1, Warrior); |
30 | | - ecs_entity_t warrior_2 = ecs_entity(ecs, { .name = "warrior_2" }); |
31 | | - ecs_add(ecs, warrior_2, Warrior); |
| 32 | + // Make the ECS aware of the inheritance relationships. |
| 33 | + ecs_add_pair(ecs, ecs_id(HealthBuf), EcsIsA, ecs_id(Buf)); |
| 34 | + ecs_add_pair(ecs, ecs_id(ManaBuf), EcsIsA, ecs_id(Buf)); |
32 | 35 |
|
33 | | - ecs_entity_t marksman_1 = ecs_entity(ecs, { .name = "marksman_1" }); |
34 | | - ecs_add(ecs, marksman_1, Marksman); |
35 | | - ecs_entity_t marksman_2 = ecs_entity(ecs, { .name = "marksman_2" }); |
36 | | - ecs_add(ecs, marksman_2, Marksman); |
| 36 | + // Create a few entities with derived buf components |
| 37 | + ecs_entity_t warrior = ecs_entity(ecs, { .name = "warrior" }); |
| 38 | + ecs_set(ecs, warrior, HealthBuf, { .value = 10 }); |
37 | 39 |
|
38 | | - ecs_entity_t wizard_1 = ecs_entity(ecs, { .name = "wizard_1" }); |
39 | | - ecs_add(ecs, wizard_1, Wizard); |
40 | | - ecs_entity_t wizard_2 = ecs_entity(ecs, { .name = "wizard_2" }); |
41 | | - ecs_add(ecs, wizard_2, Wizard); |
| 40 | + ecs_entity_t wizard = ecs_entity(ecs, { .name = "wizard" }); |
| 41 | + ecs_set(ecs, wizard, ManaBuf, { .value = 25 }); |
42 | 42 |
|
43 | | - ecs_entity_t builder_1 = ecs_entity(ecs, { .name = "builder_1" }); |
44 | | - ecs_add(ecs, builder_1, Builder); |
45 | | - ecs_entity_t builder_2 = ecs_entity(ecs, { .name = "builder_2" }); |
46 | | - ecs_add(ecs, builder_2, Builder); |
| 43 | + ecs_entity_t paladin = ecs_entity(ecs, { .name = "paladin" }); |
| 44 | + ecs_set(ecs, paladin, HealthBuf, { .value = 5 }); |
47 | 45 |
|
48 | | - // Create a query to find all ranged units |
| 46 | + // Create a query for the base component. This matches all entities with a |
| 47 | + // component that derives from Buf. |
49 | 48 | ecs_query_t *q = ecs_query(ecs, { |
50 | | - .terms = {{ .id = RangedUnit }} |
| 49 | + .terms = {{ .id = ecs_id(Buf) }} |
51 | 50 | }); |
52 | 51 |
|
53 | | - // Iterate the query |
| 52 | + // Iterate the query. Because the matched component can be a derived type |
| 53 | + // that is larger than Buf, use ecs_base_field to get the field pointer and |
| 54 | + // ecs_field_stride to advance from one element to the next. |
54 | 55 | ecs_iter_t it = ecs_query_iter(ecs, q); |
55 | 56 | while (ecs_query_next(&it)) { |
| 57 | + void *bufs = ecs_base_field(&it, Buf, 0); |
| 58 | + size_t stride = ecs_field_stride(&it, 0); |
56 | 59 | for (int i = 0; i < it.count; i ++) { |
57 | | - printf("Unit %s found\n", ecs_get_name(ecs, it.entities[i])); |
| 60 | + Buf *buf = ECS_OFFSET(bufs, stride * i); |
| 61 | + printf("%s has buf value %.0f\n", |
| 62 | + ecs_get_name(ecs, it.entities[i]), buf->value); |
58 | 63 | } |
59 | 64 | } |
60 | 65 |
|
61 | 66 | ecs_query_fini(q); |
62 | 67 |
|
63 | 68 | // Output |
64 | | - // Unit wizard_1 found |
65 | | - // Unit wizard_2 found |
66 | | - // Unit marksman_1 found |
67 | | - // Unit marksman_2 found |
| 69 | + // warrior has buf value 10 |
| 70 | + // paladin has buf value 5 |
| 71 | + // wizard has buf value 25 |
68 | 72 |
|
69 | 73 | return ecs_fini(ecs); |
70 | 74 | } |
0 commit comments