melonjs 9.1.0 → 10.0.1

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 (78) hide show
  1. package/{LICENSE → LICENSE.md} +0 -0
  2. package/README.md +93 -57
  3. package/dist/melonjs.js +10334 -11179
  4. package/dist/melonjs.min.js +4 -10
  5. package/dist/melonjs.module.d.ts +13206 -0
  6. package/dist/melonjs.module.js +9913 -10872
  7. package/package.json +19 -14
  8. package/src/audio/audio.js +477 -553
  9. package/src/camera/camera2d.js +67 -65
  10. package/src/entity/draggable.js +26 -35
  11. package/src/entity/droptarget.js +17 -14
  12. package/src/entity/entity.js +59 -79
  13. package/src/game.js +194 -204
  14. package/src/index.js +12 -30
  15. package/src/input/gamepad.js +8 -19
  16. package/src/input/keyboard.js +4 -4
  17. package/src/input/pointer.js +14 -12
  18. package/src/input/pointerevent.js +15 -13
  19. package/src/lang/deprecated.js +2 -887
  20. package/src/level/level.js +3 -3
  21. package/src/level/tiled/TMXGroup.js +7 -11
  22. package/src/level/tiled/TMXLayer.js +33 -32
  23. package/src/level/tiled/TMXTileMap.js +15 -19
  24. package/src/level/tiled/TMXTileset.js +5 -5
  25. package/src/level/tiled/TMXUtils.js +3 -3
  26. package/src/level/tiled/renderer/TMXRenderer.js +4 -0
  27. package/src/loader/loader.js +8 -23
  28. package/src/loader/loadingscreen.js +51 -60
  29. package/src/math/matrix3.js +1 -1
  30. package/src/particles/emitter.js +36 -39
  31. package/src/particles/particle.js +27 -12
  32. package/src/particles/particlecontainer.js +17 -16
  33. package/src/physics/body.js +80 -118
  34. package/src/physics/collision.js +5 -235
  35. package/src/physics/detector.js +235 -0
  36. package/src/physics/quadtree.js +14 -14
  37. package/src/physics/world.js +84 -18
  38. package/src/plugin/plugin.js +26 -24
  39. package/src/polyfill/console.js +9 -14
  40. package/src/renderable/GUI.js +48 -62
  41. package/src/renderable/collectable.js +11 -4
  42. package/src/renderable/colorlayer.js +28 -26
  43. package/src/renderable/container.js +120 -96
  44. package/src/renderable/imagelayer.js +94 -93
  45. package/src/renderable/renderable.js +164 -138
  46. package/src/renderable/sprite.js +42 -44
  47. package/src/renderable/trigger.js +24 -17
  48. package/src/shapes/ellipse.js +27 -27
  49. package/src/shapes/line.js +12 -8
  50. package/src/shapes/poly.js +77 -49
  51. package/src/shapes/rectangle.js +193 -268
  52. package/src/state/stage.js +23 -25
  53. package/src/state/state.js +35 -86
  54. package/src/system/device.js +233 -285
  55. package/src/system/event.js +485 -432
  56. package/src/system/pooling.js +61 -54
  57. package/src/system/save.js +17 -16
  58. package/src/system/timer.js +34 -38
  59. package/src/text/bitmaptext.js +44 -46
  60. package/src/text/text.js +39 -34
  61. package/src/tweens/easing.js +0 -2
  62. package/src/tweens/interpolation.js +3 -8
  63. package/src/tweens/tween.js +332 -351
  64. package/src/utils/function.js +6 -8
  65. package/src/utils/utils.js +34 -30
  66. package/src/video/canvas/canvas_renderer.js +13 -8
  67. package/src/video/renderer.js +8 -7
  68. package/src/video/texture.js +8 -8
  69. package/src/video/texture_cache.js +5 -5
  70. package/src/video/video.js +373 -403
  71. package/src/video/webgl/glshader.js +2 -2
  72. package/src/video/webgl/webgl_compositor.js +14 -8
  73. package/src/video/webgl/webgl_renderer.js +21 -19
  74. package/plugins/debug/debugPanel.js +0 -770
  75. package/plugins/debug/font/PressStart2P.fnt +0 -100
  76. package/plugins/debug/font/PressStart2P.ltr +0 -1
  77. package/plugins/debug/font/PressStart2P.png +0 -0
  78. package/plugins/debug/particleDebugPanel.js +0 -303
@@ -2,29 +2,48 @@
2
2
  import {Howl, Howler} from "howler";
3
3
  import {clamp} from "./../math/math.js";
4
4
  import loader from "./../loader/loader.js";
5
- import { initialized } from "./../index.js";
6
5
 
7
- // audio channel list
6
+ /**
7
+ * @namespace audio
8
+ * @memberOf me
9
+ */
10
+
11
+ /**
12
+ * audio channel list
13
+ * @ignore
14
+ */
8
15
  var audioTracks = {};
9
16
 
10
- // current music
17
+ /**
18
+ * current active track
19
+ * @ignore
20
+ */
11
21
  var current_track_id = null;
12
22
 
13
- // a retry counter
23
+ /**
24
+ * error retry counter
25
+ * @ignore
26
+ */
14
27
  var retry_counter = 0;
15
28
 
29
+ /**
30
+ * list of active audio formats
31
+ * @ignore
32
+ */
33
+ var audioExts = [];
34
+
16
35
  /**
17
36
  * event listener callback on load error
18
37
  * @ignore
19
38
  */
20
- var soundLoadError = function(sound_name, onerror_cb) {
39
+ var soundLoadError = function (sound_name, onerror_cb) {
21
40
  // check the retry counter
22
41
  if (retry_counter++ > 3) {
23
42
  // something went wrong
24
43
  var errmsg = "melonJS: failed loading " + sound_name;
25
- if (audio.stopOnAudioError === false) {
44
+ if (stopOnAudioError === false) {
26
45
  // disable audio
27
- audio.disable();
46
+ disable();
28
47
  // call error callback if defined
29
48
  if (onerror_cb) {
30
49
  onerror_cb();
@@ -44,564 +63,469 @@ var soundLoadError = function(sound_name, onerror_cb) {
44
63
  };
45
64
 
46
65
  /**
47
- * @namespace me.audio
48
- * @memberOf me
66
+ * Specify either to stop on audio loading error or not<br>
67
+ * if true, melonJS will throw an exception and stop loading<br>
68
+ * if false, melonJS will disable sounds and output a warning message
69
+ * in the console<br>
70
+ * @name stopOnAudioError
71
+ * @type {Boolean}
72
+ * @default true
73
+ * @memberOf me.audio
49
74
  */
50
- var audio = {
51
-
52
- /**
53
- * Specify either to stop on audio loading error or not<br>
54
- * if true, melonJS will throw an exception and stop loading<br>
55
- * if false, melonJS will disable sounds and output a warning message
56
- * in the console<br>
57
- * @type {Boolean}
58
- * @default true
59
- * @memberOf me.audio
60
- */
61
- stopOnAudioError : true,
62
-
63
- /**
64
- * Initialize and configure the audio support.<br>
65
- * melonJS supports a wide array of audio codecs that have varying browser support :
66
- * <i> ("mp3", "mpeg", opus", "ogg", "oga", "wav", "aac", "caf", "m4a", "m4b", "mp4", "weba", "webm", "dolby", "flac")</i>.<br>
67
- * For a maximum browser coverage the recommendation is to use at least two of them,
68
- * typically default to webm and then fallback to mp3 for the best balance of small filesize and high quality,
69
- * webm has nearly full browser coverage with a great combination of compression and quality, and mp3 will fallback gracefully for other browsers.
70
- * It is important to remember that melonJS selects the first compatible sound based on the list of extensions and given order passed here.
71
- * So if you want webm to be used before mp3, you need to put the audio format in that order.
72
- * @name init
73
- * @memberOf me.audio
74
- * @public
75
- * @function
76
- * @param {String} [audioFormat="mp3"] audio format to prioritize
77
- * @return {Boolean} Indicates whether audio initialization was successful
78
- * @example
79
- * // initialize the "sound engine", giving "webm" as default desired audio format, and "mp3" as a fallback
80
- * if (!me.audio.init("webm,mp3")) {
81
- * alert("Sorry but your browser does not support html 5 audio !");
82
- * return;
83
- * }
84
- */
85
- init : function (audioFormat) {
86
- if (!initialized) {
87
- throw new Error("me.audio.init() called before engine initialization.");
88
- }
89
- // if no param is given to init we use mp3 by default
90
- audioFormat = typeof audioFormat === "string" ? audioFormat : "mp3";
91
- // convert it into an array
92
- this.audioFormats = audioFormat.split(",");
93
-
94
- return !Howler.noAudio;
95
- },
96
-
97
-
98
- /**
99
- * return true if the given audio format is supported
100
- * @name hasFormat
101
- * @param {String} format audio format : "mp3", "mpeg", opus", "ogg", "oga", "wav", "aac", "caf", "m4a", "m4b", "mp4", "weba", "webm", "dolby", "flac"
102
- * @memberOf me.audio
103
- * @public
104
- * @function
105
- */
106
- hasFormat:function (codec) {
107
- return this.hasAudio && Howler.codecs(codec);
108
- },
109
-
110
- /**
111
- * return true if audio (HTML5 or WebAudio) is supported
112
- * @name hasAudio
113
- * @memberOf me.audio
114
- * @public
115
- * @function
116
- */
117
- hasAudio :function () {
118
- return !Howler.noAudio;
119
- },
120
-
121
- /**
122
- * enable audio output <br>
123
- * only useful if audio supported and previously disabled through
124
- * @see me.audio#disable
125
- * @name enable
126
- * @memberOf me.audio
127
- * @public
128
- * @function
129
- */
130
- enable : function () {
131
- this.unmuteAll();
132
- },
133
-
134
- /**
135
- * disable audio output
136
- *
137
- * @name disable
138
- * @memberOf me.audio
139
- * @public
140
- * @function
141
- */
142
- disable : function () {
143
- this.muteAll();
144
- },
145
-
146
- /**
147
- * Load an audio file.<br>
148
- * <br>
149
- * sound item must contain the following fields :<br>
150
- * - name : name of the sound<br>
151
- * - src : source path<br>
152
- * @ignore
153
- */
154
- load : function (sound, html5, onload_cb, onerror_cb) {
155
- var urls = [];
156
- if (typeof(this.audioFormats) === "undefined" || this.audioFormats.length === 0) {
157
- throw new Error("target audio extension(s) should be set through me.audio.init() before calling the preloader.");
158
- }
159
- for (var i = 0; i < this.audioFormats.length; i++) {
160
- urls.push(sound.src + sound.name + "." + this.audioFormats[i] + loader.nocache);
161
- }
162
- audioTracks[sound.name] = new Howl({
163
- src : urls,
164
- volume : Howler.volume(),
165
- html5 : html5 === true,
166
- xhrWithCredentials : loader.withCredentials,
167
- /**
168
- * @ignore
169
- */
170
- onloaderror : function () {
171
- soundLoadError.call(this, sound.name, onerror_cb);
172
- },
173
- /**
174
- * @ignore
175
- */
176
- onload : function () {
177
- retry_counter = 0;
178
- if (onload_cb) {
179
- onload_cb();
180
- }
181
- }
182
- });
183
-
184
- return 1;
185
- },
186
-
187
- /**
188
- * play the specified sound
189
- * @name play
190
- * @memberOf me.audio
191
- * @public
192
- * @function
193
- * @param {String} sound_name audio clip name - case sensitive
194
- * @param {Boolean} [loop=false] loop audio
195
- * @param {Function} [onend] Function to call when sound instance ends playing.
196
- * @param {Number} [volume=default] Float specifying volume (0.0 - 1.0 values accepted).
197
- * @return {Number} the sound instance ID.
198
- * @example
199
- * // play the "cling" audio clip
200
- * me.audio.play("cling");
201
- * // play & repeat the "engine" audio clip
202
- * me.audio.play("engine", true);
203
- * // play the "gameover_sfx" audio clip and call myFunc when finished
204
- * me.audio.play("gameover_sfx", false, myFunc);
205
- * // play the "gameover_sfx" audio clip with a lower volume level
206
- * me.audio.play("gameover_sfx", false, null, 0.5);
207
- */
208
- play : function (sound_name, loop = false, onend, volume) {
209
- var sound = audioTracks[sound_name];
210
- if (sound && typeof sound !== "undefined") {
211
- var id = sound.play();
212
- if (typeof loop === "boolean") {
213
- // arg[0] can take different types in howler 2.0
214
- sound.loop(loop, id);
215
- }
216
- sound.volume(typeof(volume) === "number" ? clamp(volume, 0.0, 1.0) : Howler.volume(), id);
217
- if (typeof(onend) === "function") {
218
- if (loop === true) {
219
- sound.on("end", onend, id);
220
- }
221
- else {
222
- sound.once("end", onend, id);
223
- }
75
+ export let stopOnAudioError = true;
76
+
77
+ /**
78
+ * Initialize and configure the audio support.<br>
79
+ * melonJS supports a wide array of audio codecs that have varying browser support :
80
+ * <i> ("mp3", "mpeg", opus", "ogg", "oga", "wav", "aac", "caf", "m4a", "m4b", "mp4", "weba", "webm", "dolby", "flac")</i>.<br>
81
+ * For a maximum browser coverage the recommendation is to use at least two of them,
82
+ * typically default to webm and then fallback to mp3 for the best balance of small filesize and high quality,
83
+ * webm has nearly full browser coverage with a great combination of compression and quality, and mp3 will fallback gracefully for other browsers.
84
+ * It is important to remember that melonJS selects the first compatible sound based on the list of extensions and given order passed here.
85
+ * So if you want webm to be used before mp3, you need to put the audio format in that order.
86
+ * @function me.audio.init
87
+ * @param {String} [format="mp3"] audio format to prioritize
88
+ * @returns {Boolean} Indicates whether audio initialization was successful
89
+ * @example
90
+ * // initialize the "sound engine", giving "webm" as default desired audio format, and "mp3" as a fallback
91
+ * if (!me.audio.init("webm,mp3")) {
92
+ * alert("Sorry but your browser does not support html 5 audio !");
93
+ * return;
94
+ * }
95
+ */
96
+ export function init(format = "mp3") {
97
+ // convert it into an array
98
+ audioExts = format.split(",");
99
+
100
+ return !Howler.noAudio;
101
+ };
102
+
103
+ /**
104
+ * check if the given audio format is supported
105
+ * @function me.audio.hasFormat
106
+ * @param {String} format audio format : "mp3", "mpeg", opus", "ogg", "oga", "wav", "aac", "caf", "m4a", "m4b", "mp4", "weba", "webm", "dolby", "flac"
107
+ * @returns {Boolean} return true if the given audio format is supported
108
+ */
109
+ export function hasFormat(codec) {
110
+ return hasAudio() && Howler.codecs(codec);
111
+ };
112
+
113
+ /**
114
+ * check if audio (HTML5 or WebAudio) is supported
115
+ * @function me.audio.hasAudio
116
+ * @returns {Boolean} return true if audio (HTML5 or WebAudio) is supported
117
+ */
118
+ export function hasAudio() {
119
+ return !Howler.noAudio;
120
+ };
121
+
122
+ /**
123
+ * enable audio output <br>
124
+ * only useful if audio supported and previously disabled through
125
+ * @function me.audio.enable
126
+ * @see me.audio#disable
127
+ */
128
+ export function enable() {
129
+ unmuteAll();
130
+ };
131
+
132
+ /**
133
+ * disable audio output
134
+ * @function me.audio.disable
135
+ */
136
+ export function disable() {
137
+ muteAll();
138
+ };
139
+
140
+ /**
141
+ * Load an audio file.<br>
142
+ * <br>
143
+ * sound item must contain the following fields :<br>
144
+ * - name : name of the sound<br>
145
+ * - src : source path<br>
146
+ * @ignore
147
+ */
148
+ export function load(sound, html5, onload_cb, onerror_cb) {
149
+ var urls = [];
150
+ if (audioExts.length === 0) {
151
+ throw new Error("target audio extension(s) should be set through me.audio.init() before calling the preloader.");
152
+ }
153
+ for (var i = 0; i < audioExts.length; i++) {
154
+ urls.push(sound.src + sound.name + "." + audioExts[i] + loader.nocache);
155
+ }
156
+ audioTracks[sound.name] = new Howl({
157
+ src : urls,
158
+ volume : Howler.volume(),
159
+ html5 : html5 === true,
160
+ xhrWithCredentials : loader.withCredentials,
161
+ /**
162
+ * @ignore
163
+ */
164
+ onloaderror() {
165
+ soundLoadError.call(this, sound.name, onerror_cb);
166
+ },
167
+ /**
168
+ * @ignore
169
+ */
170
+ onload() {
171
+ retry_counter = 0;
172
+ if (onload_cb) {
173
+ onload_cb();
224
174
  }
225
- return id;
226
- } else {
227
- throw new Error("audio clip " + sound_name + " does not exist");
228
175
  }
229
- },
230
-
231
- /**
232
- * Fade a currently playing sound between two volumee.
233
- * @name fade
234
- * @memberOf me.audio
235
- * @public
236
- * @function
237
- * @param {String} sound_name audio clip name - case sensitive
238
- * @param {Number} from Volume to fade from (0.0 to 1.0).
239
- * @param {Number} to Volume to fade to (0.0 to 1.0).
240
- * @param {Number} duration Time in milliseconds to fade.
241
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will fade.
242
- */
243
- fade : function (sound_name, from, to, duration, id) {
244
- var sound = audioTracks[sound_name];
245
- if (sound && typeof sound !== "undefined") {
246
- sound.fade(from, to, duration, id);
247
- } else {
248
- throw new Error("audio clip " + sound_name + " does not exist");
249
- }
250
- },
251
-
252
- /**
253
- * get/set the position of playback for a sound.
254
- * @name seek
255
- * @memberOf me.audio
256
- * @public
257
- * @function
258
- * @param {String} sound_name audio clip name - case sensitive
259
- * @param {Number} [seek] The position to move current playback to (in seconds).
260
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will changed.
261
- * @return return the current seek position (if no extra parameters were given)
262
- * @example
263
- * // return the current position of the background music
264
- * var current_pos = me.audio.seek("dst-gameforest");
265
- * // set back the position of the background music to the beginning
266
- * me.audio.seek("dst-gameforest", 0);
267
- */
268
- seek : function (sound_name, seek, id) {
269
- var sound = audioTracks[sound_name];
270
- if (sound && typeof sound !== "undefined") {
271
- return sound.seek.apply(sound, Array.prototype.slice.call(arguments, 1));
272
- } else {
273
- throw new Error("audio clip " + sound_name + " does not exist");
274
- }
275
- },
276
-
277
- /**
278
- * get or set the rate of playback for a sound.
279
- * @name rate
280
- * @memberOf me.audio
281
- * @public
282
- * @function
283
- * @param {String} sound_name audio clip name - case sensitive
284
- * @param {Number} [rate] playback rate : 0.5 to 4.0, with 1.0 being normal speed.
285
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will be changed.
286
- * @return return the current playback rate (if no extra parameters were given)
287
- * @example
288
- * // get the playback rate of the background music
289
- * var rate = me.audio.rate("dst-gameforest");
290
- * // speed up the playback of the background music
291
- * me.audio.rate("dst-gameforest", 2.0);
292
- */
293
- rate : function (sound_name, rate, id) {
294
- var sound = audioTracks[sound_name];
295
- if (sound && typeof sound !== "undefined") {
296
- return sound.rate.apply(sound, Array.prototype.slice.call(arguments, 1));
297
- } else {
298
- throw new Error("audio clip " + sound_name + " does not exist");
176
+ });
177
+
178
+ return 1;
179
+ };
180
+
181
+ /**
182
+ * play the specified sound
183
+ * @function me.audio.play
184
+ * @param {String} sound_name audio clip name - case sensitive
185
+ * @param {Boolean} [loop=false] loop audio
186
+ * @param {Function} [onend] Function to call when sound instance ends playing.
187
+ * @param {Number} [volume=default] Float specifying volume (0.0 - 1.0 values accepted).
188
+ * @return {Number} the sound instance ID.
189
+ * @example
190
+ * // play the "cling" audio clip
191
+ * me.audio.play("cling");
192
+ * // play & repeat the "engine" audio clip
193
+ * me.audio.play("engine", true);
194
+ * // play the "gameover_sfx" audio clip and call myFunc when finished
195
+ * me.audio.play("gameover_sfx", false, myFunc);
196
+ * // play the "gameover_sfx" audio clip with a lower volume level
197
+ * me.audio.play("gameover_sfx", false, null, 0.5);
198
+ */
199
+ export function play(sound_name, loop = false, onend, volume) {
200
+ var sound = audioTracks[sound_name];
201
+ if (sound && typeof sound !== "undefined") {
202
+ var id = sound.play();
203
+ if (typeof loop === "boolean") {
204
+ // arg[0] can take different types in howler 2.0
205
+ sound.loop(loop, id);
299
206
  }
300
- },
301
-
302
- /**
303
- * stop the specified sound on all channels
304
- * @name stop
305
- * @memberOf me.audio
306
- * @public
307
- * @function
308
- * @param {String} [sound_name] audio clip name (case sensitive). If none is passed, all sounds are stopped.
309
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will stop.
310
- * @example
311
- * me.audio.stop("cling");
312
- */
313
- stop : function (sound_name, id) {
314
- if (typeof sound_name !== "undefined") {
315
- var sound = audioTracks[sound_name];
316
- if (sound && typeof sound !== "undefined") {
317
- sound.stop(id);
318
- // remove the defined onend callback (if any defined)
319
- sound.off("end", undefined, id);
320
- } else {
321
- throw new Error("audio clip " + sound_name + " does not exist");
207
+ sound.volume(typeof(volume) === "number" ? clamp(volume, 0.0, 1.0) : Howler.volume(), id);
208
+ if (typeof(onend) === "function") {
209
+ if (loop === true) {
210
+ sound.on("end", onend, id);
211
+ }
212
+ else {
213
+ sound.once("end", onend, id);
322
214
  }
323
- } else {
324
- Howler.stop();
325
- }
326
- },
327
-
328
- /**
329
- * pause the specified sound on all channels<br>
330
- * this function does not reset the currentTime property
331
- * @name pause
332
- * @memberOf me.audio
333
- * @public
334
- * @function
335
- * @param {String} sound_name audio clip name - case sensitive
336
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will pause.
337
- * @example
338
- * me.audio.pause("cling");
339
- */
340
- pause : function (sound_name, id) {
341
- var sound = audioTracks[sound_name];
342
- if (sound && typeof sound !== "undefined") {
343
- sound.pause(id);
344
- } else {
345
- throw new Error("audio clip " + sound_name + " does not exist");
346
215
  }
347
- },
348
-
349
- /**
350
- * resume the specified sound on all channels<br>
351
- * @name resume
352
- * @memberOf me.audio
353
- * @public
354
- * @function
355
- * @param {String} sound_name audio clip name - case sensitive
356
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will resume.
357
- * @example
358
- * // play a audio clip
359
- * var id = me.audio.play("myClip");
360
- * ...
361
- * // pause it
362
- * me.audio.pause("myClip", id);
363
- * ...
364
- * // resume
365
- * me.audio.resume("myClip", id);
366
- */
367
- resume : function (sound_name, id) {
216
+ return id;
217
+ } else {
218
+ throw new Error("audio clip " + sound_name + " does not exist");
219
+ }
220
+ };
221
+
222
+ /**
223
+ * Fade a currently playing sound between two volumee.
224
+ * @function me.audio.fade
225
+ * @param {String} sound_name audio clip name - case sensitive
226
+ * @param {Number} from Volume to fade from (0.0 to 1.0).
227
+ * @param {Number} to Volume to fade to (0.0 to 1.0).
228
+ * @param {Number} duration Time in milliseconds to fade.
229
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will fade.
230
+ */
231
+ export function fade(sound_name, from, to, duration, id) {
232
+ var sound = audioTracks[sound_name];
233
+ if (sound && typeof sound !== "undefined") {
234
+ sound.fade(from, to, duration, id);
235
+ } else {
236
+ throw new Error("audio clip " + sound_name + " does not exist");
237
+ }
238
+ };
239
+
240
+ /**
241
+ * get/set the position of playback for a sound.
242
+ * @function me.audio.seek
243
+ * @param {String} sound_name audio clip name - case sensitive
244
+ * @param {Number} [seek] The position to move current playback to (in seconds).
245
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will changed.
246
+ * @return return the current seek position (if no extra parameters were given)
247
+ * @example
248
+ * // return the current position of the background music
249
+ * var current_pos = me.audio.seek("dst-gameforest");
250
+ * // set back the position of the background music to the beginning
251
+ * me.audio.seek("dst-gameforest", 0);
252
+ */
253
+ export function seek(sound_name, ...args) {
254
+ var sound = audioTracks[sound_name];
255
+ if (sound && typeof sound !== "undefined") {
256
+ return sound.seek(...args);
257
+ } else {
258
+ throw new Error("audio clip " + sound_name + " does not exist");
259
+ }
260
+ };
261
+
262
+ /**
263
+ * get or set the rate of playback for a sound.
264
+ * @function me.audio.rate
265
+ * @param {String} sound_name audio clip name - case sensitive
266
+ * @param {Number} [rate] playback rate : 0.5 to 4.0, with 1.0 being normal speed.
267
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will be changed.
268
+ * @return return the current playback rate (if no extra parameters were given)
269
+ * @example
270
+ * // get the playback rate of the background music
271
+ * var rate = me.audio.rate("dst-gameforest");
272
+ * // speed up the playback of the background music
273
+ * me.audio.rate("dst-gameforest", 2.0);
274
+ */
275
+ export function rate(sound_name, ...args) {
276
+ var sound = audioTracks[sound_name];
277
+ if (sound && typeof sound !== "undefined") {
278
+ return sound.rate(...args);
279
+ } else {
280
+ throw new Error("audio clip " + sound_name + " does not exist");
281
+ }
282
+ };
283
+
284
+ /**
285
+ * stop the specified sound on all channels
286
+ * @function me.audio.stop
287
+ * @param {String} [sound_name] audio clip name (case sensitive). If none is passed, all sounds are stopped.
288
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will stop.
289
+ * @example
290
+ * me.audio.stop("cling");
291
+ */
292
+ export function stop(sound_name, id) {
293
+ if (typeof sound_name !== "undefined") {
368
294
  var sound = audioTracks[sound_name];
369
295
  if (sound && typeof sound !== "undefined") {
370
- sound.play(id);
296
+ sound.stop(id);
297
+ // remove the defined onend callback (if any defined)
298
+ sound.off("end", undefined, id);
371
299
  } else {
372
300
  throw new Error("audio clip " + sound_name + " does not exist");
373
301
  }
374
- },
375
-
376
- /**
377
- * play the specified audio track<br>
378
- * this function automatically set the loop property to true<br>
379
- * and keep track of the current sound being played.
380
- * @name playTrack
381
- * @memberOf me.audio
382
- * @public
383
- * @function
384
- * @param {String} sound_name audio track name - case sensitive
385
- * @param {Number} [volume=default] Float specifying volume (0.0 - 1.0 values accepted).
386
- * @return {Number} the sound instance ID.
387
- * @example
388
- * me.audio.playTrack("awesome_music");
389
- */
390
- playTrack : function (sound_name, volume) {
391
- current_track_id = sound_name;
392
- return this.play(
393
- current_track_id,
394
- true,
395
- null,
396
- volume
397
- );
398
- },
399
-
400
- /**
401
- * stop the current audio track
402
- *
403
- * @see me.audio#playTrack
404
- * @name stopTrack
405
- * @memberOf me.audio
406
- * @public
407
- * @function
408
- * @example
409
- * // play a awesome music
410
- * me.audio.playTrack("awesome_music");
411
- * // stop the current music
412
- * me.audio.stopTrack();
413
- */
414
- stopTrack : function () {
415
- if (current_track_id !== null) {
416
- audioTracks[current_track_id].stop();
417
- current_track_id = null;
418
- }
419
- },
420
-
421
- /**
422
- * pause the current audio track
423
- *
424
- * @name pauseTrack
425
- * @memberOf me.audio
426
- * @public
427
- * @function
428
- * @example
429
- * me.audio.pauseTrack();
430
- */
431
- pauseTrack : function () {
432
- if (current_track_id !== null) {
433
- audioTracks[current_track_id].pause();
434
- }
435
- },
436
-
437
- /**
438
- * resume the previously paused audio track
439
- *
440
- * @name resumeTrack
441
- * @memberOf me.audio
442
- * @public
443
- * @function
444
- * @example
445
- * // play an awesome music
446
- * me.audio.playTrack("awesome_music");
447
- * // pause the audio track
448
- * me.audio.pauseTrack();
449
- * // resume the music
450
- * me.audio.resumeTrack();
451
- */
452
- resumeTrack : function () {
453
- if (current_track_id !== null) {
454
- audioTracks[current_track_id].play();
455
- }
456
- },
457
-
458
- /**
459
- * returns the current track Id
460
- * @name getCurrentTrack
461
- * @memberOf me.audio
462
- * @public
463
- * @function
464
- * @return {String} audio track name
465
- */
466
- getCurrentTrack : function () {
467
- return current_track_id;
468
- },
469
-
470
- /**
471
- * set the default global volume
472
- * @name setVolume
473
- * @memberOf me.audio
474
- * @public
475
- * @function
476
- * @param {Number} volume Float specifying volume (0.0 - 1.0 values accepted).
477
- */
478
- setVolume : function (volume) {
479
- Howler.volume(volume);
480
- },
481
-
482
- /**
483
- * get the default global volume
484
- * @name getVolume
485
- * @memberOf me.audio
486
- * @public
487
- * @function
488
- * @returns {Number} current volume value in Float [0.0 - 1.0] .
489
- */
490
- getVolume : function () {
491
- return Howler.volume();
492
- },
493
-
494
- /**
495
- * mute or unmute the specified sound, but does not pause the playback.
496
- * @name mute
497
- * @memberOf me.audio
498
- * @public
499
- * @function
500
- * @param {String} sound_name audio clip name - case sensitive
501
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will mute.
502
- * @param {Boolean} [mute=true] True to mute and false to unmute
503
- * @example
504
- * // mute the background music
505
- * me.audio.mute("awesome_music");
506
- */
507
- mute : function (sound_name, id, mute) {
508
- // if not defined : true
509
- mute = (typeof(mute) === "undefined" ? true : !!mute);
510
- var sound = audioTracks[sound_name];
511
- if (sound && typeof(sound) !== "undefined") {
512
- sound.mute(mute, id);
513
- } else {
514
- throw new Error("audio clip " + sound_name + " does not exist");
515
- }
516
- },
517
-
518
- /**
519
- * unmute the specified sound
520
- * @name unmute
521
- * @memberOf me.audio
522
- * @public
523
- * @function
524
- * @param {String} sound_name audio clip name
525
- * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will unmute.
526
- */
527
- unmute : function (sound_name, id) {
528
- this.mute(sound_name, id, false);
529
- },
530
-
531
- /**
532
- * mute all audio
533
- * @name muteAll
534
- * @memberOf me.audio
535
- * @public
536
- * @function
537
- */
538
- muteAll : function () {
539
- Howler.mute(true);
540
- },
541
-
542
- /**
543
- * unmute all audio
544
- * @name unmuteAll
545
- * @memberOf me.audio
546
- * @public
547
- * @function
548
- */
549
- unmuteAll : function () {
550
- Howler.mute(false);
551
- },
552
-
553
- /**
554
- * Returns true if audio is muted globally.
555
- * @name muted
556
- * @memberOf me.audio
557
- * @public
558
- * @function
559
- * @return {Boolean} true if audio is muted globally
560
- */
561
- muted : function () {
562
- return Howler._muted;
563
- },
564
-
565
- /**
566
- * unload specified audio track to free memory
567
- *
568
- * @name unload
569
- * @memberOf me.audio
570
- * @public
571
- * @function
572
- * @param {String} sound_name audio track name - case sensitive
573
- * @return {Boolean} true if unloaded
574
- * @example
575
- * me.audio.unload("awesome_music");
576
- */
577
- unload : function (sound_name) {
578
- if (!(sound_name in audioTracks)) {
579
- return false;
580
- }
302
+ } else {
303
+ Howler.stop();
304
+ }
305
+ };
581
306
 
582
- // destroy the Howl object
583
- audioTracks[sound_name].unload();
584
- delete audioTracks[sound_name];
585
- return true;
586
- },
587
-
588
- /**
589
- * unload all audio to free memory
590
- *
591
- * @name unloadAll
592
- * @memberOf me.audio
593
- * @public
594
- * @function
595
- * @example
596
- * me.audio.unloadAll();
597
- */
598
- unloadAll : function () {
599
- for (var sound_name in audioTracks) {
600
- if (audioTracks.hasOwnProperty(sound_name)) {
601
- this.unload(sound_name);
602
- }
603
- }
307
+ /**
308
+ * pause the specified sound on all channels<br>
309
+ * this function does not reset the currentTime property
310
+ * @function me.audio.pause
311
+ * @param {String} sound_name audio clip name - case sensitive
312
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will pause.
313
+ * @example
314
+ * me.audio.pause("cling");
315
+ */
316
+ export function pause(sound_name, id) {
317
+ var sound = audioTracks[sound_name];
318
+ if (sound && typeof sound !== "undefined") {
319
+ sound.pause(id);
320
+ } else {
321
+ throw new Error("audio clip " + sound_name + " does not exist");
604
322
  }
605
323
  };
606
324
 
607
- export default audio;
325
+ /**
326
+ * resume the specified sound on all channels<br>
327
+ * @function me.audio.resume
328
+ * @param {String} sound_name audio clip name - case sensitive
329
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will resume.
330
+ * @example
331
+ * // play a audio clip
332
+ * var id = me.audio.play("myClip");
333
+ * ...
334
+ * // pause it
335
+ * me.audio.pause("myClip", id);
336
+ * ...
337
+ * // resume
338
+ * me.audio.resume("myClip", id);
339
+ */
340
+ export function resume(sound_name, id) {
341
+ var sound = audioTracks[sound_name];
342
+ if (sound && typeof sound !== "undefined") {
343
+ sound.play(id);
344
+ } else {
345
+ throw new Error("audio clip " + sound_name + " does not exist");
346
+ }
347
+ };
348
+
349
+ /**
350
+ * play the specified audio track<br>
351
+ * this function automatically set the loop property to true<br>
352
+ * and keep track of the current sound being played.
353
+ * @function me.audio.playTrack
354
+ * @param {String} sound_name audio track name - case sensitive
355
+ * @param {Number} [volume=default] Float specifying volume (0.0 - 1.0 values accepted).
356
+ * @return {Number} the sound instance ID.
357
+ * @example
358
+ * me.audio.playTrack("awesome_music");
359
+ */
360
+ export function playTrack(sound_name, volume) {
361
+ current_track_id = sound_name;
362
+ return play(
363
+ current_track_id,
364
+ true,
365
+ null,
366
+ volume
367
+ );
368
+ };
369
+
370
+ /**
371
+ * stop the current audio track
372
+ * @function me.audio.stopTrack
373
+ * @see me.audio#playTrack
374
+ * @example
375
+ * // play a awesome music
376
+ * me.audio.playTrack("awesome_music");
377
+ * // stop the current music
378
+ * me.audio.stopTrack();
379
+ */
380
+ export function stopTrack() {
381
+ if (current_track_id !== null) {
382
+ audioTracks[current_track_id].stop();
383
+ current_track_id = null;
384
+ }
385
+ };
386
+
387
+ /**
388
+ * pause the current audio track
389
+ * @function me.audio.pauseTrack
390
+ * @example
391
+ * me.audio.pauseTrack();
392
+ */
393
+ export function pauseTrack() {
394
+ if (current_track_id !== null) {
395
+ audioTracks[current_track_id].pause();
396
+ }
397
+ };
398
+
399
+ /**
400
+ * resume the previously paused audio track
401
+ * @function me.audio.resumeTrack
402
+ * @example
403
+ * // play an awesome music
404
+ * me.audio.playTrack("awesome_music");
405
+ * // pause the audio track
406
+ * me.audio.pauseTrack();
407
+ * // resume the music
408
+ * me.audio.resumeTrack();
409
+ */
410
+ export function resumeTrack() {
411
+ if (current_track_id !== null) {
412
+ audioTracks[current_track_id].play();
413
+ }
414
+ };
415
+
416
+ /**
417
+ * returns the current track Id
418
+ * @function me.audio.getCurrentTrack
419
+ * @return {String} audio track name
420
+ */
421
+ export function getCurrentTrack() {
422
+ return current_track_id;
423
+ };
424
+
425
+ /**
426
+ * set the default global volume
427
+ * @function me.audio.setVolume
428
+ * @param {Number} volume Float specifying volume (0.0 - 1.0 values accepted).
429
+ */
430
+ export function setVolume(volume) {
431
+ Howler.volume(volume);
432
+ };
433
+
434
+ /**
435
+ * get the default global volume
436
+ * @function me.audio.getVolume
437
+ * @returns {Number} current volume value in Float [0.0 - 1.0] .
438
+ */
439
+ export function getVolume() {
440
+ return Howler.volume();
441
+ };
442
+
443
+ /**
444
+ * mute or unmute the specified sound, but does not pause the playback.
445
+ * @function me.audio.mute
446
+ * @param {String} sound_name audio clip name - case sensitive
447
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will mute.
448
+ * @param {Boolean} [mute=true] True to mute and false to unmute
449
+ * @example
450
+ * // mute the background music
451
+ * me.audio.mute("awesome_music");
452
+ */
453
+ export function mute(sound_name, id, mute) {
454
+ // if not defined : true
455
+ mute = (typeof(mute) === "undefined" ? true : !!mute);
456
+ var sound = audioTracks[sound_name];
457
+ if (sound && typeof(sound) !== "undefined") {
458
+ sound.mute(mute, id);
459
+ } else {
460
+ throw new Error("audio clip " + sound_name + " does not exist");
461
+ }
462
+ };
463
+
464
+ /**
465
+ * unmute the specified sound
466
+ * @function me.audio.unmute
467
+ * @param {String} sound_name audio clip name
468
+ * @param {Number} [id] the sound instance ID. If none is passed, all sounds in group will unmute.
469
+ */
470
+ export function unmute(sound_name, id) {
471
+ mute(sound_name, id, false);
472
+ };
473
+
474
+ /**
475
+ * mute all audio
476
+ * @function me.audio.muteAll
477
+ */
478
+ export function muteAll() {
479
+ Howler.mute(true);
480
+ };
481
+
482
+ /**
483
+ * unmute all audio
484
+ * @function me.audio.unmuteAll
485
+ */
486
+ export function unmuteAll() {
487
+ Howler.mute(false);
488
+ };
489
+
490
+ /**
491
+ * Returns true if audio is muted globally.
492
+ * @function me.audio.muted
493
+ * @return {Boolean} true if audio is muted globally
494
+ */
495
+ export function muted() {
496
+ return Howler._muted;
497
+ };
498
+
499
+ /**
500
+ * unload specified audio track to free memory
501
+ * @function me.audio.unload
502
+ * @param {String} sound_name audio track name - case sensitive
503
+ * @return {Boolean} true if unloaded
504
+ * @example
505
+ * me.audio.unload("awesome_music");
506
+ */
507
+ export function unload(sound_name) {
508
+ if (!(sound_name in audioTracks)) {
509
+ return false;
510
+ }
511
+
512
+ // destroy the Howl object
513
+ audioTracks[sound_name].unload();
514
+ delete audioTracks[sound_name];
515
+ return true;
516
+ };
517
+
518
+ /**
519
+ * unload all audio to free memory
520
+ * @function me.audio.unloadAll
521
+ * @function
522
+ * @example
523
+ * me.audio.unloadAll();
524
+ */
525
+ export function unloadAll() {
526
+ for (var sound_name in audioTracks) {
527
+ if (audioTracks.hasOwnProperty(sound_name)) {
528
+ unload(sound_name);
529
+ }
530
+ }
531
+ };