littlejsengine 1.26.1 → 1.27.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.
- package/CHANGELOG.md +16 -0
- package/FAQ.md +3 -2
- package/README.md +4 -3
- package/REFERENCE.md +38 -0
- package/dist/littlejs.d.ts +181 -16
- package/dist/littlejs.esm.js +810 -98
- package/dist/littlejs.esm.min.js +3 -3
- package/dist/littlejs.js +810 -98
- package/dist/littlejs.min.js +2 -2
- package/dist/littlejs.release.js +790 -92
- package/package.json +1 -1
- package/plugins/lightSystem.js +84 -2
- package/plugins/newgrounds.js +92 -0
- package/plugins/parallax.js +3 -1
- package/plugins/render3dEditor.js +20 -6
- package/plugins/render3dExtras.js +1 -0
- package/plugins/wavedash.js +235 -4
- package/src/engine.js +24 -3
- package/src/engineObject.js +244 -65
- package/src/engineParticles.js +8 -3
- package/src/engineTileLayer.js +95 -10
- package/src/engineWebGL.js +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ 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.27.0 - 2026-10-08
|
|
11
|
+
|
|
12
|
+
### New Changes
|
|
13
|
+
- 2D lights have cones and gels, as 3D spotlights do: `light.coneAngle` makes a light a cone, like a flashlight or a car's headlights, looking along its up and turned by its `angle`, its edge fading by `coneSoftness`; `light.gel` is a picture the light shines through, a tile or a texture across its square that turns with it, so one light can be a car's headlights and tail lights. Shadows still fall through both, and a light with neither draws as before. The Light System short has a swinging searchlight, and Light Shadows a mouse light shining through colored panes
|
|
14
|
+
- One way collision, platforms jumped up through and landed on: `layer.setOneWay(tile, direction)` makes the cells that draw a tile passable moving that way, up, down, left or right, so they block only what was wholly on their far side before it moved; turned and mirrored as each cell's tile is, so a platform turned a quarter is one way to the side. Objects, particles and raycasts all follow it, `collideWithTile` is not asked about a tile passed through, and returning false from it drops through. A solid object's `oneWay` does the same for objects, and a rising platform keeps its rider. The new Platform Physics short shows it with a lift, a crate, a bouncy ball and an ice floor
|
|
15
|
+
- `obj.isBullet` for small fast objects: it moves through the tiles as a point along a ray, so it never passes through a tile at any speed and is not held to objectMaxSpeed for them; `collideWithTile` sees it where it meets the tile, so sparks start on the surface; it bounces by restitution and goes on with the rest of its move, so it rolls along a floor as a box does. One with a size that collides with solid objects is still held to objectMaxSpeed. The platformer's bullets use it in place of their own raycast
|
|
16
|
+
- Cloud saves on Newgrounds and Wavedash, the same on both: `cloudSave(slot, data)` keeps any value JSON can hold for the player, `cloudLoad(slot)` gives it back, null for an empty slot and undefined for a load that failed, so a game does not save over a save it could not load, with `loadFailure(slot)` saying when the slot holds a file that is not a save, and off the platform or not logged in they do nothing; Wavedash stats, `setStat` and `getStat`, and presence, `setPresence(status, details)`; Newgrounds events, `logEvent(name)`. The Newgrounds calls are built from its API docs and not yet tried on the site
|
|
17
|
+
|
|
18
|
+
### Fixes
|
|
19
|
+
- An object of no size is no longer held to objectMaxSpeed by `collideSolidObjects`, since it never collides with solids; one with `collideLevel` and a mass still is
|
|
20
|
+
- A Shader disposed before its first draw was drawn stayed in the engine's list of shaders, the flush compiling it put it back
|
|
21
|
+
- A ParticleEmitter3D callback that changed a particle's `age` or `lifeTime` had the change thrown away, now it is kept as `pos` and `velocity` are
|
|
22
|
+
- A light pass whose `renderLight` or `renderEmissive` throws hands back the screen, its viewport, texture and blend, where a game that caught the error went on drawing into the lightmap
|
|
23
|
+
- A tile layer redraw whose `onRedraw` or tile draw throws hands back the camera, the canvas and the draw target, where it left the game drawing into the layer
|
|
24
|
+
- 3D level editor: a scale drag keeps a mirrored axis mirrored, where it turned every negative axis to the smallest size; a turned object lands, drops and pastes by the box around it as turned; opening the editor lets go of a mouse the game captured; a frame that throws gives the game its camera back; an orthographic game camera's near is not copied to the editor's view; the box select is drawn over a 3D pass drawn after the 2D
|
|
25
|
+
|
|
10
26
|
## 1.26.1 - 2026-10-08
|
|
11
27
|
|
|
12
28
|
### New Changes
|
package/FAQ.md
CHANGED
|
@@ -282,7 +282,8 @@ Plugins are self-contained features that live alongside the engine but aren't pa
|
|
|
282
282
|
| `pathFinder.js` | Grid-based A* pathfinding with optional path smoothing |
|
|
283
283
|
| `tweakables.js` | A debug panel to change values live while the game runs, press 9 with the debug overlay open |
|
|
284
284
|
| `medalSystem.js` | Achievement / medal tracking with popup notifications |
|
|
285
|
-
| `newgrounds.js` | Newgrounds.io integration (medals held on the server, scoreboards) |
|
|
285
|
+
| `newgrounds.js` | Newgrounds.io integration (medals held on the server, scoreboards, cloud saves, events) |
|
|
286
|
+
| `wavedash.js` | Wavedash integration (achievements, leaderboards, cloud saves, stats, presence), the same shape as the Newgrounds one |
|
|
286
287
|
| `audioEffects.js` | Web Audio effects like filter, reverb, delay, distortion and compressor, for a group of sounds or everything |
|
|
287
288
|
| `drawUtilities.js` | Higher-level drawing helpers like nine-slice and three-slice |
|
|
288
289
|
| `render3dVoxels.js` | `VoxelMap`, a 3D grid of blocks that draws itself and that objects collide with |
|
|
@@ -826,7 +827,7 @@ medal_firstWin.unlock();
|
|
|
826
827
|
|
|
827
828
|
You can pass an image URL as the fifth argument to `Medal` instead of an emoji icon. The `saveName` you pass to `medalsInit` is used to track which medals have been unlocked in localStorage, so unlocks persist across visits. Give it a name of its own, not the one you pass to `readSaveData` and `writeSaveData`, or the medals and your save data overwrite each other.
|
|
828
829
|
|
|
829
|
-
The plugin also supports [Newgrounds](https://www.newgrounds.com) scoreboards and medals held on the server through [plugins/newgrounds.js](plugins/newgrounds.js): create each medal as a `NewgroundsMedal` with the id Newgrounds gave it, call `medalsInit` as usual, then `new NewgroundsPlugin(app_id, cipher)`. The "LittleJS Medals & Newgrounds" section of REFERENCE.md has a short example.
|
|
830
|
+
The plugin also supports [Newgrounds](https://www.newgrounds.com) scoreboards and medals held on the server through [plugins/newgrounds.js](plugins/newgrounds.js): create each medal as a `NewgroundsMedal` with the id Newgrounds gave it, call `medalsInit` as usual, then `new NewgroundsPlugin(app_id, cipher)`. The "LittleJS Medals & Newgrounds" section of REFERENCE.md has a short example. [plugins/wavedash.js](plugins/wavedash.js) does the same for [Wavedash](https://wavedash.com/) with `WavedashMedal` and `WavedashPlugin`, and both have `cloudSave(slot, data)` and `cloudLoad(slot)` to keep a player's save on the platform.
|
|
830
831
|
|
|
831
832
|
---
|
|
832
833
|
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ The code is very clean and well documented with many examples to get you started
|
|
|
39
39
|
|
|
40
40
|
- Blazing fast WebGL2 + Canvas2D hybrid rendering system
|
|
41
41
|
- Apply [Shadertoy](https://www.shadertoy.com) style shaders for post-processing effects, or on any object or draw
|
|
42
|
-
- 2D lights with soft shadows, tinted glass and emissive objects
|
|
42
|
+
- 2D lights with soft shadows, tinted glass and emissive objects, a sun with long shadows, and spotlight cones and gels
|
|
43
43
|
- Robust particle effect system with a library of ready made effects and an [effect design tool](https://killedbyapixel.github.io/LittleJS/examples/particles/)
|
|
44
44
|
- Parallax background layers that repeat across a level of any size
|
|
45
45
|
- Load sprites and animations into texture sheets at runtime, or import [TexturePacker](https://www.codeandweb.com/texturepacker) and [Aseprite](https://www.aseprite.org) atlases
|
|
@@ -74,7 +74,8 @@ The code is very clean and well documented with many examples to get you started
|
|
|
74
74
|
### 💥 Physics
|
|
75
75
|
|
|
76
76
|
- Robust arcade physics system with collision handling
|
|
77
|
-
- Fast tilemap collision and raycasting
|
|
77
|
+
- Fast tilemap collision and raycasting, with one-way platforms that turn with their tiles
|
|
78
|
+
- Swept bullet collision, so small fast objects never pass through a wall
|
|
78
79
|
- Object collision that stays fast with thousands of objects
|
|
79
80
|
- Full Box2D integration for realistic physics using [Box2D v2.3.1 wasm](https://github.com/kripken/box2d.js)
|
|
80
81
|
- Grid-based A* pathfinding plugin with optional path smoothing
|
|
@@ -96,7 +97,7 @@ The code is very clean and well documented with many examples to get you started
|
|
|
96
97
|
- UI system with buttons, sliders, text input and nine-slice skins
|
|
97
98
|
- Tween system with easing curves, and a scene system for titles, menus and game states
|
|
98
99
|
- Debug overlay and primitive rendering system
|
|
99
|
-
-
|
|
100
|
+
- Medals, leaderboards and cloud saves on [Newgrounds](https://www.newgrounds.com/) and [Wavedash](https://wavedash.com/)
|
|
100
101
|
- Node.js build system
|
|
101
102
|
|
|
102
103
|
### 🤖 AI Friendly
|
package/REFERENCE.md
CHANGED
|
@@ -689,6 +689,12 @@ EngineObject.clampSpeed // Hold each axis of velocity to objectMaxSpeed while
|
|
|
689
689
|
// while it has a mass, so it can not pass through a thin wall; true by default, false for
|
|
690
690
|
// a fast bullet that collides; what does not collide moves as fast as it is told
|
|
691
691
|
EngineObject.parent / children // Set by addChild, a child is placed by its parent and sits out solid collision
|
|
692
|
+
EngineObject.isBullet // Moves through the tiles as a point along a ray, never passing one at any speed and not held
|
|
693
|
+
// to objectMaxSpeed for them; collideWithTile sees it where it meets the tile; on a hit it
|
|
694
|
+
// bounces by restitution and goes on with the rest of its move, so it rolls along a floor;
|
|
695
|
+
// its collision with solid objects is the usual one, so one with a size is still clamped
|
|
696
|
+
EngineObject.oneWay // Up, down, left or right, like vec2(0, 1): a solid passed through that way, a platform
|
|
697
|
+
// jumped up through; it blocks only what was wholly on its far side or stood on it
|
|
692
698
|
|
|
693
699
|
// Engine Object settings
|
|
694
700
|
enablePhysicsSolver = true // Enable collisions, between objects and with tiles, and in 3D with solids and the level?
|
|
@@ -766,6 +772,12 @@ TileCollisionLayer.collisionTest(pos, size=(0,0), object) // Like tileCollisionT
|
|
|
766
772
|
TileCollisionLayer.collisionRaycast(posStart, posEnd, object, normal) // Like tileCollisionRaycast for this layer only
|
|
767
773
|
TileCollisionLayer.isSolid = true // Solid layers block objects and particles, the solidOnly tests
|
|
768
774
|
// skip the others
|
|
775
|
+
TileCollisionLayer.setOneWay(tile, direction=vec2(0,1)) // The cells drawing that tile index are passed through
|
|
776
|
+
// moving that way and block only what was wholly on the far
|
|
777
|
+
// side, objects, particles and rays; turned and mirrored with
|
|
778
|
+
// each cell's art; vec2(0, 1) is a platform jumped up through
|
|
779
|
+
TileCollisionLayer.oneWayTiles // Map of the one way tiles, tile index to direction; delete one
|
|
780
|
+
// to make it solid again
|
|
769
781
|
tileCollisionGetData(pos, solidOnly=true) // Get tile collision data at pos
|
|
770
782
|
tileCollisionTest(pos, size=(0,0), object) // Check if collision should occur
|
|
771
783
|
tileCollisionRaycast(posStart, posEnd, callbackObject, normal, solidOnly=true) // Where the ray meets the first tile hit,
|
|
@@ -1137,6 +1149,11 @@ new Light(pos, radius, color=WHITE, fadeRange=radius)
|
|
|
1137
1149
|
light.glow = 0 // size across of a soft hazy glow over the light, like a lamp at night, 0 for none; added
|
|
1138
1150
|
// over the lit scene after the lightmap, so it shows in the dark, in front of everything
|
|
1139
1151
|
light.glowFalloff = 1 // how fast the glow fades from its middle, .5 a wide haze, 2 a tight bright core
|
|
1152
|
+
light.coneAngle = 0 // a cone, like a flashlight or headlight: radians from its up to the cone's edge, the beam
|
|
1153
|
+
// twice this across; it looks along getUp(), turned by its angle; 0 shines every way
|
|
1154
|
+
light.coneSoftness = .2 // how much of the cone is its fading edge: 0 a hard edge, 1 fading from the middle
|
|
1155
|
+
light.gel = tileInfo // or a whole TextureInfo: a picture the light shines through, across its square, its top
|
|
1156
|
+
// the way it looks, turned with it, multiplied into its color; shadows still fall
|
|
1140
1157
|
|
|
1141
1158
|
// One directional light, a sun: lights the whole scene from one direction, added with the point lights
|
|
1142
1159
|
new DirectionalLight(sunDirection=vec2(-1,1), color=WHITE) // toward the sun, as render3D.sunDirection; its color
|
|
@@ -2270,6 +2287,15 @@ newgrounds.postScore(id, value) // needs a logged in player and a whole num
|
|
|
2270
2287
|
await newgrounds.getScores(id, user, social, skip, limit, period) // the scores are in result.data.scores; period
|
|
2271
2288
|
// 'D' today (the server default), 'W', 'M', 'Y', 'A' all time; a user or social
|
|
2272
2289
|
// narrows it down, and without either it is the whole board even when logged in
|
|
2290
|
+
await newgrounds.cloudSave(slot, data) // any value JSON can hold, to a slot numbered from 1, as many as the app's
|
|
2291
|
+
// settings give; needs a logged in player; true once saved, false with a
|
|
2292
|
+
// warning for a value JSON can not hold
|
|
2293
|
+
await newgrounds.cloudLoad(slot) // the value saved there, null when the slot is empty, undefined when it could
|
|
2294
|
+
// not be loaded or the player is not logged in: never save over one undefined
|
|
2295
|
+
newgrounds.loadFailure(slot) // why that slot's last cloudLoad gave undefined: 'notSave' for a file there that
|
|
2296
|
+
// is not a save, where a game may offer to start over, else 'failed'; a saved
|
|
2297
|
+
// null loads as null, as an empty slot does
|
|
2298
|
+
newgrounds.logEvent(name) // count an event of the game's own, by name, on its stats page
|
|
2273
2299
|
newgrounds.unlockMedal(id) // low level request only, the medal is not changed; games call medal.unlock()
|
|
2274
2300
|
newgrounds.pendingUnlocks // advanced: the unlocks in flight or waiting to be resent, with their promises
|
|
2275
2301
|
newgrounds.resendUnlocks() // advanced: send the ones whose request did not reach the server again now, as
|
|
@@ -2314,6 +2340,18 @@ await wavedash.postScore(name, score) // a whole number, milliseconds for a time
|
|
|
2314
2340
|
await wavedash.getScores(name, offset=0, limit=10, friendsOnly=false) // the entries as Wavedash gives them,
|
|
2315
2341
|
// undefined off Wavedash or when they could not be read
|
|
2316
2342
|
wavedash.leaderboards // each board's id promise by its name
|
|
2343
|
+
await wavedash.cloudSave(slot, data) // any value JSON can hold, kept across devices as saves/slot#.json; at most 30
|
|
2344
|
+
// saves a minute and 300 an hour, so at checkpoints; true once saved, false
|
|
2345
|
+
// with a warning for a value JSON can not hold
|
|
2346
|
+
await wavedash.cloudLoad(slot) // the value saved there, null when the slot is empty, undefined when it could
|
|
2347
|
+
// not be loaded or off Wavedash: never save over one that loaded undefined
|
|
2348
|
+
wavedash.loadFailure(slot) // why that slot's last cloudLoad gave undefined: 'notSave' for a file there that
|
|
2349
|
+
// is not a save, where a game may offer to start over, else 'failed'; a saved
|
|
2350
|
+
// null loads as null, as an empty slot does
|
|
2351
|
+
await wavedash.setStat(name, value, storeNow=false) // a stat made in the developer portal, kept a second later or
|
|
2352
|
+
// at once; the player's stats load the first time one is used
|
|
2353
|
+
await wavedash.getStat(name) // a stat's value, 0 for one never set or off Wavedash
|
|
2354
|
+
await wavedash.setPresence(status, details) // what the player is doing, kept with their presence; none clears it
|
|
2317
2355
|
```
|
|
2318
2356
|
|
|
2319
2357
|
## LittleJS Drawing Utilities
|
package/dist/littlejs.d.ts
CHANGED
|
@@ -4110,16 +4110,6 @@ declare module "littlejsengine" {
|
|
|
4110
4110
|
* @return {Float32Array} - The audio samples
|
|
4111
4111
|
* @memberof Audio */
|
|
4112
4112
|
export function zzfxG(volume?: number, randomness?: number, frequency?: number, attack?: number, sustain?: number, release?: number, shape?: number, shapeCurve?: number, slide?: number, deltaSlide?: number, pitchJump?: number, pitchJumpTime?: number, repeatTime?: number, noise?: number, modulation?: number, bitCrush?: number, delay?: number, sustainVolume?: number, decay?: number, tremolo?: number, filter?: number): Float32Array;
|
|
4113
|
-
/**
|
|
4114
|
-
* LittleJS Object System
|
|
4115
|
-
* - EngineObject is the base class for all game objects
|
|
4116
|
-
* - Handles automatic updating, rendering, physics, and collision
|
|
4117
|
-
* - Supports parent-child hierarchies with transform inheritance
|
|
4118
|
-
* - 2D physics with velocity, acceleration, damping, and gravity
|
|
4119
|
-
* - Collision system with tiles and other objects
|
|
4120
|
-
* - Renders sprites from tile sheets with color and rotation
|
|
4121
|
-
* - Objects sorted by renderOrder for layered rendering
|
|
4122
|
-
*/
|
|
4123
4113
|
/**
|
|
4124
4114
|
* LittleJS Object Base Object Class
|
|
4125
4115
|
* - Top level object class used by the engine
|
|
@@ -4219,9 +4209,27 @@ declare module "littlejsengine" {
|
|
|
4219
4209
|
children: Array<EngineObject>;
|
|
4220
4210
|
/** @property {boolean} - Limit object speed along x and y axis */
|
|
4221
4211
|
clampSpeed: boolean;
|
|
4212
|
+
/** @property {boolean} - Move through the tiles as a point along a ray, so it can not pass through one at
|
|
4213
|
+
* any speed, for small fast things like bullets: its speed is not held to objectMaxSpeed for the tiles,
|
|
4214
|
+
* collideWithTile is asked with this.pos where the ray goes into the tile, and on a hit it stops at the
|
|
4215
|
+
* surface, bounces off it by restitution and goes on with the rest of its move, so it slides along a floor
|
|
4216
|
+
* - Its collision with solid objects is the usual one, so one with a size that collides with them is still held
|
|
4217
|
+
* to objectMaxSpeed; one of no size is not, it never collides with them
|
|
4218
|
+
* - this.pos is set for each tile asked about and put where the move ends after, so a change collideWithTile
|
|
4219
|
+
* makes to it is not kept; move it after the physics, in update
|
|
4220
|
+
* - Once destroyed, as by its own collideWithTile, it is asked about no more tiles that frame, where an object
|
|
4221
|
+
* that is not a bullet still is */
|
|
4222
|
+
isBullet: boolean;
|
|
4222
4223
|
/** @property {EngineObject|undefined} - Object we are standing on, if any
|
|
4223
4224
|
* @type {EngineObject|undefined} */
|
|
4224
4225
|
groundObject: EngineObject | undefined;
|
|
4226
|
+
/** @property {Vector2|undefined} - Makes a solid object one way, like a platform jumped up through: up, down,
|
|
4227
|
+
* left or right, the way others pass through it; it blocks only what was wholly on its far side before it
|
|
4228
|
+
* moved, or stood on it, and the rest are not stopped or asked through collideWithObject; with no mass it
|
|
4229
|
+
* moves before the other objects each frame, so a lift works the same at any render order; tiles are made one
|
|
4230
|
+
* way by the layer's setOneWay
|
|
4231
|
+
* @type {Vector2|undefined} */
|
|
4232
|
+
oneWay: Vector2 | undefined;
|
|
4225
4233
|
/** @property {EngineObject|undefined} - Parent of object if in local space
|
|
4226
4234
|
* @type {EngineObject|undefined} */
|
|
4227
4235
|
parent: EngineObject | undefined;
|
|
@@ -4250,6 +4258,10 @@ declare module "littlejsengine" {
|
|
|
4250
4258
|
* update: a solid an override moves for another object, a lift carrying a crate, is found there from the next
|
|
4251
4259
|
* update on */
|
|
4252
4260
|
updatePhysics(): void;
|
|
4261
|
+
/** @private */
|
|
4262
|
+
private updatePhysicsBullet;
|
|
4263
|
+
/** @private */
|
|
4264
|
+
private updatePhysicsTiles;
|
|
4253
4265
|
/** Update the object, called automatically by engine once each frame. Does nothing by default */
|
|
4254
4266
|
update(): void;
|
|
4255
4267
|
/** Render the object, draws a tile by default, automatically called each frame, sorted by renderOrder */
|
|
@@ -4287,10 +4299,10 @@ declare module "littlejsengine" {
|
|
|
4287
4299
|
/** Called to check if a tile collision should be resolved. Return true for physics to resolve the collision or false to ignore and resolve it manually
|
|
4288
4300
|
* - Called for each solid tile the physics tests, which can be several times a frame for the same tile, and for
|
|
4289
4301
|
* positions it only tries, so keep it free of side effects or guard them to once a frame
|
|
4290
|
-
* - this.pos has already moved, so a check on where it came from
|
|
4291
|
-
*
|
|
4292
|
-
* - For the point of impact, like sparks where a bullet hit,
|
|
4293
|
-
*
|
|
4302
|
+
* - this.pos has already moved, so a check on where it came from needs the position saved in update; for a one
|
|
4303
|
+
* way platform the layer's setOneWay does that, and this is not asked about a one way tile it passes through
|
|
4304
|
+
* - For the point of impact, like sparks where a bullet hit, set isBullet: this.pos is then where it meets the
|
|
4305
|
+
* tile, as the platformer's Bullet uses it
|
|
4294
4306
|
* @param {number} tileData - the value of the tile at the position
|
|
4295
4307
|
* @param {Vector2} pos - the tile's bottom left corner in world space
|
|
4296
4308
|
* @return {boolean} - true if the collision should be resolved by modifying it's position and velocity */
|
|
@@ -4712,6 +4724,24 @@ declare module "littlejsengine" {
|
|
|
4712
4724
|
/** @property {boolean} - In the light system's shadow pass, cast only from the cells with collision, drawn
|
|
4713
4725
|
* as the layer shows them, so a floor in the same layer stays lit; false casts every tile */
|
|
4714
4726
|
shadowSolidOnly: boolean;
|
|
4727
|
+
/** @property {Map<number, Vector2>} - The tiles set one way, by tile index, and the way each can be passed
|
|
4728
|
+
* through, see setOneWay
|
|
4729
|
+
* @type {Map<number, Vector2>} */
|
|
4730
|
+
oneWayTiles: Map<number, Vector2>;
|
|
4731
|
+
/** Make the cells that draw a tile one way, like a platform jumped up through and landed on: an object, a
|
|
4732
|
+
* particle or a ray passes through moving that way, and the tile blocks only what was wholly on its far side
|
|
4733
|
+
* before it moved, the side it is passed toward; turned and mirrored as each cell's tile is, so a platform turned
|
|
4734
|
+
* a quarter is one way to the side
|
|
4735
|
+
* - A moving object is not stopped or asked through collideWithTile until the tile would block it, so a
|
|
4736
|
+
* collideWithTile that returns false lets it drop through
|
|
4737
|
+
* - tileCollisionTest with an object goes by the object's pos, a raycast by its start, and a test with no object
|
|
4738
|
+
* or with a callback finds every one way tile solid
|
|
4739
|
+
* @param {number} tile - The tile index, as tile() and TileLayerData take it
|
|
4740
|
+
* @param {Vector2} [direction] - Up, down, left or right, the way it can be passed through: vec2(0, 1), the
|
|
4741
|
+
* default, is a platform landed on from above; layer.oneWayTiles.delete(tile) makes the tile solid again
|
|
4742
|
+
* @example
|
|
4743
|
+
* layer.setOneWay(5); // tile 5 is a platform, jumped up through and stood on */
|
|
4744
|
+
setOneWay(tile: number, direction?: Vector2): void;
|
|
4715
4745
|
/** Clear and initialize tile collision, the size is the layer's own, the tile data and canvas keep it
|
|
4716
4746
|
* @param {Vector2} size - width and height of tile collision 2d grid */
|
|
4717
4747
|
initCollision(size: Vector2): void;
|
|
@@ -5133,6 +5163,8 @@ declare module "littlejsengine" {
|
|
|
5133
5163
|
/** @property {Array<Object>} - Scoreboards fetched from Newgrounds, empty until ready
|
|
5134
5164
|
* @type {Array<Object>} */
|
|
5135
5165
|
scoreboards: Array<any>;
|
|
5166
|
+
/** @type {Map<number, 'failed'|'notSave'>} */
|
|
5167
|
+
loadFailures: Map<number, 'failed' | 'notSave'>;
|
|
5136
5168
|
/** @property {{id: number, name: string, url: string, supporter: boolean}|null} - The logged in player once ready, null when not logged in
|
|
5137
5169
|
* @type {{id: number, name: string, url: string, supporter: boolean}|null} */
|
|
5138
5170
|
user: {
|
|
@@ -5182,6 +5214,42 @@ declare module "littlejsengine" {
|
|
|
5182
5214
|
* result.data.scores, each with user.name, value and formatted_value; without a user or social it is the whole board
|
|
5183
5215
|
*/
|
|
5184
5216
|
getScores(id: number, user?: string | number, social?: boolean, skip?: number, limit?: number, period?: string): Promise<any>;
|
|
5217
|
+
/** Save a value to one of the player's cloud save slots, which needs a logged in player
|
|
5218
|
+
* - Any value JSON can hold; the slots are numbered from 1, as many as the app's Newgrounds settings give it
|
|
5219
|
+
* @param {number} slot - The slot number
|
|
5220
|
+
* @param {*} data - The value to save
|
|
5221
|
+
* @return {Promise<boolean>} - Whether it saved, false when not logged in
|
|
5222
|
+
* @example
|
|
5223
|
+
* newgrounds.cloudSave(1, {level, coins}); */
|
|
5224
|
+
cloudSave(slot: number, data: any): Promise<boolean>;
|
|
5225
|
+
/** Load the value a cloud save slot holds: null when Newgrounds says it holds none, undefined when it could not be
|
|
5226
|
+
* loaded or the player is not logged in, said in the console when logged in
|
|
5227
|
+
* - Do not save over a slot that loaded as undefined, it may hold the player's save; loadFailure(slot) says why
|
|
5228
|
+
* it did: 'notSave' for a file there that is not a save, where a game may offer to start over, 'failed' otherwise
|
|
5229
|
+
* - A saved null loads as null, as an empty slot does
|
|
5230
|
+
* @param {number} slot - The slot number
|
|
5231
|
+
* @return {Promise<*>} - The value saved, null for none, undefined for a load that failed
|
|
5232
|
+
* @example
|
|
5233
|
+
* const save = await newgrounds.cloudLoad(1); */
|
|
5234
|
+
cloudLoad(slot: number): Promise<any>;
|
|
5235
|
+
/** Why a slot's last cloudLoad gave undefined: 'notSave' when the slot holds a file that is not a save, where a
|
|
5236
|
+
* game may offer to start over, 'failed' when it could not be loaded, as when not logged in, where a game must
|
|
5237
|
+
* not save over it; undefined when it loaded a save or found the slot empty, or was not loaded
|
|
5238
|
+
* @param {number} slot - The slot number
|
|
5239
|
+
* @return {'failed'|'notSave'|undefined} */
|
|
5240
|
+
loadFailure(slot: number): 'failed' | 'notSave' | undefined;
|
|
5241
|
+
/** A slot's load, its value and why it failed, if it did
|
|
5242
|
+
* @param {number} slot
|
|
5243
|
+
* @return {Promise<{value: *, failure: 'failed'|'notSave'|undefined}>}
|
|
5244
|
+
* @ignore */
|
|
5245
|
+
loadSlot(slot: number): Promise<{
|
|
5246
|
+
value: any;
|
|
5247
|
+
failure: 'failed' | 'notSave' | undefined;
|
|
5248
|
+
}>;
|
|
5249
|
+
/** Count an event of the game's own on its Newgrounds stats page, like a level finished or a button pressed
|
|
5250
|
+
* @param {string} name - The event's name
|
|
5251
|
+
* @return {Promise<Object>} - The response JSON object, undefined when the call failed */
|
|
5252
|
+
logEvent(name: string): Promise<any>;
|
|
5185
5253
|
/** Encrypt text the way the Newgrounds gateway expects, AES-128 CBC with a random iv in front, as Base64
|
|
5186
5254
|
* @param {string} text
|
|
5187
5255
|
* @return {Promise<string>} */
|
|
@@ -5210,7 +5278,8 @@ declare module "littlejsengine" {
|
|
|
5210
5278
|
}
|
|
5211
5279
|
/**
|
|
5212
5280
|
* LittleJS Wavedash Plugin
|
|
5213
|
-
* - The Wavedash twin of the Newgrounds plugin: achievements and
|
|
5281
|
+
* - The Wavedash twin of the Newgrounds plugin: achievements, leaderboards and cloud saves, the same shape so a game
|
|
5282
|
+
* can switch, and stats and presence of Wavedash's own
|
|
5214
5283
|
* - Wavedash serves the game's page and puts its SDK in window.Wavedash before the game runs, so nothing is bundled;
|
|
5215
5284
|
* off Wavedash (local, itch, GitHub Pages) there is none, and every call does nothing
|
|
5216
5285
|
* - Make the plugin when the game can draw, at the end of gameInit: Wavedash.init is called then, and until it is
|
|
@@ -5270,6 +5339,14 @@ declare module "littlejsengine" {
|
|
|
5270
5339
|
};
|
|
5271
5340
|
/** @type {number|undefined} */
|
|
5272
5341
|
achievementRetry: number | undefined;
|
|
5342
|
+
/** @type {Promise<boolean>|undefined} */
|
|
5343
|
+
stats: Promise<boolean> | undefined;
|
|
5344
|
+
/** @type {Map<string, Promise<*>>} */
|
|
5345
|
+
slotQueues: Map<string, Promise<any>>;
|
|
5346
|
+
/** @type {Map<string, Set<Promise<*>>>} */
|
|
5347
|
+
slotCalls: Map<string, Set<Promise<any>>>;
|
|
5348
|
+
/** @type {Map<string, 'failed'|'notSave'>} */
|
|
5349
|
+
loadFailures: Map<string, 'failed' | 'notSave'>;
|
|
5273
5350
|
/** Whether the game is on Wavedash, its SDK on the page
|
|
5274
5351
|
* @return {boolean} */
|
|
5275
5352
|
isActive(): boolean;
|
|
@@ -5298,6 +5375,74 @@ declare module "littlejsengine" {
|
|
|
5298
5375
|
* @param {boolean} [friendsOnly] - Only the player and their friends
|
|
5299
5376
|
* @return {Promise<Array<Object>|undefined>} - The entries, as Wavedash gives them */
|
|
5300
5377
|
getScores(name: string, offset?: number, limit?: number, friendsOnly?: boolean): Promise<Array<any> | undefined>;
|
|
5378
|
+
/** Save a value to one of the player's cloud save slots, kept by Wavedash across devices; off Wavedash it does
|
|
5379
|
+
* nothing
|
|
5380
|
+
* - Any value JSON can hold, stored as the file saves/slot#.json
|
|
5381
|
+
* - Wavedash takes at most 30 saves a minute and 300 an hour from a player, so save at checkpoints, the end of a
|
|
5382
|
+
* level or when asked, not every frame; one over the limit is refused, said in the console
|
|
5383
|
+
* @param {number} slot - The slot number, any whole number the game picks
|
|
5384
|
+
* @param {*} data - The value to save
|
|
5385
|
+
* @return {Promise<boolean>} - Whether it saved
|
|
5386
|
+
* @example
|
|
5387
|
+
* wavedash.cloudSave(1, {level, coins}); */
|
|
5388
|
+
cloudSave(slot: number, data: any): Promise<boolean>;
|
|
5389
|
+
/** Load the value a cloud save slot holds: null when Wavedash says it holds none, undefined when it could not be
|
|
5390
|
+
* loaded or off Wavedash, said in the console on Wavedash
|
|
5391
|
+
* - Do not save over a slot that loaded as undefined, it may hold the player's save; loadFailure(slot) says why
|
|
5392
|
+
* it did: 'notSave' for a file there that is not a save, where a game may offer to start over, 'failed' otherwise
|
|
5393
|
+
* - A saved null loads as null, as an empty slot does
|
|
5394
|
+
* @param {number} slot - The slot number
|
|
5395
|
+
* @return {Promise<*>} - The value saved, null for none, undefined for a load that failed
|
|
5396
|
+
* @example
|
|
5397
|
+
* const save = await wavedash.cloudLoad(1); */
|
|
5398
|
+
cloudLoad(slot: number): Promise<any>;
|
|
5399
|
+
/** Why a slot's last cloudLoad gave undefined: 'notSave' when the slot holds a file that is not a save, where a
|
|
5400
|
+
* game may offer to start over, 'failed' when it could not be loaded, as off Wavedash or on a timeout, where a
|
|
5401
|
+
* game must not save over it; undefined when it loaded a save or found the slot empty, or was not loaded
|
|
5402
|
+
* @param {number} slot - The slot number
|
|
5403
|
+
* @return {'failed'|'notSave'|undefined} */
|
|
5404
|
+
loadFailure(slot: number): 'failed' | 'notSave' | undefined;
|
|
5405
|
+
/** A slot's load, its value and why it failed, if it did
|
|
5406
|
+
* @param {number} slot
|
|
5407
|
+
* @param {function(*): *} track
|
|
5408
|
+
* @return {Promise<{value: *, failure: 'failed'|'notSave'|undefined}>}
|
|
5409
|
+
* @ignore */
|
|
5410
|
+
loadSlot(slot: number, track: (arg0: any) => any): Promise<{
|
|
5411
|
+
value: any;
|
|
5412
|
+
failure: 'failed' | 'notSave' | undefined;
|
|
5413
|
+
}>;
|
|
5414
|
+
/** Run a slot's save or load after the one before it, as they share the slot's local file; other slots go on
|
|
5415
|
+
* at once, and one that fails does not hold up the next
|
|
5416
|
+
* - A call that timed out may still change the file when Wavedash gets to it, so the next waits for it to be
|
|
5417
|
+
* answered too, and gives up with failed when it is not, leaving the file alone
|
|
5418
|
+
* @param {number} slot
|
|
5419
|
+
* @param {*} failed - What the task gives when it can not run
|
|
5420
|
+
* @param {function(function(*): *): Promise<*>} task - Given track, which keeps a call's answer until it is in
|
|
5421
|
+
* @return {Promise<*>}
|
|
5422
|
+
* @ignore */
|
|
5423
|
+
slotQueue(slot: number, failed: any, task: (arg0: (arg0: any) => any) => Promise<any>): Promise<any>;
|
|
5424
|
+
/** Set one of the player's stats, as made for the game in the Wavedash developer portal, which can unlock an
|
|
5425
|
+
* achievement set to follow it; Wavedash keeps it about a second later, or at once with storeNow; off Wavedash it
|
|
5426
|
+
* does nothing
|
|
5427
|
+
* @param {string} name - The stat's identifier
|
|
5428
|
+
* @param {number} value
|
|
5429
|
+
* @param {boolean} [storeNow] - Keep it now, as at the end of a game, not a second later
|
|
5430
|
+
* @return {Promise<boolean>} - Whether Wavedash took it */
|
|
5431
|
+
setStat(name: string, value: number, storeNow?: boolean): Promise<boolean>;
|
|
5432
|
+
/** Read one of the player's stats, 0 for one never set or off Wavedash
|
|
5433
|
+
* @param {string} name - The stat's identifier
|
|
5434
|
+
* @return {Promise<number>} */
|
|
5435
|
+
getStat(name: string): Promise<number>;
|
|
5436
|
+
/** The player's stats loaded from Wavedash, which they must be before they are read or set, asked for the first
|
|
5437
|
+
* time a stat is
|
|
5438
|
+
* @return {Promise<boolean>} - Whether they loaded
|
|
5439
|
+
* @ignore */
|
|
5440
|
+
statsLoaded(): Promise<boolean>;
|
|
5441
|
+
/** Set what the player is doing, kept with their presence on Wavedash; off Wavedash it does nothing
|
|
5442
|
+
* @param {string} [status] - One line of what they are doing, like 'In a race'
|
|
5443
|
+
* @param {string} [details] - More about it, like 'Lap 2 of 3'; both left out clears it
|
|
5444
|
+
* @return {Promise<boolean>} - Whether it was set */
|
|
5445
|
+
setPresence(status?: string, details?: string): Promise<boolean>;
|
|
5301
5446
|
/** Send every unlocked WavedashMedal's achievement Wavedash has not taken yet, again every two seconds while it
|
|
5302
5447
|
* refuses some, as it does until it has loaded the player's achievements; one refused for about a minute is
|
|
5303
5448
|
* taken as an identifier Wavedash does not have, said once in the console, and not sent again this visit
|
|
@@ -5713,11 +5858,16 @@ declare module "littlejsengine" {
|
|
|
5713
5858
|
* - A light inside a caster is blocked entirely, so the object that holds it, its lamp, a torch, the player
|
|
5714
5859
|
* carrying it, needs a shadowCore that reaches past it, castShadow = false, or a renderShadow that leaves
|
|
5715
5860
|
* the light's spot out
|
|
5861
|
+
* - A coneAngle makes it a cone along its up, turned by its angle, and a gel is a picture it shines through; both
|
|
5862
|
+
* are applied over the round light with its shadows, so they cost next to nothing
|
|
5716
5863
|
* @extends EngineObject
|
|
5717
5864
|
* @memberof LightSystem
|
|
5718
5865
|
* @example
|
|
5719
5866
|
* new Light(vec2(5, 5), 4, rgb(1, 0.5, 0)); // orange light, full soft blob
|
|
5720
5867
|
* new Light(vec2(0, 0), 8, rgb(1, 1, 1), 2); // white core with 2-unit soft halo
|
|
5868
|
+
* const flashlight = new Light(vec2(), 10); // a flashlight looking right, its beam 60 degrees across
|
|
5869
|
+
* flashlight.coneAngle = PI/6;
|
|
5870
|
+
* flashlight.angle = PI/2;
|
|
5721
5871
|
*/
|
|
5722
5872
|
export class Light extends EngineObject {
|
|
5723
5873
|
/** Create a light object and add it to the engine object list
|
|
@@ -5742,6 +5892,19 @@ declare module "littlejsengine" {
|
|
|
5742
5892
|
glowFalloff: number;
|
|
5743
5893
|
/** @type {TileInfo|undefined} */
|
|
5744
5894
|
glowTileInfo: TileInfo | undefined;
|
|
5895
|
+
/** @property {number} - Makes it a cone, like a flashlight or headlight: the angle in radians from its up out
|
|
5896
|
+
* to the edge of the cone, so the beam is twice this across; it looks along getUp(), turned by its angle and
|
|
5897
|
+
* by what it is attached to; 0 for a light that shines every way */
|
|
5898
|
+
coneAngle: number;
|
|
5899
|
+
/** @property {number} - How much of the cone is its fading edge: 0 a hard edge, .2 by default, the outer
|
|
5900
|
+
* fifth, 1 fading all the way from the middle of the beam */
|
|
5901
|
+
coneSoftness: number;
|
|
5902
|
+
/** @property {TileInfo|TextureInfo|undefined} - A gel, a picture the light shines through, called a cookie in
|
|
5903
|
+
* some engines: stretched across the light's square, twice its radius, its top the way the light looks,
|
|
5904
|
+
* turned with it, and multiplied into its color, so one light can be a car's headlights and tail lights;
|
|
5905
|
+
* a TileInfo's own tile, or a whole TextureInfo; shadows still fall through it
|
|
5906
|
+
* @type {TileInfo|TextureInfo|undefined} */
|
|
5907
|
+
gel: TileInfo | TextureInfo | undefined;
|
|
5745
5908
|
/** Draw this light's glow, soft and round, its glow size across and in its color, added over the lit scene;
|
|
5746
5909
|
* called by LightSystemPlugin after the lightmap is applied */
|
|
5747
5910
|
renderGlow(): void;
|
|
@@ -8068,7 +8231,9 @@ declare module "littlejsengine" {
|
|
|
8068
8231
|
* and 1 with the screen, a Vector2 to follow x and y by different amounts
|
|
8069
8232
|
* @param {number} [renderOrder] - Low to draw behind the game, far layers lowest
|
|
8070
8233
|
* @param {function(OffscreenCanvasRenderingContext2D, Vector2, ParallaxLayer): void} [drawFunction] - Draws
|
|
8071
|
-
* the image, given the canvas context, its size in pixels and the layer; mountains when not given
|
|
8234
|
+
* the image, given the canvas context, its size in pixels and the layer; mountains when not given; called
|
|
8235
|
+
* once when the layer is made and on redraw(), not each frame, so it draws with the canvas 2D context, not
|
|
8236
|
+
* the engine's draws like drawTile
|
|
8072
8237
|
* @param {Vector2} [canvasSize] - Size of the image in pixels */
|
|
8073
8238
|
constructor(pos?: Vector2, size?: Vector2, parallax?: number | Vector2, renderOrder?: number, drawFunction?: (arg0: OffscreenCanvasRenderingContext2D, arg1: Vector2, arg2: ParallaxLayer) => void, canvasSize?: Vector2);
|
|
8074
8239
|
/** @property {Vector2} - How much of the camera's movement it follows on each axis, 0 stays with the world
|