littlejsengine 1.18.4 → 1.18.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/README.md +19 -1
  4. package/dist/littlejs.d.ts +354 -55
  5. package/dist/littlejs.esm.js +1531 -489
  6. package/dist/littlejs.esm.min.js +1 -1
  7. package/dist/littlejs.js +1499 -476
  8. package/dist/littlejs.min.js +1 -1
  9. package/dist/littlejs.release.js +1493 -470
  10. package/package.json +8 -1
  11. package/plugins/box2d.js +32 -7
  12. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  13. package/plugins/pathFinder.js +758 -0
  14. package/plugins/pluginExport.js +19 -0
  15. package/plugins/{tween.js → tweenSystem.js} +7 -7
  16. package/plugins/uiSystem.js +186 -25
  17. package/src/engine.js +2 -141
  18. package/src/engineAudio.js +3 -3
  19. package/src/engineBuild.mjs +4 -2
  20. package/src/engineDebug.js +7 -7
  21. package/src/engineDraw.js +26 -8
  22. package/src/engineExport.js +13 -13
  23. package/src/engineInput.js +8 -8
  24. package/src/engineLogo.js +146 -0
  25. package/src/engineMath.js +15 -6
  26. package/src/engineObject.js +11 -5
  27. package/src/engineParticles.js +6 -3
  28. package/src/engineRelease.js +1 -1
  29. package/src/engineSettings.js +0 -47
  30. package/src/engineUtilities.js +13 -8
  31. package/src/engineWebGL.js +34 -7
  32. package/src/jsconfig.json +3 -1
  33. package/.github/workflows/test.yml +0 -17
  34. package/AI.md +0 -173
  35. package/CLAUDE.md +0 -1
  36. package/examples/box2d/game.js +0 -192
  37. package/examples/box2d/gameObjects.js +0 -564
  38. package/examples/box2d/index.html +0 -9
  39. package/examples/box2d/scenes.js +0 -194
  40. package/examples/box2d/tiles.png +0 -0
  41. package/examples/breakout/game.js +0 -175
  42. package/examples/breakout/gameObjects.js +0 -147
  43. package/examples/breakout/index.html +0 -8
  44. package/examples/breakout/tiles.png +0 -0
  45. package/examples/breakoutTutorial/README.md +0 -521
  46. package/examples/breakoutTutorial/game.js +0 -191
  47. package/examples/breakoutTutorial/images/1.png +0 -0
  48. package/examples/breakoutTutorial/images/10.png +0 -0
  49. package/examples/breakoutTutorial/images/11.png +0 -0
  50. package/examples/breakoutTutorial/images/2.png +0 -0
  51. package/examples/breakoutTutorial/images/3.png +0 -0
  52. package/examples/breakoutTutorial/images/4.png +0 -0
  53. package/examples/breakoutTutorial/images/5.png +0 -0
  54. package/examples/breakoutTutorial/images/6.png +0 -0
  55. package/examples/breakoutTutorial/images/7.png +0 -0
  56. package/examples/breakoutTutorial/images/8.png +0 -0
  57. package/examples/breakoutTutorial/images/9.png +0 -0
  58. package/examples/breakoutTutorial/index.html +0 -8
  59. package/examples/electron/build.mjs +0 -127
  60. package/examples/electron/electron.js +0 -35
  61. package/examples/electron/game.js +0 -54
  62. package/examples/electron/index.html +0 -13
  63. package/examples/electron/package.json +0 -5
  64. package/examples/electron/tiles.png +0 -0
  65. package/examples/empty/game.js +0 -51
  66. package/examples/empty/index.html +0 -5
  67. package/examples/empty/tiles.png +0 -0
  68. package/examples/favicon.png +0 -0
  69. package/examples/games.jpg +0 -0
  70. package/examples/htmlMenu/game.js +0 -82
  71. package/examples/htmlMenu/index.html +0 -45
  72. package/examples/htmlMenu/tiles.png +0 -0
  73. package/examples/index.html +0 -62
  74. package/examples/logo.png +0 -0
  75. package/examples/logo2.png +0 -0
  76. package/examples/module/build.mjs +0 -124
  77. package/examples/module/game.js +0 -132
  78. package/examples/module/index.html +0 -10
  79. package/examples/module/tiles.png +0 -0
  80. package/examples/particles/index.html +0 -426
  81. package/examples/particles/tiles.png +0 -0
  82. package/examples/platformer/data/gameLevelData.tmx +0 -143
  83. package/examples/platformer/data/gameLevelData.tsx +0 -4
  84. package/examples/platformer/game.js +0 -147
  85. package/examples/platformer/gameCharacter.js +0 -309
  86. package/examples/platformer/gameEffects.js +0 -278
  87. package/examples/platformer/gameLevel.js +0 -205
  88. package/examples/platformer/gameLevelData.json +0 -171
  89. package/examples/platformer/gameObjects.js +0 -378
  90. package/examples/platformer/gamePlayer.js +0 -35
  91. package/examples/platformer/index.html +0 -9
  92. package/examples/platformer/tiles.png +0 -0
  93. package/examples/platformer/tilesLevel.png +0 -0
  94. package/examples/puzzle/game.js +0 -331
  95. package/examples/puzzle/index.html +0 -8
  96. package/examples/puzzle/tiles.png +0 -0
  97. package/examples/screenshot.jpg +0 -0
  98. package/examples/shorts/animation.js +0 -18
  99. package/examples/shorts/base.html +0 -54
  100. package/examples/shorts/blending.js +0 -14
  101. package/examples/shorts/box2d.js +0 -51
  102. package/examples/shorts/box2dCar.js +0 -59
  103. package/examples/shorts/box2dPool.js +0 -107
  104. package/examples/shorts/box2dTileLayer.js +0 -48
  105. package/examples/shorts/cameraDrag.js +0 -22
  106. package/examples/shorts/clock.js +0 -21
  107. package/examples/shorts/colors.js +0 -25
  108. package/examples/shorts/debugDraw.js +0 -37
  109. package/examples/shorts/empty.js +0 -30
  110. package/examples/shorts/flappyGame.js +0 -55
  111. package/examples/shorts/fontImage.js +0 -17
  112. package/examples/shorts/fps.js +0 -90
  113. package/examples/shorts/helloWorld.js +0 -11
  114. package/examples/shorts/hillGlideGame.js +0 -63
  115. package/examples/shorts/input.js +0 -64
  116. package/examples/shorts/landerGame.js +0 -57
  117. package/examples/shorts/maze.js +0 -48
  118. package/examples/shorts/medals.js +0 -51
  119. package/examples/shorts/music.js +0 -78
  120. package/examples/shorts/musicPlayer.js +0 -137
  121. package/examples/shorts/nineSlice.js +0 -40
  122. package/examples/shorts/parallax.js +0 -72
  123. package/examples/shorts/particles.js +0 -28
  124. package/examples/shorts/piano.js +0 -44
  125. package/examples/shorts/platformer.js +0 -45
  126. package/examples/shorts/pongGame.js +0 -41
  127. package/examples/shorts/postProcess.js +0 -62
  128. package/examples/shorts/sequencer.js +0 -124
  129. package/examples/shorts/shader.js +0 -29
  130. package/examples/shorts/shapes.js +0 -21
  131. package/examples/shorts/slidingPuzzle.js +0 -52
  132. package/examples/shorts/song.mp3 +0 -0
  133. package/examples/shorts/sound.js +0 -36
  134. package/examples/shorts/spaceGame.js +0 -58
  135. package/examples/shorts/spriteAtlas.js +0 -31
  136. package/examples/shorts/starfield.js +0 -15
  137. package/examples/shorts/texture.js +0 -16
  138. package/examples/shorts/textureWrapped.js +0 -12
  139. package/examples/shorts/tileLayer.js +0 -48
  140. package/examples/shorts/tileRaycast.js +0 -39
  141. package/examples/shorts/tiles.png +0 -0
  142. package/examples/shorts/tiltedView.js +0 -63
  143. package/examples/shorts/timers.js +0 -53
  144. package/examples/shorts/topDown.js +0 -38
  145. package/examples/shorts/tween.js +0 -24
  146. package/examples/shorts/uiSystem.js +0 -61
  147. package/examples/shorts/video.webm +0 -0
  148. package/examples/shorts/videoPlayer.js +0 -34
  149. package/examples/shorts.js +0 -743
  150. package/examples/starter/build.bat +0 -7
  151. package/examples/starter/build.mjs +0 -126
  152. package/examples/starter/game.js +0 -137
  153. package/examples/starter/index.html +0 -35
  154. package/examples/starter/tiles.png +0 -0
  155. package/examples/stress/index.html +0 -173
  156. package/examples/style.css +0 -150
  157. package/examples/tweenSystem/game.js +0 -171
  158. package/examples/tweenSystem/index.html +0 -10
  159. package/examples/tweenSystem/tiles.png +0 -0
  160. package/examples/typescript/build.mjs +0 -60
  161. package/examples/typescript/game.js +0 -100
  162. package/examples/typescript/game.ts +0 -132
  163. package/examples/typescript/index.html +0 -10
  164. package/examples/typescript/tiles.png +0 -0
  165. package/examples/typescript/tsconfig.json +0 -17
  166. package/examples/uiSystem/game.js +0 -139
  167. package/examples/uiSystem/index.html +0 -10
  168. package/examples/uiSystem/tiles.png +0 -0
  169. package/jsconfig.json +0 -12
  170. package/plugins/desktop.ini +0 -2
  171. package/reference.md +0 -448
  172. package/test/math.test.mjs +0 -774
  173. package/test/setup.mjs +0 -22
  174. package/test/smoke.test.mjs +0 -274
  175. package/test/tween.test.mjs +0 -576
  176. package/test/util.test.mjs +0 -80
@@ -99,7 +99,7 @@ function glInit(rootElement)
99
99
  // reinit WebGL and restore textures
100
100
  initWebGL();
101
101
  for (const info of glTextureInfos)
102
- info.glTexture = glCreateTexture(info.image);
102
+ info.glTexture = glCreateTexture(info.image, info.wrap);
103
103
  pluginList.forEach(plugin=>plugin.glContextRestored?.());
104
104
  });
105
105
 
@@ -315,6 +315,30 @@ function glSetTexture(texture)
315
315
  glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
316
316
  }
317
317
 
318
+ /** Set the wrap mode (REPEAT or CLAMP_TO_EDGE) on an existing WebGL texture
319
+ * Flushes the current batch only if the texture is the active one
320
+ * @param {WebGLTexture} texture
321
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE
322
+ * @memberof WebGL */
323
+ function glSetTextureWrap(texture, wrap=true)
324
+ {
325
+ if (!glContext || !texture) return;
326
+
327
+ // flush only if changing wrap on the currently bound texture
328
+ const isCurrent = texture === glActiveTexture;
329
+ if (isCurrent)
330
+ glFlush();
331
+ else
332
+ glContext.bindTexture(glContext.TEXTURE_2D, texture);
333
+
334
+ const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
335
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, wrapMode);
336
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, wrapMode);
337
+
338
+ if (!isCurrent && glActiveTexture)
339
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
340
+ }
341
+
318
342
  /** Compile WebGL shader of the given type, will throw errors if in debug mode
319
343
  * @param {string} source
320
344
  * @param {number} type
@@ -359,9 +383,10 @@ function glCreateProgram(vsSource, fsSource)
359
383
  /** Create WebGL texture from an image and init the texture settings
360
384
  * Restores the active texture when done
361
385
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
386
+ * @param {boolean} [wrap] - true for REPEAT, false for CLAMP_TO_EDGE
362
387
  * @return {WebGLTexture}
363
388
  * @memberof WebGL */
364
- function glCreateTexture(image)
389
+ function glCreateTexture(image, wrap=false)
365
390
  {
366
391
  if (!glContext) return;
367
392
 
@@ -387,8 +412,9 @@ function glCreateTexture(image)
387
412
  const minFilter = mipMap ? glContext.LINEAR_MIPMAP_LINEAR : magFilter;
388
413
  glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, magFilter);
389
414
  glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, minFilter);
390
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, glContext.REPEAT);
391
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, glContext.REPEAT);
415
+ const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
416
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_S, wrapMode);
417
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_WRAP_T, wrapMode);
392
418
  if (mipMap)
393
419
  glContext.generateMipmap(glContext.TEXTURE_2D);
394
420
 
@@ -440,7 +466,7 @@ function glRegisterTextureInfo(textureInfo)
440
466
  if (textureInfo.glTexture)
441
467
  glSetTextureData(textureInfo.glTexture, textureInfo.image);
442
468
  else
443
- textureInfo.glTexture = glCreateTexture(textureInfo.image);
469
+ textureInfo.glTexture = glCreateTexture(textureInfo.image, textureInfo.wrap);
444
470
  }
445
471
 
446
472
  /** Tells WebGL to destroy the glTexture and stop tracking it
@@ -659,6 +685,7 @@ function glSetRenderTarget(texture, clear=false)
659
685
  glFlush();
660
686
  glRenderTarget = undefined;
661
687
  glContext.bindFramebuffer(glContext.FRAMEBUFFER, null);
688
+ glContext.viewport(0, 0, mainCanvasSize.x, mainCanvasSize.y);
662
689
  }
663
690
  }
664
691
 
@@ -781,9 +808,9 @@ function glPolyStrip(points)
781
808
  return area;
782
809
  }
783
810
 
784
- // ensure counter-clockwise winding
811
+ // ensure counter-clockwise winding (slice first so we don't mutate caller's array)
785
812
  if (signedArea(points) < 0)
786
- points = points.reverse();
813
+ points = points.slice().reverse();
787
814
 
788
815
  // check if point is inside triangle
789
816
  const e = 1e-9;
package/src/jsconfig.json CHANGED
@@ -2,7 +2,9 @@
2
2
  "compilerOptions": {
3
3
  "checkJs": true,
4
4
  "target": "ES2020",
5
- "module": "esnext"
5
+ "module": "esnext",
6
+ "noImplicitAny": false,
7
+ "strict": false
6
8
  },
7
9
  "exclude": [
8
10
  "engineRelease.js",
@@ -1,17 +0,0 @@
1
- name: Test
2
-
3
- on:
4
- push:
5
- pull_request:
6
-
7
- jobs:
8
- test:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - uses: actions/checkout@v5
12
- - uses: actions/setup-node@v5
13
- with:
14
- node-version: '22'
15
- - run: npm install
16
- - run: npm run build
17
- - run: npm test
package/AI.md DELETED
@@ -1,173 +0,0 @@
1
- # LittleJS Project - AI Agent Instructions
2
-
3
- These instructions are for making changes in the LittleJS repo safely. Optimize for small diffs, clarity, and ease of use.
4
-
5
- ## Non-negotiable rules
6
-
7
- - **Prefer minimal, local changes.** Do not refactor for style unless asked.
8
- - **No new runtime dependencies.** Keep LittleJS dependency-free at runtime.
9
- - **Do not hand-edit generated build artifacts.**
10
- - Treat `dist/` as generated output.
11
- - Make changes in `src/` (and `plugins/` when appropriate), then run the build.
12
- - **Match surrounding style.** Follow the conventions in the files you touch.
13
- - **Avoid breaking public APIs.** If a change could break users, call it out clearly and offer a compatible alternative.
14
-
15
- If anything in this doc conflicts with the actual repo behavior, follow the repo behavior and update this doc.
16
-
17
- ## Key resources
18
-
19
- - `README.md` - Overview and getting started
20
- - `reference.md` - API quick reference
21
- - `examples/` - Working examples demonstrating engine features
22
-
23
- ## Architecture overview
24
-
25
- LittleJS is a modular HTML5 game engine with:
26
-
27
- - **Core engine**: `src/engine*.js` (main loop, objects, rendering, physics, input, etc.)
28
- - **Plugins**: `plugins/*.js` (optional features like Box2D, post-processing, UI, audio helpers, etc.)
29
- - **Build system**: `src/engineBuild.mjs` (concatenates modules into distributable bundles)
30
-
31
- ## Repo structure and file types
32
-
33
- ### Engine source (`src/*.js`)
34
- - Modular architecture (one subsystem per file)
35
- - Concatenated at build time (internal source does not use ES modules)
36
- - Code is vanilla JavaScript with type info expressed via JSDoc comments
37
-
38
- ### Build output (`dist/`)
39
- Common outputs include:
40
- - `littlejs.js` - Full bundle (debug features included)
41
- - `littlejs.release.js` - Production bundle (debug stripped)
42
- - `littlejs.esm.js` - ES module build (import/export)
43
- - `littlejs.esm.min.js` - Minified ES module
44
- - `littlejs.d.ts` - TypeScript definitions
45
-
46
- Use via script tag or ES module import:
47
- - `<script src="dist/littlejs.js"></script>`
48
- - `import * as LJS from './dist/littlejs.esm.js'`
49
-
50
- Prefer adding new optional features as plugins when it keeps the core simpler.
51
-
52
- ### Examples
53
- - `examples/starter/` - Plain JavaScript global usage via `<script>` (recommended starting point)
54
- - `examples/module/` - ES module import pattern
55
- - `examples/typescript/` - TypeScript example usage
56
- - `examples/shorts/*.js` - Single-file demos loaded by the shorts harness
57
-
58
- ### Short examples (`examples/shorts/*.js`)
59
- Short examples are special:
60
- - Pure JS code file, no HTML
61
- - No imports, do not use LJS namespace - engine APIs are available globally
62
- - Override hooks: `gameInit()`, `gameUpdate()`, `gameUpdatePost()`, `gameRender()`, `gameRenderPost()`
63
-
64
- ## Coding conventions
65
-
66
- ### Factory functions vs constructors
67
- Prefer factory functions for core types:
68
- - `vec2(x, y)` not `new Vector2(x, y)`
69
- - `rgb(r, g, b, a)` or `hsl(h, s, l, a)` not `new Color(...)`
70
- - `tile(index, size)` for tile info
71
-
72
- Use constructors for game objects and complex types:
73
- - `new EngineObject(pos, size)`
74
- - `new ParticleEmitter(...)`
75
- - `new Sound(zzfxParams)`
76
- - `new Timer(duration)`
77
-
78
- ### Naming
79
- - `camelCase` for variables and functions
80
- - `PascalCase` for classes
81
- - `UPPER_CASE` for constants that are truly constant (like `PI`)
82
-
83
- ### Code style
84
- - Use JSDoc with `@memberof` grouping (namespaces: Engine, Math, Draw, Input, Audio, Debug, Settings, etc.)
85
- - Prefer single-line comments: `// comment`
86
- - Use `ASSERT(condition, 'error message')` for validation (stripped in release)
87
- - Use `LOG(...)` for debug output (stripped in release)
88
-
89
- ### Type checking
90
- Use built-in type helpers for validation:
91
- ```javascript
92
- isNumber(n) // true if number and not NaN
93
- isString(s) // true if not null/undefined (has toString)
94
- isArray(a) // true if array
95
- isVector2(v) // true if valid Vector2
96
- isColor(c) // true if valid Color
97
- ```
98
-
99
- ### Global variables
100
- - Engine time: `time`, `timeReal`, `frame`, `timeDelta`
101
- - Camera: `cameraPos`, `cameraScale`, `cameraAngle`
102
- - Input: `mousePos`, `mousePosScreen`, `mouseWheel`
103
- - State: `paused`, `debug`, `debugOverlay`
104
- - Settings are in `engineSettings.js` with corresponding setter functions
105
-
106
- ## Common patterns
107
-
108
- ### Game structure
109
- ```javascript
110
- function gameInit() { } // Called once after engine starts
111
- function gameUpdate() { } // Called every frame for game logic
112
- function gameUpdatePost() { } // Called after physics, even when paused
113
- function gameRender() { } // Called before objects render
114
- function gameRenderPost() { } // Called after objects render
115
-
116
- engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
117
- ```
118
-
119
- ### Creating objects
120
- ```javascript
121
- class Player extends EngineObject {
122
- constructor(pos) {
123
- super(pos, vec2(1), tile(0, 16));
124
- this.setCollision();
125
- }
126
- update() {
127
- super.update();
128
- // custom logic
129
- }
130
- }
131
- ```
132
-
133
- ### Common drawing functions
134
- ```javascript
135
- drawRect(pos, size, color) // solid rectangle
136
- drawTile(pos, size, tileInfo, color) // sprite from tile sheet
137
- drawText(text, pos, size, color) // text rendering
138
- drawLine(posA, posB, thickness, color) // line between points
139
- drawEllipse(pos, size, color) // filled ellipse
140
- ```
141
-
142
- ## Common pitfalls
143
-
144
- - **New public APIs must be added to `src/engineExport.js`** - Variables and functions added to engine source files are accessible in script-tag builds automatically, but the ESM build (`littlejs.esm.js`) and TypeScript definitions (`littlejs.d.ts`) only include what's listed in `engineExport.js`. Plugin exports go in `plugins/pluginExport.js`. Forgetting this means ESM/TS users can't access the new API.
145
- - **ASSERT and LOG are stripped in release builds** - Don't rely on side effects
146
- - **Don't modify constant colors** - `WHITE`, `BLACK`, `RED`, etc. are frozen; use `.copy()` first
147
- - **Time variables are global** - `time`, `frame` update automatically each frame
148
- - **Fixed 60 FPS timestep** - Physics runs at 60 FPS regardless of display refresh rate
149
- - **WebGL is enabled by default** - Set `glEnable = false` before `engineInit()` for Canvas2D only
150
- - **Tile coordinates are bottom-left origin** - Y increases upward in world space
151
-
152
- ## Developer workflows
153
-
154
- ### Build
155
- ```bash
156
- npm run build
157
- ```
158
-
159
- ### Testing
160
- ```bash
161
- npm test
162
- ```
163
-
164
- - Tests target `dist/littlejs.esm.js` — rebuild with `npm run build` after changing source.
165
- - [test/setup.mjs](test/setup.mjs) stubs minimal DOM and enables headless mode. Tests shouldn't call `engineInit`, `render()`, or assume `time` advances.
166
- - Zero test dependencies — uses Node's built-in `node --test`. Match the style in [test/](test/) when adding new ones.
167
- - CI runs build + test on every push/PR ([.github/workflows/test.yml](.github/workflows/test.yml)).
168
-
169
- ### Debug features
170
- - Press `Esc` to toggle debug overlay
171
- - Number keys toggle visualizations
172
- - `+`/`-` keys control time scale
173
- - Debug functions: `debugRect()`, `debugCircle()`, `debugLine()`, `debugText()`
package/CLAUDE.md DELETED
@@ -1 +0,0 @@
1
- See @AI.md for instructions.
@@ -1,192 +0,0 @@
1
- /*
2
- Little JS Box2d Demo
3
- - Demonstrates how to use Box2D with LittleJS
4
- - Several scenes to demonstrate Box2D features
5
- - Every type of shape and joint
6
- - Contact begin and end callbacks
7
- - Raycasting and querying
8
- - Collision filtering
9
- - User Interaction
10
- */
11
-
12
- 'use strict';
13
-
14
- // import LittleJS module
15
- import * as LJS from '../../dist/littlejs.esm.js';
16
- import * as GameObjects from './gameObjects.js';
17
- import * as Scenes from './scenes.js';
18
- const {vec2, hsl} = LJS;
19
-
20
- // use HD textures
21
- LJS.setCanvasPixelated(false);
22
- LJS.setTilesPixelated(false);
23
-
24
- ///////////////////////////////////////////////////////////////////////////////
25
- // game variables
26
-
27
- const sceneCount = 12;
28
- const startScene = 0;
29
- export let spriteAtlas, groundObject, mouseJoint, repeatSpawnTimer = new LJS.Timer;
30
- const sound_click = new LJS.Sound([.2,.1,,,,.01,,,,,,,,,,,,,,,-500]);
31
-
32
- ///////////////////////////////////////////////////////////////////////////////
33
- function setScene(scene)
34
- {
35
- // setup
36
- LJS.setCameraPos(vec2(20,10));
37
- LJS.setGravity(vec2(0,-20));
38
-
39
- // destroy old scene
40
- LJS.engineObjectsDestroy();
41
- mouseJoint = 0;
42
-
43
- // create walls
44
- groundObject = GameObjects.spawnBox(vec2(0,-4), vec2(1e3,8), hsl(0,0,.2), LJS.box2d.bodyTypeStatic);
45
- GameObjects.spawnBox(vec2(-4, 0), vec2(8,1e3), LJS.BLACK, LJS.box2d.bodyTypeStatic);
46
- GameObjects.spawnBox(vec2(44, 0), vec2(8,1e3), LJS.BLACK, LJS.box2d.bodyTypeStatic);
47
- GameObjects.spawnBox(vec2(0,100), vec2(1e3,8), LJS.BLACK, LJS.box2d.bodyTypeStatic);
48
-
49
- // load the scene
50
- Scenes.loadScene(scene);
51
- }
52
-
53
- ///////////////////////////////////////////////////////////////////////////////
54
- async function gameInit()
55
- {
56
- // start up LittleJS Box2D plugin
57
- await LJS.box2dInit();
58
- //LJS.box2dSetDebug(true); // enable box2d debug draw
59
-
60
- // create a table of all sprites
61
- const gameTile = (i)=> LJS.tile(i, 124, 0, 2);
62
- spriteAtlas =
63
- {
64
- circle: gameTile(0),
65
- dot: gameTile(1),
66
- circleOutline: gameTile(2),
67
- squareOutline: gameTile(3),
68
- wheel: gameTile(4),
69
- gear: gameTile(5),
70
- squareOutline2: gameTile(6),
71
- };
72
-
73
- // startup the demo
74
- LJS.setCanvasClearColor(hsl(0,0,.8));
75
- setScene(startScene);
76
- }
77
-
78
- ///////////////////////////////////////////////////////////////////////////////
79
- function gameUpdate()
80
- {
81
- // scale canvas to fit based on 1080p
82
- LJS.setCameraScale(LJS.mainCanvasSize.y * 48 / 1080);
83
-
84
- // mouse controls
85
- if (mouseJoint)
86
- {
87
- // update mouse joint
88
- mouseJoint.setTarget(LJS.mousePos);
89
- if (LJS.mouseWasReleased(0))
90
- {
91
- // release object
92
- sound_click.play(LJS.mousePos, 1, .5);
93
- mouseJoint.destroy();
94
- mouseJoint = 0;
95
- }
96
- }
97
- else if (LJS.mouseWasPressed(0))
98
- {
99
- // grab object
100
- sound_click.play(LJS.mousePos);
101
- const object = LJS.box2d.pointCast(LJS.mousePos);
102
- if (object)
103
- mouseJoint = new LJS.Box2dTargetJoint(object, groundObject, LJS.mousePos);
104
- }
105
-
106
- // controls
107
- if (LJS.mouseIsDown(1) || LJS.keyIsDown('KeyZ'))
108
- {
109
- const isSet = repeatSpawnTimer.isSet();
110
- if (!isSet || repeatSpawnTimer.elapsed())
111
- {
112
- // spawn continuously after a delay
113
- isSet || repeatSpawnTimer.set(.5);
114
- GameObjects.spawnRandomObject(LJS.mousePos);
115
- }
116
- }
117
- else
118
- repeatSpawnTimer.unset();
119
- if (LJS.mouseWasPressed(2) || LJS.keyWasPressed('KeyX'))
120
- GameObjects.explosion(LJS.mousePos);
121
-
122
- if (LJS.keyWasPressed('KeyR'))
123
- setScene(Scenes.scene); // reset scene
124
- if (LJS.keyWasPressed('ArrowUp') || LJS.keyWasPressed('ArrowDown'))
125
- {
126
- // change scene
127
- const upPressed = LJS.keyWasPressed('ArrowUp');
128
- setScene(LJS.mod(Scenes.scene + (upPressed?1:-1), sceneCount));
129
- }
130
- }
131
-
132
- ///////////////////////////////////////////////////////////////////////////////
133
- function gameUpdatePost()
134
- {
135
-
136
- }
137
-
138
- ///////////////////////////////////////////////////////////////////////////////
139
- function gameRender()
140
- {
141
- if (Scenes.scene == 5)
142
- {
143
- // raycast test
144
- const count = 100;
145
- const distance = 10;
146
- for (let i=count;i--;)
147
- {
148
- const start = LJS.mousePos;
149
- const end = start.add(vec2(distance,0).rotate(i/count*LJS.PI*2));
150
- const result = LJS.box2d.raycast(start, end);
151
- const color = result ? hsl(0,1,.5,.5) : hsl(.5,1,.5,.5);
152
- LJS.drawLine(start, result ? result.point : end, .1, color);
153
- }
154
- }
155
- }
156
-
157
- ///////////////////////////////////////////////////////////////////////////////
158
- function gameRenderPost()
159
- {
160
- if (mouseJoint)
161
- {
162
- // draw mouse joint
163
- const ab = mouseJoint.getAnchorB();
164
- LJS.drawTile(ab, vec2(.3), spriteAtlas.circle, LJS.BLACK);
165
- LJS.drawLine(LJS.mousePos, ab, .1, LJS.BLACK);
166
- }
167
-
168
- // draw demo info
169
- const pos = vec2(LJS.mainCanvasSize.x/2, 50);
170
- drawText('LittleJS Box2D Demo', 65, 70);
171
- drawText(Scenes.sceneName, 50, 100);
172
- if (Scenes.scene == 0)
173
- {
174
- drawText('Mouse Left = Grab');
175
- drawText('Mouse Middle or Z = Spawn');
176
- drawText('Mouse Right or X = Explode');
177
- drawText('Arrows Up/Down = Change Scene');
178
- }
179
- if (Scenes.scene == 3)
180
- {
181
- drawText('Right = Accelerate');
182
- drawText('Left = Reverse');
183
- }
184
-
185
- function drawText(text, size=40, gap=50)
186
- { LJS.drawTextScreen(text, pos, size, LJS.WHITE, size*.1); pos.y += gap; }
187
- }
188
-
189
- ///////////////////////////////////////////////////////////////////////////////
190
- // Startup LittleJS Engine with Box2D
191
-
192
- LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);