|
|
## **Keep in mind that this wiki is still work in progress!!**
|
|
|
|
|
|
It this chapter I will explain how to create simple working program in Bubel ECS.
|
|
|
|
|
|
Program exists of given steps:
|
|
|
- Library initialization
|
|
|
- Setup data
|
|
|
- Registration process
|
|
|
- Update loop
|
|
|
- Freeing memory
|
|
|
|
|
|
### Library initialization
|
|
|
Library initialization is simple and requires one call:
|
|
|
```d
|
|
|
EntityManager.initialize();
|
|
|
```
|
|
|
This call will allocate global EntityManager object which can be accessed as `gEntitiyManager` from now. `EntityManager.initialize()` has three optional arguments:
|
|
|
- `threads_count` - maximum number of threads. Data for threads is allocated there. Default value is one.
|
|
|
- `page_size` - number of bytes per chunk. Its value have to be power of two. Currently default value is 32768 (32KB), and maximum allowed value is 65536 (64KB)
|
|
|
- `block_pages_count` - number of chunks in one allocation. 128 by default. Library allocates multiple chunks at once using `malloc` and then suballocate chunks when needed.
|
|
|
|
|
|
### Registration process
|
|
|
Components, system and events need to be registered before usage. Registration process will assign unique ID for each registered element. This process ideally should be done once at start of program. Systems can be re-registered in case of hot-reload. Re-registered systems are destroying and re-created.
|
|
|
|
|
|
First of all we need to create some components and systems. Let's create simple position and velocity components:
|
|
|
```d
|
|
|
struct CLocation
|
|
|
{
|
|
|
float x, y;
|
|
|
}
|
|
|
|
|
|
struct CVelocity
|
|
|
{
|
|
|
float x, y;
|
|
|
}
|
|
|
```
|
|
|
As you can see, component is simply a standard structure.
|
|
|
|
|
|
Next will be system for gravity:
|
|
|
```d
|
|
|
struct GravitySystem
|
|
|
{
|
|
|
//gravity vector. This value can be changed in runtime
|
|
|
vec2 gravity_vector = vec2(0, -9.8);
|
|
|
|
|
|
//nested struct has to have name "EntitiesData" as templates will be looking for that name
|
|
|
struct EntitiesData
|
|
|
{
|
|
|
//variable length will contain number of entities in batch. Name "length" is essential
|
|
|
uint length;
|
|
|
//assign velocity component to that system. We need only velocity of entity
|
|
|
CVelocity[] celocity;
|
|
|
}
|
|
|
|
|
|
//"onUpdate" callback is called during update process for entity batches
|
|
|
void onUpdate(EntitiesData data)
|
|
|
{
|
|
|
//foreach entity
|
|
|
foreach(i; 0..data.length)
|
|
|
{
|
|
|
//add gravity to entity
|
|
|
data.velocity[i].x += gravity_vector.x;
|
|
|
data.velocity[i].y += gravity_vector.y;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
We have gravity applied to entities, but we need also movement system:
|
|
|
```d
|
|
|
struct MovementSystem
|
|
|
{
|
|
|
//nested struct has to have name "EntitiesData" as templates will be looking for that name
|
|
|
struct EntitiesData
|
|
|
{
|
|
|
//variable length will contain number of entities in batch. Name "length" is essential
|
|
|
uint length;
|
|
|
//assign location component to that system
|
|
|
CLocation[] location;
|
|
|
//assign velocity component to that system
|
|
|
CVelocity[] celocity;
|
|
|
}
|
|
|
|
|
|
//"onUpdate" callback is called during update process for entity batches
|
|
|
void onUpdate(EntitiesData data)
|
|
|
{
|
|
|
//foreach entity
|
|
|
foreach(i; 0..data.length)
|
|
|
{
|
|
|
//move entities by velocity
|
|
|
data.location[i].x += data.velocity[i].x;
|
|
|
data.location[i].y += data.velocity[i].y;
|
|
|
|
|
|
//slow down entities a little bit
|
|
|
data.velocity[i].x *= 0.99;
|
|
|
data.velocity[i].y *= 0.99;
|
|
|
|
|
|
//jump off from floor
|
|
|
if(data.location[i].y < 0 && data.velocity[i].y < 0)
|
|
|
{
|
|
|
//swap velocity vector 'y' direction
|
|
|
data.velocity[i].y = -data.velocity[i].y;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
Now we can register those elements:
|
|
|
```d
|
|
|
//begin registration process
|
|
|
gEntityManager.beginRegister();
|
|
|
|
|
|
//register components
|
|
|
gEntityManager.registerComponent!CLocation;
|
|
|
gEntityManager.registerComponent!CVelocity;
|
|
|
|
|
|
//register systems. Components used by system have to be registered before it
|
|
|
gEntityManager.registerSystem!GravitySystem(0 /*system priority*/);
|
|
|
gEntityManager.registerSystem!MovementSystem(1 /*system priority*/);
|
|
|
|
|
|
//end registration process
|
|
|
gEntityManager.endRegister();
|
|
|
```
|
|
|
|
|
|
### Setup data
|
|
|
Before we could run code we need add some entities. I will also show how you can change system data.
|
|
|
```d
|
|
|
//get gravity system instance
|
|
|
GravitySystem* gravity_system = gEntityManager.getSystem!GravitySystem;
|
|
|
//change gravity vector
|
|
|
graivty_system.gravity_vector = vec2(0, -9.81);
|
|
|
|
|
|
//create new template. Templates are required to adding entities
|
|
|
EntityTemplate* tmpl = gEntityManager.allocateTemplate(
|
|
|
[becsID!CLocation, becsID!CVelocity].staticArray //allocate with those components
|
|
|
);
|
|
|
|
|
|
//Now we will set default value for template velocity component
|
|
|
//Get component from template
|
|
|
CVelocity* tmpl_veclocity = tmpl.getComponent!CVelocity;
|
|
|
//change value
|
|
|
tmpl_velocity.y = 5;
|
|
|
|
|
|
//create component with values for new entity
|
|
|
CLocation loc = CLocation(10,10);
|
|
|
//add new entity
|
|
|
gEntityManager.addEntity(
|
|
|
tmpl, //template to use for new entity
|
|
|
[ComponentRef(&loc, becsID!CLocation)].staticArray //change location component values. Rest of data will be taken from template
|
|
|
);
|
|
|
```
|
|
|
|
|
|
### Update loop
|
|
|
|
|
|
```d
|
|
|
while(1)
|
|
|
{
|
|
|
//start frame
|
|
|
gEntityManager.begin();
|
|
|
|
|
|
//call update process
|
|
|
gEntityManager.update();
|
|
|
|
|
|
//end frame
|
|
|
gEntityManager.end();
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**TODO** |
|
|
\ No newline at end of file |