]> git.r.bdr.sh - rbdr/serpentity/blame - lib/serpentity/serpentity.js
Adds priorities
[rbdr/serpentity] / lib / serpentity / serpentity.js
CommitLineData
85861d67
BB
1require("neon");
2
3/*
4Serpentity is a simple entity framework inspired by Ash.
5
6Usage:
7
c2c83a18 8 require('serpentity');
85861d67
BB
9
10## Instantiating an engine
11
c2c83a18 12 var engine = Serpentity();
85861d67 13
42c62ebf
BB
14Add entities or systems, systems are added with a priority (the smaller
15the number, the earlier it will be called):
85861d67
BB
16
17 engine.addEntity(entityFactory());
42c62ebf 18 engine.addSystem(new GameSystem(), priority);
85861d67
BB
19
20Update all systems:
21
22 engine.update(dt);
23
24Remove entities or systems:
25
26 engine.removeEntity(entityReference);
27 engine.removeSystem(systemReference);
28
29## Creating Entities
30
31Entities are the basic object of Serpentity, and they do nothing.
32
971ff307 33 var entity = new Serpentity.Entity();
85861d67
BB
34
35All the behavior is added through components
36
37## Creating Components
38
39Components define data that we can add to an entity. This data will
40eventually be consumed by "Systems"
41
42 Class("PositionComponent").inherits(Serpentity.Component)({
43 prototype : {
44 x : 0,
45 y : 0
46 }
47 });
48
49You can add components to entities by using the add method:
50
51 entity.add(new PositionComponent());
52
53
54Systems can refer to entities by requesting nodes.
55
56## Working with Nodes
57
58Nodes are sets of components that you define, so your system can require
59entities that always follow the API defined in the node.
60
61 Class("MovementNode").inherits(Serpentity.Node)({
62 types : {
63 position : PositionComponent,
64 motion : MotionComponent
65 }
66 });
67
68You can then request an array of all the nodes representing entities
69that comply with that API
70
71 engine.getNodes(MovementNode);
72
73## Creating Systems
74
75Systems are called on every update, and they use components through nodes.
76
c2c83a18
BB
77 Class("TestSystem").inherits(Serpentity.System)({
78 prototype : {
79 added : function added(engine){
80 this.nodeList = engine.getNodes(MovementNode);
81 },
82 removed : function removed(engine){
83 this.nodeList = undefined;
84 }
85 update : function update(dt){
86 this.nodeList.forEach(function (node) {
87 console.log("Current position is: " + node.position.x + "," + node.position.y);
88 });
89 }
85861d67 90 }
c2c83a18 91 });
85861d67
BB
92
93## That's it
94
95Just run `engine.update(dt)` in your game loop :D
96
97*/
98Class("Serpentity")({
99 prototype : {
100 systems : null,
101 nodeCollections : null,
102 entities : null,
103
104 init : function init(config) {
105 var property;
106
107 config = config || {};
108
109 this.systems = [];
110 this.entities = [];
111 this.nodeCollections = {};
112
113 for (property in config) {
114 if (config.hasOwnProperty(property)) {
115 this[property] = config[property];
116 }
117 }
118 },
119
120 /*
121 * Adds a system to the engine, so its update method will be called
122 * with the others. Triggers added hook.
123 *
124 * returns true if added succesfully, false if already added
125 */
42c62ebf
BB
126 addSystem : function addSystem(system, priority) {
127 var lastIndex, found;
128
85861d67
BB
129 if (this.systems.indexOf(system) >= 0) {
130 return false;
131 }
42c62ebf
BB
132
133 system.priority = priority;
134
135 found = false;
136 lastIndex = 0;
137
138 this.systems.some(function findPriority(existingSystem, i) {
139 lastIndex = i;
140 if (existingSystem.priority >= system.priority) {
141 found = true;
142 return true;
143 }
144 });
145
146 if (!found) {
147 lastIndex += 1
148 }
149
150 this.systems.splice(lastIndex, 0, system);
85861d67
BB
151 system.added(this);
152 return true;
153 },
154
155 /*
156 * Removes a system from the engine, so its update method will no
157 * longer will be called. Triggers the removed hook.
158 *
159 * returns true if removed succesfully, false if already added
160 */
161 removeSystem : function removeSystem(system) {
162 var position;
163
164 position = this.systems.indexOf(system);
165 if (position >= 0) {
166 this.systems[position].removed(this);
167 this.systems.splice(position, 1);
168 return true;
169 }
170
171 return false;
172 },
173
174 /*
175 * Adds an entity to the engine, adds to existing node collections
176 *
177 * returns true if added, false if already there
178 */
179 addEntity : function addEntity(entity) {
180 var property;
181
182 if (this.entities.indexOf(entity) >= 0) {
183 return false;
184 }
185 this.entities.push(entity);
186
187 for (property in this.nodeCollections) {
188 if (this.nodeCollections.hasOwnProperty(property)) {
189 this.nodeCollections[property].add(entity);
190 }
191 }
192 return true;
193 },
194
195 /*
196 * Removes entity from system, removing from all node collections
197 *
198 * returns true if removed, false if not present
199 */
200 removeEntity : function removeEntity(entity) {
201 var position;
202
203 position = this.entities.indexOf(entity);
204 if (position >= 0) {
205 for (property in this.nodeCollections) {
206 if (this.nodeCollections.hasOwnProperty(property)) {
207 this.nodeCollections[property].remove(entity);
208 }
209 }
210
211 this.entities.splice(position, 1);
212 return true;
213 }
214
215 return false;
216 },
217
218 /*
219 * Given a Node Class, retrieves a list of all the nodes for each
220 * applicable entity.
221 */
222 getNodes : function getNodes(nodeType) {
223 var nodeCollection;
224
225 if (this.nodeCollections.hasOwnProperty(nodeType)) {
226 return this.nodeCollections[nodeType].nodes;
227 }
228
229 nodeCollection = new Serpentity.NodeCollection({
230 type : nodeType,
231 });
232 this.nodeCollections[nodeType] = nodeCollection;
233
234 this.entities.forEach(function (entity) {
235 nodeCollection.add(entity);
236 });
237
238 return nodeCollection.nodes;
239 },
240
241 /*
242 * Calls update for every loaded system.
243 */
244 update : function update(dt) {
245 this.systems.forEach(function (system) {
246 system.update(dt);
247 });
248 }
249 }
250});
251
252require("./component.js");
253require("./entity.js");
254require("./node.js");
255require("./node_collection.js");
256require("./system.js");