littlejsengine 1.12.4 → 1.13.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.
- package/dist/box2d.wasm.js +630 -0
- package/dist/box2d.wasm.wasm +0 -0
- package/dist/littlejs.d.ts +437 -219
- package/dist/littlejs.esm.js +5950 -5307
- package/dist/littlejs.esm.min.js +4 -1
- package/dist/littlejs.js +5921 -5295
- package/dist/littlejs.min.js +4 -1
- package/dist/littlejs.release.js +5485 -4886
- package/examples/box2d/game.js +37 -42
- package/examples/box2d/gameObjects.js +41 -37
- package/examples/box2d/index.html +2 -2
- package/examples/box2d/scenes.js +24 -20
- package/examples/box2d/tiles.png +0 -0
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +1 -1
- package/examples/breakoutTutorial/README.md +2 -2
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/breakoutTutorial/index.html +1 -1
- package/examples/empty/index.html +1 -1
- package/examples/htmlMenu/index.html +1 -1
- package/examples/index.html +410 -159
- package/examples/module/game.js +1 -1
- package/examples/module/index.html +1 -1
- package/examples/platformer/game.js +6 -15
- package/examples/platformer/gameCharacter.js +6 -6
- package/examples/platformer/gameEffects.js +74 -57
- package/examples/platformer/gameLevel.js +61 -70
- package/examples/platformer/gameObjects.js +4 -4
- package/examples/platformer/index.html +1 -1
- package/examples/puzzle/index.html +1 -1
- package/examples/shorts/base.html +24 -3
- package/examples/shorts/box2d.js +46 -0
- package/examples/shorts/box2dCar.js +45 -0
- package/examples/shorts/flappyGame.js +52 -0
- package/examples/shorts/helloWorld.js +6 -3
- package/examples/shorts/hillGlideGame.js +56 -0
- package/examples/shorts/landerGame.js +32 -0
- package/examples/shorts/maze.js +47 -0
- package/examples/shorts/medals.js +42 -0
- package/examples/shorts/nineSlice.js +21 -0
- package/examples/shorts/piano.js +52 -0
- package/examples/shorts/platformer.js +24 -20
- package/examples/shorts/{pong.js → pongGame.js} +1 -1
- package/examples/shorts/postProcess.js +45 -0
- package/examples/shorts/raycasting.js +71 -0
- package/examples/shorts/slidingPuzzle.js +42 -0
- package/examples/shorts/spaceGame.js +56 -0
- package/examples/shorts/starfield.js +17 -0
- package/examples/shorts/tileLayer.js +3 -5
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +8 -7
- package/examples/shorts/topDown.js +18 -26
- package/examples/shorts/uiSystem.js +36 -0
- package/examples/starter/build.bat +6 -1
- package/examples/starter/game.js +4 -2
- package/examples/starter/index.html +23 -13
- package/examples/stress/index.html +2 -3
- package/examples/style.css +136 -0
- package/examples/typescript/build.js +1 -2
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/game.ts +1 -1
- package/examples/typescript/index.html +1 -1
- package/examples/uiSystem/game.js +9 -25
- package/examples/uiSystem/index.html +1 -1
- package/package.json +1 -1
- package/plugins/box2d.js +29 -35
- package/plugins/drawUtilities.js +126 -0
- package/plugins/newgrounds.js +1 -1
- package/plugins/pluginExport.js +8 -2
- package/plugins/postProcess.js +2 -2
- package/plugins/uiSystem.js +162 -68
- package/plugins/zzfxm.js +1 -1
- package/reference.md +10 -10
- package/src/engine.js +59 -39
- package/src/engineAudio.js +38 -20
- package/src/engineBuild.bat +6 -1
- package/src/engineBuild.js +32 -7
- package/src/engineDebug.js +53 -26
- package/src/engineDraw.js +108 -57
- package/src/engineExport.js +22 -9
- package/src/engineInput.js +112 -40
- package/src/engineObject.js +68 -67
- package/src/engineParticles.js +26 -9
- package/src/engineSettings.js +15 -16
- package/src/engineTileLayer.js +312 -153
- package/src/engineUtilities.js +198 -130
- package/src/engineWebGL.js +58 -35
package/src/engineAudio.js
CHANGED
|
@@ -47,17 +47,17 @@ class Sound
|
|
|
47
47
|
{
|
|
48
48
|
/** Create a sound object and cache the zzfx samples for later use
|
|
49
49
|
* @param {Array} zzfxSound - Array of zzfx parameters, ex. [.5,.5]
|
|
50
|
-
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
50
|
+
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
51
51
|
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
52
52
|
*/
|
|
53
53
|
constructor(zzfxSound, range=soundDefaultRange, taper=soundDefaultTaper)
|
|
54
54
|
{
|
|
55
55
|
if (!soundEnable || headlessMode) return;
|
|
56
56
|
|
|
57
|
-
/** @property {number} - World space max range of sound
|
|
57
|
+
/** @property {number} - World space max range of sound */
|
|
58
58
|
this.range = range;
|
|
59
59
|
|
|
60
|
-
/** @property {number} - At what percentage of range should it start tapering
|
|
60
|
+
/** @property {number} - At what percentage of range should it start tapering */
|
|
61
61
|
this.taper = taper;
|
|
62
62
|
|
|
63
63
|
/** @property {number} - How much to randomize frequency each time sound plays */
|
|
@@ -122,11 +122,20 @@ class Sound
|
|
|
122
122
|
this.gainNode.gain.value = volume;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
/** Stop the last instance of this sound that was played
|
|
126
|
-
|
|
125
|
+
/** Stop the last instance of this sound that was played
|
|
126
|
+
* @param {number} [fadeTime] - How long to fade out (seconds)
|
|
127
|
+
*/
|
|
128
|
+
stop(fadeTime=0)
|
|
127
129
|
{
|
|
128
|
-
if (this.source)
|
|
129
|
-
|
|
130
|
+
if (!this.source)
|
|
131
|
+
return;
|
|
132
|
+
|
|
133
|
+
// ramp off gain
|
|
134
|
+
const startFade = audioContext.currentTime;
|
|
135
|
+
const endFade = startFade + fadeTime;
|
|
136
|
+
this.gainNode.gain.linearRampToValueAtTime(1, startFade);
|
|
137
|
+
this.gainNode.gain.linearRampToValueAtTime(0, endFade);
|
|
138
|
+
this.source.stop(endFade);
|
|
130
139
|
this.source = undefined;
|
|
131
140
|
}
|
|
132
141
|
|
|
@@ -173,8 +182,8 @@ class SoundWave extends Sound
|
|
|
173
182
|
/** Create a sound object and cache the wave file for later use
|
|
174
183
|
* @param {string} filename - Filename of audio file to load
|
|
175
184
|
* @param {number} [randomness] - How much to randomize frequency each time sound plays
|
|
176
|
-
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
177
|
-
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
185
|
+
* @param {number} [range=soundDefaultRange] - World space max range of sound
|
|
186
|
+
* @param {number} [taper=soundDefaultTaper] - At what percentage of range should it start tapering
|
|
178
187
|
* @param {Function} [onloadCallback] - callback function to call when sound is loaded
|
|
179
188
|
*/
|
|
180
189
|
constructor(filename, randomness=0, range, taper, onloadCallback)
|
|
@@ -182,17 +191,26 @@ class SoundWave extends Sound
|
|
|
182
191
|
super(undefined, range, taper);
|
|
183
192
|
if (!soundEnable || headlessMode) return;
|
|
184
193
|
|
|
194
|
+
/** @property {Function} - callback function to call when sound is loaded */
|
|
195
|
+
this.onloadCallback = onloadCallback;
|
|
185
196
|
this.randomness = randomness;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
this.loadSound(filename);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Loads a sound from a URL and decodes it into sample data. Must be used with await!
|
|
201
|
+
* @param {string} filename
|
|
202
|
+
* @return {Promise<void>} */
|
|
203
|
+
async loadSound(filename)
|
|
204
|
+
{
|
|
205
|
+
const response = await fetch(filename);
|
|
206
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
207
|
+
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
|
208
|
+
this.sampleChannels = [];
|
|
209
|
+
for (let i = audioBuffer.numberOfChannels; i--;)
|
|
210
|
+
this.sampleChannels[i] = Array.from(audioBuffer.getChannelData(i));
|
|
211
|
+
this.sampleRate = audioBuffer.sampleRate;
|
|
212
|
+
if (this.onloadCallback)
|
|
213
|
+
this.onloadCallback();
|
|
196
214
|
}
|
|
197
215
|
}
|
|
198
216
|
|
|
@@ -460,4 +478,4 @@ function zzfxG
|
|
|
460
478
|
}
|
|
461
479
|
|
|
462
480
|
return b; // return sample buffer
|
|
463
|
-
}
|
|
481
|
+
}
|
package/src/engineBuild.bat
CHANGED
package/src/engineBuild.js
CHANGED
|
@@ -26,7 +26,6 @@ const engineSourceFiles =
|
|
|
26
26
|
`${SOURCE_FOLDER}/engineParticles.js`,
|
|
27
27
|
`${SOURCE_FOLDER}/engineMedals.js`,
|
|
28
28
|
`${SOURCE_FOLDER}/engineWebGL.js`,
|
|
29
|
-
`${SOURCE_FOLDER}/engine.js`,
|
|
30
29
|
];
|
|
31
30
|
const enginePluginFiles =
|
|
32
31
|
[
|
|
@@ -35,6 +34,12 @@ const enginePluginFiles =
|
|
|
35
34
|
`${PLUGIN_FOLDER}/zzfxm.js`,
|
|
36
35
|
`${PLUGIN_FOLDER}/uiSystem.js`,
|
|
37
36
|
`${PLUGIN_FOLDER}/box2d.js`,
|
|
37
|
+
`${PLUGIN_FOLDER}/drawUtilities.js`,
|
|
38
|
+
];
|
|
39
|
+
const engineExtraFiles =
|
|
40
|
+
[
|
|
41
|
+
`${PLUGIN_FOLDER}/box2d.wasm.js`,
|
|
42
|
+
`${PLUGIN_FOLDER}/box2d.wasm.wasm`,
|
|
38
43
|
];
|
|
39
44
|
const asciiArt =`
|
|
40
45
|
~~~~°°°°ooo°oOo°ooOooOooOo.
|
|
@@ -44,7 +49,7 @@ const asciiArt =`
|
|
|
44
49
|
OOO OOO OO OO OO=OO-oo\\
|
|
45
50
|
`;
|
|
46
51
|
const license = '// LittleJS Engine - MIT License - Copyright 2021 Frank Force\n'+
|
|
47
|
-
'// https://github.com/KilledByAPixel/LittleJS\n';
|
|
52
|
+
'// https://github.com/KilledByAPixel/LittleJS\n\n';
|
|
48
53
|
|
|
49
54
|
console.log(asciiArt);
|
|
50
55
|
console.log('Choo Choo... Building LittleJS Engine!\n');
|
|
@@ -57,6 +62,11 @@ try
|
|
|
57
62
|
// Setup build folder
|
|
58
63
|
fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
|
|
59
64
|
fs.mkdirSync(BUILD_FOLDER);
|
|
65
|
+
|
|
66
|
+
// copy extra files to build folder
|
|
67
|
+
for (const file of engineExtraFiles)
|
|
68
|
+
fs.copyFileSync(file, `${BUILD_FOLDER}/${file.substring(file.lastIndexOf('/')+1)}`);
|
|
69
|
+
|
|
60
70
|
}
|
|
61
71
|
catch (e) { handleError(e, 'Failed to create build folder!'); }
|
|
62
72
|
|
|
@@ -65,6 +75,7 @@ Build
|
|
|
65
75
|
'Build Engine -- all',
|
|
66
76
|
`${BUILD_FOLDER}/${ENGINE_NAME}.js`,
|
|
67
77
|
[
|
|
78
|
+
`${SOURCE_FOLDER}/engine.js`,
|
|
68
79
|
`${SOURCE_FOLDER}/engineDebug.js`,
|
|
69
80
|
...engineSourceFiles,
|
|
70
81
|
...enginePluginFiles
|
|
@@ -77,6 +88,7 @@ Build
|
|
|
77
88
|
'Build Engine -- release',
|
|
78
89
|
`${BUILD_FOLDER}/${ENGINE_NAME}.release.js`,
|
|
79
90
|
[
|
|
91
|
+
`${SOURCE_FOLDER}/engine.js`,
|
|
80
92
|
`${SOURCE_FOLDER}/engineRelease.js`,
|
|
81
93
|
...engineSourceFiles,
|
|
82
94
|
...enginePluginFiles
|
|
@@ -89,7 +101,7 @@ Build
|
|
|
89
101
|
'Build Engine -- minified',
|
|
90
102
|
`${BUILD_FOLDER}/${ENGINE_NAME}.min.js`,
|
|
91
103
|
[`${BUILD_FOLDER}/${ENGINE_NAME}.release.js`],
|
|
92
|
-
[closureCompilerStep, uglifyBuildStep]
|
|
104
|
+
[closureCompilerStep, uglifyBuildStep, addLicenseStep]
|
|
93
105
|
);
|
|
94
106
|
|
|
95
107
|
Build
|
|
@@ -113,7 +125,7 @@ Build
|
|
|
113
125
|
`${SOURCE_FOLDER}/engineExport.js`,
|
|
114
126
|
`${PLUGIN_FOLDER}/pluginExport.js`
|
|
115
127
|
],
|
|
116
|
-
[uglifyBuildStep]
|
|
128
|
+
[uglifyBuildStep, addLicenseStep]
|
|
117
129
|
);
|
|
118
130
|
|
|
119
131
|
console.log(`Engine built in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
|
|
@@ -131,7 +143,7 @@ function Build(message, outputFile, files=[], buildSteps=[], isPrimaryBuild)
|
|
|
131
143
|
if (isPrimaryBuild)
|
|
132
144
|
{
|
|
133
145
|
// add license and strict mode to top
|
|
134
|
-
buffer += license
|
|
146
|
+
buffer += license;
|
|
135
147
|
buffer += "'use strict';\n\n";
|
|
136
148
|
}
|
|
137
149
|
|
|
@@ -140,9 +152,9 @@ function Build(message, outputFile, files=[], buildSteps=[], isPrimaryBuild)
|
|
|
140
152
|
// get file content
|
|
141
153
|
let fileContent = fs.readFileSync(file) + '\n';
|
|
142
154
|
|
|
143
|
-
// remove first 'use strict'
|
|
155
|
+
// remove first 'use strict' and surrounding new lines
|
|
144
156
|
if (isPrimaryBuild)
|
|
145
|
-
fileContent = fileContent.replace(
|
|
157
|
+
fileContent = fileContent.replace(/'use strict';\s*\n/g, '');
|
|
146
158
|
|
|
147
159
|
// add it to the buffer
|
|
148
160
|
buffer += fileContent;
|
|
@@ -179,6 +191,19 @@ function uglifyBuildStep(filename)
|
|
|
179
191
|
catch (e) { handleError(e,'Failed to run Uglify minification step!'); }
|
|
180
192
|
};
|
|
181
193
|
|
|
194
|
+
// Add license to top of file
|
|
195
|
+
function addLicenseStep(filename)
|
|
196
|
+
{
|
|
197
|
+
try
|
|
198
|
+
{
|
|
199
|
+
// add license to top of minified file
|
|
200
|
+
let fileContent = fs.readFileSync(filename, 'utf8');
|
|
201
|
+
fileContent = license + fileContent;
|
|
202
|
+
fs.writeFileSync(filename, fileContent);
|
|
203
|
+
}
|
|
204
|
+
catch (e) { handleError(e, 'Failed to add license to minified file!'); }
|
|
205
|
+
};
|
|
206
|
+
|
|
182
207
|
// Build TypeScript definitions
|
|
183
208
|
function typeScriptBuildStep(filename)
|
|
184
209
|
{
|
package/src/engineDebug.js
CHANGED
|
@@ -47,19 +47,19 @@ let debugKey = 'Escape';
|
|
|
47
47
|
let debugOverlay = false;
|
|
48
48
|
|
|
49
49
|
// Engine internal variables not exposed to documentation
|
|
50
|
-
let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParticles = false, debugGamepads = false, debugMedals = false, debugTakeScreenshot, downloadLink;
|
|
50
|
+
let debugPrimitives = [], debugPhysics = false, debugRaycast = false, debugParticles = false, debugGamepads = false, debugMedals = false, debugTakeScreenshot, downloadLink, debugCanvas;
|
|
51
51
|
|
|
52
52
|
///////////////////////////////////////////////////////////////////////////////
|
|
53
53
|
// Debug helper functions
|
|
54
54
|
|
|
55
55
|
/** Asserts if the expression is false, does not do anything in release builds
|
|
56
|
-
* @param {boolean} assert
|
|
57
|
-
* @param {Object} [output]
|
|
56
|
+
* @param {boolean} assert
|
|
57
|
+
* @param {...Object} [output] - error message output
|
|
58
58
|
* @memberof Debug */
|
|
59
|
-
function ASSERT(assert, output)
|
|
59
|
+
function ASSERT(assert, ...output)
|
|
60
60
|
{
|
|
61
61
|
if (enableAsserts)
|
|
62
|
-
|
|
62
|
+
console.assert(assert, ...output);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/** Draw a debug rectangle in world space
|
|
@@ -132,16 +132,22 @@ function debugLine(posA, posB, color, thickness=.1, time)
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/** Draw a debug combined axis aligned bounding box in world space
|
|
135
|
-
* @param {Vector2}
|
|
136
|
-
* @param {Vector2}
|
|
137
|
-
* @param {Vector2}
|
|
138
|
-
* @param {Vector2}
|
|
135
|
+
* @param {Vector2} posA
|
|
136
|
+
* @param {Vector2} sizeA
|
|
137
|
+
* @param {Vector2} posB
|
|
138
|
+
* @param {Vector2} sizeB
|
|
139
139
|
* @param {string} [color]
|
|
140
140
|
* @memberof Debug */
|
|
141
|
-
function debugOverlap(
|
|
141
|
+
function debugOverlap(posA, sizeA, posB, sizeB, color)
|
|
142
142
|
{
|
|
143
|
-
const minPos = vec2(
|
|
144
|
-
|
|
143
|
+
const minPos = vec2(
|
|
144
|
+
min(posA.x - sizeA.x/2, posB.x - sizeB.x/2),
|
|
145
|
+
min(posA.y - sizeA.y/2, posB.y - sizeB.y/2)
|
|
146
|
+
);
|
|
147
|
+
const maxPos = vec2(
|
|
148
|
+
max(posA.x + sizeA.x/2, posB.x + sizeB.x/2),
|
|
149
|
+
max(posA.y + sizeA.y/2, posB.y + sizeB.y/2)
|
|
150
|
+
);
|
|
145
151
|
debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color);
|
|
146
152
|
}
|
|
147
153
|
|
|
@@ -169,12 +175,25 @@ function debugClear() { debugPrimitives = []; }
|
|
|
169
175
|
function debugScreenshot() { debugTakeScreenshot = 1; }
|
|
170
176
|
|
|
171
177
|
/** Save a canvas to disk
|
|
172
|
-
* @param {HTMLCanvasElement} canvas
|
|
173
|
-
* @param {string}
|
|
174
|
-
* @param {string}
|
|
178
|
+
* @param {HTMLCanvasElement|OffscreenCanvas} canvas
|
|
179
|
+
* @param {string} [filename]
|
|
180
|
+
* @param {string} [type]
|
|
175
181
|
* @memberof Debug */
|
|
176
182
|
function debugSaveCanvas(canvas, filename='screenshot', type='image/png')
|
|
177
|
-
{
|
|
183
|
+
{
|
|
184
|
+
if (canvas instanceof OffscreenCanvas)
|
|
185
|
+
{
|
|
186
|
+
// copy to temporary canvas and save
|
|
187
|
+
if (!debugCanvas)
|
|
188
|
+
debugCanvas = document.createElement('canvas');
|
|
189
|
+
debugCanvas.width = canvas.width;
|
|
190
|
+
debugCanvas.height = canvas.height;
|
|
191
|
+
debugCanvas.getContext('2d').drawImage(canvas, 0, 0);
|
|
192
|
+
debugSaveDataURL(debugCanvas.toDataURL(type), filename);
|
|
193
|
+
}
|
|
194
|
+
else
|
|
195
|
+
debugSaveDataURL(canvas.toDataURL(type), filename);
|
|
196
|
+
}
|
|
178
197
|
|
|
179
198
|
/** Save a text file to disk
|
|
180
199
|
* @param {string} text
|
|
@@ -252,7 +271,8 @@ function debugRender()
|
|
|
252
271
|
if (debugVideoCaptureIsActive())
|
|
253
272
|
return; // don't show debug info when capturing video
|
|
254
273
|
|
|
255
|
-
|
|
274
|
+
// flush any gl sprites before drawing debug info
|
|
275
|
+
glFlush();
|
|
256
276
|
|
|
257
277
|
if (debugTakeScreenshot)
|
|
258
278
|
{
|
|
@@ -329,8 +349,11 @@ function debugRender()
|
|
|
329
349
|
}
|
|
330
350
|
}
|
|
331
351
|
|
|
332
|
-
if (
|
|
333
|
-
|
|
352
|
+
if (tileCollisionTest(mousePos))
|
|
353
|
+
{
|
|
354
|
+
// show floored tile pick for tile collision
|
|
355
|
+
drawRect(mousePos.floor().add(vec2(.5)), vec2(1), rgb(1,1,0,.5));
|
|
356
|
+
}
|
|
334
357
|
mainContext = saveContext;
|
|
335
358
|
}
|
|
336
359
|
|
|
@@ -405,10 +428,10 @@ function debugRender()
|
|
|
405
428
|
mainContext = overlayContext;
|
|
406
429
|
const raycastHitPos = tileCollisionRaycast(debugObject.pos, mousePos);
|
|
407
430
|
raycastHitPos && drawRect(raycastHitPos.floor().add(vec2(.5)), vec2(1), rgb(0,1,1,.3));
|
|
408
|
-
drawLine(mousePos, debugObject.pos, .1, raycastHitPos ? rgb(1,0,0,.5) : rgb(0,1,0,.5)
|
|
431
|
+
drawLine(mousePos, debugObject.pos, .1, raycastHitPos ? rgb(1,0,0,.5) : rgb(0,1,0,.5));
|
|
409
432
|
|
|
410
433
|
const debugText = 'mouse pos = ' + mousePos +
|
|
411
|
-
'\nmouse collision = ' +
|
|
434
|
+
'\nmouse collision = ' + tileCollisionGetData(mousePos) +
|
|
412
435
|
'\n\n--- object info ---\n' +
|
|
413
436
|
debugObject.toString();
|
|
414
437
|
drawTextScreen(debugText, mousePosScreen, 24, rgb(), .05, undefined, 'center', 'monospace');
|
|
@@ -417,20 +440,24 @@ function debugRender()
|
|
|
417
440
|
|
|
418
441
|
{
|
|
419
442
|
// draw debug overlay
|
|
443
|
+
const fontSize = 20;
|
|
444
|
+
const lineHeight = fontSize * 1.2 | 0;
|
|
420
445
|
overlayContext.save();
|
|
421
446
|
overlayContext.fillStyle = '#fff';
|
|
422
447
|
overlayContext.textAlign = 'left';
|
|
423
448
|
overlayContext.textBaseline = 'top';
|
|
424
|
-
overlayContext.font = '
|
|
449
|
+
overlayContext.font = fontSize + 'px monospace';
|
|
425
450
|
overlayContext.shadowColor = '#000';
|
|
426
451
|
overlayContext.shadowBlur = 9;
|
|
427
452
|
|
|
428
|
-
let x = 9, y =
|
|
453
|
+
let x = 9, y = 0, h = lineHeight;
|
|
429
454
|
if (debugOverlay)
|
|
430
455
|
{
|
|
431
|
-
overlayContext.fillText(engineName, x, y += h);
|
|
432
|
-
overlayContext.fillText('Objects: ' + engineObjects.length, x, y += h);
|
|
456
|
+
overlayContext.fillText(engineName, x, y += h/2 );
|
|
433
457
|
overlayContext.fillText('Time: ' + formatTime(time), x, y += h);
|
|
458
|
+
overlayContext.fillText('FPS: ' + averageFPS.toFixed(1), x, y += h);
|
|
459
|
+
overlayContext.fillText('Objects: ' + engineObjects.length, x, y += h);
|
|
460
|
+
overlayContext.fillText('Draw Count: ' + drawCount, x, y += h);
|
|
434
461
|
overlayContext.fillText('---------', x, y += h);
|
|
435
462
|
overlayContext.fillStyle = '#f00';
|
|
436
463
|
overlayContext.fillText('ESC: Debug Overlay', x, y += h);
|
|
@@ -444,7 +471,7 @@ function debugRender()
|
|
|
444
471
|
overlayContext.fillText('4: Debug Raycasts', x, y += h);
|
|
445
472
|
overlayContext.fillStyle = '#fff';
|
|
446
473
|
overlayContext.fillText('5: Save Screenshot', x, y += h);
|
|
447
|
-
overlayContext.fillText('6:
|
|
474
|
+
overlayContext.fillText('6: Toggle Video Capture', x, y += h);
|
|
448
475
|
|
|
449
476
|
let keysPressed = '';
|
|
450
477
|
for(const i in inputData[0])
|