UNPKG

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