@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
@@ -0,0 +1,289 @@
1
+ /**
2
+ ## JSON Definition
3
+ {
4
+ "type": "NodeResident",
5
+
6
+ "nodeId": "city-hall",
7
+ // Optional. The id of the node that this entity should start on. Uses the entity's nodeId property if not set here.
8
+
9
+ "nodes": ['path','sidewalk','road'],
10
+ // Optional. This is a list of node types that this entity can reside on. If not set, entity can reside on any type of node.
11
+
12
+ "shares": ['friends','neighbors','city-council-members'],
13
+ // Optional. This is a list of entities that this entity can reside with on the same node. If not set, this entity cannot reside with any entities on the same node.
14
+
15
+ "speed": 5,
16
+ // Optional. Sets the speed with which the entity moves along an edge to an adjacent node. Default is 0 (instantaneous movement).
17
+
18
+ "updateOrientation": true
19
+ // Optional. Determines whether the entity's orientation is updated by movement across the NodeMap. Default is false.
20
+ }
21
+ */
22
+ import {arrayCache, greenSplice} from '../utils/array.js';
23
+ import Vector from '../Vector.js';
24
+ import createComponentClass from '../factory.js';
25
+
26
+ export default createComponentClass(/** @lends platypus.components.Node.prototype */{
27
+
28
+ id: 'Node',
29
+
30
+ properties: {
31
+ /**
32
+ * If provided, treats these property names as neighbors, assigning them to the neighbors object. For example, ["east", "west"] creates `entity.east` and `entity.west` entity properties that are pointers to those neighbors.
33
+ *
34
+ * @property neighborProperties
35
+ * @type Array
36
+ * @default null
37
+ */
38
+ neighborProperties: null
39
+ },
40
+
41
+ publicProperties: {
42
+ neighbors: null,
43
+ nodeId: '',
44
+ x: 0,
45
+ y: 0,
46
+ z: 0
47
+ },
48
+
49
+ /**
50
+ * This component causes an entity to be a position on a [[NodeMap]]. This component should not be confused with `NodeResident` which should be used on entities that move around on a NodeMap: `Node` simply represents a non-moving location on the NodeMap.
51
+ *
52
+ * @memberof platypus.components
53
+ * @uses platypus.Component
54
+ * @constructs
55
+ */
56
+ initialize: function () {
57
+ const owner = this.owner;
58
+
59
+ this.nodeId = this.nodeId || owner.id || String(Math.random());
60
+
61
+ if ((typeof this.nodeId !== 'string') && (this.nodeId.length)) {
62
+ this.nodeId = this.nodeId.join('|');
63
+ }
64
+
65
+ owner.nodeId = this.nodeId;
66
+
67
+ owner.isNode = true;
68
+ this.map = owner.map = owner.map || owner.parent || null;
69
+ this.contains = owner.contains = arrayCache.setUp();
70
+ this.edgesContain = owner.edgesContain = arrayCache.setUp();
71
+
72
+ Vector.assign(owner, 'position', 'x', 'y', 'z');
73
+
74
+ if (!this.neighbors) {
75
+ this.neighbors = {};
76
+ }
77
+
78
+ if (this.neighborProperties) {
79
+ const properties = this.neighborProperties;
80
+
81
+ for (let i = 0; i < properties.length; i++) {
82
+ const
83
+ propertyName = properties[i],
84
+ value = owner[propertyName];
85
+
86
+ if (value) {
87
+ this.neighbors[propertyName] = value;
88
+ }
89
+ Object.defineProperty(owner, propertyName, {
90
+ get: () => this.neighbors[propertyName],
91
+ set: (value) => {
92
+ if (value !== this.neighbors[propertyName]) {
93
+ this.neighbors[propertyName] = value;
94
+ for (let i = 0; i < this.contains.length; i++) {
95
+ this.contains[i].triggerEvent('set-directions');
96
+ }
97
+ }
98
+ }
99
+ });
100
+ }
101
+ }
102
+ },
103
+
104
+ events: {
105
+ "add-neighbors": function (neighbors) {
106
+ const
107
+ directions = Object.keys(neighbors);
108
+
109
+ for (let i = 0; i < directions.length; i++) {
110
+ const
111
+ direction = directions[i];
112
+
113
+ this.neighbors[direction] = neighbors[direction];
114
+ }
115
+
116
+ for (let i = 0; i < this.contains.length; i++) {
117
+ this.contains[i].triggerEvent('set-directions');
118
+ }
119
+ },
120
+ "remove-neighbor": function (nodeOrNodeId) {
121
+ const
122
+ id = nodeOrNodeId.nodeId ?? nodeOrNodeId,
123
+ neighbors = Object.keys(this.neighbors);
124
+
125
+ for (let i = 0; i < neighbors.length; i++) {
126
+ const
127
+ neighbor = neighbors[i];
128
+
129
+ if ((neighbor === id) || (neighbor.nodeId === id)) {
130
+ delete this.neighbors[i];
131
+ }
132
+ }
133
+ }
134
+ },
135
+
136
+ methods: {
137
+ toJSON (entityProperties) {
138
+ const
139
+ neighborProperties = this.neighborProperties;
140
+
141
+ neighborProperties.forEach((neighbor) => {
142
+ const
143
+ neighborNode = this.neighbors[neighbor];
144
+
145
+ if (neighborNode) {
146
+ entityProperties[neighbor] = neighborNode.id;
147
+ }
148
+ });
149
+
150
+ entityProperties.nodeId = this.nodeId;
151
+
152
+ return {
153
+ type: 'Node',
154
+ neighborProperties
155
+ };
156
+ },
157
+
158
+ destroy () {
159
+ arrayCache.recycle(this.contains);
160
+ this.contains = this.owner.contains = null;
161
+ arrayCache.recycle(this.edgesContain);
162
+ this.edgesContain = this.owner.edgesContain = null;
163
+ }
164
+ },
165
+
166
+ publicMethods: {
167
+ joinNode (node, direction, mutual = false) {
168
+ this.neighbors[direction] = node;
169
+
170
+ for (let i = 0; i < this.contains.length; i++) {
171
+ this.contains[i].triggerEvent('set-directions');
172
+ }
173
+
174
+ if (mutual) {
175
+ node.joinNode(this.owner, (typeof mutual === 'boolean') ? direction : mutual);
176
+ }
177
+ },
178
+
179
+ /**
180
+ * Gets a neighboring node Entity.
181
+ *
182
+ * @memberof Node.prototype
183
+ * @param {String} desc Describes the direction to check.
184
+ * @returns {platypus.Entity}
185
+ */
186
+ getNode: function (desc) {
187
+ const
188
+ neighbor = this.neighbors[desc];
189
+
190
+ //map check
191
+ if (!this.map && this.owner.map) {
192
+ this.map = this.owner.map;
193
+ }
194
+
195
+ if (neighbor) {
196
+ const
197
+ testNeighbor = neighbor.destroyed ? neighbor.id : neighbor;
198
+
199
+ if (testNeighbor.isNode) {
200
+ return testNeighbor;
201
+ } else if (typeof testNeighbor === 'string') {
202
+ const
203
+ actualNeighbor = this.map.getNode(testNeighbor);
204
+
205
+ if (actualNeighbor) {
206
+ this.neighbors[desc] = actualNeighbor;
207
+ return actualNeighbor;
208
+ }
209
+ } else if (testNeighbor.length) {
210
+ const
211
+ actualNeighbor = this.map.getNode(testNeighbor.join('|'));
212
+
213
+ if (actualNeighbor) {
214
+ this.neighbors[desc] = actualNeighbor;
215
+ return actualNeighbor;
216
+ }
217
+ }
218
+ }
219
+
220
+ return null;
221
+ },
222
+
223
+ /**
224
+ * Puts an entity on this node.
225
+ *
226
+ * @memberof Node.prototype
227
+ * @param {platypus.Entity} entity
228
+ * @returns {platypus.Entity}
229
+ */
230
+ addToNode: function (entity) {
231
+ for (let i = 0; i < this.contains.length; i++) {
232
+ if (this.contains[i] === entity) {
233
+ return false;
234
+ }
235
+ }
236
+ this.contains.push(entity);
237
+ return entity;
238
+ },
239
+
240
+ /**
241
+ * Removes an entity from this node.
242
+ *
243
+ * @memberof Node.prototype
244
+ * @param {platypus.Entity} entity
245
+ * @returns {platypus.Entity}
246
+ */
247
+ removeFromNode: function (entity) {
248
+ for (let i = 0; i < this.contains.length; i++) {
249
+ if (this.contains[i] === entity) {
250
+ return greenSplice(this.contains, i);
251
+ }
252
+ }
253
+ return false;
254
+ },
255
+
256
+ /**
257
+ * Adds an entity to this node's edges.
258
+ *
259
+ * @memberof Node.prototype
260
+ * @param {platypus.Entity} entity
261
+ * @returns {platypus.Entity}
262
+ */
263
+ addToEdge: function (entity) {
264
+ for (let i = 0; i < this.edgesContain.length; i++) {
265
+ if (this.edgesContain[i] === entity) {
266
+ return false;
267
+ }
268
+ }
269
+ this.edgesContain.push(entity);
270
+ return entity;
271
+ },
272
+
273
+ /**
274
+ * Removes an entity from this node's edges.
275
+ *
276
+ * @memberof Node.prototype
277
+ * @param {platypus.Entity} entity
278
+ * @returns {platypus.Entity}
279
+ */
280
+ removeFromEdge: function (entity) {
281
+ for (let i = 0; i < this.edgesContain.length; i++) {
282
+ if (this.edgesContain[i] === entity) {
283
+ return greenSplice(this.edgesContain, i);
284
+ }
285
+ }
286
+ return false;
287
+ }
288
+ }
289
+ });
@@ -0,0 +1,295 @@
1
+ import {arrayCache, greenSplice} from '../utils/array.js';
2
+ import Entity from '../Entity.js';
3
+ import Vector from '../Vector.js';
4
+ import createComponentClass from '../factory.js';
5
+ import recycle from 'recycle';
6
+
7
+ const
8
+ Node = function (definition, map) { // This is a basic node object, but can be replaced by entities having a `Node` component if more functionality is needed.
9
+ if (definition.id) {
10
+ if (typeof definition.id === 'string') {
11
+ this.id = definition.id;
12
+ } else if (Array.isArray(definition.id)) {
13
+ this.id = definition.id.join('|');
14
+ } else {
15
+ this.id = String(Math.random());
16
+ }
17
+ } else {
18
+ this.id = String(Math.random());
19
+ }
20
+
21
+ this.isNode = true;
22
+ this.map = map;
23
+ this.contains = arrayCache.setUp();
24
+ this.type = definition.type || '';
25
+
26
+ if (!this.position) {
27
+ Vector.assign(this, 'position', 'x', 'y', 'z');
28
+ }
29
+ this.x = definition.x || 0;
30
+ this.y = definition.y || 0;
31
+ this.z = definition.z || 0;
32
+
33
+ this.neighbors = definition.neighbors || {};
34
+ },
35
+ proto = Node.prototype;
36
+
37
+ proto.getNode = function (desc) {
38
+ const
39
+ neighbor = this.neighbors[desc];
40
+
41
+ if (neighbor) {
42
+ if (neighbor.isNode) {
43
+ return neighbor;
44
+ } else if (typeof neighbor === 'string') {
45
+ const
46
+ node = this.map.getNode(neighbor);
47
+
48
+ if (node) {
49
+ this.neighbors[desc] = node;
50
+ return node;
51
+ }
52
+ } else if (Array.isArray(neighbor)) {
53
+ const
54
+ node = this.map.getNode(neighbor.join('|'));
55
+
56
+ if (node) {
57
+ this.neighbors[desc] = node;
58
+ return node;
59
+ }
60
+ }
61
+ return null;
62
+ } else {
63
+ return null;
64
+ }
65
+ };
66
+
67
+ proto.addToNode = function (entity) {
68
+ for (let i = 0; i < this.contains.length; i++) {
69
+ if (this.contains[i] === entity) {
70
+ return false;
71
+ }
72
+ }
73
+ this.contains.push(entity);
74
+ return entity;
75
+ };
76
+
77
+ proto.removeFromNode = function (entity) {
78
+ for (let i = 0; i < this.contains.length; i++) {
79
+ if (this.contains[i] === entity) {
80
+ return greenSplice(this.contains, i);
81
+ }
82
+ }
83
+ return false;
84
+ };
85
+
86
+ recycle.add(Node, 'Node', Node, function () {
87
+ arrayCache.recycle(this.contains);
88
+ }, true);
89
+
90
+ export default createComponentClass(/** @lends platypus.components.NodeMap.prototype */{
91
+ id: 'NodeMap',
92
+
93
+ publicProperties: {
94
+ /**
95
+ * An array of node definitions to create the NodeMap. A node definition can take the following form:
96
+ *
97
+ * {
98
+ * "NodeId": "Node1",
99
+ * // A string or array that becomes the id of the Node. Arrays are joined using "|" to create the id string.
100
+ * "type": "path",
101
+ * // A string that determines the type of the node.
102
+ * "x": 0,
103
+ * // Sets the x axis position of the node.
104
+ * "y": 0,
105
+ * // Sets the y axis position of the node.
106
+ * "z": 0,
107
+ * // Sets the z axis position of the node.
108
+ * "neighbors": {
109
+ * // A list of key/value pairs where the keys are directions from the node and values are node ids.
110
+ * "west": "node0",
111
+ * "east": "node2"
112
+ * }
113
+ * }
114
+ *
115
+ * @property map
116
+ * @type Array
117
+ * @default []
118
+ */
119
+ map: []
120
+ },
121
+
122
+ /**
123
+ * This component sets up a NodeMap to be used by the [NodeResident](platypus.components.NodeResident.html) component on this entity's child entities.
124
+ *
125
+ * @memberof platypus.components
126
+ * @uses platypus.Component
127
+ * @constructs
128
+ * @listens platypus.Entity#add-node
129
+ * @listens platypus.Entity#child-entity-added
130
+ * @fires platypus.Entity#add-node
131
+ */
132
+ initialize: function () {
133
+ const
134
+ map = this.map;
135
+
136
+ this.map = arrayCache.setUp(); // Original map is node definitions, so we replace it with actual nodes.
137
+ this.nodes = {};
138
+ this.residentsAwaitingNode = arrayCache.setUp();
139
+
140
+ for (let i = 0; i < map.length; i++) {
141
+ this.addNode(Node.setUp(map[i], this));
142
+ }
143
+ },
144
+
145
+ events: {
146
+ "add-node": function (nodeDefinition) {
147
+ let node = null;
148
+
149
+ if (nodeDefinition.isNode) {// if it's already a node, put it on the map.
150
+ node = nodeDefinition;
151
+ nodeDefinition.map = this;
152
+ } else {
153
+ node = Node.setUp(nodeDefinition, this);
154
+ }
155
+
156
+ this.addNode(node);
157
+
158
+ for (let i = this.residentsAwaitingNode.length - 1; i >= 0; i--) {
159
+ const
160
+ entity = this.residentsAwaitingNode[i];
161
+
162
+ if (node.id === entity.nodeId) {
163
+ greenSplice(this.residentsAwaitingNode, i);
164
+ entity.node = this.getNode(entity.nodeId);
165
+ }
166
+ }
167
+ },
168
+
169
+ "child-entity-added": function (entity) {
170
+ if (entity.isNode) { // a node
171
+ /**
172
+ * Expects a node definition to create a node in the NodeMap.
173
+ *
174
+ * @event platypus.Entity#add-node
175
+ * @param definition {Object} Key/value pairs.
176
+ * @param definition.nodeId {String|Array} This value becomes the id of the Node. Arrays are joined using "|" to create the id string.
177
+ * @param definition.type {String} This determines the type of the node.
178
+ * @param definition.x {String} Sets the x axis position of the node.
179
+ * @param definition.y {String} Sets the y axis position of the node.
180
+ * @param definition.z {String} Sets the z axis position of the node.
181
+ * @param definition.neighbors {Object} A list of key/value pairs where the keys are directions from the node and values are node ids. For example: {"west": "node12"}.
182
+ */
183
+ this.owner.triggerEvent('add-node', entity);
184
+ } else if (entity.nodeId) { // a NodeResident
185
+ entity.node = this.getNode(entity.nodeId);
186
+ if (!entity.node) {
187
+ this.residentsAwaitingNode.push(entity);
188
+ }
189
+ }
190
+ },
191
+
192
+ "child-entity-removed": function (entity) {
193
+ if (entity.isNode) {
194
+ this.owner.triggerEvent('remove-node', entity);
195
+ }
196
+ },
197
+
198
+ "remove-node": function (node) {
199
+ this.removeNode(node);
200
+ }
201
+ },
202
+
203
+ methods: {
204
+ addNode: function (node) {
205
+ this.map.push(node);
206
+ this.nodes[node.id] = node;
207
+ },
208
+
209
+ removeNode: function (node) {
210
+ const
211
+ index = this.map.indexOf(node);
212
+
213
+ if (index >= 0) {
214
+ this.map.splice(index, 1);
215
+ delete this.nodes[node.id];
216
+ } else {
217
+ platypus.debug.warn(`NodeMap: "${node.id}" is not mapped, so it cannot be removed.`);
218
+ }
219
+ },
220
+
221
+ destroy: function () {
222
+ // Destroy simple node objects.
223
+ for (let i = 0; i < this.map.length; i++) {
224
+ if (!(this.map[i] instanceof Entity)) {
225
+ this.map[i].recycle();
226
+ }
227
+ }
228
+
229
+ arrayCache.recycle(this.map);
230
+ arrayCache.recycle(this.residentsAwaitingNode);
231
+ }
232
+ },
233
+
234
+ publicMethods: {
235
+ /**
236
+ * Gets a node by node id.
237
+ *
238
+ * @method platypus.components.NodeMap#getNode
239
+ * @param id {String|Array|Node} This id of the node to retrieve. If an array or more than one parameter is supplied, values are concatenated with "|" to create a single string id. Supplying a node returns the same node (useful for processing a mixed list of nodes and node ids).
240
+ */
241
+ getNode: function (...args) {
242
+ let id = args.join('|');
243
+
244
+ if (args.length === 1) {
245
+ if (args[0].isNode) {
246
+ if (args[0].destroyed) {
247
+ return this.nodes[args[0].id];
248
+ } else {
249
+ return args[0];
250
+ }
251
+ } else if (Array.isArray(args[0])) {
252
+ id = args[0].join('|');
253
+ }
254
+ }
255
+
256
+ return this.nodes[id] ?? null;
257
+ },
258
+
259
+ /**
260
+ * Finds the closest node to a given point, with respect to any inclusion or exclusion lists.
261
+ *
262
+ * @method platypus.components.NodeMap#getClosestNode
263
+ * @param point {platypus.Vector} A location for which a closest node is being found.
264
+ * @param [including] {Array} A list of nodes to include in the search. If not set, the entire map is searched.
265
+ * @param [excluding] {Array} A list of nodes to exclude from the search.
266
+ */
267
+ getClosestNode: function (point, including, excluding) {
268
+ const
269
+ p1 = Vector.setUp(point),
270
+ p2 = Vector.setUp(),
271
+ list = including || this.map;
272
+ let closest = null,
273
+ d = Infinity;
274
+
275
+ for (let i = 0; i < list.length; i++) {
276
+ const
277
+ m = p2.setVector(p1).subtractVector(list[i].position).magnitude();
278
+
279
+ if (m < d) {
280
+ if (excluding?.indexOf(list[i]) >= 0) {
281
+ break;
282
+ }
283
+
284
+ d = m;
285
+ closest = list[i];
286
+ }
287
+ }
288
+
289
+ p1.recycle();
290
+ p2.recycle();
291
+
292
+ return closest;
293
+ }
294
+ }
295
+ });