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.
Files changed (48) hide show
  1. package/AI.md +162 -0
  2. package/README.md +50 -63
  3. package/dist/littlejs.d.ts +150 -68
  4. package/dist/littlejs.esm.js +323 -105
  5. package/dist/littlejs.esm.min.js +1 -1
  6. package/dist/littlejs.js +320 -104
  7. package/dist/littlejs.min.js +1 -1
  8. package/dist/littlejs.release.js +318 -101
  9. package/examples/electron/{build.js → build.mjs} +26 -23
  10. package/examples/electron/game.js +5 -50
  11. package/examples/electron/index.html +2 -2
  12. package/examples/index.html +1 -0
  13. package/examples/module/{build.js → build.mjs} +22 -19
  14. package/examples/shorts/base.html +1 -1
  15. package/examples/shorts/hillGlideGame.js +1 -1
  16. package/examples/shorts/nineSlice.js +3 -3
  17. package/examples/shorts/shapes.js +1 -1
  18. package/examples/shorts/uiSystem.js +17 -16
  19. package/examples/starter/build.bat +1 -1
  20. package/examples/starter/{build.js → build.mjs} +25 -22
  21. package/examples/starter/index.html +2 -2
  22. package/examples/typescript/build.mjs +60 -0
  23. package/examples/typescript/game.js +2 -2
  24. package/examples/typescript/tsconfig.json +11 -2
  25. package/package.json +2 -2
  26. package/plugins/pluginExport.js +1 -0
  27. package/plugins/uiSystem.js +143 -20
  28. package/reference.md +0 -1
  29. package/src/engine.js +16 -14
  30. package/src/engineAudio.js +9 -6
  31. package/src/{engineBuild.js → engineBuild.mjs} +95 -78
  32. package/src/engineDebug.js +8 -5
  33. package/src/engineDraw.js +16 -14
  34. package/src/engineExport.js +2 -1
  35. package/src/engineInput.js +29 -8
  36. package/src/engineMath.js +46 -14
  37. package/src/engineMedals.js +6 -3
  38. package/src/engineObject.js +14 -3
  39. package/src/engineParticles.js +8 -3
  40. package/src/engineRelease.js +6 -2
  41. package/src/engineTileLayer.js +8 -4
  42. package/src/engineUtilities.js +6 -2
  43. package/src/engineWebGL.js +11 -8
  44. package/src/jsconfig.json +2 -1
  45. package/examples/electron/build.bat +0 -7
  46. package/examples/module/build.bat +0 -7
  47. package/examples/typescript/build.bat +0 -5
  48. package/examples/typescript/build.js +0 -31
@@ -1,19 +1,24 @@
1
- #!/usr/bin/env node
2
-
3
1
  /**
4
2
  * LittleJS Build System
5
3
  */
6
4
 
7
5
  'use strict';
8
6
 
7
+ import { fileURLToPath } from 'node:url';
8
+ import { dirname, join } from 'node:path';
9
+ import fs from 'node:fs';
10
+ import { execSync } from 'node:child_process';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+
9
14
  const PROGRAM_TITLE = 'Little JS Electron Project';
10
15
  const PROGRAM_NAME = 'game';
11
- const BUILD_FOLDER = 'build';
16
+ const BUILD_FOLDER = join(__dirname, 'build');
12
17
  const USE_ROADROLLER = false; // enable for extra compression
13
18
  const sourceFiles =
14
19
  [
15
- '../../dist/littlejs.release.js',
16
- 'game.js',
20
+ join(__dirname, '../../dist/littlejs.release.js'),
21
+ join(__dirname, 'game.js'),
17
22
  // add your game's files here
18
23
  ];
19
24
  const dataFiles =
@@ -24,24 +29,22 @@ const dataFiles =
24
29
 
25
30
  console.log(`Building ${PROGRAM_NAME}...`);
26
31
  const startTime = Date.now();
27
- const fs = require('node:fs');
28
- const child_process = require('node:child_process');
29
32
 
30
33
  // rebuild engine
31
- //child_process.execSync(`npm run build`, { stdio: 'inherit' });
34
+ //execSync(`npm run build`, { stdio: 'inherit' });
32
35
 
33
36
  // remove old files and setup build folder
34
37
  fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
35
- fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
38
+ fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
36
39
  fs.mkdirSync(BUILD_FOLDER);
37
40
 
38
41
  // copy data files
39
42
  for (const file of dataFiles)
40
- fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
43
+ fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
41
44
 
42
45
  Build
43
46
  (
44
- `${BUILD_FOLDER}/index.js`,
47
+ join(BUILD_FOLDER, 'index.js'),
45
48
  sourceFiles,
46
49
  USE_ROADROLLER ?
47
50
  [closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, electronBuildStep] :
@@ -77,21 +80,21 @@ function closureCompilerStep(filename)
77
80
  // use closer compiler to minify the code
78
81
  const filenameTemp = filename + '.tmp';
79
82
  fs.copyFileSync(filename, filenameTemp);
80
- child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
83
+ execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
81
84
  fs.rmSync(filenameTemp);
82
- };
85
+ }
83
86
 
84
87
  function uglifyBuildStep(filename)
85
88
  {
86
89
  console.log('Running uglify...');
87
- child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
88
- };
90
+ execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
91
+ }
89
92
 
90
93
  function roadrollerBuildStep(filename)
91
94
  {
92
95
  console.log('Running roadroller...');
93
- child_process.execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
94
- };
96
+ execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
97
+ }
95
98
 
96
99
  function htmlBuildStep(filename)
97
100
  {
@@ -108,17 +111,17 @@ function htmlBuildStep(filename)
108
111
  buffer += `<script src='index.js'></script>`;
109
112
 
110
113
  // output html file
111
- fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
112
- };
114
+ fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
115
+ }
113
116
 
114
117
  function electronBuildStep(filename)
115
118
  {
116
119
  console.log('Building executable with electron...');
117
120
 
118
121
  // copy elecron files to build folder
119
- fs.copyFileSync('electron.js', `${BUILD_FOLDER}/electron.js`);
120
- fs.copyFileSync('package.json', `${BUILD_FOLDER}/package.json`);
122
+ fs.copyFileSync(join(__dirname, 'electron.js'), join(BUILD_FOLDER, 'electron.js'));
123
+ fs.copyFileSync(join(__dirname, 'package.json'), join(BUILD_FOLDER, 'package.json'));
121
124
 
122
125
  // run electron packager
123
- child_process.execSync(`npx electron-packager ./${BUILD_FOLDER} --overwrite`, {stdio: 'inherit'});
124
- };
126
+ execSync(`npx electron-packager "${BUILD_FOLDER}" --overwrite --out="${__dirname}"`, {stdio: 'inherit'});
127
+ }
@@ -10,47 +10,13 @@
10
10
  // show the LittleJS splash screen
11
11
  setShowSplashScreen(true);
12
12
 
13
- // fix texture bleeding by shrinking tile slightly
14
- setTileDefaultBleed(.5);
15
-
16
13
  // sound effects
17
14
  const sound_click = new Sound([1,.5]);
18
15
 
19
16
  ///////////////////////////////////////////////////////////////////////////////
20
17
  function gameInit()
21
18
  {
22
- // create tile collision and visible tile layer
23
- const pos = vec2();
24
- const tileLayer = new TileCollisionLayer(pos, vec2(32,16));
25
-
26
- // get level data from the tiles image
27
- const tileImage = textureInfos[0].image;
28
- mainContext.drawImage(tileImage,0,0);
29
- const imageData = mainContext.getImageData(0,0,tileImage.width,tileImage.height).data;
30
- for (pos.x = tileLayer.size.x; pos.x--;)
31
- for (pos.y = tileLayer.size.y; pos.y--;)
32
- {
33
- // check if this pixel is set
34
- const i = pos.x + tileImage.width*(15 + tileLayer.size.y - pos.y);
35
- if (!imageData[4*i])
36
- continue;
37
-
38
- // set tile data
39
- const tileIndex = 1;
40
- const direction = randInt(4)
41
- const mirror = randBool();
42
- const color = randColor();
43
- const data = new TileLayerData(tileIndex, direction, mirror, color);
44
- tileLayer.setData(pos, data);
45
- tileLayer.setCollisionData(pos);
46
- }
47
-
48
- // draw tile layer with new data
49
- tileLayer.redraw();
50
-
51
- // setup camera
52
- setCameraPos(vec2(16,8));
53
- setCameraScale(32);
19
+ setCanvasClearColor(GRAY);
54
20
  }
55
21
 
56
22
  ///////////////////////////////////////////////////////////////////////////////
@@ -61,37 +27,26 @@ function gameUpdate()
61
27
  // play sound when mouse is pressed
62
28
  sound_click.play(mousePos);
63
29
  }
64
-
65
- if (mouseWheel)
66
- {
67
- // zoom in and out with mouse wheel
68
- cameraScale -= sign(mouseWheel)*cameraScale/5;
69
- cameraScale = clamp(cameraScale, 10, 300);
70
- }
71
30
  }
72
31
 
73
32
  ///////////////////////////////////////////////////////////////////////////////
74
33
  function gameUpdatePost()
75
34
  {
76
-
77
35
  }
78
36
 
79
37
  ///////////////////////////////////////////////////////////////////////////////
80
38
  function gameRender()
81
39
  {
82
- // draw a grey square in the background
83
- drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6));
84
-
85
40
  // draw the logo as a tile
86
- drawTile(vec2(21,5), vec2(4.5), tile(3,128));
41
+ drawTile(vec2(sin(time)*4, 0), vec2(10), tile(3,128));
87
42
  }
88
43
 
89
44
  ///////////////////////////////////////////////////////////////////////////////
90
45
  function gameRenderPost()
91
46
  {
92
- drawTextScreen('LittleJS Electron Demo',
93
- vec2(mainCanvasSize.x/2, 70), 80, // position, size
94
- hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
47
+ drawTextScreen('LittleJS\nElectron Demo',
48
+ vec2(mainCanvasSize.x/2, 100), 80, // position, size
49
+ hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
95
50
  }
96
51
 
97
52
  ///////////////////////////////////////////////////////////////////////////////
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.17.11></script>
10
+ <script src=../../dist/littlejs.js></script>
11
11
 
12
12
  <!-- Add your game scripts here -->
13
- <script src=game.js?1.17.11></script>
13
+ <script src=game.js></script>
@@ -58,6 +58,7 @@ Theme:
58
58
  <select id=selectExample onchange=setExample() size=2></select>
59
59
  </div>
60
60
  </div>
61
+ <a href="https://github.com/KilledByAPixel/LittleJS" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#70B7FD; color:#fff; position: absolute; top: 0; border: 0; left: 0; transform: scale(-1, 1);" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
61
62
  <script>
62
63
  'use strict';
63
64
 
@@ -1,20 +1,25 @@
1
- #!/usr/bin/env node
2
-
3
1
  /**
4
2
  * LittleJS Build System
5
3
  */
6
4
 
7
5
  'use strict';
8
6
 
7
+ import { fileURLToPath } from 'node:url';
8
+ import { dirname, join } from 'node:path';
9
+ import fs from 'node:fs';
10
+ import { execSync } from 'node:child_process';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+
9
14
  const PROGRAM_TITLE = 'Little JS Starter Project';
10
15
  const PROGRAM_NAME = 'game';
11
- const BUILD_FOLDER = 'build';
16
+ const BUILD_FOLDER = join(__dirname, 'build');
12
17
  const sourceFiles =
13
18
  [
14
19
  'game.js',
15
20
  // add your game's source files here
16
21
  ];
17
- const engineFile = '../../dist/littlejs.esm.min.js'; // Use the minified ES module
22
+ const engineFile = join(__dirname, '../../dist/littlejs.esm.min.js'); // Use the minified ES module
18
23
  const dataFiles =
19
24
  [
20
25
  'tiles.png',
@@ -23,23 +28,21 @@ const dataFiles =
23
28
 
24
29
  console.log(`Building ${PROGRAM_NAME}...`);
25
30
  const startTime = Date.now();
26
- const fs = require('node:fs');
27
- const child_process = require('node:child_process');
28
31
 
29
32
  // rebuild engine
30
- //child_process.execSync(`npm run build`, { stdio: 'inherit' });
33
+ //execSync(`npm run build`, { stdio: 'inherit' });
31
34
 
32
35
  // remove old files and setup build folder
33
36
  fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
34
- fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
37
+ fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
35
38
  fs.mkdirSync(BUILD_FOLDER);
36
39
 
37
40
  // copy data files
38
41
  for (const file of dataFiles)
39
- fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
42
+ fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
40
43
 
41
44
  // copy engine module
42
- fs.copyFileSync(engineFile, `${BUILD_FOLDER}/littlejs.esm.min.js`);
45
+ fs.copyFileSync(engineFile, join(BUILD_FOLDER, 'littlejs.esm.min.js'));
43
46
 
44
47
  Build
45
48
  (
@@ -59,8 +62,8 @@ function Build(files=[], buildSteps=[])
59
62
  // process each source file separately (don't concatenate modules!)
60
63
  for (const file of files)
61
64
  {
62
- const outputFile = `${BUILD_FOLDER}/${file}`;
63
- fs.copyFileSync(file, outputFile);
65
+ const outputFile = join(BUILD_FOLDER, file);
66
+ fs.copyFileSync(join(__dirname, file), outputFile);
64
67
  moduleFixStep(outputFile);
65
68
  uglifyBuildStep(outputFile);
66
69
  }
@@ -89,8 +92,8 @@ function moduleFixStep(filename)
89
92
  function uglifyBuildStep(filename)
90
93
  {
91
94
  console.log('Running uglify...');
92
- child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
93
- };
95
+ execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
96
+ }
94
97
 
95
98
  function htmlBuildStep()
96
99
  {
@@ -108,14 +111,14 @@ function htmlBuildStep()
108
111
  buffer += '</body>';
109
112
 
110
113
  // output html file
111
- fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
112
- };
114
+ fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
115
+ }
113
116
 
114
117
  function zipBuildStep()
115
118
  {
116
119
  console.log('Zipping...');
117
120
  const sources = ['index.html', 'littlejs.esm.min.js', ...sourceFiles, ...dataFiles];
118
121
  const sourceList = sources.join(' ');
119
- child_process.execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
120
- console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(`${PROGRAM_NAME}.zip`).size} bytes`);
121
- };
122
+ execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
123
+ console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(join(__dirname, `${PROGRAM_NAME}.zip`)).size} bytes`);
124
+ }
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1.17.11></script>
2
+ <script src=../../dist/littlejs.js?1.17.15></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
@@ -57,7 +57,7 @@ function gameRender()
57
57
  pos.y = getGroundHeight(x);
58
58
  drawRect(pos, sizeTop, BLACK);
59
59
  pos.y -= h/2;
60
- color.setHSLA(.2+.2*wave(.2,1,x), .7, .5);
60
+ color.setHSLA(.2+.2*oscillate(.2,1,x), .7, .5);
61
61
  drawRect(pos, size, color);
62
62
  }
63
63
  }
@@ -6,7 +6,7 @@ function gameRender()
6
6
  {
7
7
  // draw nine slice with thin border and color
8
8
  const pos = vec2(-7,4);
9
- const size = vec2(11+wave(.5,2), 6);
9
+ const size = vec2(11+oscillate(.5,2), 6);
10
10
  const color = hsl(.1,.5,.9);
11
11
  const border = .5;
12
12
  drawNineSlice(pos, size, nineSliceTile, color, border);
@@ -25,7 +25,7 @@ function gameRender()
25
25
  // draw three slice with variable border and additive color
26
26
  const pos = vec2(-7,-4);
27
27
  const size = vec2(9, 7);
28
- const border = 2 + wave(.2)*2;
28
+ const border = 2 + oscillate(.2)*2;
29
29
  const additive = hsl(time/30,.5,.5);
30
30
  drawThreeSlice(pos, size, threeSliceTile, WHITE, border, additive);
31
31
  drawText('Three Slice\nVariable\nBorder', pos, 1, BLACK);
@@ -33,7 +33,7 @@ function gameRender()
33
33
  {
34
34
  // draw three slice in screen space with changing size
35
35
  const pos = vec2(700,420);
36
- const size = vec2(350-wave(.3,90),120+wave(.3,60));
36
+ const size = vec2(350-oscillate(.3,90),120+oscillate(.3,60));
37
37
  drawThreeSliceScreen(pos, size, threeSliceTile);
38
38
  drawTextScreen('Three Slice\nScreen Space', pos, 30, BLACK);
39
39
  }
@@ -2,7 +2,7 @@ function gameRender()
2
2
  {
3
3
  // circles and ellipses
4
4
  drawEllipse(vec2(-6,5), vec2(3,2), YELLOW, .5);
5
- drawCircle(vec2(0,5), 2+wave(.5), RED);
5
+ drawCircle(vec2(0,5), 2+oscillate(.5), RED);
6
6
  drawEllipse(vec2(6,5), vec2(2,4), CLEAR_BLACK, .3, .5, CYAN)
7
7
 
8
8
  // polygon shapes
@@ -9,43 +9,44 @@ function gameInit()
9
9
 
10
10
  // setup example menu
11
11
  let navigationIndex = 0;
12
- const uiMenu = new UIObject(mainCanvasSize.scale(.5), vec2(600,450));
12
+ const uiMenu = new UIObject(mainCanvasSize.scale(.5), vec2(700,450));
13
13
  canvasClearColor = hsl(0,0,.8);
14
14
 
15
15
  // example text
16
- uiMenu.addChild(new UIText(vec2(-80,-120), vec2(400, 80),
16
+ uiMenu.addChild(new UIText(vec2(-100,-120), vec2(450, 80),
17
17
  'LittleJS UI\nSystem Demo'));
18
18
 
19
19
  // example image
20
- uiMenu.addChild(new UITile(vec2(200,-140), vec2(128), tile(3, 128)));
20
+ uiMenu.addChild(new UITile(vec2(230,-140), vec2(170), tile(3, 128)));
21
21
 
22
22
  // example checkbox
23
- const checkbox = new UICheckbox(vec2(-80,0), vec2(50));
23
+ const checkbox = new UICheckbox(vec2(-170,0), vec2(50));
24
24
  checkbox.navigationIndex = ++navigationIndex;
25
25
  checkbox.onChange = ()=> button1.disabled = checkbox.checked;
26
26
  uiMenu.addChild(checkbox);
27
27
 
28
28
  // example button
29
- const button1 = new UIButton(vec2(80,0), vec2(140, 80), 'Test');
30
- button1.textHeight = 60;
31
- button1.navigationIndex = ++navigationIndex;
32
- uiMenu.addChild(button1);
33
- button1.onClick = ()=> canvasClearColor = randColor();
29
+ const textInput = new UITextInput(vec2(50,0), vec2(300, 80), 'Text Input');
30
+ textInput.textHeight = 60;
31
+ textInput.maxLength = 16;
32
+ textInput.navigationIndex = ++navigationIndex;
33
+ uiMenu.addChild(textInput);
34
+ textInput.onChange = ()=> canvasClearColor = randColor();
34
35
 
35
36
  // example scrollbar
36
- const scrollbar = new UIScrollbar(vec2(0,90), vec2(300, 50),
37
+ const scrollbar = new UIScrollbar(vec2(0,90), vec2(400, 50),
37
38
  soundVolume, 'Volume');
38
39
  scrollbar.navigationIndex = ++navigationIndex;
39
40
  uiMenu.addChild(scrollbar);
40
41
  scrollbar.onChange = ()=> setSoundVolume(scrollbar.value);
41
42
 
42
43
  // exit button
43
- const button2 = new UIButton(vec2(0,170), vec2(300, 50), 'Exit Menu');
44
- button2.textHeight = 40;
45
- button2.navigationIndex = ++navigationIndex;
46
- button2.navigationAutoSelect = true;
47
- uiMenu.addChild(button2);
48
- button2.onClick = ()=> uiSystem.showConfirmDialog('Exit menu?',
44
+ const button1 = new UIButton(vec2(0,170), vec2(200, 50), 'Exit Menu');
45
+ button1.textHeight = 40;
46
+ button1.navigationIndex = ++navigationIndex;
47
+ button1.navigationAutoSelect = true;
48
+ uiMenu.addChild(button1);
49
+ button1.onClick = ()=> uiSystem.showConfirmDialog('Exit menu?',
49
50
  ()=> { uiMenu.visible=false; buttonBack.visible=true; });
50
51
 
51
52
  // example button that returns to menu
@@ -1,5 +1,5 @@
1
1
  rem LittleJS Build Script
2
- call node build.js
2
+ call node build.mjs
3
3
  if %errorlevel% neq 0 (
4
4
  echo Build failed with error level %errorlevel%
5
5
  pause
@@ -1,19 +1,24 @@
1
- #!/usr/bin/env node
2
-
3
1
  /**
4
2
  * LittleJS Build System
5
3
  */
6
4
 
7
5
  'use strict';
8
6
 
7
+ import { fileURLToPath } from 'node:url';
8
+ import { dirname, join } from 'node:path';
9
+ import fs from 'node:fs';
10
+ import { execSync } from 'node:child_process';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+
9
14
  const PROGRAM_TITLE = 'Little JS Starter Project';
10
15
  const PROGRAM_NAME = 'game';
11
- const BUILD_FOLDER = 'build';
16
+ const BUILD_FOLDER = join(__dirname, 'build');
12
17
  const USE_ROADROLLER = false; // enable for extra compression
13
18
  const sourceFiles =
14
19
  [
15
- '../../dist/littlejs.release.js',
16
- 'game.js',
20
+ join(__dirname, '../../dist/littlejs.release.js'),
21
+ join(__dirname, 'game.js'),
17
22
  // add your game's files here
18
23
  ];
19
24
  const dataFiles =
@@ -24,24 +29,22 @@ const dataFiles =
24
29
 
25
30
  console.log(`Building ${PROGRAM_NAME}...`);
26
31
  const startTime = Date.now();
27
- const fs = require('node:fs');
28
- const child_process = require('node:child_process');
29
32
 
30
33
  // rebuild engine
31
- //child_process.execSync(`npm run build`, { stdio: 'inherit' });
34
+ //execSync(`npm run build`, { stdio: 'inherit' });
32
35
 
33
36
  // remove old files and setup build folder
34
37
  fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
35
- fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
38
+ fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
36
39
  fs.mkdirSync(BUILD_FOLDER);
37
40
 
38
41
  // copy data files
39
42
  for (const file of dataFiles)
40
- fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
43
+ fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
41
44
 
42
45
  Build
43
46
  (
44
- `${BUILD_FOLDER}/index.js`,
47
+ join(BUILD_FOLDER, 'index.js'),
45
48
  sourceFiles,
46
49
  USE_ROADROLLER ?
47
50
  [closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, zipBuildStep] :
@@ -77,21 +80,21 @@ function closureCompilerStep(filename)
77
80
  // use closer compiler to minify the code
78
81
  const filenameTemp = filename + '.tmp';
79
82
  fs.copyFileSync(filename, filenameTemp);
80
- child_process.execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
83
+ execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
81
84
  fs.rmSync(filenameTemp);
82
- };
85
+ }
83
86
 
84
87
  function uglifyBuildStep(filename)
85
88
  {
86
89
  console.log('Running uglify...');
87
- child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
88
- };
90
+ execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
91
+ }
89
92
 
90
93
  function roadrollerBuildStep(filename)
91
94
  {
92
95
  console.log('Running roadroller...');
93
- child_process.execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
94
- };
96
+ execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
97
+ }
95
98
 
96
99
  function htmlBuildStep(filename)
97
100
  {
@@ -110,14 +113,14 @@ function htmlBuildStep(filename)
110
113
  buffer += '</script>';
111
114
 
112
115
  // output html file
113
- fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
114
- };
116
+ fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
117
+ }
115
118
 
116
119
  function zipBuildStep(filename)
117
120
  {
118
121
  console.log('Zipping...');
119
122
  const sources = ['index.html', ...dataFiles];
120
123
  const sourceList = sources.join(' ');
121
- child_process.execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
122
- console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(`${PROGRAM_NAME}.zip`).size} bytes`);
123
- };
124
+ execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
125
+ console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(join(__dirname, `${PROGRAM_NAME}.zip`)).size} bytes`);
126
+ }
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.17.11></script>
10
+ <script src=../../dist/littlejs.js?1.17.15></script>
11
11
 
12
12
  <!-- LittleJS Engine Source
13
13
  <script src=../../src/engine.js></script>
@@ -32,4 +32,4 @@
32
32
  -->
33
33
 
34
34
  <!-- Add your game scripts here -->
35
- <script src=game.js?1.17.11></script>
35
+ <script src=game.js?1.17.15></script>
@@ -0,0 +1,60 @@
1
+ /**
2
+ * LittleJS TypeScript Example Build System
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ import { fileURLToPath } from 'node:url';
8
+ import { dirname, join } from 'node:path';
9
+ import fs from 'node:fs';
10
+ import { execSync } from 'node:child_process';
11
+
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ const PROGRAM_NAME = 'game';
14
+ const BUILD_FOLDER = join(__dirname, 'build');
15
+
16
+ // Define TypeScript source files
17
+ const tsSourceFiles = [
18
+ 'game.ts',
19
+ // add your TypeScript files here
20
+ ];
21
+
22
+ // Corresponding JS output files
23
+ const jsSourceFiles = tsSourceFiles.map(file => file.replace('.ts', '.js'));
24
+
25
+ console.log(`Building TypeScript for ${PROGRAM_NAME}...`);
26
+ const startTime = Date.now();
27
+
28
+ console.log(`Removing old build folder...`);
29
+ fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
30
+
31
+ console.log(`Compiling TypeScript...`);
32
+
33
+ // Use tsconfig.json for compilation settings
34
+ try
35
+ {
36
+ const result = execSync(`npx -p typescript tsc`, {cwd: __dirname, encoding: 'utf8', stdio: 'pipe'});
37
+ console.log(result);
38
+ } catch (error)
39
+ {
40
+ console.error('TypeScript compilation errors:');
41
+ if (error.stdout) console.log(error.stdout);
42
+ if (error.stderr) console.error(error.stderr);
43
+ console.error('TypeScript compilation failed!');
44
+ process.exit(1);
45
+ }
46
+
47
+ console.log(`Copying js files back to root...`);
48
+ for (const file of jsSourceFiles)
49
+ {
50
+ // TypeScript outputs to build/examples/typescript/ because of relative paths
51
+ const buildFile = join(BUILD_FOLDER, 'examples', 'typescript', file);
52
+ const targetFile = join(__dirname, file);
53
+ console.log(`Copying ${file}...`);
54
+ if (fs.existsSync(buildFile))
55
+ fs.copyFileSync(buildFile, targetFile);
56
+ else
57
+ console.error(`✗ Build file not found: ${buildFile}`);
58
+ }
59
+
60
+ console.log(`TypeScript built in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
@@ -61,7 +61,7 @@ function gameInit() {
61
61
  .05, .5, true, true // fadeRate, randomness, collide, additive
62
62
  );
63
63
  particleEmitter.restitution = .3; // bounce when it collides
64
- particleEmitter.trailScale = 2; // stretch as it moves
64
+ particleEmitter.trailScale = 2; // stretch stretch as it moves
65
65
  particleEmitter.velocityInheritance = .3; // inherit emitter velocity
66
66
  }
67
67
  ///////////////////////////////////////////////////////////////////////////////
@@ -97,4 +97,4 @@ function gameRenderPost() {
97
97
  }
98
98
  ///////////////////////////////////////////////////////////////////////////////
99
99
  // Startup LittleJS Engine
100
- LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
100
+ LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);