littlejsengine 1.24.1 → 1.24.2
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.
- package/CHANGELOG.md +59 -1
- package/EDITOR.md +2 -0
- package/FAQ.md +13 -2
- package/README.md +1 -1
- package/REFERENCE.md +20 -6
- package/dist/littlejs.d.ts +77 -13
- package/dist/littlejs.esm.js +2395 -1939
- package/dist/littlejs.esm.min.js +3 -3
- package/dist/littlejs.js +2392 -1939
- package/dist/littlejs.min.js +2 -2
- package/dist/littlejs.release.js +2356 -1952
- package/package.json +1 -1
- package/plugins/gltf.js +62 -9
- package/plugins/lightSystem.js +1 -1
- package/plugins/math3d.js +1014 -1013
- package/plugins/medalSystem.js +7 -11
- package/plugins/particleEffects.js +2 -2
- package/plugins/pathFinder.js +2 -2
- package/plugins/pluginExport.js +1 -0
- package/plugins/render3d.js +131 -55
- package/plugins/render3dEditor.js +24 -10
- package/plugins/render3dExtras.js +29 -17
- package/plugins/render3dLevel.js +21 -12
- package/plugins/render3dVoxels.js +2 -2
- package/plugins/textureSheet.js +97 -3
- package/plugins/tweakables.js +1 -1
- package/plugins/tweenSystem.js +2 -2
- package/plugins/uiSystem.js +6 -2
- package/src/engine.js +34 -11
- package/src/engineAudio.js +13 -3
- package/src/engineDebug.js +4 -1
- package/src/engineDraw.js +29 -16
- package/src/engineEditor.js +82 -50
- package/src/engineExport.js +2 -0
- package/src/engineInput.js +17 -3
- package/src/engineMath.js +6 -2
- package/src/engineObject.js +675 -675
- package/src/engineParticles.js +1 -1
- package/src/engineSettings.js +16 -0
- package/src/engineTileLayer.js +85 -22
- package/src/engineUtilities.js +20 -8
- package/src/engineWebGL.js +12 -8
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,60 @@ What changed in each release, newest first. Releases before 1.20.0 are on the
|
|
|
7
7
|
|
|
8
8
|
Nothing yet.
|
|
9
9
|
|
|
10
|
+
## 1.24.2 - 2026-10-03
|
|
11
|
+
|
|
12
|
+
### New Changes
|
|
13
|
+
|
|
14
|
+
- Tile sets from separate images: `loadTiles(['grass.png', 'brick.png', 'props.png'], 16)` packs tile images, or several tile sheets, into the texture sheets as one tile set, numbered in the order given, for `tileLayersLoad`, tile layers and the level editor's palette; an image that is not whole tiles gives the whole tiles in it, and a map's tileset margin or spacing does not replace the set
|
|
15
|
+
- Spotlight gels: `light.gel` is a picture the shadow casting spotlight shines through, cast along its beam in its colors, like a slide or stained glass; with none a scene draws exactly as before. The 3D First Person flashlight has one on G
|
|
16
|
+
- Less garbage each frame: objects are sorted only when one is out of render order and the destroyed taken out only when there are some, an object with mass that collides with nothing copies no position, and outlines and regular polygons are made into kept vectors, about 98 fewer for each outlined circle; a 3D pick makes no vectors for an object it misses
|
|
17
|
+
- `Mesh.computeNormals(true)` is 5 to 7 times faster, the same normals to the last bit: a 960 point flag in 0.24 ms where it took 1.8, so a mesh can be bent every frame
|
|
18
|
+
- `loadSprite`, `loadTiles` and `loadAtlas` give back what the first load did when the same image is loaded again with the same settings, packed once
|
|
19
|
+
- A release build goes on past an error in a frame, logging the first, where one error froze the game for good; a debug build stops and shows it as before
|
|
20
|
+
|
|
21
|
+
### Fixes
|
|
22
|
+
|
|
23
|
+
- A Tiled property named as a method of the object it is for, like `update`, is left out, where it replaced the method; a debug build says so
|
|
24
|
+
- `noise2D` stays noise however far out y is, where past about 24 million every row was one value; it gives the same values as before everywhere else
|
|
25
|
+
- Medals: the save keeps the unlock of a medal the game has not made this time, and a medal made after `medalsInit` reads its unlock, so a medal made late or behind a flag is never lost; `medalsReset` locks those too
|
|
26
|
+
- Older browsers: the engine starts with no `OffscreenCanvas` (Safari before 16.4), drawing into a canvas element in its place, and so do the textures it makes itself (normal maps from heights, particle shapes, light glows, lens flares, glTF's white texture), and uses neither `Array.prototype.at` nor `Object.hasOwn` (Safari before 15.4); the example browser's markdown has no lookbehind, which Safari before 16.4 could not read
|
|
27
|
+
- On an iPhone the silent switch mutes the game, as it does a ringtone, and the player's music plays on beside it; `setSoundIgnoreSilentSwitch(true)` has the game play through the switch as media does (Safari 16.4 and up)
|
|
28
|
+
- Level editor: the brush, its ghost and the palette read a tile past the end of a sheet as nothing, as the layer draws it, where a collision value picked up with the right button asserted every frame; the palette of a tile set filled in after it was first shown shows its tiles
|
|
29
|
+
- A light's flare looks past four lamps around it to what is behind them, where the fourth counted as hidden
|
|
30
|
+
- A click or tap in the bars around a letterboxed canvas presses nothing, where it pressed whatever was at the canvas edge
|
|
31
|
+
- `showConfirmDialog` while one is open gives the one open, where a second broke UI navigation in release builds
|
|
32
|
+
- The level editor's cut, copy and stamps keep an object's name, size, turn and visibility, where a paste made a bare point; objects moved with a selection or stamped land on their place to the digit, not a hair off
|
|
33
|
+
- The 3D editor's terrain paint rounds no heights, and a sculpt stroke rounds only those it changed
|
|
34
|
+
- A `UISlider` let go in the frame it moves takes that last place
|
|
35
|
+
- A gamepad of fewer buttons put in the slot of another holds none of the other's buttons; a gamepad axis that reads NaN is centered, where it failed an assert in debug builds
|
|
36
|
+
- `UITextInput` takes a keydown with no key, as autofill sends, where it threw
|
|
37
|
+
- `parseOBJ` reads a comment after a face, carriage return line ends and a line carried on with a backslash, and a release build leaves out a face of a vertex the file does not have
|
|
38
|
+
- `tileLayersFromLDtk` keeps a tile layer with no tiles as an empty layer, so a level of one loads and the editor can paint it
|
|
39
|
+
- Level editor: a property set in the box keeps its place and a `file` or `object` property its type; a save leaves out the object layer made for a first object that was undone; a new object layer's id is past every layer's
|
|
40
|
+
- 3D editor: taking a prefab out of the level takes its instances out of the game; a level's parts are saved in one order, so a level reloaded from its autosave saves the same
|
|
41
|
+
- `writeSaveData` asserts its data is an object, which `readSaveData` reads back, and returns whether it was written, false when storage is full or unavailable
|
|
42
|
+
- `parseAtlas` warns of two sprites with one name; `nearestPowerOfTwo` is never less than its value and is 1 for a value of 1 or less; a particle effect's name cut to 60 characters ends with no space
|
|
43
|
+
- A tile layer's raycast toward a point far beyond the layer walks only across the layer, where a ray to a far constant took seconds
|
|
44
|
+
- `debugShowErrors` shows a message as text, so a file name with markup in it can not add elements to the page
|
|
45
|
+
- Canvas2D tints clamp the color to 0 to 1, as WebGL does
|
|
46
|
+
- glTF: the keys of the files given may start with ./ or / or use backslashes, a uri above them is refused, and an accessor that reaches past its buffer is refused before its floats are made
|
|
47
|
+
- A level whose prefab holds itself, several times over, loads at once with that prefab left out where it holds itself, in place of making thousands of objects
|
|
48
|
+
- Small malformed files no longer make a loader run on: an Aseprite tag past its frames keeps to them, a glTF node reached twice and an accessor of millions with no buffer are refused, an LDtk level of millions of cells is refused and a tile or entity with no place is passed by
|
|
49
|
+
- LDtk: an IntGrid layer whose rule tiles are on another tileset keeps its values for collision, its tiles left out with a warning
|
|
50
|
+
- A collision layer named that no layer has says so in release builds too
|
|
51
|
+
- A light's lens flare: its lamp is a mesh around the light that the ray meets near the light and that is thin, so a globe or a lamp post is its own fixture, while a room or a level mesh hides the light, even one close behind its wall
|
|
52
|
+
- VoxelMap: the inside of a doubleSided face is split along the same diagonal as its outside, so it shows no seam
|
|
53
|
+
- glTF: `parseGLTF(data, baseUrl, files)` finds the `.bin` and image files a `.gltf` names among files given, like a drop's, from the model's own folder, or by the file name alone when only one file has it; a file it can not find is named in the error, and an image that can not be read in a warning; the 3D Mesh example takes a `.gltf` dropped with its files or in its folder, and frees the model it replaces
|
|
54
|
+
- Example browser: after the arrow keys move through the list, Enter keeps the example they went to, and Escape in the search clears it without also closing the list
|
|
55
|
+
- 3D levels: a color that is not a string, and a number that is NaN or Infinity (1e999 in JSON), are read as the default, in place of an assert or a NaN
|
|
56
|
+
- `tileLayersLoad` says so when a map is not a whole number of cells across and down, has no layers, or a layer's tiles do not fill it, in release builds too, in place of running on; every layer is checked before any is made. A game that relied on a release build loading such a map anyway now gets the error
|
|
57
|
+
- A tile past the end of a sheet read by its columns draws nothing, as an LDtk IntGrid layer's values past the art did in the level editor, which asserted
|
|
58
|
+
- A tween that loops or ping pongs with a duration of 0 or less, possible in release builds, ends its loops
|
|
59
|
+
|
|
60
|
+
### New Demos
|
|
61
|
+
|
|
62
|
+
- [Custom Editor](https://killedbyapixel.github.io/LittleJS/examples/?example=Custom%20Editor) - A level editor made for one game: a class of its own with a tool that lays out rooms by a drag, a button, a key and an overlay
|
|
63
|
+
|
|
10
64
|
## 1.24.1 - 2026-10-02
|
|
11
65
|
|
|
12
66
|
### New Changes
|
|
@@ -16,7 +70,11 @@ Nothing yet.
|
|
|
16
70
|
- `tileLayersLoad`'s `collisionLayer` may be a layer's name
|
|
17
71
|
- `light.addFlare` takes the flare's color too
|
|
18
72
|
- LDtk: an IntGrid layer is always a hidden layer of its values under its own name, its rule tiles in layers over it named with tiles, so `tileLayersLoad(map, tileInfo, 0, 'Collisions')` is solid where the values say, whatever the tiles stack or fade; a project of several worlds loads; a project with no tileset entry keeps its tiles
|
|
19
|
-
- The example browser has a new look, in the dark colors of the docs site: a slim top bar in place of the title, the demo at 16:9, and the example list as rows under their headings. A handle between the code and its write-up drags to give one the other's space, by touch and the arrow keys too, and is remembered; a double click puts the quarter back. On a phone the example's name, between Prev and Next, opens a full screen picker with the search. The Screenshot button is gone
|
|
73
|
+
- The example browser has a new look, in the dark colors of the docs site: a slim top bar in place of the title, the demo at 16:9, and the example list as rows under their headings. A handle between the code and its write-up drags to give one the other's space, by touch and the arrow keys too, and is remembered; a double click puts the quarter back. On a phone the example's name, between Prev and Next, opens a full screen picker with the search. The Screenshot button is gone. A button in the top bar switches between dark and light, the choice shared with the docs site
|
|
74
|
+
|
|
75
|
+
### Breaking Changes
|
|
76
|
+
|
|
77
|
+
- LDtk: an IntGrid layer with tiles is now a hidden layer of its values under its own name, its tiles in layers named with tiles over it, so the layer indices and names of such a level move; name the collision layer, `tileLayersLoad(map, tileInfo, 0, 'Collisions')`, in place of an index
|
|
20
78
|
|
|
21
79
|
### Fixes
|
|
22
80
|
|
package/EDITOR.md
CHANGED
|
@@ -341,6 +341,8 @@ after a reload.
|
|
|
341
341
|
|
|
342
342
|
## Where the working examples are
|
|
343
343
|
|
|
344
|
+
- `examples/shorts/customEditor.js`: a 2D editor class of a game's own, with a tool that lays out rooms by a
|
|
345
|
+
drag, a button, a key and an overlay drawn in `onDraw`.
|
|
344
346
|
- `examples/shorts/render3dLevelEditor.js`: a 3D level with its own Coin and PlayerStart types and both hooks.
|
|
345
347
|
- `examples/shorts/render3dPrefab.js`: the 3D editor used as a prefab maker.
|
|
346
348
|
- `examples/shorts/levelEditor.js` and `examples/platformer/`: the 2D editor with a game's own types, palette
|
package/FAQ.md
CHANGED
|
@@ -206,6 +206,10 @@ If you are using [Visual Studio Code](https://code.visualstudio.com/) there is a
|
|
|
206
206
|
|
|
207
207
|
Another option is to setup a simple local web server like [http-server](https://www.npmjs.com/package/http-server) via npm.
|
|
208
208
|
|
|
209
|
+
### Which browsers does LittleJS run in?
|
|
210
|
+
|
|
211
|
+
Current Chrome, Edge, Firefox and Safari, on desktop and on phones. The oldest it aims to support is Safari 15 (iOS 15) and the other browsers from 2021 on. Where WebGL2 is missing, 2D games fall back to Canvas2D rendering on their own; the 3D plugin needs WebGL2.
|
|
212
|
+
|
|
209
213
|
### How does the camera and world coordinate systems work?
|
|
210
214
|
|
|
211
215
|
LittleJS drawing functions are all handled in world coordinates by default.
|
|
@@ -263,6 +267,13 @@ Plugins are self-contained features that live alongside the engine but aren't pa
|
|
|
263
267
|
| `newgrounds.js` | Newgrounds.io integration (medals held on the server, scoreboards) |
|
|
264
268
|
| `audioEffects.js` | Web Audio effects like filter, reverb, delay, distortion and compressor, for a group of sounds or everything |
|
|
265
269
|
| `drawUtilities.js` | Higher-level drawing helpers like nine-slice and three-slice |
|
|
270
|
+
| `render3dVoxels.js` | `VoxelMap`, a 3D grid of blocks that draws itself and that objects collide with |
|
|
271
|
+
| `render3dLevel.js` | 3D levels as JSON: object types, prefabs, a scene block, block maps and terrain, loaded with `level3DLoad` |
|
|
272
|
+
| `render3dDebug.js` | 3D debug draws (`debugBox3D`, `debugSphere3D`, `debugLine3D`), in debug builds only |
|
|
273
|
+
| `render3dEditor.js` | The free camera and the 3D level editor, in debug builds only |
|
|
274
|
+
| `sceneSystem.js` | Scenes as plain objects, switched with `setScene` |
|
|
275
|
+
| `parallax.js` | `ParallaxLayer`, a background that follows the camera at its own depth and repeats |
|
|
276
|
+
| `particleEffects.js` | A library of ready made particle effects, and their designer's file format |
|
|
266
277
|
|
|
267
278
|
This self-contained design means the community can also ship plugins independently of the main repo — you can write your own plugin as just a JavaScript file that uses the engine's public API.
|
|
268
279
|
|
|
@@ -367,7 +378,7 @@ LittleJS has a dedicated [js13k branch](https://github.com/KilledByAPixel/Little
|
|
|
367
378
|
- **Lean on built-ins to avoid asset files**: `Sound` with ZzFX parameters generates sound effects from a tiny array, and built-in shape drawing avoids shipping image assets.
|
|
368
379
|
- **Use a packer**: the js13k branch is set up to compress the final bundle with Roadroller or a similar packer. Check the branch's build script for the current toolchain.
|
|
369
380
|
|
|
370
|
-
For normal production (non-13KB) builds, the engine ships `dist/littlejs.release.js` (asserts stripped) and `dist/littlejs.min.js` (minified)
|
|
381
|
+
For normal production (non-13KB) builds, the engine ships `dist/littlejs.release.js` (asserts stripped, about 1.5 MB with every plugin and its comments) and `dist/littlejs.min.js` (minified, about 420 KB, about 125 KB gzipped). A bundler like Vite leaves out the plugins a game does not use, which makes a small game far smaller.
|
|
371
382
|
|
|
372
383
|
---
|
|
373
384
|
|
|
@@ -387,7 +398,7 @@ LittleJS works best when your tile sheet is broken up into grids of tiles becaus
|
|
|
387
398
|
drawTile(vec2(21,5), vec2(4.5), tile(3,128));
|
|
388
399
|
```
|
|
389
400
|
|
|
390
|
-
Once loaded, the underlying images are available via `textureInfos[0].image`, `textureInfos[1].image`, etc. This is useful for tasks like reading pixel data to generate a level —
|
|
401
|
+
Once loaded, the underlying images are available via `textureInfos[0].image`, `textureInfos[1].image`, etc. This is useful for tasks like reading pixel data to generate a level — the [Level Editor short](https://killedbyapixel.github.io/LittleJS/examples/?example=Level%20Editor) loads a level from data instead, and [examples/module/game.js](examples/module/game.js) builds one from a string.
|
|
391
402
|
|
|
392
403
|
### What is the tile function and how do tile indexes work?
|
|
393
404
|
|
package/README.md
CHANGED
|
@@ -172,7 +172,7 @@ LittleJS comes with several demos both for learning and using as starter project
|
|
|
172
172
|
| [littlejs.esm.js](https://github.com/KilledByAPixel/LittleJS/blob/main/dist/littlejs.esm.js) | Debug | ESM | Debug mode with asserts |
|
|
173
173
|
| [littlejs.esm.min.js](https://github.com/KilledByAPixel/LittleJS/blob/main/dist/littlejs.esm.min.js) | Release | ESM | Optimized for release and minified |
|
|
174
174
|
|
|
175
|
-
Every build includes the plugins. littlejs.min.js is about
|
|
175
|
+
Every build includes the plugins. littlejs.min.js is about 125 KB gzipped, and the 3D plugins are a large part of that. A bundler like Vite leaves out the plugins a game does not use, so a small 2D game comes to about 26 KB gzipped, and a lit 3D scene to about 47 KB.
|
|
176
176
|
|
|
177
177
|
## Games Made With LittleJS
|
|
178
178
|
|
package/REFERENCE.md
CHANGED
|
@@ -144,7 +144,7 @@ fetchJSON(url) // Fetch and parse a JSON file (async)
|
|
|
144
144
|
shareURL(title, url, callback) // Share a URL via the navigator share API
|
|
145
145
|
readSaveData(saveName, defaultSaveData) // Read game save data from localStorage, default must be an object
|
|
146
146
|
// the result has the default's type in TypeScript
|
|
147
|
-
writeSaveData(saveName, saveData) // Write
|
|
147
|
+
writeSaveData(saveName, saveData) // Write a save data object to localStorage, false if it could not; give medalsInit a different name
|
|
148
148
|
|
|
149
149
|
// Random functions
|
|
150
150
|
rand(valueA=1, valueB=0) // Random float between values
|
|
@@ -441,6 +441,8 @@ getNoteFrequency(semitoneOffset, rootFrequency=220) // Get frequency for musica
|
|
|
441
441
|
|
|
442
442
|
// Audio settings
|
|
443
443
|
soundEnable = true // Should sound be enabled?
|
|
444
|
+
soundIgnoreSilentSwitch = false // play with an iPhone's silent switch on, as media, pausing the player's music;
|
|
445
|
+
// off, the switch mutes the game; setSoundIgnoreSilentSwitch(true)
|
|
444
446
|
soundVolume = .3 // Volume scale to apply to all sound
|
|
445
447
|
soundDefaultRange = 40 // Default range where sound no longer plays
|
|
446
448
|
soundDefaultTaper = .7 // Default range percent to taper off sound (0-1)
|
|
@@ -1301,6 +1303,9 @@ light.coneAngle = .5 // a spotlight: the angle in radians from its
|
|
|
1301
1303
|
// cone, 0 by default for a light that shines every way; it shines along its
|
|
1302
1304
|
// own forward, so rotation3D or what it is attached to aims it
|
|
1303
1305
|
light.coneSoftness = .2 // how much of the cone is its fading edge: 0 a hard edge, 1 fading from the middle
|
|
1306
|
+
light.gel = textureInfo // or a TileInfo's whole texture: a picture the light shines through, cast along its cone in its colors, upright
|
|
1307
|
+
// as the light looks out, like a slide or stained glass; only the spotlight that
|
|
1308
|
+
// casts the shadows has one, render3D.shadows on and it as render3D.shadowLight
|
|
1304
1309
|
light.glow = 1 // a soft hazy glow over the light this big, like a lamp at night; 0 by default,
|
|
1305
1310
|
// added onto what is behind it, hidden by what is in front
|
|
1306
1311
|
light.glowFalloff = 1 // how fast the glow fades from its middle, .5 a wide haze, 2 a tight bright core
|
|
@@ -1667,8 +1672,9 @@ const map = new VoxelMap(pos3D=vec3(), mapSize=vec3(16), tileInfo=tile()) // a g
|
|
|
1667
1672
|
// that objects with collideLevel collide with; pos3D is its corner and a cell is 1 unit, it stays upright
|
|
1668
1673
|
map.setVoxel(cell, type) / map.getVoxel(cell) // type 1-255 shows that tile on every face, 0 is empty, a cell outside
|
|
1669
1674
|
// the map is ignored and reads 0
|
|
1670
|
-
map.setBlockType(type, faces, {seeThrough, transparent}) // faces: a tile, six (+x, -x, +y, -y, +z,
|
|
1671
|
-
// {top, side, bottom}; seeThrough for holes like leaves, transparent to blend like water, drawn after
|
|
1675
|
+
map.setBlockType(type, faces, {seeThrough, transparent, doubleSided}) // faces: a tile, six (+x, -x, +y, -y, +z,
|
|
1676
|
+
// -z), or {top, side, bottom}; seeThrough for holes like leaves, transparent to blend like water, drawn after
|
|
1677
|
+
// the rest; doubleSided for faces seen from inside too, so the surface of water shows from under it
|
|
1672
1678
|
map.raycast(ray, maxDistance, test) // {distance, cell, normal, type} of the first block a ray hits, or
|
|
1673
1679
|
// undefined; test(type, cell) says which blocks count
|
|
1674
1680
|
map.data / map.rebuild() // the Uint8Array of types, x + mapSize.x*(y + mapSize.y*z); rebuild
|
|
@@ -1683,8 +1689,10 @@ await loadOBJ(url, smooth) // fetch then parse, in an async gameInit; chain .cen
|
|
|
1683
1689
|
// glTF models - the glTF plugin, .gltf with its files beside it or .glb in one file; meshes with their node placement,
|
|
1684
1690
|
// vertex colors, material colors and base color textures, and node animations; no skins or morph targets, and no
|
|
1685
1691
|
// Draco or meshopt compressed geometry, which throws saying so
|
|
1686
|
-
const model = await loadGLTF(url) // a GLTFModel, in an async gameInit; or await parseGLTF(data, baseUrl) on
|
|
1687
|
-
// JSON you already have
|
|
1692
|
+
const model = await loadGLTF(url) // a GLTFModel, in an async gameInit; or await parseGLTF(data, baseUrl, files) on
|
|
1693
|
+
// bytes or JSON you already have; files, a Map of the .bin and image files a
|
|
1694
|
+
// .gltf names by their paths, like the files of a drop, in place of fetching,
|
|
1695
|
+
// baseUrl then the .gltf's folder among them
|
|
1688
1696
|
model.parts // one GLTFPart per primitive of every node: name, mesh in model space, color,
|
|
1689
1697
|
// textureInfo when the material has one and WebGL is on, transparent for a
|
|
1690
1698
|
// blending material or glass (KHR_materials_transmission), which comes in
|
|
@@ -2172,6 +2180,11 @@ getCrescentPoints(pos, size=1, percent=0, angle=0, invert=false, sides=glCircleS
|
|
|
2172
2180
|
- See `examples/shorts/textureSheet.js`
|
|
2173
2181
|
|
|
2174
2182
|
```javascript
|
|
2183
|
+
loadTiles(sources, tileSize, padding=1) // Pack tile images, or several tile sheets, into one tile set: each image cut
|
|
2184
|
+
// into tiles, numbered from 0 in the order given; give the TileInfo it
|
|
2185
|
+
// returns to tileLayersLoad or a TileLayer, and await spritesReady first
|
|
2186
|
+
tileInfo.tiles // a tile set's tiles, each where it was packed: a tile layer draws tile n
|
|
2187
|
+
// from tiles[n], and the level editor's palette offers each
|
|
2175
2188
|
loadSprite(src, frameSize, padding=1, sourcePadding=0) // Load an image and pack it, returns a TileInfo
|
|
2176
2189
|
loadAtlas(imageSrc, jsonSrc, padding=1) // Load a TexturePacker or Aseprite atlas, returns name->TileInfo object
|
|
2177
2190
|
parseAtlas(data) // Parse atlas json into named frame groups, used by loadAtlas
|
|
@@ -2288,7 +2301,8 @@ debugLine(posA, posB, color, width=.1, time) // Draw debug line
|
|
|
2288
2301
|
debugPoly(pos, points, color=WHITE, time=0, angle=0, fill) // Draw debug polygon
|
|
2289
2302
|
debugText(text, pos, size=1, color=WHITE, time=0, angle=0) // Draw debug text
|
|
2290
2303
|
debugOverlap(pA, sA, pB, sB, color) // Draw a debug overlap between two boxes
|
|
2291
|
-
// each debug draw also takes screenSpace
|
|
2304
|
+
// each debug draw also takes screenSpace as its last parameter, defaulting to drawScreenSpace; debugText takes a
|
|
2305
|
+
// font before it
|
|
2292
2306
|
debugClear() // Clear all debug primitives
|
|
2293
2307
|
debugScreenshot() // Save a screenshot at the end of this frame
|
|
2294
2308
|
debugShowErrors() // Show full page error message when an error occurs
|
package/dist/littlejs.d.ts
CHANGED
|
@@ -1345,6 +1345,12 @@ declare module "littlejsengine" {
|
|
|
1345
1345
|
* @default
|
|
1346
1346
|
* @memberof Settings */
|
|
1347
1347
|
export let soundEnable: boolean;
|
|
1348
|
+
/** Play sound with an iPhone's silent switch on, as media does; off by default, so the switch mutes the game as it
|
|
1349
|
+
* does a ringtone, and the player's own music keeps playing beside it; Safari 16.4 and up, elsewhere it does nothing
|
|
1350
|
+
* @type {boolean}
|
|
1351
|
+
* @default
|
|
1352
|
+
* @memberof Settings */
|
|
1353
|
+
export let soundIgnoreSilentSwitch: boolean;
|
|
1348
1354
|
/** Volume scale to apply to all sound, music and speech
|
|
1349
1355
|
* Use setSoundVolume to also update the audio master gain immediately
|
|
1350
1356
|
* @type {number}
|
|
@@ -1614,6 +1620,10 @@ declare module "littlejsengine" {
|
|
|
1614
1620
|
* @param {boolean} enable
|
|
1615
1621
|
* @memberof Settings */
|
|
1616
1622
|
export function setSoundEnable(enable: boolean): void;
|
|
1623
|
+
/** Set if sound plays with an iPhone's silent switch on, as media does, which also pauses the player's own music
|
|
1624
|
+
* @param {boolean} ignore
|
|
1625
|
+
* @memberof Settings */
|
|
1626
|
+
export function setSoundIgnoreSilentSwitch(ignore: boolean): void;
|
|
1617
1627
|
/** Set volume scale to apply to all sound, music and speech
|
|
1618
1628
|
* @param {number} volume
|
|
1619
1629
|
* @memberof Settings */
|
|
@@ -1806,7 +1816,7 @@ declare module "littlejsengine" {
|
|
|
1806
1816
|
* @return {number}
|
|
1807
1817
|
* @memberof Math */
|
|
1808
1818
|
export function smoothStep(percent: number): number;
|
|
1809
|
-
/** Returns the nearest power of two not less than the value
|
|
1819
|
+
/** Returns the nearest whole power of two not less than the value, 1 for a value of 1 or less
|
|
1810
1820
|
* @param {number} value
|
|
1811
1821
|
* @return {number}
|
|
1812
1822
|
* @memberof Math */
|
|
@@ -1899,6 +1909,7 @@ declare module "littlejsengine" {
|
|
|
1899
1909
|
export function saveText(text: string, filename?: string, type?: string): void;
|
|
1900
1910
|
/** Create an offscreen canvas to draw into, and return its 2D context
|
|
1901
1911
|
* - The canvas is context.canvas, which is what TextureInfo and the like take
|
|
1912
|
+
* - A browser with no OffscreenCanvas, Safari before 16.4, gets a canvas element that is not on the page
|
|
1902
1913
|
* @param {number} width - In pixels
|
|
1903
1914
|
* @param {number} [height] - In pixels, defaults to the width for a square
|
|
1904
1915
|
* @param {boolean} [willReadFrequently] - Keep it in software, faster when getImageData is called on it often
|
|
@@ -1933,11 +1944,12 @@ declare module "littlejsengine" {
|
|
|
1933
1944
|
export function readSaveData<T extends {
|
|
1934
1945
|
[x: string]: any;
|
|
1935
1946
|
} = any>(saveName: string, defaultSaveData?: T): T;
|
|
1936
|
-
/** Write save data to local storage
|
|
1947
|
+
/** Write save data to local storage, an object as readSaveData gives it back
|
|
1937
1948
|
* @param {string} saveName - unique name for the game/save
|
|
1938
1949
|
* @param {object} saveData - object containing data to be saved
|
|
1950
|
+
* @return {boolean} - Whether it was written, false when storage is unavailable or full
|
|
1939
1951
|
* @memberof Utilities */
|
|
1940
|
-
export function writeSaveData(saveName: string, saveData: object):
|
|
1952
|
+
export function writeSaveData(saveName: string, saveData: object): boolean;
|
|
1941
1953
|
/** 1D value noise — returns a smooth value in [0, 1] for any real x.
|
|
1942
1954
|
* Integer inputs land on deterministic lattice values; non-integer inputs
|
|
1943
1955
|
* are interpolated with smoothStep for C1 continuity.
|
|
@@ -2535,6 +2547,10 @@ declare module "littlejsengine" {
|
|
|
2535
2547
|
padding: number;
|
|
2536
2548
|
/** @property {TextureInfo} - The texture info for this tile */
|
|
2537
2549
|
textureInfo: TextureInfo;
|
|
2550
|
+
/** @property {Array<TileInfo>|undefined} - A tile set's tiles, each wherever it was packed, as loadTiles makes
|
|
2551
|
+
* them: a tile layer given this tile info draws its tile n from tiles[n] and not from a grid on one sheet
|
|
2552
|
+
* @type {Array<TileInfo>|undefined} */
|
|
2553
|
+
tiles: Array<TileInfo> | undefined;
|
|
2538
2554
|
/** @property {number} - Shrinks tile by this many pixels to prevent neighbors bleeding */
|
|
2539
2555
|
bleed: number;
|
|
2540
2556
|
/** @property {number} - How many frames per row for frame(), 0 to keep frames on a single row */
|
|
@@ -3660,13 +3676,13 @@ declare module "littlejsengine" {
|
|
|
3660
3676
|
* @memberof Audio
|
|
3661
3677
|
* @example
|
|
3662
3678
|
* // load an audio asset file
|
|
3663
|
-
* const
|
|
3679
|
+
* const music = new Sound('sound.mp3');
|
|
3664
3680
|
*
|
|
3665
3681
|
* // create a zzfx sound
|
|
3666
|
-
* const
|
|
3682
|
+
* const blip = new Sound([.5,.5]);
|
|
3667
3683
|
*
|
|
3668
3684
|
* // play a sound
|
|
3669
|
-
*
|
|
3685
|
+
* blip.play();
|
|
3670
3686
|
*/
|
|
3671
3687
|
export class Sound {
|
|
3672
3688
|
/** Create a sound object and cache the audio for later use
|
|
@@ -4284,7 +4300,8 @@ declare module "littlejsengine" {
|
|
|
4284
4300
|
* @param {number} [renderOrder] - Render order of the top layer
|
|
4285
4301
|
* @param {number|string} [collisionLayer] - Layer to use for collision if any, by its index or its name
|
|
4286
4302
|
* @param {boolean} [draw] - Should the layer be drawn automatically
|
|
4287
|
-
* @return {Array<TileCollisionLayer>}
|
|
4303
|
+
* @return {Array<TileCollisionLayer>} - It throws for a map that is not whole cells, or a layer whose tiles do not
|
|
4304
|
+
* fill it, before it makes any layer
|
|
4288
4305
|
* @memberof TileLayers */
|
|
4289
4306
|
export function tileLayersLoad(tileMapData: any, tileInfo?: TileInfo, renderOrder?: number, collisionLayer?: number | string, draw?: boolean): Array<TileCollisionLayer>;
|
|
4290
4307
|
/**
|
|
@@ -4605,7 +4622,7 @@ declare module "littlejsengine" {
|
|
|
4605
4622
|
* rgb(1,1,1,0), rgb(0,0,0,0), // colorEndA, colorEndB
|
|
4606
4623
|
* 1, .2, .2, .1, .05, // particleTime, sizeStart, sizeEnd, particleSpeed, particleAngleSpeed
|
|
4607
4624
|
* .99, 1, 1, PI, .05, // damping, angleDamping, gravityScale, particleCone, fadeRate
|
|
4608
|
-
* .5,
|
|
4625
|
+
* .5, true // randomness, collide
|
|
4609
4626
|
* );
|
|
4610
4627
|
*/
|
|
4611
4628
|
export class ParticleEmitter extends EngineObject {
|
|
@@ -7681,8 +7698,8 @@ declare module "littlejsengine" {
|
|
|
7681
7698
|
* const path = pf.findPath(player.pos, mousePos);
|
|
7682
7699
|
*
|
|
7683
7700
|
* // Bare grid with custom walkability:
|
|
7684
|
-
* const
|
|
7685
|
-
*
|
|
7701
|
+
* const gridFinder = new PathFinder(vec2(50, 50));
|
|
7702
|
+
* gridFinder.isWalkable = (x, y) => myGrid[y*50 + x] === 0;
|
|
7686
7703
|
*/
|
|
7687
7704
|
export class PathFinder {
|
|
7688
7705
|
/** @param {TileCollisionLayer|Vector2} source - Either a TileCollisionLayer
|
|
@@ -8503,6 +8520,7 @@ declare module "littlejsengine" {
|
|
|
8503
8520
|
viewProjection: Matrix4;
|
|
8504
8521
|
/** @property {Matrix4} - This frame's light view projection for the shadow map */
|
|
8505
8522
|
shadowMatrix: Matrix4;
|
|
8523
|
+
gelAxes: number[];
|
|
8506
8524
|
/** @property {Vector3} - Camera right axis this frame */
|
|
8507
8525
|
cameraRight: Vector3;
|
|
8508
8526
|
/** @property {Vector3} - Camera up axis this frame */
|
|
@@ -9885,6 +9903,13 @@ declare module "littlejsengine" {
|
|
|
9885
9903
|
/** @property {number} - How fast the glow fades from its middle: 1 by default, .5 a wide haze, 2 a tight
|
|
9886
9904
|
* bright core */
|
|
9887
9905
|
glowFalloff: number;
|
|
9906
|
+
/** @property {TextureInfo|TileInfo|undefined} - A gel: a picture the light shines through, like a stained glass
|
|
9907
|
+
* window or the leaves of a tree, cast along its cone in its colors, upright as the light looks out, the whole
|
|
9908
|
+
* texture of a TileInfo; only the spotlight that casts the shadows has one, with render3D.shadows on and it
|
|
9909
|
+
* as render3D.shadowLight, and only on what takes its shadows: an object with receiveShadow off is lit
|
|
9910
|
+
* without the gel; its alpha is not read, see through panes are dark
|
|
9911
|
+
* @type {TextureInfo|TileInfo|undefined} */
|
|
9912
|
+
gel: TextureInfo | TileInfo | undefined;
|
|
9888
9913
|
/** @type {LensFlare3D|undefined} */
|
|
9889
9914
|
flareObject: LensFlare3D | undefined;
|
|
9890
9915
|
/** Give the light a lens flare, made with the arguments of LensFlare3D, in place of the one it had
|
|
@@ -10219,7 +10244,8 @@ declare module "littlejsengine" {
|
|
|
10219
10244
|
* with the sun's own color; shapes says what its ghosts are, glowSize and ghostSize how big its parts are; or
|
|
10220
10245
|
* give it elements of your own, which may be tiles of the game's
|
|
10221
10246
|
* - visible is how much of the sun shows, 0 to 1, eased over fadeTime, there for a game to read; it is 0 while the
|
|
10222
|
-
* sun is too far off the screen for the flare to show, a
|
|
10247
|
+
* sun is too far off the screen for the flare to show, about a seventh of the screen past its edge, where nothing
|
|
10248
|
+
* is tested
|
|
10223
10249
|
* - What hides the sun is found with a ray from the camera, against the level and every object that is not see
|
|
10224
10250
|
* through, each on the triangles of its mesh, see render3D.pick; turn it off with occlusion
|
|
10225
10251
|
* - It needs WebGL, and it draws nothing in the shadow of renderAfter2D
|
|
@@ -10262,7 +10288,7 @@ declare module "littlejsengine" {
|
|
|
10262
10288
|
elements: Array<LensFlareElement> | undefined;
|
|
10263
10289
|
/** @property {Light3D|undefined} - A light the flare is of in place of the sun, a lamp or a spotlight: the
|
|
10264
10290
|
* flare is at the light and in its color, smaller from farther than the light reaches, hidden by what is
|
|
10265
|
-
* in front of the light but its lamp, a mesh around it
|
|
10291
|
+
* in front of the light but its lamp, a mesh around it whose surface is near it, and a spotlight's
|
|
10266
10292
|
* shows from inside its beam only; a DirectionalLight3D's is far
|
|
10267
10293
|
* away where it shines from, like the sun's; the flare is destroyed when its light is; light.addFlare
|
|
10268
10294
|
* sets this
|
|
@@ -10566,11 +10592,24 @@ declare module "littlejsengine" {
|
|
|
10566
10592
|
duration: number;
|
|
10567
10593
|
}
|
|
10568
10594
|
/** Parse a model from GLB bytes or glTF JSON, fetching the buffers and images it refers to
|
|
10595
|
+
* - A .gltf names its .bin and image files, which are fetched from baseUrl, or found among files: what a game
|
|
10596
|
+
* has in hand, like the files dropped on the page, by their paths in the drop; with files, baseUrl is the
|
|
10597
|
+
* .gltf's own folder among them ('' or 'models/house/'), its names are read from there, and a name found nowhere
|
|
10598
|
+
* there is taken by its file name alone only when one file of the drop has it; only an http, https or blob uri
|
|
10599
|
+
* is fetched then
|
|
10600
|
+
* - A file the model needs that is not found is named in the error, and an image that can not be read is named in
|
|
10601
|
+
* a warning and left out
|
|
10569
10602
|
* @param {ArrayBuffer|Object|string} data - GLB bytes, or the glTF JSON as bytes, text or an object
|
|
10570
10603
|
* @param {string} [baseUrl] - Where the .bin and image files are, with its trailing slash; loadGLTF passes the file's folder
|
|
10604
|
+
* @param {Map<string, Blob>} [files] - The files it refers to, by their paths, in place of fetching them
|
|
10571
10605
|
* @return {Promise<GLTFModel>}
|
|
10606
|
+
* @example
|
|
10607
|
+
* // the files of a drop, a .gltf with its .bin and textures, by their names
|
|
10608
|
+
* const files = new Map([...dataTransfer.files].map((file)=> [file.name, file]));
|
|
10609
|
+
* const gltf = [...files.values()].find((file)=> file.name.endsWith('.gltf'));
|
|
10610
|
+
* const model = await parseGLTF(await gltf.text(), '', files);
|
|
10572
10611
|
* @memberof GLTF */
|
|
10573
|
-
export function parseGLTF(data: ArrayBuffer | any | string, baseUrl?: string): Promise<GLTFModel>;
|
|
10612
|
+
export function parseGLTF(data: ArrayBuffer | any | string, baseUrl?: string, files?: Map<string, Blob>): Promise<GLTFModel>;
|
|
10574
10613
|
/** Load a glTF or GLB model, the .bin and images of a .gltf from beside it
|
|
10575
10614
|
* - A texture only OPAQUE materials use loads with its alpha set to 1, so the 3D pass cuts no holes in it
|
|
10576
10615
|
* @param {string} url
|
|
@@ -10831,6 +10870,7 @@ declare module "littlejsengine" {
|
|
|
10831
10870
|
* - Animation frames keep layout and wrap across rows as needed
|
|
10832
10871
|
* - WebGL textures upload once per batch of loads
|
|
10833
10872
|
* - loadAtlas imports pre-packed atlases (TexturePacker and Aseprite json)
|
|
10873
|
+
* - loadTiles packs separate tile images, or several tile sheets, into one tile set for tile layers and maps
|
|
10834
10874
|
* @namespace TextureSheets
|
|
10835
10875
|
*/
|
|
10836
10876
|
/** Width and height in pixels of texture sheets created by loadSprite
|
|
@@ -10901,6 +10941,7 @@ declare module "littlejsengine" {
|
|
|
10901
10941
|
* - Pass frameSize for animations, then step through them with TileInfo.frame
|
|
10902
10942
|
* - Grid images keep their layout and frames wrap down to the next row
|
|
10903
10943
|
* - Pass sourcePadding if the source image has padding baked in around frames
|
|
10944
|
+
* - The same image loaded again with the same settings gives back what the first load did, packed once
|
|
10904
10945
|
* @param {string} src - Image source path
|
|
10905
10946
|
* @param {Vector2|number} [frameSize] - Size of each animation frame in pixels, or the whole image less its
|
|
10906
10947
|
* source padding if not passed
|
|
@@ -10912,6 +10953,28 @@ declare module "littlejsengine" {
|
|
|
10912
10953
|
* const runTile = loadSprite('run.png', vec2(16)); // a 16x16 frame animation
|
|
10913
10954
|
* @memberof TextureSheets */
|
|
10914
10955
|
export function loadSprite(src: string, frameSize?: Vector2 | number, padding?: number, sourcePadding?: number | Vector2): TileInfo;
|
|
10956
|
+
/** Load tile images and pack them into texture sheets as one tile set, for tile layers and maps
|
|
10957
|
+
* - Each image is cut into tiles of tileSize, left to right then down, so an image of one tile is one tile and a
|
|
10958
|
+
* sheet is all of its tiles; the tiles are numbered from 0 in the order the images are given
|
|
10959
|
+
* - Returns a tile set at once, a TileInfo whose tiles fill in as the images load; wait for them with spritesReady
|
|
10960
|
+
* - Give it to tileLayersLoad, a TileLayer or a TileCollisionLayer as its tile info: tile n draws tiles[n],
|
|
10961
|
+
* wherever it was packed, and the level editor's palette offers each of them; frame and index do not read the
|
|
10962
|
+
* list, use set.tiles[n] for one tile; make the layers after spritesReady, a layer made before draws nothing
|
|
10963
|
+
* - An image that is not a whole number of tiles gives the whole tiles in it; a sheet with gaps between its tiles
|
|
10964
|
+
* is not read, cut it into its tiles first
|
|
10965
|
+
* - An image that fails to load, or that no sheet can hold, adds no tiles and says so in the console, so the tiles
|
|
10966
|
+
* of the images after it move up
|
|
10967
|
+
* - The same images loaded again with the same settings give back what the first load did, packed once
|
|
10968
|
+
* @param {Array<string>} sources - Image source paths
|
|
10969
|
+
* @param {Vector2|number} [tileSize] - Size of a tile in pixels
|
|
10970
|
+
* @param {number} [padding] - How many pixels padding around each tile on the sheet
|
|
10971
|
+
* @return {TileInfo}
|
|
10972
|
+
* @example
|
|
10973
|
+
* const tiles = loadTiles(['grass.png', 'dirt.png', 'water.png', 'props.png'], 16);
|
|
10974
|
+
* await spritesReady();
|
|
10975
|
+
* tileLayersLoad(map, tiles); // tile 0 is grass, 1 dirt, 2 water, then the tiles of props.png
|
|
10976
|
+
* @memberof TextureSheets */
|
|
10977
|
+
export function loadTiles(sources: Array<string>, tileSize?: Vector2 | number, padding?: number): TileInfo;
|
|
10915
10978
|
/** Load a pre-packed texture atlas and repack it onto texture sheets
|
|
10916
10979
|
* - Supports TexturePacker json (hash and array) and Aseprite json
|
|
10917
10980
|
* - Returns an empty object which is filled with TileInfos when loaded
|
|
@@ -10919,6 +10982,7 @@ declare module "littlejsengine" {
|
|
|
10919
10982
|
* - Aseprite frame tags become animations, so do names like run_0, run_1
|
|
10920
10983
|
* - Trimmed frames are restored to their full source size when packed
|
|
10921
10984
|
* - Rotated frames are rotated back upright when packed
|
|
10985
|
+
* - The same atlas loaded again by its paths, with the same padding, gives back what the first load did, packed once
|
|
10922
10986
|
* @param {string} imageSrc - Atlas image path
|
|
10923
10987
|
* @param {string|Object} jsonSrc - Atlas json path, or already parsed json data
|
|
10924
10988
|
* @param {number} [padding] - How many pixels padding around each frame
|