littlejsengine 1.18.2 → 1.18.7

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 (172) hide show
  1. package/COPYRIGHT.txt +38 -0
  2. package/FAQ.md +633 -0
  3. package/LICENSE +5 -27
  4. package/README.md +19 -1
  5. package/dist/littlejs.d.ts +550 -57
  6. package/dist/littlejs.esm.js +2208 -492
  7. package/dist/littlejs.esm.min.js +1 -1
  8. package/dist/littlejs.js +2165 -480
  9. package/dist/littlejs.min.js +1 -1
  10. package/dist/littlejs.release.js +2166 -481
  11. package/package.json +8 -1
  12. package/plugins/box2d.js +36 -9
  13. package/{src/engineMedals.js → plugins/medalSystem.js} +248 -196
  14. package/plugins/pathFinder.js +758 -0
  15. package/plugins/pluginExport.js +26 -0
  16. package/plugins/tween.js +509 -0
  17. package/plugins/tweenSystem.js +509 -0
  18. package/plugins/uiSystem.js +151 -12
  19. package/src/engine.js +9 -145
  20. package/src/engineAudio.js +8 -5
  21. package/src/engineBuild.mjs +4 -1
  22. package/src/engineDebug.js +1 -1
  23. package/src/engineDraw.js +154 -5
  24. package/src/engineExport.js +17 -12
  25. package/src/engineInput.js +27 -1
  26. package/src/engineLogo.js +146 -0
  27. package/src/engineMath.js +10 -3
  28. package/src/engineObject.js +11 -5
  29. package/src/engineParticles.js +6 -3
  30. package/src/engineRelease.js +1 -1
  31. package/src/engineSettings.js +17 -47
  32. package/src/engineUtilities.js +7 -2
  33. package/src/engineWebGL.js +31 -8
  34. package/src/jsconfig.json +3 -1
  35. package/.claude/settings.local.json +0 -7
  36. package/.github/workflows/test.yml +0 -17
  37. package/AI.md +0 -172
  38. package/CLAUDE.md +0 -1
  39. package/examples/box2d/game.js +0 -192
  40. package/examples/box2d/gameObjects.js +0 -564
  41. package/examples/box2d/index.html +0 -9
  42. package/examples/box2d/scenes.js +0 -194
  43. package/examples/box2d/tiles.png +0 -0
  44. package/examples/breakout/game.js +0 -175
  45. package/examples/breakout/gameObjects.js +0 -147
  46. package/examples/breakout/index.html +0 -8
  47. package/examples/breakout/tiles.png +0 -0
  48. package/examples/breakoutTutorial/README.md +0 -521
  49. package/examples/breakoutTutorial/game.js +0 -191
  50. package/examples/breakoutTutorial/images/1.png +0 -0
  51. package/examples/breakoutTutorial/images/10.png +0 -0
  52. package/examples/breakoutTutorial/images/11.png +0 -0
  53. package/examples/breakoutTutorial/images/2.png +0 -0
  54. package/examples/breakoutTutorial/images/3.png +0 -0
  55. package/examples/breakoutTutorial/images/4.png +0 -0
  56. package/examples/breakoutTutorial/images/5.png +0 -0
  57. package/examples/breakoutTutorial/images/6.png +0 -0
  58. package/examples/breakoutTutorial/images/7.png +0 -0
  59. package/examples/breakoutTutorial/images/8.png +0 -0
  60. package/examples/breakoutTutorial/images/9.png +0 -0
  61. package/examples/breakoutTutorial/index.html +0 -8
  62. package/examples/electron/build.mjs +0 -127
  63. package/examples/electron/electron.js +0 -35
  64. package/examples/electron/game.js +0 -54
  65. package/examples/electron/index.html +0 -13
  66. package/examples/electron/package.json +0 -5
  67. package/examples/electron/tiles.png +0 -0
  68. package/examples/empty/game.js +0 -51
  69. package/examples/empty/index.html +0 -5
  70. package/examples/empty/tiles.png +0 -0
  71. package/examples/favicon.png +0 -0
  72. package/examples/games.jpg +0 -0
  73. package/examples/htmlMenu/game.js +0 -82
  74. package/examples/htmlMenu/index.html +0 -45
  75. package/examples/htmlMenu/tiles.png +0 -0
  76. package/examples/index.html +0 -800
  77. package/examples/logo.png +0 -0
  78. package/examples/logo2.png +0 -0
  79. package/examples/module/build.mjs +0 -124
  80. package/examples/module/game.js +0 -132
  81. package/examples/module/index.html +0 -10
  82. package/examples/module/tiles.png +0 -0
  83. package/examples/particles/index.html +0 -426
  84. package/examples/particles/tiles.png +0 -0
  85. package/examples/platformer/data/gameLevelData.tmx +0 -143
  86. package/examples/platformer/data/gameLevelData.tsx +0 -4
  87. package/examples/platformer/game.js +0 -147
  88. package/examples/platformer/gameCharacter.js +0 -309
  89. package/examples/platformer/gameEffects.js +0 -278
  90. package/examples/platformer/gameLevel.js +0 -205
  91. package/examples/platformer/gameLevelData.json +0 -171
  92. package/examples/platformer/gameObjects.js +0 -378
  93. package/examples/platformer/gamePlayer.js +0 -35
  94. package/examples/platformer/index.html +0 -9
  95. package/examples/platformer/tiles.png +0 -0
  96. package/examples/platformer/tilesLevel.png +0 -0
  97. package/examples/puzzle/game.js +0 -331
  98. package/examples/puzzle/index.html +0 -8
  99. package/examples/puzzle/tiles.png +0 -0
  100. package/examples/screenshot.jpg +0 -0
  101. package/examples/shorts/animation.js +0 -18
  102. package/examples/shorts/base.html +0 -54
  103. package/examples/shorts/blending.js +0 -14
  104. package/examples/shorts/box2d.js +0 -51
  105. package/examples/shorts/box2dCar.js +0 -59
  106. package/examples/shorts/box2dPool.js +0 -107
  107. package/examples/shorts/box2dTileLayer.js +0 -48
  108. package/examples/shorts/cameraDrag.js +0 -22
  109. package/examples/shorts/clock.js +0 -21
  110. package/examples/shorts/colors.js +0 -25
  111. package/examples/shorts/debugDraw.js +0 -37
  112. package/examples/shorts/empty.js +0 -30
  113. package/examples/shorts/flappyGame.js +0 -55
  114. package/examples/shorts/fontImage.js +0 -17
  115. package/examples/shorts/fps.js +0 -90
  116. package/examples/shorts/helloWorld.js +0 -11
  117. package/examples/shorts/hillGlideGame.js +0 -63
  118. package/examples/shorts/input.js +0 -64
  119. package/examples/shorts/landerGame.js +0 -57
  120. package/examples/shorts/maze.js +0 -48
  121. package/examples/shorts/medals.js +0 -51
  122. package/examples/shorts/music.js +0 -78
  123. package/examples/shorts/musicPlayer.js +0 -137
  124. package/examples/shorts/nineSlice.js +0 -40
  125. package/examples/shorts/parallax.js +0 -72
  126. package/examples/shorts/particles.js +0 -28
  127. package/examples/shorts/piano.js +0 -44
  128. package/examples/shorts/platformer.js +0 -45
  129. package/examples/shorts/pongGame.js +0 -41
  130. package/examples/shorts/postProcess.js +0 -62
  131. package/examples/shorts/sequencer.js +0 -124
  132. package/examples/shorts/shader.js +0 -29
  133. package/examples/shorts/shapes.js +0 -21
  134. package/examples/shorts/slidingPuzzle.js +0 -52
  135. package/examples/shorts/song.mp3 +0 -0
  136. package/examples/shorts/sound.js +0 -36
  137. package/examples/shorts/spaceGame.js +0 -58
  138. package/examples/shorts/spriteAtlas.js +0 -31
  139. package/examples/shorts/starfield.js +0 -15
  140. package/examples/shorts/texture.js +0 -16
  141. package/examples/shorts/tileLayer.js +0 -48
  142. package/examples/shorts/tileRaycast.js +0 -39
  143. package/examples/shorts/tiles.png +0 -0
  144. package/examples/shorts/tiltedView.js +0 -63
  145. package/examples/shorts/timers.js +0 -53
  146. package/examples/shorts/topDown.js +0 -38
  147. package/examples/shorts/uiSystem.js +0 -61
  148. package/examples/shorts/video.webm +0 -0
  149. package/examples/shorts/videoPlayer.js +0 -34
  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/typescript/build.mjs +0 -60
  158. package/examples/typescript/game.js +0 -100
  159. package/examples/typescript/game.ts +0 -132
  160. package/examples/typescript/index.html +0 -10
  161. package/examples/typescript/tiles.png +0 -0
  162. package/examples/typescript/tsconfig.json +0 -17
  163. package/examples/uiSystem/game.js +0 -139
  164. package/examples/uiSystem/index.html +0 -10
  165. package/examples/uiSystem/tiles.png +0 -0
  166. package/jsconfig.json +0 -12
  167. package/plugins/desktop.ini +0 -2
  168. package/reference.md +0 -447
  169. package/test/math.test.mjs +0 -774
  170. package/test/setup.mjs +0 -22
  171. package/test/smoke.test.mjs +0 -258
  172. package/test/util.test.mjs +0 -80
@@ -1,331 +0,0 @@
1
- /*
2
- Little Puzzle Game
3
- - A simple match 3 style puzzle game
4
- - Uses a high resolution texture
5
- - Tracks high score in local storage
6
- - Control with mouse or touch
7
- */
8
-
9
- 'use strict';
10
-
11
- // import LittleJS module
12
- import * as LJS from '../../dist/littlejs.esm.js';
13
- const {vec2, rgb, hsl, tile} = LJS;
14
-
15
- ///////////////////////////////////////////////////////////////////////////////
16
- // do not use pixelated rendering
17
- LJS.setCanvasPixelated(false);
18
- LJS.setTilesPixelated(false);
19
-
20
- const fallTime = .2;
21
- const cameraOffset = vec2(0,-.5);
22
- const backgroundColor = hsl(0,0,.2);
23
- const minMatchCount = 3;
24
- const highScoreKey = 'puzzleBestScore';
25
-
26
- // sound effects
27
- const sound_goodMove = new LJS.Sound([.4,.2,250,.04,,.04,,,1,,,,,3]);
28
- const sound_badMove = new LJS.Sound([,,700,,,.07,,,,3.7,,,,3,,,.1]);
29
- const sound_fall = new LJS.Sound([.2,,1900,,,.01,,1.4,,91,,,,,,,,,,.7]);
30
-
31
- let level, levelSize, levelFall, fallTimer, dragStartPos, comboCount, score, bestScore;
32
-
33
- ///////////////////////////////////////////////////////////////////////////////
34
- // tiles
35
- const tileColors =
36
- [
37
- rgb(1,0,0),
38
- rgb(1,1,1),
39
- rgb(1,1,0),
40
- rgb(0,1,0),
41
- rgb(0,.6,1),
42
- rgb(.8,0,1),
43
- rgb(.5,.5,.5),
44
- ];
45
- const tileTypeCount = tileColors.length;
46
-
47
- const getTile = (pos)=> level[pos.x + pos.y * levelSize.x];
48
- const setTile = (pos, data)=> level[pos.x + pos.y * levelSize.x] = data;
49
-
50
- ///////////////////////////////////////////////////////////////////////////////
51
- function gameReset()
52
- {
53
- // reset game objects
54
- LJS.engineObjectsDestroy();
55
-
56
- // randomize level
57
- level = [];
58
- const pos = vec2();
59
- for (pos.x = levelSize.x; pos.x--;)
60
- for (pos.y = levelSize.y; pos.y--;)
61
- setTile(pos, LJS.randInt(tileTypeCount));
62
-
63
- comboCount = score = 0;
64
- fallTimer = new LJS.Timer;
65
- }
66
-
67
- ///////////////////////////////////////////////////////////////////////////////
68
- function gameInit()
69
- {
70
- // setup canvas
71
- LJS.setCanvasFixedSize(vec2(1920, 1080)); // 1080p
72
- LJS.setCanvasClearColor(backgroundColor);
73
- // load high score
74
- bestScore = localStorage[highScoreKey] || 0;
75
-
76
- // setup game
77
- levelSize = vec2(12,6);
78
- LJS.setCameraPos(levelSize.scale(.5).add(cameraOffset));
79
- LJS.setCameraScale(900/levelSize.y);
80
- LJS.setGravity(vec2(0,-.004));
81
-
82
- // start a new game
83
- gameReset();
84
- }
85
-
86
- ///////////////////////////////////////////////////////////////////////////////
87
- function gameUpdate()
88
- {
89
- if (fallTimer.isSet())
90
- {
91
- // update falling tiles
92
- if (fallTimer.elapsed())
93
- {
94
- // add more blocks in the top
95
- for (let x = 0; x < levelSize.x; ++x)
96
- setTile(vec2(x,levelSize.y), LJS.randInt(tileTypeCount));
97
- }
98
-
99
- // allow blocks to fall
100
- if (!fallTimer.active())
101
- {
102
- // check if there is more to fall
103
- levelFall = [];
104
- let keepFalling = 0;
105
- const pos = vec2();
106
- for (pos.x = levelSize.x; pos.x--;)
107
- for (pos.y = 0; pos.y<levelSize.y; pos.y++)
108
- {
109
- const data = getTile(pos);
110
- const abovePos = pos.add(vec2(0,1));
111
- const aboveData = getTile(abovePos);
112
- if (data == -1 && aboveData >= 0)
113
- {
114
- setTile(pos, aboveData);
115
- setTile(abovePos, -1);
116
- levelFall[pos.x+pos.y*levelSize.x] = keepFalling = 1;
117
- }
118
- }
119
-
120
- if (keepFalling)
121
- {
122
- const p = LJS.percent(comboCount, 9, 0);
123
- fallTimer.set(fallTime*p);
124
- sound_fall.play();
125
- }
126
- else
127
- fallTimer.unset();
128
- }
129
- }
130
- else
131
- {
132
- // try to clear matches
133
- clearMatches();
134
- if (!fallTimer.isSet())
135
- {
136
- // mouse/touch control
137
- const mouseTilePos = LJS.mousePos.floor();
138
- if (!LJS.mousePos.arrayCheck(levelSize))
139
- {
140
- // cancel drag if mouse is not in the level bounds
141
- dragStartPos = 0;
142
- }
143
- else if (LJS.mouseWasPressed(0) && !dragStartPos)
144
- {
145
- // start drag
146
- dragStartPos = mouseTilePos.copy();
147
- }
148
- else if (LJS.mouseIsDown(0) && dragStartPos)
149
- {
150
- // if dragging to a neighbor tile
151
- const dx = LJS.abs(dragStartPos.x - mouseTilePos.x);
152
- const dy = LJS.abs(dragStartPos.y - mouseTilePos.y);
153
- if (dx == 1 && dy == 0 || dx == 0 && dy == 1)
154
- {
155
- const startTile = getTile(dragStartPos);
156
- const endTile = getTile(mouseTilePos);
157
- if (startTile >= 0 && endTile >= 0)
158
- {
159
- // swap tiles
160
- setTile(mouseTilePos, startTile);
161
- setTile(dragStartPos, endTile);
162
-
163
- // try to clear matches
164
- clearMatches();
165
-
166
- // undo if no matches
167
- if (!fallTimer.isSet())
168
- {
169
- sound_badMove.play();
170
- setTile(mouseTilePos, endTile);
171
- setTile(dragStartPos, startTile);
172
- }
173
- else
174
- sound_goodMove.play();
175
- dragStartPos = 0;
176
- }
177
- }
178
- }
179
- else
180
- dragStartPos = 0;
181
- }
182
- }
183
-
184
- if (score > bestScore)
185
- {
186
- // update high score
187
- bestScore = score;
188
- localStorage[highScoreKey] = bestScore;
189
- }
190
-
191
- if (LJS.keyWasPressed('KeyR'))
192
- gameReset();
193
- }
194
-
195
- ///////////////////////////////////////////////////////////////////////////////
196
- function gameUpdatePost()
197
- {
198
-
199
- }
200
-
201
- ///////////////////////////////////////////////////////////////////////////////
202
- function gameRender()
203
- {
204
- // draw a black square for the background
205
- LJS.drawRect(LJS.cameraPos.subtract(cameraOffset), levelSize, hsl(0,0,0));
206
-
207
- // draw the blocks
208
- const pos = vec2();
209
- for (pos.x = levelSize.x; pos.x--;)
210
- for (pos.y = levelSize.y; pos.y--;)
211
- {
212
- const data = getTile(pos);
213
- if (data == -1)
214
- continue;
215
-
216
- // highlight drag start
217
- const drawPos = pos.add(vec2(.5));
218
- if (dragStartPos && pos.x == dragStartPos.x && pos.y == dragStartPos.y)
219
- LJS.drawRect(drawPos, vec2(1.05));
220
-
221
- // make pieces fall gradually
222
- if (fallTimer.active() && levelFall[pos.x + pos.y*levelSize.x])
223
- drawPos.y += 1-fallTimer.getPercent();
224
-
225
- // draw background
226
- const color = tileColors[data];
227
- LJS.drawRect(drawPos, vec2(.95), color);
228
-
229
- // use darker color for icon
230
- const color2 = color.scale(.8, 1);
231
- LJS.drawTile(drawPos, vec2(.5), tile(data, 64), color2);
232
- }
233
-
234
- // draw a grey square at top to cover up incoming tiles
235
- LJS.drawRect(LJS.cameraPos.subtract(cameraOffset).add(vec2(0,levelSize.y)), levelSize, backgroundColor);
236
- }
237
-
238
- ///////////////////////////////////////////////////////////////////////////////
239
- function gameRenderPost()
240
- {
241
- // draw text on top of everything
242
- LJS.drawText('Score: ' + score, LJS.cameraPos.add(vec2(-3,-3.1)), .9, hsl(), .1);
243
- LJS.drawText('Best: ' + bestScore, LJS.cameraPos.add(vec2( 3,-3.1)), .9, hsl(), .1);
244
- }
245
-
246
- ///////////////////////////////////////////////////////////////////////////////
247
- // Startup LittleJS Engine
248
- LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
249
-
250
- ///////////////////////////////////////////////////////////////////////////////
251
- // find and remove all runs of 3 or higher
252
- function clearMatches()
253
- {
254
- // horizontal match check
255
- const removeTiles = [], pos = vec2();
256
- for (pos.y = levelSize.y; pos.y--;)
257
- {
258
- let runCount, runData;
259
- for (pos.x = levelSize.x; pos.x--;)
260
- {
261
- const data = getTile(pos);
262
- if (data >= 0 && data == runData)
263
- {
264
- for (let i=++runCount; runCount >= minMatchCount && i--;)
265
- removeTiles[pos.x + i + pos.y * levelSize.x] = 1;
266
- }
267
- else
268
- {
269
- runData = data;
270
- runCount = 1;
271
- }
272
- }
273
- }
274
-
275
- // vertical match check
276
- for (pos.x = levelSize.x; pos.x--;)
277
- {
278
- let runCount, runData;
279
- for (pos.y = levelSize.y; pos.y--;)
280
- {
281
- const data = getTile(pos);
282
- if (data >= 0 && data == runData)
283
- {
284
- for (let i=++runCount; runCount >= minMatchCount && i--;)
285
- removeTiles[pos.x + (pos.y + i) * levelSize.x] = 1;
286
- }
287
- else
288
- {
289
- runData = data;
290
- runCount = 1;
291
- }
292
- }
293
- }
294
-
295
- // remove tiles all at once like this to handle shapes like L or T
296
- let removedCount = 0;
297
- for (pos.x = levelSize.x; pos.x--;)
298
- for (pos.y = levelSize.y; pos.y--;)
299
- {
300
- if (removeTiles[pos.x + pos.y * levelSize.x])
301
- {
302
- // remove tile
303
- ++removedCount;
304
- const data = getTile(pos);
305
- setTile(pos, -1);
306
-
307
- // spawn particles
308
- const color1 = tileColors[data];
309
- const color2 = color1.lerp(hsl(), .5);
310
- new LJS.ParticleEmitter(
311
- pos.add(vec2(.5)), 0, // pos, angle
312
- .5, .1, 200, 3.14, // emitSize, emitTime, rate, cone
313
- 0, // tileInfo
314
- color1, color2, // colorStartA, colorStartB
315
- color1.scale(1,0), color2.scale(1,0),// colorEndA, colorEndB
316
- .5, .3, .2, .05, .05, // particleTime, sizeStart, sizeEnd, speed, angleSpeed
317
- .99, 1, 1, 3.14, .05, // damp, angleDamp, gravityScale, particleCone, fadeRate
318
- .5, 0, 1 // randomness, collide, additive, colorLinear, renderOrder
319
- );
320
- }
321
- }
322
-
323
- if (removedCount)
324
- {
325
- score += ++comboCount*removedCount;
326
- fallTimer.set();
327
- levelFall = [];
328
- }
329
- else
330
- comboCount = 0;
331
- }
@@ -1,8 +0,0 @@
1
- <!DOCTYPE html><head>
2
- <title>LittleJS Puzzle Game</title>
3
- <meta charset=utf-8>
4
- <meta name=apple-mobile-web-app-capable content=yes>
5
- <meta name=mobile-web-app-capable content=yes>
6
- <link rel=icon type=image/png href=../favicon.png>
7
- </head><body>
8
- <script src=game.js type=module></script>
Binary file
Binary file
@@ -1,18 +0,0 @@
1
- canvasClearColor = GRAY;
2
-
3
- function gameRender()
4
- {
5
- {
6
- // animate by changing frames
7
- const pos = vec2(-5, 2*abs(sin(time*2*PI)));
8
- const frame = (time*4)%2|0;
9
- drawTile(pos, vec2(7), tile(3).frame(frame), RED);
10
- }
11
- {
12
- // animate with stretch and squash
13
- const s = sin(time*9)*.5;
14
- const size = vec2(7-s,7+s);
15
- const pos = vec2(5,size.y-7);
16
- drawTile(pos, size, tile(5), GREEN);
17
- }
18
- }
@@ -1,54 +0,0 @@
1
- <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1.18.2></script>
3
- <script src=../../dist/box2d.wasm.js></script>
4
-
5
- <!-- LittleJS Engine Source
6
- <script src=../../src/engine.js></script>
7
- <script src=../../src/engineDebug.js></script>
8
- <script src=../../src/engineMath.js></script>
9
- <script src=../../src/engineUtilities.js></script>
10
- <script src=../../src/engineSettings.js></script>
11
- <script src=../../src/engineObject.js></script>
12
- <script src=../../src/engineDraw.js></script>
13
- <script src=../../src/engineInput.js></script>
14
- <script src=../../src/engineAudio.js></script>
15
- <script src=../../src/engineTileLayer.js></script>
16
- <script src=../../src/engineParticles.js></script>
17
- <script src=../../src/engineMedals.js></script>
18
- <script src=../../src/engineWebGL.js></script>
19
- <script src=../../plugins/box2d.js></script>
20
- <script src=../../plugins/box2d.wasm.js></script>
21
- <script src=../../plugins/drawUtilities.js></script>
22
- <script src=../../plugins/postProcess.js></script>
23
- <script src=../../plugins/uiSystem.js></script>
24
- <script src=../../plugins/zzfxm.js></script>
25
- -->
26
- <script>
27
- 'use strict';
28
-
29
- // use fixed size canvas for examples
30
- canvasFixedSize = vec2(960, 540);
31
-
32
- // fix bleeding from neighboring pixels
33
- tileDefaultBleed = .5;
34
-
35
- // allow improved canvas scaling for smoother graphics
36
- canvasPixelated = false;
37
-
38
- // disable watermark
39
- debugWatermark = false;
40
-
41
- // disable showing the engine version in console
42
- showEngineVersion = false;
43
-
44
- // these functions can be overridden for each example
45
- function gameInit() {}
46
- function gameUpdate() {}
47
- function gameUpdatePost() {}
48
- function gameRender() {}
49
- function gameRenderPost() {}
50
-
51
- // check if WebGL can be enabled
52
- function glCanEnable() { return glCanBeEnabled; }
53
-
54
- </script>
@@ -1,14 +0,0 @@
1
- function gameRender()
2
- {
3
- // additive blending
4
- setBlendMode(1);
5
- drawCircle(vec2(-8,-2), 7, rgb(0,0,.5));
6
- drawCircle(vec2(-6, 2), 7, rgb(0,1,0));
7
- drawCircle(vec2(-4,-2), 7, rgb(1,0,0));
8
-
9
- // alpha blending
10
- setBlendMode(0);
11
- drawCircle(vec2(4,-2), 7, hsl(time/9 ,1,.5));
12
- drawCircle(vec2(8,-2), 7, hsl(time/9+1/3,1,.5,.5));
13
- drawCircle(vec2(6, 2), 7, hsl(time/9+2/3,1,.5,.5));
14
- }
@@ -1,51 +0,0 @@
1
- async function gameInit()
2
- {
3
- // setup box2d
4
- await box2dInit();
5
- mouseJoint = 0;
6
- gravity.y = -50;
7
- canvasClearColor = hsl(0,0,.9);
8
-
9
- // create ground object
10
- groundObject = new Box2dStaticObject(vec2(-8));
11
- groundObject.color = GRAY;
12
- groundObject.addBox(vec2(100,2));
13
-
14
- // add some random objects
15
- for (let i=50; i--;)
16
- {
17
- const pos = randInCircle(5);
18
- const color = randColor();
19
- const o = new Box2dObject(pos, vec2(), 0, 0, color);
20
- randInt(2) ? o.addCircle(rand(1,2)) : o.addRandomPoly(rand(1,2));
21
- }
22
- }
23
-
24
- function gameUpdate()
25
- {
26
- // mouse controls
27
- if (mouseJoint)
28
- {
29
- // update mouse joint
30
- mouseJoint.setTarget(mousePos);
31
- if (mouseWasReleased(0))
32
- {
33
- // release object
34
- mouseJoint = mouseJoint.destroy();
35
- }
36
- }
37
- else if (mouseWasPressed(0))
38
- {
39
- // grab object
40
- const object = box2d.pointCast(mousePos);
41
- if (object)
42
- mouseJoint = new Box2dTargetJoint(object,
43
- groundObject, mousePos);
44
- }
45
- }
46
-
47
- function gameRenderPost()
48
- {
49
- // draw mouse joint
50
- mouseJoint && drawLine(mousePos, mouseJoint.getAnchorB(), .2, RED);
51
- }
@@ -1,59 +0,0 @@
1
- async function gameInit()
2
- {
3
- // setup box2d and create the objects
4
- await box2dInit();
5
- gravity.y = -20;
6
-
7
- // create edge list for ground
8
- const edgePoints = [];
9
- for (let i=0, y=0, s=0; i<1e3; ++i)
10
- {
11
- y = clamp(y+rand(-1,1),0,5);
12
- edgePoints.push(vec2(i*5-15, y-8));
13
- }
14
- const ground = new Box2dStaticObject;
15
- ground.lineWidth = 1;
16
- ground.addEdgeList(edgePoints);
17
-
18
- // make a car
19
- new CarObject(vec2(0,-2));
20
- canvasClearColor = hsl(0,0,.9);
21
- }
22
-
23
- class CarObject extends Box2dObject
24
- {
25
- constructor(pos)
26
- {
27
- super(pos);
28
-
29
- // create car with wheels
30
- this.color = RED;
31
- this.addBox(vec2(7,2));
32
- const frequency = 4, maxTorque = 250;
33
- this.wheels = [];
34
- for (let i=2; i--;)
35
- {
36
- const wheelPos = pos.add(vec2(i?2:-2, -1));
37
- const wheel = new Box2dObject(wheelPos, vec2(2), tile(7));
38
- const joint = new Box2dWheelJoint(this, wheel);
39
- joint.setSpringFrequencyHz(frequency);
40
- joint.setMaxMotorTorque(maxTorque);
41
- joint.enableMotor(!i);
42
- const friction = 20;
43
- wheel.addCircle(2, vec2(), 1, friction);
44
- wheel.motorJoint = joint;
45
- this.wheels[i] = wheel;
46
- }
47
- }
48
- update()
49
- {
50
- // car controls - use mouse, arrow keys, or A/D to drive
51
- const maxSpeed = 40;
52
- const input = mouseIsDown(0) ? 1 :
53
- mouseIsDown(2) ? -1 : keyDirection().x ;
54
- let s = this.wheels[0].motorJoint.getMotorSpeed();
55
- s = input ? clamp(s - input, -maxSpeed, maxSpeed) : 0;
56
- this.wheels[0].motorJoint.setMotorSpeed(s);
57
- cameraPos.x = this.pos.x;
58
- }
59
- }
@@ -1,107 +0,0 @@
1
- const hitSound = new Sound([,.1,2e3,,,.01,,,,,,,,1]);
2
- const maxHitDistance = 6;
3
-
4
- class Ball extends Box2dObject
5
- {
6
- constructor(pos, number=0)
7
- {
8
- const color = hsl(number/9, 1, number? .5 : 1);
9
- super(pos, vec2(), 0, 0, color);
10
- this.number = number;
11
-
12
- // setup pool ball physics
13
- const friction = 0, restitution = .95;
14
- this.addCircle(1, vec2(), 1, friction, restitution);
15
- this.setLinearDamping(.4);
16
- this.setBullet(true);
17
- this.setFixedRotation(true);
18
- }
19
- beginContact()
20
- { hitSound.play(this.pos, clamp(this.getSpeed()/20)); }
21
- canHit()
22
- { return this == cueBall && this.getSpeed() < 1; }
23
- getHitStrength()
24
- { return this.getHitOffset().length()/maxHitDistance; }
25
- getHitOffset()
26
- {
27
- // hit from cue ball to mouse position
28
- const deltaPos = mousePos.subtract(this.pos);
29
- const length = min(deltaPos.length(), maxHitDistance);
30
- return deltaPos.normalize(length);
31
- }
32
- update()
33
- {
34
- if (this.canHit() && mouseWasPressed(0))
35
- {
36
- // hit the cue ball
37
- const accel = this.getHitOffset().scale(8);
38
- this.applyAcceleration(accel);
39
- hitSound.play(cueBall.pos, this.getHitStrength(), .5);
40
- }
41
- if (this.pocketed)
42
- this.destroy();
43
- }
44
- render()
45
- {
46
- super.render();
47
-
48
- // draw white circle and ball number
49
- drawCircle(this.pos, .6, WHITE);
50
- const textPos = this.pos.add(vec2(0,-.06));
51
- if (this.number)
52
- drawText(this.number, textPos, .5, BLACK);
53
- if (this.canHit())
54
- {
55
- // draw the aim line
56
- const endPos = this.pos.add(this.getHitOffset());
57
- const width = this.getHitStrength();
58
- drawLine(this.pos, endPos, width, hsl(0,1,.5,.5),
59
- vec2(), 0, false);
60
- }
61
- }
62
- }
63
-
64
- class Pocket extends Box2dStaticObject
65
- {
66
- constructor(pos, size)
67
- {
68
- super(pos, size, 0, 0, BLACK);
69
-
70
- // create a sensor circle for pocket
71
- this.addCircle(size.x);
72
- this.setSensor(true);
73
- }
74
- render()
75
- {
76
- // add ball size to pocket size for drawing
77
- drawCircle(this.pos, this.size.x + 1, BLACK);
78
- }
79
- beginContact(other) { other.pocketed = 1; }
80
- }
81
-
82
- async function gameInit()
83
- {
84
- // setup box2d
85
- await box2dInit();
86
- canvasClearColor = hsl(.4,.5,.5);
87
-
88
- // create table walls
89
- const groundObject = new Box2dStaticObject;
90
- groundObject.color = hsl(.1,1,.2);
91
- groundObject.addBox(vec2(100,3), vec2( 0, 8.5));
92
- groundObject.addBox(vec2(100,3), vec2( 0,-8.5));
93
- groundObject.addBox(vec2(3,100), vec2( 15,0));
94
- groundObject.addBox(vec2(3,100), vec2(-15,0));
95
-
96
- // create pockets
97
- for (let j=0; j<2; ++j)
98
- for (let i=0; i<3; ++i)
99
- new Pocket(vec2(i-1, j-.5).scale(13), vec2(.5));
100
-
101
- // create balls
102
- let number = 1;
103
- for (let i=5; i--;)
104
- for (let j=i+1; j--;)
105
- new Ball(vec2(6+i*.9, j-i/2), number++);
106
- cueBall = new Ball(vec2(-6, 0));
107
- }