@makefully/platypus 4.1.4 → 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 (134) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -2
  3. package/lib/platypus.js +1 -1
  4. package/package.json +7 -2
  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
@@ -0,0 +1,315 @@
1
+ import AABB from './AABB.js';
2
+ import Vector from './Vector.js';
3
+ import recycle from 'recycle';
4
+
5
+ const
6
+ circleRectCollision = function (circle, rect) {
7
+ const
8
+ rectAabb = rect.aABB,
9
+ hh = rectAabb.halfHeight,
10
+ hw = rectAabb.halfWidth,
11
+ shapeDistanceX = Math.abs(circle.x - rect.x),
12
+ shapeDistanceY = Math.abs(circle.y - rect.y),
13
+ radius = circle.radius;
14
+
15
+ /* This checks the following in order:
16
+ - Is the x or y distance between shapes less than half the width or height respectively of the rectangle? If so, we know they're colliding.
17
+ - Is the x or y distance between the shapes greater than the half width/height plus the radius of the circle? Then we know they're not colliding.
18
+ - Otherwise, we check the distance between a corner of the rectangle and the center of the circle. If that distance is less than the radius of the circle, we know that there is a collision; otherwise there is not.
19
+ */
20
+ return (shapeDistanceX < hw) || (shapeDistanceY < hh) || ((shapeDistanceX < (hw + radius)) && (shapeDistanceY < (hh + radius)) && ((((shapeDistanceX - hw) ** 2) + ((shapeDistanceY - hh) ** 2)) < radius ** 2));
21
+ },
22
+ collidesCircle = function (shape) {
23
+ return this.aABB.collides(shape.aABB) && (
24
+ ((shape.type === 'rectangle') && circleRectCollision(this, shape)) ||
25
+ ((shape.type === 'circle') && ((((this.x - shape.x) ** 2) + ((this.y - shape.y) ** 2)) <= ((this.radius + shape.radius) ** 2)))
26
+ );
27
+ },
28
+ collidesDefault = function () {
29
+ return false;
30
+ },
31
+ collidesRectangle = function (shape) {
32
+ return this.aABB.collides(shape.aABB) && (
33
+ (shape.type === 'rectangle') ||
34
+ ((shape.type === 'circle') && circleRectCollision(shape, this))
35
+ );
36
+ },
37
+ /**
38
+ * This class defines a collision shape, which defines the 'space' an entity occupies in the collision system. Currently only rectangle and circle shapes can be created. Collision shapes include an axis-aligned bounding box (AABB) that tightly wraps the shape. The AABB is used for initial collision checks.
39
+ *
40
+ * @memberof platypus
41
+ * @class CollisionShape
42
+ * @param owner {platypus.Entity} The entity that uses this shape.
43
+ * @param definition {Object} This is an object of key/value pairs describing the shape.
44
+ * @param definition.x {number} The x position of the shape. The x is always located in the center of the object.
45
+ * @param definition.y {number} The y position of the shape. The y is always located in the center of the object.
46
+ * @param [definition.type="rectangle"] {String} The type of shape this is. Currently this can be either "rectangle" or "circle".
47
+ * @param [definition.jumpThrough] {Object} x/y unit determining jump-through face.
48
+ * @param [definition.width] {number} The width of the shape if it's a rectangle.
49
+ * @param [definition.height] {number} The height of the shape if it's a rectangle.
50
+ * @param [definition.radius] {number} The radius of the shape if it's a circle.
51
+ * @param [definition.offsetX] {number} The x offset of the collision shape from the owner entity's location.
52
+ * @param [definition.offsetY] {number} The y offset of the collision shape from the owner entity's location.
53
+ * @param [definition.regX] {number} The registration x of the collision shape with the owner entity's location if offsetX is not provided.
54
+ * @param [definition.regY] {number} The registration y of the collision shape with the owner entity's location if offsetX is not provided.
55
+ * @param collisionType {String} A string describing the collision type of this shape.
56
+ */
57
+ CollisionShape = function (owner, definition, collisionType) {
58
+ const
59
+ {x, y} = owner ?? definition,
60
+ {offsetX, offsetY, radius = 0, type = 'rectangle'} = definition,
61
+ diameter = radius * 2,
62
+ width = type === 'circle' ? diameter : definition.width ?? diameter,
63
+ height = type === 'circle' ? diameter : definition.height ?? diameter,
64
+ regX = definition.regX ?? (width / 2),
65
+ regY = definition.regY ?? (height / 2);
66
+
67
+ // If this shape is recycled, the vectors will already be in place.
68
+ if (!this.initialized) {
69
+ this.initialized = true;
70
+ Vector.assign(this, 'offset', 'offsetX', 'offsetY');
71
+ Vector.assign(this, 'position', 'x', 'y');
72
+ Vector.assign(this, 'size', 'width', 'height');
73
+ this.aABB = AABB.setUp();
74
+ }
75
+
76
+ this.owner = owner;
77
+ this.collisionType = collisionType;
78
+ this.jumpThrough = definition.jumpThrough ? Vector.setUp(definition.jumpThrough.x, definition.jumpThrough.y) : null;
79
+ this.type = type;
80
+ this.subType = '';
81
+
82
+ /**
83
+ * Determines whether shapes collide.
84
+ *
85
+ * @method platypus.CollisionShape#collides
86
+ * @param shape {platypus.CollisionShape} The shape to check against for collision.
87
+ * @return {Boolean} Whether the shapes collide.
88
+ */
89
+ if (type === 'circle') {
90
+ this.collides = collidesCircle;
91
+ } else if (type === 'rectangle') {
92
+ this.collides = collidesRectangle;
93
+ } else {
94
+ this.collides = collidesDefault;
95
+ }
96
+ this.size.setXYZ(width, height);
97
+ this.radius = radius;
98
+
99
+ this.offset.setXYZ(offsetX ?? ((width / 2) - regX), offsetY ?? ((height / 2) - regY));
100
+ this.position.setXYZ(x, y).add(this.offset);
101
+ this.aABB.setAll(this.x, this.y, width, height);
102
+ },
103
+ proto = CollisionShape.prototype;
104
+
105
+ /**
106
+ * Updates the shape to match another shape.
107
+ *
108
+ * @method platypus.CollisionShape#updateAll
109
+ * @param updateAll {platypus.CollisionShape} The shape to copy into this one.
110
+ */
111
+ proto.updateAll = function (shape) {
112
+ this.owner = shape.owner;
113
+ this.collisionType = shape.collisionType;
114
+ this.type = shape.type;
115
+ this.subType = shape.subType;
116
+ this.offset.x = shape.offset.x;
117
+ this.offset.y = shape.offset.y;
118
+ this.position.x = shape.position.x;
119
+ this.position.y = shape.position.y;
120
+ this.size.x = shape.size.x;
121
+ this.size.y = shape.size.y;
122
+ this.radius = shape.radius;
123
+ this.aABB.setAll(this.x, this.y, this.width, this.height);
124
+ if (this.type === 'circle') {
125
+ this.collides = collidesCircle;
126
+ } else if (this.type === 'rectangle') {
127
+ this.collides = collidesRectangle;
128
+ } else {
129
+ this.collides = collidesDefault;
130
+ }
131
+ };
132
+
133
+ /**
134
+ * Updates the location of the shape and AABB. The position you send should be that of the owner, the offset of the shape is added inside the function.
135
+ *
136
+ * @method platypus.CollisionShape#update
137
+ * @param ownerX {number} The x position of the owner.
138
+ * @param ownerY {number} The y position of the owner.
139
+ */
140
+ proto.update = function (ownerX, ownerY) {
141
+ const
142
+ x = ownerX + this.offsetX,
143
+ y = ownerY + this.offsetY;
144
+
145
+ this.position.setXYZ(x, y);
146
+ this.aABB.move(x, y);
147
+ };
148
+
149
+ /**
150
+ * Move the shape's x position.
151
+ *
152
+ * @method platypus.CollisionShape#moveX
153
+ * @param x {number} The x position to which the shape should be moved.
154
+ */
155
+ proto.moveX = function (x) {
156
+ this.x = x;
157
+ this.aABB.moveX(x);
158
+ };
159
+
160
+ /**
161
+ * Move the shape's y position.
162
+ *
163
+ * @method platypus.CollisionShape#moveY
164
+ * @param y {number} The y position to which the shape should be moved.
165
+ */
166
+ proto.moveY = function (y) {
167
+ this.y = y;
168
+ this.aABB.moveY(y);
169
+ };
170
+
171
+ /**
172
+ * Move the shape's x and y position.
173
+ *
174
+ * @method platypus.CollisionShape#moveXY
175
+ * @param x {number} The x position to which the shape should be moved.
176
+ * @param y {number} The y position to which the shape should be moved.
177
+ */
178
+ proto.moveXY = function (x, y) {
179
+ this.x = x;
180
+ this.y = y;
181
+ this.aABB.move(x, y);
182
+ };
183
+
184
+ /**
185
+ * Returns the axis-aligned bounding box of the shape.
186
+ *
187
+ * @method platypus.CollisionShape#getAABB
188
+ * @return {platypus.AABB} The AABB of the shape.
189
+ */
190
+ proto.getAABB = function () {
191
+ return this.aABB;
192
+ };
193
+
194
+ /**
195
+ * Set the shape's position as if the entity's x position is in a certain location.
196
+ *
197
+ * @method platypus.CollisionShape#setXWithEntityX
198
+ * @param entityX {number} The x position of the entity.
199
+ */
200
+ proto.setXWithEntityX = function (entityX) {
201
+ this.x = entityX + this.offsetX;
202
+ this.aABB.moveX(this.x);
203
+ };
204
+
205
+ /**
206
+ * Set the shape's position as if the entity's y position is in a certain location.
207
+ *
208
+ * @method platypus.CollisionShape#setYWithEntityY
209
+ * @param entityY {number} The y position of the entity.
210
+ */
211
+ proto.setYWithEntityY = function (entityY) {
212
+ this.y = entityY + this.offsetY;
213
+ this.aABB.moveY(this.y);
214
+ };
215
+
216
+ /**
217
+ * Transform the shape using a matrix transformation.
218
+ *
219
+ * @method platypus.CollisionShape#multiply
220
+ * @param matrix {Array} A matrix used to transform the shape.
221
+ */
222
+ proto.multiply = function (m) {
223
+ const
224
+ pos = this.position,
225
+ own = this.owner.position;
226
+
227
+ pos.subtractVector(own);
228
+
229
+ pos.multiply(m);
230
+ this.offset.multiply(m);
231
+ this.size.multiply(m);
232
+
233
+ pos.addVector(own);
234
+ this.width = Math.abs(this.width);
235
+ this.height = Math.abs(this.height);
236
+
237
+ this.aABB.setAll(this.x, this.y, this.width, this.height);
238
+ };
239
+
240
+ /**
241
+ * Expresses whether this shape contains the given point.
242
+ *
243
+ * @method platypus.CollisionShape#containsPoint
244
+ * @param x {number} The x-axis value.
245
+ * @param y {number} The y-axis value.
246
+ * @return {boolean} Returns `true` if this shape contains the point.
247
+ */
248
+ proto.containsPoint = function (x, y) {
249
+ return this.aABB.containsPoint(x, y) && (
250
+ (this.type === 'rectangle') ||
251
+ ((this.type === 'circle') && ((((this.x - x) ** 2) + ((this.y - y) ** 2)) <= this.radius ** 2))
252
+ );
253
+ };
254
+
255
+ /**
256
+ * Returns a JSON object describing the collision shape.
257
+ *
258
+ * @method platypus.CollisionShape#toJSON
259
+ * @return {Object} Returns a JSON definition that can be used to recreate the collision shape.
260
+ **/
261
+ proto.toJSON = function () {
262
+ const
263
+ json = {
264
+ type: this.type
265
+ },
266
+ width = this.size.width,
267
+ height = this.size.height;
268
+
269
+ if (width / 2 !== this.regX) {
270
+ json.regX = this.regX;
271
+ }
272
+ if (height / 2 !== this.regY) {
273
+ json.regY = this.regY;
274
+ }
275
+ if (this.offset.x !== ((width / 2) - this.regX)) {
276
+ json.offsetX = this.offset.x;
277
+ }
278
+ if (this.offset.y !== ((height / 2) - this.regY)) {
279
+ json.offsetY = this.offset.y;
280
+ }
281
+ if (this.type === 'circle') {
282
+ json.radius = this.radius;
283
+ } else {
284
+ json.width = width;
285
+ json.height = height;
286
+ }
287
+
288
+ return json;
289
+ };
290
+
291
+ /**
292
+ * Returns an CollisionShape from cache or creates a new one if none are available.
293
+ *
294
+ * @method platypus.CollisionShape.setUp
295
+ * @return {platypus.CollisionShape} The instantiated CollisionShape.
296
+ */
297
+ /**
298
+ * Returns a CollisionShape back to the cache.
299
+ *
300
+ * @method platypus.CollisionShape.recycle
301
+ * @param {platypus.CollisionShape} The CollisionShape to be recycled.
302
+ */
303
+ /**
304
+ * Relinquishes properties of the CollisionShape and recycles it.
305
+ *
306
+ * @method platypus.CollisionShape#recycle
307
+ */
308
+ recycle.add(CollisionShape, 'CollisionShape', CollisionShape, function () {
309
+ if (this.jumpThrough) {
310
+ this.jumpThrough.recycle();
311
+ }
312
+ this.jumpThrough = null;
313
+ }, true);
314
+
315
+ export default CollisionShape;
@@ -0,0 +1,231 @@
1
+ /*global platypus */
2
+ import {arrayCache, greenSplice} from './utils/array.js';
3
+ import Data from './Data.js';
4
+
5
+ /**
6
+ * This is the extendable Component class. Typically specific component classes should be created using `createComponentClass()`. This method accepts component definitions and creates component classes that can be used to create components by entities. It adds properties and methods that are common to all components so that component definitions can focus on unique properties and methods.
7
+ *
8
+ * To create an extended component class, use the following syntax:
9
+ *
10
+ * createComponentClass(componentDefinition, prototype);
11
+ *
12
+ * * `componentDefinition` is list of key/value pairs that describe the component's behavior.
13
+ * * `prototype` is an optional prototype that this component extends.
14
+ * See [component-template.js]("component-template"%20Component.html) for an example componentDefinition that can be sent into this component class factory.
15
+ *
16
+ * @memberof platypus
17
+ * @class Component
18
+ * @static
19
+ */
20
+ export default class Component {
21
+ constructor (type, owner, id) {
22
+ this.type = type;
23
+ this.owner = owner;
24
+ this.id = id;
25
+ this.publicMethods = Data.setUp();
26
+ this.listener = Data.setUp(
27
+ "events", arrayCache.setUp(),
28
+ "messages", arrayCache.setUp()
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Called by constructor once the component is ready.
34
+ *
35
+ * @method platypus.Component#initialize
36
+ */
37
+ initialize () {}
38
+
39
+ /**
40
+ * Returns a JSON object describing the component.
41
+ *
42
+ * @method platypus.Component#toJSON
43
+ * @return {Object} Returns a JSON definition that can be used to recreate the component.
44
+ **/
45
+ /* toJSON () {} */ // defined in factory.js
46
+
47
+ /**
48
+ * Returns a string describing the component.
49
+ *
50
+ * @method platypus.Component#toString
51
+ * @return {String} Returns the component type as a string of the form "[Component ComponentType]".
52
+ **/
53
+ toString () {
54
+ return "[Component " + this.type + "]";
55
+ }
56
+
57
+ /**
58
+ * This method cleans up listeners and methods that this component added to the entity. It should never be called by the component itself. Call this.owner.removeComponent(this) instead.
59
+ *
60
+ * @method platypus.Component#destroy
61
+ * @private
62
+ */
63
+ destroy () {
64
+ if (this.listener) {
65
+ const
66
+ publicMethods = this.publicMethods,
67
+ keys = Object.keys(publicMethods);
68
+ let i = keys.length;
69
+
70
+ // Handle component's destroy method before removing messaging and methods.
71
+ if (this._destroy) {
72
+ this._destroy();
73
+ }
74
+
75
+ // Now remove event listeners and methods.
76
+ while (i--) {
77
+ this.removeMethod(keys[i]);
78
+ }
79
+ this.publicMethods.recycle();
80
+
81
+ this.removeEventListeners();
82
+ arrayCache.recycle(this.listener.events);
83
+ arrayCache.recycle(this.listener.messages);
84
+ this.listener.recycle();
85
+ this.listener = null;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * This method removes multiple event listeners from the entity.
91
+ *
92
+ * @method platypus.Component#removeEventListeners
93
+ * @param [listeners] {Array} The list of listeners to remove. If not supplied, all event listeners are removed.
94
+ * @private
95
+ */
96
+ removeEventListeners (listeners) {
97
+ if (!listeners) {
98
+ const
99
+ {listener, owner} = this,
100
+ {events, messages} = listener,
101
+ {length} = events;
102
+
103
+ for (let i = 0; i < length; i++) {
104
+ owner.off(events[i], messages[i]);
105
+ }
106
+ events.length = 0;
107
+ messages.length = 0;
108
+ } else {
109
+ for (let i = 0; i < listeners.length; i++) {
110
+ this.removeEventListener(listeners[i]);
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * This method adds an event listener to the entity.
117
+ *
118
+ * @method platypus.Component#addEventListener
119
+ * @param event {String} The event that this component should listen for.
120
+ * @param callback {Function} The handler for the event.
121
+ * @return handler {Function} A reference to the bound handler.
122
+ * @private
123
+ */
124
+ addEventListener (event, callback, priority) {
125
+ const
126
+ handler = callback.bind(this); // <-- I think we need to stop doing this
127
+
128
+ this.listener.events.push(event);
129
+ this.listener.messages.push(handler);
130
+ this.owner.on(event, handler, priority);
131
+
132
+ return handler;
133
+ }
134
+
135
+ /**
136
+ * This method adds one or more event listeners to the entity and returns a teardown function.
137
+ *
138
+ * @method platypus.Component#addEventListener
139
+ * @param eventsObject {Object} Key/value pairs with event names for keys and handlers as values.
140
+ * @return {Function} Handler teardown function.
141
+ * @private
142
+ */
143
+ addEventListeners (eventsObject) {
144
+ const
145
+ {owner} = this,
146
+ {parent} = owner,
147
+ tds = Object.keys(eventsObject).map((key) => {
148
+ const
149
+ handler = this.addEventListener(key, eventsObject[key]);
150
+
151
+ return () => this.removeEventListener(key, handler);
152
+ });
153
+
154
+ if (owner.state.get('loaded')) {
155
+ parent.triggerEvent?.('child-entity-updated', owner);
156
+ }
157
+
158
+ return () => {
159
+ tds.forEach((td) => td());
160
+ parent.triggerEvent?.('child-entity-updated', owner);
161
+ };
162
+ }
163
+
164
+ /**
165
+ * This method adds a method to the entity.
166
+ *
167
+ * @method platypus.Component#addMethod
168
+ * @param name {String} The name of the method. For example, if name is "turnYellow", the method is accessible on the entity as `entity.turnYellow()`.
169
+ * @param func {Function} The function describing the method.
170
+ * @private
171
+ */
172
+ addMethod (name, func) {
173
+ if (this.owner[name]) {
174
+ platypus.debug.warn(this.owner.type + ': Entity already has a method called "' + name + '". Method not added.');
175
+ } else {
176
+ this.owner[name] = func.bind(this);
177
+ this.publicMethods[name] = func;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * This method removes an event listener from the entity.
183
+ *
184
+ * @method platypus.Component#removeEventListener
185
+ * @param event {String} The event for which to remove a listener.
186
+ * @param callback {Function} The listener to remove. If not supplied, all event listeners for the provided event are removed.
187
+ * @private
188
+ */
189
+ removeEventListener (event, callback) {
190
+ const
191
+ {listener, owner} = this,
192
+ {events, messages} = listener;
193
+
194
+ for (let i = events.length - 1; i >= 0; i--) {
195
+ if ((events[i] === event) && (!callback || (messages[i] === callback))) {
196
+ owner.off(event, messages[i]);
197
+ greenSplice(events, i);
198
+ greenSplice(messages, i);
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * This method removes a method from the entity.
205
+ *
206
+ * @method platypus.Component#removeMethod
207
+ * @param name {String} The name of the method to be removed.
208
+ * @private
209
+ */
210
+ removeMethod (name) {
211
+ if (!this.owner[name]) {
212
+ platypus.debug.warn(this.owner.type + ': Entity does not have a method called "' + name + '".');
213
+ } else {
214
+ delete this.owner[name];
215
+ }
216
+ delete this.publicMethods[name];
217
+ };
218
+
219
+ /**
220
+ * This method can be overwritten to provide the list of assets this component requires. This method is invoked when the list of game scenes is created to determine assets for each scene.
221
+ *
222
+ * @method platypus.Component#getAssetList
223
+ * @param definition {Object} The definition for the component.
224
+ * @param properties {Object} The properties of the Entity.
225
+ * @param defaultProperties {Object} The default properties of the Entity.
226
+ * @return {Array} A list of the necessary assets to load.
227
+ */
228
+ static getAssetList () {
229
+ return arrayCache.setUp();
230
+ }
231
+ }
package/src/Data.js ADDED
@@ -0,0 +1,64 @@
1
+ import recycle from 'recycle';
2
+
3
+ /**
4
+ * This class defines a generic data object to use for messaging. It includes recycle methods to encourage reuse.
5
+ *
6
+ * @memberof platypus
7
+ * @class Data
8
+ * @param {String|Object} first Can be an object of key/value pairs or the parameters can be an alternating list of keys and values.
9
+ * @return {Data} Returns the new Data object.
10
+ */
11
+ const
12
+ Data = function (first) {
13
+ let i = arguments.length;
14
+
15
+ if (first) {
16
+ if (typeof first === 'string') {
17
+ if (i % 2) {
18
+ this[i] = null;
19
+ i -= 1;
20
+ }
21
+ while (i) {
22
+ this[arguments[i - 2]] = arguments[i - 1];
23
+ i -= 2;
24
+ }
25
+ } else {
26
+ const
27
+ keys = Object.keys(first);
28
+ let j = keys.length;
29
+
30
+ while (j--) {
31
+ this[keys[j]] = first[keys[j]];
32
+ }
33
+ }
34
+ }
35
+ };
36
+
37
+ /**
38
+ * Returns Data from cache or creates a new one if none are available.
39
+ *
40
+ * @method platypus.Data.setUp
41
+ * @return {platypus.Data} The instantiated Data.
42
+ */
43
+ /**
44
+ * Returns Data back to the cache. Prefer the Data's recycle method since it recycles property objects as well.
45
+ *
46
+ * @method platypus.Data.recycle
47
+ * @param {platypus.Data} The Data to be recycled.
48
+ */
49
+ /**
50
+ * Relinquishes Data properties and recycles it.
51
+ *
52
+ * @method platypus.Data#recycle
53
+ */
54
+ recycle.add(Data, 'Data', Data, function () {
55
+ const
56
+ keys = Object.keys(this);
57
+ let i = keys.length;
58
+
59
+ while (i--) {
60
+ delete this[keys[i]];
61
+ }
62
+ }, true);
63
+
64
+ export default Data;