UNPKG

7.12 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8exports.ComponentManager = exports.Component = void 0;
9
10var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
12var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
14var _Entity = require("./Entity");
15
16var Component = function Component(data) {//
17
18 (0, _classCallCheck2.default)(this, Component);
19};
20/**
21 * 管理某一类 Component,尽可能做到 AoS 而非 SoA
22 * @see https://wickedengine.net/2019/09/29/entity-component-system/
23 * @see https://github.com/turanszkij/WickedEngine/blob/master/WickedEngine/wiECS.h
24 */
25// tslint:disable-next-line:max-classes-per-file
26
27
28exports.Component = Component;
29
30var ComponentManager = /*#__PURE__*/function () {
31 /**
32 * 不在 Entity 中维护拥有的 Component 列表,反之亦然
33 */
34 function ComponentManager(clazz) {
35 (0, _classCallCheck2.default)(this, ComponentManager);
36 this.clazz = void 0;
37 this.components = [];
38 this.entities = [];
39 this.lookup = {};
40 this.clazz = clazz;
41 }
42
43 (0, _createClass2.default)(ComponentManager, [{
44 key: "clear",
45 value: function clear() {
46 this.components = [];
47 this.entities = [];
48 this.lookup = {};
49 }
50 }, {
51 key: "contains",
52 value: function contains(entity) {
53 return this.lookup[entity] > -1;
54 }
55 }, {
56 key: "create",
57 value: function create(entity, data) {
58 this.lookup[entity] = this.components.length;
59 var component = new this.clazz(data || {});
60 this.components.push(component);
61 this.entities.push(entity);
62 return component;
63 }
64 }, {
65 key: "remove",
66 value: function remove(entity) {
67 var componentIndex = this.lookup[entity];
68
69 if (componentIndex > -1) {
70 if (componentIndex < this.components.length - 1) {
71 // 将待删除元素和最后一个元素交换
72 // C++ 中有 std::move 这样的操作,避免数据的拷贝
73 // @see https://github.com/turanszkij/WickedEngine/blob/master/WickedEngine/wiECS.h#L169
74 this.components[componentIndex] = this.components[this.components.length - 1];
75 this.entities[componentIndex] = this.entities[this.entities.length - 1];
76 this.lookup[this.entities[componentIndex]] = componentIndex;
77 }
78 } // 待删除元素已经移动到了最后一个
79
80
81 this.components.pop();
82 this.entities.pop();
83 delete this.lookup[entity];
84 }
85 }, {
86 key: "removeKeepSorted",
87 value: function removeKeepSorted(entity) {
88 var componentIndex = this.lookup[entity];
89
90 if (componentIndex > -1) {
91 var entity2 = this.entities[componentIndex];
92
93 if (componentIndex < this.components.length - 1) {
94 // Move every component left by one that is after this element:
95 for (var _i = componentIndex + 1; _i < this.components.length; ++_i) {
96 this.components[_i - 1] = this.components[_i];
97 } // Move every entity left by one that is after this element and update lut:
98
99
100 for (var _i2 = componentIndex + 1; _i2 < this.entities.length; ++_i2) {
101 this.entities[_i2 - 1] = this.entities[_i2];
102 this.lookup[this.entities[_i2 - 1]] = _i2 - 1;
103 }
104 }
105
106 this.components.pop();
107 this.entities.pop();
108 delete this.lookup[entity2];
109 }
110 }
111 }, {
112 key: "moveItem",
113 value: function moveItem(srcIndex, destIndex) {
114 if (srcIndex === destIndex) {
115 return;
116 } // Save the moved component and entity:
117
118
119 var srcComponent = this.components[srcIndex];
120 var srcEntity = this.entities[srcIndex]; // Every other entity-component that's in the way gets moved by one and lut is kept updated:
121
122 var direction = srcIndex < destIndex ? 1 : -1;
123
124 for (var _i3 = srcIndex; _i3 !== destIndex; _i3 += direction) {
125 var next = _i3 + direction;
126 this.components[_i3] = this.components[next];
127 this.entities[_i3] = this.entities[next];
128 this.lookup[this.entities[_i3]] = _i3;
129 } // Saved entity-component moved to the required position:
130
131
132 this.components[destIndex] = srcComponent;
133 this.entities[destIndex] = srcEntity;
134 this.lookup[srcEntity] = destIndex;
135 }
136 }, {
137 key: "getEntity",
138 value: function getEntity(index) {
139 return this.entities[index];
140 }
141 /**
142 * 由于缺少类似 C++ 的重载操作符,没法通过 [下标] 直接访问。因此只能增加该方法用于遍历。
143 */
144
145 }, {
146 key: "getComponent",
147 value: function getComponent(index) {
148 return this.components[index];
149 }
150 }, {
151 key: "getComponentByEntity",
152 value: function getComponentByEntity(entity) {
153 var componentIndex = this.lookup[entity];
154
155 if (componentIndex > -1) {
156 return this.components[componentIndex];
157 }
158
159 return null;
160 }
161 }, {
162 key: "getCount",
163 value: function getCount() {
164 return this.components.length;
165 }
166 }, {
167 key: "getEntityByComponentIndex",
168 value: function getEntityByComponentIndex(componentIdx) {
169 for (var _i4 = 0, _Object$keys = Object.keys(this.lookup); _i4 < _Object$keys.length; _i4++) {
170 var _entity = _Object$keys[_i4];
171 var entityInNum = Number(_entity);
172
173 if (this.lookup[entityInNum] === componentIdx) {
174 return entityInNum;
175 }
176 }
177
178 return _Entity.EMPTY;
179 }
180 }, {
181 key: "find",
182 value: function find(callback) {
183 for (var _i5 = 0; _i5 < this.getCount(); _i5++) {
184 var _component = this.getComponent(_i5);
185
186 if (callback(_component, _i5)) {
187 return _component;
188 }
189 }
190
191 return null;
192 }
193 }, {
194 key: "findIndex",
195 value: function findIndex(callback) {
196 for (var _i6 = 0; _i6 < this.getCount(); _i6++) {
197 var _component2 = this.getComponent(_i6);
198
199 if (callback(_component2, _i6)) {
200 return _i6;
201 }
202 }
203
204 return -1;
205 }
206 }, {
207 key: "forEach",
208 value: function forEach(callback) {
209 for (var _i7 = 0, _Object$keys2 = Object.keys(this.lookup); _i7 < _Object$keys2.length; _i7++) {
210 var _entity2 = _Object$keys2[_i7];
211 var entityInNum = Number(_entity2);
212 var componentIndex = this.lookup[entityInNum];
213 callback(entityInNum, this.getComponent(componentIndex));
214 }
215 }
216 }, {
217 key: "map",
218 value: function map(callback) {
219 var result = [];
220
221 for (var _i8 = 0, _Object$keys3 = Object.keys(this.lookup); _i8 < _Object$keys3.length; _i8++) {
222 var _entity3 = _Object$keys3[_i8];
223 var entityInNum = Number(_entity3);
224 var componentIndex = this.lookup[entityInNum];
225 result.push(callback(entityInNum, this.getComponent(componentIndex)));
226 }
227
228 return result;
229 }
230 }]);
231 return ComponentManager;
232}();
233
234exports.ComponentManager = ComponentManager;
235//# sourceMappingURL=ComponentManager.js.map
\No newline at end of file