littlejsengine 1.24.3 → 1.26.0

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 (53) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/EDITOR.md +2 -2
  3. package/FAQ.md +55 -11
  4. package/README.md +6 -2
  5. package/REFERENCE.md +203 -57
  6. package/dist/littlejs.d.ts +933 -313
  7. package/dist/littlejs.esm.js +5143 -2419
  8. package/dist/littlejs.esm.min.js +38 -24
  9. package/dist/littlejs.js +5132 -2416
  10. package/dist/littlejs.min.js +37 -23
  11. package/dist/littlejs.release.js +4905 -2232
  12. package/package.json +4 -4
  13. package/plugins/box2d.js +141 -56
  14. package/plugins/drawUtilities.js +374 -380
  15. package/plugins/gltf.js +383 -60
  16. package/plugins/lightSystem.js +412 -30
  17. package/plugins/math3d.js +1015 -1014
  18. package/plugins/medalSystem.js +19 -7
  19. package/plugins/newgrounds.js +5 -6
  20. package/plugins/parallax.js +1 -0
  21. package/plugins/particleEffects.js +47 -14
  22. package/plugins/pathFinder.js +60 -38
  23. package/plugins/pluginExport.js +11 -0
  24. package/plugins/postProcess.js +200 -67
  25. package/plugins/render3d.js +493 -2391
  26. package/plugins/render3dDebug.js +5 -8
  27. package/plugins/render3dEditor.js +84 -9
  28. package/plugins/render3dExtras.js +122 -33
  29. package/plugins/render3dLevel.js +67 -8
  30. package/plugins/render3dMesh.js +1158 -0
  31. package/plugins/render3dObject.js +1451 -0
  32. package/plugins/render3dVoxels.js +15 -3
  33. package/plugins/textureSheet.js +9 -8
  34. package/plugins/threejs.js +1 -1
  35. package/plugins/tweenSystem.js +117 -87
  36. package/plugins/uiSystem.js +62 -28
  37. package/plugins/wavedash.js +229 -0
  38. package/src/engine.js +192 -40
  39. package/src/engineAudio.js +47 -27
  40. package/src/engineBuild.mjs +6 -1
  41. package/src/engineDebug.js +23 -162
  42. package/src/engineDraw.js +148 -43
  43. package/src/engineEditor.js +153 -40
  44. package/src/engineExport.js +0 -3
  45. package/src/engineInput.js +31 -25
  46. package/src/engineMath.js +38 -20
  47. package/src/engineObject.js +68 -50
  48. package/src/engineParticles.js +66 -18
  49. package/src/engineRelease.js +18 -15
  50. package/src/engineSettings.js +48 -9
  51. package/src/engineTileLayer.js +44 -18
  52. package/src/engineUtilities.js +56 -11
  53. package/src/engineWebGL.js +68 -22
@@ -15,6 +15,17 @@
15
15
 
16
16
  const LEVEL3D_VERSION = 1; // the format a level's littlejs3D names
17
17
 
18
+ /** A 3D level as it is saved, what level3DLoad takes and the 3D level editor edits
19
+ * @typedef {Object} Level3D
20
+ * @property {number} [littlejs3D] - The format's version, 1
21
+ * @property {Array<Object>} objects - Each {id, type, pos, rotation, scale, properties}, all but type optional
22
+ * @property {Object} [scene] - The scene block: sky, ambient, sunDirection, sunColor, fog, fogColor, shadows, lensFlare,
23
+ * skyBox, environment
24
+ * @property {Object} [voxels] - A block map: {pos, size, blocks}
25
+ * @property {Object} [terrain] - A height map: {pos, size, height, color, heights, paint}
26
+ * @property {Object} [prefabs] - The level's own prefabs by name, each {objects, attached}
27
+ * @memberof Level3D */
28
+
18
29
  // the types a level's objects are made from, by name
19
30
  const level3DTypes = new Map;
20
31
 
@@ -33,7 +44,7 @@ const level3DBaseScale = new WeakMap;
33
44
  * - Adding a name again replaces it, Box, Sphere, Cylinder and Light too
34
45
  * @param {string} name - The type the objects have in the level
35
46
  * @param {Function} make - A class made at each object's position, or a function called with it
36
- * @param {Object} [defaults] - Properties of each one made, the level editor shows inputs for them
47
+ * @param {Object<string, any>} [defaults] - Properties of each one made, the level editor shows inputs for them
37
48
  * @param {TileInfo} [tileInfo] - An icon for the level editor
38
49
  * @memberof Level3D
39
50
  * @example
@@ -84,10 +95,11 @@ function level3DAddMesh(name, mesh, tileInfo, color=WHITE)
84
95
  * are added before its objects are made, one the game added itself keeps its place
85
96
  * - A level may set the scene too, in a scene block beside its objects: sky, three colors for straight up, the
86
97
  * horizon and straight down, ambient, how much of them lights the scene, .5 when not given, sunDirection and
87
- * sunColor, fog, its start and end, fogColor, the horizon color when not given, shadows, and lensFlare, the
88
- * sun's lens flare; what the block leaves out stays as the game set it, and a level with no block changes
89
- * nothing
90
- * @param {Object} level - The level, the level editor edits this same object
98
+ * sunColor, fog, its start and end, fogColor, the horizon color when not given, shadows, lensFlare, the
99
+ * sun's lens flare, and skyBox and environment, each six image urls as loadCubeMap takes them, which load in
100
+ * the background and are set when they have; what the block leaves out stays as the game set it, and a level
101
+ * with no block changes nothing
102
+ * @param {Level3D} level - The level, the level editor edits this same object
91
103
  * @return {Array<any>} - What each object's type made, a function that made nothing is left out
92
104
  * @memberof Level3D */
93
105
  function level3DLoad(level)
@@ -290,6 +302,8 @@ const level3DSkies = new WeakSet;
290
302
  // and shadows; a setting the block does not have, or has wrong, stays as it is
291
303
  function level3DSceneApply(scene)
292
304
  {
305
+ // a sky box or environment an earlier scene is still loading does not land on this one's
306
+ ++level3DSceneCubeLoads.skyBox, ++level3DSceneCubeLoads.environment;
293
307
  const r = render3D;
294
308
  if (!r || !scene || typeof scene !== 'object') return;
295
309
  const color = level3DHexColor;
@@ -316,6 +330,47 @@ function level3DSceneApply(scene)
316
330
  r.shadows = scene.shadows;
317
331
  if (typeof scene.lensFlare === 'boolean')
318
332
  level3DSceneFlare(scene.lensFlare);
333
+ level3DSceneCubeMap('skyBox', scene.skyBox);
334
+ level3DSceneCubeMap('environment', scene.environment);
335
+ }
336
+
337
+ // the cube maps scene blocks loaded, by their six urls, the four used last, so the same ones load once; a load that
338
+ // failed is not kept, and is tried again by the next scene that names it
339
+ const level3DSceneCubeMaps = new Map;
340
+ const level3DSceneCubeLoaded = new WeakMap; // the cube map each of their loads gave, once it has
341
+
342
+ // which load each of render3D.skyBox and environment waits for: every scene applied, or the editor putting the
343
+ // game's back, moves it on, and a load that finishes after is dropped
344
+ const level3DSceneCubeLoads = {skyBox: 0, environment: 0};
345
+
346
+ // load the six urls a scene block gives for render3D.skyBox or environment and set it when they have loaded; a value
347
+ // that is not six strings leaves it as it is, and a failed load says so and leaves it too
348
+ function level3DSceneCubeMap(field, urls)
349
+ {
350
+ if (!isArray(urls) || urls.length !== 6 || !urls.every((url)=> typeof url === 'string')) return;
351
+ const key = urls.join('\n'), load = ++level3DSceneCubeLoads[field], before = render3D[field];
352
+ // kept by the urls, newest last: one used again moves to the end, and past four the oldest goes, its texture
353
+ // freed unless it is still on screen
354
+ let cube = level3DSceneCubeMaps.get(key);
355
+ level3DSceneCubeMaps.delete(key);
356
+ level3DSceneCubeMaps.set(key, cube ||= loadCubeMap(urls));
357
+ cube.then((map)=> level3DSceneCubeLoaded.set(cube, map), ()=> {});
358
+ for (const [oldKey, old] of level3DSceneCubeMaps)
359
+ {
360
+ if (level3DSceneCubeMaps.size <= 4) break;
361
+ // one on screen stays, so it is not loaded again and the copy on screen left behind
362
+ const map = level3DSceneCubeLoaded.get(old);
363
+ if (map && (map === render3D.skyBox || map === render3D.environment)) continue;
364
+ level3DSceneCubeMaps.delete(oldKey);
365
+ old.then((map)=> map !== render3D.skyBox && map !== render3D.environment && map.dispose(), ()=> {});
366
+ }
367
+ // set when it has loaded, unless a newer scene came, or the game set the field itself meanwhile
368
+ const landed = (map)=> load === level3DSceneCubeLoads[field] && render3D[field] === before && (render3D[field] = map);
369
+ cube.then(landed, (error)=>
370
+ {
371
+ level3DSceneCubeMaps.get(key) === cube && level3DSceneCubeMaps.delete(key);
372
+ console.warn(error.message);
373
+ });
319
374
  }
320
375
 
321
376
  // the sun's lens flare as a scene sets it: on makes one unless the sun has a flare already, the game's own or an
@@ -420,7 +475,7 @@ function level3DMakeAt(object, pos, rotation, scale)
420
475
  * @param {Vector3} [pos3D]
421
476
  * @param {Vector3} [rotation3D] - In radians, as an object has it
422
477
  * @param {Vector3} [scale3D] - Times the scale the type makes it with
423
- * @param {Object} [properties] - Over the type's defaults
478
+ * @param {Object<string, any>} [properties] - Over the type's defaults
424
479
  * @return {any} - What the type made, a Prefab3D for a prefab, undefined when there is no such type
425
480
  * @memberof Level3D
426
481
  * @example
@@ -459,7 +514,8 @@ const level3DPrefabMaking = [];
459
514
  * by hand does
460
515
  * - Adding a name again replaces it
461
516
  * @param {string} name - The type its instances have in a level
462
- * @param {Object} prefab - {objects, attached}
517
+ * @param {{objects: Array<Object>, attached?: boolean}} prefab - Its objects, about its own origin, and whether
518
+ * they are attached
463
519
  * @memberof Level3D
464
520
  * @example
465
521
  * level3DAddPrefab('Tower', {objects: [{type: 'Box', pos: [0, 1, 0], scale: [2, 2, 2]},
@@ -533,12 +589,14 @@ class Prefab3D extends EngineObject3D
533
589
  this.prefabName = prefabName;
534
590
  /** @property {boolean} - Are its parts its children, moving with it as one body */
535
591
  this.attached = !!level3DPrefabs.get(prefabName)?.attached || level3DPrefabAttached > 0;
536
- /** @property {Array<any>} - What the prefab's objects made, in the prefab's order */
592
+ /** @property {Array<EngineObject3D>} - What the prefab's objects made, in the prefab's order
593
+ * @type {Array<EngineObject3D>} */
537
594
  this.parts = [];
538
595
  /** @property {Vector3} - From the prefab's origin to the handle, in the prefab's own space: nothing for
539
596
  * separate parts, and for an attached prefab the middle of the box around its parts, where its handle
540
597
  * is, as an object's place is the middle of its body */
541
598
  this.originOffset = vec3();
599
+ /** @type {Array<{id?: number, type: string, pos?: Array<number>, rotation?: Array<number>, scale?: Array<number>|number, properties?: Object}>} */
542
600
  this.partObjects = []; // the prefab's object of each part
543
601
  this.partsPlaced = ''; // where the handle was when its parts were last placed, undefined parts not made
544
602
  this.partsMade = false;
@@ -630,6 +688,7 @@ class Prefab3D extends EngineObject3D
630
688
  for (const part of children)
631
689
  {
632
690
  part.pos3D = part.pos3D.subtract(this.originOffset);
691
+ render3DShareSettings(part, this); // drawn with what is set on the handle, its own otherwise
633
692
  this.addChild(part);
634
693
  }
635
694
  }