littlejsengine 1.9.5 → 1.9.7

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.
@@ -5,6 +5,6 @@
5
5
  <link rel=icon type=image/png href=../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../dist/littlejs.js?192></script>
9
- <script src=gameObjects.js?192></script>
10
- <script src=game.js?192></script>
8
+ <script src=../../dist/littlejs.js?196></script>
9
+ <script src=gameObjects.js?196></script>
10
+ <script src=game.js?196></script>
@@ -5,5 +5,5 @@
5
5
  <link rel=icon type=image/png href=../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../dist/littlejs.js?192></script>
9
- <script src=game.js?192></script>
8
+ <script src=../../dist/littlejs.js?196></script>
9
+ <script src=game.js?196></script>
@@ -6,7 +6,7 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- LittleJS Engine -->
9
- <script src=../../dist/littlejs.js?192></script>
9
+ <script src=../../dist/littlejs.js?196></script>
10
10
 
11
11
  <!-- Add your game scripts here -->
12
- <script src=game.js?192></script>
12
+ <script src=game.js?196></script>
@@ -95,6 +95,7 @@ function htmlBuildStep(filename)
95
95
 
96
96
  // create html file
97
97
  let buffer = '';
98
+ buffer += '<body>';
98
99
  buffer += '<script>';
99
100
  buffer += fs.readFileSync(filename);
100
101
  buffer += '</script>';
@@ -1,18 +1,18 @@
1
1
  <head><title>LittleJS JS13K Project</title></head><body>
2
2
 
3
3
  <!-- LittleJS Engine -->
4
- <script src=../../src/engineDebug.js?192></script>
5
- <script src=../../src/engineUtilities.js?192></script>
6
- <script src=../../src/engineSettings.js?192></script>
7
- <script src=../../src/engineObject.js?192></script>
8
- <script src=../../src/engineDraw.js?192></script>
9
- <script src=../../src/engineInput.js?192></script>
10
- <script src=../../src/engineAudio.js?192></script>
11
- <script src=../../src/engineTileLayer.js?192></script>
12
- <script src=../../src/engineParticles.js?192></script>
13
- <script src=../../src/engineMedals.js?192></script>
14
- <script src=../../src/engineWebGL.js?192></script>
15
- <script src=../../src/engine.js?192></script>
4
+ <script src=../../src/engineDebug.js?196></script>
5
+ <script src=../../src/engineUtilities.js?196></script>
6
+ <script src=../../src/engineSettings.js?196></script>
7
+ <script src=../../src/engineObject.js?196></script>
8
+ <script src=../../src/engineDraw.js?196></script>
9
+ <script src=../../src/engineInput.js?196></script>
10
+ <script src=../../src/engineAudio.js?196></script>
11
+ <script src=../../src/engineTileLayer.js?196></script>
12
+ <script src=../../src/engineParticles.js?196></script>
13
+ <script src=../../src/engineMedals.js?196></script>
14
+ <script src=../../src/engineWebGL.js?196></script>
15
+ <script src=../../src/engine.js?196></script>
16
16
 
17
17
  <!-- Add your game scripts here -->
18
- <script src=game.js?192></script>
18
+ <script src=game.js?196></script>
@@ -6,4 +6,4 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- Add your game scripts here -->
9
- <script src=game.js?192 type=module></script>
9
+ <script src=game.js?196 type=module></script>
@@ -9,7 +9,7 @@ button { margin:1px; }
9
9
  </style>
10
10
  </head><body>
11
11
 
12
- <script src=../../dist/littlejs.js?192></script>
12
+ <script src=../../dist/littlejs.js?196></script>
13
13
  <script>
14
14
 
15
15
  'use strict';
@@ -6,11 +6,11 @@
6
6
  <link rel=icon type=image/png href=../favicon.png>
7
7
  </head><body>
8
8
 
9
- <script src=../../dist/littlejs.js?192></script>
10
- <script src=gameObjects.js?192></script>
11
- <script src=gameCharacter.js?192></script>
12
- <script src=gamePlayer.js?192></script>
13
- <script src=gameEffects.js?192></script>
14
- <script src=gameLevel.js?192></script>
15
- <script src=gameLevelData.js?192></script>
16
- <script src=game.js?192></script>
9
+ <script src=../../dist/littlejs.js?196></script>
10
+ <script src=gameObjects.js?196></script>
11
+ <script src=gameCharacter.js?196></script>
12
+ <script src=gamePlayer.js?196></script>
13
+ <script src=gameEffects.js?196></script>
14
+ <script src=gameLevel.js?196></script>
15
+ <script src=gameLevelData.js?196></script>
16
+ <script src=game.js?196></script>
@@ -5,5 +5,5 @@
5
5
  <link rel=icon type=image/png href=../favicon.png>
6
6
  </head><body>
7
7
 
8
- <script src=../../dist/littlejs.js?192></script>
9
- <script src=game.js?192></script>
8
+ <script src=../../dist/littlejs.js?196></script>
9
+ <script src=game.js?196></script>
@@ -6,18 +6,18 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- LittleJS Engine -->
9
- <script src=../../src/engineDebug.js?192></script>
10
- <script src=../../src/engineUtilities.js?192></script>
11
- <script src=../../src/engineSettings.js?192></script>
12
- <script src=../../src/engineObject.js?192></script>
13
- <script src=../../src/engineDraw.js?192></script>
14
- <script src=../../src/engineInput.js?192></script>
15
- <script src=../../src/engineAudio.js?192></script>
16
- <script src=../../src/engineTileLayer.js?192></script>
17
- <script src=../../src/engineParticles.js?192></script>
18
- <script src=../../src/engineMedals.js?192></script>
19
- <script src=../../src/engineWebGL.js?192></script>
20
- <script src=../../src/engine.js?192></script>
9
+ <script src=../../src/engineDebug.js?196></script>
10
+ <script src=../../src/engineUtilities.js?196></script>
11
+ <script src=../../src/engineSettings.js?196></script>
12
+ <script src=../../src/engineObject.js?196></script>
13
+ <script src=../../src/engineDraw.js?196></script>
14
+ <script src=../../src/engineInput.js?196></script>
15
+ <script src=../../src/engineAudio.js?196></script>
16
+ <script src=../../src/engineTileLayer.js?196></script>
17
+ <script src=../../src/engineParticles.js?196></script>
18
+ <script src=../../src/engineMedals.js?196></script>
19
+ <script src=../../src/engineWebGL.js?196></script>
20
+ <script src=../../src/engine.js?196></script>
21
21
 
22
22
  <!-- Add your game scripts here -->
23
- <script src=game.js?192></script>
23
+ <script src=game.js?196></script>
@@ -6,7 +6,7 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- LittleJS Engine -->
9
- <script src=../../dist/littlejs.min.js?192></script>
9
+ <script src=../../dist/littlejs.min.js?196></script>
10
10
  <script>
11
11
 
12
12
  /*
@@ -6,4 +6,4 @@
6
6
  </head><body>
7
7
 
8
8
  <!-- Add your game scripts here -->
9
- <script src=game.js?192 type=module></script>
9
+ <script src=game.js?196 type=module></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.9.5",
3
+ "version": "1.9.7",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
package/src/engine.js CHANGED
@@ -30,7 +30,7 @@ const engineName = 'LittleJS';
30
30
  * @type {String}
31
31
  * @default
32
32
  * @memberof Engine */
33
- const engineVersion = '1.9.5';
33
+ const engineVersion = '1.9.7';
34
34
 
35
35
  /** Frames per second to update
36
36
  * @type {Number}
@@ -107,7 +107,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
107
107
  mainContext.imageSmoothingEnabled = !canvasPixelated;
108
108
 
109
109
  // setup gl rendering if enabled
110
- glEnable && glPreRender();
110
+ glPreRender();
111
111
  }
112
112
 
113
113
  // internal update loop for engine
@@ -126,11 +126,14 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
126
126
  frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
127
127
  if (!debugSpeedUp)
128
128
  frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp in case of slow framerate
129
+
129
130
  updateCanvas();
130
131
 
131
132
  if (paused)
132
133
  {
133
- // do post update even when paused
134
+ // update object transforms even when paused
135
+ for (const o of engineObjects)
136
+ o.parent || o.updateTransforms();
134
137
  inputUpdate();
135
138
  debugUpdate();
136
139
  gameUpdatePost();
@@ -142,7 +145,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
142
145
  let deltaSmooth = 0;
143
146
  if (frameTimeBufferMS < 0 && frameTimeBufferMS > -9)
144
147
  {
145
- // force an update each frame if time is close enough (not just a fast refresh rate)
148
+ // force at least one update each frame since it is waiting for refresh
146
149
  deltaSmooth = frameTimeBufferMS;
147
150
  frameTimeBufferMS = 0;
148
151
  }
@@ -167,34 +170,37 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
167
170
  // add the time smoothing back in
168
171
  frameTimeBufferMS += deltaSmooth;
169
172
  }
170
-
171
- // render sort then render while removing destroyed objects
172
- enginePreRender();
173
- gameRender();
174
- engineObjects.sort((a,b)=> a.renderOrder - b.renderOrder);
175
- for (const o of engineObjects)
176
- o.destroyed || o.render();
177
- gameRenderPost();
178
- glRenderPostProcess();
179
- medalsRender();
180
- touchGamepadRender();
181
- debugRender();
182
- glEnable && glCopyToContext(mainContext);
183
-
184
- if (showWatermark)
173
+
174
+ if (!headlessMode)
185
175
  {
186
- // update fps
187
- overlayContext.textAlign = 'right';
188
- overlayContext.textBaseline = 'top';
189
- overlayContext.font = '1em monospace';
190
- overlayContext.fillStyle = '#000';
191
- const text = engineName + ' ' + 'v' + engineVersion + ' / '
192
- + drawCount + ' / ' + engineObjects.length + ' / ' + averageFPS.toFixed(1)
193
- + (glEnable ? ' GL' : ' 2D') ;
194
- overlayContext.fillText(text, mainCanvas.width-3, 3);
195
- overlayContext.fillStyle = '#fff';
196
- overlayContext.fillText(text, mainCanvas.width-2, 2);
197
- drawCount = 0;
176
+ // render sort then render while removing destroyed objects
177
+ enginePreRender();
178
+ gameRender();
179
+ engineObjects.sort((a,b)=> a.renderOrder - b.renderOrder);
180
+ for (const o of engineObjects)
181
+ o.destroyed || o.render();
182
+ gameRenderPost();
183
+ glRenderPostProcess();
184
+ medalsRender();
185
+ touchGamepadRender();
186
+ debugRender();
187
+ glCopyToContext(mainContext);
188
+
189
+ if (showWatermark)
190
+ {
191
+ // update fps
192
+ overlayContext.textAlign = 'right';
193
+ overlayContext.textBaseline = 'top';
194
+ overlayContext.font = '1em monospace';
195
+ overlayContext.fillStyle = '#000';
196
+ const text = engineName + ' ' + 'v' + engineVersion + ' / '
197
+ + drawCount + ' / ' + engineObjects.length + ' / ' + averageFPS.toFixed(1)
198
+ + (glEnable ? ' GL' : ' 2D') ;
199
+ overlayContext.fillText(text, mainCanvas.width-3, 3);
200
+ overlayContext.fillStyle = '#fff';
201
+ overlayContext.fillText(text, mainCanvas.width-2, 2);
202
+ drawCount = 0;
203
+ }
198
204
  }
199
205
 
200
206
  requestAnimationFrame(engineUpdate);
@@ -202,6 +208,8 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
202
208
 
203
209
  function updateCanvas()
204
210
  {
211
+ if (headlessMode) return;
212
+
205
213
  if (canvasFixedSize.x)
206
214
  {
207
215
  // clear canvas and set fixed size
@@ -229,8 +237,20 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
229
237
  mainCanvasSize = vec2(mainCanvas.width, mainCanvas.height);
230
238
  }
231
239
 
240
+ function startEngine()
241
+ {
242
+ gameInit();
243
+ engineUpdate();
244
+ }
245
+
246
+ if (headlessMode)
247
+ {
248
+ startEngine();
249
+ return;
250
+ }
251
+
232
252
  // setup html
233
- const styleBody =
253
+ const styleBody =
234
254
  'margin:0;overflow:hidden;' + // fill the window
235
255
  'background:#000;' + // set background color
236
256
  'touch-action:none;' + // prevent mobile pinch to resize
@@ -242,8 +262,10 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
242
262
  mainContext = mainCanvas.getContext('2d');
243
263
 
244
264
  // init stuff and start engine
265
+ inputInit();
266
+ audioInit();
245
267
  debugInit();
246
- glEnable && glInit();
268
+ glInit();
247
269
 
248
270
  // create overlay canvas for hud to appear above gl canvas
249
271
  document.body.appendChild(overlayCanvas = document.createElement('canvas'));
@@ -284,12 +306,7 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
284
306
  }));
285
307
 
286
308
  // load all of the images
287
- Promise.all(promises).then(()=>
288
- {
289
- // start the engine
290
- gameInit();
291
- engineUpdate();
292
- });
309
+ Promise.all(promises).then(startEngine);
293
310
  }
294
311
 
295
312
  /** Update each engine object, remove destroyed objects, and update time
@@ -310,7 +327,14 @@ function engineObjectsUpdate()
310
327
  }
311
328
  }
312
329
  for (const o of engineObjects)
313
- o.parent || updateObject(o);
330
+ {
331
+ // update top level objects
332
+ if (!o.parent)
333
+ {
334
+ updateObject(o);
335
+ o.updateTransforms();
336
+ }
337
+ }
314
338
 
315
339
  // remove destroyed objects
316
340
  engineObjects = engineObjects.filter(o=>!o.destroyed);
@@ -11,6 +11,32 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ /** Audio context used by the engine
15
+ * @type {AudioContext}
16
+ * @memberof Audio */
17
+ let audioContext;
18
+
19
+ /** Master gain node for all audio to pass through
20
+ * @type {GainNode}
21
+ * @memberof Audio */
22
+ let audioGainNode;
23
+
24
+ function audioInit()
25
+ {
26
+ if (!soundEnable || headlessMode) return;
27
+
28
+ // create audio context
29
+ audioContext = new AudioContext;
30
+
31
+ // create and connect gain node
32
+ // (createGain is more widely spported then GainNode construtor)
33
+ audioGainNode = audioContext.createGain();
34
+ audioGainNode.connect(audioContext.destination);
35
+ setSoundVolume(soundVolume); // update gain volume
36
+ }
37
+
38
+ ///////////////////////////////////////////////////////////////////////////////
39
+
14
40
  /**
15
41
  * Sound Object - Stores a sound for later use and can be played positionally
16
42
  *
@@ -31,7 +57,7 @@ class Sound
31
57
  */
32
58
  constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
33
59
  {
34
- if (!soundEnable) return;
60
+ if (!soundEnable || headlessMode) return;
35
61
 
36
62
  /** @property {Number} - World space max range of sound, will not play if camera is farther away */
37
63
  this.range = range;
@@ -45,8 +71,8 @@ class Sound
45
71
  if (zzfxSound)
46
72
  {
47
73
  // generate zzfx sound now for fast playback
48
- this.randomness = zzfxSound[1] || 0;
49
- zzfxSound[1] = 0; // generate without randomness
74
+ const defaultRandomness = .05;
75
+ this.randomness = zzfxSound[1] || defaultRandomness;
50
76
  this.sampleChannels = [zzfxG(...zzfxSound)];
51
77
  this.sampleRate = zzfxR;
52
78
  }
@@ -62,7 +88,8 @@ class Sound
62
88
  */
63
89
  play(pos, volume=1, pitch=1, randomnessScale=1, loop=false)
64
90
  {
65
- if (!soundEnable || !this.sampleChannels) return;
91
+ if (!soundEnable || headlessMode) return;
92
+ if (!this.sampleChannels) return;
66
93
 
67
94
  let pan;
68
95
  if (pos)
@@ -139,14 +166,14 @@ class SoundWave extends Sound
139
166
  * @param {Number} [randomness] - How much to randomize frequency each time sound plays
140
167
  * @param {Number} [range=soundDefaultRange] - World space max range of sound, will not play if camera is farther away
141
168
  * @param {Number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering off
169
+ * @param {Function} [onloadCallback] - callback function to call when sound is loaded
142
170
  */
143
- constructor(filename, randomness=0, range, taper)
171
+ constructor(filename, randomness=0, range, taper, onloadCallback)
144
172
  {
145
173
  super(undefined, range, taper);
146
- this.randomness = randomness;
147
-
148
- if (!soundEnable) return;
174
+ if (!soundEnable || headlessMode) return;
149
175
 
176
+ this.randomness = randomness;
150
177
  fetch(filename)
151
178
  .then(response => response.arrayBuffer())
152
179
  .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))
@@ -156,10 +183,23 @@ class SoundWave extends Sound
156
183
  for (let i = audioBuffer.numberOfChannels; i--;)
157
184
  this.sampleChannels[i] = Array.from(audioBuffer.getChannelData(i));
158
185
  this.sampleRate = audioBuffer.sampleRate;
159
- });
186
+ }).then(() => onloadCallback && onloadCallback(this));
160
187
  }
161
188
  }
162
189
 
190
+ /** Play an mp3, ogg, or wav audio from a local file or url
191
+ * @param {String} filename - Location of sound file to play
192
+ * @param {Number} [volume] - How much to scale volume by
193
+ * @param {Boolean} [loop] - True if the music should loop
194
+ * @return {SoundWave} - The sound object for this file
195
+ * @memberof Audio */
196
+ function playAudioFile(filename, volume=1, loop=false)
197
+ {
198
+ if (!soundEnable || headlessMode) return;
199
+
200
+ return new SoundWave(filename,0,0,0, s=>s.play(undefined, volume, 1, 1, loop));
201
+ }
202
+
163
203
  /**
164
204
  * Music Object - Stores a zzfx music track for later use
165
205
  *
@@ -199,7 +239,7 @@ class Music extends Sound
199
239
  {
200
240
  super(undefined);
201
241
 
202
- if (!soundEnable) return;
242
+ if (!soundEnable || headlessMode) return;
203
243
  this.randomness = 0;
204
244
  this.sampleChannels = zzfxM(...zzfxMusic);
205
245
  this.sampleRate = zzfxR;
@@ -214,23 +254,6 @@ class Music extends Sound
214
254
  { return super.play(undefined, volume, 1, 1, loop); }
215
255
  }
216
256
 
217
- /** Play an mp3, ogg, or wav audio from a local file or url
218
- * @param {String} filename - Location of sound file to play
219
- * @param {Number} [volume] - How much to scale volume by
220
- * @param {Boolean} [loop] - True if the music should loop
221
- * @return {HTMLAudioElement} - The audio element for this sound
222
- * @memberof Audio */
223
- function playAudioFile(filename, volume=1, loop=false)
224
- {
225
- if (!soundEnable) return;
226
-
227
- const audio = new Audio(filename);
228
- audio.volume = soundVolume * volume;
229
- audio.loop = loop;
230
- audio.play();
231
- return audio;
232
- }
233
-
234
257
  /** Speak text with passed in settings
235
258
  * @param {String} text - The text to speak
236
259
  * @param {String} [language] - The language/accent to use (examples: en, it, ru, ja, zh)
@@ -241,7 +264,8 @@ function playAudioFile(filename, volume=1, loop=false)
241
264
  * @memberof Audio */
242
265
  function speak(text, language='', volume=1, rate=1, pitch=1)
243
266
  {
244
- if (!soundEnable || !speechSynthesis) return;
267
+ if (!soundEnable || headlessMode) return;
268
+ if (!speechSynthesis) return;
245
269
 
246
270
  // common languages (not supported by all browsers)
247
271
  // en - english, it - italian, fr - french, de - german, es - spanish
@@ -271,14 +295,8 @@ function getNoteFrequency(semitoneOffset, rootFrequency=220)
271
295
 
272
296
  ///////////////////////////////////////////////////////////////////////////////
273
297
 
274
- /** Audio context used by the engine
275
- * @type {AudioContext}
276
- * @memberof Audio */
277
- let audioContext = new AudioContext;
278
-
279
- /** Keep track if audio was suspended when last sound was played
280
- * @type {Boolean}
281
- * @memberof Audio */
298
+ // internal tracking if audio was suspended when last sound was played
299
+ // allows first suspended sound to play when audio is resumed
282
300
  let audioSuspended = false;
283
301
 
284
302
  /** Play cached audio samples with given settings
@@ -292,7 +310,7 @@ let audioSuspended = false;
292
310
  * @memberof Audio */
293
311
  function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sampleRate=zzfxR)
294
312
  {
295
- if (!soundEnable) return;
313
+ if (!soundEnable || headlessMode) return;
296
314
 
297
315
  // prevent sounds from building up if they can't be played
298
316
  const audioWasSuspended = audioSuspended;
@@ -316,10 +334,13 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
316
334
  source.playbackRate.value = rate;
317
335
  source.loop = loop;
318
336
 
319
- // create and connect gain node (createGain is more widely spported then GainNode construtor)
337
+ // set master gain volume
338
+ setSoundVolume(soundVolume);
339
+
340
+ // create and connect gain node
320
341
  const gainNode = audioContext.createGain();
321
- gainNode.gain.value = soundVolume*volume;
322
- gainNode.connect(audioContext.destination);
342
+ gainNode.gain.value = volume;
343
+ gainNode.connect(audioGainNode);
323
344
 
324
345
  // connect source to stereo panner and gain
325
346
  source.connect(new StereoPannerNode(audioContext, {'pan':clamp(pan, -1, 1)})).connect(gainNode);
@@ -338,7 +359,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=false, sample
338
359
  * @param {Array} zzfxSound - Array of ZzFX parameters, ex. [.5,.5]
339
360
  * @return {AudioBufferSourceNode} - The audio node of the sound played
340
361
  * @memberof Audio */
341
- function zzfx(...zzfxSound) { return playSamples([zzfxG(...zzfxSound)]); }
362
+ function zzfx(...zzfxSound) { return new Sound(zzfxSound).play(); }
342
363
 
343
364
  /** Sample rate used for all ZzFX sounds
344
365
  * @default 44100
@@ -347,7 +368,7 @@ const zzfxR = 44100;
347
368
 
348
369
  /** Generate samples for a ZzFX sound
349
370
  * @param {Number} [volume] - Volume scale (percent)
350
- * @param {Number} [randomness] - How much to randomize frequency (percent Hz)
371
+ * @param {Number} [randomness] - Unused in this fuction, handled by Sound class
351
372
  * @param {Number} [frequency] - Frequency of sound (Hz)
352
373
  * @param {Number} [attack] - Attack time, how fast sound starts (seconds)
353
374
  * @param {Number} [sustain] - Sustain time, how long sound holds (seconds)
@@ -373,17 +394,18 @@ const zzfxR = 44100;
373
394
  function zzfxG
374
395
  (
375
396
  // parameters
376
- volume = 1, randomness = .05, frequency = 220, attack = 0, sustain = 0,
397
+ volume = 1, randomness = 0, frequency = 220, attack = 0, sustain = 0,
377
398
  release = .1, shape = 0, shapeCurve = 1, slide = 0, deltaSlide = 0,
378
399
  pitchJump = 0, pitchJumpTime = 0, repeatTime = 0, noise = 0, modulation = 0,
379
400
  bitCrush = 0, delay = 0, sustainVolume = 1, decay = 0, tremolo = 0, filter = 0
380
401
  )
381
402
  {
403
+ // LJS Note: ZZFX modded so randomness is handled by Sound class
404
+
382
405
  // init parameters
383
406
  let PI2 = PI*2, sampleRate = zzfxR,
384
407
  startSlide = slide *= 500 * PI2 / sampleRate / sampleRate,
385
- startFrequency = frequency *=
386
- rand(1 + randomness, 1-randomness) * PI2 / sampleRate,
408
+ startFrequency = frequency *= PI2 / sampleRate,
387
409
  b = [], t = 0, tm = 0, i = 0, j = 1, r = 0, c = 0, s = 0, f, length,
388
410
 
389
411
  // biquad LP/HP filter
@@ -405,7 +427,6 @@ function zzfxG
405
427
  pitchJump *= PI2 / sampleRate;
406
428
  pitchJumpTime *= sampleRate;
407
429
  repeatTime = repeatTime * sampleRate | 0;
408
- volume *= soundVolume;
409
430
 
410
431
  // generate waveform
411
432
  for(length = attack + decay + sustain + release + delay | 0;
@@ -149,7 +149,7 @@ function debugClear() { debugPrimitives = []; }
149
149
  * @param {String} [filename]
150
150
  * @param {String} [type]
151
151
  * @memberof Debug */
152
- function debugSaveCanvas(canvas, filename=engineName, type='image/png')
152
+ function debugSaveCanvas(canvas, filename='screenshot', type='image/png')
153
153
  { debugSaveDataURL(canvas.toDataURL(type), filename); }
154
154
 
155
155
  /** Save a text file to disk
@@ -157,7 +157,7 @@ function debugSaveCanvas(canvas, filename=engineName, type='image/png')
157
157
  * @param {String} [filename]
158
158
  * @param {String} [type]
159
159
  * @memberof Debug */
160
- function debugSaveText(text, filename=engineName, type='text/plain')
160
+ function debugSaveText(text, filename='text', type='text/plain')
161
161
  { debugSaveDataURL(URL.createObjectURL(new Blob([text], {'type':type})), filename); }
162
162
 
163
163
  /** Save a data url to disk
@@ -177,8 +177,7 @@ function debugSaveDataURL(dataURL, filename)
177
177
  function debugInit()
178
178
  {
179
179
  // create link for saving screenshots
180
- document.body.appendChild(downloadLink = document.createElement('a'));
181
- downloadLink.style.display = 'none';
180
+ downloadLink = document.createElement('a');
182
181
  }
183
182
 
184
183
  function debugUpdate()