-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWorld.java
200 lines (172 loc) · 5.54 KB
/
World.java
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package ecs;
import ecs.debug.WorldDebugger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.util.Comparator;
import ecs.debug.$Entity;
public class World {
//These modes are used for internal updates on ECS system
public static final int MODE_ADD = 0; //When add a new Entity
public static final int MODE_REMOVE = 1; //When remove an Entity
public static final int MODE_UPDATE = 2; //When update the component list of an Entity
private List<System> systems = new ArrayList<>(); //List of systems for process entities
private List<Entity> entities = new ArrayList<>(); //List of actived entities, used for update new added systems
private List<Entity> entitiesToRemove = new ArrayList<>(); //List of entities to remove before the next update
private int current_max_id = 0; //Current id, increased by one for each new entity added in the World.
private WorldDebugger debugger = new WorldDebugger();
public List<Entity> getEntities() {
return entities;
}
//Alias to quick add entities
public <T extends Entity> T $(T entity) {
addEntity(entity);
return entity;
}
//Alias to quick add multiple systems
public <T extends System> void $(T... systems) {
for (T system : systems) {
addSystem(system);
}
}
//Alias to quick add systems
public <T extends System> T $(T system) {
addSystem(system);
return system;
}
//Alias to quick get systems
public <T extends System> T $(Class<T> systemType) {
return getSystem(systemType);
}
//Search for a system by the given class
public <T extends System> T getSystem(Class<T> systemType) {
for (int i = 0; i < systems.size(); i++) {
if (systems.get(i).getClass().getName().hashCode() == systemType.getName().hashCode()) {
return (T) systems.get(i);
}
}
return null;
}
//Fill the given system with entities it can process, and insert it into the World
public void addSystem(System system) {
for (Entity entity : entities) {
if (system.canProcess(entity)) {
system.entities.add(entity);
}
}
systems.add(system);
debugger.systems.put(system, 0L);
}
//Remove a system from the world
public void removeSystem(System system) {
systems.remove(system);
}
//Remove a system from the world that is instance of the given class
public <T> void removeSystemByType(Class<T> systemClass) {
for (int i = 0; i < systems.size(); i++) {
if (systems.get(i).getClass() instanceof T) {
systems.remove(i);
break;
}
}
}
//Get an entity by the ID, no longer recommended, because it generate iterations in the system
public Entity getEntityById(int entityId) {
for (int i = 0; i < entities.size(); i++) {
if (entities.get(i).getId() == entityId) {
return entities.get(i);
}
}
return null;
}
//Add a entity to the world after setup it
public void addEntity(Entity entity) {
entity.setWorld(this);
entity.setId(++current_max_id);
entities.add(entity);
entity.setActived(true);
onUpdateEntities(entity, MODE_ADD); //Call to the system that an new entity have added, for insert it in the required systems
}
//Add multiple entities to the world
public void addEntities(Entity... entities) {
for (Entity entity : entities) {
addEntity(entity);
}
}
//Put an entity in the remove list
public void removeEntity(Entity entity) {
entitiesToRemove.add(entity);
entity.setActived(false);
}
//Call the system for each entities modification (ADD, UPDATE, and REMOVE)
public void onUpdateEntities(Entity e, int mode) {
for (System system : systems) {
if (system.canProcess(e)) {
if (mode == MODE_ADD) {
system.entities.add(e);
} else if (mode == MODE_REMOVE) {
system.entities.remove(e);
} else if (mode == MODE_UPDATE) {
system.entities.remove(e);
if (system.canProcess(e)) {
system.entities.add(e);
}
}
}
}
}
//Called for update the ECS, it will call process() for each entity in each systems entity lists
public void update(float delta) {
debugger.iterations = 0;
for (System system : systems) {
debugger.start();
system.start();
for (Entity entity : system.entities) {
system._process(this, entity, delta);
debugger.iterations++;
}
system.end();
debugger.end(system);
}
for (Entity entity : entitiesToRemove) {
entities.remove(entity);
onUpdateEntities(entity, MODE_REMOVE);
}
entitiesToRemove.clear();
}
//Returns the last iteration count (Number of time that process() is called)
// public int getIterationCount() {
// return iterationCount;
// }
//Number of entities in the world
public int getEntitiesCount() {
return entities.size();
}
//Number of systems in the world
public int getSystemCount() {
return systems.size();
}
public <T extends Map.Entry<System, Long>> String log() {
String log = "WORLD DEBUGER\n";
log += "Entity count: "+getEntitiesCount()+"\n";
log += "Iterations: "+debugger.iterations+"\n";
log += "Systems duration, in nanos:\n";
List<T> list = new ArrayList<>(debugger.systems.entrySet());
Collections.sort(list, new Comparator<T>() {
@Override
public int compare(T a, T b) {
return (int)(b.getValue() - a.getValue());
}
});
for (T entry : list) {
log += "- "+entry.getKey().getClass().getName() + ": " + entry.getValue()+"\n";
}
for (Entity entity : entities) {
if (entity instanceof $Entity) {
log += (($Entity)entity).log();
}
}
return log;
}
}