littlejsengine 1.6.6 → 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 (57) hide show
  1. package/README.md +51 -35
  2. package/build/littlejs.d.ts +71 -80
  3. package/build/littlejs.esm.js +162 -139
  4. package/build/littlejs.esm.min.js +1 -1
  5. package/build/littlejs.js +159 -129
  6. package/build/littlejs.min.js +1 -1
  7. package/build/littlejs.release.js +1942 -1907
  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/js13k/build.bat +2 -0
  20. package/examples/js13k/build.js +110 -0
  21. package/examples/js13k/game.js +109 -0
  22. package/examples/js13k/index.html +18 -0
  23. package/examples/js13k/tiles.png +0 -0
  24. package/examples/module/game.js +9 -3
  25. package/examples/module/index.html +2 -2
  26. package/examples/particles/index.html +7 -13
  27. package/examples/platformer/game.js +5 -2
  28. package/examples/platformer/gameEffects.js +1 -2
  29. package/examples/platformer/gamePlayer.js +2 -2
  30. package/examples/platformer/index.html +8 -8
  31. package/examples/puzzle/game.js +5 -3
  32. package/examples/puzzle/index.html +4 -4
  33. package/examples/starter/build.bat +2 -78
  34. package/examples/starter/build.js +109 -0
  35. package/examples/starter/game.js +4 -1
  36. package/examples/starter/index.html +15 -18
  37. package/examples/stress/index.html +2 -4
  38. package/examples/typescript/build.bat +2 -14
  39. package/examples/typescript/build.js +31 -0
  40. package/examples/typescript/game.js +94 -89
  41. package/examples/typescript/game.ts +9 -3
  42. package/examples/typescript/index.html +2 -2
  43. package/package.json +2 -2
  44. package/src/engine.js +3 -3
  45. package/src/engineAudio.js +2 -2
  46. package/src/engineBuild.bat +2 -132
  47. package/src/engineBuild.js +143 -0
  48. package/src/engineDebug.js +4 -10
  49. package/src/engineDraw.js +12 -4
  50. package/src/engineExport.js +1 -8
  51. package/src/engineInput.js +1 -1
  52. package/src/engineObject.js +13 -11
  53. package/src/engineParticles.js +6 -6
  54. package/src/engineRelease.js +0 -1
  55. package/src/engineTileLayer.js +31 -18
  56. package/src/engineUtilities.js +74 -61
  57. package/examples/electron/build.bat +0 -52
@@ -1,5 +1,9 @@
1
1
  /*
2
- LittleJS Breakout Example
2
+ Little JS Breakout Game
3
+ - A simple breakout game
4
+ - Includes sound and particles
5
+ - Uses a post processing effect
6
+ - Control with mouse, touch, or gamepad
3
7
  */
4
8
 
5
9
  'use strict';
@@ -1,11 +1,11 @@
1
- <html><head>
2
- <title>Little JS Breakout Game Demo</title>
1
+ <!DOCTYPE html><head>
2
+ <title>Little JS Breakout Game</title>
3
3
  <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
4
4
  <meta name=apple-mobile-web-app-capable content=yes>
5
5
  <meta name=mobile-web-app-capable content=yes>
6
6
  <link rel=icon type=image/png href=../favicon.png>
7
7
  </head><body>
8
8
 
9
- <script src=../../build/littlejs.js?166></script>
10
- <script src=gameObjects.js?166></script>
11
- <script src=game.js?166></script>
9
+ <script src=../../build/littlejs.js?1691></script>
10
+ <script src=gameObjects.js?1691></script>
11
+ <script src=game.js?1691></script>
@@ -53,7 +53,7 @@ for(let y=0; y<=levelSize.y; y+=1)
53
53
  Let’s move the camera to the center of our level by setting the cameraPos variable to half the level size.
54
54
 
55
55
  ```javascript
56
- cameraPos = levelSize.scale(.5); // center camera in level
56
+ setCameraPos(levelSize.scale(.5)); // center camera in level
57
57
  ```
58
58
 
59
59
  We’ll also start with a blank slate by commenting out the default “Hello World!” text in gameRenderPost.
@@ -73,7 +73,7 @@ For this example we will use a fixed size canvas. This will let the drawing canv
73
73
  To enable it we will set canvasFixedSize in gameInit to use 720p resolution.
74
74
 
75
75
  ```javascript
76
- canvasFixedSize = vec2(1280, 720); // use a 720p fixed size canvas
76
+ setCanvasFixedSize(vec2(1280, 720)); // use a 720p fixed size canvas
77
77
  ```
78
78
 
79
79
  Before we tweak the level size, let’s add this bit of code to gameRender to show the size of the level. This will cause some rects to be drawn each frame before the engine objects. To create color objects we pass in RGB values between 0 and 1.
@@ -222,9 +222,9 @@ We can create walls on the sides and top by adding a few more lines of code to t
222
222
 
223
223
  ```javascript
224
224
  // create walls
225
- new Wall(vec2(-.5,levelSize.y/2), vec2(1,100)) // top
226
- new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // left
227
- new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // right
225
+ new Wall(vec2(-.5,levelSize.y/2), vec2(1,100)) // left
226
+ new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // right
227
+ new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // top
228
228
  ```
229
229
 
230
230
  ![LittleJS Screenshot](images/6.png)
@@ -503,7 +503,7 @@ sound_bounce.play(this.pos, 1, speed); // play bounce sound with pitch scaled by
503
503
 
504
504
  Now you know the basics of how to use the LittleJS engine! [The final result with all the code from this tutorial is playable here.](https://killedbyapixel.github.io/LittleJS/examples/breakoutTutorial/)
505
505
 
506
- If you need a little help completing the tutoiral, [join us on the LittleJS discord](https://discord.gg/zb7hcGkyZe).
506
+ If you need a little help completing the tutorial, [join us on the LittleJS discord](https://discord.gg/zb7hcGkyZe).
507
507
 
508
508
  Feel free to continue building on this tutorial to make a more interesting breakout game. What kind of ideas would you like to include?
509
509
 
@@ -1,5 +1,8 @@
1
1
  /*
2
2
  Little JS Breakout Tutorial
3
+ - Shows how to make a simple breakout game
4
+ - Includes sound and particles
5
+ - Control with mouse or touch
3
6
  */
4
7
 
5
8
  'use strict';
@@ -1,4 +1,4 @@
1
- <html><head>
1
+ <!DOCTYPE html><head>
2
2
  <title>Little JS Breakout Tutorial</title>
3
3
  <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
4
4
  <meta name=apple-mobile-web-app-capable content=yes>
@@ -6,5 +6,5 @@
6
6
  <link rel=icon type=image/png href=../favicon.png>
7
7
  </head><body>
8
8
 
9
- <script src=../../build/littlejs.js?166></script>
10
- <script src=game.js?166></script>
9
+ <script src=../../build/littlejs.js?1691></script>
10
+ <script src=game.js?1691></script>
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * LittleJS Build System
5
+ */
6
+
7
+ const PROGRAM_NAME = 'game';
8
+ const BUILD_FOLDER = 'build';
9
+ const sourceFiles =
10
+ [
11
+ '../../build/littlejs.release.js',
12
+ 'game.js',
13
+ // add your game's files here
14
+ ];
15
+ const dataFiles =
16
+ [
17
+ 'tiles.png',
18
+ // add your game's data files here
19
+ ];
20
+
21
+ console.log(`Building ${PROGRAM_NAME} with electron...`);
22
+ const startTime = Date.now();
23
+ const fs = require('node:fs');
24
+ const child_process = require('node:child_process');
25
+
26
+ // remove old files and setup build folder
27
+ fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
28
+ fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
29
+ fs.mkdirSync(BUILD_FOLDER);
30
+
31
+ // copy data files
32
+ for(const file of dataFiles)
33
+ fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
34
+
35
+ Build
36
+ (
37
+ `${BUILD_FOLDER}/index.js`,
38
+ sourceFiles,
39
+ [closureCompilerStep, uglifyBuildStep, htmlBuildStep, electronBuildStep]
40
+ );
41
+
42
+ console.log(`Build Completed in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
43
+
44
+ ///////////////////////////////////////////////////////////////////////////////
45
+
46
+ // A single build with its own source files, build steps, and output file
47
+ // - each build step is a callback that accepts a single filename
48
+ function Build(outputFile, files=[], buildSteps=[])
49
+ {
50
+ // copy files into a buffer
51
+ let buffer = '';
52
+ for (const file of files)
53
+ buffer += fs.readFileSync(file) + '\n';
54
+
55
+ // output file
56
+ fs.writeFileSync(outputFile, buffer, {flag: 'w+'});
57
+
58
+ // execute build steps in order
59
+ for (const buildStep of buildSteps)
60
+ buildStep(outputFile);
61
+ }
62
+
63
+ function closureCompilerStep(filename)
64
+ {
65
+ console.log(`Running closure compiler...`);
66
+
67
+ const filenameTemp = filename + '.tmp';
68
+ fs.copyFileSync(filename, filenameTemp);
69
+ child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
70
+ fs.rmSync(filenameTemp);
71
+ };
72
+
73
+ function uglifyBuildStep(filename)
74
+ {
75
+ console.log(`Running uglify...`);
76
+ child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
77
+ };
78
+
79
+ function htmlBuildStep(filename)
80
+ {
81
+ console.log(`Building html...`);
82
+
83
+ // create html file
84
+ let buffer = '<!DOCTYPE html>';
85
+ buffer += '<script>';
86
+ buffer += fs.readFileSync(filename) + '\n';
87
+ buffer += '</script>';
88
+
89
+ // output html file
90
+ fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
91
+ };
92
+
93
+ function electronBuildStep(filename)
94
+ {
95
+ console.log(`Building executable with electron...`);
96
+
97
+ // delete intermediate files
98
+ fs.rmSync(filename);
99
+
100
+ // copy elecron files to build folder
101
+ fs.copyFileSync('electron.js', `${BUILD_FOLDER}/electron.js`);
102
+ fs.copyFileSync('package.json', `${BUILD_FOLDER}/package.json`);
103
+
104
+ child_process.execSync(`npx electron-packager ./${BUILD_FOLDER} --overwrite`, {stdio: 'inherit'});
105
+ };
@@ -1,5 +1,7 @@
1
1
  /*
2
- LittleJS Hello World Starter Game
2
+ Little JS Electron Demo
3
+ - A simple starter project
4
+ - Builds to an executable with Electron
3
5
  */
4
6
 
5
7
  'use strict';
@@ -103,7 +105,7 @@ function gameRender()
103
105
  function gameRenderPost()
104
106
  {
105
107
  // draw to overlay canvas for hud rendering
106
- drawTextScreen('LittleJS Engine Demo', vec2(mainCanvasSize.x/2, 80), 80);
108
+ drawTextScreen('LittleJS Electron Demo', vec2(mainCanvasSize.x/2, 80), 80);
107
109
  }
108
110
 
109
111
  ///////////////////////////////////////////////////////////////////////////////
@@ -1,2 +1,13 @@
1
- <body><script>
2
- eval(Function("[M='DYhuJzCBV~LKby?Vt_b^ejSdE[eOF]^xwJzztBUSE|iPNBKKb?dBsnnlAtsdW{Bah}DrNQBAvepYbgAd|MkbArM~O||rTzOp@j@plQJwXWvVhjJOIAP]qltDKs]}eKr_hNM[lCb@AimlGZse}EkgtrHOvPEpL_wCglz}RRMIaRQzRhG{}zBgw@o]PR]~GKdRJGuuTSzzixXpGA}gRynsIAu{Sw{F}R|LIG@CsRCM`JUJvCzAYYZu@oL[I|WDTw|soA_N|ancvowsba{YWMEFfRfNMYRp_TvI~Fx`ZQzun_?[FQ@j?nsDgS}HlS_G~]h^vAvy^dSsvmUzvoHPLSdEgeGgYV{KTFMcq?byagUHA{yNhjvosWF|JY}?fQEbD}OjGVwx^c}OMOl^bWOui^[Ivg[jsXiPsH`v}AUS`pXxUJz]hAOQhlYOCMUceMnrGhge|EkH{?WpWojSpLiJRRVcNwXKw{JXRZgzX]gQ@etO^dYcUGvirBooulMfYq@JovQKWTOHCIDd`K?junfya]tnwNmtrCnEB{FBvcPIR|p|]apt~LzVZ`uIsSeaTtTVKi[|LYGO[ML_ulpHJ?QteSYjISIHNzI~mePARzyvRJcPtslrQgXO`fAyNNzFJ{abI]jpXTnT{YFRvrJAZnOzUaRuTX?uAkmmeJpZJmvyULO@`p@R}[t~qOlHB_TqPslYp|R^ftUiccRghndwglFSLpBAa[g}cKvx|HibXgWlIGXsGIHCa_f[tS?]eiZq^dtAhlWJffyPW]n|D[zRUFIAdi_iVHNQfkSn@QdEqqhUEgzE{pCpfnhacZJWV[MOjtdQq_ZMcC@pwJwmnFt^HK^tEOUeu{nl[wvQqf{SE`UhYtcDsdLALAbt`qDfmeZ`Gyj_iWv_[?}SPzvE[AtFJ^_X?pq|SjuuYFSkniQYdhaUmNmvDtHn[DTt{TIE}NtkDvi~?bd~RAu|fK^?lOvUUv]AWT?Ui]^_Z{kytzlQ@rhR`_OTEnDFk[bDtj|uyttWJ_VkirTg]WBlS{[om@LudgyTdJ^MNdmXo^lRP`e`kKtZVD|YGFqjGCYQH`EpErSwlhtYDgRUwujfAXWXJI|NDwQ|OApShIKEJJeOcBUbchxxQ^}gcH?gbfNYwk~{|]LScUWE`Gzv{hx^FyioJP[^_CMUeICIIdroIVKkR}xTKYDLqUzfl{XVao`@zbtAlV{?mOXelBkgKeQuwqPWbf^PM]ahX]{IFKYF@b_VE_vFs[ct~l?CA_}mZV^aoMAdYCOU`PDjYFEwqxxUHWzpnY@?H~GagutCltWqq{zsWds^jkN{`z{Pp}pZCnyfV^tLhLE|ydFFDytCUAIghmjfWqbH?ma]_gRnYJsboB{nQSoIVYVrqHLO`mzC{QkZojEUA`FLfOKzM_mQommrT?yezZeYPodczzc_aQuQrBSNeQ@Kitt^QKmf@]KKHjygOxxYH?B^UgPp]zXK[xffIt`jHIFw?zfy~|m`KpIyJ{{nwW@TqacRjViIfW{UKT@mYNZWOTUeckbaYMnJ~h|}y_?a{nnE_s?GV_tWBqSPr?gqq@wfIZWLCA|CAN_MvkhvcnQhKZsBrmU^w[D|YNf}_nZJwNXM{Dw?PDY~rusf_Nrm{NyzSY}qt|y]mPgPRl?SliU@CxtCFf@ZNP`gg|g@FsI^mUayJjOK~doq~|GuDt`PwKMWyb}|~iklbESGhcS?a~zT_a]yTKpMi?Llrs@bQ_L|xh?wUOpuXkZoSzWDvwmyg[ggMnEAAr_w?Fctw|EHql|OGtTRN{XBWxdvVsiEwZkGFD|{WspkNjMSV[nxYmppwBVb]tlZReEPHhIDZfHgEZemYtiXft_}_sOEnA~U~`awBrmQ`W[[jaOu@Fp_dtyZc]|BR{[jSOy}SA]?sfaRz[jwiMufnOLOBKalL`JiYH]YUQMkwJuqvd[lPcZt[Ek?r`TkRDTXBszW}QszISPMPzj]l}ALBP?coK[M}QMu|wHvPrMNPA^vCUGbGeCBhF|SgQeVptFfDMWrpc@Taj~WpCNPzwvBSSY`ccans??UzK^adxVBOtiNdoZmqaJ]T^RkMfPuxlyn|YUcdf[AQWqOVGUTUSz_CROMCRtM^WCCCcFo}o@bH[J{l?wUM[soFzKgJRpv[FCLYRXOd|bdqfd?AAwYCSeZkbWj~SoXDi`xRUyQWQX_j@GuxZkjxN^RZgfd~~|N`gBA]kJ^jLTZxlNV]N`_urbSf|Yt?prXcvhiS?hfbamVv{LPqhim{]bCM}OA}^DYjrDsrFIsSDvhCKLu^]`vKo{tWV_FdyqpUPIKgN`Qa[GaKuKvF?kcEhJvS[ypCruGUVHmk^xG_Q@HXMmpiaKvf?UjJ{icwDQrrq{UYw_DmVFzhHqzUUi?o_~VRU_HxKdUm|y`dvA^{Ai`tnSdO@YsBWAIBflM?UvLR]vTf`TcMoc`fVGNWIkTJsfMkDMzHIJcuC^ASrCabcl[?QfonyEFyogsunyRacV{CgFm[hynYFecGgAdftoVsZJNdPCRDkk[UUMWq_Pox`Xk{HeeROyfq`?rCg?JIrtnO@Ns{Tm{@r|}gExLpF|JgzZV~eliS?zT?y~CxIIZ?[_SRbJcO@_kdVJOWwZNAUFEVBBgxK_xhkGZa_JxymZlCAaygyaf?dIo]m}Wgpf~K_]bAQgOwnJ{k{XmHGGyePZsjd{?OvUCG_zrjAo{Uo_QyCJzWJ]wf|_FIYQxgrdqjv~lcItCWI}sAyqPX]RlX?FJjKUBJKccMPWcgp[`YALWnUJpmyp`oqB~IP@zOZZpz`b_xMG}dCNuxsaRgsqIv?cGPWEFWeBIFPQ@l}OVPbwvrGvkPBZ?jRyrh^i{gO@?wqvzGHzFnAPw}mkpzvJWrNQfLof]WL[}?nXSz_ADPjhQcG_aGS[|@DYJqMX?O^NqUQ^Bi@d~}`fhleXD?L~J|NzlkQoJCBMWvwgzMhAXqxIbIgNf@?vroNXhzJ?@oUShEqi}LAyTp|cYKyjf|Vs[wbGDfkegITHOozosxloZdxlFmE_?pjFMZMrR]DbjdzXPzNYT}@rPKDwY^_WWgNRYtoIETZhvzXP[wa|tWKTwF^KogSPW{o?[N}AyT`GtdzSErko?DtjzKBJdWXugT~s`rW~|TjTCTgCeD|Fu_YsR]VXmUOxBVVY|GMNC`BhQltZtz`YsG?k_DXUfSGKMSYlhiabhMLOyYJfUlR_|RRzFmb@FQxZO`wlGQP^FxEE`?l~n~W`DNYmbnz_pnZZaDG|_YeeF[wqjSVu{^BMQg}wpp{J_qyLlzMrTY|HDTN`QzoQuHeaktwqmPOg[Z[cEzjmQyF][qtCQ]NPJk~jZkDRDej]yk^tLJmRJZsEBh{Sa]Md^D|EI~yCSNMqAjn?BMwuXNe|KnjSXrmPThgj_hc^B_SficQw|T@SSgzBygIwDtvEqDRlTB}hA@mZUW]g`dfbtEsR?rWqWkVp``InYlyoerOtU?okUZV?jK}CPWw?Onq?^IezHJTqBASonkuD{_GzqZ[aSMZPhvBnpQYII~VT}JPxgQUZShecdMcDNYjemVgIF|~dnM[{@~~QDAcCeK_QLSx|BFIC`esdZmo??xI]~p|uRcQY_Q}LlzWioticXqY?pNOWNhOW_q{sm[?NLoivJcl~qDRwFM_dTK[j@^DF[bFY`sEVhUq[miWk[xV?RM?KVNSG^f_qnvRxN?zMwCaxwZNvw@ohtzk^gDC`Z_]zUHnOFLr~ZhGFYIYyWOl?IbAKVJcKtj@~ToUxGCDDZIx?nd?iOV^uh{dsRWtva?faEhvImhRbneQWoSCPFu}[Hb]XrcDOqkVbkyIazdpDcAaCxYW]jmcQhOsE|b[}CdczX^J}yKGjtAJAWsgGSV~ntNxtmYJEhbh{u[HKv_kPDhZt?oGT~V}dLsPWWCpT|qtGix|mfU`rFh`ir{bTgskDf]FZ}NZXJiAVUNaiIwkuskx~}u@djezJXzq?LBA^_dCIW@XW|t`bouxD|ACJvpChHVp[|wD]FpB_~~lV_Pz[|_s[ku^wAzh[{qm|W~K@OBK@vlDG|Y|RelcMQKvtmmdVGQ}OCFexbHzJR}Y}akNvONeOxcZ@JhVUC{dcXndDvsG[ytriKIdRIwVJgQ]wX?Cg~aTXtDcvVM^Z``tLyH~Ez~BRKDBplY`tnvS_w|RmGBQ[Yh_Q[ftvHMPpFoUR|cAGAjKj^[Ht@cD}ruQOpnTQhpYC`@yKdJPaSbIRv}VfCbYDE@BUuqaM?AFYo_ZGM]{ndLiLzrQsYWIUrisBQBBBOf_ImzH@|}xU}yC~ry`mbSlHgnMDKqFIRFqKZ?CXUToMcveLQaQ~]|OPC[[tfFvu{V^h]s[G{l?O`Y}kBnJk}XPy`ldz^Ktur?CEWVfWkgLMzS`usxxfDEuN`UHbfikOU~YG]lDfAlv]Vctn`KxS~v|ALhjCSZEHC}NwYuRIyjgYQUtp]lMAGyQNqFLfyMiHnK`SyMdXOofrwQg_VMKJgP@QtWto@v]qAGxbJDh_MVJJZRASfi@GjM]TwzgaM^zyLke~eYnHcq_ZBr`RKoeq~pauJETAgraal?EdOgqRfcjcpBExanDBdw[YYj]p@nRyCcBFx_STvj~nMeXGyEslPfCQJm_acS|}OvEeYanDQSEVzFbVIWvNnIxjPT_NXi@y]IkSGiFmu^lq`pKB_UpFoSmKkufT[{^i?rccrmoGMVtYjcOZolZdgUwKI^voQfjNd}LxukpVjx~VqN|nyLUBY^qAqn`^?phzGoiRhx_c?btr^AFByUK]wNtGGrkfsXpjjLUCe?O}iCqbnwBNXjrrVFPgKtBKMUnpaYdj@acAua[PeU]n_U?tpDMoepGZhPcuB|IynrfSCKNkzftCqZ?ti~jKOHBRM}jWza^cVFRXnzK?tL_TFmqSsqMfIAPINqLDqQy}YZGuhyzyb|OLj~vfgRfEfv?usSOLsF`[uUcJY_gnaKF?dXNvDEFQWqDbSBpi~ZCQEUy_hd@Owm^YKt_BIXv@NDk[jxRMWICW~GD[`sTQLGv`gPyUbmDdDO}OdbKvwzLoDKavDJRgQwnHIMe?u|xtBo?eqqSPMgwfzyatUiSnBnEuToTwb]cbrRQQ^uAIPswLp|hKaPWk^`MKhE^auir{sJNzqptiGN@Iz@~X`O`JuL?efbeF_k][dvHESTkxn^HnXUsxPbI?lE|EDbKmCRL~NprItUGvq~q{qBp]njD[yctdo^JxjZFSrgHwDouGkqHxgg}mj{noEHzfmb~JSVzIoyAlzwtmQbL~OdZWRZ`mpUDKagmcvNmne[jP|nxCJqzUgLXJBmGG~?a}uDTGbIqsC@u]VfgPVgbg[xto`zeQ_nXRbwY}K~|n`yKeSBFswLA?oCOdiwmc?YwcVGvitUWIjVSawT~Yh`NXx~Jr?HRf}LqVExCisFu|@KvWGETo]?[Xviep^tXQlsS|xschkIzdVzNdgf?ZcwsXX]RanjaebtW[Ujl|^BOlkwK`CTOkvyC?N@EnuWVN]X?oUwlhJVyZAVLmLW]P_vrZoZ}O]vFrWBXwz{lU]XVwrPx]khjwUuv}xUAfaVgfEwv[JgiUpxIIfr}??wIhnnNvMtbmq[hDkfgfTaInXGW[WW?@nnaDVLbGRvFXDSZHcjoMrwbZ`BQCegnD}NJjtNR`[AfJjVAfwrWLnVftTcVYUNCFb[n}[yyEEFSHNllFBh@c^^t?bQDld}OlyIxKwTv[BnLENhKGrHITL^|waFPlQsa]soPPFxON}UKWy^yvyKe]WuqWb]xaGAbPL@tGyLknI_AfSAj^YD?tlORYT_Go`AdJXhJkgiIAhIzV`^ZsyCagoORq`yviJcbAJKuuiE}c{WeoI_mjcjLQtfwgGIYzYGsTE@i@IrvgUj[U[DzmS|bH?DDeDldazEsXBLlqf[uUeYPtq`tLUvkIs~a`HiXFac~WV@t[[eAnLWcpvASBOYiRLCdyCLwpBQXwXGJorQcyNTQkBQQ][rYy~p^RCj~ELPkV`aka}aNSLpyDydUGrC@zG?wSlIuvQjaZH}~tIgYYvrfXIaMHvMg}@~xgr[NKsgUpGcGBwVcRmjw@@NFaGY[|WyQkF_n^~rGpcDr?fqBEq~ZoagW[wCMirZB[l}~hSX^XzCyabfiLXPkbDplwGdIzJPNPQb@BtN^Wmh[?]dMeCkwa@VQSeQCkEQwKBpuZ_ClD}E_sEr?B`_rupxp?ckRsn~Cfoxji^Tucc@}nKCFrW@gHe?Cxd@}SlS@iX^aTzMY_CK@o|nr}{y@qXsgRJ`ItgUP?yvnaIxTr{AfplV}cvEVUeUFPtFD?g_imZ^tw]vHcFclKsqvOYdgJl@hlOrNN|zniXkJMqiSvtnn~AUyuOheTwX_tLz|_cfikR{IEyRw~OuCf[]IAT[PPKIOnc|IAsec^cFwcoeIHFFUQAyRIUAEDzngxosbFd@NEJzFGQCGwWKJNmBwZ_F}OA}MKzIE@LAfAXcp}fNBNCTpGgmV[BaoDIvOd}h~@^N@WD?w|s[i[B@Pv_ZMCzk^qBbNuVzjYWscbJfQVPn|mCKrrazm]QAVS?mfw^vGf]b@N?xA@~b{fily@]f_F@FW|DdLsFng?rdE`PftgWBH^rYn@f`zAZanDdBXkAplT}mpcokSIVfmHbvKNmYblbBu^OYJQqKFHgRwuYfOnvvaSuXBUWS?^Bzkto^gbv?YlP@lnWGEayDQsaqu_fm{WcoCleS@axo~[FqMaUfIikX~vssKAzyevpoHmLGKFfus|tfroqyXJMJ|{`MNrg}Rf`T]weSQIPnD~L?mRfT^ciedQ~BK]?`OcBE~B@j]`D?OF]GPfIwnlX|jgopQQNgqMZkqAjz}ZYDnsBPlyYigZEy[Gfdi@{afvogVO}du{f}j]Eto@si]yf?dVr[yaSIXBrxWiSRxa_BG_pADKsF]|`mLGUHdE_Z}moOXKMbwpzi[XfYTQ_QrdN[pyowYJue|{xLgVdI}{?njX`^MwWV@LWAanGO|u`V?`Da{JAT?HvoL|sDTeeZxSf@hIqwRLrlQGONq?lOCeoAIF?I?AOdg`MxyfyKyyXEjsv[r^Uq?Wj~CoRvTjjxausxHB`CwauprXOle`IpYdsOg]F?iDz]hTSp[_FhmUkRGy]f^dS?fJYFYYgaYSi_DUbNWMSYJfdheVFdw[I}WjP_GMD^LMn~pGQytBn~Qe}aT^VeM_E{M`mNA^{orkcdMy?DToGNLtF[oPbBCd|BmXn|ynz@noy~b}|mGEOQ[f_Dx`JxhL]?DZuvdEpd[f]z|b{xCkFirFxdK|ZAOofbKYngwAEKeaPsFEg?Q`vgkb}`rmuz^f`hvVpOjtjqtcXmhq^W@uRPNnqcmVhp`HJ@WuUIOmpc?`CE??ewy}gAEcMUjY^MqrtQrfoQhqbx]lrHn`cAG|cI`rHF?_?g]HXG][~BcjDigTFkgkW[geovnUFARvz[i?]EV{rIAJ}Rna@_L[vdrd{QlbHs[FlJKpRXlyPp`zeNYoT_am]YOkJiWZBBhb~tvANUcsy|mmj]X|cUdkwIW|vGFUselsg?QFjk?lI[XUr|je@~`NWwJhFHG`ek}TX?UcezDgU]TcMdRy{rq}r[||oBIAXjFtKx_?rXhiVN|dwuVFbfVMsBzfpq|Z|bKRifQ_Bp@mY_]dt{lMB`vDGs~aBKNS@DQ{trAl^^nO_BSb{nZ]AuCZGN@cDPYL{ZJpPvR[PUgoLncXbMpgucJjgETBi[hhmpzbw@TjvZOP]EhFcH{g]HWOmSOBkEjXCkvO`gZSL?NW}PBGqaObGE]Qw[UZtEv~xLk@^~oSXWBaOmjnNQYh^H~KQbhox?X{uNa}aJJf}Qc~`}_MtvjXcNr@?VafbhkRFJqCSFe``I{yqFMjmUVB^fau~}ieSUcEOe`l?VWThanHwXPU`fGHFruFQm`h~`{|GVHv~_Wbz_v]`_TLuGYp_RZvFtTn@@PUTSMWXRNnoEaYKNT{sqQIHt_UUvA|ziPqvbQi~t@s]QmrQaYxpIFHqdYxsRSrUb^GhDk`@wYE^JFABqmjKtkWwWkWfMM}Yj~bvgd`WQYefZg}YqJ'",...']charCodeAtUinyxp',"for(;e<13590;c[e++]=x-128)for(x=1;x<128;n=p.map((i,y)=>(t=r[i]*2+1,t=Math.log(t/(h-t)),A-=a[y]*t,t/750)),A=~-h/(1+Math.exp(A))|1,U=o%h<A,o=o%h+(U?A:h-A)*(o>>13)-!U*A,p.map((i,y)=>(t=r[i]+=(U*h/2-r[i]<<17)/((C[i]+=C[i]<5)+.1)>>17,a[y]+=n[y]*(U-A/h))),x=x*2+U)for(p='010202103203210431053105410642065206541'.split(A=0).map((i,y)=>(t=0,[...i].map((i,y)=>(t=t*997+(c[e-i]|0)|0)),h*512-1&t*997+x)*12+y);o<h*512;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<<13,[0,0,0,0,0,0,0,0,0,0,0,0],new Uint16Array(51e6).fill(1<<11),new Uint8Array(51e6),0,0,0))</script>
1
+ <!DOCTYPE html><head>
2
+ <title>Little JS Electron Demo</title>
3
+ <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
4
+ <meta name=apple-mobile-web-app-capable content=yes>
5
+ <meta name=mobile-web-app-capable content=yes>
6
+ <link rel=icon type=image/png href=../favicon.png>
7
+ </head><body>
8
+
9
+ <!-- LittleJS Engine -->
10
+ <script src=../../build/littlejs.js?1691></script>
11
+
12
+ <!-- Add your game scripts here -->
13
+ <script src=game.js?1691></script>
@@ -3,15 +3,17 @@
3
3
  "version": "1.0.0",
4
4
  "description": "A minimal Electron application",
5
5
  "main": "electron.js",
6
- "scripts": {},
6
+ "scripts": {
7
+ "build": "node build.js"
8
+ },
7
9
  "repository": "https://github.com/electron/electron-quick-start",
8
10
  "keywords": [
9
11
  "Electron",
10
12
  "LittleJS",
11
13
  "Game"
12
14
  ],
13
- "author": "GitHub",
14
- "license": "CC0-1.0",
15
+ "author": "Frank Force",
16
+ "license": "MIT",
15
17
  "devDependencies": {
16
18
  "electron": "~25.2.0",
17
19
  "electron-packager": "~17.1.1"
@@ -1,5 +1,7 @@
1
1
  /*
2
- LittleJS Empty Project Example
2
+ Little JS Hello World Demo
3
+ - Just prints "Hello World!"
4
+ - A good starting point for new projects
3
5
  */
4
6
 
5
7
  'use strict';
@@ -1,4 +1,4 @@
1
- <html><head>
1
+ <!DOCTYPE html><head>
2
2
  <title>Little JS Hello World Demo</title>
3
3
  </head><body>
4
4
 
@@ -0,0 +1,2 @@
1
+ rem LittleJS Build Script
2
+ call node build.js
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * LittleJS Build System
5
+ */
6
+
7
+ const PROGRAM_NAME = 'game';
8
+ const BUILD_FOLDER = 'build';
9
+ const sourceFiles =
10
+ [
11
+ '../../build/littlejs.release.js',
12
+ 'game.js',
13
+ // add your game's files here
14
+ ];
15
+ const dataFiles =
16
+ [
17
+ 'tiles.png',
18
+ // add your game's data files here
19
+ ];
20
+
21
+ console.log(`Building ${PROGRAM_NAME}...`);
22
+ const startTime = Date.now();
23
+ const fs = require('node:fs');
24
+ const child_process = require('node:child_process');
25
+
26
+ // rebuild engine
27
+ child_process.execSync(`npm run build`, { stdio: 'inherit' });
28
+
29
+ // remove old files and setup build folder
30
+ fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
31
+ fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
32
+ fs.mkdirSync(BUILD_FOLDER);
33
+
34
+ // copy data files
35
+ for(const file of dataFiles)
36
+ fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
37
+
38
+ Build
39
+ (
40
+ `${BUILD_FOLDER}/index.js`,
41
+ sourceFiles,
42
+ [closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, zipBuildStep]
43
+ );
44
+
45
+ console.log(``);
46
+ console.log(`Build Completed in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
47
+ console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(`${PROGRAM_NAME}.zip`).size} bytes`);
48
+
49
+ ///////////////////////////////////////////////////////////////////////////////
50
+
51
+ // A single build with its own source files, build steps, and output file
52
+ // - each build step is a callback that accepts a single filename
53
+ function Build(outputFile, files=[], buildSteps=[])
54
+ {
55
+ // copy files into a buffer
56
+ let buffer = '';
57
+ for (const file of files)
58
+ buffer += fs.readFileSync(file) + '\n';
59
+
60
+ // output file
61
+ fs.writeFileSync(outputFile, buffer, {flag: 'w+'});
62
+
63
+ // execute build steps in order
64
+ for (const buildStep of buildSteps)
65
+ buildStep(outputFile);
66
+ }
67
+
68
+ function closureCompilerStep(filename)
69
+ {
70
+ console.log(`Running closure compiler...`);
71
+
72
+ const filenameTemp = filename + '.tmp';
73
+ fs.copyFileSync(filename, filenameTemp);
74
+ child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --language_out=ECMASCRIPT_2021 --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
75
+ fs.rmSync(filenameTemp);
76
+ };
77
+
78
+ function uglifyBuildStep(filename)
79
+ {
80
+ console.log(`Running uglify...`);
81
+ child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
82
+ };
83
+
84
+ function roadrollerBuildStep(filename)
85
+ {
86
+ console.log(`Running roadroller...`);
87
+ child_process.execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
88
+ };
89
+
90
+ function htmlBuildStep(filename)
91
+ {
92
+ console.log(`Building html...`);
93
+
94
+ // create html file
95
+ let buffer = '';
96
+ buffer += '<script>';
97
+ buffer += fs.readFileSync(filename);
98
+ buffer += '</script>';
99
+
100
+ // output html file
101
+ fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
102
+ };
103
+
104
+ function zipBuildStep(filename)
105
+ {
106
+ console.log(`Zipping...`);
107
+ const ect = '../../../node_modules/ect-bin/vendor/win32/ect.exe';
108
+ const args = ['-9', '-strip', '-zip', `../${PROGRAM_NAME}.zip`, 'index.html', ...dataFiles];
109
+ child_process.spawnSync(ect, args, {stdio: 'inherit', cwd: BUILD_FOLDER});
110
+ };
@@ -0,0 +1,109 @@
1
+ /*
2
+ LittleJS JS13K Starter Game
3
+ - For size limited projects
4
+ - Builds to 7kb zip file
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ // sound effects
10
+ const sound_click = new Sound([1,.5]);
11
+
12
+ // game variables
13
+ let particleEmitter;
14
+
15
+ // webgl can be disabled to save even more space
16
+ //glEnable = false;
17
+
18
+ ///////////////////////////////////////////////////////////////////////////////
19
+ function gameInit()
20
+ {
21
+ // create tile collision and visible tile layer
22
+ initTileCollision(vec2(32, 16));
23
+ const pos = vec2();
24
+ const tileLayer = new TileLayer(pos, tileCollisionSize);
25
+
26
+ // get level data from the tiles image
27
+ const imageLevelDataRow = 1;
28
+ mainContext.drawImage(tileImage, 0, 0);
29
+ for (pos.x = tileCollisionSize.x; pos.x--;)
30
+ for (pos.y = tileCollisionSize.y; pos.y--;)
31
+ {
32
+ const imageData = mainContext.getImageData(pos.x, 16*(imageLevelDataRow+1)-pos.y-1, 1, 1).data;
33
+ if (imageData[0])
34
+ {
35
+ const tileIndex = 1;
36
+ const direction = randInt(4)
37
+ const mirror = randInt(2);
38
+ const color = randColor();
39
+ const data = new TileLayerData(tileIndex, direction, mirror, color);
40
+ tileLayer.setData(pos, data);
41
+ setTileCollisionData(pos, 1);
42
+ }
43
+ }
44
+ tileLayer.redraw();
45
+
46
+ // move camera to center of collision
47
+ cameraPos = tileCollisionSize.scale(.5);
48
+
49
+ // enable gravity
50
+ gravity = -.01;
51
+
52
+ // create particle emitter
53
+ particleEmitter = new ParticleEmitter(
54
+ vec2(16), 0, // emitPos, emitAngle
55
+ 1, 0, 500, PI, // emitSize, emitTime, emitRate, emiteCone
56
+ 0, vec2(16), // tileIndex, tileSize
57
+ new Color(1,1,1), new Color(0,0,0), // colorStartA, colorStartB
58
+ new Color(1,1,1,0), new Color(0,0,0,0), // colorEndA, colorEndB
59
+ 2, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
60
+ .99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
61
+ .05, .5, 1, 1 // fadeRate, randomness, collide, additive
62
+ );
63
+ particleEmitter.elasticity = .3; // bounce when it collides
64
+ particleEmitter.trailScale = 2; // stretch in direction of motion
65
+ }
66
+
67
+ ///////////////////////////////////////////////////////////////////////////////
68
+ function gameUpdate()
69
+ {
70
+ if (mouseWasPressed(0))
71
+ {
72
+ // play sound when mouse is pressed
73
+ sound_click.play(mousePos);
74
+
75
+ // change particle color and set to fade out
76
+ particleEmitter.colorStartA = new Color;
77
+ particleEmitter.colorStartB = randColor();
78
+ particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1,0);
79
+ particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1,0);
80
+ }
81
+
82
+ // move particles to mouse location if on screen
83
+ if (mousePosScreen.x)
84
+ particleEmitter.pos = mousePos;
85
+ }
86
+
87
+ ///////////////////////////////////////////////////////////////////////////////
88
+ function gameUpdatePost()
89
+ {
90
+
91
+ }
92
+
93
+ ///////////////////////////////////////////////////////////////////////////////
94
+ function gameRender()
95
+ {
96
+ // draw a grey square in the background without using webgl
97
+ drawRect(cameraPos, tileCollisionSize.add(vec2(5)), new Color(.2,.2,.2), 0, 0);
98
+ }
99
+
100
+ ///////////////////////////////////////////////////////////////////////////////
101
+ function gameRenderPost()
102
+ {
103
+ // draw to overlay canvas for hud rendering
104
+ drawTextScreen('LittleJS JS13K Project', vec2(mainCanvasSize.x/2, 80), 80);
105
+ }
106
+
107
+ ///////////////////////////////////////////////////////////////////////////////
108
+ // Startup LittleJS Engine
109
+ engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, 'tiles.png');
@@ -0,0 +1,18 @@
1
+ <head><title>LittleJS JS13K Project</title></head>
2
+
3
+ <!-- LittleJS Engine -->
4
+ <script src=../../src/engineDebug.js?1691></script>
5
+ <script src=../../src/engineUtilities.js?1691></script>
6
+ <script src=../../src/engineSettings.js?1691></script>
7
+ <script src=../../src/engineObject.js?1691></script>
8
+ <script src=../../src/engineDraw.js?1691></script>
9
+ <script src=../../src/engineInput.js?1691></script>
10
+ <script src=../../src/engineAudio.js?1691></script>
11
+ <script src=../../src/engineTileLayer.js?1691></script>
12
+ <script src=../../src/engineParticles.js?1691></script>
13
+ <script src=../../src/engineMedals.js?1691></script>
14
+ <script src=../../src/engineWebGL.js?1691></script>
15
+ <script src=../../src/engine.js?1691></script>
16
+
17
+ <!-- Add your game scripts here -->
18
+ <script src=game.js?1691></script>
Binary file
@@ -1,5 +1,7 @@
1
1
  /*
2
- LittleJS Hello World Starter Game
2
+ Little JS Module Demo
3
+ - A simple starter project
4
+ - Shows how to use LittleJS with modules
3
5
  */
4
6
 
5
7
  'use strict';
@@ -16,14 +18,14 @@ const medal_example = new LittleJS.Medal(0, 'Example Medal', 'Welcome to LittleJ
16
18
  LittleJS.medalsInit('Hello World');
17
19
 
18
20
  // game variables
19
- let particleEmiter;
21
+ let particleEmiter, gameTimer;
20
22
 
21
23
  ///////////////////////////////////////////////////////////////////////////////
22
24
  function gameInit()
23
25
  {
24
26
  // create tile collision and visible tile layer
25
27
  LittleJS.initTileCollision(vec2(32, 16));
26
- const pos = vec2();
28
+ const pos = new Vector2;
27
29
  const tileLayer = new LittleJS.TileLayer(pos, LittleJS.tileCollisionSize);
28
30
 
29
31
  // get level data from the tiles image
@@ -67,6 +69,10 @@ function gameInit()
67
69
  );
68
70
  particleEmiter.elasticity = .3; // bounce when it collides
69
71
  particleEmiter.trailScale = 2; // stretch in direction of motion
72
+
73
+ // start the game timer
74
+ gameTimer = new Timer;
75
+ gameTimer.set();
70
76
  }
71
77
 
72
78
  ///////////////////////////////////////////////////////////////////////////////
@@ -1,4 +1,4 @@
1
- <html><head>
1
+ <!DOCTYPE html><head>
2
2
  <title>Little JS Module Demo</title>
3
3
  <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
4
4
  <meta name=apple-mobile-web-app-capable content=yes>
@@ -7,4 +7,4 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- Add your game scripts here -->
10
- <script src=game.js?166 type=module></script>
10
+ <script src=game.js?1691 type=module></script>
@@ -1,22 +1,16 @@
1
- <html><head>
1
+ <!DOCTYPE html><head>
2
2
  <title>Little JS Particle System Designer</title>
3
3
  <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
4
4
  <meta name=apple-mobile-web-app-capable content=yes>
5
5
  <meta name=mobile-web-app-capable content=yes>
6
6
  <link rel=icon type=image/png href=../favicon.png>
7
7
  <style>
8
- input
9
- {
10
- width:99px;
11
- }
12
- button
13
- {
14
- margin:1px;
15
- }
8
+ input { width:99px; }
9
+ button { margin:1px; }
16
10
  </style>
17
11
  </head><body>
18
12
 
19
- <script src=../../build/littlejs.js?166></script>
13
+ <script src=../../build/littlejs.js?1691></script>
20
14
  <script>
21
15
 
22
16
  'use strict';
@@ -80,7 +74,7 @@ function gameInit()
80
74
 
81
75
  const div = particleSystemDiv = document.createElement('div');
82
76
  div.innerHTML = '<big><b>LittleJS Particle Tool';
83
- div.style = 'position:absolute;top:10;left:10;color:#fff';
77
+ div.style = 'position:absolute;top:10px;left:10px;color:#fff';
84
78
  document.body.appendChild(div);
85
79
 
86
80
  for (const setting of particleSettings)
@@ -184,8 +178,8 @@ function gameInit()
184
178
  //div.appendChild(document.createTextNode('JavaScript Code... '));
185
179
  div.appendChild(document.createElement('br'));
186
180
  div.appendChild(particleSystemCode = document.createElement('textarea'));
187
- particleSystemCode.style.width = 500;
188
- particleSystemCode.style.height = 100;
181
+ particleSystemCode.style.width = '500px';
182
+ particleSystemCode.style.height = '100px';
189
183
  particleSystemCode.disabled = true;
190
184
 
191
185
  updateInputs(0);
@@ -1,6 +1,9 @@
1
1
  /*
2
- LittleJS Platformer Example
3
- - A platforming starter game with destructibe terrain
2
+ Little JS Platforming Game
3
+ - A basic platforming starter project
4
+ - Platforming phyics and controls
5
+ - Includes destructibe terrain
6
+ - Control with keyboard, mouse, touch, or gamepad
4
7
  */
5
8
 
6
9
  'use strict';