littlejsengine 1.25.0 → 1.26.1
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 +99 -0
- package/FAQ.md +49 -11
- package/README.md +6 -2
- package/REFERENCE.md +129 -21
- package/dist/littlejs.d.ts +487 -102
- package/dist/littlejs.esm.js +2898 -719
- package/dist/littlejs.esm.min.js +3 -3
- package/dist/littlejs.js +2888 -716
- package/dist/littlejs.min.js +2 -2
- package/dist/littlejs.release.js +2702 -527
- package/package.json +4 -4
- package/plugins/box2d.js +110 -34
- package/plugins/gltf.js +74 -22
- package/plugins/lightSystem.js +410 -28
- package/plugins/math3d.js +4 -2
- package/plugins/medalSystem.js +19 -7
- package/plugins/newgrounds.js +4 -2
- package/plugins/parallax.js +1 -0
- package/plugins/particleEffects.js +44 -10
- package/plugins/pathFinder.js +9 -11
- package/plugins/pluginExport.js +9 -0
- package/plugins/postProcess.js +9 -3
- package/plugins/render3d.js +499 -2389
- package/plugins/render3dDebug.js +5 -8
- package/plugins/render3dEditor.js +81 -6
- package/plugins/render3dExtras.js +103 -31
- package/plugins/render3dLevel.js +53 -5
- package/plugins/render3dMesh.js +1158 -0
- package/plugins/render3dObject.js +1451 -0
- package/plugins/render3dVoxels.js +15 -3
- package/plugins/textureSheet.js +9 -8
- package/plugins/threejs.js +1 -1
- package/plugins/tweenSystem.js +76 -51
- package/plugins/uiSystem.js +37 -8
- package/plugins/wavedash.js +229 -0
- package/src/engine.js +199 -40
- package/src/engineAudio.js +37 -21
- package/src/engineBuild.mjs +6 -1
- package/src/engineDebug.js +22 -162
- package/src/engineDraw.js +142 -34
- package/src/engineEditor.js +79 -18
- package/src/engineExport.js +1 -3
- package/src/engineInput.js +34 -24
- package/src/engineMath.js +35 -14
- package/src/engineObject.js +60 -41
- package/src/engineParticles.js +58 -11
- package/src/engineRelease.js +1 -5
- package/src/engineSettings.js +48 -9
- package/src/engineTileLayer.js +11 -4
- package/src/engineUtilities.js +41 -9
- package/src/engineWebGL.js +37 -13
package/REFERENCE.md
CHANGED
|
@@ -25,8 +25,9 @@ engineName // Name of the engine: 'LittleJS'
|
|
|
25
25
|
engineVersion // Version of the engine
|
|
26
26
|
frameRate // Fixed frame rate for updates (60)
|
|
27
27
|
frame // Current update frame
|
|
28
|
-
time // Game time since start in seconds (stops when paused)
|
|
28
|
+
time // Game time since start in seconds (stops when paused, falls behind the clock below 20 FPS)
|
|
29
29
|
timeReal // Real time since start in seconds (keeps running when paused; the debug speed keys scale it)
|
|
30
|
+
averageFPS // Frames drawn per second, smoothed
|
|
30
31
|
timeDelta // Seconds the update covers: 1/60, or the display frame's time with engineVariableStep
|
|
31
32
|
timeScale = 1 // Game speed, more or fewer fixed updates per second; with engineVariableStep it scales timeDelta
|
|
32
33
|
paused // Is the game paused? (set with setPaused)
|
|
@@ -94,7 +95,11 @@ let remaining = 36000;
|
|
|
94
95
|
gravity, at the fixed 60 updates a second
|
|
95
96
|
- **Seconds:** `Timer`, `Tween`, `time`, a particle emitter's `emitTime` and `particleTime` and its `emitRate` (per
|
|
96
97
|
second) and `lifeTime`; a particle's `fadeRate` is a part of its life, not seconds
|
|
98
|
+
- **Materials:** `roughness`, `reflectivity` and `specular` run 0 to 1, `shininess` 1 up, about 10,000 a mirror (a roughness of 0 sets it far higher), and
|
|
99
|
+
`emissive` from 0 up
|
|
97
100
|
- **Milliseconds:** `gamepadVibrate`'s duration, `vibrate` patterns and `saveDataURL`'s `revokeTime`
|
|
101
|
+
- **Limits:** the GPU draws with 32-bit floats: keep the world within about ±10,000 units of the origin, and a
|
|
102
|
+
shader's `iTime` gets coarse in a game left running for days; the FAQ says more
|
|
98
103
|
|
|
99
104
|
## What functions give back
|
|
100
105
|
- **Raycasts:** where the ray hits, a Vector2: `tileCollisionRaycast`, `lineTest`; how far along the ray, a number:
|
|
@@ -321,8 +326,13 @@ toggleFullscreen()
|
|
|
321
326
|
// Shader Object - a custom fragment shader for objects and draws, 2D or 3D
|
|
322
327
|
new Shader(fragmentCode) // fragmentCode defines void mainImage(out vec4 c, vec2 uv) in the post processing
|
|
323
328
|
// style; it gives the surface color, then the object's color and additive color
|
|
324
|
-
// apply in 2D, and the lighting, shadows and fog in 3D
|
|
329
|
+
// apply in 2D, and the lighting, shadows and fog in 3D; in 3D it may also define
|
|
330
|
+
// void mainNormal(inout vec3 n), the world normal after the normal map, to bend
|
|
331
|
+
// it per pixel (waves, ripples) for the lighting, specular and reflection
|
|
325
332
|
obj.shader = shader // any EngineObject or EngineObject3D; draws that share a Shader share a batch
|
|
333
|
+
shader.dispose() // frees its programs and takes it off the engine's list, which keeps every Shader
|
|
334
|
+
// for a lost context; for one made each time a scene starts; drawn again it
|
|
335
|
+
// compiles again, so let go of only one nothing draws with
|
|
326
336
|
// names in the snippet: iChannel0 the texture, iTime, iResolution, localUV 0 to 1 across the sprite or the mesh uv,
|
|
327
337
|
// premultipliedTexture true for a render target or a smooth image (tilesPixelated false), whose rgb and alpha
|
|
328
338
|
// change together;
|
|
@@ -447,7 +457,9 @@ glDraw(x, y, sizeX, sizeY, angle=0, uv0X, uv0Y, uv1X, uv1Y, rgba=-1, rgbaAdditiv
|
|
|
447
457
|
```javascript
|
|
448
458
|
// Sound Object
|
|
449
459
|
Sound(zzfxSound, randomness, range, taper, onloadCallback) // Create a zzfx sound
|
|
450
|
-
|
|
460
|
+
zzfx(...zzfxSound) // Generate and play a zzfx sound at once, no Sound kept
|
|
461
|
+
Sound(filename, randomness, range, taper, onloadCallback) // Load a wave, mp3, or ogg; onloadCallback(sound) is
|
|
462
|
+
// called once it loads or fails to, isLoaded says which
|
|
451
463
|
Sound.play(pos, volume=1, pitch=1, randomnessScale=1, loop=false, paused=false) // Play a sound, returns SoundInstance
|
|
452
464
|
Sound.playLoop(pos, volume=1, pitch=1, randomnessScale=1, paused=false) // Play on a loop, like play with loop on
|
|
453
465
|
Sound.playMusic(volume=1, loop=true, paused=false) // Play as music with looping
|
|
@@ -480,7 +492,8 @@ speakStop() // Stop all queued speech
|
|
|
480
492
|
getNoteFrequency(semitoneOffset, rootFrequency=220) // Get frequency for musical notes
|
|
481
493
|
|
|
482
494
|
// Audio settings
|
|
483
|
-
soundEnable = true // Should sound be enabled?
|
|
495
|
+
soundEnable = true // Should sound be enabled? set it before sounds are made, setSoundEnable(false)
|
|
496
|
+
// before they are, setSoundVolume(0) to mute while the game runs
|
|
484
497
|
soundIgnoreSilentSwitch = false // play with an iPhone's silent switch on, as media, pausing the player's music;
|
|
485
498
|
// off, the switch mutes the game; setSoundIgnoreSilentSwitch(true)
|
|
486
499
|
soundVolume = .3 // Volume scale to apply to all sound
|
|
@@ -678,7 +691,7 @@ EngineObject.clampSpeed // Hold each axis of velocity to objectMaxSpeed while
|
|
|
678
691
|
EngineObject.parent / children // Set by addChild, a child is placed by its parent and sits out solid collision
|
|
679
692
|
|
|
680
693
|
// Engine Object settings
|
|
681
|
-
enablePhysicsSolver = true // Enable collisions, between objects and with tiles?
|
|
694
|
+
enablePhysicsSolver = true // Enable collisions, between objects and with tiles, and in 3D with solids and the level?
|
|
682
695
|
objectDefaultMass = 1 // Default object mass for collisions
|
|
683
696
|
objectDefaultDamping = 1 // Fraction of velocity kept each frame (1 keeps all)
|
|
684
697
|
objectDefaultAngleDamping = 1 // Fraction of angular velocity kept each frame (1 keeps all)
|
|
@@ -849,7 +862,8 @@ particleEffectApply(emitter, effect) // set a live 2D emitter to an effect
|
|
|
849
862
|
particleEffectApply3D(emitter, effect) // the same for a ParticleEmitter3D, its particles, place and scale kept
|
|
850
863
|
particleEffectFromEmitter(emitter, name='Effect') // a 2D emitter's settings as an effect, to save or build in 3D
|
|
851
864
|
particleEffectsAddBehavior(name, update, update3D, min=-2, max=2, value=1, description='') // add a behavior effects
|
|
852
|
-
// can name, with 2D and 3D pushes; min
|
|
865
|
+
// can name, with 2D and 3D pushes; min and max for the designer and to clamp
|
|
866
|
+
// a strength to, value to start at
|
|
853
867
|
particleEffectsAdd(effects) // add effects to play by name, one of the same name replaces it
|
|
854
868
|
particleEffectsGet(name) // an effect's data, any case, to change or build by hand
|
|
855
869
|
await particleEffectsLoad(url) // load the file the particle designer's Save Library wrote, and add its effects
|
|
@@ -1124,6 +1138,20 @@ light.glow = 0 // size across of a soft hazy glow over the light, like
|
|
|
1124
1138
|
// over the lit scene after the lightmap, so it shows in the dark, in front of everything
|
|
1125
1139
|
light.glowFalloff = 1 // how fast the glow fades from its middle, .5 a wide haze, 2 a tight bright core
|
|
1126
1140
|
|
|
1141
|
+
// One directional light, a sun: lights the whole scene from one direction, added with the point lights
|
|
1142
|
+
new DirectionalLight(sunDirection=vec2(-1,1), color=WHITE) // toward the sun, as render3D.sunDirection; its color
|
|
1143
|
+
sun.sunDirection // toward the sun, it shines the other way
|
|
1144
|
+
sun.castShadow = true // foreground casters (castShadow) throw long shadows; no lightSystem.shadows needed
|
|
1145
|
+
sun.shadowLength = 20 // world units a long shadow reaches before it has faded out; a caster casts from inside
|
|
1146
|
+
// the shadow map only, (shadowMapScale - 1) / 2 of a view past the screen
|
|
1147
|
+
sun.backgroundDepth = 3 // world units the light gets into a background area from its edges facing it
|
|
1148
|
+
lightSystem.directionalLight // the one there is, or undefined; a second one asserts, destroy the first
|
|
1149
|
+
// (a release build destroys the first itself)
|
|
1150
|
+
lightSystem.directionalTextureSize = 512 // pixels across its work textures, which cover the shadow map's area; a
|
|
1151
|
+
// power of two, as shadowMapSize is, or the shadows shimmer as the view pans
|
|
1152
|
+
obj.castBackgroundShadow = false // a background: dark to the directional light inside, lit at its edges;
|
|
1153
|
+
// a background layer sets castShadow = false and this true
|
|
1154
|
+
|
|
1127
1155
|
// Per-object lightmap contribution hook (on every EngineObject)
|
|
1128
1156
|
class LavaTile extends EngineObject {
|
|
1129
1157
|
renderLight() {
|
|
@@ -1154,6 +1182,7 @@ postProcessBloom(threshold=.6, strength=1, size=6, includeMainCanvas=false) // s
|
|
|
1154
1182
|
// and past a size of 32 it would take hundreds, so that is as wide as it goes
|
|
1155
1183
|
postProcessBloomShader(threshold, strength, size) // its shader code, to pass to PostProcessPlugin or build on
|
|
1156
1184
|
postProcess.setShaderCode(shaderCode) // shade with new code from the next frame, to switch effects while running
|
|
1185
|
+
postProcess.enabled = true // false skips the pass, the frame showing as drawn, to turn an effect off and back on
|
|
1157
1186
|
|
|
1158
1187
|
// Built in effects: each is a piece of shader code with its settings written in, working on c, the pixel's color,
|
|
1159
1188
|
// and uv, where it is on the screen from 0 to 1; postProcessEffects joins pieces in order into one shader, and your
|
|
@@ -1308,6 +1337,7 @@ render3D.camera.follow(target, offset, percent=1) // chase camera: ease toward t
|
|
|
1308
1337
|
// is how far it moves each call, so call it every frame, from
|
|
1309
1338
|
// gameUpdatePost once the target has moved
|
|
1310
1339
|
render3D.camera.align2D = true // lock to the 2D camera so the z=0 plane matches world space, false by default
|
|
1340
|
+
render3D.camera.align2DZ = 0 // the z of the plane align2D lines up, the camera its distance in front
|
|
1311
1341
|
render3D.camera.getForward() .getRight() .getUp() // the camera's axes as it is right now; render3D.cameraRight
|
|
1312
1342
|
// .cameraUp .cameraForward are this frame's, read only
|
|
1313
1343
|
render3D.viewMatrix .projectionMatrix .viewProjection .shadowMatrix // this frame's, rebuilt by updateMatrices()
|
|
@@ -1383,7 +1413,8 @@ render3D.shadowLight = flashlight // a spotlight, a Light3D with a coneAngle
|
|
|
1383
1413
|
render3D.shadowRange = 40 // world size the map covers around shadowCenter, smaller is sharper
|
|
1384
1414
|
// it is a square facing the light, so ~1.5x an area's width covers it
|
|
1385
1415
|
render3D.shadowCenter = undefined // Vector3 center of the shadowed area, read each frame; undefined follows the camera
|
|
1386
|
-
render3D.shadowBias = .003 // raise if lit surfaces get speckled with their own shadow, lower if shadows float away
|
|
1416
|
+
render3D.shadowBias = .003 // raise if lit surfaces get speckled with their own shadow, lower if shadows float away;
|
|
1417
|
+
// a share of the map's depth (2 * shadowRange for the sun), so the gap grows with the range
|
|
1387
1418
|
// from their casters
|
|
1388
1419
|
render3D.shadowSoftness = 1 // how far to blur the shadow edge, in shadow map pixels
|
|
1389
1420
|
|
|
@@ -1394,6 +1425,19 @@ render3D.setSky(topColor, horizonColor, bottomColor, ambient=.5) // dome colors
|
|
|
1394
1425
|
// color from below, both times ambient; 0 leaves ambient dark
|
|
1395
1426
|
render3D.setFog(fogStart, fogEnd, fogColor) // the fog distances and color at once, no color keeps the current one
|
|
1396
1427
|
render3D.sky = buildSky(topColor, horizonColor, bottomColor, sides, rings) // or set a dome yourself
|
|
1428
|
+
render3D.skyBox = cubeMap // a CubeMap drawn behind everything in place of the dome, undefined by default;
|
|
1429
|
+
// fog fades to fogColor, so set it to the sky box's horizon color
|
|
1430
|
+
render3D.environment = cubeMap // what reflective surfaces reflect, undefined reflects the sky's colors; one
|
|
1431
|
+
// made again and again disposes the one it replaces, its GPU memory
|
|
1432
|
+
makeCubeMap(size, colorOf) // a CubeMap of six size by size faces, colorOf(direction) the Color each way,
|
|
1433
|
+
// a unit Vector3; paint a sky in code, 64 or so is plenty for a blurry one
|
|
1434
|
+
await loadCubeMap([px, nx, py, ny, pz, nz]) // a CubeMap from six square image urls, +x, -x, +y, -y, +z and -z,
|
|
1435
|
+
// a sky box set shown as three.js shows it, each face as its image is drawn
|
|
1436
|
+
cubeMap.size cubeMap.faces cubeMap.dispose() // its face size, its six faces, and freeing its GPU texture
|
|
1437
|
+
const mirror = new CubeMap(128) // no faces: a cube map to draw the scene into
|
|
1438
|
+
mirror.capture(pos3D) // draw the scene around pos3D into it in the next frame's pass, six views of
|
|
1439
|
+
// the whole scene: once for a still scene, every few frames for a moving one
|
|
1440
|
+
mirror.capturePos // where it was last captured from, captured again from there after a lost context
|
|
1397
1441
|
|
|
1398
1442
|
// Draw state, read at each draw; the pass sets it from each object's flags before render3D() and resets it before each
|
|
1399
1443
|
// callback, so set it inside those, or use the object flags below
|
|
@@ -1405,6 +1449,7 @@ render3D.specular = 0 // Phong highlight strength, the shiny spo
|
|
|
1405
1449
|
// out; shininess sets the size of the spot
|
|
1406
1450
|
render3D.shininess = 16 // the highlight's exponent, 4 broad like rubber, 100 sharp like polished metal
|
|
1407
1451
|
render3D.normalMap render3D.normalScale render3D.reflectivity render3D.emissiveMap render3D.emissiveMapColor
|
|
1452
|
+
render3D.environmentMap // the cube map reflected in place of render3D.environment, from obj.environment
|
|
1408
1453
|
// the material, set from each object's fields of the same names
|
|
1409
1454
|
render3D.receiveShadow = true // false keeps the next draws out of the shadow map's darkening
|
|
1410
1455
|
render3D.shader = undefined // a Shader for the next draws, set from each object's shader; with emissive 1
|
|
@@ -1525,13 +1570,20 @@ obj.emissive = 1 // 0 by default; how much it lights itse
|
|
|
1525
1570
|
// things, between partly self lit, above 1 brighter for bloom; still casts
|
|
1526
1571
|
obj.specular = .5 // highlight strength, 0 is none and 1 is full, as render3D.specular; 0 by default
|
|
1527
1572
|
obj.shininess = 100 // 16 by default; the highlight's exponent, higher is smaller and sharper
|
|
1573
|
+
obj.roughness = .5 // shininess set the way glTF measures it, 0 a mirror to 1 matte: it sets
|
|
1574
|
+
// shininess = 2 / roughness^4 - 2, at least 1, and reads it back, as
|
|
1575
|
+
// .9 from about .9 up, where shininess is 1
|
|
1528
1576
|
obj.normalMap = textureInfo // bumps and grooves that catch the light, read at the color texture's uvs;
|
|
1529
1577
|
// green points up the image (OpenGL and glTF), flip the green of a DirectX one;
|
|
1530
1578
|
// no tangents needed, any mesh with uvs works; normalMapFromHeight makes one
|
|
1531
1579
|
obj.normalScale = 1 // how strongly it bends the surface, 0 turns it off
|
|
1532
|
-
obj.reflectivity = .5 // 0 by default, 1 a mirror
|
|
1533
|
-
//
|
|
1534
|
-
//
|
|
1580
|
+
obj.reflectivity = .5 // 0 by default, 1 a mirror; more at a glancing angle (Fresnel); shows
|
|
1581
|
+
// render3D.environment, sharper the higher shininess, as the highlight
|
|
1582
|
+
// is: 10000 a mirror, 1000 polished, 10 a wide blur;
|
|
1583
|
+
// with none, the colors of render3D.sky from setSky or buildSky, or the
|
|
1584
|
+
// ambient ones with no sky
|
|
1585
|
+
obj.environment = mirror // a CubeMap it reflects in place of render3D.environment, as one captured
|
|
1586
|
+
// from its own middle; undefined by default
|
|
1535
1587
|
obj.emissiveMap = textureInfo // where it glows, added on top of the lit surface so it shows in the dark
|
|
1536
1588
|
obj.emissiveMapColor = WHITE // multiplies the emissive map
|
|
1537
1589
|
obj.castShadow = false // true by default, false keeps it out of the shadow map; sprites and cut out
|
|
@@ -1752,7 +1804,7 @@ model.parts // one GLTFPart per primitive of every node
|
|
|
1752
1804
|
// are the set the texture's texCoord names, moved by KHR_texture_transform;
|
|
1753
1805
|
// normalMap and normalScale from normalTexture, emissiveMap and
|
|
1754
1806
|
// emissiveMapColor from emissiveTexture and emissiveFactor, read at the base
|
|
1755
|
-
// color texture's uvs
|
|
1807
|
+
// color texture's uvs, and roughness from roughnessFactor, 1 when it has none
|
|
1756
1808
|
model.mesh, model.textureInfo // everything as one Mesh tinted by its materials, and its texture when every
|
|
1757
1809
|
// part uses the same one; a model mixing plain and textured parts, or using
|
|
1758
1810
|
// several textures or unlit parts, draws right through createObject
|
|
@@ -1795,6 +1847,7 @@ emitter3D.gravityScale = 0 // a share of render3D.gravity added on top of its ow
|
|
|
1795
1847
|
// an emitter with an emitTime destroys itself once its last particle is gone, so a burst is fire and forget
|
|
1796
1848
|
// untextured particles are soft round dots, textured ones are billboards of the tile
|
|
1797
1849
|
emitter.collideLevel = false // particles hit the height maps and voxel maps, bounce by restitution, slide by friction
|
|
1850
|
+
// only: not solid objects, as 2D particles hit only tile layers
|
|
1798
1851
|
emitter.particleCreateCallback / particleUpdateCallback / particleCollideCallback / particleDestroyCallback
|
|
1799
1852
|
// as in 2D, each given a Particle3D {pos, velocity, age, lifeTime, emitter, destroy()}, one object
|
|
1800
1853
|
// the emitter reuses, so copy what you keep; the collide callback gets (particle, level, pos) and
|
|
@@ -1875,7 +1928,9 @@ material.side = THREE.DoubleSide // mesh.doubleSided = true
|
|
|
1875
1928
|
material.emissiveIntensity // obj.emissive
|
|
1876
1929
|
material.normalMap, normalScale // obj.normalMap, obj.normalScale (a number, three.js takes a Vector2)
|
|
1877
1930
|
material.shininess (MeshPhongMaterial) // obj.shininess, with obj.specular the strength
|
|
1878
|
-
material.
|
|
1931
|
+
material.reflectivity // obj.reflectivity, with render3D.environment or obj.environment the map
|
|
1932
|
+
material.metalness // none; a dark color with reflectivity reads as metal
|
|
1933
|
+
material.roughness (MeshStandardMaterial) // obj.roughness, which sets obj.shininess: 0 a mirror, 1 matte
|
|
1879
1934
|
material.emissiveMap, emissive // obj.emissiveMap, obj.emissiveMapColor
|
|
1880
1935
|
material.transparent, blending // obj.transparent, obj.additive
|
|
1881
1936
|
new THREE.ShaderMaterial({fragmentShader}) // obj.shader = new Shader(code), a mainImage snippet the engine wraps;
|
|
@@ -1890,7 +1945,12 @@ new THREE.SpotLight(color, i, d, angle, penumbra) // a Light3D with coneAngle =
|
|
|
1890
1945
|
// for its castShadow
|
|
1891
1946
|
light.castShadow, light.shadow.camera // render3D.shadows, shadowRange and shadowCenter
|
|
1892
1947
|
scene.fog = new THREE.Fog(c, near, far) // render3D.setFog(near, far, c)
|
|
1893
|
-
scene.background // render3D.setSky(topColor, horizonColor, bottomColor)
|
|
1948
|
+
scene.background // render3D.setSky(topColor, horizonColor, bottomColor), or
|
|
1949
|
+
// render3D.skyBox for a cube map
|
|
1950
|
+
scene.environment // render3D.environment
|
|
1951
|
+
material.envMap on one mesh // obj.environment
|
|
1952
|
+
new THREE.CubeCamera(near, far, target) // new CubeMap(size), then cubeMap.capture(pos3D) in place of update
|
|
1953
|
+
new THREE.CubeTextureLoader().load(urls) // await loadCubeMap(urls), the same order
|
|
1894
1954
|
OrbitControls // new CameraControl3D(target, distance)
|
|
1895
1955
|
PointerLockControls // new FirstPersonCamera3D
|
|
1896
1956
|
new THREE.Raycaster() // render3D.screenToRay, pick and engineObjectsRaycast3D
|
|
@@ -1936,7 +1996,11 @@ level3DVoxelSetup(tileInfo, (map)=> {}) // The sheet a level's block m
|
|
|
1936
1996
|
"fog": [25, 70], "fogColor": "#d6ecff", // start and end, an end of 0 for none; the horizon color
|
|
1937
1997
|
// when the level has a sky and no fogColor
|
|
1938
1998
|
"shadows": true,
|
|
1939
|
-
"lensFlare": true
|
|
1999
|
+
"lensFlare": true, // the sun's lens flare, a LensFlare3D made for it
|
|
2000
|
+
"skyBox": ["px.png", "nx.png", "py.png", "ny.png", "pz.png", "nz.png"], // render3D.skyBox, six images
|
|
2001
|
+
"environment": ["px.png", "nx.png", "py.png", "ny.png", "pz.png", "nz.png"]}, // as loadCubeMap takes
|
|
2002
|
+
// them, loaded in the background, the same urls once;
|
|
2003
|
+
// urls are from the page, not from the level's file
|
|
1940
2004
|
"objects": []}
|
|
1941
2005
|
|
|
1942
2006
|
// A level can hold a map of blocks, made a VoxelMap when it loads: its corner, its size in cells, and its blocks
|
|
@@ -1952,7 +2016,8 @@ level3DVoxelSetup(tileInfo, (map)=> {}) // The sheet a level's block m
|
|
|
1952
2016
|
// Prefabs - a prefab is a small level, objects about its own origin, placed many times under one name. The level
|
|
1953
2017
|
// editor saves one as it saves a level, so it is the prefab editor too, and there every instance follows its prefab
|
|
1954
2018
|
level3DAddPrefab(name, prefab) // Add {objects: [...]} as a type; its objects may be of other prefabs
|
|
1955
|
-
await level3DLoadPrefab(name, url) // Fetch a prefab file and add it
|
|
2019
|
+
await level3DLoadPrefab(name, url) // Fetch a prefab file and add it; a prefab used inside it is
|
|
2020
|
+
// named by its type, the game adds that one too
|
|
1956
2021
|
level3DSpawn(type, pos3D, rotation3D, scale3D, properties) // Make one object of any type from code, a prefab's
|
|
1957
2022
|
// instance or a plain type; rotation in radians
|
|
1958
2023
|
prefab = new Prefab3D // what a prefab's type makes, a handle that draws nothing:
|
|
@@ -2051,6 +2116,12 @@ obj.syncMesh() // copy the 2D transform to the mesh
|
|
|
2051
2116
|
read only, move it with `setPosition`, `setAngle` or `setTransform` and push it with velocities and forces
|
|
2052
2117
|
- Joints, raycasting, polygon/circle/edge fixtures
|
|
2053
2118
|
- Angular values are clockwise like `angle`: angular velocity, torque, joint angles and limits, motor speeds
|
|
2119
|
+
- The EngineObject's own physics fields do nothing on a Box2dObject, Box2D moves it: `velocity`, `angleVelocity`,
|
|
2120
|
+
`damping`, `angleDamping`, `mass`, `friction`, `restitution` and `gravityScale`. Use `getLinearVelocity`,
|
|
2121
|
+
`setLinearVelocity`, `setAngularVelocity`, `setLinearDamping`, `setAngularDamping`, `setMass`, the friction and
|
|
2122
|
+
restitution given to its shapes, and `setGravityScale`; a debug build warns once when one is set
|
|
2123
|
+
- A world made again after `engineObjectsDestroy` does not step exactly as a fresh one, as Box2D reuses its ids, so
|
|
2124
|
+
a replay or a lockstep game that needs the same steps every time reloads the page
|
|
2054
2125
|
- See `examples/box2d/` for a full demo
|
|
2055
2126
|
|
|
2056
2127
|
```javascript
|
|
@@ -2093,8 +2164,8 @@ obj.setAwake(awake=true)
|
|
|
2093
2164
|
obj.setFixedRotation(isFixed=true) // Stop the body from rotating
|
|
2094
2165
|
obj.setBullet(isBullet=true) // Continuous collision for fast bodies, so they don't pass through thin ones
|
|
2095
2166
|
obj.setSensor(isSensor=true) // The fixtures it has now detect contacts without colliding
|
|
2096
|
-
obj.setLinearDamping(damping) // Box2D's damping, 0 is none, larger slows it faster
|
|
2097
|
-
obj.setAngularDamping(damping)
|
|
2167
|
+
obj.setLinearDamping(damping) // Box2D's damping, a rate: 0 is none, larger slows it faster, no upper limit
|
|
2168
|
+
obj.setAngularDamping(damping) // the same for its turning, where an EngineObject's damping is 0 to 1
|
|
2098
2169
|
obj.setGravityScale(scale=1)
|
|
2099
2170
|
obj.setMassData(localCenter, mass, momentOfInertia) // undefined leaves that one as it is, inertia is about the
|
|
2100
2171
|
// center of mass
|
|
@@ -2205,6 +2276,46 @@ newgrounds.resendUnlocks() // advanced: send the ones whose request di
|
|
|
2205
2276
|
// the minute's session check does; one the server refused is not resent
|
|
2206
2277
|
```
|
|
2207
2278
|
|
|
2279
|
+
## LittleJS Wavedash
|
|
2280
|
+
- Optional plugin for Wavedash achievements and leaderboards, the same shape as the Newgrounds one
|
|
2281
|
+
- Wavedash serves the game's page and puts its SDK in `window.Wavedash`, so nothing is bundled; off Wavedash every call
|
|
2282
|
+
does nothing and medals unlock as any do
|
|
2283
|
+
- Make the plugin at the end of `gameInit`: it calls `Wavedash.init()`, until which Wavedash keeps its loading screen
|
|
2284
|
+
- Achievements are made with the Wavedash CLI, `--description` required; numbering the identifiers (`ACH_01_...`)
|
|
2285
|
+
orders them, since Wavedash lists them by identifier
|
|
2286
|
+
- A game built with its own minifier keeps the SDK's names (`Wavedash`, `init`, `success`, `data`, `id` and the
|
|
2287
|
+
methods) and real booleans: the SDK throws on a renamed call or a 1 for true (Terser's booleans_as_integers); the
|
|
2288
|
+
engine's own builds keep both
|
|
2289
|
+
|
|
2290
|
+
```javascript
|
|
2291
|
+
// the medals, each with the identifier of its achievement on Wavedash
|
|
2292
|
+
const medal_finish = new WavedashMedal(0, 'ACH_01_FINISH', 'Finish', 'Finish a level');
|
|
2293
|
+
function gameInit()
|
|
2294
|
+
{
|
|
2295
|
+
medalsInit('My Game');
|
|
2296
|
+
new WavedashPlugin({LEVEL_1: {lowerWins: true, display: 'milliseconds'}, HIGH_SCORE: {}}); // last, it calls init
|
|
2297
|
+
}
|
|
2298
|
+
// later, in game code
|
|
2299
|
+
medal_finish.unlock(); // Wavedash's toast on Wavedash, the engine's popup anywhere else
|
|
2300
|
+
wavedash.postScore('LEVEL_1', timeMs);
|
|
2301
|
+
|
|
2302
|
+
new WavedashMedal(id, achievement, name, description, icon, src) // a Medal that is also a Wavedash achievement; its
|
|
2303
|
+
// unlock is sent until Wavedash takes it, which it refuses until it has loaded
|
|
2304
|
+
// the player's, a moment after launch; saved unlocks are sent too; one refused
|
|
2305
|
+
// for a minute warns in the console with its identifier, a typo or not made
|
|
2306
|
+
medal.achievement // the identifier of its Wavedash achievement
|
|
2307
|
+
new WavedashPlugin(leaderboards) // sets the wavedash global, calls Wavedash.init and makes the leaderboards: by
|
|
2308
|
+
// name, lowerWins for times and golf (higher wins when left out) and display
|
|
2309
|
+
// 'number' (the default), 'seconds', 'milliseconds' or 'ticks' (60 a second)
|
|
2310
|
+
wavedash.isActive() // whether the game is on Wavedash, its SDK on the page
|
|
2311
|
+
await wavedash.postScore(name, score) // a whole number, milliseconds for a time, Wavedash keeping the best; true once
|
|
2312
|
+
// posted, false off Wavedash or when it failed or took over 15 seconds; a board
|
|
2313
|
+
// not in the table is made then, higher wins
|
|
2314
|
+
await wavedash.getScores(name, offset=0, limit=10, friendsOnly=false) // the entries as Wavedash gives them,
|
|
2315
|
+
// undefined off Wavedash or when they could not be read
|
|
2316
|
+
wavedash.leaderboards // each board's id promise by its name
|
|
2317
|
+
```
|
|
2318
|
+
|
|
2208
2319
|
## LittleJS Drawing Utilities
|
|
2209
2320
|
- Optional plugin: nine-slice and three-slice helpers for scalable UI panels, plus a crescent shape
|
|
2210
2321
|
- World-space (WebGL or 2D) and screen-space (2D by default, useWebGL for WebGL) variants
|
|
@@ -2339,7 +2450,7 @@ setLevelEditor(new MyEditor) // Make it the one in use, before the editor open
|
|
|
2339
2450
|
- Press Escape key to toggle debug overlay
|
|
2340
2451
|
- Number keys toggle debug functions while the overlay is open: 1 physics, 2 tiles (each tile layer's bounds, the
|
|
2341
2452
|
collision values on screen, and the tiles under the mouse; pressing 2 again steps through the layers one at a time,
|
|
2342
|
-
then off), 3 particles, 4 raycasts, 5 gamepads, 6 sound, 7 screenshot,
|
|
2453
|
+
then off), 3 particles, 4 raycasts, 5 gamepads, 6 sound, 7 screenshot, 9 tweakables panel,
|
|
2343
2454
|
0 level editor
|
|
2344
2455
|
- C, while the overlay is open, is a free camera for a 3D game: the mouse looks once captured or with the right
|
|
2345
2456
|
button held, WASD and QE fly, Shift is faster and the wheel sets the speed; the game runs on and reads no keys or
|
|
@@ -2364,9 +2475,6 @@ debugOverlap(posA, sizeA, posB, sizeB, color) // Draw a debug overlap between tw
|
|
|
2364
2475
|
debugClear() // Clear all debug primitives
|
|
2365
2476
|
debugScreenshot() // Save a screenshot at the end of this frame
|
|
2366
2477
|
debugShowErrors() // Show full page error message when an error occurs
|
|
2367
|
-
debugVideoCaptureStart() // Start capturing a video of the canvas
|
|
2368
|
-
debugVideoCaptureStop() // Stop capturing and save the video to disk
|
|
2369
|
-
debugVideoCaptureIsActive() // Is video currently being captured?
|
|
2370
2478
|
createCanvasContext(width, height=width, willReadFrequently=false) // Offscreen canvas to draw into, returns its
|
|
2371
2479
|
// 2D context; the canvas is context.canvas
|
|
2372
2480
|
saveCanvas(canvas, filename='screenshot', type='image/png') // Save canvas to a file
|