@makefully/platypus 4.1.5 → 4.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +3 -3
  3. package/lib/platypus.js +1 -1
  4. package/package.json +7 -6
  5. package/src/AABB.js +685 -0
  6. package/src/ActionState.js +121 -0
  7. package/src/AssetManager.js +206 -0
  8. package/src/CollisionData.js +96 -0
  9. package/src/CollisionDataContainer.js +127 -0
  10. package/src/CollisionShape.js +315 -0
  11. package/src/Component.js +231 -0
  12. package/src/Data.js +64 -0
  13. package/src/DataMap.js +204 -0
  14. package/src/Entity.js +404 -0
  15. package/src/EntityLinker.js +113 -0
  16. package/src/EventHandler.js +115 -0
  17. package/src/EventHandlerList.js +251 -0
  18. package/src/Game.js +840 -0
  19. package/src/Gamepad.js +175 -0
  20. package/src/ID3CaptionPlayer.js +61 -0
  21. package/src/Messenger.js +365 -0
  22. package/src/PIXIAnimation.js +622 -0
  23. package/src/RandomSet.js +140 -0
  24. package/src/SFXPlayer.js +120 -0
  25. package/src/StateMap.js +252 -0
  26. package/src/Storage.js +152 -0
  27. package/src/TickerClient.js +48 -0
  28. package/src/TickerServer.js +23 -0
  29. package/src/TimeEvent.js +50 -0
  30. package/src/TimeEventList.js +100 -0
  31. package/src/VOPlayer.js +684 -0
  32. package/src/Vector.js +702 -0
  33. package/src/components/AIChaser.js +161 -0
  34. package/src/components/AIPacer.js +107 -0
  35. package/src/components/AudioMusic.js +151 -0
  36. package/src/components/AudioSFX.js +673 -0
  37. package/src/components/AudioVO.js +301 -0
  38. package/src/components/CollisionBasic.js +826 -0
  39. package/src/components/CollisionFilter.js +74 -0
  40. package/src/components/CollisionGroup.js +448 -0
  41. package/src/components/CollisionTiles.js +608 -0
  42. package/src/components/ComponentSwitcher.js +173 -0
  43. package/src/components/ControllerInput.js +65 -0
  44. package/src/components/Counter.js +165 -0
  45. package/src/components/EntityCamera.js +215 -0
  46. package/src/components/EntityContainer.js +549 -0
  47. package/src/components/EntityController.js +541 -0
  48. package/src/components/HandlerCamera.js +1052 -0
  49. package/src/components/HandlerCollision.js +1318 -0
  50. package/src/components/HandlerController.js +291 -0
  51. package/src/components/HandlerLogic.js +394 -0
  52. package/src/components/HandlerRender.js +217 -0
  53. package/src/components/Interactive.js +502 -0
  54. package/src/components/LevelBuilder.js +524 -0
  55. package/src/components/LogicAngularMovement.js +154 -0
  56. package/src/components/LogicAttachment.js +265 -0
  57. package/src/components/LogicButton.js +466 -0
  58. package/src/components/LogicCarrier.js +39 -0
  59. package/src/components/LogicDestroyMe.js +58 -0
  60. package/src/components/LogicDirectionalMovement.js +325 -0
  61. package/src/components/LogicDragDrop.js +371 -0
  62. package/src/components/LogicImpactLaunch.js +144 -0
  63. package/src/components/LogicPacingPlatform.js +64 -0
  64. package/src/components/LogicPortable.js +112 -0
  65. package/src/components/LogicPortal.js +115 -0
  66. package/src/components/LogicPushable.js +98 -0
  67. package/src/components/LogicRebounder.js +136 -0
  68. package/src/components/LogicRegionSpawner.js +139 -0
  69. package/src/components/LogicRotationalMovement.js +205 -0
  70. package/src/components/LogicSpawner.js +159 -0
  71. package/src/components/LogicStateMachine.js +382 -0
  72. package/src/components/LogicSwitch.js +77 -0
  73. package/src/components/LogicTeleportee.js +68 -0
  74. package/src/components/LogicTeleporter.js +93 -0
  75. package/src/components/LogicTimer.js +178 -0
  76. package/src/components/LogicWindUpRacer.js +179 -0
  77. package/src/components/Motion.js +371 -0
  78. package/src/components/Mover.js +566 -0
  79. package/src/components/Node.js +289 -0
  80. package/src/components/NodeMap.js +295 -0
  81. package/src/components/NodeResident.js +636 -0
  82. package/src/components/Orientation.js +697 -0
  83. package/src/components/RandomEvents.js +73 -0
  84. package/src/components/RelativePosition.js +204 -0
  85. package/src/components/RelayFamily.js +106 -0
  86. package/src/components/RelayGame.js +53 -0
  87. package/src/components/RelayLinker.js +94 -0
  88. package/src/components/RelayParent.js +57 -0
  89. package/src/components/RelaySelf.js +55 -0
  90. package/src/components/Render.js +178 -0
  91. package/src/components/RenderAnimator.js +275 -0
  92. package/src/components/RenderContainer.js +646 -0
  93. package/src/components/RenderDebug.js +319 -0
  94. package/src/components/RenderDestroyMe.js +59 -0
  95. package/src/components/RenderLottie.js +149 -0
  96. package/src/components/RenderProgress.js +120 -0
  97. package/src/components/RenderSpine.js +840 -0
  98. package/src/components/RenderSprite.js +527 -0
  99. package/src/components/RenderText.js +147 -0
  100. package/src/components/RenderTiles.js +1440 -0
  101. package/src/components/SceneChanger.js +128 -0
  102. package/src/components/TiledLoader.js +1459 -0
  103. package/src/components/Timeline.js +314 -0
  104. package/src/components/Tutorial.js +267 -0
  105. package/src/components/Tween.js +296 -0
  106. package/src/components/VoiceOver.js +373 -0
  107. package/src/components/XHR.js +129 -0
  108. package/src/components/index.js +79 -0
  109. package/src/factory.js +305 -0
  110. package/src/index.js +159 -0
  111. package/src/mixins/PIXI.Graphics.js +41 -0
  112. package/src/platypus.css +68 -0
  113. package/src/sayHello.js +50 -0
  114. package/src/shapes/Capsule.js +74 -0
  115. package/src/shapes/Circle.js +43 -0
  116. package/src/shapes/Ellipse.js +117 -0
  117. package/src/shapes/Point.js +191 -0
  118. package/src/shapes/Polygon.js +112 -0
  119. package/src/shapes/Polyline.js +97 -0
  120. package/src/shapes/Rectangle.js +78 -0
  121. package/src/shapes/RoundedRectangle.js +33 -0
  122. package/src/shapes/Segment.js +346 -0
  123. package/src/shapes/adjustedXY.js +19 -0
  124. package/src/shapes/castFromBox2D.js +92 -0
  125. package/src/shapes/castFromObject.js +53 -0
  126. package/src/shapes/castFromPixiGraphics.js +6 -0
  127. package/src/shapes/castFromPixiShape.js +89 -0
  128. package/src/shapes/castToBox2D.js +190 -0
  129. package/src/shapes/castToPixiGraphics.js +100 -0
  130. package/src/shapes/castToPixiShape.js +61 -0
  131. package/src/shapes/checkPointsMap.js +313 -0
  132. package/src/shapes/index.js +35 -0
  133. package/src/utils/array.js +73 -0
  134. package/src/utils/string.js +39 -0
  135. package/lib/243.platypus.mjs +0 -1
  136. package/lib/platypus.mjs +0 -1
package/src/DataMap.js ADDED
@@ -0,0 +1,204 @@
1
+ /* global Map */
2
+ import {arrayCache, greenSplice} from './utils/array.js';
3
+ import recycle from 'recycle';
4
+
5
+ const
6
+ mapSet = function (keys, key, value) {
7
+ if (this.get(key) !== value) {
8
+ if (!this.has(key)) {
9
+ keys.push(key);
10
+ }
11
+ this.set(key, value);
12
+ }
13
+ return value;
14
+ },
15
+ mapDelete = function (keys, key) {
16
+ const
17
+ i = keys.indexOf(key),
18
+ value = this.get(key);
19
+
20
+ if (i >= 0) {
21
+ greenSplice(keys, i);
22
+ this.delete(key);
23
+ }
24
+
25
+ return value;
26
+ },
27
+ mapClear = function (keys) {
28
+ let i = keys.length;
29
+
30
+ while (i--) {
31
+ this.delete(keys[i]);
32
+ }
33
+ keys.length = 0;
34
+ },
35
+ mapToJSON = function (keys) {
36
+ const
37
+ json = {};
38
+ let i = keys.length;
39
+
40
+ while (i--) {
41
+ const
42
+ key = keys[i];
43
+
44
+ json[key] = this.get(key);
45
+ }
46
+
47
+ return json;
48
+ },
49
+ mapMethods = {
50
+ get: {
51
+ value: null
52
+ },
53
+ has: {
54
+ value: null
55
+ },
56
+ keys: {
57
+ value: null
58
+ },
59
+ set: {
60
+ value: null
61
+ },
62
+ delete: {
63
+ value: null
64
+ },
65
+ clear: {
66
+ value: null
67
+ },
68
+ toJSON: {
69
+ value: null
70
+ }
71
+ },
72
+
73
+ /**
74
+ * This class defines a generic iterable data object. It behaves similarly to Map but maintains a list of keys as an Array. It includes recycle methods to encourage reuse.
75
+ *
76
+ * @memberof platypus
77
+ * @class DataMap
78
+ * @uses Map
79
+ * @return {platypus.DataMap} Returns the new DataMap object.
80
+ */
81
+ DataMap = function (first) {
82
+ if (!this.map) {
83
+ const
84
+ mm = mapMethods,
85
+ map = this.map = new Map(),
86
+
87
+ /**
88
+ * Tracks keys on this object to make iteration faster.
89
+ *
90
+ * @property keys
91
+ * @type Array
92
+ * @default []
93
+ */
94
+ keys = mm.keys.value = arrayCache.setUp();
95
+
96
+ /**
97
+ * Returns the value of the provided key.
98
+ *
99
+ * @method platypus.DataMap#get
100
+ * @param key {String} The key to lookup.
101
+ * @return value {any} The value of the provded key.
102
+ */
103
+ mm.get.value = map.get.bind(map);
104
+
105
+ /**
106
+ * Determines whether the provided key is available on this DataMap.
107
+ *
108
+ * @method platypus.DataMap#has
109
+ * @param key {String} The key to lookup.
110
+ * @return value {Boolean} Whether the key is listed in this DataMap.
111
+ */
112
+ mm.has.value = map.has.bind(map);
113
+
114
+ /**
115
+ * Sets a value to a key in the DataMap.
116
+ *
117
+ * @method platypus.DataMap#set
118
+ * @param key {String} The key to associate with the provided value.
119
+ * @param value {any} The value to be stored by the DataMap.
120
+ * @return value {any} The value passed in is returned for chaining.
121
+ */
122
+ mm.set.value = mapSet.bind(map, keys);
123
+
124
+ /**
125
+ * Deletes a key (and value) from the DataMap.
126
+ *
127
+ * @method platypus.DataMap#delete
128
+ * @param key {String} The key to delete from the DataMap.
129
+ * @return value {any} The value of the key is returned.
130
+ */
131
+ mm.delete.value = mapDelete.bind(map, keys);
132
+
133
+ /**
134
+ * Clears out of keys (and values) from the DataMap.
135
+ *
136
+ * @method platypus.DataMap#clear
137
+ */
138
+ mm.clear.value = mapClear.bind(map, keys);
139
+
140
+ /**
141
+ * Returns a JSON object describing the component.
142
+ *
143
+ * @method platypus.DataMap#toJSON
144
+ * @return {Object} Returns a JSON definition that can be used to recreate the component.
145
+ **/
146
+ mm.toJSON.value = mapToJSON.bind(map, keys);
147
+
148
+ Object.defineProperties(this, mm);
149
+ }
150
+
151
+ if (first) {
152
+ if (typeof first === 'string') {
153
+ let i = arguments.length;
154
+
155
+ if (i % 2) {
156
+ i -= 1;
157
+ this.set(arguments[i], null);
158
+ }
159
+ while (i) {
160
+ i -= 2;
161
+ this.set(arguments[i], arguments[i + 1]);
162
+ }
163
+ } else if (first.keys) {
164
+ const
165
+ keys = first.keys;
166
+ let i = keys.length;
167
+
168
+ while (i--) {
169
+ this.set(keys[i], first.get(keys[i]));
170
+ }
171
+ } else {
172
+ const
173
+ keys = Object.keys(first);
174
+ let i = keys.length;
175
+
176
+ while (i--) {
177
+ this.set(keys[i], first[keys[i]]);
178
+ }
179
+ }
180
+ }
181
+ };
182
+
183
+ /**
184
+ * Returns DataMap from cache or creates a new one if none are available.
185
+ *
186
+ * @method platypus.DataMap.setUp
187
+ * @return dataMap {platypus.DataMap} The instantiated DataMap.
188
+ */
189
+ /**
190
+ * Returns DataMap back to the cache. Prefer the DataMap's recycle method since it recycles property objects as well.
191
+ *
192
+ * @method platypus.DataMap.recycle
193
+ * @param dataMap {platypus.DataMap} The DataMap to be recycled.
194
+ */
195
+ /**
196
+ * Relinquishes DataMap properties and recycles it.
197
+ *
198
+ * @method platypus.DataMap#recycle
199
+ */
200
+ recycle.add(DataMap, 'DataMap', DataMap, function () {
201
+ this.clear();
202
+ }, true);
203
+
204
+ export default DataMap;
package/src/Entity.js ADDED
@@ -0,0 +1,404 @@
1
+ /* global platypus */
2
+ import {arrayCache, greenSplice} from './utils/array.js';
3
+ import Messenger from './Messenger.js';
4
+ import StateMap from './StateMap.js';
5
+ import createComponentClass from './factory.js';
6
+
7
+ const
8
+ entityIds = {},
9
+ getComponentClass = function (componentDefinition) {
10
+ const
11
+ {type} = componentDefinition;
12
+
13
+ if (type) {
14
+ if (typeof type === 'function') {
15
+ return type;
16
+ } else if (platypus.components[type]) {
17
+ return platypus.components[type];
18
+ }
19
+ } else if (componentDefinition.id) { // "type" not specified, so we create the component directly.
20
+ return createComponentClass(componentDefinition);
21
+ } else if (typeof componentDefinition === 'function') {
22
+ return componentDefinition;
23
+ } else {
24
+ return null;
25
+ }
26
+ };
27
+
28
+ /**
29
+ * The Entity object acts as a container for components, facilitates communication between components and other game objects, and includes properties set by components to maintain a current state. The entity object serves as the foundation for most of the game objects in the platypus engine.
30
+ *
31
+ * ## JSON Definition Example
32
+ {
33
+ "id": "entity-id",
34
+ // "entity-id" becomes `entity.type` once the entity is created.
35
+
36
+ "components": [
37
+ // This array lists one or more component definition objects
38
+
39
+ {"type": "example-component"}
40
+ // The component objects must include a "type" property corresponding to a component to load, but may also include additional properties to customize the component in a particular way for this entity.
41
+ ],
42
+
43
+ "properties": {
44
+ // This object lists properties that will be attached directly to this entity.
45
+
46
+ "x": 240
47
+ // For example, `x` becomes `entity.x` on the new entity.
48
+ },
49
+
50
+ "preload": ['image.png', 'sound.mp3']
51
+ // assets that need to be loaded before this entity loads
52
+ }
53
+ *
54
+ * @memberof platypus
55
+ * @extends platypus.Messenger
56
+ **/
57
+ export default class Entity extends Messenger {
58
+ /**
59
+ * @param {Object} [definition] Base definition for the entity.
60
+ * @param {Object} [definition.components] This lists the components that should be attached to this entity.
61
+ * @param {Object} [definition.id] This declares the type of entity and will be stored on the Entity as `entity.type` after instantiation.
62
+ * @param {Object} [definition.properties] [definition.properties] This is a list of key/value pairs that are added directly to the Entity as `entity.key = value`.
63
+ * @param {Object} [instanceDefinition] Specific instance definition including properties that override the base definition properties.
64
+ * @param {Object} [instanceDefinition.properties] This is a list of key/value pairs that are added directly to the Entity as `entity.key = value`.
65
+ * @param {Function} [callback] A function to run once all of the components on the Entity have been loaded. The first parameter is the entity itself.
66
+ * @param {Entity} [parent] Presets the parent of the entity so that the parent entity is available during component instantiation. Overrides `parent` in properties definitions.
67
+ * @return {Entity} Returns the new entity made up of the provided components.
68
+ * @fires platypus.Entity#load
69
+ */
70
+ constructor ({
71
+ components: componentDefinitions,
72
+ properties: defaultProperties = {},
73
+ id: type
74
+ }, {
75
+ id,
76
+ properties: instanceProperties = {}
77
+ } = {}, callback, parent) {
78
+ // Set properties of messenger on this entity.
79
+ super();
80
+
81
+ const
82
+ componentInit = (Component, componentDefinition) => new Promise((resolve) => this.addComponent(new Component(this, componentDefinition, resolve))),
83
+ componentInits = arrayCache.setUp(),
84
+ savedEvents = arrayCache.setUp(),
85
+ trigger = this.trigger; // trigger reference for saved events
86
+
87
+ this.components = arrayCache.setUp();
88
+ this.type = type || 'none';
89
+
90
+ this.id = id ?? instanceProperties.id;
91
+ if (this.id) { // check to make sure auto-ids don't overlap.
92
+ if (this.id.search(this.type + '-') === 0) {
93
+ const
94
+ i = parseInt(this.id.substring(this.id.search('-') + 1), 10);
95
+
96
+ if (!isNaN(i) && (!entityIds[this.type] || (entityIds[this.type] <= i))) {
97
+ entityIds[this.type] = i + 1;
98
+ }
99
+ }
100
+ } else {
101
+ if (!entityIds[this.type]) {
102
+ entityIds[this.type] = 0;
103
+ }
104
+ this.id = this.type + '-' + entityIds[this.type];
105
+ entityIds[this.type] += 1;
106
+ }
107
+
108
+ this.setProperty(defaultProperties); // This takes the list of properties in the JSON definition and appends them directly to the object.
109
+ this.setProperty(instanceProperties); // This takes the list of options for this particular instance and appends them directly to the object.
110
+ this.on('set-property', (keyValuePairs) => {
111
+ this.setProperty(keyValuePairs);
112
+ });
113
+
114
+ this.state = StateMap.setUp(this.state); //starts with no state information. This expands with boolean value properties entered by various logic components.
115
+ this.lastState = StateMap.setUp(); //This is used to determine if the state of the entity has changed.
116
+
117
+ if (parent) {
118
+ this.parent = parent;
119
+ }
120
+
121
+ this.trigger = this.triggerEvent = (...args) => {
122
+ savedEvents.push(trigger.bind(this, ...args));
123
+
124
+ return -1; // Message has not been delivered yet.
125
+ };
126
+
127
+ if (componentDefinitions) {
128
+ for (let i = 0; i < componentDefinitions.length; i++) {
129
+ const
130
+ componentDefinition = componentDefinitions[i];
131
+
132
+ if (componentDefinition) {
133
+ if (componentDefinition.type) {
134
+ const
135
+ componentClass = getComponentClass(componentDefinition);
136
+
137
+ if (componentClass) {
138
+ componentInits.push(componentInit(componentClass, componentDefinition));
139
+ } else {
140
+ platypus.debug.warn('Entity "' + this.type + '": Component "' + componentDefinition.type + '" is not defined.', componentDefinition);
141
+ }
142
+ } else if (componentDefinition.id) { // "type" not specified, so we create the component directly.
143
+ componentInits.push(componentInit(createComponentClass(componentDefinition)));
144
+ } else if (typeof componentDefinition === 'function') {
145
+ componentInits.push(componentInit(componentDefinition));
146
+ } else {
147
+ platypus.debug.warn('Entity "' + this.type + '": Component must have an `id` or `type` value.', componentDefinition);
148
+ }
149
+ }
150
+ }
151
+ }
152
+ this.loadingComponents = Promise.all(componentInits).then(() => {
153
+ this.loadingComponents = null;
154
+
155
+ // Trigger saved events that were being fired during component addition.
156
+ delete this.trigger;
157
+ delete this.triggerEvent;
158
+ for (let i = 0; i < savedEvents.length; i++) {
159
+ savedEvents[i]();
160
+ }
161
+ arrayCache.recycle(savedEvents);
162
+
163
+ /**
164
+ * The entity triggers `load` on itself once all the properties and components have been attached, notifying the components that all their peer components are ready for messages.
165
+ *
166
+ * @event platypus.Entity#load
167
+ */
168
+ this.triggerEvent('load');
169
+
170
+ if (callback) {
171
+ callback(this);
172
+ }
173
+ });
174
+
175
+ arrayCache.recycle(componentInits);
176
+ }
177
+
178
+ /**
179
+ * Returns a string describing the entity.
180
+ *
181
+ * @return {String} Returns the entity type as a string of the form "[Entity entity-type]".
182
+ **/
183
+ toString () {
184
+ return "[Entity " + this.type + "]";
185
+ }
186
+
187
+ /**
188
+ * Returns a JSON object describing the entity.
189
+ *
190
+ * @param includeComponents {Boolean} Whether the returned JSON should list components. Defaults to `false` to condense output since components are generally defined in `platypus.game.settings.entities`, but may be needed for custom-constructed entities not so defined.
191
+ * @return {Object} Returns a JSON definition that can be used to recreate the entity.
192
+ **/
193
+ toJSON (includeComponents) {
194
+ const
195
+ {components, type} = this,
196
+ properties = {
197
+ id: this.id,
198
+ state: this.state.toJSON()
199
+ },
200
+ definition = {
201
+ properties
202
+ };
203
+
204
+ if (includeComponents) {
205
+ definition.id = type;
206
+ definition.components = [];
207
+ } else {
208
+ definition.type = type;
209
+ }
210
+
211
+ for (let i = 0; i < components.length; i++) {
212
+ const
213
+ json = components[i].toJSON(properties);
214
+
215
+ if (includeComponents && json) {
216
+ definition.components.push(json);
217
+ }
218
+ }
219
+
220
+ return definition;
221
+ }
222
+
223
+ /**
224
+ * Attaches the provided component to the entity.
225
+ *
226
+ * @param {platypus.Component} component Must be an object that functions as a Component.
227
+ * @return {platypus.Component} Returns the same object that was submitted.
228
+ * @fires platypus.Entity#component-added
229
+ **/
230
+ addComponent (component) {
231
+ this.components.push(component);
232
+
233
+ /**
234
+ * The entity triggers `component-added` on itself once a component has been attached, notifying other components of their peer component.
235
+ *
236
+ * @event platypus.Entity#component-added
237
+ * @param {platypus.Component} component The added component.
238
+ * @param {String} component.type The type of component.
239
+ **/
240
+ this.triggerEvent('component-added', component);
241
+ return component;
242
+ }
243
+
244
+ /**
245
+ * Removes the mentioned component from the entity.
246
+ *
247
+ * @param {Component} component Must be a [[Component]] attached to the entity.
248
+ * @return {Component} Returns the same object that was submitted if removal was successful; otherwise returns false (the component was not found attached to the entity).
249
+ * @fires platypus.Entity#component-removed
250
+ **/
251
+ removeComponent (component) {
252
+ /**
253
+ * The entity triggers `component-removed` on itself once a component has been removed, notifying other components of their peer component's removal.
254
+ *
255
+ * @event platypus.Entity#component-removed
256
+ * @param {Component} component The removed component.
257
+ * @param {String} component.type The type of component.
258
+ **/
259
+ if (typeof component === 'string') {
260
+ for (let i = 0; i < this.components.length; i++) {
261
+ if (this.components[i].type === component) {
262
+ component = this.components[i];
263
+ greenSplice(this.components, i);
264
+ this.triggerEvent('component-removed', component);
265
+ component.destroy();
266
+ return component;
267
+ }
268
+ }
269
+ } else {
270
+ for (let i = 0; i < this.components.length; i++) {
271
+ if (this.components[i] === component) {
272
+ greenSplice(this.components, i);
273
+ this.triggerEvent('component-removed', component);
274
+ component.destroy();
275
+ return component;
276
+ }
277
+ }
278
+ }
279
+
280
+ return false;
281
+ }
282
+
283
+ /**
284
+ * This method gets a component by its id.
285
+ *
286
+ * @param {String} componentId
287
+ * @returns {Component} A component
288
+ */
289
+ getComponentById (componentId) {
290
+ return this.components.filter(({id}) => id === componentId)[0] ?? null;
291
+ }
292
+
293
+ /**
294
+ * This method gets all components by their type.
295
+ *
296
+ * @param {String} componentType
297
+ * @returns {Array} An array of components
298
+ */
299
+ getComponentsByType (componentType) {
300
+ return this.components.filter(({type}) => type === componentType);
301
+ }
302
+
303
+ /**
304
+ * Allows lookup for components or child entities and their properties.
305
+ *
306
+ * For example, "component-id.sprite" will return an entity component's sprite property value.
307
+ *
308
+ * @param {String} path
309
+ * @returns {*}
310
+ */
311
+ get (path) {
312
+ const
313
+ tree = path.split('.');
314
+ let obj = this;
315
+
316
+ while (tree.length) {
317
+ let param = tree.shift();
318
+
319
+ obj = obj[param] ?? obj.getComponentById?.(param) ?? obj.getEntityById?.(param);
320
+
321
+ if (!obj) {
322
+ return null;
323
+ }
324
+ }
325
+
326
+ return obj;
327
+ }
328
+
329
+ /**
330
+ * This method sets one or more properties on the entity.
331
+ *
332
+ * @param {Object} properties A list of key/value pairs to set as properties on the entity.
333
+ **/
334
+ setProperty (properties) {
335
+ const
336
+ keys = Object.keys(properties);
337
+
338
+ // This takes a list of properties and appends them directly to the object.
339
+ for (let i = 0; i < keys.length; i++) {
340
+ const
341
+ key = keys[i];
342
+
343
+ this[key] = properties[key];
344
+ }
345
+ }
346
+
347
+ /**
348
+ * This method removes all components from the entity.
349
+ *
350
+ **/
351
+ destroy () {
352
+ const
353
+ components = this.components;
354
+
355
+ if (!this._destroyed) {
356
+ while (components.length) {
357
+ components[0].destroy();
358
+ components.shift();
359
+ }
360
+ arrayCache.recycle(components);
361
+ this.components = null;
362
+
363
+ this.state.recycle();
364
+ this.state = null;
365
+
366
+ this.lastState.recycle();
367
+ this.lastState = null;
368
+
369
+ super.destroy();
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Returns all of the assets required for this Entity. This method calls the corresponding method on all components to determine the list of assets.
375
+ *
376
+ * @param definition {Object} The definition for the Entity.
377
+ * @param properties {Object} Properties for this instance of the Entity.
378
+ * @param data {Object} Layer data that affects asset list.
379
+ * @return {Array} A list of the necessary assets to load.
380
+ */
381
+ static getAssetList ({components = [], preload = [], properties = {}, type} = {}, props, data) {
382
+ if (type) {
383
+ const
384
+ definition = platypus.game.settings.entities[type];
385
+
386
+ if (!definition) {
387
+ platypus.debug.warn(`Entity "${type}": This entity is not defined.`);
388
+ return arrayCache.setUp();
389
+ }
390
+ return Entity.getAssetList({
391
+ ...definition,
392
+ preload: [
393
+ ...preload,
394
+ ...definition.preload ?? []
395
+ ]
396
+ }, properties, data);
397
+ } else {
398
+ return [...new Set([
399
+ ...preload,
400
+ ...components.map((component) => getComponentClass(component)?.getAssetList(component, properties, props, data) ?? []).flat()
401
+ ])];
402
+ }
403
+ }
404
+ }