littlejsengine 1.6.4 → 1.6.92

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 (61) hide show
  1. package/README.md +61 -41
  2. package/build/littlejs.d.ts +160 -165
  3. package/build/littlejs.esm.js +451 -367
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +408 -314
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +2573 -2470
  8. package/examples/breakout/game.js +5 -1
  9. package/examples/breakout/index.html +5 -5
  10. package/examples/breakoutTutorial/README.md +6 -6
  11. package/examples/breakoutTutorial/game.js +3 -0
  12. package/examples/breakoutTutorial/index.html +3 -3
  13. package/examples/electron/build.js +105 -0
  14. package/examples/electron/game.js +4 -2
  15. package/examples/electron/index.html +13 -2
  16. package/examples/electron/package.json +5 -3
  17. package/examples/empty/game.js +3 -1
  18. package/examples/empty/index.html +1 -1
  19. package/examples/favicon.png +0 -0
  20. package/examples/js13k/build.bat +2 -0
  21. package/examples/js13k/build.js +110 -0
  22. package/examples/js13k/game.js +109 -0
  23. package/examples/js13k/index.html +18 -0
  24. package/examples/js13k/tiles.png +0 -0
  25. package/examples/module/game.js +9 -3
  26. package/examples/module/index.html +2 -2
  27. package/examples/particles/index.html +7 -13
  28. package/examples/platformer/game.js +5 -2
  29. package/examples/platformer/gameEffects.js +1 -2
  30. package/examples/platformer/gamePlayer.js +2 -2
  31. package/examples/platformer/index.html +8 -8
  32. package/examples/puzzle/game.js +6 -4
  33. package/examples/puzzle/index.html +4 -4
  34. package/examples/starter/build.bat +2 -78
  35. package/examples/starter/build.js +109 -0
  36. package/examples/starter/game.js +4 -1
  37. package/examples/starter/index.html +15 -18
  38. package/examples/stress/index.html +2 -4
  39. package/examples/typescript/build.bat +2 -14
  40. package/examples/typescript/build.js +31 -0
  41. package/examples/typescript/game.js +94 -89
  42. package/examples/typescript/game.ts +9 -3
  43. package/examples/typescript/index.html +2 -2
  44. package/package.json +3 -3
  45. package/src/engine.js +30 -31
  46. package/src/engineAudio.js +44 -20
  47. package/src/engineBuild.bat +2 -132
  48. package/src/engineBuild.js +143 -0
  49. package/src/engineDebug.js +21 -32
  50. package/src/engineDraw.js +36 -28
  51. package/src/engineExport.js +41 -51
  52. package/src/engineInput.js +33 -20
  53. package/src/engineMedals.js +31 -8
  54. package/src/engineObject.js +34 -32
  55. package/src/engineParticles.js +9 -12
  56. package/src/engineRelease.js +18 -20
  57. package/src/engineSettings.js +4 -4
  58. package/src/engineTileLayer.js +49 -32
  59. package/src/engineUtilities.js +96 -74
  60. package/src/engineWebGL.js +8 -8
  61. package/examples/electron/build.bat +0 -52
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * LittleJS Input System
3
- * <br> - Tracks key down, pressed, and released
4
- * <br> - Also tracks mouse buttons, position, and wheel
5
- * <br> - Supports multiple gamepads
6
- * <br> - Virtual gamepad for touch devices with touchGamepadSize
3
+ * - Tracks key down, pressed, and released
4
+ * - Also tracks mouse buttons, position, and wheel
5
+ * - Supports multiple gamepads
6
+ * - Virtual gamepad for touch devices with touchGamepadSize
7
7
  * @namespace Input
8
8
  */
9
9
 
@@ -14,25 +14,28 @@
14
14
  * @param {Number} [device=0]
15
15
  * @return {Boolean}
16
16
  * @memberof Input */
17
- const keyIsDown = (key, device=0)=> inputData[device] && inputData[device][key] & 1;
17
+ function keyIsDown(key, device=0)
18
+ { return inputData[device] && inputData[device][key] & 1; }
18
19
 
19
20
  /** Returns true if device key was pressed this frame
20
21
  * @param {Number} key
21
22
  * @param {Number} [device=0]
22
23
  * @return {Boolean}
23
24
  * @memberof Input */
24
- const keyWasPressed = (key, device=0)=> inputData[device] && inputData[device][key] & 2 ? 1 : 0;
25
+ function keyWasPressed(key, device=0)
26
+ { return inputData[device] && inputData[device][key] & 2 ? 1 : 0; }
25
27
 
26
28
  /** Returns true if device key was released this frame
27
29
  * @param {Number} key
28
30
  * @param {Number} [device=0]
29
31
  * @return {Boolean}
30
32
  * @memberof Input */
31
- const keyWasReleased = (key, device=0)=> inputData[device] && inputData[device][key] & 4 ? 1 : 0;
33
+ function keyWasReleased(key, device=0)
34
+ { return inputData[device] && inputData[device][key] & 4 ? 1 : 0; }
32
35
 
33
36
  /** Clears all input
34
37
  * @memberof Input */
35
- const clearInput = ()=> inputData = [[]];
38
+ function clearInput() { inputData = [[]]; }
36
39
 
37
40
  /** Returns true if mouse button is down
38
41
  * @function
@@ -85,28 +88,32 @@ let preventDefaultInput = 0;
85
88
  * @param {Number} [gamepad=0]
86
89
  * @return {Boolean}
87
90
  * @memberof Input */
88
- const gamepadIsDown = (button, gamepad=0)=> keyIsDown(button, gamepad+1);
91
+ function gamepadIsDown(button, gamepad=0)
92
+ { return keyIsDown(button, gamepad+1); }
89
93
 
90
94
  /** Returns true if gamepad button was pressed
91
95
  * @param {Number} button
92
96
  * @param {Number} [gamepad=0]
93
97
  * @return {Boolean}
94
98
  * @memberof Input */
95
- const gamepadWasPressed = (button, gamepad=0)=> keyWasPressed(button, gamepad+1);
99
+ function gamepadWasPressed(button, gamepad=0)
100
+ { return keyWasPressed(button, gamepad+1); }
96
101
 
97
102
  /** Returns true if gamepad button was released
98
103
  * @param {Number} button
99
104
  * @param {Number} [gamepad=0]
100
105
  * @return {Boolean}
101
106
  * @memberof Input */
102
- const gamepadWasReleased = (button, gamepad=0)=> keyWasReleased(button, gamepad+1);
107
+ function gamepadWasReleased(button, gamepad=0)
108
+ { return keyWasReleased(button, gamepad+1); }
103
109
 
104
110
  /** Returns gamepad stick value
105
111
  * @param {Number} stick
106
112
  * @param {Number} [gamepad=0]
107
113
  * @return {Vector2}
108
114
  * @memberof Input */
109
- const gamepadStick = (stick, gamepad=0)=> stickData[gamepad] ? stickData[gamepad][stick] || vec2() : vec2();
115
+ function gamepadStick(stick, gamepad=0)
116
+ { return stickData[gamepad] ? stickData[gamepad][stick] || vec2() : vec2(); }
110
117
 
111
118
  ///////////////////////////////////////////////////////////////////////////////
112
119
  // Input update called by engine
@@ -145,12 +152,18 @@ onkeydown = (e)=>
145
152
  e.repeat || (inputData[isUsingGamepad = 0][remapKey(e.which)] = 3);
146
153
  preventDefaultInput && e.preventDefault();
147
154
  }
155
+
148
156
  onkeyup = (e)=>
149
157
  {
150
158
  if (debug && e.target != document.body) return;
151
159
  inputData[0][remapKey(e.which)] = 4;
152
160
  }
153
- const remapKey = (c)=> inputWASDEmulateDirection ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
161
+
162
+ function remapKey(c)
163
+ {
164
+ return inputWASDEmulateDirection ?
165
+ c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
166
+ }
154
167
 
155
168
  ///////////////////////////////////////////////////////////////////////////////
156
169
  // Mouse event handlers
@@ -159,10 +172,10 @@ onmousedown = (e)=> {inputData[isUsingGamepad = 0][e.button] = 3; onmousemove(e)
159
172
  onmouseup = (e)=> inputData[0][e.button] = inputData[0][e.button] & 2 | 4;
160
173
  onmousemove = (e)=> mousePosScreen = mouseToScreen(e);
161
174
  onwheel = (e)=> e.ctrlKey || (mouseWheel = sign(e.deltaY));
162
- oncontextmenu = (e)=> !1; // prevent right click menu
175
+ oncontextmenu = (e)=> false; // prevent right click menu
163
176
 
164
177
  // convert a mouse or touch event position to screen space
165
- const mouseToScreen = (mousePos)=>
178
+ function mouseToScreen(mousePos)
166
179
  {
167
180
  if (!mainCanvas)
168
181
  return vec2(); // fix bug that can occur if user clicks before page loads
@@ -208,8 +221,7 @@ function gamepadsUpdate()
208
221
  if (gamepad)
209
222
  {
210
223
  // read clamp dead zone of analog sticks
211
- const deadZone = .3, deadZoneMax = .8;
212
- const applyDeadZone = (v)=>
224
+ const deadZone = .3, deadZoneMax = .8, applyDeadZone = (v)=>
213
225
  v > deadZone ? percent( v, deadZone, deadZoneMax) :
214
226
  v < -deadZone ? -percent(-v, deadZone, deadZoneMax) : 0;
215
227
 
@@ -242,11 +254,12 @@ function gamepadsUpdate()
242
254
  /** Pulse the vibration hardware if it exists
243
255
  * @param {Number} [pattern=100] - a single value in miliseconds or vibration interval array
244
256
  * @memberof Input */
245
- const vibrate = (pattern)=> vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern);
257
+ function vibrate(pattern)
258
+ { vibrateEnable && navigator && navigator.vibrate && navigator.vibrate(pattern); }
246
259
 
247
260
  /** Cancel any ongoing vibration
248
261
  * @memberof Input */
249
- const vibrateStop = ()=> vibrate(0);
262
+ function vibrateStop() { vibrate(0); }
250
263
 
251
264
  ///////////////////////////////////////////////////////////////////////////////
252
265
  // Touch input
@@ -418,7 +431,7 @@ function touchGamepadRender()
418
431
  const rightCenter = vec2(mainCanvasSize.x-touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
419
432
  for (let i=4; i--;)
420
433
  {
421
- const pos = rightCenter.add((new Vector2).setAngle(i*PI/2, touchGamepadSize/2));
434
+ const pos = rightCenter.add(vec2().setAngle(i*PI/2, touchGamepadSize/2));
422
435
  overlayContext.fillStyle = touchGamepadButtons[i] ? '#fff' : '#000';
423
436
  overlayContext.beginPath();
424
437
  overlayContext.arc(pos.x, pos.y, touchGamepadSize/4, 0,9);
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * LittleJS Medal System
3
- * <br> - Tracks and displays medals
4
- * <br> - Saves medals to local storage
5
- * <br> - Newgrounds integration
3
+ * - Tracks and displays medals
4
+ * - Saves medals to local storage
5
+ * - Newgrounds integration
6
6
  * @namespace Medals
7
7
  */
8
8
 
@@ -19,8 +19,8 @@ let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
19
19
  ///////////////////////////////////////////////////////////////////////////////
20
20
 
21
21
  /** Initialize medals with a save name used for storage
22
- * <br> - Call this after creating all medals
23
- * <br> - Checks if medals are unlocked
22
+ * - Call this after creating all medals
23
+ * - Checks if medals are unlocked
24
24
  * @param {String} saveName
25
25
  * @memberof Medals */
26
26
  function medalsInit(saveName)
@@ -290,9 +290,32 @@ class Newgrounds
290
290
  CryptoJS()
291
291
  {
292
292
  ///////////////////////////////////////////////////////////////////////////////
293
- // Crypto-JS - https://github.com/brix/crypto-js [The MIT License (MIT)]
294
- // Copyright (c) 2009-2013 Jeff Mott Copyright (c) 2013-2016 Evan Vosberg
295
-
293
+ // Crypto-JS - https://github.com/brix/crypto-js - MIT License
294
+ //
295
+ // [The MIT License (MIT)](http://opensource.org/licenses/MIT)
296
+ //
297
+ // Copyright (c) 2009-2013 Jeff Mott
298
+ // Copyright (c) 2013-2016 Evan Vosberg
299
+ //
300
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
301
+ // of this software and associated documentation files (the "Software"), to deal
302
+ // in the Software without restriction, including without limitation the rights
303
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
304
+ // copies of the Software, and to permit persons to whom the Software is
305
+ // furnished to do so, subject to the following conditions:
306
+ //
307
+ // The above copyright notice and this permission notice shall be included in
308
+ // all copies or substantial portions of the Software.
309
+ //
310
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
311
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
312
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
313
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
314
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
315
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
316
+ // THE SOFTWARE.
296
317
  return eval(Function("[M='GBMGXz^oVYPPKKbB`agTXU|LxPc_ZBcMrZvCr~wyGfWrwk@ATqlqeTp^N?p{we}jIpEnB_sEr`l?YDkDhWhprc|Er|XETG?pTl`e}dIc[_N~}fzRycIfpW{HTolvoPB_FMe_eH~BTMx]yyOhv?biWPCGc]kABencBhgERHGf{OL`Dj`c^sh@canhy[secghiyotcdOWgO{tJIE^JtdGQRNSCrwKYciZOa]Y@tcRATYKzv|sXpboHcbCBf`}SKeXPFM|RiJsSNaIb]QPc[D]Jy_O^XkOVTZep`ONmntLL`Qz~UupHBX_Ia~WX]yTRJIxG`ioZ{fefLJFhdyYoyLPvqgH?b`[TMnTwwfzDXhfM?rKs^aFr|nyBdPmVHTtAjXoYUloEziWDCw_suyYT~lSMksI~ZNCS[Bex~j]Vz?kx`gdYSEMCsHpjbyxQvw|XxX_^nQYue{sBzVWQKYndtYQMWRef{bOHSfQhiNdtR{o?cUAHQAABThwHPT}F{VvFmgN`E@FiFYS`UJmpQNM`X|tPKHlccT}z}k{sACHL?Rt@MkWplxO`ASgh?hBsuuP|xD~LSH~KBlRs]t|l|_tQAroDRqWS^SEr[sYdPB}TAROtW{mIkE|dWOuLgLmJrucGLpebrAFKWjikTUzS|j}M}szasKOmrjy[?hpwnEfX[jGpLt@^v_eNwSQHNwtOtDgWD{rk|UgASs@mziIXrsHN_|hZuxXlPJOsA^^?QY^yGoCBx{ekLuZzRqQZdsNSx@ezDAn{XNj@fRXIwrDX?{ZQHwTEfu@GhxDOykqts|n{jOeZ@c`dvTY?e^]ATvWpb?SVyg]GC?SlzteilZJAL]mlhLjYZazY__qcVFYvt@|bIQnSno@OXyt]OulzkWqH`rYFWrwGs`v|~XeTsIssLrbmHZCYHiJrX}eEzSssH}]l]IhPQhPoQ}rCXLyhFIT[clhzYOvyHqigxmjz`phKUU^TPf[GRAIhNqSOdayFP@FmKmuIzMOeoqdpxyCOwCthcLq?n`L`tLIBboNn~uXeFcPE{C~mC`h]jUUUQe^`UqvzCutYCgct|SBrAeiYQW?X~KzCz}guXbsUw?pLsg@hDArw?KeJD[BN?GD@wgFWCiHq@Ypp_QKFixEKWqRp]oJFuVIEvjDcTFu~Zz]a{IcXhWuIdMQjJ]lwmGQ|]g~c]Hl]pl`Pd^?loIcsoNir_kikBYyg?NarXZEGYspt_vLBIoj}LI[uBFvm}tbqvC|xyR~a{kob|HlctZslTGtPDhBKsNsoZPuH`U`Fqg{gKnGSHVLJ^O`zmNgMn~{rsQuoymw^JY?iUBvw_~mMr|GrPHTERS[MiNpY[Mm{ggHpzRaJaoFomtdaQ_?xuTRm}@KjU~RtPsAdxa|uHmy}n^i||FVL[eQAPrWfLm^ndczgF~Nk~aplQvTUpHvnTya]kOenZlLAQIm{lPl@CCTchvCF[fI{^zPkeYZTiamoEcKmBMfZhk_j_~Fjp|wPVZlkh_nHu]@tP|hS@^G^PdsQ~f[RqgTDqezxNFcaO}HZhb|MMiNSYSAnQWCDJukT~e|OTgc}sf[cnr?fyzTa|EwEtRG|I~|IO}O]S|rp]CQ}}DWhSjC_|z|oY|FYl@WkCOoPuWuqr{fJu?Brs^_EBI[@_OCKs}?]O`jnDiXBvaIWhhMAQDNb{U`bqVR}oqVAvR@AZHEBY@depD]OLh`kf^UsHhzKT}CS}HQKy}Q~AeMydXPQztWSSzDnghULQgMAmbWIZ|lWWeEXrE^EeNoZApooEmrXe{NAnoDf`m}UNlRdqQ@jOc~HLOMWs]IDqJHYoMziEedGBPOxOb?[X`KxkFRg@`mgFYnP{hSaxwZfBQqTm}_?RSEaQga]w[vxc]hMne}VfSlqUeMo_iqmd`ilnJXnhdj^EEFifvZyxYFRf^VaqBhLyrGlk~qowqzHOBlOwtx?i{m~`n^G?Yxzxux}b{LSlx]dS~thO^lYE}bzKmUEzwW^{rPGhbEov[Plv??xtyKJshbG`KuO?hjBdS@Ru}iGpvFXJRrvOlrKN?`I_n_tplk}kgwSXuKylXbRQ]]?a|{xiT[li?k]CJpwy^o@ebyGQrPfF`aszGKp]baIx~H?ElETtFh]dz[OjGl@C?]VDhr}OE@V]wLTc[WErXacM{We`F|utKKjgllAxvsVYBZ@HcuMgLboFHVZmi}eIXAIFhS@A@FGRbjeoJWZ_NKd^oEH`qgy`q[Tq{x?LRP|GfBFFJV|fgZs`MLbpPYUdIV^]mD@FG]pYAT^A^RNCcXVrPsgk{jTrAIQPs_`mD}rOqAZA[}RETFz]WkXFTz_m{N@{W@_fPKZLT`@aIqf|L^Mb|crNqZ{BVsijzpGPEKQQZGlApDn`ruH}cvF|iXcNqK}cxe_U~HRnKV}sCYb`D~oGvwG[Ca|UaybXea~DdD~LiIbGRxJ_VGheI{ika}KC[OZJLn^IBkPrQj_EuoFwZ}DpoBRcK]Q}?EmTv~i_Tul{bky?Iit~tgS|o}JL_VYcCQdjeJ_MfaA`FgCgc[Ii|CBHwq~nbJeYTK{e`CNstKfTKPzw{jdhp|qsZyP_FcugxCFNpKitlR~vUrx^NrSVsSTaEgnxZTmKc`R|lGJeX}ccKLsQZQhsFkeFd|ckHIVTlGMg`~uPwuHRJS_CPuN_ogXe{Ba}dO_UBhuNXby|h?JlgBIqMKx^_u{molgL[W_iavNQuOq?ap]PGB`clAicnl@k~pA?MWHEZ{HuTLsCpOxxrKlBh]FyMjLdFl|nMIvTHyGAlPogqfZ?PlvlFJvYnDQd}R@uAhtJmDfe|iJqdkYr}r@mEjjIetDl_I`TELfoR|qTBu@Tic[BaXjP?dCS~MUK[HPRI}OUOwAaf|_}HZzrwXvbnNgltjTwkBE~MztTQhtRSWoQHajMoVyBBA`kdgK~h`o[J`dm~pm]tk@i`[F~F]DBlJKklrkR]SNw@{aG~Vhl`KINsQkOy?WhcqUMTGDOM_]bUjVd|Yh_KUCCgIJ|LDIGZCPls{RzbVWVLEhHvWBzKq|^N?DyJB|__aCUjoEgsARki}j@DQXS`RNU|DJ^a~d{sh_Iu{ONcUtSrGWW@cvUjefHHi}eSSGrNtO?cTPBShLqzwMVjWQQCCFB^culBjZHEK_{dO~Q`YhJYFn]jq~XSnG@[lQr]eKrjXpG~L^h~tDgEma^AUFThlaR{xyuP@[^VFwXSeUbVetufa@dX]CLyAnDV@Bs[DnpeghJw^?UIana}r_CKGDySoRudklbgio}kIDpA@McDoPK?iYcG?_zOmnWfJp}a[JLR[stXMo?_^Ng[whQlrDbrawZeSZ~SJstIObdDSfAA{MV}?gNunLOnbMv_~KFQUAjIMj^GkoGxuYtYbGDImEYiwEMyTpMxN_LSnSMdl{bg@dtAnAMvhDTBR_FxoQgANniRqxd`pWv@rFJ|mWNWmh[GMJz_Nq`BIN@KsjMPASXORcdHjf~rJfgZYe_uulzqM_KdPlMsuvU^YJuLtofPhGonVOQxCMuXliNvJIaoC?hSxcxKVVxWlNs^ENDvCtSmO~WxI[itnjs^RDvI@KqG}YekaSbTaB]ki]XM@[ZnDAP~@|BzLRgOzmjmPkRE@_sobkT|SszXK[rZN?F]Z_u}Yue^[BZgLtR}FHzWyxWEX^wXC]MJmiVbQuBzkgRcKGUhOvUc_bga|Tx`KEM`JWEgTpFYVeXLCm|mctZR@uKTDeUONPozBeIkrY`cz]]~WPGMUf`MNUGHDbxZuO{gmsKYkAGRPqjc|_FtblEOwy}dnwCHo]PJhN~JoteaJ?dmYZeB^Xd?X^pOKDbOMF@Ugg^hETLdhwlA}PL@_ur|o{VZosP?ntJ_kG][g{Zq`Tu]dzQlSWiKfnxDnk}KOzp~tdFstMobmy[oPYjyOtUzMWdjcNSUAjRuqhLS@AwB^{BFnqjCmmlk?jpn}TksS{KcKkDboXiwK]qMVjm~V`LgWhjS^nLGwfhAYrjDSBL_{cRus~{?xar_xqPlArrYFd?pHKdMEZzzjJpfC?Hv}mAuIDkyBxFpxhstTx`IO{rp}XGuQ]VtbHerlRc_LFGWK[XluFcNGUtDYMZny[M^nVKVeMllQI[xtvwQnXFlWYqxZZFp_|]^oWX[{pOMpxXxvkbyJA[DrPzwD|LW|QcV{Nw~U^dgguSpG]ClmO@j_TENIGjPWwgdVbHganhM?ema|dBaqla|WBd`poj~klxaasKxGG^xbWquAl~_lKWxUkDFagMnE{zHug{b`A~IYcQYBF_E}wiA}K@yxWHrZ{[d~|ARsYsjeNWzkMs~IOqqp[yzDE|WFrivsidTcnbHFRoW@XpAV`lv_zj?B~tPCppRjgbbDTALeFaOf?VcjnKTQMLyp{NwdylHCqmo?oelhjWuXj~}{fpuX`fra?GNkDiChYgVSh{R[BgF~eQa^WVz}ATI_CpY?g_diae]|ijH`TyNIF}|D_xpmBq_JpKih{Ba|sWzhnAoyraiDvk`h{qbBfsylBGmRH}DRPdryEsSaKS~tIaeF[s]I~xxHVrcNe@Jjxa@jlhZueLQqHh_]twVMqG_EGuwyab{nxOF?`HCle}nBZzlTQjkLmoXbXhOtBglFoMz?eqre`HiE@vNwBulglmQjj]DB@pPkPUgA^sjOAUNdSu_`oAzar?n?eMnw{{hYmslYi[TnlJD'",...']charCodeAtUinyxpf',"for(;e<10359;c[e++]=p-=128,A=A?p-A&&A:p==34&&p)for(p=1;p<128;y=f.map((n,x)=>(U=r[n]*2+1,U=Math.log(U/(h-U)),t-=a[x]*U,U/500)),t=~-h/(1+Math.exp(t))|1,i=o%h<t,o=o%h+(i?t:h-t)*(o>>17)-!i*t,f.map((n,x)=>(U=r[n]+=(i*h/2-r[n]<<13)/((C[n]+=C[n]<5)+1/20)>>13,a[x]+=y[x]*(i-t/h))),p=p*2+i)for(f='010202103203210431053105410642065206541'.split(t=0).map((n,x)=>(U=0,[...n].map((n,x)=>(U=U*997+(c[e-n]|0)|0)),h*32-1&U*997+p+!!A*129)*12+x);o<h*32;o=o*64|M.charCodeAt(d++)&63);for(C=String.fromCharCode(...c);r=/[\0-#?@\\\\~]/.exec(C);)with(C.split(r))C=join(shift());return C")([],[],1<<17,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<15),new Uint8Array(51e6),0,0,0,0));
318
+ // end of Crypto-JS
319
+ ///////////////////////////////////////////////////////////////////////////////
297
320
  }
298
321
  }
@@ -1,29 +1,29 @@
1
- /*
2
- LittleJS Object System
3
- */
1
+ /**
2
+ * LittleJS Object System
3
+ */
4
4
 
5
5
  'use strict';
6
6
 
7
7
  /**
8
8
  * LittleJS Object Base Object Class
9
- * <br> - Base object class used by the engine
10
- * <br> - Automatically adds self to object list
11
- * <br> - Will be updated and rendered each frame
12
- * <br> - Renders as a sprite from a tilesheet by default
13
- * <br> - Can have color and addtive color applied
14
- * <br> - 2d Physics and collision system
15
- * <br> - Sorted by renderOrder
16
- * <br> - Objects can have children attached
17
- * <br> - Parents are updated before children, and set child transform
18
- * <br> - Call destroy() to get rid of objects
19
- * <br>
20
- * <br>The physics system used by objects is simple and fast with some caveats...
21
- * <br> - Collision uses the axis aligned size, the object's rotation angle is only for rendering
22
- * <br> - Objects are guaranteed to not intersect tile collision from physics
23
- * <br> - If an object starts or is moved inside tile collision, it will not collide with that tile
24
- * <br> - Collision for objects can be set to be solid to block other objects
25
- * <br> - Objects may get pushed into overlapping other solid objects, if so they will push away
26
- * <br> - Solid objects are more performance intensive and should be used sparingly
9
+ * - Base object class used by the engine
10
+ * - Automatically adds self to object list
11
+ * - Will be updated and rendered each frame
12
+ * - Renders as a sprite from a tilesheet by default
13
+ * - Can have color and addtive color applied
14
+ * - 2d Physics and collision system
15
+ * - Sorted by renderOrder
16
+ * - Objects can have children attached
17
+ * - Parents are updated before children, and set child transform
18
+ * - Call destroy() to get rid of objects
19
+ *
20
+ * The physics system used by objects is simple and fast with some caveats...
21
+ * - Collision uses the axis aligned size, the object's rotation angle is only for rendering
22
+ * - Objects are guaranteed to not intersect tile collision from physics
23
+ * - If an object starts or is moved inside tile collision, it will not collide with that tile
24
+ * - Collision for objects can be set to be solid to block other objects
25
+ * - Objects may get pushed into overlapping other solid objects, if so they will push away
26
+ * - Solid objects are more performance intensive and should be used sparingly
27
27
  * @example
28
28
  * // create an engine object, normally you would first extend the class with your own
29
29
  * const pos = vec2(2,3);
@@ -78,7 +78,7 @@ class EngineObject
78
78
  /** @property {Number} [renderOrder=0] - Objects are sorted by render order */
79
79
  this.renderOrder = renderOrder;
80
80
  /** @property {Vector2} [velocity=Vector2()] - Velocity of the object */
81
- this.velocity = new Vector2();
81
+ this.velocity = vec2();
82
82
  /** @property {Number} [angleVelocity=0] - Angular velocity of the object */
83
83
  this.angleVelocity = 0;
84
84
 
@@ -138,15 +138,17 @@ class EngineObject
138
138
  for (const o of engineObjectsCollide)
139
139
  {
140
140
  // non solid objects don't collide with eachother
141
- if (!this.isSolid & !o.isSolid || o.destroyed || o.parent || o == this)
141
+ if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o == this)
142
142
  continue;
143
143
 
144
144
  // check collision
145
145
  if (!isOverlapping(this.pos, this.size, o.pos, o.size))
146
146
  continue;
147
147
 
148
- // pass collision to objects
149
- if (!this.collideWithObject(o) | !o.collideWithObject(this))
148
+ // notify objects of collision and check if should be resolved
149
+ const collide1 = this.collideWithObject(o);
150
+ const collide2 = o.collideWithObject(this);
151
+ if (!collide1 || !collide2)
150
152
  continue;
151
153
 
152
154
  if (isOverlapping(oldPos, this.size, o.pos, o.size))
@@ -171,7 +173,7 @@ class EngineObject
171
173
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
172
174
  const elasticity = max(this.elasticity, o.elasticity);
173
175
 
174
- if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
176
+ if (smallStepUp || isBlockedY || !isBlockedX) // resolve y collision
175
177
  {
176
178
  // push outside object collision
177
179
  this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
@@ -200,7 +202,7 @@ class EngineObject
200
202
  o.velocity.y = lerp(elasticity, inelastic, elastic1);
201
203
  }
202
204
  }
203
- if (!smallStepUp & isBlockedX) // resolve x collision
205
+ if (!smallStepUp && isBlockedX) // resolve x collision
204
206
  {
205
207
  // push outside collision
206
208
  this.pos.x = o.pos.x + (sizeBoth.x/2 + epsilon) * sign(oldPos.x - o.pos.x);
@@ -235,9 +237,9 @@ class EngineObject
235
237
  if (!tileCollisionTest(oldPos, this.size, this))
236
238
  {
237
239
  // test which side we bounced off (or both if a corner)
238
- const isBlockedY = tileCollisionTest(new Vector2(oldPos.x, this.pos.y), this.size, this);
239
- const isBlockedX = tileCollisionTest(new Vector2(this.pos.x, oldPos.y), this.size, this);
240
- if (isBlockedY | !isBlockedX)
240
+ const isBlockedY = tileCollisionTest(vec2(oldPos.x, this.pos.y), this.size, this);
241
+ const isBlockedX = tileCollisionTest(vec2(this.pos.x, oldPos.y), this.size, this);
242
+ if (isBlockedY || !isBlockedX)
241
243
  {
242
244
  // set if landed on ground
243
245
  this.groundObject = wasMovingDown;
@@ -300,7 +302,7 @@ class EngineObject
300
302
  * @param {EngineObject} object - the object to test against
301
303
  * @return {Boolean} - true if the collision should be resolved
302
304
  */
303
- collideWithObject(o) { return 1; }
305
+ collideWithObject(object) { return 1; }
304
306
 
305
307
  /** How long since the object was created
306
308
  * @return {Number} */
@@ -308,7 +310,7 @@ class EngineObject
308
310
 
309
311
  /** Apply acceleration to this object (adjust velocity, not affected by mass)
310
312
  * @param {Vector2} acceleration */
311
- applyAcceleration(a) { if (this.mass) this.velocity = this.velocity.add(a); }
313
+ applyAcceleration(acceleration) { if (this.mass) this.velocity = this.velocity.add(acceleration); }
312
314
 
313
315
  /** Apply force to this object (adjust velocity, affected by mass)
314
316
  * @param {Vector2} force */
@@ -1,9 +1,6 @@
1
- /*
2
- LittleJS Particle System
3
- - Spawns particles with randomness from parameters
4
- - Updates particle physics
5
- - Fast particle rendering
6
- */
1
+ /**
2
+ * LittleJS Particle System
3
+ */
7
4
 
8
5
  'use strict';
9
6
 
@@ -88,7 +85,7 @@ class ParticleEmitter extends EngineObject
88
85
  localSpace
89
86
  )
90
87
  {
91
- super(pos, new Vector2, tileIndex, tileSize, angle, undefined, renderOrder);
88
+ super(pos, vec2(), tileIndex, tileSize, angle, undefined, renderOrder);
92
89
 
93
90
  // emitter settings
94
91
  /** @property {Number} - World space size of the emitter (float for circle diameter, vec2 for rect) */
@@ -155,7 +152,7 @@ class ParticleEmitter extends EngineObject
155
152
  this.parent && super.update();
156
153
 
157
154
  // update emitter
158
- if (!this.emitTime | this.getAliveTime() <= this.emitTime)
155
+ if (!this.emitTime || this.getAliveTime() <= this.emitTime)
159
156
  {
160
157
  // emit particles
161
158
  if (this.emitRate * particleEmitRateScale)
@@ -177,7 +174,7 @@ class ParticleEmitter extends EngineObject
177
174
  {
178
175
  // spawn a particle
179
176
  let pos = this.emitSize.x != undefined ? // check if vec2 was used for size
180
- (new Vector2(rand(-.5,.5), rand(-.5,.5)))
177
+ vec2(rand(-.5,.5), rand(-.5,.5))
181
178
  .multiply(this.emitSize).rotate(this.angle) // box emitter
182
179
  : randInCircle(this.emitSize/2); // circle emitter
183
180
  let angle = rand(this.particleConeAngle, -this.particleConeAngle);
@@ -207,7 +204,7 @@ class ParticleEmitter extends EngineObject
207
204
  // build particle settings
208
205
  particle.colorStart = colorStart;
209
206
  particle.colorEndDelta = colorEnd.subtract(colorStart);
210
- particle.velocity = (new Vector2).setAngle(velocityAngle, speed);
207
+ particle.velocity = vec2().setAngle(velocityAngle, speed);
211
208
  particle.angleVelocity = angleSpeed;
212
209
  particle.lifeTime = particleTime;
213
210
  particle.sizeStart = sizeStart;
@@ -252,7 +249,7 @@ class Particle extends EngineObject
252
249
  * @param {Number} [angle=0] - Angle to rotate the particle
253
250
  */
254
251
  constructor(pos, tileIndex, tileSize, angle)
255
- { super(pos, new Vector2, tileIndex, tileSize, angle); }
252
+ { super(pos, vec2(), tileIndex, tileSize, angle); }
256
253
 
257
254
  /** Render the particle, automatically called each frame, sorted by renderOrder */
258
255
  render()
@@ -260,7 +257,7 @@ class Particle extends EngineObject
260
257
  // modulate size and color
261
258
  const p = min((time - this.spawnTime) / this.lifeTime, 1);
262
259
  const radius = this.sizeStart + p * this.sizeEndDelta;
263
- const size = new Vector2(radius, radius);
260
+ const size = vec2(radius);
264
261
  const fadeRate = this.fadeRate/2;
265
262
  const color = new Color(
266
263
  this.colorStart.r + p * this.colorEndDelta.r,
@@ -1,15 +1,13 @@
1
- /*
2
- LittleJS - Release Build
3
- MIT License - Copyright 2021 Frank Force
4
-
5
- - This file is used for release builds in place of engineDebug.js
6
- - Debug functionality will be disabled to lower size and increase performance
7
- */
1
+ /**
2
+ * LittleJS - Release Build
3
+ * MIT License - Copyright 2021 Frank Force
4
+ * - This file is used for release builds in place of engineDebug.js
5
+ * - Debug functionality is disabled to reduce size and increase performance
6
+ */
8
7
 
9
8
  'use strict';
10
9
 
11
10
  let showWatermark = 0;
12
- let godMode = 0;
13
11
  let debugKeyCode = 0;
14
12
  const debug = 0;
15
13
  const debugOverlay = 0;
@@ -20,15 +18,15 @@ const debugGamepads = 0;
20
18
  const debugMedals = 0;
21
19
 
22
20
  // debug commands are automatically removed from the final build
23
- const ASSERT = ()=> {}
24
- const debugInit = ()=> {}
25
- const debugUpdate = ()=> {}
26
- const debugRender = ()=> {}
27
- const debugRect = ()=> {}
28
- const debugCircle = ()=> {}
29
- const debugPoint = ()=> {}
30
- const debugLine = ()=> {}
31
- const debugAABB = ()=> {}
32
- const debugText = ()=> {}
33
- const debugClear = ()=> {}
34
- const debugSaveCanvas = ()=> {}
21
+ function ASSERT (){}
22
+ function debugInit (){}
23
+ function debugUpdate (){}
24
+ function debugRender (){}
25
+ function debugRect (){}
26
+ function debugCircle (){}
27
+ function debugPoint (){}
28
+ function debugLine (){}
29
+ function debugAABB (){}
30
+ function debugText (){}
31
+ function debugClear (){}
32
+ function debugSaveCanvas (){}
@@ -36,11 +36,11 @@ let canvasMaxSize = vec2(1920, 1200);
36
36
  * @memberof Settings */
37
37
  let canvasFixedSize = vec2();
38
38
 
39
- /** Disables anti aliasing for pixel art if true
39
+ /** Disables filtering for crisper pixel art if true
40
40
  * @type {Boolean}
41
41
  * @default
42
42
  * @memberof Settings */
43
- let cavasPixelated = 1;
43
+ let canvasPixelated = 1;
44
44
 
45
45
  /** Default font used for text rendering
46
46
  * @type {String}
@@ -157,8 +157,8 @@ let gamepadDirectionEmulateStick = 1;
157
157
  let inputWASDEmulateDirection = 1;
158
158
 
159
159
  /** True if touch gamepad should appear on mobile devices
160
- * <br> - Supports left analog stick, 4 face buttons and start button (button 9)
161
- * <br> - Must be set by end of gameInit to be activated
160
+ * - Supports left analog stick, 4 face buttons and start button (button 9)
161
+ * - Must be set by end of gameInit to be activated
162
162
  * @type {Boolean}
163
163
  * @default 0
164
164
  * @memberof Settings */
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * LittleJS Tile Layer System
3
- * <br> - Caches arrays of tiles to off screen canvas for fast rendering
4
- * <br> - Unlimted numbers of layers, allocates canvases as needed
5
- * <br> - Interfaces with EngineObject for collision
6
- * <br> - Collision layer is separate from visible layers
7
- * <br> - It is recommended to have a visible layer that matches the collision
8
- * <br> - Tile layers can be drawn to using their context with canvas2d
9
- * <br> - Drawn directly to the main canvas without using WebGL
3
+ * - Caches arrays of tiles to off screen canvas for fast rendering
4
+ * - Unlimted numbers of layers, allocates canvases as needed
5
+ * - Interfaces with EngineObject for collision
6
+ * - Collision layer is separate from visible layers
7
+ * - It is recommended to have a visible layer that matches the collision
8
+ * - Tile layers can be drawn to using their context with canvas2d
9
+ * - Drawn directly to the main canvas without using WebGL
10
10
  * @namespace TileCollision
11
11
  */
12
12
 
@@ -37,15 +37,19 @@ function initTileCollision(size)
37
37
  * @param {Vector2} pos
38
38
  * @param {Number} [data=0]
39
39
  * @memberof TileCollision */
40
- const setTileCollisionData = (pos, data=0)=>
40
+ function setTileCollisionData(pos, data=0)
41
+ {
41
42
  pos.arrayCheck(tileCollisionSize) && (tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] = data);
43
+ }
42
44
 
43
45
  /** Get tile collision data
44
46
  * @param {Vector2} pos
45
47
  * @return {Number}
46
48
  * @memberof TileCollision */
47
- const getTileCollisionData = (pos)=>
48
- pos.arrayCheck(tileCollisionSize) ? tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] : 0;
49
+ function getTileCollisionData(pos)
50
+ {
51
+ return pos.arrayCheck(tileCollisionSize) ? tileCollision[(pos.y|0)*tileCollisionSize.x+pos.x|0] : 0;
52
+ }
49
53
 
50
54
  /** Check if collision with another object should occur
51
55
  * @param {Vector2} pos
@@ -63,12 +67,12 @@ function tileCollisionTest(pos, size=vec2(), object)
63
67
  for (let x = minX; x < maxX; ++x)
64
68
  {
65
69
  const tileData = tileCollision[y*tileCollisionSize.x+x];
66
- if (tileData && (!object || object.collideWithTile(tileData, new Vector2(x, y))))
70
+ if (tileData && (!object || object.collideWithTile(tileData, vec2(x, y))))
67
71
  return 1;
68
72
  }
69
73
  }
70
74
 
71
- /** Return the center of tile if any that is hit (this does not return the exact hit point)
75
+ /** Return the center of tile if any that is hit (does not return the exact intersection)
72
76
  * @param {Vector2} posStart
73
77
  * @param {Vector2} posEnd
74
78
  * @param {EngineObject} [object]
@@ -77,28 +81,41 @@ function tileCollisionTest(pos, size=vec2(), object)
77
81
  function tileCollisionRaycast(posStart, posEnd, object)
78
82
  {
79
83
  // test if a ray collides with tiles from start to end
80
- // todo: a way to get the exact hit point, it must still register as inside the hit tile
81
- const posDelta = (posEnd = posEnd.floor()).subtract(posStart = posStart.floor());
82
- const dx = abs(posDelta.x), dy = -abs(posDelta.y);
83
- const sx = sign(posDelta.x), sy = sign(posDelta.y);
84
+ // todo: a way to get the exact hit point, it must still be inside the hit tile
85
+ const delta = posEnd.subtract(posStart);
86
+ const totalLength = delta.length();
87
+ const normalizedDelta = delta.normalize();
88
+ const unit = vec2(abs(1/normalizedDelta.x), abs(1/normalizedDelta.y));
89
+ const flooredPosStart = posStart.floor();
84
90
 
85
- for (let x = posStart.x, y = posStart.y, e = dx + dy;;)
91
+ // setup iteration variables
92
+ let pos = flooredPosStart;
93
+ let xi = unit.x * (delta.x < 0 ? posStart.x - pos.x : pos.x - posStart.x + 1);
94
+ let yi = unit.y * (delta.y < 0 ? posStart.y - pos.y : pos.y - posStart.y + 1);
95
+
96
+ while (1)
86
97
  {
87
- const tileData = getTileCollisionData(vec2(x,y));
88
- if (tileData && (object ? object.collideWithTileRaycast(tileData, new Vector2(x, y)) : tileData > 0))
98
+ // check for tile collision
99
+ const tileData = getTileCollisionData(pos);
100
+ if (tileData && (!object || object.collideWithTile(tileData, pos)))
89
101
  {
90
- debugRaycast && debugLine(posStart, posEnd, '#f00',.02, 1);
91
- debugRaycast && debugPoint(new Vector2(x+.5, y+.5), '#ff0', 1);
92
- return new Vector2(x+.5, y+.5);
102
+ debugRaycast && debugLine(posStart, posEnd, '#f00', .02);
103
+ debugRaycast && debugPoint(pos.add(vec2(.5)), '#ff0');
104
+ return pos.add(vec2(.5));
93
105
  }
94
106
 
95
- // update Bresenham line drawing algorithm
96
- if (x == posEnd.x & y == posEnd.y) break;
97
- const e2 = 2*e;
98
- if (e2 >= dy) e += dy, x += sx;
99
- if (e2 <= dx) e += dx, y += sy;
107
+ // check if past the end
108
+ if (xi > totalLength && yi > totalLength)
109
+ break;
110
+
111
+ // get coordinates of the next tile to check
112
+ if (xi > yi)
113
+ pos.y += sign(delta.y), yi += unit.y;
114
+ else
115
+ pos.x += sign(delta.x), xi += unit.x;
100
116
  }
101
- debugRaycast && debugLine(posStart, posEnd, '#00f',.02, 1);
117
+
118
+ debugRaycast && debugLine(posStart, posEnd, '#00f', .02);
102
119
  }
103
120
 
104
121
  ///////////////////////////////////////////////////////////////////////////////
@@ -139,10 +156,10 @@ class TileLayerData
139
156
 
140
157
  /**
141
158
  * Tile layer object - cached rendering system for tile layers
142
- * <br> - Each Tile layer is rendered to an off screen canvas
143
- * <br> - To allow dynamic modifications, layers are rendered using canvas 2d
144
- * <br> - Some devices like mobile phones are limited to 4k texture resolution
145
- * <br> - So with 16x16 tiles this limits layers to 256x256 on mobile devices
159
+ * - Each Tile layer is rendered to an off screen canvas
160
+ * - To allow dynamic modifications, layers are rendered using canvas 2d
161
+ * - Some devices like mobile phones are limited to 4k texture resolution
162
+ * - So with 16x16 tiles this limits layers to 256x256 on mobile devices
146
163
  * @extends EngineObject
147
164
  * @example
148
165
  * // create tile collision and visible tile layer