littlejsengine 1.18.12 → 1.18.15
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/FAQ.md +197 -15
- package/README.md +28 -7
- package/dist/littlejs.d.ts +105 -77
- package/dist/littlejs.esm.js +414 -277
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +406 -272
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +403 -265
- package/package.json +4 -1
- package/plugins/box2d.js +17 -6
- package/plugins/newgrounds.js +15 -3
- package/plugins/pathFinder.js +5 -3
- package/plugins/pluginExport.js +4 -3
- package/plugins/postProcess.js +8 -1
- package/plugins/tweenSystem.js +25 -20
- package/plugins/uiSystem.js +21 -3
- package/src/engine.js +14 -3
- package/src/engineAudio.js +27 -13
- package/src/engineBuild.mjs +1 -1
- package/src/engineDebug.js +3 -7
- package/src/engineDraw.js +71 -40
- package/src/engineExport.js +4 -2
- package/src/engineInput.js +17 -12
- package/src/engineLogo.js +1 -1
- package/src/engineMath.js +21 -7
- package/src/engineObject.js +19 -11
- package/src/engineParticles.js +26 -27
- package/src/engineSettings.js +3 -2
- package/src/engineTileLayer.js +62 -43
- package/src/engineUtilities.js +24 -11
- package/src/engineWebGL.js +23 -55
package/FAQ.md
CHANGED
|
@@ -4,7 +4,7 @@ Welcome to the LittleJS FAQ!
|
|
|
4
4
|
This document addresses common questions and issues to help developers get started and troubleshoot their projects.
|
|
5
5
|
If you don't find an answer here, feel free to ask the community or check the documentation.
|
|
6
6
|
|
|
7
|
-
Getting Started
|
|
7
|
+
**Getting Started**
|
|
8
8
|
- [What is LittleJS, and how is it different from other JavaScript game engines?](#what-is-littlejs-and-how-is-it-different-from-other-javascript-game-engines)
|
|
9
9
|
- [How do I set up a basic LittleJS project?](#how-do-i-set-up-a-basic-littlejs-project)
|
|
10
10
|
- [How do I use LittleJS as an ES module?](#how-do-i-use-littlejs-as-an-es-module)
|
|
@@ -12,11 +12,14 @@ Getting Started
|
|
|
12
12
|
- [Why do I see a blank screen when I run my game?](#why-do-i-see-a-blank-screen-when-i-run-my-game)
|
|
13
13
|
- [Do I need a local server to run LittleJS games, and how do I set one up?](#do-i-need-a-local-server-to-run-littlejs-games-and-how-do-i-set-one-up)
|
|
14
14
|
- [How does the camera and world coordinate systems work?](#how-does-the-camera-and-world-coordinate-systems-work)
|
|
15
|
+
- [How do I configure engine settings?](#how-do-i-configure-engine-settings)
|
|
16
|
+
- [What plugins ship with LittleJS?](#what-plugins-ship-with-littlejs)
|
|
15
17
|
- [How do I use Vite with LittleJS?](#how-do-i-use-vite-with-littlejs)
|
|
16
18
|
- [How do I use Box2D with Vite?](#how-do-i-use-box2d-with-vite)
|
|
17
19
|
- [How do I build and publish my game?](#how-do-i-build-and-publish-my-game)
|
|
20
|
+
- [How do I shrink my game for js13kGames?](#how-do-i-shrink-my-game-for-js13kgames)
|
|
18
21
|
|
|
19
|
-
Graphics and Sound
|
|
22
|
+
**Graphics and Sound**
|
|
20
23
|
- [How do I load and add images to my game?](#how-do-i-load-and-add-images-to-my-game)
|
|
21
24
|
- [What is the tile function and how do tile indexes work?](#what-is-the-tile-function-and-how-do-tile-indexes-work)
|
|
22
25
|
- [Can I add and switch between multiple sprites for a game object?](#can-i-add-and-switch-between-multiple-sprites-for-a-game-object)
|
|
@@ -25,20 +28,25 @@ Graphics and Sound
|
|
|
25
28
|
- [How do I control the camera in LittleJS?](#how-do-i-control-the-camera-in-littlejs)
|
|
26
29
|
- [How do I use post-processing shaders?](#how-do-i-use-post-processing-shaders)
|
|
27
30
|
- [How do I play sounds in LittleJS?](#how-do-i-play-sounds-in-littlejs)
|
|
31
|
+
- [How do I play music?](#how-do-i-play-music)
|
|
32
|
+
- [Why doesn't my audio play until the user clicks something?](#why-doesnt-my-audio-play-until-the-user-clicks-something)
|
|
28
33
|
- [If I load several images, how do I control which is used?](#if-i-load-several-images-how-do-i-control-which-is-used)
|
|
29
34
|
- [How can I check if an object is on screen?](#how-can-i-check-if-an-object-is-on-screen)
|
|
30
35
|
|
|
31
|
-
Gameplay and Programming
|
|
36
|
+
**Gameplay and Programming**
|
|
32
37
|
- [How do I add keyboard or mouse input to my game?](#how-do-i-add-keyboard-or-mouse-input-to-my-game)
|
|
33
38
|
- [How does touch input work on mobile?](#how-does-touch-input-work-on-mobile)
|
|
34
39
|
- [How do I create and update game objects?](#how-do-i-create-and-update-game-objects)
|
|
40
|
+
- [How do I use parent/child objects?](#how-do-i-use-parentchild-objects)
|
|
41
|
+
- [How do collisions work?](#how-do-collisions-work)
|
|
35
42
|
- [How can I load a 2D level map?](#how-can-i-load-a-2d-level-map)
|
|
36
43
|
- [Can I use physics with LittleJS?](#can-i-use-physics-with-littlejs)
|
|
37
44
|
- [How do I add particle effects to my game?](#how-do-i-add-particle-effects-to-my-game)
|
|
45
|
+
- [How do I use timers?](#how-do-i-use-timers)
|
|
38
46
|
- [How do I save and load game state?](#how-do-i-save-and-load-game-state)
|
|
39
47
|
- [How do I use the medals (achievements) system?](#how-do-i-use-the-medals-achievements-system)
|
|
40
48
|
|
|
41
|
-
Debugging and Development
|
|
49
|
+
**Debugging and Development**
|
|
42
50
|
- [How do I debug my game in LittleJS?](#how-do-i-debug-my-game-in-littlejs)
|
|
43
51
|
|
|
44
52
|
---
|
|
@@ -47,9 +55,9 @@ Debugging and Development
|
|
|
47
55
|
### What is LittleJS, and how is it different from other JavaScript game engines?
|
|
48
56
|
|
|
49
57
|
LittleJS is a lightweight, high-performance JavaScript game engine designed for simplicity and speed.
|
|
50
|
-
It offers a hybrid rendering system that combines the advantages of WebGL and 2D Canvas.
|
|
51
|
-
Unlike
|
|
52
|
-
LittleJS is perfect for developers who want a minimal yet powerful engine to bring their 2D game ideas to life without the complexity of larger frameworks.
|
|
58
|
+
It offers a hybrid rendering system that combines the advantages of WebGL and 2D Canvas, and in our sprite-rendering benchmarks it outperforms larger engines like Phaser, Pixi, and Kaboom.
|
|
59
|
+
Unlike those feature-heavy engines, LittleJS focuses on 2D games and providing a comprehensive set of simple, easy to use features.
|
|
60
|
+
LittleJS is perfect for developers who want a minimal yet powerful engine to bring their 2D game ideas to life without the complexity of larger frameworks, and it's especially well suited for size-constrained competitions like js13kGames.
|
|
53
61
|
|
|
54
62
|
### How do I set up a basic LittleJS project?
|
|
55
63
|
|
|
@@ -67,6 +75,7 @@ The most basic example is just an empty project.
|
|
|
67
75
|
|
|
68
76
|
<script src=../../dist/littlejs.js></script>
|
|
69
77
|
<script src=game.js></script>
|
|
78
|
+
</body></html>
|
|
70
79
|
```
|
|
71
80
|
|
|
72
81
|
[Empty Example JavaScript file:](https://github.com/KilledByAPixel/LittleJS/blob/main/examples/empty/game.js)
|
|
@@ -198,9 +207,54 @@ Another option is to setup a simple local web server like [http-server](https://
|
|
|
198
207
|
|
|
199
208
|
LittleJS drawing functions are all handled in world coordinates by default.
|
|
200
209
|
The conversion from world to screen is determined by the camera position and scale as well as the canvas size in pixels.
|
|
201
|
-
Camera scale determines how many screen pixels equals 1 world unit while the
|
|
210
|
+
Camera scale determines how many screen pixels equals 1 world unit while the cameraPos is the offset in world units.
|
|
202
211
|
There is also a function you can use called getCameraSize() to get the viewable camera window in world coordinates.
|
|
203
212
|
|
|
213
|
+
One thing to keep in mind: in **world space**, Y increases *upward* and tile coordinates use a bottom-left origin. This often surprises developers coming from Canvas2D or other 2D libraries. **Screen space** (used when you pass `screenSpace=true` to a draw function, or when reading `mousePosScreen`) follows the Canvas2D convention instead — Y increases *downward* with a top-left origin. Pick the right one for what you're doing: world space for gameplay, screen space for HUDs and UI overlays.
|
|
214
|
+
|
|
215
|
+
### How do I configure engine settings?
|
|
216
|
+
|
|
217
|
+
LittleJS exposes settings through `setX()` functions for every tunable value. Most settings need to be applied **before** `engineInit()` because they affect canvas creation, WebGL setup, or input registration:
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
setCanvasFixedSize(vec2(640, 480)); // lock canvas to a fixed resolution
|
|
221
|
+
setCanvasPixelated(true); // crisp pixel-art scaling
|
|
222
|
+
setGLEnable(false); // Canvas2D only (no WebGL)
|
|
223
|
+
setShowSplashScreen(false); // skip the LittleJS splash
|
|
224
|
+
setGravity(vec2(0, -.02)); // global gravity for physics
|
|
225
|
+
setTileDefaultSize(vec2(8)); // default tile size for tile()
|
|
226
|
+
|
|
227
|
+
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
A few common categories of settings:
|
|
231
|
+
|
|
232
|
+
- **Canvas** — `setCanvasFixedSize`, `setCanvasMaxSize`, `setCanvasMinAspect`, `setCanvasPixelated`, `setCanvasPixelRatio`
|
|
233
|
+
- **Rendering** — `setGLEnable`, `setTilesPixelated`, `setCanvasClearColor`
|
|
234
|
+
- **Physics** — `setGravity`, `setObjectDefaultDamping`, `setObjectDefaultRestitution`, `setEnablePhysicsSolver`
|
|
235
|
+
- **Audio** — `setSoundEnable`, `setSoundVolume`, `setSoundDefaultRange`
|
|
236
|
+
- **Input** — `setTouchInputEnable`, `setTouchGamepadEnable`, `setInputWASDEmulateDirection`
|
|
237
|
+
|
|
238
|
+
Camera settings (`setCameraPos`, `setCameraScale`, `setCameraAngle`) are safe to call at runtime — typically from `gameInit` or `gameUpdate`. See [src/engineSettings.js](src/engineSettings.js) for the full list with defaults.
|
|
239
|
+
|
|
240
|
+
### What plugins ship with LittleJS?
|
|
241
|
+
|
|
242
|
+
Plugins are self-contained features that live alongside the engine but aren't part of it — nothing in the core engine source references them, and they only depend on the public engine API. Drop in only what you need:
|
|
243
|
+
|
|
244
|
+
| Plugin | Purpose |
|
|
245
|
+
|--------|---------|
|
|
246
|
+
| `box2d.js` | Full Box2D physics via WebAssembly (more realistic than the built-in arcade physics) |
|
|
247
|
+
| `postProcess.js` | Shadertoy-style fragment shaders for screen-wide effects |
|
|
248
|
+
| `uiSystem.js` | Lightweight in-engine UI widgets (buttons, text, tabs) |
|
|
249
|
+
| `tweenSystem.js` | Tween any property over time with easing curves |
|
|
250
|
+
| `pathFinder.js` | Grid-based A* pathfinding with optional path smoothing |
|
|
251
|
+
| `medalSystem.js` | Achievement / medal tracking with toast notifications |
|
|
252
|
+
| `newgrounds.js` | Newgrounds.io integration (scoreboards, cloud saves) |
|
|
253
|
+
| `zzfxm.js` | Procedural chiptune music via the `ZzFXMusic` class |
|
|
254
|
+
| `drawUtilities.js` | Higher-level drawing helpers like nine-slice and three-slice |
|
|
255
|
+
|
|
256
|
+
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.
|
|
257
|
+
|
|
204
258
|
### How do I use Vite with LittleJS?
|
|
205
259
|
|
|
206
260
|
There is an official [Vite](https://vite.dev) starter template in `examples/vite-starter`. The fastest way to start a new project from it is with [degit](https://github.com/Rich-Harris/degit):
|
|
@@ -293,6 +347,17 @@ Then zip up your game folder for itch.io or push to GitHub Pages.
|
|
|
293
347
|
|
|
294
348
|
**For size coding competitions** like js13kGames, see the [js13k branch](https://github.com/KilledByAPixel/LittleJS/tree/js13k) which provides a build that fits in 7KB zipped.
|
|
295
349
|
|
|
350
|
+
### How do I shrink my game for js13kGames?
|
|
351
|
+
|
|
352
|
+
LittleJS has a dedicated [js13k branch](https://github.com/KilledByAPixel/LittleJS/tree/js13k) that builds to about 7KB zipped, leaving most of the 13KB budget for your game. A few practical tips for hitting tiny sizes:
|
|
353
|
+
|
|
354
|
+
- **Use Canvas2D instead of WebGL**: call `setGLEnable(false)` before `engineInit`. Stripping the WebGL renderer saves a significant chunk of bytes, and for most pixel-art and low-sprite-count games the visual difference is imperceptible. A nice side effect: once the jam is over, you can flip WebGL back on with a single setting change for a big performance boost when publishing the game elsewhere.
|
|
355
|
+
- **Drop unused plugins**: every plugin is self-contained, so only include what you actually use. Skip `uiSystem.js`, `box2d.js`, `pathFinder.js`, etc. unless you need them.
|
|
356
|
+
- **Lean on built-ins to avoid asset files**: `Sound` with ZzFX parameters generates sound effects from a tiny array, `ZzFXMusic` makes procedural chiptunes, and built-in shape drawing avoids shipping image assets.
|
|
357
|
+
- **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.
|
|
358
|
+
|
|
359
|
+
For normal production (non-13KB) builds, the engine ships `dist/littlejs.release.js` (asserts stripped) and `dist/littlejs.min.js` (minified) — both well under 100KB.
|
|
360
|
+
|
|
296
361
|
---
|
|
297
362
|
|
|
298
363
|
## Graphics and Sound
|
|
@@ -390,8 +455,8 @@ this.tileInfo = playerSprite.frame(animationFrame);
|
|
|
390
455
|
### How do I control the camera in LittleJS?
|
|
391
456
|
|
|
392
457
|
LittleJS uses a world space rendering system, so objects can move independently of the camera.
|
|
393
|
-
The camera is easy to control using
|
|
394
|
-
The default cameraScale is 32 while the default
|
|
458
|
+
The camera is easy to control using cameraPos and cameraScale, which indicate the world space position and how many pixels is equivalent to one world unit.
|
|
459
|
+
The default cameraScale is 32 while the default cameraPos is just the origin.
|
|
395
460
|
It is also possible to draw using screen space pixel coordinates by passing in true as the screenSpace parameter to most drawing functions.
|
|
396
461
|
|
|
397
462
|
```javascript
|
|
@@ -427,8 +492,8 @@ The constructor has two optional positional arguments after the shader source:
|
|
|
427
492
|
new PostProcessPlugin(shader, includeMainCanvas, feedbackTexture);
|
|
428
493
|
```
|
|
429
494
|
|
|
430
|
-
- `includeMainCanvas
|
|
431
|
-
- `feedbackTexture
|
|
495
|
+
- `includeMainCanvas` (default `false`) composites the Canvas2D layer (where some debug and text rendering goes) onto the WebGL canvas before the shader runs. Pass `true` if your post-process effect should apply to *everything* on screen, not just the WebGL-rendered objects.
|
|
496
|
+
- `feedbackTexture` (default `false`) makes the previous frame available as `iChannel0` for effects like motion trails or feedback loops. Mutually exclusive with `includeMainCanvas`.
|
|
432
497
|
|
|
433
498
|
See [plugins/postProcess.js](plugins/postProcess.js) and the [Breakout example](https://killedbyapixel.github.io/LittleJS/examples/breakout/) for working post-process effects.
|
|
434
499
|
|
|
@@ -444,6 +509,28 @@ const sound_jump = new Sound('jump.mp3'); // load an mp3 sound
|
|
|
444
509
|
sound_click.play(pos, volume, pitch); // play a sound
|
|
445
510
|
```
|
|
446
511
|
|
|
512
|
+
### How do I play music?
|
|
513
|
+
|
|
514
|
+
For procedural chiptune music, use the `ZzFXMusic` class from the [ZzFXM plugin](plugins/zzfxm.js). It extends `Sound` and accepts a ZzFXM-format song array — the music is generated on the fly so it adds essentially no bytes to your build. For longer scored music, load an mp3 or ogg file with the regular `Sound` class and pass `true` as the loop parameter.
|
|
515
|
+
|
|
516
|
+
```javascript
|
|
517
|
+
// procedural ZzFXM music (tiny, generated at runtime)
|
|
518
|
+
const music = new ZzFXMusic(zzfxmSongData);
|
|
519
|
+
music.play();
|
|
520
|
+
|
|
521
|
+
// or load an mp3/ogg and loop it
|
|
522
|
+
const music = new Sound('music.mp3');
|
|
523
|
+
music.play(undefined, 1, 1, 0, true); // pos, volume, rate, pan, loop
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Both pause automatically when the tab loses focus (audio context suspends) and resume when it comes back. Use `music.stop()` to halt playback.
|
|
527
|
+
|
|
528
|
+
### Why doesn't my audio play until the user clicks something?
|
|
529
|
+
|
|
530
|
+
Browsers require a user interaction (click, key press, touch) before audio is allowed to play — this is a hard rule from the browser's autoplay policy, not something the engine can bypass. LittleJS handles the actual resume for you: the audio context starts in a suspended state and is automatically resumed on the first input event. You don't need to call `audioContext.resume()` yourself.
|
|
531
|
+
|
|
532
|
+
The practical implication is that sounds you try to play during `gameInit()` or on the very first frame won't be audible. Design opening audio (title-screen music, intro sounds) so it kicks in after the first input — a common pattern is a "Press any key to start" screen that begins playing music the moment the player presses something.
|
|
533
|
+
|
|
447
534
|
### If I load several images, how do I control which is used?
|
|
448
535
|
|
|
449
536
|
Pass multiple image paths to `engineInit` and select between them with the third argument to `tile()` (the `texture` index):
|
|
@@ -543,6 +630,55 @@ Common things you'll do on an `EngineObject`:
|
|
|
543
630
|
- `this.gravityScale = 0` — disable gravity for this object (e.g. UI or floating objects)
|
|
544
631
|
- `this.destroy()` — remove from the world (calls cleanup on children too)
|
|
545
632
|
|
|
633
|
+
### How do I use parent/child objects?
|
|
634
|
+
|
|
635
|
+
`EngineObject` supports a parent/child hierarchy with local transforms. Attached children automatically follow their parent's position, angle, and mirror state each frame:
|
|
636
|
+
|
|
637
|
+
```javascript
|
|
638
|
+
const ship = new EngineObject(vec2(10, 5), vec2(2));
|
|
639
|
+
const turret = new EngineObject(vec2(), vec2(.5));
|
|
640
|
+
ship.addChild(turret, vec2(0, .5)); // turret sits .5 units above the ship in local space
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
`addChild(child, localPos, localAngle)` attaches the child with a local offset; the child's world-space `pos` and `angle` are recomputed each frame from the parent's transform. To detach, call `parent.removeChild(child)` — or just `child.destroy()`, which also detaches it (and destroying a parent destroys all its children).
|
|
644
|
+
|
|
645
|
+
A few things to know:
|
|
646
|
+
- **Mirroring a parent flips children** — a mirrored ship has its turret on the correct side automatically (`localPos.x` and `localAngle` are inverted).
|
|
647
|
+
- **Velocity is not inherited** — physics runs on the world transform after parenting, so a child doesn't automatically pick up the parent's velocity. If you need that, set the child's velocity manually before attaching.
|
|
648
|
+
- **For decorative attachments** that shouldn't be affected by physics, set `gravityScale = 0` and skip `setCollision()` on the child.
|
|
649
|
+
|
|
650
|
+
### How do collisions work?
|
|
651
|
+
|
|
652
|
+
Opt in to collision on an `EngineObject` by calling `setCollision()` — by default it's off so most objects don't pay the collision cost.
|
|
653
|
+
|
|
654
|
+
```javascript
|
|
655
|
+
class Player extends EngineObject {
|
|
656
|
+
constructor(pos) {
|
|
657
|
+
super(pos, vec2(1), tile(0, 16));
|
|
658
|
+
this.setCollision(); // collide with solid objects and tile map
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
`setCollision(collideSolidObjects, isSolid, collideTiles, collideRaycast)` — all default to `true`. Pass `false` to opt out of any of them (e.g. a ghost that passes through walls: `setCollision(false, false, false)`).
|
|
664
|
+
|
|
665
|
+
For custom collision logic, override `collideWithObject(other)` and `collideWithTile(tileData, pos)` on your subclass. Return `true` to actually block the collision, `false` to pass through. Both fire during the physics step:
|
|
666
|
+
|
|
667
|
+
```javascript
|
|
668
|
+
class Bullet extends EngineObject {
|
|
669
|
+
collideWithObject(other) {
|
|
670
|
+
if (other instanceof Enemy) {
|
|
671
|
+
other.damage(1);
|
|
672
|
+
this.destroy();
|
|
673
|
+
return false; // don't physically bounce off the enemy
|
|
674
|
+
}
|
|
675
|
+
return true; // solid collision with everything else
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
For raycasting against the tile collision map (line-of-sight checks, hitscan weapons, etc.), use `tileCollisionRaycast(start, end)` which returns the hit position or `undefined`.
|
|
681
|
+
|
|
546
682
|
### How can I load a 2D level map?
|
|
547
683
|
|
|
548
684
|
There are two parts that work together to make 2D level maps in LittleJS.
|
|
@@ -578,6 +714,36 @@ new ParticleEmitter(
|
|
|
578
714
|
);
|
|
579
715
|
```
|
|
580
716
|
|
|
717
|
+
### How do I use timers?
|
|
718
|
+
|
|
719
|
+
The `Timer` class is a small but very useful utility for anything that needs to happen *after some time has passed* — cooldowns, animation timing, delayed spawns, fades, etc. It tracks elapsed time automatically, so you don't have to add `timeDelta` to a variable every frame.
|
|
720
|
+
|
|
721
|
+
```javascript
|
|
722
|
+
const cooldown = new Timer(2); // 2-second timer, starts immediately
|
|
723
|
+
|
|
724
|
+
function gameUpdate() {
|
|
725
|
+
if (cooldown.elapsed()) {
|
|
726
|
+
fireWeapon();
|
|
727
|
+
cooldown.set(2); // restart it
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Useful methods:
|
|
733
|
+
- `set(seconds)` — start or restart the timer
|
|
734
|
+
- `unset()` — disable it (`isSet()` becomes false)
|
|
735
|
+
- `active()` / `elapsed()` — boolean checks
|
|
736
|
+
- `get()` — seconds elapsed (negative while still counting down)
|
|
737
|
+
- `getPercent()` — 0 → 1 progress, handy for easing animations
|
|
738
|
+
|
|
739
|
+
By default, a timer ticks on **game time** — it pauses when the game is paused and slows down or speeds up with `setTimeScale`. For UI animations, on-screen notifications, or anything that should keep running regardless of game state, use a real-time timer:
|
|
740
|
+
|
|
741
|
+
```javascript
|
|
742
|
+
const uiFade = new Timer(.5, true); // useRealTime = true
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Real-time timers track `timeReal` instead of `time` — unaffected by pause or time scale. You can also flip an existing timer between modes with `timer.setUseRealTime(true)` while it's unset.
|
|
746
|
+
|
|
581
747
|
### How do I save and load game state?
|
|
582
748
|
|
|
583
749
|
LittleJS has built-in helpers for localStorage-backed save data — no need to roll your own JSON serialization:
|
|
@@ -618,10 +784,26 @@ The plugin also supports [Newgrounds](https://www.newgrounds.com) integration vi
|
|
|
618
784
|
|
|
619
785
|
### How do I debug my game in LittleJS?
|
|
620
786
|
|
|
621
|
-
In addition to your browser's built
|
|
622
|
-
|
|
787
|
+
In addition to your browser's built-in developer tools, LittleJS has its own debug overlay. Press `Esc` to show it — the overlay lists the available toggles and their number-key bindings, so you don't have to memorize them. `+` and `-` adjust the time scale, which is great for slowing tricky moments down or speeding past a slow section.
|
|
788
|
+
|
|
789
|
+
**Debug draw functions** let you visualize state directly in the world without committing to permanent UI. They're drawn for one frame and only render in debug builds:
|
|
790
|
+
|
|
791
|
+
```javascript
|
|
792
|
+
debugRect(pos, size, color); // outline a rectangle
|
|
793
|
+
debugCircle(pos, radius, color); // outline a circle
|
|
794
|
+
debugLine(posA, posB, color); // a line between two points
|
|
795
|
+
debugText(string, pos, size, color); // text at a world position
|
|
796
|
+
debugPoint(pos, color); // small marker
|
|
797
|
+
```
|
|
623
798
|
|
|
624
|
-
|
|
799
|
+
These are perfect for "where exactly is this AI heading?" or "is this hitbox where I think it is?" investigations — drop a call into your update or render code, see the answer, then delete it.
|
|
800
|
+
|
|
801
|
+
**`ASSERT` and `LOG`** are similar to `console.assert` / `console.log`, but they're *stripped from release builds* (`littlejs.release.js`, `littlejs.min.js`). That means you can leave them in your code with no cost to shipped users. Don't rely on side effects inside the arguments — they won't run in release.
|
|
802
|
+
|
|
803
|
+
```javascript
|
|
804
|
+
ASSERT(player.health > 0, 'player damaged below zero', player);
|
|
805
|
+
LOG('spawned enemy at', pos);
|
|
806
|
+
```
|
|
625
807
|
|
|
626
808
|
---
|
|
627
809
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[![Build Size][build-size]][build-size-url]
|
|
9
9
|
[![NPM Downloads][npm-downloads]][npmtrends-url]
|
|
10
10
|
[![DeepScan][deepscan]][deepscan-url]
|
|
11
|
+
[![MIT License][license]][license-url]
|
|
11
12
|
[![Discord][discord]][discord-url]
|
|
12
13
|
|
|
13
14
|
</div>
|
|
@@ -24,7 +25,7 @@ The code is very clean and well documented with many examples to get you started
|
|
|
24
25
|
|
|
25
26
|
<div align='center' markdown='1'>
|
|
26
27
|
|
|
27
|
-
## [Demos](https://killedbyapixel.github.io/LittleJS/examples) | [Docs](https://killedbyapixel.github.io/LittleJS/docs) | [
|
|
28
|
+
## [Demos](https://killedbyapixel.github.io/LittleJS/examples) | [Docs](https://killedbyapixel.github.io/LittleJS/docs) | [Reference](https://github.com/KilledByAPixel/LittleJS/blob/main/REFERENCE.md) | [FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md) | [Trailer](https://youtu.be/chuBzGjv7Ms) | [Discord](https://discord.gg/zb7hcGkyZe)
|
|
28
29
|
|
|
29
30
|
</div>
|
|
30
31
|
|
|
@@ -89,21 +90,37 @@ npm install
|
|
|
89
90
|
npm run dev
|
|
90
91
|
```
|
|
91
92
|
|
|
93
|
+
Here is a minimal Hello World example game.
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<!DOCTYPE html>
|
|
97
|
+
<script src="../dist/littlejs.js"></script>
|
|
98
|
+
<script>
|
|
99
|
+
function gameInit() {}
|
|
100
|
+
function gameUpdate() {}
|
|
101
|
+
function gameUpdatePost() {}
|
|
102
|
+
function gameRender() {}
|
|
103
|
+
function gameRenderPost() { drawTextScreen('Hello World!', mainCanvasSize.scale(.5), 80); }
|
|
104
|
+
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost);
|
|
105
|
+
</script>
|
|
106
|
+
```
|
|
107
|
+
|
|
92
108
|
## Tutorials
|
|
93
109
|
|
|
94
110
|
- [Making Awesome Games With LittleJS](https://youtu.be/_dXKU0WgAj8?si=ZDXLYAFDWp54hrGT) - A short talk about LittleJS with some tips on how to use it.
|
|
95
111
|
- [Tutorial: Breakout](https://github.com/KilledByAPixel/LittleJS/tree/main/examples/breakoutTutorial) - Learn how to make a simple game from scratch
|
|
96
112
|
- [Tutorial: Make a ski game](https://eoinmcgrath.com/little-ski/tutorial.html) - This tutorial by eoinmcg that shows how to make a pixel art style game.
|
|
97
|
-
- [LittleJS Quick Reference Sheet](https://github.com/KilledByAPixel/LittleJS/blob/main/
|
|
113
|
+
- [LittleJS Quick Reference Sheet](https://github.com/KilledByAPixel/LittleJS/blob/main/REFERENCE.md) - A reference sheet to help you get started.
|
|
98
114
|
- [Little JS FAQ](https://github.com/KilledByAPixel/LittleJS/blob/main/FAQ.md) - Answers to common questions about LittleJS.
|
|
99
115
|
- [JS13k Branch](https://github.com/KilledByAPixel/LittleJS/tree/js13k) - For size coding events like JS13k there is a special branch that builds to a 7KB zip.
|
|
100
116
|
- [LittleJS AI Tools](https://github.com/KilledByAPixel/LittleJS-AI) - Experiments, games, and templates to improve LittleJS + AI workflows.
|
|
101
117
|
|
|
102
118
|
## Examples
|
|
103
119
|
|
|
104
|
-
LittleJS comes with
|
|
120
|
+
LittleJS comes with several demos both for learning and using as starter projects to create new games.
|
|
105
121
|
|
|
106
|
-
- [Example Browser](https://killedbyapixel.github.io/LittleJS/examples/) - Live example browser with all examples
|
|
122
|
+
- [Example Browser](https://killedbyapixel.github.io/LittleJS/examples/) - Live example browser with all examples and editable source
|
|
123
|
+
- [Short Examples](https://github.com/KilledByAPixel/LittleJS/tree/main/examples/shorts) - 60+ single-file demos showing off individual engine features
|
|
107
124
|
- [Breakout](https://killedbyapixel.github.io/LittleJS/examples/breakout/) - Block breaking game with post-processing effects
|
|
108
125
|
- [Puzzle Game](https://killedbyapixel.github.io/LittleJS/examples/puzzle/) - Match 3 puzzle game with HD rendering and high score tracking
|
|
109
126
|
- [Platformer](https://killedbyapixel.github.io/LittleJS/examples/platformer/) - Platformer/shooter demo that loads level data
|
|
@@ -141,13 +158,15 @@ Here are a few of the many amazing games created with LittleJS...
|
|
|
141
158
|
- [Bug&Bee](https://itch.io/jam/littlejs-game-jam-2025/results) - Low fi shoot em up with co-op gameplay. LittleJS Jam 1st place! by [eoinmcg](https://eoinmcg.itch.io/)
|
|
142
159
|
- [Little Platformer](https://psemo.itch.io/little-platformer) - Platformer with many mechanics. LittleJS Jam 2st place! by [PSEMO](https://psemo.itch.io/), [Solita666](https://itch.io/profile/solita666), [GabrielRG](https://gabrielrg.itch.io/), [Nate](https://natesassoon.itch.io/)
|
|
143
160
|
- [Rogue Pong](https://itch.io/jam/littlejs-game-jam-2025/rate/4004165) - Roguelike crossed with classic pong gameplay. LittleJS Jam 3rd place! by [webdevbrian](https://webdevbrian.itch.io/)
|
|
144
|
-
- [
|
|
161
|
+
- [Alien Escape Pinball](https://focaccai.itch.io/alien-pinball) - Pinball game with physics and aliens. by [Focaccai](https://www.focaccai.com/)
|
|
145
162
|
- [LittleJS Jam 2024 Results](https://itch.io/jam/littlejs-jam-2024/results) - All the games from the first LittleJS Game Jam.
|
|
146
163
|
- [LittleJS Jam 2025 Results](https://itch.io/jam/littlejs-game-jam-2025/results) - All the games from the second LittleJS Game Jam.
|
|
147
164
|
|
|
148
|
-

|
|
166
|
+
|
|
167
|
+
*A sample of games built with LittleJS.*
|
|
149
168
|
|
|
150
|
-

|
|
151
170
|
|
|
152
171
|
[npm]: https://img.shields.io/npm/v/littlejsengine
|
|
153
172
|
[npm-url]: https://www.npmjs.com/package/littlejsengine
|
|
@@ -159,3 +178,5 @@ Here are a few of the many amazing games created with LittleJS...
|
|
|
159
178
|
[deepscan-url]: https://deepscan.io/dashboard#view=project&tid=22950&pid=26229&bid=831487
|
|
160
179
|
[discord]: https://img.shields.io/discord/939926111469568050
|
|
161
180
|
[discord-url]: https://discord.gg/zb7hcGkyZe
|
|
181
|
+
[license]: https://img.shields.io/github/license/KilledByAPixel/LittleJS
|
|
182
|
+
[license-url]: https://github.com/KilledByAPixel/LittleJS/blob/main/LICENSE
|