Skip to content
This repository has been archived by the owner on Oct 4, 2019. It is now read-only.

Commit

Permalink
- Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert G authored and Robert G committed Oct 23, 2017
0 parents commit 94a91ec
Show file tree
Hide file tree
Showing 12 changed files with 1,170 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.dub
docs.json
__dummy.html
*.o
*.obj
decs.exe
dub.selections.json
source/app.d
23 changes: 23 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
164 changes: 164 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/** Works in progress **/

decs
===========

decs is my attempt to build a @nogc D language Entity Component System.
I'm not really an game dev, im trying to learn how an ECS works so some portions of this code can be inefficients or bug prone.

It's inspired by the following projects :

https://github.com/miguelmartin75/anax => C++ ECS
https://github.com/jzhu98/star-entity => D ECS
https://github.com/claudemr/entitysysd => D ECS

## How to build

You have to use [dub](https://code.dlang.org/download) to build the project.

Add this project as a dependency to your **dub.json**:

```json
"dependencies": {
"decs": "~>1.0.0"
}
```

## How to use

### Entity Manager

```cs

import decs;

void main()
{
auto em = new EntityManager();

while(game)
{
em.update(dt);
}

// !important!
em.dispose();
}

```

### Entities

You can create an entity, kill it, invalidate it or activate it (still need some work here).

```cs
auto entity = em.createEntity();

// Notifies all systems that a new entity is alive (check system section to understand this part)
entity.activate();

// Entity is still alive but will be invalid in current scope
entity.invalidate();

// Poor entity :<
entity.kill();
```

### Components

An component must be represented as a struct.

```cs
struct PositionComponent
{
float x, y, z;
}
```

You can add a component to an entity :

```cs
// add
entity.add!PositionComponent(1, 2, 3);

// update (its handled as a pointer)
entity.get!PositionComponent().y = 50;

// check
if(entity.has!PositionComponent())
{
// ...
}
```
### Systems

An system must be a class that inherits **decs.System**.

```cs
class MovementSystem : System
{
public void update(in float delta)
{

}
}
```
There is 2 ways to query entities from your system :

* 1 => Using entity manager **entities!(components...)** function
* 2 => Using the components filter mixin **mixin ComponentsFilter!(components...);**


If you provide an components filter, when an entity is activated, it will be automatically added to the systems whose filters match her components.

```cs
class MovementSystem : System
{
// option 2
mixin ComponentsFilter!(PositionComponent);

public void update(in float deltaTime)
{
// option 1
auto entities = this.m_entityManager.entities!(PositionComponent);

// option 2 (should be more efficient)
foreach(entity; this.m_entities)
{

}
}
}
```
System's update method will be called automatically by the entity manager in the main loop. If you want to handle the update manually, you can set the **System.UpdatePolicy** to manual :

```cs
class MovementSystem : System
{
public this()
{
super(System.UpdatePolicy.Manual);
}
}

// ...
while(game)
{
em.update(dt);

// you have to call it manually (before or after the em.update call)
myMovementSystem.update(dt);
}
```

### Events

wip

## TODOs

* Add **@component** and **@event** UDAs
* Add the possibility to defines systems execution order when using **em.update(dt)**
* Add anexample project
* Improve this readme
11 changes: 11 additions & 0 deletions dub.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "decs",
"authors": [
"aldo"
],
"dependencies": {
"dnogc": "~master"
},
"description": "@nogc D Entity Component System",
"license": "Boost Software License"
}
27 changes: 27 additions & 0 deletions source/decs/Component.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module decs.Component;

struct GlobalComponentCounter
{
static uint counter = 0;
}

/**
* Helper used to get an unique id per component
*/
struct ComponentCounter(Component)
{
private GlobalComponentCounter globalComponentCounter;

public static uint getId() nothrow @safe @nogc
{
static uint counter = -1;

if(counter == -1)
{
counter = globalComponentCounter.counter;
globalComponentCounter.counter++;
}

return counter;
}
}
74 changes: 74 additions & 0 deletions source/decs/ComponentPool.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module decs.ComponentPool;

import dnogc.DynamicArray;

interface IComponentPool
{
public void dispose();
public void expand() nothrow @safe @nogc;
public size_t length() const pure nothrow @safe @nogc;
}

class ComponentPool(T) : IComponentPool
{
private DynamicArray!T m_components;

public this(in size_t poolSize) nothrow @safe @nogc
{
this.m_components = DynamicArray!T(poolSize);
this.m_components.length = poolSize;
}

public void dispose()
{
this.m_components.dispose();
}

public void insert()(auto ref T component) nothrow @safe @nogc
{
this.m_components.insert(component);
}

/**
* Returns the component at the specified index
* Params:
* index :
*/
public T* get(in uint index) pure nothrow @trusted @nogc
{
assert(index < this.m_components.length);

immutable ptr = index * T.sizeof;

auto data = this.m_components.ptr;

return cast(T*)data[ptr..(ptr + T.sizeof)];
}

/**
* Sets the value of the component at the specified index
* Params:
* index :
* component :
*/
public void set(in uint index, ref T component) pure nothrow @safe @nogc
{
assert(index < this.m_components.length);

this.m_components[index] = component;
}

/**
* Expands the pool with an empty value
*/
public void expand() nothrow @safe @nogc
{
this.m_components.insert(T());
}

@property
public size_t length() const pure nothrow @safe @nogc
{
return this.m_components.length;
}
}
Loading

0 comments on commit 94a91ec

Please sign in to comment.