-
C/C++ Entity Component System (Flecs)컴퓨터/C & C++ 2020. 8. 4. 19:46728x90반응형
Flecs
소개
Flecs는 C89 / C99 / C++11를 위한 빠르고, 가벼운 Entity Component System(ECS) 빌드 툴이다.
아래는 foot-print 목록이다.
- Blazing fast iteration speeds with direct access to raw C arrays across multiple components
- Built-in support for entity hierarchies, prefabs, nested prefabs and prefab variants
- An efficient lock-free architecture allows for modifying entities across multiple threads
- Expressive entity queries with support for and, or, not and optional operators
- Systems that are time triggered, rate triggered, run every frame or run only when needed
- A customizable core that lets you include only the features you need
1. Entity Component System
ECS란 무엇일까?
한줄로 표현하자면, 데이터 목적(data-oriented)으로 코딩을 하는 시스템이다. (게임에 많이 쓰임)
ECS에는 아래 3가지의 핵심 키워드가 있다.
- entity (독립체) : 독립체들, things, indices, ID라고 생각하면 편하고, 값을 갖고 있지 않음
- component (요소) : 데이터, entity로 정리되기 보단, 데이터 자체로 정리됨 (data-oriented)
- system (체계) : 데이터를 변형하기 위한 코드
system 예제) 모든 독립체들이 프레임마다 움직일 때 위치를 업데이트 해줌
정리
- 각 entity들은 unique ID를 갖는다.
- component는 plain 데이터 타입을 갖는다.
- system은 component 기반 entity들에 맞는 행동들을 제어한다.
2. Flecs 라이브러리
우선 라이브러리를 사용하려면 아래 두 파일을 작업 환경에 추가한다.
github.com/SanderMertens/flecs/blob/master/flecs.c
github.com/SanderMertens/flecs/blob/master/flecs.h
1. Hello World
#include "flec.h" typedef struct Position { float x; float y; } Position; int main(int argc, char *argv[]) { /* Create the world, pass arguments for overriding the number of threads,fps * or for starting the admin dashboard (see flecs.h for details). */ ecs_world_t *world = ecs_init_w_args(argc, argv); /* Register a component with the world. */ ECS_COMPONENT(world, Position); /* Create a new empty entity */ ECS_ENTITY(world, MyEntity, 0); /* Set the Position component on the entity */ ecs_set(world, MyEntity, Position, {10, 20}); /* Get the Position component */ const Position *p = ecs_get(world, MyEntity, Position); printf("Position of %s is {%f, %f}\n", ecs_get_name(world, MyEntity), p->x, p->y); /* Cleanup */ return ecs_fini(world); }
2. Move System (프레임마다 1.0 좌표 이동)
#include "flec.h" /* Component types */ typedef struct Vector2D { float x; float y; } Vector2D; /* Typedefs can be used as component types */ typedef Vector2D Position; typedef Vector2D Velocity; /* Implement a simple move system */ void Move(ecs_iter_t *it) { /* Get the two columns from the system signature */ ECS_COLUMN(it, Position, p, 1); ECS_COLUMN(it, Velocity, v, 2); for (int i = 0; i < it->count; i ++) { p[i].x += v[i].x; p[i].y += v[i].y; /* Print something to the console so we can see the system is being * invoked */ printf("%s moved to {.x = %f, .y = %f}\n", ecs_get_name(it->world, it->entities[i]), p[i].x, p[i].y); } } int main(int argc, char *argv[]) { /* Create the world, pass arguments for overriding the number of threads,fps * or for starting the admin dashboard (see flecs.h for details). */ ecs_world_t *world = ecs_init_w_args(argc, argv); /* Register components */ ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); /* Define a system called Move that is executed every frame, and subscribes * for the 'Position' and 'Velocity' components */ ECS_SYSTEM(world, Move, EcsOnUpdate, Position, Velocity); /* Create an entity with Position and Velocity. Creating an entity with the * ECS_ENTITY macro is an easy way to create entities with multiple * components. Additionally, entities created with this macro can be looked * up by their name ('MyEntity'). */ ECS_ENTITY(world, MyEntity, Position, Velocity); /* Initialize values for the entity */ ecs_set(world, MyEntity, Position, {0, 0}); ecs_set(world, MyEntity, Velocity, {1, 1}); /* Set target FPS for main loop to 1 frame per second */ ecs_set_target_fps(world, 1); printf("Application move_system is running, press CTRL-C to exit...\n"); /* Run systems */ while ( ecs_progress(world, 0)); /* Cleanup */ return ecs_fini(world); }
3. Sorting
#include "flec.h" typedef struct Position { float x; float y; } Position; /* Order by x member of Position */ int compare_position( ecs_entity_t e1, void* ptr1, ecs_entity_t e2, void* ptr2) { Position* p1 = ptr1; Position* p2 = ptr2; return p1->x - p2->x; } /* Iterate query, printed values will be ordered */ void print_query(ecs_query_t* q) { ecs_iter_t it = ecs_query_iter(q); while (ecs_query_next(&it)) { Position* p = ecs_column(&it, Position, 1); int32_t i; for (i = 0; i < it.count; i++) { printf("{%f, %f}\n", p[i].x, p[i].y); } } } int main(int argc, char* argv[]) { ecs_world_t* world = ecs_init(); ECS_COMPONENT(world, Position); /* Create entities, set Position in random order */ ecs_entity_t e = ecs_set(world, 0, Position, { 3, 0 }); ecs_set(world, 0, Position, { 1, 0 }); ecs_set(world, 0, Position, { 6, 0 }); ecs_set(world, 0, Position, { 2, 0 }); ecs_set(world, 0, Position, { 5, 0 }); ecs_set(world, 0, Position, { 4, 0 }); /* Create a query for component Position */ ecs_query_t* q = ecs_query_new(world, "Position"); /* Order by Position component */ ecs_query_order_by(world, q, ecs_entity(Position), compare_position); /* Iterate query, print values of Position */ printf("-- First iteration\n"); print_query(q); /* Change the value of one entity, invalidating the order */ ecs_set(world, e, Position, { 7, 0 }); /* Iterate query again, printed values are still ordered */ printf("\n-- Second iteration\n"); print_query(q); /* Cleanup */ return ecs_fini(world); }
참고 : https://github.com/SanderMertens/flecs
728x90'컴퓨터 > C & C++' 카테고리의 다른 글
C++ Insertion Sort 및 성능 테스트 (0) 2020.10.05 C언어 while EOF scanf 작동안할 때 참고 (0) 2017.11.15 C언어 스트링(string)들로 구성된 배열(array) 만들기 (0) 2017.11.15