@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,296 @@
1
+ /* global platypus */
2
+ import TweenJS from '@tweenjs/tween.js';
3
+ import createComponentClass from '../factory.js';
4
+
5
+ const
6
+ Easing = TweenJS.Easing,
7
+ Group = TweenJS.Group,
8
+ Interpolation = TweenJS.Interpolation,
9
+ Tween = TweenJS.Tween,
10
+ eases = (function () {
11
+ const
12
+ easing = {},
13
+ keys = Object.keys(Easing),
14
+ {length} = keys;
15
+
16
+ for (let i = 0; i < length; i++) {
17
+ const
18
+ key = keys[i],
19
+ types = Object.keys(Easing[key]),
20
+ {length: typesLength} = types;
21
+
22
+ for (let j = 0; j < typesLength; j++) {
23
+ const
24
+ type = types[j];
25
+
26
+ easing[key + '.' + type] = Easing[key][type];
27
+ }
28
+ }
29
+
30
+ return easing;
31
+ }());
32
+
33
+ export default createComponentClass(/** @lends platypus.components.Tween.prototype */{
34
+ id: 'Tween',
35
+
36
+ properties: {
37
+ /**
38
+ * Required. A key/value list of events and an array or object representing the tween they should trigger.
39
+ *
40
+ * {
41
+ * "begin-flying": { // When "begin-flying" is triggered on this entity, the following tween begins. Tween definitions adhere to a similar structure outlined by the [TweenJS documentation](https://github.com/tweenjs/tween.js/blob/master/docs/user_guide.md).
42
+ * "target": "entityId", // This defaults to the entity that this component is on, but can be the id of any entity in this layer.
43
+ * "to": { // Specifies the values to change and what they should tween to.
44
+ * "scaleY": 1,
45
+ * "y": [400, 450, 425]
46
+ * },
47
+ * "time": 1000, // Time in MS to make transition.
48
+ * "easing": "Quadratic.In", Easing function to use.
49
+ * "onUpdate": "flying", // Event to trigger while transition is running.
50
+ * "onStart": "wave", // Event to trigger when tween begins (after delay).
51
+ * "onStop": "whoa", // Event to trigger when tween is stopped (not completed normally).
52
+ * "onComplete": "done", // Event to trigger when tween is complete.
53
+ * "onRepeat": "going-again", // Event to trigger when tween is beginning again.
54
+ * "chain": "stop-flying", // Specifies a tween to use next.
55
+ * "repeat": 0, // Sets how many times to repeat this tween once it completes.
56
+ * "yoyo": false, // If this tween repeats, yoyo makes it transition back-and-forth.
57
+ * "delay": 500, // Time in MS to delay before starting transition.
58
+ * "repeatDelay": 0, // Time in MS that the transition should wait between repeats if it shouldn't be the `delay` value.
59
+ * "interpolation": "Linear" // Interpolation method to use for an array of values.
60
+ * },
61
+ *
62
+ * "stop-flying": [{ // May also chain tweens by specifying an array.
63
+ * "to": {"y": 100},
64
+ * "time": 250
65
+ * }, {
66
+ * "to": {"y": 0},
67
+ * "time": 250
68
+ * }]
69
+ * }
70
+ *
71
+ * @property events
72
+ * @type Object
73
+ * @default null
74
+ */
75
+ events: null
76
+ },
77
+
78
+ /**
79
+ * This component takes a list of tween definitions and plays them as needed. This component requires TweenJS.
80
+ *
81
+ * @memberof platypus.components
82
+ * @uses platypus.Component
83
+ * @constructs
84
+ * @listens platypus.Entity#handle-logic
85
+ * @listens platypus.Entity#pause-tween
86
+ * @listens platypus.Entity#stop-tween
87
+ * @listens platypus.Entity#tween
88
+ * @listens platypus.Entity#unpause-tween
89
+ */
90
+ initialize: function () {
91
+ const
92
+ events = this.events;
93
+
94
+ this.group = new Group();
95
+ this.time = 0;
96
+ this.paused = false;
97
+
98
+ if (events) {
99
+ Object.keys(events).forEach((event) => this.addEventListener(event, (augmentTweenData) => {
100
+ const
101
+ data = events[event],
102
+ isArr = Array.isArray(data);
103
+
104
+ if (typeof augmentTweenData === typeof data && Array.isArray(augmentTweenData) === isArr) {
105
+ if (isArr) {
106
+ this.runTween([...data, ...augmentTweenData]);
107
+ } else {
108
+ this.runTween({...data, ...augmentTweenData});
109
+ }
110
+ } else {
111
+ this.runTween(data);
112
+ }
113
+ }));
114
+ }
115
+ },
116
+
117
+ events: {
118
+ /**
119
+ * Trigger this event to play a tween using the same spec used for a tween on this component's `events` property.
120
+ *
121
+ * @event platypus.Entity#tween
122
+ * @param {Object|Array} tween
123
+ */
124
+ 'tween': function (tween) {
125
+ this.runTween(tween);
126
+ },
127
+
128
+ 'handle-logic': function (tick) {
129
+ if (!this.paused) {
130
+ this.time += tick.delta;
131
+ this.group.update(this.time);
132
+ }
133
+ },
134
+
135
+ /**
136
+ * This event stops all running tweens on this component.
137
+ *
138
+ * @event platypus.Entity#stop-tween
139
+ */
140
+ 'stop-tween': function () {
141
+ this.group.removeAll();
142
+ },
143
+
144
+ /**
145
+ * This event pauses all running tweens on this component.
146
+ *
147
+ * @event platypus.Entity#pause-tween
148
+ */
149
+ "pause-tween": function () {
150
+ this.paused = true;
151
+ },
152
+
153
+ /**
154
+ * This event unpauses all running tweens on this component.
155
+ *
156
+ * @event platypus.Entity#unpause-tween
157
+ */
158
+ "unpause-tween": function () {
159
+ this.paused = false;
160
+ }
161
+ },
162
+
163
+ methods: {
164
+ createTween: function (tweenDefinition, chainable) {
165
+ const
166
+ owner = this.owner,
167
+ entity = tweenDefinition.target ? (typeof tweenDefinition.target === 'string' ? owner.get(tweenDefinition.target) ?? owner.parent.get(tweenDefinition.target) : tweenDefinition.target) : owner;
168
+
169
+ if (!entity) {
170
+ platypus.debug.warn('Component Tween: Could not find entity as specified by `target` - ' + tweenDefinition.target);
171
+ return null;
172
+ } else if (!tweenDefinition.to || !tweenDefinition.time) {
173
+ platypus.debug.warn('Component Tween: Both `time` and `to` must be specified to create tween.');
174
+ return null;
175
+ } else {
176
+ const
177
+ tween = new Tween(entity, this.group);
178
+
179
+ tween.to(tweenDefinition.to, tweenDefinition.time);
180
+
181
+ if (tweenDefinition.onUpdate) {
182
+ tween.onUpdate((typeof tweenDefinition.onUpdate !== 'function') ? (...args) => owner.trigger(tweenDefinition.onUpdate, ...args) : tweenDefinition.onUpdate);
183
+ }
184
+ if (tweenDefinition.onStart) {
185
+ tween.onStart((typeof tweenDefinition.onStart !== 'function') ? (...args) => owner.trigger(tweenDefinition.onStart, ...args) : tweenDefinition.onStart);
186
+ }
187
+ if (tweenDefinition.onStop) {
188
+ tween.onStop((typeof tweenDefinition.onStop !== 'function') ? (...args) => owner.trigger(tweenDefinition.onStop, ...args) : tweenDefinition.onStop);
189
+ }
190
+ if (tweenDefinition.onComplete) {
191
+ tween.onComplete(() => {
192
+ tween.stop();
193
+ if (tweenDefinition.onComplete) {
194
+ if (typeof tweenDefinition.onComplete !== 'function') {
195
+ owner.trigger(tweenDefinition.onComplete);
196
+ } else {
197
+ tweenDefinition.onComplete();
198
+ }
199
+ }
200
+ });
201
+ }
202
+ if (tweenDefinition.onRepeat) {
203
+ tween.onRepeat((typeof tweenDefinition.onRepeat !== 'function') ? (...args) => owner.trigger(tweenDefinition.onRepeat, ...args) : tweenDefinition.onRepeat);
204
+ }
205
+
206
+ if (tweenDefinition.chain) {
207
+ if (!chainable) {
208
+ platypus.debug.warn('Component Tween: ignoring `chain` on tween since it is part of an array of tweens.');
209
+ } else if (typeof tweenDefinition.chain === 'string') {
210
+ if (this.events[tweenDefinition.chain]) {
211
+ tween.chain(this.createTweens(this.events[tweenDefinition.chain]));
212
+ } else {
213
+ platypus.debug.warn(`Component Tween: ignoring chain on tween since there is no tween event trigger "${tweenDefinition.chain}".`);
214
+ }
215
+ } else {
216
+ tween.chain(tweenDefinition.chain);
217
+ }
218
+ }
219
+
220
+ if (tweenDefinition.repeat) {
221
+ tween.repeat(tweenDefinition.repeat);
222
+ }
223
+ if (tweenDefinition.yoyo) {
224
+ tween.yoyo(true);
225
+ }
226
+ if (tweenDefinition.delay) {
227
+ tween.delay(tweenDefinition.delay);
228
+ }
229
+ if (typeof tweenDefinition.repeatDelay !== 'undefined') {
230
+ tween.repeatDelay(tweenDefinition.repeatDelay);
231
+ }
232
+
233
+ if (tweenDefinition.interpolation) {
234
+ if (typeof tweenDefinition.interpolation === 'function') {
235
+ tween.interpolation(tweenDefinition.interpolation);
236
+ } else if (Interpolation[tweenDefinition.interpolation]) {
237
+ tween.interpolation(Interpolation[tweenDefinition.interpolation]);
238
+ } else {
239
+ platypus.debug.warn('Component Tween: "' + tweenDefinition.interpolation + '" is not a valid interpolation value; must be "Linear", "Bezier", or "CatmullRom".');
240
+ }
241
+ }
242
+
243
+ if (tweenDefinition.easing) {
244
+ if (typeof tweenDefinition.easing === 'function') {
245
+ tween.easing(tweenDefinition.easing);
246
+ } else if (eases[tweenDefinition.easing]) {
247
+ tween.easing(eases[tweenDefinition.easing]);
248
+ } else {
249
+ const
250
+ joinEnd = '", or "',
251
+ join = '", "';
252
+
253
+ platypus.debug.warn(`Component Tween: "${tweenDefinition.easing}" is not a valid easing value; must be ${Object.keys(eases).reduce((str, value, index) => `${index === 0 ? joinEnd : join}${value}${str}`, '".').substring(3)}`);
254
+ }
255
+ }
256
+
257
+ return tween;
258
+ }
259
+ },
260
+
261
+ createTweens: function (tween) {
262
+ if (Array.isArray(tween)) {
263
+ let i = tween.length,
264
+ lastTween = null;
265
+
266
+ while (i--) {
267
+ const newTween = this.createTween(tween[i], !lastTween);
268
+
269
+ if (lastTween) {
270
+ newTween.chain(lastTween);
271
+ }
272
+ lastTween = newTween;
273
+ }
274
+
275
+ return lastTween;
276
+ } else {
277
+ return this.createTween(tween, true);
278
+ }
279
+ },
280
+
281
+ destroy: function () {
282
+ this.group.removeAll();
283
+ },
284
+
285
+ runTween: function (tweenDefinition) {
286
+ const
287
+ tween = this.createTweens(tweenDefinition);
288
+
289
+ if (tween) {
290
+ tween.start(this.time);
291
+ } else {
292
+ platypus.debug.warn('Component Tween: Unable to run requested tween.', tweenDefinition);
293
+ }
294
+ }
295
+ }
296
+ });
@@ -0,0 +1,373 @@
1
+ /* global platypus */
2
+ import {arrayCache, greenSlice} from '../utils/array.js';
3
+ import AudioVO from './AudioVO.js';
4
+ import createComponentClass from '../factory.js';
5
+
6
+ const
7
+ getEventName = function (msg, VO) {
8
+ if (VO === ' ') {
9
+ return msg + 'default';
10
+ } else {
11
+ return msg + VO;
12
+ }
13
+ },
14
+ createAudioDefinition = function (sound, events = [], message, frameLength) {
15
+ const
16
+ soundId = typeof sound === 'string' ? sound : typeof sound.sound === 'string' ? sound.sound : '',
17
+ soundObj = soundId ? {} : sound.sound,
18
+ definition = {
19
+ sound: soundId,
20
+ events: [...sound.events ?? []],
21
+ ...soundObj
22
+ },
23
+ voice = sound.voice,
24
+ mouthCues = sound.mouthCues ?? platypus.game.settings.mouthCues?.[definition.sound] ?? platypus.game.settings.mouthCues?.[definition.sound.substring(definition.sound.lastIndexOf('/') + 1)];
25
+
26
+ if (voice) {
27
+ let lastFrame = null,
28
+ time = 0;
29
+
30
+ voice += ' ';
31
+
32
+ for (let i = 0; i < voice.length; i++) {
33
+ const
34
+ thisFrame = voice[i];
35
+
36
+ if (thisFrame !== lastFrame) {
37
+ lastFrame = thisFrame;
38
+ definition.events.push({
39
+ time,
40
+ event: getEventName(message, thisFrame)
41
+ });
42
+ }
43
+ time += frameLength;
44
+ }
45
+ } else if (mouthCues) {
46
+ // if in condensed format
47
+ if (typeof mouthCues[0] === 'number') {
48
+ const
49
+ length = (mouthCues.length / 2) >> 0;
50
+
51
+ for (let i = 0; i < length; i++) {
52
+ const
53
+ index = i * 2;
54
+
55
+ definition.events.push({
56
+ time: mouthCues[index] * 1000,
57
+ event: getEventName(message, mouthCues[index + 1])
58
+ });
59
+ }
60
+ } else {
61
+ for (let i = 0; i < mouthCues.length; i++) {
62
+ const
63
+ thisFrame = mouthCues[i];
64
+
65
+ definition.events.push({
66
+ time: thisFrame.start * 1000,
67
+ event: getEventName(message, thisFrame.value)
68
+ });
69
+ }
70
+ }
71
+ }
72
+
73
+ return definition;
74
+ },
75
+ createVO = function (sound, events, message, frameLength) {
76
+ if (!events[' ']) {
77
+ events[' '] = events.default;
78
+ }
79
+
80
+ if (Array.isArray(sound)) {
81
+ return sound.map((clip) => {
82
+ if (typeof clip === 'number' || typeof clip === 'function') {
83
+ return clip;
84
+ } else {
85
+ return createAudioDefinition(clip, events, message, frameLength);
86
+ }
87
+ });
88
+ } else {
89
+ return createAudioDefinition(sound, events, message, frameLength);
90
+ }
91
+ };
92
+
93
+ export default createComponentClass(/** @lends platypus.components.VoiceOver.prototype */{
94
+ id: 'VoiceOver',
95
+
96
+ properties: {
97
+ aliases: null,
98
+
99
+ /**
100
+ * Sets the pairing between letters in the voice-over strings and the animation frame to play.
101
+ *
102
+ * "animationMap": {
103
+ * "default": "mouth-closed"
104
+ * // Required. Specifies animation of default position.
105
+ *
106
+ * "w": "mouth-o",
107
+ * "a": "mouth-aah",
108
+ * "t": "mouth-t"
109
+ * // Optional. Also list single characters that should map to a given voice-over animation frame.
110
+ * }
111
+ *
112
+ * @property animationMap
113
+ * @type Object
114
+ * @default: {"default": "default"}
115
+ */
116
+ animationMap: {"default": "default"},
117
+
118
+ /**
119
+ * Specifies the type of component to add to handle VO lip-sync animation.
120
+ *
121
+ * @property renderComponent
122
+ * @type String
123
+ * @default 'RenderSprite'
124
+ */
125
+ renderComponent: 'RenderSprite',
126
+
127
+ /**
128
+ * Specifies how long a described voice-over frame should last in milliseconds.
129
+ *
130
+ * @property frameLength
131
+ * @type Number
132
+ * @default 100
133
+ */
134
+ frameLength: 100,
135
+
136
+ /**
137
+ * Specifies the prefix that messages between the render and Audio components should use. This will cause the audio to trigger events like "i-say-w" and "i-say-a" (characters listed in the animationMap), that the RenderSprite uses to show the proper frame.
138
+ *
139
+ * @property messagePrefix
140
+ * @type String
141
+ * @default ""
142
+ */
143
+ messagePrefix: "",
144
+
145
+ /**
146
+ * This maps events to audio clips and voice over strings.
147
+ *
148
+ * "voiceOverMap": {
149
+ * "message-triggered": [{
150
+ * "sound": "audio-id",
151
+ * // Required. This is the audio clip to play when "message-triggered" is triggered. It may be a string as shown or an object of key/value pairs as described in an [[audio]] component definition.
152
+ * "voice": "waat"
153
+ * // Optional. This string defines the voice-over sequence according to the frames defined by animationMap. Each character lasts the length specified by "frameLength" above. If not specified, voice will be the default frame.
154
+ * }]
155
+ * }
156
+ *
157
+ * @property voiceOverMap
158
+ * @type Object
159
+ * @default null
160
+ */
161
+ voiceOverMap: null,
162
+
163
+ /**
164
+ * This generates voice over maps. An array of specifications for batches of voice maps to generate. Includes basic properties that can add a prefix to the event name, initial delay before the audio, and an onEnd event that fires when the voice over completes.
165
+ *
166
+ * "generatedVoiceOverMap": [{
167
+ * "eventPrefix": "vo-" //Optional. Defaults to "vo-". Is prefixed to the audio file name to create the event to call to trigger to VO.
168
+ * "initialDelay": 0 //Optional. Defaults to 0. An intial audio delay before the VO starts. Useful to prevent audio from triggering as a scene is loading.
169
+ * "onEndEvent": "an-event" //Optional. Defaults to "". This event fires when the VO completes.
170
+ * "endEventTime": 500 //Optional. Defaults to 99999. When the onEnd event fires.
171
+ * "audio": ["audio-0", "audio-1", "audio-2"] //Required. An array of strings that coorespond to the audio files to create a VOMap for, or a key/value list of id to audio path pairings.
172
+ * }]
173
+ *
174
+ * A generated VO Map is equivalent to this structure:
175
+ *
176
+ * "prefix-audio-0": [
177
+ * 500, //initialDelay
178
+ * {
179
+ * "sound": {
180
+ * "sound": "audio-0", //the audio string
181
+ * "events": [
182
+ * {
183
+ * "event": "on-end-event", //onEndEvent
184
+ * "time": 99999
185
+ * }
186
+ * ]
187
+ * }
188
+ * }
189
+ * ],
190
+ *
191
+ * @property generatedVoiceOverMap
192
+ * @type Object[]
193
+ * @default null
194
+ */
195
+ generatedVoiceOverMaps: null,
196
+
197
+ acceptInput: null,
198
+ animation: null,
199
+ flip: null,
200
+ hidden: null,
201
+ interactive: null,
202
+ mask: null,
203
+ mirror: null,
204
+ offsetZ: null,
205
+ regX: null,
206
+ regY: null,
207
+ restart: null,
208
+ scaleX: null,
209
+ scaleY: null,
210
+ spriteSheet: null,
211
+ stateBased: null,
212
+ },
213
+
214
+ /**
215
+ * This component uses its definition to load an AudioVO component and a RenderSprite component. These work in an interconnected way to render animations corresponding to one or more audio tracks.
216
+ *
217
+ * In addition to its own properties, this component also accepts all properties accepted by [RenderSprite](platypus.components.RenderSprite.html) and [AudioVO](platypus.components.AudioVO.html) and passes them along when it creates those components.
218
+ *
219
+ * @memberof platypus.components
220
+ * @uses platypus.Component
221
+ * @uses platypus.AudioVO
222
+ * @uses platypus.RenderSprite
223
+ * @constructs
224
+ * @listens platypus.Entity#load
225
+ */
226
+ initialize: function (definition, callback) {
227
+ const
228
+ {aliases, acceptInput, animation, animationMap, flip, hidden, interactive, mask, messagePrefix, mirror, offsetZ, owner, regX, regY, renderComponent, restart, scaleX, scaleY, spriteSheet, stateBased, voiceOverMap = {}} = this,
229
+ animationKeys = Object.keys(animationMap),
230
+ {length: animationLength} = animationKeys,
231
+ componentInit = (Component, definition) => new Promise((resolve) => {
232
+ owner.addComponent(new Component(owner, definition, resolve));
233
+ }),
234
+ voMapKeys = Object.keys(voiceOverMap),
235
+ {length: voMapLength} = voMapKeys,
236
+ audioDefinition = {
237
+ audioMap: {},
238
+ aliases
239
+ },
240
+ animationDefinition = {
241
+ acceptInput,
242
+ aliases,
243
+ animation,
244
+ animationMap: {},
245
+ eventBased: true, // VO triggers events for changing lip-sync frames.
246
+ flip,
247
+ hidden,
248
+ interactive,
249
+ mask,
250
+ mirror,
251
+ offsetZ,
252
+ regX,
253
+ regY,
254
+ restart,
255
+ scaleX,
256
+ scaleY,
257
+ spriteSheet,
258
+ stateBased
259
+ };
260
+
261
+ if (messagePrefix) {
262
+ this.message = `${messagePrefix}-`;
263
+ } else {
264
+ this.message = '';
265
+ }
266
+
267
+ this.relayLipSyncEvents = ({descriptor, content}) => {
268
+ if (descriptor === 'lipsync') {
269
+ this.owner.triggerEvent(getEventName(this.message, content));
270
+ }
271
+ };
272
+ platypus.game.voPlayer.on('lyric', this.relayLipSyncEvents);
273
+
274
+ for (let i = 0; i < animationLength; i++) {
275
+ const
276
+ key = animationKeys[i];
277
+
278
+ animationDefinition.animationMap[getEventName(this.message, key)] = animationMap[key];
279
+ }
280
+ animationDefinition.animationMap.default = this.animationMap.default;
281
+
282
+ if (this.generatedVoiceOverMaps) {
283
+ const
284
+ createMapping = (key, path, voBatch) => {
285
+ if (!this.voiceOverMap[key]) {
286
+ const
287
+ delay = voBatch.initialDelay || 0,
288
+ endEventTime = voBatch.endEventTime || 99999,
289
+ onEnd = voBatch.onEndEvent || "";
290
+
291
+ this.voiceOverMap[key] = [
292
+ delay,
293
+ {
294
+ "sound": {
295
+ "sound": path,
296
+ "events": [
297
+ {
298
+ "event": onEnd,
299
+ "time": endEventTime
300
+ }
301
+ ]
302
+ }
303
+ }
304
+ ];
305
+ }
306
+ };
307
+
308
+ for (let y = 0; y < this.generatedVoiceOverMaps.length; y++) {
309
+ const
310
+ voBatch = this.generatedVoiceOverMaps[y],
311
+ prefix = voBatch.eventPrefix || "vo-",
312
+ audios = voBatch.audio;
313
+
314
+ if (Array.isArray(audios)) {
315
+ for (let x = 0; x < audios.length; x++) {
316
+ const
317
+ audio = audios[x];
318
+
319
+ createMapping(`${prefix}${audio}`, audio, voBatch);
320
+ }
321
+ } else {
322
+ Object.keys(audios).forEach((key) => createMapping(`${prefix}${key}`, audios[key], voBatch));
323
+ }
324
+ }
325
+ }
326
+
327
+ for (let i = 0; i < voMapLength; i++) {
328
+ const
329
+ key = voMapKeys[i];
330
+
331
+ audioDefinition.audioMap[key] = createVO(voiceOverMap[key], animationMap, this.message, this.frameLength);
332
+ }
333
+
334
+ Promise.all([componentInit(typeof this.renderComponent === 'string' ? platypus.components[this.renderComponent] : this.renderComponent, animationDefinition), componentInit(AudioVO, audioDefinition)]).then(callback);
335
+
336
+ return true;
337
+ },
338
+
339
+ methods: {
340
+ destroy () {
341
+ platypus.game.voPlayer.off('lipsync', this.relayLipSyncEvents);
342
+ }
343
+ },
344
+
345
+ events: {
346
+ "play-voice-over-with-lip-sync": function (vo) {
347
+ this.owner.triggerEvent('play-voice-over', createVO(vo, this.animationMap, this.message, this.frameLength));
348
+ }
349
+ },
350
+
351
+ getAssetList: function (component, props, defaultProps) {
352
+ const
353
+ ss = component?.spriteSheet ?? props?.spriteSheet ?? defaultProps?.spriteSheet,
354
+ audioMap = component?.voiceOverMap ?? props?.voiceOverMap ?? defaultProps?.voiceOverMap,
355
+ voAssets = AudioVO.getAssetList({
356
+ audioMap
357
+ });
358
+
359
+ if (typeof ss === 'string') {
360
+ return [
361
+ ...greenSlice(platypus.game.settings.spriteSheets[ss].images),
362
+ ...voAssets
363
+ ];
364
+ } else if (ss) {
365
+ return [
366
+ ...greenSlice(ss.images),
367
+ ...voAssets
368
+ ];
369
+ } else {
370
+ return voAssets;
371
+ }
372
+ }
373
+ });