littlejsengine 1.5.2 → 1.6.4

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 (72) hide show
  1. package/README.md +155 -33
  2. package/{engine/index.d.ts → build/littlejs.d.ts} +14 -6
  3. package/{engine/engine.all.module.js → build/littlejs.esm.js} +110 -99
  4. package/build/littlejs.esm.min.js +1 -0
  5. package/{engine/engine.all.js → build/littlejs.js} +102 -97
  6. package/build/littlejs.min.js +1 -0
  7. package/{engine/engine.all.release.js → build/littlejs.release.js} +95 -95
  8. package/examples/breakout/game.js +5 -0
  9. package/examples/breakout/gameObjects.js +41 -48
  10. package/examples/breakout/index.html +5 -4
  11. package/examples/breakoutTutorial/README.md +514 -0
  12. package/examples/breakoutTutorial/game.js +181 -0
  13. package/examples/breakoutTutorial/images/1.png +0 -0
  14. package/examples/breakoutTutorial/images/10.png +0 -0
  15. package/examples/breakoutTutorial/images/11.png +0 -0
  16. package/examples/breakoutTutorial/images/2.png +0 -0
  17. package/examples/breakoutTutorial/images/3.png +0 -0
  18. package/examples/breakoutTutorial/images/4.png +0 -0
  19. package/examples/breakoutTutorial/images/5.png +0 -0
  20. package/examples/breakoutTutorial/images/6.png +0 -0
  21. package/examples/breakoutTutorial/images/7.png +0 -0
  22. package/examples/breakoutTutorial/images/8.png +0 -0
  23. package/examples/breakoutTutorial/images/9.png +0 -0
  24. package/examples/breakoutTutorial/index.html +10 -0
  25. package/examples/electron/build.bat +52 -0
  26. package/{electron → examples/electron}/electron.js +18 -21
  27. package/{game.js → examples/electron/game.js} +1 -1
  28. package/examples/electron/index.html +2 -0
  29. package/examples/electron/package.json +20 -0
  30. package/examples/empty/game.js +11 -1
  31. package/examples/empty/index.html +2 -2
  32. package/examples/module/game.js +1 -1
  33. package/examples/module/index.html +3 -2
  34. package/examples/particles/index.html +3 -2
  35. package/examples/platformer/gameLevel.js +1 -1
  36. package/examples/platformer/gamePlayer.js +1 -1
  37. package/examples/platformer/index.html +8 -7
  38. package/examples/puzzle/index.html +4 -3
  39. package/{build.bat → examples/starter/build.bat} +17 -17
  40. package/examples/starter/game.js +111 -0
  41. package/examples/starter/index.html +27 -0
  42. package/examples/starter/tiles.png +0 -0
  43. package/examples/stress/index.html +3 -2
  44. package/examples/typescript/game.js +89 -89
  45. package/examples/typescript/game.ts +11 -11
  46. package/examples/typescript/index.html +3 -2
  47. package/package.json +4 -4
  48. package/{engine → src}/engine.js +1 -2
  49. package/{engine → src}/engineAudio.js +11 -11
  50. package/src/engineBuild.bat +132 -0
  51. package/{engine → src}/engineDebug.js +8 -2
  52. package/{engine → src}/engineDraw.js +19 -15
  53. package/{engine → src}/engineExport.js +8 -2
  54. package/{engine → src}/engineInput.js +54 -58
  55. package/{engine → src}/engineMedals.js +1 -1
  56. package/{engine → src}/engineObject.js +4 -4
  57. package/{engine → src}/engineRelease.js +1 -0
  58. package/{engine → src}/engineUtilities.js +4 -4
  59. package/electron/electronBuild.bat +0 -32
  60. package/electron/electronSetup.bat +0 -2
  61. package/electron/package.json +0 -21
  62. package/engine/engine.all.min.js +0 -1
  63. package/engine/engine.all.module.min.js +0 -1
  64. package/engine/engineBuild.bat +0 -127
  65. package/index.html +0 -26
  66. /package/{tiles.png → examples/electron/tiles.png} +0 -0
  67. /package/{favicon.png → examples/favicon.png} +0 -0
  68. /package/{engine → src}/engineFont.png +0 -0
  69. /package/{engine → src}/engineParticles.js +0 -0
  70. /package/{engine → src}/engineSettings.js +0 -0
  71. /package/{engine → src}/engineTileLayer.js +0 -0
  72. /package/{engine → src}/engineWebGL.js +0 -0
@@ -10,6 +10,7 @@
10
10
 
11
11
  let showWatermark = 0;
12
12
  let godMode = 0;
13
+ let debugKeyCode = 0;
13
14
  const debug = 0;
14
15
  const debugOverlay = 0;
15
16
  const debugPhysics = 0;
@@ -381,7 +382,7 @@ class Vector2
381
382
  * @return {Color}
382
383
  * @memberof Utilities
383
384
  */
384
- const colorRGBA = (r, g, b, a)=> new Color(r, g, b, a);
385
+ const rgb = (r, g, b, a)=> new Color(r, g, b, a);
385
386
 
386
387
  /**
387
388
  * Create a color object with HSLA values
@@ -392,7 +393,7 @@ const colorRGBA = (r, g, b, a)=> new Color(r, g, b, a);
392
393
  * @return {Color}
393
394
  * @memberof Utilities
394
395
  */
395
- const colorHSLA = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
396
+ const hsl = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
396
397
 
397
398
  /**
398
399
  * Color object (red, green, blue, alpha) with some helpful functions
@@ -400,8 +401,8 @@ const colorHSLA = (h, s, l, a)=> new Color().setHSLA(h, s, l, a);
400
401
  * let a = new Color; // white
401
402
  * let b = new Color(1, 0, 0); // red
402
403
  * let c = new Color(0, 0, 0, 0); // transparent black
403
- * let d = colorRGBA(0, 0, 1); // blue using rgb color
404
- * let e = colorHSLA(.3, 1, .5); // green using hsl color
404
+ * let d = RGB(0, 0, 1); // blue using rgb color
405
+ * let e = HSL(.3, 1, .5); // green using hsl color
405
406
  */
406
407
  class Color
407
408
  {
@@ -898,7 +899,7 @@ const engineName = 'LittleJS';
898
899
  * @type {String}
899
900
  * @default
900
901
  * @memberof Engine */
901
- const engineVersion = '1.5.2';
902
+ const engineVersion = '1.6.4';
902
903
 
903
904
  /** Frames per second to update objects
904
905
  * @type {Number}
@@ -989,7 +990,6 @@ function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRender
989
990
  (glCanvas||mainCanvas).style = mainCanvas.style = overlayCanvas.style = styleCanvas;
990
991
 
991
992
  gameInit();
992
- touchGamepadCreate();
993
993
  engineUpdate();
994
994
  };
995
995
 
@@ -1300,6 +1300,7 @@ class EngineObject
1300
1300
  this.velocity.y += gravity * this.gravityScale;
1301
1301
  this.pos.x += this.velocity.x *= this.damping;
1302
1302
  this.pos.y += this.velocity.y *= this.damping;
1303
+ this.angle += this.angleVelocity *= this.angleDamping;
1303
1304
 
1304
1305
  // physics sanity checks
1305
1306
  ASSERT(this.angleDamping >= 0 && this.angleDamping <= 1);
@@ -1356,6 +1357,7 @@ class EngineObject
1356
1357
  const smallStepUp = (oldPos.y - o.pos.y)*2 > sizeBoth.y + gravity; // prefer to push up if small delta
1357
1358
  const isBlockedX = abs(oldPos.y - o.pos.y)*2 < sizeBoth.y;
1358
1359
  const isBlockedY = abs(oldPos.x - o.pos.x)*2 < sizeBoth.x;
1360
+ const elasticity = max(this.elasticity, o.elasticity);
1359
1361
 
1360
1362
  if (smallStepUp | isBlockedY | !isBlockedX) // resolve y collision
1361
1363
  {
@@ -1368,7 +1370,7 @@ class EngineObject
1368
1370
  this.groundObject = o;
1369
1371
 
1370
1372
  // bounce if other object is fixed or grounded
1371
- this.velocity.y *= -this.elasticity;
1373
+ this.velocity.y *= -elasticity;
1372
1374
  }
1373
1375
  else if (o.mass)
1374
1376
  {
@@ -1382,7 +1384,6 @@ class EngineObject
1382
1384
  + this.velocity.y * 2 * this.mass / (this.mass + o.mass);
1383
1385
 
1384
1386
  // lerp betwen elastic or inelastic based on elasticity
1385
- const elasticity = max(this.elasticity, o.elasticity);
1386
1387
  this.velocity.y = lerp(elasticity, inelastic, elastic0);
1387
1388
  o.velocity.y = lerp(elasticity, inelastic, elastic1);
1388
1389
  }
@@ -1403,12 +1404,11 @@ class EngineObject
1403
1404
  + this.velocity.x * 2 * this.mass / (this.mass + o.mass);
1404
1405
 
1405
1406
  // lerp betwen elastic or inelastic based on elasticity
1406
- const elasticity = max(this.elasticity, o.elasticity);
1407
1407
  this.velocity.x = lerp(elasticity, inelastic, elastic0);
1408
1408
  o.velocity.x = lerp(elasticity, inelastic, elastic1);
1409
1409
  }
1410
1410
  else // bounce if other object is fixed
1411
- this.velocity.x *= -this.elasticity;
1411
+ this.velocity.x *= -elasticity;
1412
1412
  }
1413
1413
  debugOverlay && debugPhysics && debugAABB(this.pos, this.size, o.pos, o.size, '#f0f');
1414
1414
  }
@@ -1790,6 +1790,23 @@ function setBlendMode(additive, useWebGL=glEnable)
1790
1790
  mainContext.globalCompositeOperation = additive ? 'lighter' : 'source-over';
1791
1791
  }
1792
1792
 
1793
+ /** Draw text on overlay canvas in world space
1794
+ * Automatically splits new lines into rows
1795
+ * @param {String} text
1796
+ * @param {Vector2} pos
1797
+ * @param {Number} [size=1]
1798
+ * @param {Color} [color=Color()]
1799
+ * @param {Number} [lineWidth=0]
1800
+ * @param {Color} [lineColor=Color(0,0,0)]
1801
+ * @param {String} [textAlign='center']
1802
+ * @param {String} [font=fontDefault]
1803
+ * @param {CanvasRenderingContext2D} [context=overlayContext]
1804
+ * @memberof Draw */
1805
+ function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, context)
1806
+ {
1807
+ drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, context);
1808
+ }
1809
+
1793
1810
  /** Draw text on overlay canvas in screen space
1794
1811
  * Automatically splits new lines into rows
1795
1812
  * @param {String} text
@@ -1799,6 +1816,8 @@ function setBlendMode(additive, useWebGL=glEnable)
1799
1816
  * @param {Number} [lineWidth=0]
1800
1817
  * @param {Color} [lineColor=Color(0,0,0)]
1801
1818
  * @param {String} [textAlign='center']
1819
+ * @param {String} [font=fontDefault]
1820
+ * @param {CanvasRenderingContext2D} [context=overlayContext]
1802
1821
  * @memberof Draw */
1803
1822
  function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineColor=new Color(0,0,0), textAlign='center', font=fontDefault, context=overlayContext)
1804
1823
  {
@@ -1819,21 +1838,6 @@ function drawTextScreen(text, pos, size=1, color=new Color, lineWidth=0, lineCol
1819
1838
  });
1820
1839
  }
1821
1840
 
1822
- /** Draw text on overlay canvas in world space
1823
- * Automatically splits new lines into rows
1824
- * @param {String} text
1825
- * @param {Vector2} pos
1826
- * @param {Number} [size=1]
1827
- * @param {Color} [color=Color()]
1828
- * @param {Number} [lineWidth=0]
1829
- * @param {Color} [lineColor=Color(0,0,0)]
1830
- * @param {String} [textAlign='center']
1831
- * @memberof Draw */
1832
- function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font)
1833
- {
1834
- drawTextScreen(text, worldToScreen(pos), size*cameraScale, color, lineWidth*cameraScale, lineColor, textAlign, font, mainContext);
1835
- }
1836
-
1837
1841
  ///////////////////////////////////////////////////////////////////////////////
1838
1842
 
1839
1843
  let engineFontImage;
@@ -2087,15 +2091,15 @@ function inputUpdatePost()
2087
2091
  onkeydown = (e)=>
2088
2092
  {
2089
2093
  if (debug && e.target != document.body) return;
2090
- e.repeat || (inputData[isUsingGamepad = 0][remapKeyCode(e.keyCode)] = 3);
2094
+ e.repeat || (inputData[isUsingGamepad = 0][remapKey(e.which)] = 3);
2091
2095
  preventDefaultInput && e.preventDefault();
2092
2096
  }
2093
2097
  onkeyup = (e)=>
2094
2098
  {
2095
2099
  if (debug && e.target != document.body) return;
2096
- inputData[0][remapKeyCode(e.keyCode)] = 4;
2100
+ inputData[0][remapKey(e.which)] = 4;
2097
2101
  }
2098
- const remapKeyCode = (c)=> inputWASDEmulateDirection ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
2102
+ const remapKey = (c)=> inputWASDEmulateDirection ? c==87?38 : c==83?40 : c==65?37 : c==68?39 : c : c;
2099
2103
 
2100
2104
  ///////////////////////////////////////////////////////////////////////////////
2101
2105
  // Mouse event handlers
@@ -2237,6 +2241,9 @@ if (isTouchDevice)
2237
2241
  return true;
2238
2242
  }
2239
2243
 
2244
+ // try to create touch game pad
2245
+ touchGamepadEnable && touchGamepadCreate();
2246
+
2240
2247
  return ontouchstart(e);
2241
2248
  }
2242
2249
  }
@@ -2250,76 +2257,69 @@ let touchGamepadTimer = new Timer, touchGamepadButtons, touchGamepadStick;
2250
2257
  // create the touch gamepad, called automatically by the engine
2251
2258
  function touchGamepadCreate()
2252
2259
  {
2253
- if (!touchGamepadEnable || !isTouchDevice)
2254
- return;
2255
-
2256
2260
  // touch input internal variables
2257
2261
  touchGamepadButtons = [];
2258
2262
  touchGamepadStick = vec2();
2259
2263
 
2260
- // setup touch input
2261
- ontouchstart = (e)=>
2264
+ let touchHandler = ontouchstart;
2265
+ ontouchstart = ontouchmove = ontouchend = (e)=>
2262
2266
  {
2263
- // fix mobile audio, force it to play a sound on first touch
2264
- zzfx(0);
2265
-
2266
- ontouchstart = ontouchmove = ontouchend = (e)=>
2267
+ // clear touch gamepad input
2268
+ touchGamepadStick = vec2();
2269
+ touchGamepadButtons = [];
2270
+
2271
+ const touching = e.touches.length;
2272
+ if (touching)
2267
2273
  {
2268
- // clear touch gamepad input
2269
- touchGamepadStick = vec2();
2270
- touchGamepadButtons = [];
2271
-
2272
- const touching = e.touches.length;
2273
- if (touching)
2274
+ touchGamepadTimer.set();
2275
+ if (paused)
2274
2276
  {
2275
- // set that gamepad is active
2276
- isUsingGamepad = 1;
2277
- touchGamepadTimer.set();
2278
-
2279
- if (paused)
2280
- {
2281
- // touch anywhere to press start when paused
2282
- touchGamepadButtons[9] = 1;
2283
- return;
2284
- }
2277
+ // touch anywhere to press start when paused
2278
+ touchGamepadButtons[9] = 1;
2279
+ return;
2285
2280
  }
2281
+ }
2286
2282
 
2287
- // get center of left and right sides
2288
- const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
2289
- const buttonCenter = mainCanvasSize.subtract(vec2(touchGamepadSize, touchGamepadSize));
2290
- const startCenter = mainCanvasSize.scale(.5);
2283
+ // get center of left and right sides
2284
+ const stickCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
2285
+ const buttonCenter = mainCanvasSize.subtract(vec2(touchGamepadSize, touchGamepadSize));
2286
+ const startCenter = mainCanvasSize.scale(.5);
2291
2287
 
2292
- // check each touch point
2293
- for (const touch of e.touches)
2288
+ // check each touch point
2289
+ for (const touch of e.touches)
2290
+ {
2291
+ const touchPos = mouseToScreen(vec2(touch.clientX, touch.clientY));
2292
+ if (touchPos.distance(stickCenter) < touchGamepadSize)
2294
2293
  {
2295
- const touchPos = mouseToScreen(vec2(touch.clientX, touch.clientY));
2296
- if (touchPos.distance(stickCenter) < touchGamepadSize)
2294
+ // virtual analog stick
2295
+ if (touchGamepadAnalog)
2296
+ touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
2297
+ else
2297
2298
  {
2298
- // virtual analog stick
2299
- if (touchGamepadAnalog)
2300
- touchGamepadStick = touchPos.subtract(stickCenter).scale(2/touchGamepadSize).clampLength();
2301
- else
2302
- {
2303
- // 8 way dpad
2304
- const angle = touchPos.subtract(stickCenter).angle();
2305
- touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
2306
- }
2307
- }
2308
- else if (touchPos.distance(buttonCenter) < touchGamepadSize)
2309
- {
2310
- // virtual face buttons
2311
- const button = touchPos.subtract(buttonCenter).direction();
2312
- touchGamepadButtons[button] = 1;
2313
- }
2314
- else if (touchPos.distance(startCenter) < touchGamepadSize)
2315
- {
2316
- // virtual start button in center
2317
- touchGamepadButtons[9] = 1;
2299
+ // 8 way dpad
2300
+ const angle = touchPos.subtract(stickCenter).angle();
2301
+ touchGamepadStick.setAngle((angle * 4 / PI + 8.5 | 0) * PI / 4);
2318
2302
  }
2319
2303
  }
2304
+ else if (touchPos.distance(buttonCenter) < touchGamepadSize)
2305
+ {
2306
+ // virtual face buttons
2307
+ const button = touchPos.subtract(buttonCenter).direction();
2308
+ touchGamepadButtons[button] = 1;
2309
+ }
2310
+ else if (touchPos.distance(startCenter) < touchGamepadSize)
2311
+ {
2312
+ // virtual start button in center
2313
+ touchGamepadButtons[9] = 1;
2314
+ }
2320
2315
  }
2321
2316
 
2322
- return ontouchstart(e);
2317
+ // call default touch handler and set to using gamepad
2318
+ touchHandler(e);
2319
+ isUsingGamepad = 1;
2320
+
2321
+ // must return true so the document will get focus
2322
+ return true;
2323
2323
  }
2324
2324
  }
2325
2325
 
@@ -2345,7 +2345,7 @@ function touchGamepadRender()
2345
2345
  overlayContext.beginPath();
2346
2346
 
2347
2347
  const leftCenter = vec2(touchGamepadSize, mainCanvasSize.y-touchGamepadSize);
2348
- if (touchGamepadAnalog)
2348
+ if (touchGamepadAnalog) // draw circle shaped gamepad
2349
2349
  {
2350
2350
  overlayContext.arc(leftCenter.x, leftCenter.y, touchGamepadSize/2, 0, 9);
2351
2351
  overlayContext.fill();
@@ -2650,7 +2650,7 @@ function playSamples(sampleChannels, volume=1, rate=1, pan=0, loop=0)
2650
2650
  }
2651
2651
 
2652
2652
  ///////////////////////////////////////////////////////////////////////////////
2653
- // ZzFXMicro - Zuper Zmall Zound Zynth - v1.1.8 by Frank Force
2653
+ // ZzFXMicro - Zuper Zmall Zound Zynth - v1.2.0 by Frank Force
2654
2654
 
2655
2655
  /** Generate and play a ZzFX sound
2656
2656
  * <br>
@@ -2676,11 +2676,11 @@ function zzfxG
2676
2676
  bitCrush = 0, delay = 0, sustainVolume = 1, decay = 0, tremolo = 0
2677
2677
  )
2678
2678
  {
2679
- // init parameters
2679
+ // locals
2680
2680
  let PI2 = PI*2, startSlide = slide *= 500 * PI2 / zzfxR / zzfxR, b=[],
2681
2681
  startFrequency = frequency *= (1 + randomness*rand(-1,1)) * PI2 / zzfxR,
2682
- t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length;
2683
-
2682
+ t=0, tm=0, i=0, j=1, r=0, c=0, s=0, f, length
2683
+
2684
2684
  // scale by sample rate
2685
2685
  attack = attack * zzfxR + 9; // minimum attack to prevent pop
2686
2686
  decay *= zzfxR;
@@ -2730,18 +2730,18 @@ function zzfxG
2730
2730
  Math.cos(modulation*tm++); // modulation
2731
2731
  t += f - f*noise*(1 - (Math.sin(i)+1)*1e9%2); // noise
2732
2732
 
2733
- if (j && ++j > pitchJumpTime) // pitch jump
2733
+ if (j && ++j > pitchJumpTime) // pitch jump
2734
2734
  {
2735
- frequency += pitchJump; // apply pitch jump
2736
- startFrequency += pitchJump; // also apply to start
2737
- j = 0; // reset pitch jump time
2735
+ frequency += pitchJump; // apply pitch jump
2736
+ startFrequency += pitchJump; // also apply to start
2737
+ j = 0; // reset pitch jump time
2738
2738
  }
2739
2739
 
2740
2740
  if (repeatTime && !(++r % repeatTime)) // repeat
2741
2741
  {
2742
- frequency = startFrequency; // reset frequency
2743
- slide = startSlide; // reset slide
2744
- j = j || 1; // reset pitch jump time
2742
+ frequency = startFrequency; // reset frequency
2743
+ slide = startSlide; // reset slide
2744
+ j ||= 1; // reset pitch jump time
2745
2745
  }
2746
2746
  }
2747
2747
 
@@ -3509,7 +3509,7 @@ class Particle extends EngineObject
3509
3509
  * LittleJS Medal System
3510
3510
  * <br> - Tracks and displays medals
3511
3511
  * <br> - Saves medals to local storage
3512
- * <br> - Newgrounds and OS13k integration
3512
+ * <br> - Newgrounds integration
3513
3513
  * @namespace Medals
3514
3514
  */
3515
3515
 
@@ -26,6 +26,11 @@ function gameInit()
26
26
  for (pos.y = 12; pos.y <= levelSize.y-2; pos.y += 1)
27
27
  new Brick(pos);
28
28
 
29
+ // create walls
30
+ new Wall(vec2(-.5,levelSize.y/2), vec2(1,100)) // top
31
+ new Wall(vec2(levelSize.x+.5,levelSize.y/2), vec2(1,100)) // left
32
+ new Wall(vec2(levelSize.x/2,levelSize.y+.5), vec2(100,1)) // right
33
+
29
34
  initPostProcess(); // set up a post processing shader
30
35
  }
31
36
 
@@ -5,31 +5,36 @@
5
5
  'use strict';
6
6
 
7
7
  ///////////////////////////////////////////////////////////////////////////////
8
- class Paddle extends EngineObject
8
+ class Wall extends EngineObject
9
+ {
10
+ constructor(pos, size)
11
+ {
12
+ super(pos, size);
13
+
14
+ this.mass = 0; // make object have static physics
15
+ this.setCollision(); // make object collide
16
+ this.color = new Color(0,0,0,0); // make object invisible
17
+ }
18
+ }
19
+
20
+ ///////////////////////////////////////////////////////////////////////////////
21
+ class Paddle extends EngineObject
9
22
  {
10
23
  constructor(pos)
11
24
  {
12
25
  super(pos, vec2(5,.5));
13
-
14
- // set to collide
15
- this.setCollision();
16
- this.mass = 0;
26
+
27
+ this.mass = 0; // make object have static physics
28
+ this.setCollision(); // make object collide
17
29
  }
18
30
 
19
31
  update()
20
32
  {
21
- if (isUsingGamepad)
22
- {
23
- // control with gamepad
24
- this.pos.x += gamepadStick(0).x;
25
- }
26
- else
27
- {
28
- // move to mouse
29
- this.pos.x = mousePos.x;
30
- }
33
+ // control with gamepad or mouse
34
+ this.pos.x = isUsingGamepad ? this.pos.x + gamepadStick(0).x : mousePos.x;
35
+
36
+ // keep paddle in bounds of level
31
37
  this.pos.x = clamp(this.pos.x, this.size.x/2, levelSize.x - this.size.x/2);
32
- super.update();
33
38
  }
34
39
  }
35
40
 
@@ -39,11 +44,10 @@ class Brick extends EngineObject
39
44
  constructor(pos)
40
45
  {
41
46
  super(pos, vec2(2,1), 1, vec2(32,16), 0, randColor());
42
-
43
- // set to collide
44
- this.setCollision();
45
- this.mass = 0;
46
47
  ++brickCount;
48
+
49
+ this.mass = 0; // make object have static physics
50
+ this.setCollision(); // make object collide
47
51
  }
48
52
 
49
53
  collideWithObject(o)
@@ -54,6 +58,7 @@ class Brick extends EngineObject
54
58
  --brickCount;
55
59
  sound_break.play(this.pos);
56
60
 
61
+ // make explosion effect
57
62
  const color1 = this.color;
58
63
  const color2 = color1.lerp(new Color, .5);
59
64
  new ParticleEmitter(
@@ -62,7 +67,7 @@ class Brick extends EngineObject
62
67
  0, vec2(16), // tileIndex, tileSize
63
68
  color1, color2, // colorStartA, colorStartB
64
69
  color1.scale(1,0), color2.scale(1,0), // colorEndA, colorEndB
65
- .2, .5, 1, .05, .05,// time, sizeStart, sizeEnd, speed, angleSpeed
70
+ .1, .3, 1, .05, .05,// time, sizeStart, sizeEnd, speed, angleSpeed
66
71
  .99, .95, .4, PI, // damping, angleDamping, gravityScale, cone
67
72
  .1, .5, 0, 1 // fadeRate, randomness, collide, additive
68
73
  );
@@ -82,55 +87,43 @@ class Ball extends EngineObject
82
87
  this.setCollision();
83
88
  this.velocity = vec2(randSign(), -1).scale(.1);
84
89
  this.elasticity = 1;
85
- this.damping = 1;
86
90
  }
87
91
 
88
92
  update()
89
93
  {
90
- if (this.pos.y < 0)
94
+ if (this.pos.y < -1)
91
95
  {
92
96
  // destroy ball if it goes below the level
93
97
  ball = 0;
94
98
  this.destroy();
95
99
  }
96
100
 
97
- // bounce on sides and top
98
- const nextPos = this.pos.x + this.velocity.x;
99
- if (nextPos - this.size.x/2 < 0 || nextPos + this.size.x/2 > levelSize.x)
100
- {
101
- this.velocity.x *= -1;
102
- this.bounce();
103
- }
104
- if (this.pos.y + this.velocity.y > levelSize.y)
105
- {
106
- this.velocity.y *= -1;
107
- this.bounce();
108
- }
109
-
110
101
  // update physics
111
102
  super.update();
112
103
  }
113
104
 
114
105
  collideWithObject(o)
115
106
  {
116
- if (o == paddle && this.velocity.y < 0)
117
- {
118
- // put english on the ball when it collides with paddle
119
- this.velocity = this.velocity.rotate(.2 * (this.pos.x - o.pos.x));
120
- this.velocity.y = max(-this.velocity.y, .2);
121
- this.bounce();
107
+ // prevent colliding with paddle if moving upwards
108
+ if (o == paddle && this.velocity.y > 0)
122
109
  return 0;
123
- }
124
- return 1;
125
- }
126
110
 
127
- bounce()
128
- {
129
111
  // speed up
130
- const speed = min(1.05*this.velocity.length(), .5);
112
+ const speed = min(1.04*this.velocity.length(), .5);
131
113
  this.velocity = this.velocity.normalize(speed);
132
114
 
133
115
  // scale bounce sound pitch by speed
134
116
  sound_bounce.play(this.pos, 1, speed);
117
+
118
+ if (o == paddle)
119
+ {
120
+ // put english on the ball when it collides with paddle
121
+ this.velocity = this.velocity.rotate(.2 * (this.pos.x - o.pos.x));
122
+ this.velocity.y = max(-this.velocity.y, .2);
123
+ return 0;
124
+ }
125
+
126
+ // prevent default collision with paddle
127
+ return 1;
135
128
  }
136
129
  }
@@ -1,10 +1,11 @@
1
1
  <html><head>
2
+ <title>Little JS Breakout Game Demo</title>
2
3
  <meta name=viewport content=width=device-width,height=device-height,initial-scale=1,maximum-scale=1>
3
4
  <meta name=apple-mobile-web-app-capable content=yes>
4
5
  <meta name=mobile-web-app-capable content=yes>
5
- <link rel=icon type=image/png href=../../favicon.png>
6
+ <link rel=icon type=image/png href=../favicon.png>
6
7
  </head><body>
7
8
 
8
- <script src=../../engine/engine.all.js?125></script>
9
- <script src=gameObjects.js?125></script>
10
- <script src=game.js?125></script>
9
+ <script src=../../build/littlejs.js?126></script>
10
+ <script src=gameObjects.js?126></script>
11
+ <script src=game.js?126></script>