@makefully/platypus 4.1.5 → 4.1.6

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 +10 -0
  2. package/README.md +3 -3
  3. package/lib/platypus.js +1 -1
  4. package/package.json +6 -5
  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 +833 -0
  98. package/src/components/RenderSprite.js +527 -0
  99. package/src/components/RenderText.js +147 -0
  100. package/src/components/RenderTiles.js +1391 -0
  101. package/src/components/SceneChanger.js +128 -0
  102. package/src/components/TiledLoader.js +1451 -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,826 @@
1
+ import {arrayCache, greenSplice} from '../utils/array.js';
2
+ import AABB from '../AABB.js';
3
+ import CollisionShape from '../CollisionShape.js';
4
+ import Data from '../Data.js';
5
+ import DataMap from '../DataMap.js';
6
+ import Vector from '../Vector.js';
7
+ import createComponentClass from '../factory.js';
8
+
9
+ const
10
+ entityBroadcast = (function () {
11
+ const
12
+ stringBroadcast = function (event, collisionType, solidOrSoft, value) {
13
+ if (value.myType === collisionType) {
14
+ if (value.hitType === solidOrSoft) {
15
+ this.owner.triggerEvent(event, value);
16
+ }
17
+ }
18
+ },
19
+ arrayBroadcast = function (event, collisionType, solidOrSoft, value) {
20
+ if (value.myType === collisionType) {
21
+ if (value.hitType === solidOrSoft) {
22
+ for (let i = 0; i < event.length; i++) {
23
+ this.owner.triggerEvent(event[i], value);
24
+ }
25
+ }
26
+ }
27
+ },
28
+ directionalBroadcast = function (event, collisionType, solidOrSoft, collisionInfo) {
29
+ let dx = collisionInfo.x,
30
+ dy = collisionInfo.y;
31
+
32
+ if (collisionInfo.entity && !(dx || dy)) {
33
+ dx = collisionInfo.entity.x - this.owner.x;
34
+ dy = collisionInfo.entity.y - this.owner.y;
35
+ }
36
+
37
+ if (collisionInfo.myType === collisionType) {
38
+ if (collisionInfo.hitType === solidOrSoft) {
39
+ if ((dy > 0) && event.bottom) {
40
+ this.owner.trigger(event.bottom, collisionInfo);
41
+ } else if ((dy < 0) && event.top) {
42
+ this.owner.trigger(event.top, collisionInfo);
43
+ }
44
+ if ((dx > 0) && event.right) {
45
+ this.owner.trigger(event.right, collisionInfo);
46
+ } else if ((dx < 0) && event.left) {
47
+ this.owner.trigger(event.left, collisionInfo);
48
+ }
49
+ if (event.all) {
50
+ this.owner.trigger(event.all, collisionInfo);
51
+ }
52
+ }
53
+ }
54
+ };
55
+
56
+ return function (self, event, solidOrSoft) {
57
+ if (typeof event === 'string') {
58
+ return stringBroadcast.bind(self, event, self.collisionType, solidOrSoft);
59
+ } else if (Array.isArray(event)) {
60
+ return arrayBroadcast.bind(self, event, self.collisionType, solidOrSoft);
61
+ } else {
62
+ return directionalBroadcast.bind(self, event, self.collisionType, solidOrSoft);
63
+ }
64
+ };
65
+ }()),
66
+ setupCollisionFunctions = (function () {
67
+ const
68
+ entityGetAABB = function (aabb, colFuncs, collisionType) {
69
+ if (!collisionType) {
70
+ const
71
+ {keys} = colFuncs;
72
+ let i = keys.length
73
+
74
+ aabb.reset();
75
+ while (i--) {
76
+ aabb.include(colFuncs.get(keys[i]).getAABB());
77
+ }
78
+ return aabb;
79
+ } else {
80
+ const
81
+ funcs = colFuncs.get(collisionType);
82
+
83
+ if (funcs) {
84
+ return funcs.getAABB();
85
+ } else {
86
+ return null;
87
+ }
88
+ }
89
+ },
90
+ entityGetPreviousAABB = function (colFuncs, collisionType) {
91
+ const
92
+ colFunc = colFuncs.get(collisionType);
93
+
94
+ if (colFunc) {
95
+ return colFunc.getPreviousAABB();
96
+ } else {
97
+ return null;
98
+ }
99
+ },
100
+ entityGetShapes = function (colFuncs, collisionType) {
101
+ const
102
+ colFunc = colFuncs.get(collisionType);
103
+
104
+ if (colFunc) {
105
+ return colFunc.getShapes();
106
+ } else {
107
+ return null;
108
+ }
109
+ },
110
+ entityGetPrevShapes = function (colFuncs, collisionType) {
111
+ const
112
+ colFunc = colFuncs.get(collisionType);
113
+
114
+ if (colFunc) {
115
+ return colFunc.getPrevShapes();
116
+ } else {
117
+ return null;
118
+ }
119
+ },
120
+ entityPrepareCollision = function (colFuncs, x, y) {
121
+ const
122
+ keys = colFuncs.keys;
123
+ let i = keys.length;
124
+
125
+ while (i--) {
126
+ colFuncs.get(keys[i]).prepareCollision(x, y);
127
+ }
128
+ },
129
+ entityRelocateEntity = (function () {
130
+ const
131
+ handleStuck = function (position, data, owner) {
132
+ let s = data.stuck;
133
+
134
+ if (s) {
135
+ const
136
+ m = position.magnitude();
137
+
138
+ if (data.thatShape.owner && (Math.abs(s) > 1)) {
139
+ s *= 0.05;
140
+ }
141
+ if (!m || (m > Math.abs(s))) {
142
+ if (data.vector.x) {
143
+ position.x = s;
144
+ position.y = 0;
145
+ }
146
+ if (data.vector.y) {
147
+ position.x = 0;
148
+ position.y = s;
149
+ }
150
+ if (owner.stuckWith) {
151
+ owner.stuckWith.recycle();
152
+ }
153
+ owner.stuckWith = Vector.setUp(data.thatShape.x, data.thatShape.y);
154
+ }
155
+ }
156
+ },
157
+ message = {
158
+ position: null,
159
+ unstick: null
160
+ };
161
+
162
+ return function (vector, collisionData) {
163
+ const
164
+ colX = collisionData.xData[0],
165
+ colY = collisionData.yData[0],
166
+ msg = message;
167
+ let v = null;
168
+
169
+ if (colX) {
170
+ v = Vector.setUp(0, 0, 0);
171
+ handleStuck(v, colX, this);
172
+ }
173
+
174
+ if (colY) {
175
+ v = v ?? Vector.setUp(0, 0, 0);
176
+ handleStuck(v, colY, this);
177
+ }
178
+
179
+ msg.position = vector;
180
+ msg.unstick = v;
181
+
182
+ /**
183
+ * This message causes the entity's x,y coordinates to update. (Usually after collision checks, but can be used to avoid collision checks during logic handling.)
184
+ *
185
+ * @event platypus.Entity#relocate-entity
186
+ * @param location {Object|platypus.Vector} The new coordinates.
187
+ * @param [location.position] {platypus.Vector} If specified, this vector is used instead of the passed-in object as the location.
188
+ * @param [location.relative=false] {boolean} Determines whether the provided x,y coordinates are relative to the entity's current position.
189
+ * @param [location.unstick=null] {platypus.Vector} Where the entity should be moved to unstick from collision contact.
190
+ * @param [relative] If `location.relative` is not specified, this parameter is also checked.
191
+ */
192
+ this.triggerEvent('relocate-entity', msg);
193
+
194
+ if (v) {
195
+ v.recycle();
196
+ }
197
+ };
198
+ }()),
199
+ entityMovePreviousX = function (colFuncs, x) {
200
+ const
201
+ {keys} = colFuncs;
202
+ let i = keys.length;
203
+
204
+ while (i--) {
205
+ colFuncs.get(keys[i]).movePreviousX(x);
206
+ }
207
+ },
208
+ entityGetCollisionTypes = function () {
209
+ return this.collisionTypes;
210
+ },
211
+ entityGetSolidCollisions = function () {
212
+ return this.solidCollisionMap;
213
+ },
214
+ getAABB = function () {
215
+ return this.getAABB();
216
+ },
217
+ getPreviousAABB = function () {
218
+ return this.getPreviousAABB();
219
+ },
220
+ getShapes = function () {
221
+ return this.getShapes();
222
+ },
223
+ getPrevShapes = function () {
224
+ return this.getPrevShapes();
225
+ },
226
+ prepareCollision = function (x, y) {
227
+ this.prepareCollision(x, y);
228
+ },
229
+ movePreviousX = function (x) {
230
+ this.movePreviousX(x);
231
+ };
232
+
233
+ return function (self, entity) {
234
+ let colFuncs = entity.collisionFunctions;
235
+
236
+ // This allows the same component type to be added multiple times.
237
+ if (!colFuncs) {
238
+ colFuncs = entity.collisionFunctions = DataMap.setUp();
239
+ entity.aabb = AABB.setUp();
240
+ entity.getAABB = entityGetAABB.bind(entity, entity.aabb, colFuncs);
241
+ entity.getPreviousAABB = entityGetPreviousAABB.bind(entity, colFuncs);
242
+ entity.getShapes = entityGetShapes.bind(entity, colFuncs);
243
+ entity.getPrevShapes = entityGetPrevShapes.bind(entity, colFuncs);
244
+ entity.prepareCollision = entityPrepareCollision.bind(entity, colFuncs);
245
+ entity.relocateEntity = entityRelocateEntity.bind(entity);
246
+ entity.movePreviousX = entityMovePreviousX.bind(entity, colFuncs);
247
+ entity.getCollisionTypes = entityGetCollisionTypes.bind(entity);
248
+ entity.getSolidCollisions = entityGetSolidCollisions.bind(entity);
249
+ }
250
+
251
+ colFuncs.set(self.collisionType, Data.setUp(
252
+ "getAABB", getAABB.bind(self),
253
+ "getPreviousAABB", getPreviousAABB.bind(self),
254
+ "getShapes", getShapes.bind(self),
255
+ "getPrevShapes", getPrevShapes.bind(self),
256
+ "prepareCollision", prepareCollision.bind(self),
257
+ "movePreviousX", movePreviousX.bind(self)
258
+ ));
259
+ };
260
+ }()),
261
+ updateShapesFull = function (shapes, prevs, aabb, x, y) {
262
+ let i = shapes.length;
263
+
264
+ while (i--) {
265
+ const shape = shapes[i];
266
+ shape.updateAll(prevs[i]);
267
+ shape.update(x, y);
268
+ aabb.include(shape.aABB);
269
+ }
270
+
271
+ // Done with the full update; back to fast!
272
+ this.updateShapes = updateShapesFast;
273
+ },
274
+ updateShapesFast = function (shapes, prevs, aabb, x, y) {
275
+ let i = shapes.length;
276
+
277
+ while (i--) {
278
+ const shape = shapes[i];
279
+ shape.update(x, y);
280
+ aabb.include(shape.aABB);
281
+ }
282
+ },
283
+ normalizeJumpThrough = function (jt) {
284
+ if (jt === true) {
285
+ return {
286
+ x: 0,
287
+ y: -1
288
+ };
289
+ }
290
+
291
+ if (!jt) {
292
+ return null;
293
+ }
294
+
295
+ return {
296
+ x: jt.x || 0,
297
+ y: jt.y || 0
298
+ };
299
+ };
300
+
301
+ export default createComponentClass(/** @lends platypus.components.CollisionBasic.prototype */{
302
+
303
+ id: 'CollisionBasic',
304
+
305
+ properties: {
306
+ /**
307
+ * Defines how this entity should be recognized by other colliding entities.
308
+ *
309
+ * @property collisionType
310
+ * @type String
311
+ * @default "none"
312
+ */
313
+ collisionType: "none",
314
+
315
+ /**
316
+ * Defines the type of colliding shape.
317
+ *
318
+ * @property shapeType
319
+ * @type String
320
+ * @default "rectangle"
321
+ */
322
+ shapeType: "rectangle",
323
+
324
+ /**
325
+ * Determines whether the collision area should transform on orientation changes.
326
+ *
327
+ * @property ignoreOrientation
328
+ * @type boolean
329
+ * @default false
330
+ */
331
+ ignoreOrientation: false,
332
+
333
+ /**
334
+ * Determines the x-axis center of the collision shape.
335
+ *
336
+ * @property regX
337
+ * @type number
338
+ * @default width / 2
339
+ */
340
+ regX: null,
341
+
342
+ /**
343
+ * Determines the y-axis center of the collision shape.
344
+ *
345
+ * @property regY
346
+ * @type number
347
+ * @default height / 2
348
+ */
349
+ regY: null,
350
+
351
+ /**
352
+ * Sets the width of the collision area in world coordinates.
353
+ *
354
+ * @property width
355
+ * @type number
356
+ * @default 0
357
+ */
358
+ width: 0,
359
+
360
+ /**
361
+ * Sets the height of the collision area in world coordinates.
362
+ *
363
+ * @property height
364
+ * @type number
365
+ * @default 0
366
+ */
367
+ height: 0,
368
+
369
+ /**
370
+ * Sets the radius of a circle collision area in world coordinates.
371
+ *
372
+ * @property radius
373
+ * @type number
374
+ * @default 0
375
+ */
376
+ radius: 0,
377
+
378
+ /**
379
+ * Determines which collision types this entity should consider soft, meaning this entity may pass through them, but triggers collision messages on doing so. Example:
380
+ *
381
+ * {
382
+ * "water": "soaked", // This triggers a "soaked" message on the entity when it passes over a "water" collision-type entity.
383
+ * "lava": ["burn", "ouch"] // This triggers both messages on the entity when it passes over a "lava" collision-type entity.
384
+ * }
385
+ *
386
+ * @property softCollisions
387
+ * @type Object
388
+ * @default null
389
+ */
390
+ softCollisions: null,
391
+
392
+ /**
393
+ * Determines which collision types this entity should consider solid, meaning this entity should not pass through them. Example:
394
+ *
395
+ * {
396
+ * "boulder": "", // This specifies that this entity should not pass through other "boulder" collision-type entities.
397
+ * "diamond": "crack-up", // This specifies that this entity should not pass through "diamond" collision-type entities, but if it touches one, it triggers a "crack-up" message on the entity.
398
+ * "marble": ["flip", "dance", "crawl"] // This specifies that this entity should not pass through "marble" collision-type entities, but if it touches one, it triggers all three specified messages on the entity.
399
+ * }
400
+ *
401
+ * @property solidCollisions
402
+ * @type Object
403
+ * @default null
404
+ */
405
+ solidCollisions: null,
406
+
407
+ /**
408
+ * This is the margin around the entity's width and height. This is an alternative method for specifying the collision shape in terms of the size of the entity. Can also pass in an object specifying the following parameters if the margins vary per side: top, bottom, left, and right.
409
+ *
410
+ * @property margin
411
+ * @type number|Object
412
+ * @default 0
413
+ */
414
+ margin: 0,
415
+
416
+ /**
417
+ * Defines one or more shapes to create the collision area. Defaults to a single shape with the width, height, regX, and regY properties of the entity if not specified. See [CollisionShape](CollisionShape.html) for the full list of properties.
418
+ *
419
+ * @property shapes
420
+ * @type Array
421
+ * @default null
422
+ */
423
+ shapes: null
424
+ },
425
+
426
+ publicProperties: {
427
+ collisionDirty: false,
428
+
429
+ /**
430
+ * This property should be set to true if entity doesn't move for better optimization. This causes other entities to check against this entity, but this entity performs no checks of its own. Available on the entity as `entity.immobile`.
431
+ *
432
+ * @property immobile
433
+ * @type boolean
434
+ * @default false
435
+ */
436
+ immobile: false,
437
+
438
+ /**
439
+ * Whether this entity should be tested across its entire movement path. This is necessary for fast-moving entities, but shouldn't be used for others due to the processing overhead. Available on the entity as `entity.bullet`.
440
+ *
441
+ * @property bullet
442
+ * @type boolean
443
+ * @default false
444
+ */
445
+ bullet: false,
446
+
447
+ /**
448
+ * Whether the entity is only solid when being collided with from the top.
449
+ *
450
+ * @property jumpThrough
451
+ * @type boolean
452
+ * @default: false
453
+ */
454
+ jumpThrough: false
455
+ },
456
+
457
+ /**
458
+ * This component causes this entity to collide with other entities. It must be part of a collision group and will receive messages when colliding with other entities in the collision group.
459
+ *
460
+ * Multiple collision components may be added to a single entity if distinct messages should be triggered for certain collision areas on the entity or if the soft collision area is a different shape from the solid collision area. Be aware that too many additional collision areas may adversely affect performance.
461
+ *
462
+ * On receiving a 'hit-by' message, custom messages may be triggered on the entity corresponding with the component's `solidCollisions` and `softCollisions` key/value mappings.
463
+ *
464
+ * @memberof platypus.components
465
+ * @uses platypus.Component
466
+ * @constructs
467
+ * @listens platypus.Entity#collide-off
468
+ * @listens platypus.Entity#collide-on
469
+ * @listens platypus.Entity#handle-logic
470
+ * @listens platypus.Entity#hit-by-*
471
+ * @listens platypus.Entity#orientation-updated
472
+ * @listens platypus.Entity#relocate-entity
473
+ * @fires platypus.Entity#add-collision-entity
474
+ * @fires platypus.Entity#relocate-entity
475
+ * @fires platypus.Entity#remove-collision-entity
476
+ */
477
+ initialize: function (definition) {
478
+ const
479
+ {
480
+ height,
481
+ margin = 0,
482
+ owner,
483
+ radius,
484
+ regX = this.width / 2,
485
+ regY = this.height / 2,
486
+ width
487
+ } = this,
488
+ marginLeft = margin.left ?? margin,
489
+ marginRight = margin.right ?? margin,
490
+ marginTop = margin.top ?? margin,
491
+ marginBottom = margin.bottom ?? margin;
492
+ let shapes = null;
493
+
494
+ Vector.assign(this.owner, 'position', 'x', 'y', 'z');
495
+ Vector.assign(this.owner, 'previousPosition', 'previousX', 'previousY', 'previousZ');
496
+ this.owner.previousX = this.owner.previousX || this.owner.x;
497
+ this.owner.previousY = this.owner.previousY || this.owner.y;
498
+
499
+ this.aabb = AABB.setUp();
500
+ this.prevAABB = AABB.setUp();
501
+
502
+ if (this.shapes) {
503
+ shapes = this.shapes;
504
+ } else if (this.shapeType === 'circle') {
505
+ const
506
+ shapeRadius = radius || (((width || 0) + (height || 0)) / 4);
507
+
508
+ shapes = [{
509
+ regX: (isNaN(regX) ? shapeRadius : regX) - (marginRight - marginLeft) / 2,
510
+ regY: (isNaN(regY) ? shapeRadius : regY) - (marginBottom - marginTop) / 2,
511
+ radius: shapeRadius,
512
+ type: this.shapeType
513
+ }];
514
+ } else {
515
+ shapes = [{
516
+ //regX: (isNaN(regX) ? (width || 0) / 2 : regX) - (marginRight - marginLeft) / 2,
517
+ //regY: (isNaN(regY) ? (height || 0) / 2 : regY) - (marginBottom - marginTop) / 2,
518
+ regX: (isNaN(regX) ? (width || 0) / 2 : regX) + marginLeft,
519
+ regY: (isNaN(regY) ? (height || 0) / 2 : regY) + marginTop,
520
+ points: definition.points,
521
+ width: (width || 0) + marginLeft + marginRight,
522
+ height: (height || 0) + marginTop + marginBottom,
523
+ type: this.shapeType
524
+ }];
525
+ }
526
+
527
+ this.owner.collisionTypes = this.owner.collisionTypes || arrayCache.setUp();
528
+ this.owner.collisionTypes.push(this.collisionType);
529
+
530
+ this.shapes = arrayCache.setUp();
531
+ this.prevShapes = arrayCache.setUp();
532
+ this.entities = null;
533
+ for (let x = 0; x < shapes.length; x++) {
534
+ const
535
+ shape = shapes[x],
536
+ shapeDefinition = {
537
+ ...shape,
538
+ jumpThrough: normalizeJumpThrough(typeof shape.jumpThrough === 'undefined' ? this.jumpThrough : shape.jumpThrough)
539
+ };
540
+
541
+ this.shapes.push(CollisionShape.setUp(this.owner, shapeDefinition, this.collisionType));
542
+ this.prevShapes.push(CollisionShape.setUp(this.owner, shapeDefinition, this.collisionType));
543
+ this.prevAABB.include(this.prevShapes[x].aABB);
544
+ this.aabb.include(this.shapes[x].aABB);
545
+ }
546
+
547
+ this.updateShapes = updateShapesFast;
548
+
549
+ setupCollisionFunctions(this, this.owner);
550
+
551
+ owner.softCollisionMap = owner.softCollisionMap ?? DataMap.setUp();
552
+ owner.solidCollisionMap = owner.solidCollisionMap ?? DataMap.setUp();
553
+ {
554
+ const
555
+ softCollisions = this.softCollisions,
556
+ keys = softCollisions ? Object.keys(softCollisions) : arrayCache.setUp(),
557
+ {length} = keys;
558
+
559
+ for (let i = 0; i < length; i++) {
560
+ const
561
+ key = keys[i];
562
+
563
+ if (softCollisions[key]) { // To make sure it's not an empty string.
564
+ this.addEventListener(`hit-by-${key}`, entityBroadcast(this, softCollisions[key], 'soft'));
565
+ }
566
+ }
567
+ owner.softCollisionMap.set(this.collisionType, keys);
568
+ }
569
+ {
570
+ const
571
+ solidCollisions = this.solidCollisions,
572
+ keys = solidCollisions ? Object.keys(solidCollisions) : arrayCache.setUp(),
573
+ {length} = keys;
574
+
575
+ for (let i = 0; i < length; i++) {
576
+ const
577
+ key = keys[i];
578
+
579
+ if (solidCollisions[key]) { // To make sure it's not an empty string.
580
+ this.addEventListener(`hit-by-${key}`, entityBroadcast(this, solidCollisions[key], 'solid'));
581
+ }
582
+ }
583
+ owner.solidCollisionMap.set(this.collisionType, keys);
584
+ }
585
+
586
+ this.active = true;
587
+ this.stuck = false;
588
+ },
589
+
590
+ events: {
591
+ /**
592
+ * On receiving this message, the component triggers `add-collision-entity` on the parent.
593
+ *
594
+ * @event platypus.Entity#collide-on
595
+ * @param type {String} If specified, only collision components of this type are added to the collision list.
596
+ */
597
+ "collide-on": function (type) {
598
+ const
599
+ {collisionType, owner} = this,
600
+ {collisionTypes} = owner;
601
+
602
+ /**
603
+ * On receiving 'collide-on', this message is triggered on the parent to turn on collision.
604
+ *
605
+ * @event platypus.Entity#add-collision-entity
606
+ * @param {platypus.Entity} entity The entity this component is attached to.
607
+ */
608
+ if (!this.active && ((typeof type !== 'string') || (type === collisionType))) {
609
+ owner.parent.triggerEvent('remove-collision-entity', owner);
610
+ if (collisionTypes.indexOf(collisionType) === -1) {
611
+ collisionTypes.push(collisionType);
612
+ }
613
+ owner.parent.triggerEvent('add-collision-entity', owner);
614
+ this.active = true;
615
+ this.collisionDirty = true;
616
+ }
617
+ },
618
+
619
+ /**
620
+ * On receiving this message, the component triggers `remove-collision-entity` on the parent.
621
+ *
622
+ * @event platypus.Entity#collide-off
623
+ * @param type {String} If specified, only collision components of this type are removed from the collision list.
624
+ */
625
+ "collide-off": function (type) {
626
+ const
627
+ {collisionType, owner} = this,
628
+ {collisionTypes, parent} = owner;
629
+
630
+ /**
631
+ * On receiving 'collide-off', this message is triggered on the parent to turn off collision.
632
+ *
633
+ * @event platypus.Entity#remove-collision-entity
634
+ * @param {platypus.Entity} entity The entity this component is attached to.
635
+ */
636
+ if (this.active && ((typeof type !== 'string') || (type === collisionType))) {
637
+ parent.triggerEvent('remove-collision-entity', owner);
638
+ const
639
+ index = collisionTypes.indexOf(collisionType);
640
+
641
+ if (index >= 0) {
642
+ greenSplice(collisionTypes, index);
643
+ }
644
+ this.active = false;
645
+
646
+ if (collisionTypes.length) {
647
+ parent.triggerEvent('add-collision-entity', owner);
648
+ }
649
+ }
650
+ },
651
+
652
+ "relocate-entity": function (location, relative) {
653
+ const
654
+ {aabb, owner, shapes} = this,
655
+ unstick = location.unstick,
656
+ um = unstick?.magnitude() ?? 0,
657
+ v = location.position ?? location;
658
+ let i = shapes.length,
659
+ x = 0,
660
+ y = 0;
661
+
662
+ if (this.move) {
663
+ this.move.recycle();
664
+ this.move = null;
665
+ }
666
+
667
+ if (location.relative || relative) {
668
+ owner.position.setVector(owner.previousPosition).add(v);
669
+ } else {
670
+ owner.position.setVector(v);
671
+ }
672
+
673
+ if (this.stuck) {
674
+ if (um > 0) {
675
+ owner.position.add(unstick);
676
+ } else {
677
+ this.stuck = false;
678
+ }
679
+ }
680
+
681
+ x = owner.x;
682
+ y = owner.y;
683
+
684
+ aabb.reset();
685
+ i = shapes.length;
686
+ while (i--) {
687
+ const
688
+ shape = shapes[i];
689
+
690
+ shape.update(x, y);
691
+ aabb.include(shape.aABB);
692
+ }
693
+
694
+ owner.previousPosition.setVector(owner.position);
695
+
696
+ if (um > 0) { // to force check in all directions for ultimate stuck resolution (esp. for stationary entities)
697
+ if (!this.stuck) {
698
+ this.stuck = true;
699
+ }
700
+ this.move = owner.stuckWith.copy().add(-x, -y).normalize();
701
+ }
702
+ },
703
+
704
+ "handle-logic": function () {
705
+ if (this.move) {
706
+ this.owner.position.add(this.move); // By trying to move into it, we should get pushed back out.
707
+ }
708
+ },
709
+
710
+ "orientation-updated": function (matrix) {
711
+ if (!this.ignoreOrientation) {
712
+ for (let i = 0; i < this.shapes.length; i++) {
713
+ this.shapes[i].multiply(matrix);
714
+ }
715
+ this.updateShapes = updateShapesFull;
716
+ this.collisionDirty = true;
717
+ }
718
+ }
719
+ },
720
+
721
+ methods: {
722
+ getAABB: function () {
723
+ return this.aabb;
724
+ },
725
+
726
+ getPreviousAABB: function () {
727
+ return this.prevAABB;
728
+ },
729
+
730
+ getShapes: function () {
731
+ return this.shapes;
732
+ },
733
+
734
+ getPrevShapes: function () {
735
+ return this.prevShapes;
736
+ },
737
+
738
+ prepareCollision: function (x, y) {
739
+ const
740
+ prevShapes = this.shapes,
741
+ shapes = this.prevShapes,
742
+ aabb = this.aabb;
743
+
744
+ this.owner.x = x;
745
+ this.owner.y = y;
746
+
747
+ this.prevShapes = prevShapes;
748
+ this.shapes = shapes;
749
+
750
+ this.prevAABB.set(aabb);
751
+ aabb.reset();
752
+
753
+ this.updateShapes(shapes, prevShapes, aabb, x, y);
754
+
755
+ if (this.collisionDirty) {
756
+ this.collisionDirty = false;
757
+ }
758
+ },
759
+
760
+ movePreviousX: function (x) {
761
+ this.prevAABB.moveX(x);
762
+ for (let i = 0; i < this.prevShapes.length; i++) {
763
+ this.prevShapes[i].setXWithEntityX(x);
764
+ }
765
+ },
766
+
767
+ destroy: function () {
768
+ const
769
+ {collisionType, owner} = this,
770
+ {collisionFunctions, collisionTypes, parent, softCollisionMap, solidCollisionMap} = owner;
771
+ let i = collisionTypes ? collisionTypes.indexOf(collisionType) : -1;
772
+
773
+ parent.triggerEvent('remove-collision-entity', owner);
774
+
775
+ this.aabb.recycle();
776
+ delete this.aabb;
777
+ this.prevAABB.recycle();
778
+ delete this.prevAABB;
779
+
780
+ if (i >= 0) {
781
+ greenSplice(collisionTypes, i);
782
+ }
783
+
784
+ if (collisionTypes) {
785
+ if (solidCollisionMap.has(collisionType)) {
786
+ arrayCache.recycle(solidCollisionMap.delete(collisionType));
787
+ }
788
+ if (softCollisionMap.has(collisionType)) {
789
+ arrayCache.recycle(softCollisionMap.delete(collisionType));
790
+ }
791
+
792
+ collisionFunctions.delete(collisionType).recycle();
793
+ }
794
+
795
+ i = this.shapes.length;
796
+ while (i--) {
797
+ this.shapes[i].recycle();
798
+ this.prevShapes[i].recycle();
799
+ }
800
+ arrayCache.recycle(this.shapes);
801
+ arrayCache.recycle(this.prevShapes);
802
+ this.shapes = null;
803
+ this.prevShapes = null;
804
+
805
+ this.entities = null;
806
+
807
+ if (collisionTypes) {
808
+ if (collisionTypes.length) {
809
+ parent.triggerEvent('add-collision-entity', owner);
810
+ } else { //remove collision functions
811
+ collisionFunctions.recycle();
812
+ owner.collisionFunctions = null;
813
+ solidCollisionMap.recycle();
814
+ owner.solidCollisionMap = null;
815
+ softCollisionMap.recycle();
816
+ owner.softCollisionMap = null;
817
+ owner.aabb.recycle();
818
+ owner.aabb = null;
819
+ arrayCache.recycle(collisionTypes);
820
+ owner.collisionTypes = null;
821
+ }
822
+ }
823
+ }
824
+ }
825
+ });
826
+