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,521 +0,0 @@
1
- # LittleJS Breakout Tutorial
2
-
3
- For this tutorial we will start with the empty project in the LittleJS examples folder. This is a blank template to start a new project.
4
-
5
- The empty project has only 3 files: one for html, one for js, and one image. The index.html and image files will not need to be changed for this example. The
6
- [game.js](https://github.com/KilledByAPixel/LittleJS/blob/main/examples/empty/game.js) file contains a stubbed out project with all the JavaScript code and is the only file we will be working with today.
7
-
8
- You can get the [LittleJS code using GitHub](https://github.com/KilledByAPixel/LittleJS) or call ```npm install littlejsengine```
9
-
10
- In this tutorial we will make a breakout style game with a player controllable paddle, a ball that bounces, and bricks that break when hit. This is a great introduction to LittleJS and takes only around 30 minutes to complete.
11
-
12
- [The tutorial is also available on YouTube!](https://youtu.be/tSwDx-NWTXE?si=bkjMa8-7AN2Wg5MO)
13
-
14
- ## [You can play the result of this tutorial here.](https://killedbyapixel.github.io/LittleJS/examples/breakoutTutorial/)
15
-
16
- ![LittleJS Screenshot](images/9.png)
17
-
18
- ## Create the Bricks
19
-
20
- The first step is to make a 2D grid of brick objects in gameInit. As a placeholder we will create an EngineObject for each cell in the grid and set it to have a random color.
21
-
22
- ```javascript
23
- // create bricks
24
- for (let x=0; x<=20; x++)
25
- for (let y=0; y<=20; y++)
26
- {
27
- const brick = new LJS.EngineObject(vec2(x,y)); // create a brick
28
- brick.color = LJS.randColor(); // give brick a random color
29
- }
30
- ```
31
-
32
- That will make a square of 20×20 engine objects, we can adjust it as we go. It also assigns the color property of each brick to a random color.
33
-
34
- ![LittleJS Screenshot](images/1.png)
35
-
36
- It is completely off center and may not look like much yet, but it's a start!
37
-
38
- ## Improve the Bricks
39
-
40
- Let's make the bricks more rectangular by passing vec2(2,1) to the size parameter of Engine Object. We will need to adjust the loop to add 2 for each x iteration. Also we can use a Vector2 to describe the size of the level.
41
-
42
- ```javascript
43
- // create bricks
44
- const levelSize = vec2(20, 20);
45
- for (let x=0; x<=levelSize.x; x+=2)
46
- for (let y=0; y<=levelSize.y; y+=1)
47
- {
48
- const brick = new LJS.EngineObject(vec2(x,y), vec2(2,1)); // create a brick
49
- brick.color = LJS.randColor(); // give brick a random color
50
- }
51
- ```
52
-
53
- ## Move the Camera
54
-
55
- Let's move the camera to the center of our level by setting the cameraPos variable to half the level size.
56
- You can also change the camera zoom by using camaraScale which controls the number of pixels for each world space unit.
57
- For this example the camera will just remain stationary, but in other types of games it is very useful!
58
-
59
- ```javascript
60
- LJS.setCameraPos(levelSize.scale(.5)); // center camera in level
61
- ```
62
-
63
- We'll also start with a blank slate by commenting out the default “Hello World!” text in gameRenderPost.
64
-
65
- ```javascript
66
- // LJS.drawTextScreen('Hello World!', LJS.mainCanvasSize.scale(.5), 80);
67
- ```
68
-
69
- ![LittleJS Screenshot](images/2.png)
70
-
71
- It is getting closer! The camera is now centered and blocks are rectangular.
72
-
73
- ## Modify the Level Size
74
-
75
- For this example we will use a fixed size canvas. This will let the drawing canvas always be the same resolution, even if the window size changes. Black space is added on the sides to compensate. It is a great option for any game that uses a single screen like this.
76
-
77
- To enable it we will set canvasFixedSize in gameInit to use 720p resolution.
78
-
79
- ```javascript
80
- LJS.setCanvasFixedSize(vec2(1280, 720)); // use a 720p fixed size canvas
81
- ```
82
-
83
- Before we tweak the level size, let's add this bit of code to gameRender to show the size of the level. This will cause some rects to be drawn each frame before the engine objects. To create color objects we pass in RGB values between 0 and 1.
84
-
85
- ```javascript
86
- LJS.drawRect(LJS.cameraPos, vec2(100), rgb(.5,.5,.5)); // draw background
87
- LJS.drawRect(LJS.cameraPos, levelSize, rgb(.1,.1,.1)); // draw level boundary
88
- ```
89
-
90
- We also need to make levelSize a global by moving it to the top so it can be accessed from other functions.
91
-
92
- ```javascript
93
- const levelSize = vec2(38, 20); // size of play area
94
- ```
95
-
96
- Now we can see the boundaries of our level and tweak the size to fill the canvas. I found that a level size of vec2(38, 20) works well here.
97
-
98
- We can also adjust the for loop where the bricks are created to make them only fill the top middle part of the level.
99
-
100
- ```javascript
101
- for (let x=2; x<=levelSize.x-2; x+=2)
102
- for (let y=12; y<=levelSize.y-2; y+=1)
103
- {
104
- const brick = new LJS.EngineObject(vec2(x,y), vec2(2,1)); // create a brick
105
- brick.color = LJS.randColor(); // give brick a random color
106
- }
107
- ```
108
-
109
- ![LittleJS Screenshot](images/3.png)
110
-
111
- Now that looks almost like a breakout game!
112
-
113
- ## Create the Player Paddle
114
-
115
- For the player's paddle, let's create a new class of object that extends the built in EngineObject. This will allow us to control movement with the mouse. In this Paddle class we will just add some new code to the update function which is automatically called each frame by the engine.
116
-
117
- ```javascript
118
- class Paddle extends LJS.EngineObject
119
- {
120
- update()
121
- {
122
- this.pos.x = LJS.mousePos.x; // move paddle to mouse
123
- }
124
- }
125
- ```
126
-
127
- Then we just need to create the paddle in gameInit.
128
-
129
- ```javascript
130
- new Paddle; // create player's paddle
131
- ```
132
-
133
- There is now a square paddle that moves along the bottom of the screen.
134
-
135
- Let's make the paddle wider and move it up a smidge by adding a constructor to the Paddle class.
136
-
137
- ```javascript
138
- constructor()
139
- {
140
- super(vec2(0,1), vec2(6,.5)); // set object position and size
141
- }
142
- ```
143
-
144
- ![LittleJS Screenshot](images/4.png)
145
-
146
- Now there is a player controllable paddle that moves along the bottom of the screen.
147
-
148
- You can also add this code to the paddle update that will keep the paddle from following the mouse offscreen, though it is not required.
149
-
150
- ```javascript
151
- // clamp paddle to level size
152
- this.pos.x = LJS.clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
153
- ```
154
-
155
- ## Create the Ball
156
- The final missing piece is of course that ball that moves around and bounces off of stuff. We will leverage the built in physics solver to handle all the ball's physics and collision math.
157
-
158
- We can create a Ball class the same way we created the paddle. In this case we will also apply some velocity to ball so it starts moving right away.
159
-
160
- ```javascript
161
- class Ball extends LJS.EngineObject
162
- {
163
- constructor(pos)
164
- {
165
- super(pos); // set object position
166
-
167
- this.velocity = vec2(-.1, -.1); // give ball some movement
168
- }
169
- }
170
- ```
171
-
172
- Then we just need to create the ball in gameInit, passing in the camera position for its location.
173
-
174
- ```javascript
175
- {
176
- // create a ball
177
- ball = new Ball(LJS.cameraPos);
178
- }
179
- ```
180
-
181
- ## Make the Ball Collide
182
-
183
- You may have noticed that the ball goes right through the paddle and bricks. To enable collision we just need to call setCollision on the ball and the paddle by adding a call in both of their constructors.
184
-
185
- ```javascript
186
- this.setCollision(); // make object collide
187
- ```
188
-
189
- Now the ball collides but unfortunately also pushes the paddle away, not quite what we want. To prevent the paddle from being moved by physics we will make it use static physics by setting its mass to 0 in the paddle constructor.
190
-
191
- ```javascript
192
- this.mass = 0; // make object have static physics
193
- ```
194
-
195
- Getting closer, the paddle is not pushed away but the ball doesn't bounce either. To make it bounce, we need to set the ball's restitution which controls how much it will bounce.
196
-
197
- ```javascript
198
- this.restitution = 1; // make object bounce
199
- ```
200
-
201
- ![LittleJS Screenshot](images/5.png)
202
-
203
- It works! The ball now bounces off the paddle, still not the walls or blocks yet though.
204
-
205
- Before we continue, let's make the ball a bit smaller by changing the super call in its constructor.
206
-
207
- ```javascript
208
- super(pos, vec2(.5)); // set object position and size
209
- ```
210
-
211
- ## Make the Ball Bounce Off Walls
212
-
213
- Next, let's make the ball bounce when it hits the top or sides of the screen. To do this, we will make a Wall object class that works similar to the paddle but without an update function.
214
-
215
- ```javascript
216
- class Wall extends LJS.EngineObject
217
- {
218
- constructor(pos, size)
219
- {
220
- super(pos, size); // set object position and size
221
-
222
- this.setCollision(); // make object collide
223
- this.mass = 0; // make object have static physics
224
- }
225
- }
226
- ```
227
-
228
- We can create walls on the sides and top by adding a few more lines of code to the gameInit function.
229
-
230
- ```javascript
231
- // create walls
232
- new Wall(vec2(-.5,levelSize.y/2), vec2(1,100)) // left
233
- new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // right
234
- new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // top
235
- ```
236
-
237
- ![LittleJS Screenshot](images/6.png)
238
-
239
- Now we have white walls around the outside that block the ball. These walls should be invisible so we will set their color to be transparent by adding another line to the Wall constructor.
240
-
241
- ```javascript
242
- this.color = rgb(0,0,0,0); // make object invisible
243
- ```
244
-
245
- ## Debug Display
246
-
247
- This is a good time to try opening up the debug info by pressing escape. This feature will allow for a selection of debug overlays while also showing all game objects with more info displayed for the object closest to the mouse. It can be really useful when trying to diagnose bugs and understand what is going on.
248
-
249
- ![LittleJS Screenshot](images/7.png)
250
-
251
- As you can see, the wall objects are still present even though they are now invisible.
252
-
253
- ## Respawn the Ball
254
-
255
- We should respawn the ball when it goes below the screen so players can keep playing.
256
-
257
- To do this, we will need to make a global ball object.
258
-
259
- ```javascript
260
- let ball; // keep track of ball object
261
- ```
262
-
263
- We can remove the old code that was creating a new ball in gameInit, and instead create the ball in gameUpdate, only when it is needed.
264
-
265
- ```javascript
266
- // if there is no ball or ball is below level
267
- if (!ball || ball.pos.y < -1)
268
- {
269
- // destroy old ball
270
- if (ball)
271
- ball.destroy();
272
-
273
- // create a ball
274
- ball = new Ball(LJS.cameraPos);
275
- }
276
- ```
277
-
278
- Don't forget to destroy the old ball before creating the new one! Though it doesn't really matter for this simple example, it would cause the old balls to continue existing while being updated and rendered. That could really slow things in bigger games with thousands of objects.
279
-
280
- ## Break the Bricks
281
-
282
- Still, the ball doesn't collide with the bricks much less breaks them and it wouldn't be breakout without that. So we need to make the brick collide with the ball, just like the walls, so let's start with Brick class that is the same as Wall.
283
-
284
- ```javascript
285
- class Brick extends LJS.EngineObject
286
- {
287
- constructor(pos, size)
288
- {
289
- super(pos, size);
290
-
291
- this.setCollision(); // make object collide
292
- this.mass = 0; // make object have static physics
293
- }
294
- }
295
- ```
296
-
297
- And we will just change the for loop in gameInit to use the Brick class.
298
-
299
- ```javascript
300
- const brick = new Brick(vec2(x,y), vec2(2,1)); // create a brick
301
- ```
302
-
303
- Now the ball will bounce off the bricks, but we want it to break the bricks. To do this we can override the brick's collideWithObject function which is called by the engine when the ball hits it. Instead of the default collide behavior, we just destroy the brick.
304
-
305
- ```javascript
306
- collideWithObject(o)
307
- {
308
- this.destroy(); // destroy block when hit
309
- }
310
- ```
311
-
312
- But wait! This will cause the ball to careen through the bricks without bouncing. Maybe fun for a special powerup, but not our goal here. This function should return a Boolean value to indicate if the collision needs to be resolved, if it returns false then the ball will not bounce. So the answer is to just add another line of code to the collideWithObject function that returns a truthy value indicating that the collision should occur.
313
-
314
- ```javascript
315
- return true; // allow object to collide
316
- ```
317
-
318
- ![LittleJS Screenshot](images/8.png)
319
-
320
- Success, we have breakout! All the core components are here though there are a few more changes we can make that will greatly increase the playability.
321
-
322
- ## Track the Player's Score
323
-
324
- We can easily add a score tracker to the game by making a global score variable called score.
325
-
326
- ```javascript
327
- let score = 0; // start score at 0
328
- ```
329
-
330
- Then increment it in the Brick.collideWithObject function.
331
-
332
- ```javascript
333
- ++score; // award a point for each brick broke
334
- ```
335
-
336
- And change that drawTextScreen code we had commented out in gameRenderPost to display the score. We can adjust the position and size of the text to fit at the top of the screen.
337
-
338
- ```javascript
339
- LJS.drawTextScreen('Score ' + score, vec2(LJS.mainCanvasSize.x/2, 70), 50); // show score
340
- ```
341
-
342
- ![LittleJS Screenshot](images/9.png)
343
-
344
- ## Add Sound Effects
345
-
346
- So far the game is completely silent. Let's add sounds using ZzFX. This is a tiny sound effect generator that works in conjunction with LittleJS and can be used on its own too.
347
-
348
- We will start with the ball bounce sound. [You can use the official ZzFX sound designer to create your own sound.](https://killedbyapixel.github.io/ZzFX/) I recommend using the Blip preset for this one.
349
-
350
- To make a sound effect with this system we will create a global object for each sound.
351
-
352
- ```javascript
353
- const sound_bounce = new LJS.Sound([,,1e3,,.03,.02,1,2,,,940,.03,,,,,.2,.6,,.06], 0);
354
- ```
355
-
356
- You can use the sound I chose or copy the code for your own sound from ZzFX. There is a checkbox for LittleJS style sounds to make exporting a little easier.
357
-
358
- To play the sound we will override collideWithObject for the Ball class. Also remember we must return 1 for the collision to occur.
359
-
360
- ```javascript
361
- collideWithObject(o)
362
- {
363
- sound_bounce.play(); // play bounce sound
364
- return true; // allow object to collide
365
- }
366
- ```
367
- Let's also make a brick break sound. You can use the ZzFX sound designer again to create your own sound, for this one try the Hit preset.
368
-
369
- Create a global object for this sound the same way we did for the bounce sound. You can replace it with your own generated sound or use mine.
370
-
371
- ```javascript
372
- const sound_break = new LJS.Sound([,,90,,.01,.03,4,,,,,,,9,50,.2,,.2,.01], 0);
373
- ```
374
-
375
- Then in the Brick's collideWithObject function just add some code to play that sound.
376
-
377
- ```javascript
378
- sound_break.play(); // play brick break sound
379
- ```
380
-
381
- Now you should hear sound as the ball bounces around and breaks bricks! Of course it is easy to swap out these sounds with other ones, feel free to experiment.
382
-
383
- ## Add Click To Start Interaction
384
-
385
- Let's improve the gameplay by letting the player click to start, instead of creating the ball right away. This will also ensure that the player has clicked which is requirement for audio to play in most browsers.
386
-
387
- We can also add a special sound that plays on startup. Try making an interesting start from the ZzFX sound designer, maybe using the Powerup preset.
388
-
389
- ```javascript
390
- const sound_start = new LJS.Sound([,0,500,,.04,.3,1,2,,,570,.02,.02,,,,.04]);
391
- ```
392
-
393
- We can modify the gameUpdate to wait for player input from the mouse and play the sound when the ball is created.
394
-
395
- ```javascript
396
- if (ball && ball.pos.y < -1) // if ball is below level
397
- {
398
- // destroy old ball
399
- ball.destroy();
400
- ball = 0;
401
- }
402
- if (!ball && LJS.mouseWasPressed(0)) // if there is no ball and left mouse is pressed
403
- {
404
- ball = new Ball(LJS.cameraPos); // create the ball
405
- sound_start.play(); // play start sound
406
- }
407
- ```
408
-
409
- ## Add Particle Effects
410
-
411
- Let's add some effects when the bricks break. You can use the LittleJS particle system designer to create an explosion effect.
412
-
413
- This will be a one shot type of effect, not a continuous emitter so change emitTime to something small like .1 for this example. Now before you play with it too much, let's test it by pasting in the code it generated into the Brick's collideWithObject function.
414
-
415
- Make sure you replace the first parameter, vec2(), with this.pos so the effect appears wherever the brick is, otherwise it will spawn at the world origin.
416
-
417
- ```javascript
418
- // create explosion effect
419
- new LJS.ParticleEmitter(this.pos, 0, 0, 0.1, 100, 3.14, 0, rgb(1, 1, 1, 1), rgb(1, 1, 1, 1), rgb(1, 1, 1, 0), rgb(1, 1, 1, 0), 0.5, 0.1, 1, 0.1, 0.05, 1, 1, 0, 3.14, 0.1, 0.2, 0, 0, 1);
420
- ```
421
-
422
- Now you should see this simple particle effect play wherever a brick breaks. You can continue tweaking the parameters to make your own effect or use the one I made which also uses this.color to change the particle's color so it matches the brick.
423
-
424
- ```javascript
425
- // create explosion effect
426
- const color = this.color;
427
- new LJS.ParticleEmitter(
428
- this.pos, 0, // pos, angle
429
- this.size, .1, 200, 3.14,// emitSize, emitTime, rate, cone
430
- undefined, // tileInfo
431
- color, color, // colorStartA, colorStartB
432
- color.scale(1,0), color.scale(1,0), // colorEndA, colorEndB
433
- .2, .5, 1, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
434
- .99, .95, .4, 3.14, // damp, angleDamp, gravity, cone
435
- .1, .5, false, true // fade, randomness, collide, additive
436
- );
437
- ```
438
-
439
- ![LittleJS Screenshot](images/10.png)
440
-
441
- ## Improve the Gameplay
442
-
443
- Last but certainly not least, let's make a few small improvements to the gameplay. It would help to give the player some more control of where the ball goes when it hits the paddle. We can do this by adding some code to the ball's collideWithObject function.
444
-
445
- This code will use the rotate function to modify the bounce angle based on the distance from the center of the paddle.
446
-
447
- We will also slightly increase the speed of the ball each time it hits the paddle to make the difficulty of the game ramp up over time.
448
-
449
- ```javascript
450
- collideWithObject(o)
451
- {
452
- // prevent colliding with paddle if moving upwards
453
- if (o == paddle && this.velocity.y > 0)
454
- return false;
455
-
456
- sound_bounce.play(); // play bounce sound
457
-
458
- if (o == paddle)
459
- {
460
- // control bounce angle when ball collides with paddle
461
- const deltaX = o.pos.x - this.pos.x;
462
- this.velocity = this.velocity.rotate(.3 * deltaX);
463
-
464
- // make sure ball is moving upwards with a minimum speed
465
- this.velocity.y = LJS.max(-this.velocity.y, .2);
466
-
467
- // prevent default collision code
468
- return false;
469
- }
470
-
471
- return true; // allow object to collide
472
- }
473
- ```
474
-
475
- Also we will need to make the paddle a global object like the ball.
476
-
477
- ```javascript
478
- let paddle; // keep track of player's paddle
479
- ```
480
-
481
- And assign that paddle object when it is created in gameInit.
482
-
483
- ```javascript
484
- paddle = new Paddle; // create player's paddle
485
- ```
486
-
487
- While we are working in the ball's collideWithObject function, let's also make it speed up a little bit each time it bounces.
488
-
489
- ```javascript
490
- // speed up the ball
491
- const speed = min(1.04*this.velocity.length(), .5);
492
- this.velocity = this.velocity.normalize(speed);
493
- ```
494
-
495
- ## Improve the Sound
496
-
497
- Let's make the sound a bit more interesting by using positional audio. This lets the volume and panning be adjusted based on the sound's on screen location. To enable this, just pass a position to the sound's play function.
498
-
499
- ```javascript
500
- sound_break.play(this.pos); // play brick break sound
501
- ```
502
-
503
- For the ball bounce sound, let's also tweak the pitch by how fast the ball is moving. For the sound play function, the second parameter takes a scalar for volume and the third parameter takes a scalar for pitch.
504
-
505
- ```javascript
506
- sound_bounce.play(this.pos, 1, speed); // play bounce sound with pitch scaled by speed
507
- ```
508
-
509
- ## Congratulations on Completing the Breakout Tutorial
510
-
511
- Now you know the basics of how to use the LittleJS engine! [The final result with all the code from this tutorial is playable here.](https://killedbyapixel.github.io/LittleJS/examples/breakoutTutorial/)
512
-
513
- If you need a little help completing the tutorial, [join us on the LittleJS discord](https://discord.gg/zb7hcGkyZe).
514
-
515
- Feel free to continue building on this tutorial to make a more interesting breakout game. What kind of ideas would you like to include?
516
-
517
- You can also check out [the breakout example game](https://killedbyapixel.github.io/LittleJS/examples/breakout/) which extends this tutorial to show textured objects, post processing, and image fonts.
518
-
519
- ![LittleJS Screenshot](images/11.png)
520
-
521
- There are several other example games you can use as a starting point for your own creations, or use a new blank project like we did for this example. What will you build with LittleJS? 🚂