littlejsengine 1.17.11 → 1.17.15
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/AI.md +162 -0
- package/README.md +50 -63
- package/dist/littlejs.d.ts +150 -68
- package/dist/littlejs.esm.js +323 -105
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +320 -104
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +318 -101
- package/examples/electron/{build.js → build.mjs} +26 -23
- package/examples/electron/game.js +5 -50
- package/examples/electron/index.html +2 -2
- package/examples/index.html +1 -0
- package/examples/module/{build.js → build.mjs} +22 -19
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/hillGlideGame.js +1 -1
- package/examples/shorts/nineSlice.js +3 -3
- package/examples/shorts/shapes.js +1 -1
- package/examples/shorts/uiSystem.js +17 -16
- package/examples/starter/build.bat +1 -1
- package/examples/starter/{build.js → build.mjs} +25 -22
- package/examples/starter/index.html +2 -2
- package/examples/typescript/build.mjs +60 -0
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/tsconfig.json +11 -2
- package/package.json +2 -2
- package/plugins/pluginExport.js +1 -0
- package/plugins/uiSystem.js +143 -20
- package/reference.md +0 -1
- package/src/engine.js +16 -14
- package/src/engineAudio.js +9 -6
- package/src/{engineBuild.js → engineBuild.mjs} +95 -78
- package/src/engineDebug.js +8 -5
- package/src/engineDraw.js +16 -14
- package/src/engineExport.js +2 -1
- package/src/engineInput.js +29 -8
- package/src/engineMath.js +46 -14
- package/src/engineMedals.js +6 -3
- package/src/engineObject.js +14 -3
- package/src/engineParticles.js +8 -3
- package/src/engineRelease.js +6 -2
- package/src/engineTileLayer.js +8 -4
- package/src/engineUtilities.js +6 -2
- package/src/engineWebGL.js +11 -8
- package/src/jsconfig.json +2 -1
- package/examples/electron/build.bat +0 -7
- package/examples/module/build.bat +0 -7
- package/examples/typescript/build.bat +0 -5
- package/examples/typescript/build.js +0 -31
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
"allowJs": true,
|
|
4
4
|
"module": "es2020",
|
|
5
5
|
"target": "es2020",
|
|
6
|
-
"outDir": "build"
|
|
7
|
-
|
|
6
|
+
"outDir": "build",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"skipLibCheck": true
|
|
9
|
+
},
|
|
10
|
+
"include": [
|
|
11
|
+
"*.ts"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"node_modules",
|
|
15
|
+
"build"
|
|
16
|
+
]
|
|
8
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "littlejsengine",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.15",
|
|
4
4
|
"description": "LittleJS - Tiny and Fast HTML5 Game Engine",
|
|
5
5
|
"main": "dist/littlejs.esm.js",
|
|
6
6
|
"types": "dist/littlejs.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/KilledByAPixel/LittleJS",
|
|
32
32
|
"scripts": {
|
|
33
|
-
"build": "node src/engineBuild.
|
|
33
|
+
"build": "node src/engineBuild.mjs"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"bestzip": "^2.2.1",
|
package/plugins/pluginExport.js
CHANGED
package/plugins/uiSystem.js
CHANGED
|
@@ -118,9 +118,16 @@ class UISystemPlugin
|
|
|
118
118
|
this.lastHoverObject = undefined;
|
|
119
119
|
/** @property {UIObject} - Current confirm menu being shown */
|
|
120
120
|
this.confirmDialog = undefined;
|
|
121
|
+
/** @property {UIObject} - Object to send keyboard input to */
|
|
122
|
+
this.keyInputObject = undefined;
|
|
121
123
|
|
|
122
124
|
engineAddPlugin(uiUpdate, uiRender);
|
|
123
125
|
|
|
126
|
+
// key down handler
|
|
127
|
+
function onKeyDown(e)
|
|
128
|
+
{ uiSystem.keyInputObject?.onKeyDown(e); }
|
|
129
|
+
document.addEventListener('keydown', onKeyDown);
|
|
130
|
+
|
|
124
131
|
// set object position in parent space
|
|
125
132
|
function updateTransforms(o)
|
|
126
133
|
{
|
|
@@ -139,9 +146,18 @@ class UISystemPlugin
|
|
|
139
146
|
// reset hover object at start of update
|
|
140
147
|
uiSystem.lastHoverObject = uiSystem.hoverObject;
|
|
141
148
|
uiSystem.hoverObject = undefined;
|
|
142
|
-
|
|
149
|
+
|
|
143
150
|
if (mouseWasPressed(0))
|
|
144
151
|
{
|
|
152
|
+
// exit navigation mode on mouse press
|
|
153
|
+
uiSystem.navigationMode = false;
|
|
154
|
+
uiSystem.navigationObject = undefined;
|
|
155
|
+
}
|
|
156
|
+
if (uiSystem.keyInputObject)
|
|
157
|
+
{
|
|
158
|
+
// handle text input
|
|
159
|
+
uiSystem.activeObject = uiSystem.keyInputObject;
|
|
160
|
+
uiSystem.hoverObject = uiSystem.keyInputObject;
|
|
145
161
|
uiSystem.navigationMode = false;
|
|
146
162
|
uiSystem.navigationObject = undefined;
|
|
147
163
|
}
|
|
@@ -150,7 +166,7 @@ class UISystemPlugin
|
|
|
150
166
|
const navigableObjects = uiSystem.getNavigableObjects();
|
|
151
167
|
if (!navigableObjects.length)
|
|
152
168
|
uiSystem.navigationObject = undefined;
|
|
153
|
-
else
|
|
169
|
+
else if (!uiSystem.keyInputObject)
|
|
154
170
|
{
|
|
155
171
|
// unselect object if it is no longer navigable
|
|
156
172
|
if (!navigableObjects.includes(uiSystem.navigationObject))
|
|
@@ -463,6 +479,7 @@ class UISystemPlugin
|
|
|
463
479
|
this.activeObject = undefined;
|
|
464
480
|
this.hoverObject = undefined;
|
|
465
481
|
this.lastHoverObject = undefined;
|
|
482
|
+
this.keyInputObject = undefined;
|
|
466
483
|
}
|
|
467
484
|
|
|
468
485
|
/** Get all navigable UI objects sorted by navigationIndex
|
|
@@ -743,7 +760,7 @@ class UIObject
|
|
|
743
760
|
}
|
|
744
761
|
}
|
|
745
762
|
|
|
746
|
-
/** Check if the mouse is overlapping
|
|
763
|
+
/** Check if the mouse is overlapping this ui object
|
|
747
764
|
* @return {boolean} - True if overlapping */
|
|
748
765
|
isMouseOverlapping()
|
|
749
766
|
{
|
|
@@ -762,8 +779,16 @@ class UIObject
|
|
|
762
779
|
this.onUpdate();
|
|
763
780
|
|
|
764
781
|
// unset active if disabled
|
|
765
|
-
if (this.disabled
|
|
766
|
-
|
|
782
|
+
if (this.disabled)
|
|
783
|
+
{
|
|
784
|
+
if (this === uiSystem.activeObject)
|
|
785
|
+
uiSystem.activeObject = undefined;
|
|
786
|
+
if (this === uiSystem.keyInputObject)
|
|
787
|
+
uiSystem.keyInputObject = undefined;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (uiSystem.keyInputObject)
|
|
791
|
+
return;
|
|
767
792
|
|
|
768
793
|
const wasHover = uiSystem.lastHoverObject === this;
|
|
769
794
|
const isActive = this.isActiveObject();
|
|
@@ -790,19 +815,12 @@ class UIObject
|
|
|
790
815
|
uiSystem.activeObject = this;
|
|
791
816
|
|
|
792
817
|
if (uiSystem.activateOnPress)
|
|
793
|
-
|
|
794
|
-
this.onClick();
|
|
795
|
-
if (!this.soundPress && this.soundClick)
|
|
796
|
-
this.soundClick.play();
|
|
797
|
-
}
|
|
818
|
+
this.click(!this.soundPress);
|
|
798
819
|
}
|
|
799
820
|
}
|
|
800
821
|
if (!uiSystem.activateOnPress)
|
|
801
822
|
if (!mouseDown && this.isActiveObject() && this.interactive)
|
|
802
|
-
|
|
803
|
-
this.onClick();
|
|
804
|
-
this.soundClick && this.soundClick.play();
|
|
805
|
-
}
|
|
823
|
+
this.click();
|
|
806
824
|
}
|
|
807
825
|
|
|
808
826
|
// clear mouse was pressed state even when disabled
|
|
@@ -854,11 +872,7 @@ class UIObject
|
|
|
854
872
|
}
|
|
855
873
|
|
|
856
874
|
/** Called when the navigation button is pressed on this object */
|
|
857
|
-
navigatePressed()
|
|
858
|
-
{
|
|
859
|
-
this.onClick();
|
|
860
|
-
this.soundClick && this.soundClick.play();
|
|
861
|
-
}
|
|
875
|
+
navigatePressed() { this.click(); }
|
|
862
876
|
|
|
863
877
|
/** @return {boolean} - Is the mouse hovering over this element */
|
|
864
878
|
isHoverObject() { return uiSystem.hoverObject === this; }
|
|
@@ -869,6 +883,9 @@ class UIObject
|
|
|
869
883
|
/** @return {boolean} - Is the gamepad or keyboard navigation object */
|
|
870
884
|
isNavigationObject() { return uiSystem.navigationObject === this; }
|
|
871
885
|
|
|
886
|
+
/** @return {boolean} - Is this object in keyboard input mode */
|
|
887
|
+
isKeyInputObject() { return uiSystem.keyInputObject === this; }
|
|
888
|
+
|
|
872
889
|
/** @return {boolean} - Can it be interacted with */
|
|
873
890
|
isInteractive() { return this.interactive && this.visible && !this.disabled;}
|
|
874
891
|
|
|
@@ -905,6 +922,15 @@ class UIObject
|
|
|
905
922
|
uiSystem.drawRect(this.pos, this.size, CLEAR_BLACK, 4, color);
|
|
906
923
|
}
|
|
907
924
|
|
|
925
|
+
/** Internal function called when object is clicked
|
|
926
|
+
* @param {boolean} [playSound] */
|
|
927
|
+
click(playSound)
|
|
928
|
+
{
|
|
929
|
+
this.onClick();
|
|
930
|
+
if (playSound && this.soundClick)
|
|
931
|
+
this.soundClick.play();
|
|
932
|
+
}
|
|
933
|
+
|
|
908
934
|
/** Called each frame before object updates */
|
|
909
935
|
onUpdate() {}
|
|
910
936
|
|
|
@@ -980,6 +1006,102 @@ class UIText extends UIObject
|
|
|
980
1006
|
}
|
|
981
1007
|
}
|
|
982
1008
|
|
|
1009
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1010
|
+
/**
|
|
1011
|
+
* UITextInput - An editable text input field
|
|
1012
|
+
* - A simple text entry field that supports basic editing
|
|
1013
|
+
* - Suitable for short text input like names or numbers
|
|
1014
|
+
* @extends UIObject
|
|
1015
|
+
* @memberof UISystem
|
|
1016
|
+
*/
|
|
1017
|
+
class UITextInput extends UIObject
|
|
1018
|
+
{
|
|
1019
|
+
/** Create a UITextInput object
|
|
1020
|
+
* @param {Vector2} [pos]
|
|
1021
|
+
* @param {Vector2} [size]
|
|
1022
|
+
* @param {string} [text]
|
|
1023
|
+
*/
|
|
1024
|
+
constructor(pos, size, text='')
|
|
1025
|
+
{
|
|
1026
|
+
super(pos, size);
|
|
1027
|
+
|
|
1028
|
+
ASSERT(isString(text), 'ui text must be a string');
|
|
1029
|
+
|
|
1030
|
+
/** @property {number} - Max length of input (0 = no limit) */
|
|
1031
|
+
this.maxLength = 0;
|
|
1032
|
+
|
|
1033
|
+
// set properties
|
|
1034
|
+
this.text = text;
|
|
1035
|
+
this.interactive = true;
|
|
1036
|
+
this.canBeHover = true;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
click()
|
|
1040
|
+
{
|
|
1041
|
+
// start editing the text
|
|
1042
|
+
uiSystem.keyInputObject = this;
|
|
1043
|
+
this.onClick();
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/** Stop editing the text edited */
|
|
1047
|
+
stopEditing()
|
|
1048
|
+
{
|
|
1049
|
+
if (!this.isKeyInputObject())
|
|
1050
|
+
return;
|
|
1051
|
+
|
|
1052
|
+
if (this.soundRelease)
|
|
1053
|
+
this.soundRelease.play();
|
|
1054
|
+
uiSystem.activeObject = undefined;
|
|
1055
|
+
uiSystem.keyInputObject = undefined;
|
|
1056
|
+
this.onChange();
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/** Key down event handler if this object is being edited
|
|
1060
|
+
* @param {KeyboardEvent} [e] */
|
|
1061
|
+
onKeyDown(e)
|
|
1062
|
+
{
|
|
1063
|
+
const code = e.code, key = e.key
|
|
1064
|
+
if (code === 'Backspace')
|
|
1065
|
+
this.text = this.text.slice(0, -1);
|
|
1066
|
+
else if (code === 'Enter' || code === 'Escape')
|
|
1067
|
+
this.stopEditing();
|
|
1068
|
+
else if (key.length === 1) // printable characters
|
|
1069
|
+
{
|
|
1070
|
+
if (!this.maxLength || this.text.length < this.maxLength)
|
|
1071
|
+
this.text += key;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
update()
|
|
1076
|
+
{
|
|
1077
|
+
super.update();
|
|
1078
|
+
|
|
1079
|
+
if (!this.isKeyInputObject())
|
|
1080
|
+
return;
|
|
1081
|
+
|
|
1082
|
+
// click off object to stop editing
|
|
1083
|
+
if (mouseWasPressed(0) && !this.isMouseOverlapping() ||
|
|
1084
|
+
gamepadWasPressed(0, gamepadPrimary))
|
|
1085
|
+
{
|
|
1086
|
+
this.stopEditing();
|
|
1087
|
+
inputClearKey(0,0);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
render()
|
|
1092
|
+
{
|
|
1093
|
+
super.render();
|
|
1094
|
+
|
|
1095
|
+
// draw the text scaled to fit
|
|
1096
|
+
const textSize = this.getTextSize();
|
|
1097
|
+
let text = this.text;
|
|
1098
|
+
if (this.isKeyInputObject()) // add a cursor to end of text
|
|
1099
|
+
text += timeReal%1 < .5 ? '█' : '░';
|
|
1100
|
+
uiSystem.drawText(text, this.pos, textSize,
|
|
1101
|
+
this.textColor, this.textLineWidth, this.textLineColor, this.align, this.font, this.fontStyle, true, this.textShadow);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
983
1105
|
///////////////////////////////////////////////////////////////////////////////
|
|
984
1106
|
/**
|
|
985
1107
|
* UITile - A UI object that displays a tile image
|
|
@@ -1091,9 +1213,10 @@ class UICheckbox extends UIObject
|
|
|
1091
1213
|
this.color = color.copy();
|
|
1092
1214
|
this.interactive = true;
|
|
1093
1215
|
}
|
|
1094
|
-
|
|
1216
|
+
click()
|
|
1095
1217
|
{
|
|
1096
1218
|
this.checked = !this.checked;
|
|
1219
|
+
this.onClick();
|
|
1097
1220
|
this.onChange();
|
|
1098
1221
|
}
|
|
1099
1222
|
render()
|
package/reference.md
CHANGED
|
@@ -49,7 +49,6 @@ smoothStep(percent) // Applies smoothstep function
|
|
|
49
49
|
nearestPowerOfTwo(value) // Returns the nearest power of two
|
|
50
50
|
isOverlapping(pointA, sizeA, pointB, sizeB) // Checks if bounding boxes overlap
|
|
51
51
|
isIntersecting(start, end, pos, size) // Checks if ray intersects box
|
|
52
|
-
wave(frequency=1, amplitude=1, t=time) // Returns oscillating wave
|
|
53
52
|
formatTime(t) // Formats seconds for display
|
|
54
53
|
|
|
55
54
|
// Random functions
|
package/src/engine.js
CHANGED
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
* MIT License - Copyright 2021 Frank Force
|
|
4
4
|
*
|
|
5
5
|
* Engine Features
|
|
6
|
-
* - Object oriented system with base class
|
|
7
|
-
* -
|
|
8
|
-
* - Engine helper classes
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - Input
|
|
12
|
-
* - Tile layer rendering and collision
|
|
13
|
-
* - Particle effect system
|
|
14
|
-
* - Medal system
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
6
|
+
* - Object oriented system with EngineObject base class
|
|
7
|
+
* - Automatic object lifecycle (update, physics, collision, rendering)
|
|
8
|
+
* - Engine helper classes: Vector2, Color, Timer, RandomGenerator
|
|
9
|
+
* - Hybrid rendering with WebGL batching and Canvas2D fallback
|
|
10
|
+
* - Audio system with wave, mp3, or ZzFX sound effects
|
|
11
|
+
* - Input system with keyboard, mouse, gamepad, and touch support
|
|
12
|
+
* - Tile layer rendering and collision detection
|
|
13
|
+
* - Particle effect system with emitters
|
|
14
|
+
* - Medal/achievement system with local storage
|
|
15
|
+
* - Comprehensive debug tools and visualizations
|
|
16
|
+
* - Fixed 60 FPS timestep with configurable time scale
|
|
17
|
+
* - Raycast and spatial query utilities
|
|
18
|
+
* - Plugin system for extending engine functionality
|
|
19
|
+
* - Start with engineInit() and provide your game callbacks
|
|
18
20
|
* @namespace Engine
|
|
19
21
|
*/
|
|
20
22
|
|
|
@@ -30,7 +32,7 @@ const engineName = 'LittleJS';
|
|
|
30
32
|
* @type {string}
|
|
31
33
|
* @default
|
|
32
34
|
* @memberof Engine */
|
|
33
|
-
const engineVersion = '1.17.
|
|
35
|
+
const engineVersion = '1.17.15';
|
|
34
36
|
|
|
35
37
|
/** Frames per second to update
|
|
36
38
|
* @type {number}
|
|
@@ -604,7 +606,7 @@ function drawEngineLogo(t)
|
|
|
604
606
|
const color = (c,l)=> l?`hsl(${[.95,.56,.13][c%3]*360} 99%${[0,50,75][l]}%`:'#000';
|
|
605
607
|
|
|
606
608
|
// center and fit tos screen
|
|
607
|
-
const alpha =
|
|
609
|
+
const alpha = oscillate(1,1,t);
|
|
608
610
|
const p = percent(alpha, .1, .5);
|
|
609
611
|
const size = min(6, min(w,h)/99);
|
|
610
612
|
x.translate(w/2,h/2);
|
package/src/engineAudio.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LittleJS Audio System
|
|
3
|
-
* -
|
|
4
|
-
* - <a href=https://
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
3
|
+
* - Play audio files (mp3, ogg, wave) and generate sounds with ZzFX
|
|
4
|
+
* - ZzFX sound generator integration: <a href=https://killedbyapixel.github.io/ZzFX/>ZzFX</a>
|
|
5
|
+
* - Sound caching for fast playback and memory efficiency
|
|
6
|
+
* - Volume control with attenuation and stereo panning
|
|
7
|
+
* - 2D spatial audio based on camera position with distance-based falloff
|
|
8
|
+
* - Sound instance management (pause, resume, stop)
|
|
9
|
+
* - Speech synthesis for text-to-speech
|
|
10
|
+
* - Music playback with ZzFXM support
|
|
11
|
+
* - Web Audio API integration with master gain control
|
|
9
12
|
* @namespace Audio
|
|
10
13
|
*/
|
|
11
14
|
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* LittleJS Build System
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
3
|
+
* - Concatenates engine source files into distributable bundles
|
|
4
|
+
* - Generates multiple output formats (standard, ES6 module, minified)
|
|
5
|
+
* - Creates debug and release builds (with/without debug code)
|
|
6
|
+
* - Produces TypeScript definition file (.d.ts)
|
|
7
|
+
* - Includes plugin files in builds
|
|
8
|
+
* - Validates code and checks for errors
|
|
9
|
+
* - Outputs to dist/ folder
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import { execSync } from 'node:child_process';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { dirname, join } from 'node:path';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
const ROOT_DIR = join(__dirname, '..');
|
|
12
20
|
|
|
13
21
|
const ENGINE_NAME = 'littlejs';
|
|
14
|
-
const BUILD_FOLDER = 'dist';
|
|
15
|
-
const SOURCE_FOLDER = 'src';
|
|
16
|
-
const PLUGIN_FOLDER = 'plugins';
|
|
22
|
+
const BUILD_FOLDER = join(ROOT_DIR, 'dist');
|
|
23
|
+
const SOURCE_FOLDER = join(ROOT_DIR, 'src');
|
|
24
|
+
const PLUGIN_FOLDER = join(ROOT_DIR, 'plugins');
|
|
17
25
|
const engineSourceFiles =
|
|
18
26
|
[
|
|
19
27
|
`${SOURCE_FOLDER}/engineMath.js`,
|
|
@@ -53,10 +61,8 @@ const license = '// LittleJS Engine - MIT License - Copyright 2021 Frank Force\n
|
|
|
53
61
|
'// https://github.com/KilledByAPixel/LittleJS\n\n';
|
|
54
62
|
|
|
55
63
|
console.log(asciiArt);
|
|
56
|
-
console.log('Choo Choo... Building LittleJS Engine
|
|
64
|
+
console.log('🚂 Choo Choo... Building LittleJS Engine!');
|
|
57
65
|
const startTime = Date.now();
|
|
58
|
-
const fs = require('node:fs');
|
|
59
|
-
const child_process = require('node:child_process');
|
|
60
66
|
|
|
61
67
|
try
|
|
62
68
|
{
|
|
@@ -71,71 +77,82 @@ try
|
|
|
71
77
|
}
|
|
72
78
|
catch (e) { handleError(e, 'Failed to create build folder!'); }
|
|
73
79
|
|
|
74
|
-
Build
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
[
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Build
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
[
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
Build
|
|
121
|
-
(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
|
|
80
|
+
// Build all versions
|
|
81
|
+
await buildAll();
|
|
82
|
+
|
|
83
|
+
console.log(`Engine built in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds! ✨`);
|
|
84
|
+
|
|
85
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
86
|
+
|
|
87
|
+
async function buildAll()
|
|
88
|
+
{
|
|
89
|
+
// Build independent base versions in parallel
|
|
90
|
+
await Promise.all([
|
|
91
|
+
Build
|
|
92
|
+
(
|
|
93
|
+
'Build Engine -- all',
|
|
94
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.js`,
|
|
95
|
+
[
|
|
96
|
+
`${SOURCE_FOLDER}/engine.js`,
|
|
97
|
+
`${SOURCE_FOLDER}/engineDebug.js`,
|
|
98
|
+
...engineSourceFiles,
|
|
99
|
+
...enginePluginFiles
|
|
100
|
+
],
|
|
101
|
+
[], true
|
|
102
|
+
),
|
|
103
|
+
Build
|
|
104
|
+
(
|
|
105
|
+
'Build Engine -- release',
|
|
106
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.release.js`,
|
|
107
|
+
[
|
|
108
|
+
`${SOURCE_FOLDER}/engine.js`,
|
|
109
|
+
`${SOURCE_FOLDER}/engineRelease.js`,
|
|
110
|
+
...engineSourceFiles,
|
|
111
|
+
...enginePluginFiles
|
|
112
|
+
],
|
|
113
|
+
[], true
|
|
114
|
+
)
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
// Build dependent versions in parallel
|
|
118
|
+
await Promise.all([
|
|
119
|
+
Build
|
|
120
|
+
(
|
|
121
|
+
'Build Engine -- minified',
|
|
122
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.min.js`,
|
|
123
|
+
[`${BUILD_FOLDER}/${ENGINE_NAME}.release.js`],
|
|
124
|
+
[closureCompilerStep, uglifyBuildStep, addLicenseStep]
|
|
125
|
+
),
|
|
126
|
+
Build
|
|
127
|
+
(
|
|
128
|
+
'Build Engine -- ESM',
|
|
129
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.esm.js`,
|
|
130
|
+
[
|
|
131
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.js`,
|
|
132
|
+
`${SOURCE_FOLDER}/engineExport.js`,
|
|
133
|
+
`${PLUGIN_FOLDER}/pluginExport.js`
|
|
134
|
+
],
|
|
135
|
+
[typeScriptBuildStep]
|
|
136
|
+
),
|
|
137
|
+
Build
|
|
138
|
+
(
|
|
139
|
+
'Build Engine -- ESM minified release',
|
|
140
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.esm.min.js`,
|
|
141
|
+
[
|
|
142
|
+
`${BUILD_FOLDER}/${ENGINE_NAME}.release.js`,
|
|
143
|
+
`${SOURCE_FOLDER}/engineExport.js`,
|
|
144
|
+
`${PLUGIN_FOLDER}/pluginExport.js`
|
|
145
|
+
],
|
|
146
|
+
[uglifyBuildStep, addLicenseStep]
|
|
147
|
+
)
|
|
148
|
+
]);
|
|
149
|
+
}
|
|
133
150
|
|
|
134
151
|
///////////////////////////////////////////////////////////////////////////////
|
|
135
152
|
|
|
136
153
|
// A single build with its own source files, build steps, and output file
|
|
137
154
|
// - each build step is a callback that accepts a single filename
|
|
138
|
-
function Build(message, outputFile, files=[], buildSteps=[], isPrimaryBuild)
|
|
155
|
+
async function Build(message, outputFile, files=[], buildSteps=[], isPrimaryBuild)
|
|
139
156
|
{
|
|
140
157
|
console.log(message);
|
|
141
158
|
|
|
@@ -176,18 +193,18 @@ function closureCompilerStep(filename)
|
|
|
176
193
|
fs.copyFileSync(filename, filenameTemp);
|
|
177
194
|
try
|
|
178
195
|
{
|
|
179
|
-
|
|
196
|
+
execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --warning_level=VERBOSE --jscomp_off=*`);
|
|
180
197
|
fs.rmSync(filenameTemp);
|
|
181
198
|
}
|
|
182
199
|
catch (e) { handleError(e, 'Failed to run Closure Compiler step!'); }
|
|
183
|
-
}
|
|
200
|
+
}
|
|
184
201
|
|
|
185
202
|
// Process with Uglify to minify
|
|
186
203
|
function uglifyBuildStep(filename)
|
|
187
204
|
{
|
|
188
205
|
try
|
|
189
206
|
{
|
|
190
|
-
|
|
207
|
+
execSync(`npx uglifyjs ${filename} -o ${filename}`);
|
|
191
208
|
}
|
|
192
209
|
catch (e) { handleError(e,'Failed to run Uglify minification step!'); }
|
|
193
210
|
};
|
|
@@ -210,8 +227,8 @@ function typeScriptBuildStep(filename)
|
|
|
210
227
|
{
|
|
211
228
|
try
|
|
212
229
|
{
|
|
213
|
-
const tsFilename = `${
|
|
214
|
-
|
|
230
|
+
const tsFilename = join(BUILD_FOLDER, `${ENGINE_NAME}.d.ts`);
|
|
231
|
+
execSync(`npx -p typescript tsc ${filename} --declaration --allowJs --emitDeclarationOnly --outFile ${tsFilename}`);
|
|
215
232
|
|
|
216
233
|
// Make declare module part use the package name littlejsengine
|
|
217
234
|
let fileContent = fs.readFileSync(tsFilename, 'utf8');
|
package/src/engineDebug.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LittleJS Debug System
|
|
3
|
-
* - Press Esc to
|
|
4
|
-
* - Number keys toggle debug
|
|
5
|
-
* - +/-
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
3
|
+
* - Press Esc to toggle debug overlay with object picking
|
|
4
|
+
* - Number keys toggle debug visualizations (physics, particles, etc.)
|
|
5
|
+
* - +/- keys control time scale for slow motion/fast forward
|
|
6
|
+
* - ASSERT and LOG macros for development (removed in release builds)
|
|
7
|
+
* - Debug primitive rendering (rectangles, circles, lines, points, text)
|
|
8
|
+
* - Screenshot and video capture support
|
|
9
|
+
* - FPS counter and performance watermark
|
|
10
|
+
* - Debug overlay shows mouse position and picked objects
|
|
8
11
|
* @namespace Debug
|
|
9
12
|
*/
|
|
10
13
|
|