-
Notifications
You must be signed in to change notification settings - Fork 0
/
world.go
124 lines (104 loc) · 2.47 KB
/
world.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package ecs
import (
"runtime"
"sort"
)
// World contains a bunch of Entitys, and a bunch of Systems. It is
// the recommended way to run ecs
type World struct {
entities map[string]*Entity
systems Systemers
isSetup bool
serial bool
}
// New initialises the World
func (w *World) New() {
if w.isSetup {
return
}
w.entities = make(map[string]*Entity)
/*
// Default WorldBounds values
WorldBounds.Max = Point{Width(), Height()}
*/
// Short-circuit bypass if there's only 1 core
if runtime.NumCPU() == 1 {
w.serial = true
} else {
w.serial = false
}
w.isSetup = true
}
// AddEntity adds a new Entity to the World, and its required Systems
func (w *World) AddEntity(entity *Entity) {
w.entities[entity.ID()] = entity
for _, system := range w.systems {
if entity.DoesRequire(system.Type()) {
system.AddEntity(entity)
}
}
}
// RemoveEntity removes an Entity from the World and its required Systems
func (w *World) RemoveEntity(entity *Entity) {
for _, system := range w.systems {
if entity.DoesRequire(system.Type()) {
system.RemoveEntity(entity)
}
}
delete(w.entities, entity.ID())
}
// AddSystem adds a new System to the World, and then sorts them based on Priority
func (w *World) AddSystem(system Systemer) {
system.New(w)
w.systems = append(w.systems, system)
sort.Sort(w.systems)
}
// Entities returns the list of Entities
func (w *World) Entities() []*Entity {
entities := make([]*Entity, len(w.entities))
i := 0
for _, v := range w.entities {
entities[i] = v
i++
}
return entities
}
// Systems returns a list of Systems
func (w *World) Systems() []Systemer {
return w.systems
}
func (w *World) HasSystem(systemType string) bool {
for _, s := range w.systems {
if s.Type() == systemType {
return true
}
}
return false
}
// Update is called on each frame, with dt being the time difference in seconds since the last Update call
func (w *World) Update(dt float32) {
complChan := make(chan struct{})
for _, system := range w.Systems() {
system.Pre()
entities := system.Entities()
count := len(entities)
// Calling them serial / in parallel, depending on the settings
if w.serial || !system.RunInParallel() {
for _, entity := range entities {
system.Update(entity, dt)
}
} else {
for _, entity := range entities {
go func(entity *Entity) {
system.Update(entity, dt)
complChan <- struct{}{}
}(entity)
}
for ; count > 0; count-- {
<-complChan
}
}
system.Post()
}
close(complChan)
}