]> git.r.bdr.sh - rbdr/serpentity/blob - dist/serpentity.js
Merge branch 'release/2.0.0'
[rbdr/serpentity] / dist / serpentity.js
1 (function webpackUniversalModuleDefinition(root, factory) {
2 if(typeof exports === 'object' && typeof module === 'object')
3 module.exports = factory();
4 else if(typeof define === 'function' && define.amd)
5 define([], factory);
6 else if(typeof exports === 'object')
7 exports["Serpentity"] = factory();
8 else
9 root["Serpentity"] = factory();
10 })(this, function() {
11 return /******/ (function(modules) { // webpackBootstrap
12 /******/ // The module cache
13 /******/ var installedModules = {};
14 /******/
15 /******/ // The require function
16 /******/ function __webpack_require__(moduleId) {
17 /******/
18 /******/ // Check if module is in cache
19 /******/ if(installedModules[moduleId])
20 /******/ return installedModules[moduleId].exports;
21 /******/
22 /******/ // Create a new module (and put it into the cache)
23 /******/ var module = installedModules[moduleId] = {
24 /******/ i: moduleId,
25 /******/ l: false,
26 /******/ exports: {}
27 /******/ };
28 /******/
29 /******/ // Execute the module function
30 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 /******/
32 /******/ // Flag the module as loaded
33 /******/ module.l = true;
34 /******/
35 /******/ // Return the exports of the module
36 /******/ return module.exports;
37 /******/ }
38 /******/
39 /******/
40 /******/ // expose the modules object (__webpack_modules__)
41 /******/ __webpack_require__.m = modules;
42 /******/
43 /******/ // expose the module cache
44 /******/ __webpack_require__.c = installedModules;
45 /******/
46 /******/ // identity function for calling harmony imports with the correct context
47 /******/ __webpack_require__.i = function(value) { return value; };
48 /******/
49 /******/ // define getter function for harmony exports
50 /******/ __webpack_require__.d = function(exports, name, getter) {
51 /******/ if(!__webpack_require__.o(exports, name)) {
52 /******/ Object.defineProperty(exports, name, {
53 /******/ configurable: false,
54 /******/ enumerable: true,
55 /******/ get: getter
56 /******/ });
57 /******/ }
58 /******/ };
59 /******/
60 /******/ // getDefaultExport function for compatibility with non-harmony modules
61 /******/ __webpack_require__.n = function(module) {
62 /******/ var getter = module && module.__esModule ?
63 /******/ function getDefault() { return module['default']; } :
64 /******/ function getModuleExports() { return module; };
65 /******/ __webpack_require__.d(getter, 'a', getter);
66 /******/ return getter;
67 /******/ };
68 /******/
69 /******/ // Object.prototype.hasOwnProperty.call
70 /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
71 /******/
72 /******/ // __webpack_public_path__
73 /******/ __webpack_require__.p = "";
74 /******/
75 /******/ // Load entry module and return exports
76 /******/ return __webpack_require__(__webpack_require__.s = 5);
77 /******/ })
78 /************************************************************************/
79 /******/ ([
80 /* 0 */
81 /***/ (function(module, exports, __webpack_require__) {
82
83 "use strict";
84
85
86 /*
87 * Components store data. Nothing to say here really, just
88 * inherit and add a prototype, or don't even inherit, see?
89 * It's just an empty class, so what I'm trying to say is your
90 * components can be any class whatsoever.
91 */
92
93 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
94
95 var Component = function Component(config) {
96 _classCallCheck(this, Component);
97
98 Object.assign(this, config);
99 };
100
101 module.exports = Component;
102
103 /***/ }),
104 /* 1 */
105 /***/ (function(module, exports, __webpack_require__) {
106
107 "use strict";
108
109
110 /*
111 * The entity gives the entity framework its name. It exists only
112 * to hold components.
113 */
114
115 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
116
117 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
118
119 var Entity = function () {
120 function Entity(config) {
121 _classCallCheck(this, Entity);
122
123 this._componentKeys = [];
124 this._components = [];
125
126 Object.assign(this, config);
127 }
128
129 /*
130 * Adds a component to the entity.
131 *
132 * returns true if added, false if already present
133 */
134
135
136 _createClass(Entity, [{
137 key: 'addComponent',
138 value: function addComponent(component) {
139
140 if (this._componentKeys.indexOf(component.constructor) >= 0) {
141 return false;
142 }
143 this._componentKeys.push(component.constructor);
144 this._components.push(component);
145 return true;
146 }
147
148 /*
149 * returns true if component is included, false otherwise
150 */
151
152 }, {
153 key: 'hasComponent',
154 value: function hasComponent(componentClass) {
155
156 if (this._componentKeys.indexOf(componentClass) >= 0) {
157 return true;
158 }
159 return false;
160 }
161
162 /*
163 * returns the component associated with that key
164 */
165
166 }, {
167 key: 'getComponent',
168 value: function getComponent(componentClass) {
169
170 var position = this._componentKeys.indexOf(componentClass);
171 if (position >= 0) {
172 return this._components[position];
173 }
174 }
175 }]);
176
177 return Entity;
178 }();
179
180 module.exports = Entity;
181
182 /***/ }),
183 /* 2 */
184 /***/ (function(module, exports, __webpack_require__) {
185
186 "use strict";
187
188
189 /*
190 * A node describes a set of components in order to describe entities
191 * that include them.
192 */
193
194 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
195
196 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
197
198 var Node = function () {
199 _createClass(Node, null, [{
200 key: 'matches',
201
202
203 /*
204 * Returns true if the given entity matches the defined protocol,
205 * false otherwise
206 */
207 value: function matches(entity) {
208
209 var typeNames = Object.keys(this.types);
210
211 var _iteratorNormalCompletion = true;
212 var _didIteratorError = false;
213 var _iteratorError = undefined;
214
215 try {
216 for (var _iterator = typeNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
217 var typeName = _step.value;
218
219
220 var type = this.types[typeName];
221 var matched = false;
222
223 if (entity.hasComponent(type)) {
224 matched = true;
225 }
226
227 if (!matched) {
228 return false;
229 }
230 }
231 } catch (err) {
232 _didIteratorError = true;
233 _iteratorError = err;
234 } finally {
235 try {
236 if (!_iteratorNormalCompletion && _iterator.return) {
237 _iterator.return();
238 }
239 } finally {
240 if (_didIteratorError) {
241 throw _iteratorError;
242 }
243 }
244 }
245
246 return true;
247 }
248 }]);
249
250 function Node(config) {
251 _classCallCheck(this, Node);
252
253 this.types = {};
254
255 Object.assign(this, config);
256 }
257
258 return Node;
259 }();
260
261 module.exports = Node;
262
263 /***/ }),
264 /* 3 */
265 /***/ (function(module, exports, __webpack_require__) {
266
267 "use strict";
268
269
270 /*
271 * Node Collections contain nodes, in order to keep the lists of nodes
272 * that belong to each type.
273 *
274 * It has a type which is the class name of the node, and an array of
275 * instances of that class.
276 */
277
278 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
279
280 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
281
282 var NodeCollection = function () {
283 function NodeCollection(config) {
284 _classCallCheck(this, NodeCollection);
285
286 this.nodes = [];
287 this.type = null;
288
289 Object.assign(this, config);
290 }
291
292 /*
293 * Creates a node for an entity if it matches, and adds it to the
294 * node list.
295 *
296 * Returns true if added, false otherwise.
297 */
298
299
300 _createClass(NodeCollection, [{
301 key: 'add',
302 value: function add(entity) {
303
304 if (this.type.matches(entity) && !this._entityExists(entity)) {
305
306 var node = new this.type({});
307 var types = this.type.types;
308 var typeNames = Object.keys(types);
309
310 node.entity = entity;
311
312 var _iteratorNormalCompletion = true;
313 var _didIteratorError = false;
314 var _iteratorError = undefined;
315
316 try {
317 for (var _iterator = typeNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
318 var typeName = _step.value;
319
320 node[typeName] = entity.getComponent(types[typeName]);
321 }
322 } catch (err) {
323 _didIteratorError = true;
324 _iteratorError = err;
325 } finally {
326 try {
327 if (!_iteratorNormalCompletion && _iterator.return) {
328 _iterator.return();
329 }
330 } finally {
331 if (_didIteratorError) {
332 throw _iteratorError;
333 }
334 }
335 }
336
337 this.nodes.push(node);
338
339 return true;
340 }
341
342 return false;
343 }
344
345 /*
346 * Removes an entity by removing its related node from the list of nodes
347 *
348 * returns true if it was removed, false otherwise.
349 */
350
351 }, {
352 key: 'remove',
353 value: function remove(entity) {
354
355 var foundIndex = -1;
356
357 var found = this.nodes.some(function (node, i) {
358
359 if (node.entity === entity) {
360 foundIndex = i;
361 return true;
362 }
363 });
364
365 if (found) {
366 this.nodes.splice(foundIndex, 1);
367 }
368
369 return found;
370 }
371
372 /*
373 * Checks whether we already have nodes for this entity.
374 */
375
376 }, {
377 key: '_entityExists',
378 value: function _entityExists(entity) {
379
380 var found = false;
381
382 var _iteratorNormalCompletion2 = true;
383 var _didIteratorError2 = false;
384 var _iteratorError2 = undefined;
385
386 try {
387 for (var _iterator2 = this.nodes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
388 var node = _step2.value;
389
390 if (node.entity === entity) {
391 found = true;
392 }
393 }
394 } catch (err) {
395 _didIteratorError2 = true;
396 _iteratorError2 = err;
397 } finally {
398 try {
399 if (!_iteratorNormalCompletion2 && _iterator2.return) {
400 _iterator2.return();
401 }
402 } finally {
403 if (_didIteratorError2) {
404 throw _iteratorError2;
405 }
406 }
407 }
408
409 return found;
410 }
411 }]);
412
413 return NodeCollection;
414 }();
415
416 module.exports = NodeCollection;
417
418 /***/ }),
419 /* 4 */
420 /***/ (function(module, exports, __webpack_require__) {
421
422 "use strict";
423
424
425 /*
426 * Systems contain most of the logic, and work with nodes in order to
427 * act and change their values.
428 *
429 * You usually want to inherit from this class and override the
430 * three methods. They are shown here to document the interface.
431 */
432
433 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
434
435 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
436
437 var System = function () {
438 function System() {
439 _classCallCheck(this, System);
440 }
441
442 _createClass(System, [{
443 key: 'added',
444
445
446 /*
447 * This will be run when the system is added to the engine
448 */
449 value: function added() {}
450 // Override with added(engine)
451 // Receives an instance of the serpentity engine
452
453
454 /*
455 * This will be run when the system is removed from the engine
456 */
457
458 }, {
459 key: 'removed',
460 value: function removed() {}
461 // Override with removed(engine)
462 // Receives an instance of the serpentity engine
463
464
465 /*
466 * This will run every time the engine's update method is called
467 */
468
469 }, {
470 key: 'update',
471 value: function update() {
472 // Override with update(dt)
473 // Receives a delta of the time
474 }
475 }]);
476
477 return System;
478 }();
479
480 module.exports = System;
481
482 /***/ }),
483 /* 5 */
484 /***/ (function(module, exports, __webpack_require__) {
485
486 "use strict";
487
488
489 /*
490 Serpentity is a simple entity framework inspired by Ash.
491
492 Usage:
493
494 const Serpentity = require('serpentity');
495
496 ## Instantiating an engine
497
498 const engine = new Serpentity();
499
500 Add entities or systems, systems are added with a priority (the smaller
501 the number, the earlier it will be called):
502
503 engine.addEntity(entityFactory());
504 engine.addSystem(new GameSystem(), priority);
505
506 Update all systems:
507
508 engine.update(dt);
509
510 Remove entities or systems:
511
512 engine.removeEntity(entityReference);
513 engine.removeSystem(systemReference);
514
515 ## Creating Entities
516
517 Entities are the basic object of Serpentity, and they do nothing.
518
519 const entity = new Serpentity.Entity();
520
521 All the behavior is added through components
522
523 ## Creating Components
524
525 Components define data that we can add to an entity. This data will
526 eventually be consumed by "Systems"
527
528 const PositionComponent = class PositionComponent extends Serpentity.Component {
529 constructor(config) {
530
531 this.x = 0;
532 this.y = 0;
533
534 super(config);
535 }
536 };
537
538 You can add components to entities by using the add method:
539
540 entity.addComponent(new PositionComponent());
541
542
543 Systems can refer to entities by requesting nodes.
544
545 ## Working with Nodes
546
547 Nodes are sets of components that you define, so your system can require
548 entities that always follow the API defined in the node.
549
550 const MovementNode = class MovementNode extends Serpentity.Node;
551 MovementNode.position = PositionComponent;
552 MovementNode.motion = MotionComponent;
553
554 You can then request an array of all the nodes representing entities
555 that comply with that API
556
557 engine.getNodes(MovementNode);
558
559 ## Creating Systems
560
561 Systems are called on every update, and they use components through nodes.
562
563 const TestSystem = class TestSystem extends Serpentity.System {
564 added(engine){
565
566 this.nodeList = engine.getNodes(MovementNode);
567 }
568
569 removed(engine){
570
571 this.nodeList = undefined;
572 }
573
574 update(dt){
575
576 for (const node of this.nodeList) {
577 console.log(`Current position is: ${node.position.x},${node.position.y}`);
578 }
579 }
580 };
581
582 ## That's it
583
584 Just run `engine.update(dt)` in your game loop :D
585
586 */
587
588 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
589
590 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
591
592 var Serpentity = function () {
593 function Serpentity(config) {
594 _classCallCheck(this, Serpentity);
595
596 this.systems = [];
597 this.entities = [];
598 this._nodeCollections = [];
599 this._nodeCollectionKeys = [];
600
601 Object.assign(this, config);
602 }
603
604 /*
605 * Adds a system to the engine, so its update method will be called
606 * with the others. Triggers added hook.
607 *
608 * returns true if added succesfully, false if already added
609 */
610
611
612 _createClass(Serpentity, [{
613 key: 'addSystem',
614 value: function addSystem(system, priority) {
615
616 if (this.systems.indexOf(system) >= 0) {
617 return false;
618 }
619
620 system.priority = priority;
621
622 var lastIndex = 0;
623
624 var found = this.systems.some(function (existingSystem, i) {
625
626 lastIndex = i;
627 if (existingSystem.priority >= system.priority) {
628 return true;
629 }
630 });
631
632 if (!found) {
633 lastIndex += 1;
634 }
635
636 this.systems.splice(lastIndex, 0, system);
637 system.added(this);
638 return true;
639 }
640
641 /*
642 * Removes a system from the engine, so its update method will no
643 * longer will be called. Triggers the removed hook.
644 *
645 * returns true if removed succesfully, false if already added
646 */
647
648 }, {
649 key: 'removeSystem',
650 value: function removeSystem(system) {
651
652 var position = this.systems.indexOf(system);
653 if (position >= 0) {
654 this.systems[position].removed(this);
655 this.systems.splice(position, 1);
656 return true;
657 }
658
659 return false;
660 }
661
662 /*
663 * Adds an entity to the engine, adds to existing node collections
664 *
665 * returns true if added, false if already there
666 */
667
668 }, {
669 key: 'addEntity',
670 value: function addEntity(entity) {
671
672 if (this.entities.indexOf(entity) >= 0) {
673 return false;
674 }
675 this.entities.push(entity);
676
677 var _iteratorNormalCompletion = true;
678 var _didIteratorError = false;
679 var _iteratorError = undefined;
680
681 try {
682 for (var _iterator = this._nodeCollections[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
683 var collection = _step.value;
684
685 collection.add(entity);
686 }
687 } catch (err) {
688 _didIteratorError = true;
689 _iteratorError = err;
690 } finally {
691 try {
692 if (!_iteratorNormalCompletion && _iterator.return) {
693 _iterator.return();
694 }
695 } finally {
696 if (_didIteratorError) {
697 throw _iteratorError;
698 }
699 }
700 }
701
702 return true;
703 }
704
705 /*
706 * Removes entity from system, removing from all node collections
707 *
708 * returns true if removed, false if not present
709 */
710
711 }, {
712 key: 'removeEntity',
713 value: function removeEntity(entity) {
714
715 var position = this.entities.indexOf(entity);
716 if (position >= 0) {
717 var _iteratorNormalCompletion2 = true;
718 var _didIteratorError2 = false;
719 var _iteratorError2 = undefined;
720
721 try {
722 for (var _iterator2 = this._nodeCollections[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
723 var collection = _step2.value;
724
725 collection.remove(entity);
726 }
727 } catch (err) {
728 _didIteratorError2 = true;
729 _iteratorError2 = err;
730 } finally {
731 try {
732 if (!_iteratorNormalCompletion2 && _iterator2.return) {
733 _iterator2.return();
734 }
735 } finally {
736 if (_didIteratorError2) {
737 throw _iteratorError2;
738 }
739 }
740 }
741
742 this.entities.splice(position, 1);
743 return true;
744 }
745
746 return false;
747 }
748
749 /*
750 * Given a Node Class, retrieves a list of all the nodes for each
751 * applicable entity.
752 */
753
754 }, {
755 key: 'getNodes',
756 value: function getNodes(nodeType) {
757
758 var position = this._nodeCollectionKeys.indexOf(nodeType);
759
760 if (position >= 0) {
761 return this._nodeCollections[position].nodes;
762 }
763
764 var nodeCollection = new Serpentity.NodeCollection({
765 type: nodeType
766 });
767
768 this._nodeCollectionKeys.push(nodeType);
769 this._nodeCollections.push(nodeCollection);
770
771 var _iteratorNormalCompletion3 = true;
772 var _didIteratorError3 = false;
773 var _iteratorError3 = undefined;
774
775 try {
776 for (var _iterator3 = this.entities[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
777 var entity = _step3.value;
778
779 nodeCollection.add(entity);
780 }
781 } catch (err) {
782 _didIteratorError3 = true;
783 _iteratorError3 = err;
784 } finally {
785 try {
786 if (!_iteratorNormalCompletion3 && _iterator3.return) {
787 _iterator3.return();
788 }
789 } finally {
790 if (_didIteratorError3) {
791 throw _iteratorError3;
792 }
793 }
794 }
795
796 return nodeCollection.nodes;
797 }
798
799 /*
800 * Calls update for every loaded system.
801 */
802
803 }, {
804 key: 'update',
805 value: function update(dt) {
806 var _iteratorNormalCompletion4 = true;
807 var _didIteratorError4 = false;
808 var _iteratorError4 = undefined;
809
810 try {
811
812 for (var _iterator4 = this.systems[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
813 var system = _step4.value;
814
815 system.update(dt);
816 }
817 } catch (err) {
818 _didIteratorError4 = true;
819 _iteratorError4 = err;
820 } finally {
821 try {
822 if (!_iteratorNormalCompletion4 && _iterator4.return) {
823 _iterator4.return();
824 }
825 } finally {
826 if (_didIteratorError4) {
827 throw _iteratorError4;
828 }
829 }
830 }
831 }
832 }]);
833
834 return Serpentity;
835 }();
836
837 // Add namespaced objects.
838 Serpentity.Component = __webpack_require__(0);
839 Serpentity.Entity = __webpack_require__(1);
840 Serpentity.Node = __webpack_require__(2);
841 Serpentity.NodeCollection = __webpack_require__(3);
842 Serpentity.System = __webpack_require__(4);
843
844 module.exports = Serpentity;
845
846 /***/ })
847 /******/ ]);
848 });