littlejsengine 1.12.6 → 1.13.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 (102) hide show
  1. package/README.md +15 -12
  2. package/dist/littlejs.d.ts +466 -236
  3. package/dist/littlejs.esm.js +6126 -5370
  4. package/dist/littlejs.esm.min.js +4 -1
  5. package/dist/littlejs.js +6093 -5359
  6. package/dist/littlejs.min.js +4 -1
  7. package/dist/littlejs.release.js +5614 -4907
  8. package/examples/box2d/game.js +2 -2
  9. package/examples/box2d/gameObjects.js +8 -7
  10. package/examples/box2d/index.html +1 -1
  11. package/examples/box2d/scenes.js +8 -8
  12. package/examples/breakout/game.js +1 -1
  13. package/examples/breakout/gameObjects.js +2 -2
  14. package/examples/breakout/index.html +1 -1
  15. package/examples/breakoutTutorial/README.md +46 -43
  16. package/examples/breakoutTutorial/game.js +3 -3
  17. package/examples/breakoutTutorial/index.html +1 -1
  18. package/examples/electron/build.bat +7 -0
  19. package/examples/electron/build.js +124 -0
  20. package/examples/electron/electron.js +35 -0
  21. package/examples/electron/game.js +140 -0
  22. package/examples/electron/index.html +13 -0
  23. package/examples/electron/package.json +12 -0
  24. package/examples/electron/tiles.png +0 -0
  25. package/examples/empty/game.js +1 -0
  26. package/examples/empty/index.html +1 -1
  27. package/examples/htmlMenu/game.js +1 -1
  28. package/examples/htmlMenu/index.html +1 -1
  29. package/examples/index.html +486 -182
  30. package/examples/module/game.js +6 -3
  31. package/examples/module/index.html +1 -1
  32. package/examples/particles/index.html +12 -3
  33. package/examples/platformer/game.js +4 -4
  34. package/examples/platformer/gameCharacter.js +6 -6
  35. package/examples/platformer/gameEffects.js +74 -57
  36. package/examples/platformer/gameLevel.js +61 -70
  37. package/examples/platformer/gameObjects.js +4 -4
  38. package/examples/platformer/index.html +1 -1
  39. package/examples/puzzle/index.html +1 -1
  40. package/examples/shorts/base.html +23 -3
  41. package/examples/shorts/blending.js +9 -5
  42. package/examples/shorts/box2d.js +1 -1
  43. package/examples/shorts/box2dCar.js +9 -13
  44. package/examples/shorts/clock.js +1 -1
  45. package/examples/shorts/colors.js +2 -2
  46. package/examples/shorts/flappyGame.js +52 -0
  47. package/examples/shorts/helloWorld.js +6 -3
  48. package/examples/shorts/hillGlideGame.js +56 -0
  49. package/examples/shorts/landerGame.js +32 -0
  50. package/examples/shorts/maze.js +47 -0
  51. package/examples/shorts/medals.js +42 -0
  52. package/examples/shorts/nineSlice.js +21 -0
  53. package/examples/shorts/piano.js +52 -0
  54. package/examples/shorts/platformer.js +24 -20
  55. package/examples/shorts/{pong.js → pongGame.js} +1 -1
  56. package/examples/shorts/raycasting.js +71 -0
  57. package/examples/shorts/shapes.js +9 -9
  58. package/examples/shorts/slidingPuzzle.js +42 -0
  59. package/examples/shorts/spaceGame.js +56 -0
  60. package/examples/shorts/starfield.js +15 -0
  61. package/examples/shorts/systemFont.js +1 -1
  62. package/examples/shorts/tileLayer.js +3 -5
  63. package/examples/shorts/tiles.png +0 -0
  64. package/examples/shorts/tiltedView.js +8 -7
  65. package/examples/shorts/topDown.js +18 -26
  66. package/examples/shorts/uiSystem.js +5 -7
  67. package/examples/starter/build.bat +6 -1
  68. package/examples/starter/build.js +9 -8
  69. package/examples/starter/game.js +7 -4
  70. package/examples/starter/index.html +23 -13
  71. package/examples/stress/index.html +7 -8
  72. package/examples/style.css +139 -0
  73. package/examples/typescript/build.js +2 -3
  74. package/examples/typescript/game.js +4 -4
  75. package/examples/typescript/game.ts +6 -3
  76. package/examples/typescript/index.html +1 -1
  77. package/examples/uiSystem/game.js +10 -25
  78. package/examples/uiSystem/index.html +1 -1
  79. package/package.json +2 -2
  80. package/plugins/box2d.js +22 -97
  81. package/plugins/drawUtilities.js +132 -0
  82. package/plugins/newgrounds.js +1 -1
  83. package/plugins/pluginExport.js +7 -1
  84. package/plugins/postProcess.js +9 -2
  85. package/plugins/uiSystem.js +155 -67
  86. package/plugins/zzfxm.js +1 -1
  87. package/reference.md +10 -10
  88. package/src/engine.js +56 -30
  89. package/src/engineAudio.js +15 -6
  90. package/src/engineBuild.bat +6 -1
  91. package/src/engineBuild.js +20 -5
  92. package/src/engineDebug.js +55 -28
  93. package/src/engineDraw.js +321 -177
  94. package/src/engineExport.js +27 -9
  95. package/src/engineInput.js +110 -38
  96. package/src/engineMedals.js +4 -4
  97. package/src/engineObject.js +71 -70
  98. package/src/engineParticles.js +33 -9
  99. package/src/engineSettings.js +69 -23
  100. package/src/engineTileLayer.js +312 -153
  101. package/src/engineUtilities.js +187 -135
  102. package/src/engineWebGL.js +70 -39
@@ -77,7 +77,7 @@ function gameInit()
77
77
  .99, 1, 1, Math.PI, // damping, angleDamping, gravityScale, cone
78
78
  .05, .5, true, true // fadeRate, randomness, collide, additive
79
79
  );
80
- particleEmitter.elasticity = .3; // bounce when it collides
80
+ particleEmitter.restitution = .3; // bounce when it collides
81
81
  particleEmitter.trailScale = 2; // stretch in direction of motion
82
82
  }
83
83
 
@@ -101,7 +101,10 @@ function gameUpdate()
101
101
 
102
102
  // move particles to mouse location if on screen
103
103
  if (LJS.mousePosScreen.x)
104
+ {
104
105
  particleEmitter.pos = LJS.mousePos;
106
+ particleEmitter.velocity = LJS.mouseDelta.scale(.3*LJS.timeDelta);
107
+ }
105
108
  }
106
109
 
107
110
  ///////////////////////////////////////////////////////////////////////////////
@@ -113,8 +116,8 @@ function gameUpdatePost()
113
116
  ///////////////////////////////////////////////////////////////////////////////
114
117
  function gameRender()
115
118
  {
116
- // draw a grey square in the background without using webgl
117
- LJS.drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6), 0, false);
119
+ // draw a grey square in the background
120
+ LJS.drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6));
118
121
 
119
122
  // draw the logo as a tile
120
123
  LJS.drawTile(vec2(21,5), vec2(4.5), tile(3,128));
@@ -7,4 +7,4 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- Add your game scripts here -->
10
- <script src=game.js type=module></script>
10
+ <script src=game.js type=module></script>
@@ -10,9 +10,6 @@
10
10
  import * as LJS from '../../dist/littlejs.esm.js';
11
11
  const {vec2, hsl, tile} = LJS;
12
12
 
13
- // sound effects
14
- const sound_ui = new LJS.Sound([1,0]);
15
-
16
13
  // UI system
17
14
  let uiRoot, uiMenu;
18
15
  const getMenuVisible =()=> uiMenu.visible;
@@ -24,6 +21,10 @@ LJS.setCanvasPixelated(false);
24
21
 
25
22
  function createUI()
26
23
  {
24
+ LJS.uiSystem.defaultSoundPress = new LJS.Sound([1,0,220]);
25
+ LJS.uiSystem.defaultSoundClick = new LJS.Sound([1,0,440]);
26
+ LJS.uiSystem.defaultCornerRadius = 8;
27
+
27
28
  // setup root to attach all ui elements to
28
29
  uiRoot = new LJS.UIObject;
29
30
  const uiInfo = new LJS.UIText(vec2(0,90), vec2(1e3, 70),
@@ -33,7 +34,7 @@ function createUI()
33
34
  uiRoot.addChild(uiInfo);
34
35
 
35
36
  // setup example menu
36
- uiMenu = new LJS.UIObject(vec2(0,450));
37
+ uiMenu = new LJS.UIObject(vec2(0,500));
37
38
  uiRoot.addChild(uiMenu);
38
39
  const uiBackground = new LJS.UIObject(vec2(0,0), vec2(450,580));
39
40
  uiBackground.lineWidth = 8;
@@ -47,7 +48,7 @@ function createUI()
47
48
  textTitle.lineColor = LJS.BLUE;
48
49
 
49
50
  // example multiline text
50
- const textTest = new LJS.UIText(vec2(-60,-140), vec2(300, 50), 'Test Text\nSecond text line.')
51
+ const textTest = new LJS.UIText(vec2(-60,-120), vec2(300, 50), 'Test Text\nSecond text line.')
51
52
  uiMenu.addChild(textTest);
52
53
 
53
54
  // example tile image
@@ -57,12 +58,7 @@ function createUI()
57
58
  // example checkbox
58
59
  const checkbox = new LJS.UICheckbox(vec2(-140,-20), vec2(40));
59
60
  uiMenu.addChild(checkbox);
60
- checkbox.onPress = ()=>
61
- {
62
- checkbox.checked = !checkbox.checked;
63
- console.log('Checkbox clicked');
64
- sound_ui.play(0,.5,checkbox.checked?4:1);
65
- }
61
+ checkbox.onChange = ()=> console.log('Checkbox clicked');
66
62
 
67
63
  // text attached to checkbox
68
64
  const checkboxText = new LJS.UIText(vec2(170,0), vec2(300, 40), 'Test Checkbox');
@@ -72,27 +68,16 @@ function createUI()
72
68
  const scrollbar = new LJS.UIScrollbar(vec2(0,60), vec2(350, 50));
73
69
  uiMenu.addChild(scrollbar);
74
70
  scrollbar.onChange = ()=> console.log('New scrollbar value:', scrollbar.value);
75
- scrollbar.onPress = ()=> sound_ui.play(0,.3,2);
76
- scrollbar.onRelease = ()=> sound_ui.play(0,.3,4);
77
71
 
78
72
  // example button
79
73
  const button1 = new LJS.UIButton(vec2(0,140), vec2(350, 50), 'Test Button');
80
74
  uiMenu.addChild(button1);
81
- button1.onPress = ()=>
82
- {
83
- console.log('Button 1 clicked');
84
- sound_ui.play();
85
- }
75
+ button1.onClick = ()=> console.log('Button 1 clicked');
86
76
 
87
77
  // exit button
88
78
  const button2 = new LJS.UIButton(vec2(0,220), vec2(350, 50), 'Exit Menu');
89
79
  uiMenu.addChild(button2);
90
- button2.onPress = ()=>
91
- {
92
- console.log('Button 2 clicked');
93
- sound_ui.play(0,.5,2);
94
- setMenuVisible(false);
95
- }
80
+ button2.onClick = ()=> setMenuVisible(false);
96
81
  }
97
82
 
98
83
  ///////////////////////////////////////////////////////////////////////////////
@@ -126,7 +111,7 @@ function gameRender()
126
111
  {
127
112
  // test game rendering
128
113
  LJS.drawRect(vec2(), vec2(1e3), hsl(0,0,.2));
129
- for(let i=0; i<1e3; ++i)
114
+ for (let i=0; i<1e3; ++i)
130
115
  {
131
116
  const pos = vec2(30*Math.sin(i+LJS.time/9),20*Math.sin(i*i+LJS.time/9));
132
117
  LJS.drawTile(pos, vec2(2), tile(3,128), hsl(i/9,1,.4), LJS.time+i, !(i%2), hsl(i/9,1,.1,0));
@@ -7,4 +7,4 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- Add your game scripts here -->
10
- <script src=game.js type=module></script>
10
+ <script src=game.js type=module></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.12.6",
3
+ "version": "1.13.4",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
@@ -39,4 +39,4 @@
39
39
  "typescript": "~5.1.6",
40
40
  "uglify-js": "~3.17.4"
41
41
  }
42
- }
42
+ }
package/plugins/box2d.js CHANGED
@@ -61,7 +61,7 @@ class Box2dObject extends EngineObject
61
61
  bodyDef.set_angle(-angle);
62
62
  this.body = box2d.world.CreateBody(bodyDef);
63
63
  this.body.object = this;
64
- this.outlineColor = BLACK;
64
+ this.lineColor = BLACK;
65
65
  }
66
66
 
67
67
  /** Destroy this object and it's physics body */
@@ -76,7 +76,7 @@ class Box2dObject extends EngineObject
76
76
  /** Copy box2d update sim data */
77
77
  update()
78
78
  {
79
- // use box2d physics update
79
+ // use box2d physics update instead of normal engine update
80
80
  this.pos = box2d.vec2From(this.body.GetPosition());
81
81
  this.angle = -this.body.GetAngle();
82
82
  }
@@ -88,7 +88,7 @@ class Box2dObject extends EngineObject
88
88
  if (this.tileInfo)
89
89
  super.render();
90
90
  else
91
- this.drawFixtures(this.color, this.outlineColor, this.lineWidth, mainContext);
91
+ this.drawFixtures(this.color, this.lineColor, this.lineWidth, mainContext);
92
92
  }
93
93
 
94
94
  /** Render debug info */
@@ -102,13 +102,13 @@ class Box2dObject extends EngineObject
102
102
 
103
103
  /** Draws all this object's fixtures
104
104
  * @param {Color} [color]
105
- * @param {Color} [outlineColor]
105
+ * @param {Color} [lineColor]
106
106
  * @param {number} [lineWidth]
107
107
  * @param {CanvasRenderingContext2D} [context] */
108
- drawFixtures(color=WHITE, outlineColor, lineWidth=.1, context)
108
+ drawFixtures(color=WHITE, lineColor, lineWidth=.1, context)
109
109
  {
110
110
  this.getFixtureList().forEach(fixture=>
111
- box2d.drawFixture(fixture, this.pos, this.angle, color, outlineColor, lineWidth, context));
111
+ box2d.drawFixture(fixture, this.pos, this.angle, color, lineColor, lineWidth, context));
112
112
  }
113
113
 
114
114
  ///////////////////////////////////////////////////////////////////////////////
@@ -131,7 +131,7 @@ class Box2dObject extends EngineObject
131
131
  * @param {number} [friction]
132
132
  * @param {number} [restitution]
133
133
  * @param {boolean} [isSensor] */
134
- addShape(shape, density=1, friction=1, restitution=0, isSensor=false)
134
+ addShape(shape, density=1, friction=.2, restitution=0, isSensor=false)
135
135
  {
136
136
  const fd = new box2d.instance.b2FixtureDef();
137
137
  fd.set_shape(shape);
@@ -1589,10 +1589,10 @@ class Box2dPlugin
1589
1589
  * @param {Vector2} pos
1590
1590
  * @param {number} angle
1591
1591
  * @param {Color} [color]
1592
- * @param {Color} [outlineColor]
1592
+ * @param {Color} [lineColor]
1593
1593
  * @param {number} [lineWidth]
1594
1594
  * @param {CanvasRenderingContext2D} [context] */
1595
- drawFixture(fixture, pos, angle, color=WHITE, outlineColor=BLACK, lineWidth=.1, context=mainContext)
1595
+ drawFixture(fixture, pos, angle, color=WHITE, lineColor=BLACK, lineWidth=.1, context=drawContext)
1596
1596
  {
1597
1597
  const shape = box2d.castObjectType(fixture.GetShape());
1598
1598
  switch (shape.GetType())
@@ -1602,101 +1602,25 @@ class Box2dPlugin
1602
1602
  let points = [];
1603
1603
  for (let i=shape.GetVertexCount(); i--;)
1604
1604
  points.push(box2d.vec2From(shape.GetVertex(i)));
1605
- box2d.drawPoly(pos, angle, points, color, outlineColor, lineWidth, context);
1605
+ drawPoly(points, color, lineWidth, lineColor, pos, angle, false, false, context);
1606
1606
  break;
1607
1607
  }
1608
1608
  case box2d.instance.b2Shape.e_circle:
1609
1609
  {
1610
1610
  const radius = shape.get_m_radius();
1611
- box2d.drawCircle(pos, radius, color, outlineColor, lineWidth, context);
1611
+ drawCircle(pos, radius, color, lineWidth, lineColor, false, false, context);
1612
1612
  break;
1613
1613
  }
1614
1614
  case box2d.instance.b2Shape.e_edge:
1615
1615
  {
1616
1616
  const v1 = box2d.vec2From(shape.get_m_vertex1());
1617
1617
  const v2 = box2d.vec2From(shape.get_m_vertex2());
1618
- box2d.drawLine(pos, angle, v1, v2, color, lineWidth, context);
1618
+ drawLine(v1, v2, lineWidth, lineColor, pos, angle, false, false, context);
1619
1619
  break;
1620
1620
  }
1621
1621
  }
1622
1622
  }
1623
1623
 
1624
- /** draws a circle
1625
- * @param {Vector2} pos
1626
- * @param {number} radius
1627
- * @param {Color} [color]
1628
- * @param {Color} [outlineColor]
1629
- * @param {number} [lineWidth]
1630
- * @param {CanvasRenderingContext2D} [context] */
1631
- drawCircle(pos, radius, color=WHITE, outlineColor=BLACK, lineWidth=.1, context=mainContext)
1632
- {
1633
- drawCanvas2D(pos, vec2(1), 0, 0, context=>
1634
- {
1635
- context.beginPath();
1636
- context.arc(0, 0, radius, 0, 9);
1637
- box2d.drawFillStroke(color, outlineColor, lineWidth, context);
1638
- }, 0, context);
1639
- }
1640
-
1641
- /** draws a polygon
1642
- * @param {Vector2} pos
1643
- * @param {number} angle
1644
- * @param {Array<Vector2>} points
1645
- * @param {Color} [color]
1646
- * @param {Color} [outlineColor]
1647
- * @param {number} [lineWidth]
1648
- * @param {CanvasRenderingContext2D} [context] */
1649
- drawPoly(pos, angle, points, color=WHITE, outlineColor=BLACK, lineWidth=.1, context=mainContext)
1650
- {
1651
- drawCanvas2D(pos, vec2(1), angle, 0, context=>
1652
- {
1653
- context.beginPath();
1654
- points.forEach(p=>context.lineTo(p.x, p.y));
1655
- context.closePath();
1656
- box2d.drawFillStroke(color, outlineColor, lineWidth, context);
1657
- }, 0, context);
1658
- }
1659
-
1660
- /** draws a line
1661
- * @param {Vector2} pos
1662
- * @param {number} angle
1663
- * @param {Vector2} posA
1664
- * @param {Vector2} posB
1665
- * @param {Color} [color]
1666
- * @param {number} [lineWidth]
1667
- * @param {CanvasRenderingContext2D} [context] */
1668
- drawLine(pos, angle, posA, posB, color=WHITE, lineWidth=.1, context=mainContext)
1669
- {
1670
- drawCanvas2D(pos, vec2(1), angle, 0, context=>
1671
- {
1672
- context.beginPath();
1673
- context.lineTo(posA.x, posA.y);
1674
- context.lineTo(posB.x, posB.y);
1675
- box2d.drawFillStroke(0, color, lineWidth, context);
1676
- }, 0, context);
1677
- }
1678
-
1679
- /** performs a fill or stroke as a helper to the other draw functions
1680
- * @param {Color} [color]
1681
- * @param {Color} [outlineColor]
1682
- * @param {number} [lineWidth]
1683
- * @param {CanvasRenderingContext2D} [context] */
1684
- drawFillStroke(color=WHITE, outlineColor=BLACK, lineWidth=.1, context=mainContext)
1685
- {
1686
- if (color)
1687
- {
1688
- context.fillStyle = color.toString();
1689
- context.fill();
1690
- }
1691
- if (outlineColor && lineWidth)
1692
- {
1693
- context.lineWidth = lineWidth;
1694
- context.lineJoin = context.lineCap = 'round';
1695
- context.strokeStyle = outlineColor.toString();
1696
- context.stroke();
1697
- }
1698
- }
1699
-
1700
1624
  ///////////////////////////////////////////////////////////////////////////////
1701
1625
  // helper functions
1702
1626
 
@@ -1797,6 +1721,7 @@ async function box2dInit()
1797
1721
  function setupDebugDraw()
1798
1722
  {
1799
1723
  // setup debug draw
1724
+ const debugLineWidth = .1;
1800
1725
  const debugDraw = new box2d.instance.JSDraw();
1801
1726
  const box2dColor = (c)=> new Color(c.get_r(), c.get_g(), c.get_b());
1802
1727
  const box2dColorPointer = (c)=>
@@ -1814,33 +1739,33 @@ async function box2dInit()
1814
1739
  color = getDebugColor(color);
1815
1740
  point1 = box2d.vec2FromPointer(point1);
1816
1741
  point2 = box2d.vec2FromPointer(point2);
1817
- box2d.drawLine(vec2(), 0, point1, point2, color, undefined, overlayContext);
1742
+ drawLine(point1, point2, debugLineWidth, color, vec2(), 0, false, false, overlayContext);
1818
1743
  };
1819
1744
  debugDraw.DrawPolygon = function(vertices, vertexCount, color)
1820
1745
  {
1821
1746
  color = getDebugColor(color);
1822
1747
  const points = getPointsList(vertices, vertexCount);
1823
- box2d.drawPoly(vec2(), 0, points, undefined, color, undefined, overlayContext);
1748
+ drawPoly(points, CLEAR_WHITE, debugLineWidth, color, vec2(), 0, false, false, overlayContext);
1824
1749
  };
1825
1750
  debugDraw.DrawSolidPolygon = function(vertices, vertexCount, color)
1826
1751
  {
1827
1752
  color = getDebugColor(color);
1828
1753
  const points = getPointsList(vertices, vertexCount);
1829
- box2d.drawPoly(vec2(), 0, points, color, color, undefined, overlayContext);
1754
+ drawPoly(points, color, 0, color, vec2(), 0, false, false, overlayContext);
1830
1755
  };
1831
1756
  debugDraw.DrawCircle = function(center, radius, color)
1832
1757
  {
1833
1758
  color = getDebugColor(color);
1834
1759
  center = box2d.vec2FromPointer(center);
1835
- box2d.drawCircle(center, radius, undefined, color, undefined, overlayContext);
1760
+ drawCircle(center, radius, CLEAR_WHITE, debugLineWidth, color, false, false, overlayContext);
1836
1761
  };
1837
1762
  debugDraw.DrawSolidCircle = function(center, radius, axis, color)
1838
1763
  {
1839
1764
  color = getDebugColor(color);
1840
1765
  center = box2d.vec2FromPointer(center);
1841
1766
  axis = box2d.vec2FromPointer(axis).scale(radius);
1842
- box2d.drawCircle(center, radius, color, color, undefined, overlayContext);
1843
- box2d.drawLine(center, 0, vec2(), axis, color, undefined, overlayContext);
1767
+ drawCircle(center, radius, color, debugLineWidth, color, false, false, overlayContext);
1768
+ drawLine(vec2(), axis, debugLineWidth, color, center, 0, false, false, overlayContext);
1844
1769
  };
1845
1770
  debugDraw.DrawTransform = function(transform)
1846
1771
  {
@@ -1849,8 +1774,8 @@ async function box2dInit()
1849
1774
  const angle = -transform.get_q().GetAngle();
1850
1775
  const p1 = vec2(1,0), c1 = rgb(.75,0,0,.8);
1851
1776
  const p2 = vec2(0,1), c2 = rgb(0,.75,0,.8);
1852
- box2d.drawLine(pos, angle, vec2(), p1, c1, undefined, overlayContext);
1853
- box2d.drawLine(pos, angle, vec2(), p2, c2, undefined, overlayContext);
1777
+ drawLine(vec2(), p1, debugLineWidth, c1, pos, angle, false, false, overlayContext);
1778
+ drawLine(vec2(), p2, debugLineWidth, c2, pos, angle, false, false, overlayContext);
1854
1779
  }
1855
1780
 
1856
1781
  debugDraw.AppendFlags(box2d.instance.b2Draw.e_shapeBit);
@@ -1860,4 +1785,4 @@ async function box2dInit()
1860
1785
  //debugDraw.AppendFlags(box2d.instance.b2Draw.e_centerOfMassBit);
1861
1786
  box2d.world.SetDebugDraw(debugDraw);
1862
1787
  }
1863
- }
1788
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * LittleJS Drawing Utilities Plugin
3
+ * - Extra drawing functions for LittleJS
4
+ * - Nine slice and three slice drawing
5
+ * @namespace DrawUtilities
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ ///////////////////////////////////////////////////////////////////////////////
11
+
12
+ /** Draw a scalable nine-slice UI element to the overlay canvas in screen space
13
+ * This function can not apply color because it draws using the overlay 2d context
14
+ * @param {Vector2} pos - Screen space position
15
+ * @param {Vector2} size - Screen space size
16
+ * @param {TileInfo} startTile - Starting tile for the nine-slice pattern
17
+ * @param {number} [borderSize] - Width of the border sections
18
+ * @param {number} [extraSpace] - Extra spacing adjustment
19
+ * @param {number} [angle] - Angle to rotate by
20
+ * @memberof DrawUtilities */
21
+ function drawNineSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2, angle=0)
22
+ {
23
+ drawNineSlice(pos, size, startTile, WHITE, borderSize, BLACK, extraSpace, angle, false, true, overlayContext);
24
+ }
25
+
26
+ /** Draw a scalable nine-slice UI element in world space
27
+ * This function can apply color and additive color if webgl is enabled
28
+ * @param {Vector2} pos - World space position
29
+ * @param {Vector2} size - World space size
30
+ * @param {TileInfo} startTile - Starting tile for the nine-slice pattern
31
+ * @param {Color} [color] - Color to modulate with
32
+ * @param {number} [borderSize] - Width of the border sections
33
+ * @param {Color} [additiveColor] - Additive color
34
+ * @param {number} [extraSpace] - Extra spacing adjustment
35
+ * @param {number} [angle] - Angle to rotate by
36
+ * @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
37
+ * @param {boolean} [screenSpace] - Use screen space coordinates
38
+ * @param {CanvasRenderingContext2D} [context] - Canvas context to use
39
+ * @memberof DrawUtilities */
40
+ function drawNineSlice(pos, size, startTile, color, borderSize=1, additiveColor, extraSpace=.05, angle=0, useWebGL=glEnable, screenSpace, context)
41
+ {
42
+ // setup nine slice tiles
43
+ const centerTile = startTile.offset(startTile.size);
44
+ const centerSize = size.add(vec2(extraSpace-borderSize*2));
45
+ const cornerSize = vec2(borderSize);
46
+ const cornerOffset = size.scale(.5).subtract(cornerSize.scale(.5));
47
+ const flip = screenSpace ? -1 : 1;
48
+ const rotateAngle = screenSpace ? -angle : angle;
49
+
50
+ // center
51
+ drawTile(pos, centerSize, centerTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
52
+ for (let i=4; i--;)
53
+ {
54
+ // sides
55
+ const horizontal = i%2;
56
+ const sidePos = cornerOffset.multiply(vec2(horizontal?i==1?1:-1:0, horizontal?0:i?-1:1));
57
+ const sideSize = vec2(horizontal ? borderSize : centerSize.x, horizontal ? centerSize.y : borderSize);
58
+ const sideTile = centerTile.offset(startTile.size.multiply(vec2(i==1?1:i==3?-1:0,i==0?-flip:i==2?flip:0)))
59
+ drawTile(pos.add(sidePos.rotate(rotateAngle)), sideSize, sideTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
60
+ }
61
+ for (let i=4; i--;)
62
+ {
63
+ // corners
64
+ const flipX = i>1;
65
+ const flipY = i && i<3;
66
+ const cornerPos = cornerOffset.multiply(vec2(flipX?-1:1, flipY?-1:1));
67
+ const cornerTile = centerTile.offset(startTile.size.multiply(vec2(flipX?-1:1,flipY?flip:-flip)));
68
+ drawTile(pos.add(cornerPos.rotate(rotateAngle)), cornerSize, cornerTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
69
+ }
70
+ }
71
+
72
+ /** Draw a scalable three-slice UI element to the overlay canvas in screen space
73
+ * This function can not apply color because it draws using the overlay 2d context
74
+ * @param {Vector2} pos - Screen space position
75
+ * @param {Vector2} size - Screen space size
76
+ * @param {TileInfo} startTile - Starting tile for the three-slice pattern
77
+ * @param {number} [borderSize] - Width of the border sections
78
+ * @param {number} [extraSpace] - Extra spacing adjustment
79
+ * @param {number} [angle] - Angle to rotate by
80
+ * @memberof DrawUtilities */
81
+ function drawThreeSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2, angle=0)
82
+ {
83
+ drawThreeSlice(pos, size, startTile, WHITE, borderSize, BLACK, extraSpace, angle, false, true, overlayContext);
84
+ }
85
+
86
+ /** Draw a scalable three-slice UI element in world space
87
+ * This function can apply color and additive color if webgl is enabled
88
+ * @param {Vector2} pos - World space position
89
+ * @param {Vector2} size - World space size
90
+ * @param {TileInfo} startTile - Starting tile for the three-slice pattern
91
+ * @param {Color} [color] - Color to modulate with
92
+ * @param {number} [borderSize] - Width of the border sections
93
+ * @param {Color} [additiveColor] - Additive color
94
+ * @param {number} [extraSpace] - Extra spacing adjustment
95
+ * @param {number} [angle] - Angle to rotate by
96
+ * @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
97
+ * @param {boolean} [screenSpace] - Use screen space coordinates
98
+ * @param {CanvasRenderingContext2D} [context] - Canvas context to use
99
+ * @memberof DrawUtilities */
100
+ function drawThreeSlice(pos, size, startTile, color, borderSize=1, additiveColor, extraSpace=.05, angle=0, useWebGL=glEnable, screenSpace, context)
101
+ {
102
+ // setup three slice tiles
103
+ const cornerTile = startTile.frame(0);
104
+ const sideTile = startTile.frame(1);
105
+ const centerTile = startTile.frame(2);
106
+ const centerSize = size.add(vec2(extraSpace-borderSize*2));
107
+ const cornerSize = vec2(borderSize);
108
+ const cornerOffset = size.scale(.5).subtract(cornerSize.scale(.5));
109
+ const flip = screenSpace ? -1 : 1;
110
+ const rotateAngle = screenSpace ? -angle : angle;
111
+
112
+ // center
113
+ drawTile(pos, centerSize, centerTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
114
+ for (let i=4; i--;)
115
+ {
116
+ // sides
117
+ const a = angle + i*PI/2;
118
+ const horizontal = i%2;
119
+ const sidePos = cornerOffset.multiply(vec2(horizontal?i==1?1:-1:0, horizontal?0:i?-flip:flip));
120
+ const sideSize = vec2(horizontal ? centerSize.y : centerSize.x, borderSize);
121
+ drawTile(pos.add(sidePos.rotate(rotateAngle)), sideSize, sideTile, color, a, false, additiveColor, useWebGL, screenSpace, context);
122
+ }
123
+ for (let i=4; i--;)
124
+ {
125
+ // corners
126
+ const a = angle + i*PI/2;
127
+ const flipX = !i || i>2;
128
+ const flipY = i>1;
129
+ const cornerPos = cornerOffset.multiply(vec2(flipX?-1:1, flipY?-flip:flip));
130
+ drawTile(pos.add(cornerPos.rotate(rotateAngle)), cornerSize, cornerTile, color, a, false, additiveColor, useWebGL, screenSpace, context);
131
+ }
132
+ }
@@ -174,4 +174,4 @@ class NewgroundsPlugin
174
174
  debugMedals && console.log(xmlHttp.responseText);
175
175
  return xmlHttp.responseText && JSON.parse(xmlHttp.responseText);
176
176
  }
177
- }
177
+ }
@@ -47,4 +47,10 @@ export
47
47
  Box2dFrictionJoint,
48
48
  Box2dPulleyJoint,
49
49
  Box2dMotorJoint,
50
- };
50
+
51
+ // Drawing Utilities
52
+ drawNineSlice,
53
+ drawNineSliceScreen,
54
+ drawThreeSlice,
55
+ drawThreeSliceScreen,
56
+ };
@@ -32,6 +32,13 @@ class PostProcessPlugin
32
32
  postProcess = this;
33
33
 
34
34
  if (headlessMode) return;
35
+
36
+ if (!glEnable)
37
+ {
38
+ console.warn('PostProcessPlugin: WebGL not enabled!');
39
+ return;
40
+ }
41
+
35
42
  if (!shaderCode) // default shader pass through
36
43
  shaderCode = 'void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}';
37
44
 
@@ -78,7 +85,7 @@ class PostProcessPlugin
78
85
  else
79
86
  {
80
87
  // set the viewport
81
- glContext.viewport(0, 0, glCanvas.width = mainCanvas.width, glCanvas.height = mainCanvas.height);
88
+ glContext.viewport(0, 0, glCanvas.width = drawCanvas.width, glCanvas.height = drawCanvas.height);
82
89
  }
83
90
 
84
91
  if (postProcess.includeOverlay)
@@ -113,4 +120,4 @@ class PostProcessPlugin
113
120
  glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
114
121
  }
115
122
  }
116
- }
123
+ }