littlejsengine 1.17.1 → 1.17.5

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.
@@ -126,7 +126,7 @@ export class CarObject extends LJS.Box2dObject
126
126
  const maxTorque = 35;
127
127
  const sprite = Game.spriteAtlas.wheel;
128
128
  this.wheels = [];
129
- const makeWheel = (pos, isMotor) =>
129
+ const makeWheel = (pos, isMotor)=>
130
130
  {
131
131
  const wheel = new LJS.Box2dObject(pos, vec2(diameter), sprite);
132
132
  const joint = new LJS.Box2dWheelJoint(this, wheel);
@@ -284,7 +284,7 @@ export class SoftBodyObject extends LJS.Box2dObject
284
284
  for (let x=sizeCount.x; x--;)
285
285
  {
286
286
  const o = this.getNode(x, y);
287
- const tryAddJoint = (xo, yo) =>
287
+ const tryAddJoint = (xo, yo)=>
288
288
  {
289
289
  const o2 = this.getNode(x+xo, y+yo);
290
290
  const joint = o2 ? new LJS.Box2dWeldJoint(o, o2) : 0;
@@ -360,7 +360,7 @@ export class ClothObject extends LJS.Box2dStaticObject
360
360
  const d = y%2 ? 1 : -1;
361
361
  const x2 = d>1 ? x : sizeCount.x-1-x;
362
362
  const o = this.getNode(x2, y);
363
- const tryAddJoint = (xo, yo) =>
363
+ const tryAddJoint = (xo, yo)=>
364
364
  {
365
365
  const o2 = this.getNode(x2+xo, y+yo);
366
366
  const joint = o2 ? new LJS.Box2dRopeJoint(o, o2) : 0;
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.17.1></script>
10
+ <script src=../../dist/littlejs.js?1.17.5></script>
11
11
 
12
12
  <!-- Add your game scripts here -->
13
- <script src=game.js?1.17.1></script>
13
+ <script src=game.js?1.17.5></script>
@@ -127,7 +127,8 @@ const exampleList =
127
127
  new ExampleInfo('--- PLUGINS ---'),
128
128
  new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
129
129
  new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
130
- new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with physics', false, 'objects, game'),
130
+ new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with Box2d physics', false, 'objects, game'),
131
+ new ExampleInfo('Box2d Tile Layer', 'box2dTileLayer.js', 'Tile layer with Box2d physics', false, 'objects, level, map, grid'),
131
132
  new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
132
133
  new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters', false, 'webgl, visual, effect'),
133
134
  new ExampleInfo('UI System', 'uiSystem.js', 'Buttons, sliders, and checkboxes', false, 'objects, widgets, interactive'),
@@ -159,7 +160,7 @@ function initExampleBrowser()
159
160
  // set the selected example from the URL parameters
160
161
  const urlParams = new URLSearchParams(window.location.search);
161
162
  const selectedExample = urlParams.get('example') || '';
162
- let exampleIndex = exampleList.findIndex((example) => example.name === selectedExample);
163
+ let exampleIndex = exampleList.findIndex((example)=> example.name === selectedExample);
163
164
  if (exampleIndex < 0)
164
165
  exampleIndex = 1;
165
166
  selectExample.selectedIndex = exampleIndex;
@@ -398,7 +399,7 @@ function codeInput()
398
399
  // debounce input - get content from code mirror if available, otherwise from textarea
399
400
  clearTimeout(inputTimeout);
400
401
  const code = codeMirror ? codeMirror.getValue() : textareaCode.value;
401
- inputTimeout = setTimeout(() => setCode(code), 500);
402
+ inputTimeout = setTimeout(()=> setCode(code), 500);
402
403
  }
403
404
 
404
405
  function restartCode()
@@ -453,7 +454,7 @@ function setCode(code, filename)
453
454
  const anonymousMatch = stack?.match(/(<anonymous>|injectedScript):(\d+)/);
454
455
  return anonymousMatch ? parseInt(anonymousMatch[2]) : -1;
455
456
  }
456
- iframeContent.onerror = (message, source, lineno, colno, error) =>
457
+ iframeContent.onerror = (message, source, lineno, colno, error)=>
457
458
  {
458
459
  let text = message;
459
460
  if (lineno)
@@ -463,7 +464,7 @@ function setCode(code, filename)
463
464
  setErrorMessage(text);
464
465
  setErrorLine(lineno);
465
466
  }
466
- iframeContent.onunhandledrejection = (event) =>
467
+ iframeContent.onunhandledrejection = (event)=>
467
468
  {
468
469
  let text = event.reason;
469
470
  setErrorMessage(text);
@@ -510,14 +511,14 @@ function setCode(code, filename)
510
511
 
511
512
  {
512
513
  // hook up buttons
513
- buttonScreenshot.onclick = () =>
514
+ buttonScreenshot.onclick = ()=>
514
515
  {
515
516
  if (iframeContent.debugScreenshot)
516
517
  iframeContent.debugScreenshot();
517
518
  }
518
519
 
519
520
  // pause/resume functionality
520
- buttonPause.onclick = () =>
521
+ buttonPause.onclick = ()=>
521
522
  {
522
523
  if (!iframeContent.getPaused || !iframeContent.setPaused)
523
524
  return;
@@ -0,0 +1,7 @@
1
+ rem LittleJS Build Script
2
+ call node build.js
3
+ if %errorlevel% neq 0 (
4
+ echo Build failed with error level %errorlevel%
5
+ pause
6
+ exit /b %errorlevel%
7
+ )
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * LittleJS Build System
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const PROGRAM_TITLE = 'Little JS Starter Project';
10
+ const PROGRAM_NAME = 'game';
11
+ const BUILD_FOLDER = 'build';
12
+ const sourceFiles =
13
+ [
14
+ 'game.js',
15
+ // add your game's source files here
16
+ ];
17
+ const engineFile = '../../dist/littlejs.esm.min.js'; // Use the minified ES module
18
+ const dataFiles =
19
+ [
20
+ 'tiles.png',
21
+ // add your game's data files here
22
+ ];
23
+
24
+ console.log(`Building ${PROGRAM_NAME}...`);
25
+ const startTime = Date.now();
26
+ const fs = require('node:fs');
27
+ const child_process = require('node:child_process');
28
+
29
+ // rebuild engine
30
+ //child_process.execSync(`npm run build`, { stdio: 'inherit' });
31
+
32
+ // remove old files and setup build folder
33
+ fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
34
+ fs.rmSync(`${PROGRAM_NAME}.zip`, { force: true });
35
+ fs.mkdirSync(BUILD_FOLDER);
36
+
37
+ // copy data files
38
+ for (const file of dataFiles)
39
+ fs.copyFileSync(file, `${BUILD_FOLDER}/${file}`);
40
+
41
+ // copy engine module
42
+ fs.copyFileSync(engineFile, `${BUILD_FOLDER}/littlejs.esm.min.js`);
43
+
44
+ Build
45
+ (
46
+ sourceFiles,
47
+ [htmlBuildStep, zipBuildStep]
48
+ );
49
+
50
+ console.log('');
51
+ console.log(`Build Completed in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
52
+
53
+ ///////////////////////////////////////////////////////////////////////////////
54
+
55
+ // A single build with its own source files, build steps, and output file
56
+ // - each build step is a callback that accepts a single filename
57
+ function Build(files=[], buildSteps=[])
58
+ {
59
+ // process each source file separately (don't concatenate modules!)
60
+ for (const file of files)
61
+ {
62
+ const outputFile = `${BUILD_FOLDER}/${file}`;
63
+ fs.copyFileSync(file, outputFile);
64
+ moduleFixStep(outputFile);
65
+ uglifyBuildStep(outputFile);
66
+ }
67
+
68
+ // execute build steps in order
69
+ for (const buildStep of buildSteps)
70
+ buildStep();
71
+ }
72
+
73
+ function moduleFixStep(filename)
74
+ {
75
+ console.log(`Fixing module imports in ${filename}...`);
76
+
77
+ let code = fs.readFileSync(filename, 'utf8');
78
+
79
+ // update the import path to use the local minified version
80
+ code = code.replace(/import \* as LJS from ['"].*littlejs\.esm(?:\.min)?\.js['"];?/g,
81
+ "import * as LJS from './littlejs.esm.min.js';");
82
+
83
+ // also fix relative imports to other game modules
84
+ code = code.replace(/from ['"]\.\.\//g, "from './");
85
+
86
+ fs.writeFileSync(filename, code);
87
+ }
88
+
89
+ function uglifyBuildStep(filename)
90
+ {
91
+ console.log('Running uglify...');
92
+ child_process.execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
93
+ };
94
+
95
+ function htmlBuildStep()
96
+ {
97
+ console.log('Building html...');
98
+
99
+ // create html file with module script tag pointing to main game file
100
+ let buffer = ''
101
+ buffer += '<!DOCTYPE html>';
102
+ buffer += '<head>';
103
+ buffer += `<title>${PROGRAM_TITLE}</title>`;
104
+ buffer += '<meta charset=utf-8>';
105
+ buffer += '</head>';
106
+ buffer += '<body>';
107
+ buffer += '<script src="game.js" type="module"></script>';
108
+ buffer += '</body>';
109
+
110
+ // output html file
111
+ fs.writeFileSync(`${BUILD_FOLDER}/index.html`, buffer, {flag: 'w+'});
112
+ };
113
+
114
+ function zipBuildStep()
115
+ {
116
+ console.log('Zipping...');
117
+ const sources = ['index.html', 'littlejs.esm.min.js', ...sourceFiles, ...dataFiles];
118
+ 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
+ };
@@ -127,7 +127,7 @@ function gameRender()
127
127
  function gameRenderPost()
128
128
  {
129
129
  // draw to main canvas for hud rendering
130
- const drawText = (text, x, y, size=40) =>
130
+ const drawText = (text, x, y, size=40)=>
131
131
  {
132
132
  const context = LJS.mainContext;
133
133
  context.textAlign = 'center';
@@ -15,9 +15,6 @@ import * as LJS from '../../dist/littlejs.esm.js';
15
15
  import * as GameLevel from './gameLevel.js';
16
16
  const {vec2, hsl, rgb} = LJS;
17
17
 
18
- // use low graphics mode on mobile devices
19
- const lowGraphicsMode = LJS.isTouchDevice;
20
-
21
18
  ///////////////////////////////////////////////////////////////////////////////
22
19
  // sound effects
23
20
 
@@ -36,8 +33,6 @@ export const sound_score = new LJS.Sound([,,783,,.03,.02,1,2,,,940,.03,,,
36
33
 
37
34
  export const persistentParticleDestroyCallback = (particle)=>
38
35
  {
39
- if (lowGraphicsMode) return;
40
-
41
36
  // draw particle to tile layer on death
42
37
  LJS.ASSERT(!particle.tileInfo, 'quick draw to tile layer uses canvas 2d so must be untextured');
43
38
  if (particle.groundObject)
@@ -158,7 +153,7 @@ export function destroyTile(pos, makeSound = 1, cleanup = 1)
158
153
  makeSound && sound_destroyObject.play(centerPos);
159
154
 
160
155
  // set and clear tile
161
- layer.setData(pos, new LJS.TileLayerData, true);
156
+ layer.clearData(pos, true);
162
157
  layer.setCollisionData(pos, GameLevel.tileType_empty);
163
158
 
164
159
  // cleanup neighbors and rebuild WebGL
@@ -199,7 +194,7 @@ export class Sky extends LJS.EngineObject
199
194
  // draw stars
200
195
  LJS.setBlendMode(true);
201
196
  const random = new LJS.RandomGenerator(this.seed);
202
- for (let i= lowGraphicsMode ? 500 : 1e3; i--;)
197
+ for (let i = 1e3; i--;)
203
198
  {
204
199
  const size = random.float(.5,2)**2;
205
200
  const speed = random.float() < .9 ? random.float(5) : random.float(9,99);
@@ -96,8 +96,8 @@ function loadLevelData()
96
96
  new GameObjects.Coin(objectPos);
97
97
 
98
98
  // replace with empty tile and empty collision
99
- tileLayer.setData(pos, new LJS.TileLayerData);
100
- tileLayer.setCollisionData(pos, 0);
99
+ tileLayer.clearData(pos);
100
+ tileLayer.clearCollisionData(pos);
101
101
  continue;
102
102
  }
103
103
 
@@ -151,7 +151,7 @@ export function decorateTile(pos, tileLayer)
151
151
  if (tileType <= 0)
152
152
  {
153
153
  // force it to clear if it is empty
154
- tileType || tileLayer.setData(pos, new LJS.TileLayerData, 1);
154
+ tileType || tileLayer.clearData(pos, true);
155
155
  return;
156
156
  }
157
157
  if (tileType == tileType_breakable)
@@ -44,8 +44,8 @@ const tileColors =
44
44
  ];
45
45
  const tileTypeCount = tileColors.length;
46
46
 
47
- const getTile = (pos) => level[pos.x + pos.y * levelSize.x];
48
- const setTile = (pos, data) => level[pos.x + pos.y * levelSize.x] = data;
47
+ const getTile = (pos)=> level[pos.x + pos.y * levelSize.x];
48
+ const setTile = (pos, data)=> level[pos.x + pos.y * levelSize.x] = data;
49
49
 
50
50
  ///////////////////////////////////////////////////////////////////////////////
51
51
  function gameReset()
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1.17.1></script>
2
+ <script src=../../dist/littlejs.js?1.17.5></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
@@ -38,6 +38,9 @@ canvasPixelated = false;
38
38
  // disable watermark
39
39
  debugWatermark = false;
40
40
 
41
+ // disable showing the engine version in console
42
+ showEngineVersion = false;
43
+
41
44
  // these functions can be overridden for each example
42
45
  function gameInit() {}
43
46
  function gameUpdate() {}
@@ -3,10 +3,10 @@ const maxHitDistance = 6;
3
3
 
4
4
  class Ball extends Box2dObject
5
5
  {
6
- constructor(position, number=0)
6
+ constructor(pos, number=0)
7
7
  {
8
8
  const color = hsl(number/9, 1, number? .5 : 1);
9
- super(position, vec2(), 0, 0, color);
9
+ super(pos, vec2(), 0, 0, color);
10
10
  this.number = number;
11
11
 
12
12
  // setup pool ball physics
@@ -0,0 +1,48 @@
1
+ let box2DTileLayer;
2
+
3
+ async function gameInit()
4
+ {
5
+ // setup box2d
6
+ await box2dInit();
7
+ cameraPos = vec2(16); // setup camera
8
+ gravity.y = -30; // enable gravity
9
+ canvasClearColor = hsl(0,0,.2); // background color
10
+
11
+ // create tile layer
12
+ const pos = vec2();
13
+ const tileLayer = new TileCollisionLayer(pos, vec2(32));
14
+ for (pos.x = tileLayer.size.x; pos.x--;)
15
+ for (pos.y = tileLayer.size.y; pos.y--;)
16
+ {
17
+ // check if tile should be solid
18
+ if (randBool(.7))
19
+ continue;
20
+
21
+ // set tile data
22
+ const tileIndex = 11;
23
+ const direction = randInt(4)
24
+ const mirror = randBool();
25
+ const color = randColor(WHITE, hsl(0,0,.2));
26
+ const data = new TileLayerData(tileIndex, direction, mirror, color);
27
+ tileLayer.setData(pos, data);
28
+ tileLayer.setCollisionData(pos);
29
+ }
30
+ tileLayer.redraw(); // redraw tile layer with new data
31
+ box2DTileLayer = new Box2dTileLayer(tileLayer);
32
+ }
33
+
34
+ function gameUpdate()
35
+ {
36
+ if (mouseWasPressed(0))
37
+ {
38
+ // clear tile that was clicked
39
+ box2DTileLayer.tileLayer.clearData(mousePos, true);
40
+ box2DTileLayer.tileLayer.clearCollisionData(mousePos);
41
+ box2DTileLayer.buildCollision();
42
+
43
+ // spawn box2d object at mouse position
44
+ const o = new Box2dObject(mousePos, vec2(), 0, 0, randColor());
45
+ const friction = .2, restitution = .5;
46
+ o.addCircle(rand(.5,1), vec2(), 1, friction, restitution);
47
+ }
48
+ }
@@ -1,4 +1,4 @@
1
- const musicSound = new SoundWave('song.mp3');
1
+ const musicSound = new Sound('song.mp3');
2
2
  let musicVolume = 1, musicInstance;
3
3
 
4
4
  function gameInit()
@@ -23,7 +23,7 @@ function gameInit()
23
23
  const volumeSlider = new UIScrollbar(vec2(0, -20), vec2(400, 30),
24
24
  musicVolume, 'Music Volume');
25
25
  musicPlayer.addChild(volumeSlider);
26
- volumeSlider.onChange = () =>
26
+ volumeSlider.onChange = ()=>
27
27
  {
28
28
  musicVolume = volumeSlider.value;
29
29
  musicInstance?.setVolume(musicVolume);
@@ -29,7 +29,7 @@ function gameInit()
29
29
  const volumeSlider = new UIScrollbar(vec2(0, -20), vec2(400, 30),
30
30
  musicVolume, 'Music Volume');
31
31
  musicPlayer.addChild(volumeSlider);
32
- volumeSlider.onChange = () =>
32
+ volumeSlider.onChange = ()=>
33
33
  {
34
34
  musicVolume = volumeSlider.value;
35
35
  musicInstance?.setVolume(musicVolume);
@@ -89,7 +89,7 @@ function gameInit()
89
89
 
90
90
  // create new sound from dropped file
91
91
  const fileURL = URL.createObjectURL(file);
92
- musicSound = new SoundWave(fileURL, musicVolume);
92
+ musicSound = new Sound(fileURL, musicVolume);
93
93
  dropZoneText.text = file.name;
94
94
 
95
95
  // reset UI
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.17.1></script>
10
+ <script src=../../dist/littlejs.js?1.17.5></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.1></script>
35
+ <script src=game.js?1.17.5></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.17.1",
3
+ "version": "1.17.5",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
@@ -34,11 +34,11 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "bestzip": "^2.2.1",
37
+ "electron": "^38.2.0",
38
+ "electron-packager": "^17.1.2",
37
39
  "google-closure-compiler": "~20230502.0.0",
38
40
  "roadroller": "~2.1.0",
39
41
  "typescript": "~5.1.6",
40
- "uglify-js": "~3.17.4",
41
- "electron": "^38.2.0",
42
- "electron-packager": "^17.1.2"
42
+ "uglify-js": "~3.17.4"
43
43
  }
44
- }
44
+ }