You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is our implementation of the "Entity Component System" model in Go. It was designed to be used in `engo`, however
5
+
This is our implementation of the "Entity Component System" model in Go. It was designed to be used in `engo`, however
6
6
it is not dependent on any other packages so is able to be used wherever!
7
7
8
8
## Basics
9
9
In the Entity Component System paradigm, you have three elements;
10
10
11
11
* Entities
12
12
* Components
13
-
* Systems.
13
+
* Systems.
14
14
15
-
In our implementation, we use the type `World` to work with those `System`s. Each `System` can have references to any number (including 0) of entities. And each `Entity` can have as many `Component`s as desired.
15
+
In our implementation, we use the type `World` to work with those `System`s. Each `System` can have references to any number (including 0) of entities. And each `Entity` can have as many `Component`s as desired.
16
16
17
17
An example of creating a `World`, adding a `System` to it, and update all systems
18
18
```go
19
-
// Declare the world - you can also use "var world ecs.World"
19
+
// Declare the world - you can also use "var world ecs.World"
20
20
world:= ecs.World{}
21
21
22
-
// You can add as many Systems here as you like. The RenderSystem provided by `engo` is just an example.
22
+
// You can add as many Systems here as you like. The RenderSystem provided by `engo` is just an example.
23
23
world.AddSystem(&engo.RenderSystem{})
24
24
25
25
// This will usually be called within the game-loop, in order to update all Systems on every frame.
@@ -39,10 +39,10 @@ type System interface {
39
39
}
40
40
```
41
41
42
-
What does this say? It needs to have an `Update` method (which is called from `world.Update`), and it needs to have a `Remove(ecs.BasicEntity)` method. Why require a Remove method, but not an Add method? Because there's no 'generic' `Add` method (the parameters may change), while in order to remove something, all you need it the unique identifier (as provided by the `BasicEntity`).
42
+
What does this say? It needs to have an `Update` method (which is called from `world.Update`), and it needs to have a `Remove(ecs.BasicEntity)` method. Why require a Remove method, but not an Add method? Because there's no 'generic' `Add` method (the parameters may change), while in order to remove something, all you need it the unique identifier (as provided by the `BasicEntity`).
43
43
44
44
### Initialization
45
-
Optionally, your `System` may implement the `Initializer` interface, which allows you to do initialization for the given `World`. Basically, it allows you to initialize values, without having to call the function manually before adding it to the `World`. Whenever you add a `System` (one that implements the `Initializer` interface) to the world, the `New` method will be called.
45
+
Optionally, your `System` may implement the `Initializer` interface, which allows you to do initialization for the given `World`. Basically, it allows you to initialize values, without having to call the function manually before adding it to the `World`. Whenever you add a `System` (one that implements the `Initializer` interface) to the world, the `New` method will be called.
46
46
47
47
```go
48
48
typeInitializerinterface {
@@ -53,7 +53,7 @@ type Initializer interface {
53
53
```
54
54
55
55
### Priority
56
-
Optionally, your `System` may implement the `Prioritizer` interface, which allows the `World` to sort the `System`s based on that priority. If omitted, a value of `0` is assumed.
56
+
Optionally, your `System` may implement the `Prioritizer` interface, which allows the `World` to sort the `System`s based on that priority. If omitted, a value of `0` is assumed.
57
57
58
58
```go
59
59
typePrioritizerinterface {
@@ -65,7 +65,7 @@ type Prioritizer interface {
65
65
## Entities and Components
66
66
Where do the entities come in? All game-logic has to be done within `System`s (the `Update` method, to be precise)). `Component`s store data (which is used by those `System`s). An `Entity` is no more than a wrapper which combines multiple `Component`s and adds a unique identifier to the whole. This unique identifier is nothing magic: simply an incrementing integer value - nothing to worry about.
67
67
68
-
> Because the precise definition of those `Component`s can vary, this `ecs` package provides no `Component`s -- we only provide examples here. The `engo.io/engo/common` package offers lots of `Component`s and `System`s to work with, out of the box.
68
+
> Because the precise definition of those `Component`s can vary, this `ecs` package provides no `Component`s -- we only provide examples here. The `github.com/EngoEngine/engo/common` package offers lots of `Component`s and `System`s to work with, out of the box.
69
69
70
70
Let's view an example:
71
71
@@ -87,7 +87,7 @@ type Player struct {
87
87
}
88
88
```
89
89
90
-
Here, the type `Player` is made out of three elements: the unique identifier (`ecs.BasicEntity`) and two `Component`s. A `System` may make use of one or more of those `Component`s. Which are required, is defined by the `Add` method on that `System`.
90
+
Here, the type `Player` is made out of three elements: the unique identifier (`ecs.BasicEntity`) and two `Component`s. A `System` may make use of one or more of those `Component`s. Which are required, is defined by the `Add` method on that `System`.
91
91
92
92
Let's view a few examples:
93
93
@@ -111,7 +111,7 @@ for _, system := range world.Systems() {
111
111
112
112
// Use a type-switch to figure out which System is which
@@ -121,13 +121,13 @@ for _, system := range world.Systems() {
121
121
}
122
122
```
123
123
124
-
That is all there is to it.
124
+
That is all there is to it.
125
125
126
126
## Custom Systems - How to save Entities?
127
127
128
-
You more than likely will want to create `System`s yourself. We will now go in depth on what you should do when defining your own `Add` method for your `System`. As seen above, you can create any number (and type of) parameters you want.
128
+
You more than likely will want to create `System`s yourself. We will now go in depth on what you should do when defining your own `Add` method for your `System`. As seen above, you can create any number (and type of) parameters you want.
129
129
130
-
> We do ask you to let *the first argument* be of type `*ecs.BasicEntity` - as a general rule.
130
+
> We do ask you to let *the first argument* be of type `*ecs.BasicEntity` - as a general rule.
131
131
132
132
Your `System` should include an array, slice or map in which to store those entities. Now it is important to note that you're not receiving entities per se -- you are receiving references to the `Component`s you need. The actual `Entity` (type `Player` in our example) may contain way more `Component`s. You will most-likely want to create a struct for you to store those pointers in. An example:
> As a convention, please include "System" in the name of your `System` -- at the end. When you define a struct (which contains pointers, as opposed to the `Player` struct we created earlier), please replace that `System` part with `Entity`. You should **only** use this newly-created struct in your similarly-named `System`. You will usually *never* want to export that `Entity` definition, as it is only being used in that `System`. If your system would be called `BallMovementSystem`, then your struct would be called `ballMovementEntity`.
150
+
> As a convention, please include "System" in the name of your `System` -- at the end. When you define a struct (which contains pointers, as opposed to the `Player` struct we created earlier), please replace that `System` part with `Entity`. You should **only** use this newly-created struct in your similarly-named `System`. You will usually *never* want to export that `Entity` definition, as it is only being used in that `System`. If your system would be called `BallMovementSystem`, then your struct would be called `ballMovementEntity`.
151
151
152
152
### Removing Entities from your System
153
-
Your `System` must implement the `Remove` method as specified by the `System` interface. Whenever you start storing entities, you should define this method in such a way, that it removes the custom-created non-exported `Entity`-struct from the array, slice or map. An `ecs.BasicEntity` is given for you to figure out which element in the array, slice or map it is.
153
+
Your `System` must implement the `Remove` method as specified by the `System` interface. Whenever you start storing entities, you should define this method in such a way, that it removes the custom-created non-exported `Entity`-struct from the array, slice or map. An `ecs.BasicEntity` is given for you to figure out which element in the array, slice or map it is.
154
154
155
155
```go
156
156
// Remove removes the Entity from the System. This is what most Remove methods will look like
> Even though that a `map` looks easier, if you want to loop over that `map` each frame, writing those additional lines to use a `slice` instead, is definitely worth it in terms of runtime performance. Iterating over a `map` is a lot slower.
180
+
> Even though that a `map` looks easier, if you want to loop over that `map` each frame, writing those additional lines to use a `slice` instead, is definitely worth it in terms of runtime performance. Iterating over a `map` is a lot slower.
181
181
182
182
## Custom Systems - The Update method
183
-
Whatever your `System` does on the `Update` method, is up to you. Each `System` is unique in that sense. If you're storing entities, then you might want to loop over them each frame. Again, this depends on your use-case.
183
+
Whatever your `System` does on the `Update` method, is up to you. Each `System` is unique in that sense. If you're storing entities, then you might want to loop over them each frame. Again, this depends on your use-case.
0 commit comments