@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,382 @@
1
+ /**
2
+ ### Local Broadcasts:
3
+ - **[output messages]** - This component triggers output messages as determined by the JSON settings.
4
+
5
+ ## JSON Definition
6
+ {
7
+ "type": "LogicStateMachine",
8
+
9
+ "inputs":{
10
+ // This is a list of messages that this component should listen for to change states.
11
+
12
+ "smell-toast":{
13
+ // If the entity triggers "smell-toast", this component will change the state of the entity as follows:
14
+
15
+ "smelling-food": true,
16
+ "smelling-nothing": false
17
+ },
18
+
19
+ "go-to-store":{
20
+ "at-store": true
21
+ }
22
+ },
23
+
24
+ "sustained-inputs":{
25
+ // These are messages that must be triggered every tick for the state to remain true: if not, they become false.
26
+ "near-grover": "smelling-trash"
27
+ }
28
+ }
29
+ */
30
+ import {arrayCache, greenSplice} from '../utils/array.js';
31
+ import DataMap from '../DataMap.js';
32
+ import StateMap from '../StateMap.js';
33
+ import createComponentClass from '../factory.js';
34
+
35
+ const
36
+ setUpOutputs = function (outs) {
37
+ if (!outs || (typeof outs !== 'object') || Array.isArray(outs) || outs.event) {
38
+ return outs;
39
+ } else {
40
+ const
41
+ data = DataMap.setUp(),
42
+ keys = Object.keys(outs),
43
+ {length} = keys;
44
+
45
+ for (let i = 0; i < length; i++) {
46
+ const
47
+ key = keys[i];
48
+
49
+ data.set(key, setUpOutputs(outs[key]));
50
+ }
51
+ return data;
52
+ }
53
+ },
54
+ recycleOutputs = function (outs) {
55
+ if (outs instanceof DataMap) {
56
+ const
57
+ keys = outs.keys;
58
+ let i = keys.length;
59
+
60
+ while (i--) {
61
+ recycleOutputs(outs[keys[i]]);
62
+ }
63
+ outs.recycle();
64
+ }
65
+ },
66
+ handleResult = function ({title, state, last, checks, changed, self, queue, appendDetails}) {
67
+ const
68
+ keys = checks.keys,
69
+ message = checks.message ?? (checks.message === 0) ?? (checks.message === false);
70
+
71
+ if (changed) {
72
+ if (typeof checks === 'string') {
73
+ if (appendDetails) {
74
+ const
75
+ stateCopy = StateMap.setUp(state);
76
+
77
+ self.triggerEvent(checks, {
78
+ entity: self,
79
+ state: stateCopy
80
+ });
81
+
82
+ stateCopy.recycle();
83
+ } else {
84
+ self.triggerEvent(checks);
85
+ }
86
+ return;
87
+ } else if (Array.isArray(checks)) {
88
+ for (let i = 0; i < checks.length; i++) {
89
+ handleResult({title, state, last, checks: checks[i], changed, self, queue, appendDetails});
90
+ }
91
+ return;
92
+ } else if (checks.event && (message || checks.delay)) {
93
+ if (checks.delay) {
94
+ queue.push(checks);
95
+ } else if (appendDetails) {
96
+ const
97
+ stateCopy = StateMap.setUp(state);
98
+
99
+ self.trigger(checks.event, {
100
+ ...checks.message ?? {},
101
+ entity: self,
102
+ state: stateCopy
103
+ });
104
+
105
+ stateCopy.recycle();
106
+ } else {
107
+ self.trigger(checks.event, checks.message);
108
+ }
109
+ return;
110
+ } else if (checks.get) {
111
+ const
112
+ value = checks.get('true');
113
+
114
+ if (value) {
115
+ handleResult({title, state, last, checks: value, changed, self, queue, appendDetails});
116
+ }
117
+ }
118
+ }
119
+
120
+ if (keys) {
121
+ let i = keys.length;
122
+
123
+ while (i--) {
124
+ const
125
+ key = keys[i];
126
+
127
+ if (key !== 'true') {
128
+ handleOutput({title: key, state, last, checks: checks.get(key), changed, self, queue, appendDetails});
129
+ }
130
+ }
131
+ }
132
+ },
133
+ handleOutput = function ({title, state, last, checks, changed, self, queue, appendDetails}) {
134
+ let c = changed,
135
+ value = false;
136
+
137
+ if (title.charAt(0) === '!') {
138
+ const
139
+ st = title.substring(1),
140
+ stateValue = state.get(st);
141
+
142
+ value = (stateValue === false);
143
+ if ((title !== 'outputs') && (last.get(st) !== stateValue)) {
144
+ c = true;
145
+ }
146
+ } else {
147
+ const
148
+ stateValue = state.get(title);
149
+
150
+ value = (stateValue === true);
151
+ if ((title !== 'outputs') && (last.get(title) !== stateValue)) {
152
+ c = true;
153
+ }
154
+ }
155
+
156
+ if (value || (title === 'outputs')) {
157
+ handleResult({title, state, last, checks, changed: c, self, queue, appendDetails});
158
+ }
159
+ };
160
+
161
+ export default createComponentClass(/** @lends platypus.components.LogicStateMachine.prototype */{
162
+ id: 'LogicStateMachine',
163
+
164
+ properties: {
165
+ /**
166
+ * Whether `entity` and `state` values should be appended to output messages on events.
167
+ *
168
+ * @property appendDetails
169
+ * @type Boolean
170
+ * @default false
171
+ */
172
+ appendDetails: false,
173
+
174
+ /**
175
+ * This is the list of events containing key/value pairs that describe state changes to make for the given event.
176
+ *
177
+ * {
178
+ * "smell-toast": {
179
+ * "smelling-food": true,
180
+ * "smelling-nothing": false
181
+ * },
182
+ * "go-to-store": {
183
+ * "at-store": true
184
+ * }
185
+ * }
186
+ *
187
+ * @property inputs
188
+ * @type Object
189
+ * @default null
190
+ */
191
+ inputs: null,
192
+
193
+ /**
194
+ * These are messages that should be triggered when certain conditions are met. The messages are only triggered the instant the condition is met, until the conditions are no longer met and then once again met. Example:
195
+ *
196
+ * {
197
+ * "smelling-food": { // Keys map to states, and if true, the value of the key is processed. In this case, the value of the "smelling-food" key is another object of key/value pairs, giving us another layer of checks.
198
+ * "!smelling-trash": "time-to-eat", // This key is an inverse check, meaning that the "smelling-trash" state of the entity must be false to continue along this path. This time the value is a string, so the string "time-to-eat" is treated as a message to be broadcast if the entity is both "smelling-food" and not "smelling-trash".
199
+ * "true": "belly-rumble" // In some cases, a message should be triggered for a set of states, while still doing deeper state checks like above. "true" will always handle the next layer of values if the parent key was true.
200
+ * },
201
+ * "smelling-trash": "feeling-sick" // Multiple states can be handled to multiple depths, like a list of if () statements
202
+ * "!smelling-nothing": {
203
+ * "!smelling-trash":{
204
+ * "!at-store": "go-to-store", // Note that the "go-to-store" message will change this entity's state to "at-store" according to "inputs" above, but LogicStateMachine uses a cache of states when broadcasting output messages, so the next section will not be processed until the next state check.
205
+ * "at-store":{
206
+ * "have-money": "buy-more-food",
207
+ * "!have-money": "buy-less-food"
208
+ * }
209
+ * }
210
+ * }
211
+ * }
212
+ *
213
+ * @property outputs
214
+ * @type Object
215
+ * @default null
216
+ */
217
+ outputs: null
218
+ },
219
+
220
+ /**
221
+ * This component is a general purpose state-machine for an entity, taking in various message inputs to determine the entity's state and triggering messages as necessary when a certain state occurs or several state combinations are in place.
222
+ *
223
+ * @memberof platypus.components
224
+ * @uses platypus.Component
225
+ * @constructs
226
+ * @param {*} definition
227
+ * @listens platypus.Entity#handle-logic
228
+ * @listens platypus.Entity#state-changed
229
+ */
230
+ initialize: function (definition) {
231
+ const
232
+ inputDefinition = this.inputs,
233
+ susDef = definition["sustained-inputs"],
234
+ thisState = this.owner.state;
235
+
236
+ this.state = thisState;
237
+
238
+ if (inputDefinition) {
239
+ const
240
+ stateObjects = arrayCache.setUp(),
241
+ keys = Object.keys(inputDefinition),
242
+ {length} = keys;
243
+
244
+ for (let i = 0; i < length; i++) {
245
+ const
246
+ key = keys[i],
247
+ state = StateMap.setUp(inputDefinition[key]),
248
+ stateKeys = state.keys;
249
+ let j = stateKeys.length;
250
+
251
+ stateObjects.push(state);
252
+ this.addEventListener(key, () => {
253
+ thisState.update(state);
254
+ });
255
+
256
+ while (j--) {
257
+ if (!thisState.has(stateKeys[j])) { // set initial value to false if it's currently undefined.
258
+ thisState.set(stateKeys[j], false);
259
+ }
260
+ }
261
+ }
262
+ this.stateObjects = stateObjects;
263
+ }
264
+
265
+ this.sustainedState = StateMap.setUp();
266
+ if (susDef) {
267
+ const
268
+ keys = Object.keys(susDef),
269
+ {length} = keys,
270
+ {sustainedState} = this;
271
+
272
+ for (let i = 0; i < length; i++) {
273
+ const
274
+ key = keys[i],
275
+ definition = susDef[key];
276
+
277
+ this.addEventListener(key, () => {
278
+ sustainedState.set(definition, true);
279
+ });
280
+ sustainedState.set(susDef[key], false);
281
+ thisState.set(susDef[key], false);
282
+ }
283
+ }
284
+
285
+ this.snapshot = StateMap.setUp();
286
+ this.last = StateMap.setUp();
287
+ this.queueTimes = arrayCache.setUp();
288
+ this.queue = arrayCache.setUp();
289
+ this.outputs = setUpOutputs(this.outputs);
290
+ },
291
+
292
+ events: {
293
+ "handle-logic": function (resp) {
294
+ const
295
+ {state, sustainedState} = this,
296
+ keys = sustainedState.keys;
297
+ let i = keys.length;
298
+
299
+ while (i--) {
300
+ const
301
+ key = keys[i];
302
+
303
+ state.set(key, sustainedState.get(key));
304
+ sustainedState.set(key, false);
305
+ }
306
+
307
+ i = this.queue.length;
308
+ while (i--) {
309
+ this.queueTimes[i] -= resp.delta;
310
+
311
+ if (this.queueTimes[i] <= 0) {
312
+ this.owner.trigger(this.queue[i].event, this.queue[i].message);
313
+ greenSplice(this.queueTimes, i);
314
+ greenSplice(this.queue, i);
315
+ }
316
+ }
317
+ },
318
+
319
+ "update-state": function (state) {
320
+ this.state.update(state);
321
+ },
322
+
323
+ "state-changed": function (state) {
324
+ const
325
+ ss = this.snapshot;
326
+
327
+ if (this.outputs) {
328
+ const
329
+ queue = arrayCache.setUp();
330
+
331
+ ss.update(state);
332
+ handleOutput({
333
+ title: 'outputs',
334
+ state: ss,
335
+ last: this.last,
336
+ checks: this.outputs,
337
+ changed: false,
338
+ self: this.owner,
339
+ queue,
340
+ appendDetails: this.appendDetails
341
+ });
342
+
343
+ let i = queue.length;
344
+
345
+ while (i--) {
346
+ this.queue.push(queue[i]);
347
+ this.queueTimes.push(queue[i].delay);
348
+ }
349
+ arrayCache.recycle(queue);
350
+
351
+ this.last.update(ss);
352
+ }
353
+ }
354
+ },
355
+
356
+ methods: {
357
+ destroy: function () {
358
+ const
359
+ so = this.stateObjects;
360
+
361
+ arrayCache.recycle(this.queueTimes);
362
+ arrayCache.recycle(this.queue);
363
+
364
+ if (so) {
365
+ let i = so.length;
366
+
367
+ while (i--) {
368
+ so[i].recycle();
369
+ }
370
+ arrayCache.recycle(so);
371
+ this.stateObjects = null;
372
+ }
373
+
374
+ this.sustainedState.recycle();
375
+ this.snapshot.recycle();
376
+ this.last.recycle();
377
+
378
+ this.state = null;
379
+ this.inputs = null;
380
+ }
381
+ }
382
+ });
@@ -0,0 +1,77 @@
1
+ /**
2
+ ### Local Broadcasts:
3
+ - **switch-on** - This message is triggered when the switch has just been pressed.
4
+ - **switch-off** - This message is triggered when the switch has just been released.
5
+ - **initial-press** - This message is triggered the first time the switch is pressed. This occurs before the "switch-on" message is triggered.
6
+
7
+ ## JSON Definition:
8
+ {
9
+ "type": "LogicSwitch",
10
+
11
+ "sticky": true
12
+ // Optional. Whether a pressed switch should stay pressed once collision messages cease. Defaults to `false`.
13
+ }
14
+ */
15
+ import createComponentClass from '../factory.js';
16
+
17
+ export default (function () {
18
+ return createComponentClass(/** @lends platypus.components.LogicSwitch.prototype */{
19
+
20
+ id: 'LogicSwitch',
21
+
22
+ /**
23
+ * This component serves as a switch in the game world, typically tied to collision events such that this entity changes state when another entity collides or passed over.
24
+ *
25
+ * @memberof platypus.components
26
+ * @uses platypus.Component
27
+ * @constructs
28
+ * @param {*} definition
29
+ * @listens platypus.Entity#handle-logic
30
+ */
31
+ initialize: function (definition) {
32
+ this.state = this.owner.state;
33
+ this.pressed = false;
34
+ this.wasPressed = this.pressed;
35
+ this.sticky = definition.sticky || false;
36
+ this.state.set('pressed', false);
37
+ this.initialPress = true;
38
+ },
39
+
40
+ events: {// These are messages that this component listens for
41
+ "handle-logic": function () {
42
+ if (this.sticky) {
43
+ if (this.pressed && !this.wasPressed) {
44
+ this.state.set('pressed', true);
45
+ this.wasPressed = true;
46
+ this.owner.triggerEvent('switch-on');
47
+ }
48
+ } else {
49
+ if (this.pressed !== this.wasPressed) {
50
+ if (this.pressed) {
51
+ this.state.set('pressed', true);
52
+ this.owner.triggerEvent('switch-on');
53
+ } else {
54
+ this.state.set('pressed', false);
55
+ this.owner.triggerEvent('switch-off');
56
+ }
57
+ }
58
+ this.wasPressed = this.pressed;
59
+ this.pressed = false;
60
+ }
61
+ },
62
+ 'switch-pressed': function () {
63
+ this.pressed = true;
64
+ if (this.initialPress) {
65
+ this.owner.triggerEvent('initial-press');
66
+ this.initialPress = false;
67
+ }
68
+ }
69
+ },
70
+
71
+ methods: {
72
+ destroy: function () {
73
+ this.state = null;
74
+ }
75
+ }
76
+ });
77
+ }());
@@ -0,0 +1,68 @@
1
+ /**
2
+ ### Local Broadcasts:
3
+ - **teleport-complete** - Triggered once the entity has been moved to the new location.
4
+
5
+ ## JSON Definition
6
+ {
7
+ "type": "LogicTeleportee"
8
+ }
9
+ */
10
+ import Vector from '../Vector.js';
11
+ import createComponentClass from '../factory.js';
12
+
13
+ export default (function () {
14
+ return createComponentClass(/** @lends platypus.components.LogicTeleportee.prototype */{
15
+ id: 'LogicTeleportee',
16
+
17
+ /**
18
+ * This component causes an entity to teleport when receiving a teleport message.
19
+ *
20
+ * @memberof platypus.components
21
+ * @uses platypus.Component
22
+ * @constructs
23
+ * @param {*} definition
24
+ * @listens platypus.Entity#handle-logic
25
+ * @fires platypus.Entity#relocate-entity
26
+ */
27
+ initialize: function () {
28
+ this.teleportDestination = Vector.setUp();
29
+ this.teleportNow = false;
30
+ this.DestinationSet = false;
31
+ this.message = {
32
+ position: this.teleportDestination
33
+ };
34
+ },
35
+
36
+ events: {// These are messages that this component listens for
37
+ "handle-logic": function () {
38
+ if (this.teleportNow) {
39
+ this.owner.triggerEvent('relocate-entity', this.message);
40
+ this.teleportNow = false;
41
+ this.owner.triggerEvent('teleport-complete');
42
+ }
43
+ },
44
+ "teleport": function () {
45
+ if (this.destinationSet) {
46
+ this.teleportNow = true;
47
+ }
48
+ },
49
+ "set-destination": function (position) {
50
+ this.setDestination(position);
51
+ },
52
+ "hit-telepoint": function (collisionInfo) {
53
+ this.setDestination(collisionInfo.entity);
54
+ }
55
+ },
56
+
57
+ methods: {
58
+ setDestination: function (position) {
59
+ this.teleportDestination.setXYZ(position.x, position.y, this.owner.z);
60
+ this.destinationSet = true;
61
+ },
62
+
63
+ destroy: function () {
64
+ this.teleportDestination.recycle();
65
+ }
66
+ }
67
+ });
68
+ }());
@@ -0,0 +1,93 @@
1
+ /**
2
+ ### Listens for:
3
+ - **teleport-entity** - On receiving this message, the component will fire `teleport` on the colliding entity, sending this.destination. The colliding entity must handle the `teleport` message and relocate itself.
4
+ - @param message.x (integer) - uses `x` to determine if collision occurred on the left (-1) or right (1) of this entity.
5
+ - @param message.y (integer) - uses `y` to determine if collision occurred on the top (-1) or bottom (1) of this entity.
6
+ - @param message.entity (object) - triggers a `teleport` message on `entity`.
7
+
8
+ ### Peer Broadcasts:
9
+ - **teleport** - On receiving a `teleport-entity` message, if the colliding entity is colliding on the teleporter's facing side, this message is triggered on the colliding entity.
10
+ - @param message (object) - sends the destination entity as the message object, the x and y coordinates being the most important information for the listening entity.
11
+
12
+ ## JSON Definition:
13
+ {
14
+ "type": "LogicTeleporter",
15
+
16
+ "facing": "up",
17
+ // Optional: "up", "down", "left", or "right". Will only trigger "teleport" if colliding entity collides on the facing side of this entity. If nothing is specified, all collisions fire a "teleport" message on the colliding entity.
18
+
19
+ "teleportId": "Destination entity's linkId property"
20
+ // Required: String that matches the "linkId" property of the destination entity. This destination entity is passed on a "teleport" message so teleporting entity knows where to relocate.
21
+ }
22
+
23
+ */
24
+ import createComponentClass from '../factory.js';
25
+
26
+ export default (function () {
27
+ return createComponentClass(/** @lends platypus.components.LogicTeleporter.prototype */{
28
+ id: 'LogicTeleporter',
29
+
30
+ /**
31
+ * This component listens for redirected collision messages and fires a message on the colliding entity to specify where the colliding entity should relocate itself.
32
+ *
33
+ * @memberof platypus.components
34
+ * @uses platypus.Component
35
+ * @constructs
36
+ * @param {*} definition
37
+ * @listens platypus.Entity#peer-entity-added
38
+ */
39
+ initialize: function (definition) {
40
+
41
+ this.destination = null;
42
+ this.linkId = this.owner.teleportId || definition.teleportId;
43
+ this.facing = this.owner.facing || definition.facing || false; //TODO: Should probably deprecate this in favor of orientation. - DDD 3/2/2016
44
+
45
+ if (this.facing) {
46
+ this.owner.state.set('facing-' + this.facing, true);
47
+ }
48
+ },
49
+
50
+ events: {// These are messages that this component listens for
51
+ "peer-entity-added": function (entity) {
52
+ if (!this.destination && (entity.linkId === this.linkId)) {
53
+ this.destination = entity;
54
+ }
55
+ },
56
+
57
+ "teleport-entity": function (collisionInfo) {
58
+ switch (this.facing) {
59
+ case 'up':
60
+ if (collisionInfo.y < 0) {
61
+ collisionInfo.entity.triggerEvent('teleport', this.destination);
62
+ }
63
+ break;
64
+ case 'right':
65
+ if (collisionInfo.x > 0) {
66
+ collisionInfo.entity.triggerEvent('teleport', this.destination);
67
+ }
68
+ break;
69
+ case 'down':
70
+ if (collisionInfo.y > 0) {
71
+ collisionInfo.entity.triggerEvent('teleport', this.destination);
72
+ }
73
+ break;
74
+ case 'left':
75
+ if (collisionInfo.x < 0) {
76
+ collisionInfo.entity.triggerEvent('teleport', this.destination);
77
+ }
78
+ break;
79
+ default:
80
+ collisionInfo.entity.triggerEvent('teleport', this.destination);
81
+ break;
82
+ }
83
+ }
84
+ },
85
+
86
+ methods: {// These are methods that are called on the component
87
+ "destroy": function () {
88
+ this.destination = null;
89
+ }
90
+ }
91
+
92
+ });
93
+ }());