melonjs 14.0.2 → 14.1.1

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 (219) hide show
  1. package/README.md +2 -0
  2. package/dist/melonjs.mjs/_virtual/_commonjsHelpers.js +10 -0
  3. package/dist/melonjs.mjs/_virtual/arraymultimap.js +10 -0
  4. package/dist/melonjs.mjs/_virtual/earcut.js +10 -0
  5. package/dist/melonjs.mjs/_virtual/howler.js +10 -0
  6. package/dist/melonjs.mjs/_virtual/index.js +10 -0
  7. package/dist/melonjs.mjs/_virtual/index2.js +10 -0
  8. package/dist/melonjs.mjs/_virtual/multimap.js +10 -0
  9. package/dist/melonjs.mjs/_virtual/setmultimap.js +10 -0
  10. package/dist/melonjs.mjs/application/application.js +238 -0
  11. package/dist/melonjs.mjs/audio/audio.js +536 -0
  12. package/dist/melonjs.mjs/camera/camera2d.js +731 -0
  13. package/dist/melonjs.mjs/entity/entity.js +247 -0
  14. package/dist/melonjs.mjs/game.js +29 -0
  15. package/dist/melonjs.mjs/geometries/ellipse.js +274 -0
  16. package/dist/melonjs.mjs/geometries/line.js +115 -0
  17. package/dist/melonjs.mjs/geometries/path2d.js +318 -0
  18. package/dist/melonjs.mjs/geometries/point.js +88 -0
  19. package/dist/melonjs.mjs/geometries/poly.js +498 -0
  20. package/dist/melonjs.mjs/geometries/rectangle.js +374 -0
  21. package/dist/melonjs.mjs/geometries/roundrect.js +167 -0
  22. package/dist/melonjs.mjs/index.js +248 -0
  23. package/dist/melonjs.mjs/input/gamepad.js +501 -0
  24. package/dist/melonjs.mjs/input/input.js +26 -0
  25. package/dist/melonjs.mjs/input/keyboard.js +470 -0
  26. package/dist/melonjs.mjs/input/pointer.js +393 -0
  27. package/dist/melonjs.mjs/input/pointerevent.js +818 -0
  28. package/dist/melonjs.mjs/lang/deprecated.js +157 -0
  29. package/dist/melonjs.mjs/level/level.js +297 -0
  30. package/dist/melonjs.mjs/level/tiled/TMXGroup.js +141 -0
  31. package/dist/melonjs.mjs/level/tiled/TMXLayer.js +446 -0
  32. package/dist/melonjs.mjs/level/tiled/TMXObject.js +355 -0
  33. package/dist/melonjs.mjs/level/tiled/TMXTile.js +193 -0
  34. package/dist/melonjs.mjs/level/tiled/TMXTileMap.js +636 -0
  35. package/dist/melonjs.mjs/level/tiled/TMXTileset.js +309 -0
  36. package/dist/melonjs.mjs/level/tiled/TMXTilesetGroup.js +81 -0
  37. package/dist/melonjs.mjs/level/tiled/TMXUtils.js +367 -0
  38. package/dist/melonjs.mjs/level/tiled/renderer/TMXHexagonalRenderer.js +504 -0
  39. package/dist/melonjs.mjs/level/tiled/renderer/TMXIsometricRenderer.js +218 -0
  40. package/dist/melonjs.mjs/level/tiled/renderer/TMXOrthogonalRenderer.js +155 -0
  41. package/dist/melonjs.mjs/level/tiled/renderer/TMXRenderer.js +124 -0
  42. package/dist/melonjs.mjs/level/tiled/renderer/TMXStaggeredRenderer.js +107 -0
  43. package/dist/melonjs.mjs/loader/loader.js +801 -0
  44. package/dist/melonjs.mjs/loader/loadingscreen.js +120 -0
  45. package/dist/melonjs.mjs/loader/melonjs_logo.png.js +11 -0
  46. package/dist/melonjs.mjs/math/color.js +616 -0
  47. package/dist/melonjs.mjs/math/math.js +218 -0
  48. package/dist/melonjs.mjs/math/matrix2.js +501 -0
  49. package/dist/melonjs.mjs/math/matrix3.js +679 -0
  50. package/dist/melonjs.mjs/math/observable_vector2.js +469 -0
  51. package/dist/melonjs.mjs/math/observable_vector3.js +559 -0
  52. package/dist/melonjs.mjs/math/vector2.js +526 -0
  53. package/dist/melonjs.mjs/math/vector3.js +567 -0
  54. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/src/arraymultimap.js +73 -0
  55. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/src/index.js +21 -0
  56. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/src/multimap.js +324 -0
  57. package/dist/melonjs.mjs/node_modules/@teppeis/multimaps/dist/src/setmultimap.js +69 -0
  58. package/dist/melonjs.mjs/node_modules/earcut/src/earcut.js +691 -0
  59. package/dist/melonjs.mjs/node_modules/eventemitter3/index.js +350 -0
  60. package/dist/melonjs.mjs/node_modules/howler/dist/howler.js +3241 -0
  61. package/dist/melonjs.mjs/particles/emitter.js +265 -0
  62. package/dist/melonjs.mjs/particles/particle.js +186 -0
  63. package/dist/melonjs.mjs/particles/settings.js +319 -0
  64. package/dist/melonjs.mjs/physics/body.js +702 -0
  65. package/dist/melonjs.mjs/physics/bounds.js +459 -0
  66. package/dist/melonjs.mjs/physics/collision.js +132 -0
  67. package/dist/melonjs.mjs/physics/detector.js +194 -0
  68. package/dist/melonjs.mjs/physics/quadtree.js +394 -0
  69. package/dist/melonjs.mjs/physics/response.js +57 -0
  70. package/dist/melonjs.mjs/physics/sat.js +483 -0
  71. package/dist/melonjs.mjs/physics/world.js +219 -0
  72. package/dist/melonjs.mjs/plugin/plugin.js +141 -0
  73. package/dist/melonjs.mjs/renderable/collectable.js +60 -0
  74. package/dist/melonjs.mjs/renderable/colorlayer.js +78 -0
  75. package/dist/melonjs.mjs/renderable/container.js +1016 -0
  76. package/dist/melonjs.mjs/renderable/dragndrop.js +224 -0
  77. package/dist/melonjs.mjs/renderable/imagelayer.js +305 -0
  78. package/dist/melonjs.mjs/renderable/light2d.js +155 -0
  79. package/dist/melonjs.mjs/renderable/nineslicesprite.js +246 -0
  80. package/dist/melonjs.mjs/renderable/renderable.js +781 -0
  81. package/dist/melonjs.mjs/renderable/sprite.js +653 -0
  82. package/dist/melonjs.mjs/renderable/trigger.js +156 -0
  83. package/dist/melonjs.mjs/renderable/ui/uibaseelement.js +212 -0
  84. package/dist/melonjs.mjs/renderable/ui/uispriteelement.js +225 -0
  85. package/dist/melonjs.mjs/renderable/ui/uitextbutton.js +127 -0
  86. package/dist/melonjs.mjs/state/stage.js +236 -0
  87. package/dist/melonjs.mjs/state/state.js +596 -0
  88. package/dist/melonjs.mjs/system/device.js +909 -0
  89. package/dist/melonjs.mjs/system/dom.js +78 -0
  90. package/dist/melonjs.mjs/system/event.js +537 -0
  91. package/dist/melonjs.mjs/system/platform.js +41 -0
  92. package/dist/melonjs.mjs/system/pooling.js +209 -0
  93. package/dist/melonjs.mjs/system/save.js +157 -0
  94. package/dist/melonjs.mjs/system/timer.js +286 -0
  95. package/dist/melonjs.mjs/text/bitmaptext.js +363 -0
  96. package/dist/melonjs.mjs/text/bitmaptextdata.js +198 -0
  97. package/dist/melonjs.mjs/text/glyph.js +65 -0
  98. package/dist/melonjs.mjs/text/text.js +452 -0
  99. package/dist/melonjs.mjs/text/textmetrics.js +175 -0
  100. package/dist/melonjs.mjs/text/textstyle.js +23 -0
  101. package/dist/melonjs.mjs/tweens/easing.js +336 -0
  102. package/dist/melonjs.mjs/tweens/interpolation.js +112 -0
  103. package/dist/melonjs.mjs/tweens/tween.js +479 -0
  104. package/dist/melonjs.mjs/utils/agent.js +76 -0
  105. package/dist/melonjs.mjs/utils/array.js +63 -0
  106. package/dist/melonjs.mjs/utils/file.js +42 -0
  107. package/dist/melonjs.mjs/utils/function.js +70 -0
  108. package/dist/melonjs.mjs/utils/string.js +82 -0
  109. package/dist/melonjs.mjs/utils/utils.js +173 -0
  110. package/dist/melonjs.mjs/video/canvas/canvas_renderer.js +806 -0
  111. package/dist/melonjs.mjs/video/renderer.js +410 -0
  112. package/dist/melonjs.mjs/video/texture/atlas.js +519 -0
  113. package/dist/melonjs.mjs/video/texture/cache.js +143 -0
  114. package/dist/melonjs.mjs/video/texture/canvas_texture.js +144 -0
  115. package/dist/melonjs.mjs/video/video.js +462 -0
  116. package/dist/melonjs.mjs/video/webgl/buffer/vertex.js +142 -0
  117. package/dist/melonjs.mjs/video/webgl/glshader.js +167 -0
  118. package/dist/melonjs.mjs/video/webgl/shaders/primitive.frag.js +10 -0
  119. package/dist/melonjs.mjs/video/webgl/shaders/primitive.vert.js +10 -0
  120. package/dist/melonjs.mjs/video/webgl/shaders/quad.frag.js +10 -0
  121. package/dist/melonjs.mjs/video/webgl/shaders/quad.vert.js +10 -0
  122. package/dist/melonjs.mjs/video/webgl/utils/attributes.js +25 -0
  123. package/dist/melonjs.mjs/video/webgl/utils/precision.js +20 -0
  124. package/dist/melonjs.mjs/video/webgl/utils/program.js +67 -0
  125. package/dist/melonjs.mjs/video/webgl/utils/string.js +25 -0
  126. package/dist/melonjs.mjs/video/webgl/utils/uniforms.js +92 -0
  127. package/dist/melonjs.mjs/video/webgl/webgl_compositor.js +494 -0
  128. package/dist/melonjs.mjs/video/webgl/webgl_renderer.js +1035 -0
  129. package/dist/melonjs.module.d.ts +1298 -1359
  130. package/dist/melonjs.module.js +2072 -3520
  131. package/package.json +21 -16
  132. package/src/application/application.js +4 -5
  133. package/src/audio/audio.js +32 -32
  134. package/src/camera/camera2d.js +32 -33
  135. package/src/entity/entity.js +18 -19
  136. package/src/geometries/ellipse.js +17 -18
  137. package/src/geometries/line.js +6 -7
  138. package/src/geometries/path2d.js +33 -34
  139. package/src/geometries/point.js +1 -2
  140. package/src/geometries/poly.js +16 -18
  141. package/src/geometries/rectangle.js +19 -20
  142. package/src/geometries/roundrect.js +9 -10
  143. package/src/input/gamepad.js +15 -15
  144. package/src/input/keyboard.js +12 -12
  145. package/src/input/pointer.js +6 -6
  146. package/src/input/pointerevent.js +12 -12
  147. package/src/lang/deprecated.js +12 -12
  148. package/src/level/level.js +25 -25
  149. package/src/level/tiled/TMXLayer.js +23 -24
  150. package/src/level/tiled/TMXTile.js +6 -7
  151. package/src/level/tiled/TMXTileMap.js +8 -10
  152. package/src/level/tiled/TMXTileset.js +3 -4
  153. package/src/level/tiled/TMXTilesetGroup.js +1 -2
  154. package/src/level/tiled/TMXUtils.js +5 -5
  155. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +3 -4
  156. package/src/level/tiled/renderer/TMXIsometricRenderer.js +3 -4
  157. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +2 -3
  158. package/src/level/tiled/renderer/TMXRenderer.js +20 -21
  159. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -2
  160. package/src/loader/loader.js +20 -20
  161. package/src/math/color.js +21 -22
  162. package/src/math/math.js +16 -16
  163. package/src/math/matrix2.js +17 -18
  164. package/src/math/matrix3.js +26 -27
  165. package/src/math/observable_vector2.js +15 -16
  166. package/src/math/observable_vector3.js +17 -18
  167. package/src/math/vector2.js +10 -11
  168. package/src/math/vector3.js +11 -12
  169. package/src/particles/emitter.js +7 -8
  170. package/src/particles/particle.js +3 -4
  171. package/src/physics/body.js +29 -30
  172. package/src/physics/bounds.js +10 -10
  173. package/src/physics/collision.js +2 -2
  174. package/src/physics/detector.js +6 -6
  175. package/src/physics/quadtree.js +18 -23
  176. package/src/physics/sat.js +31 -31
  177. package/src/physics/world.js +6 -7
  178. package/src/plugin/plugin.js +5 -5
  179. package/src/renderable/collectable.js +4 -6
  180. package/src/renderable/colorlayer.js +6 -8
  181. package/src/renderable/container.js +25 -27
  182. package/src/renderable/dragndrop.js +14 -14
  183. package/src/renderable/imagelayer.js +14 -15
  184. package/src/renderable/light2d.js +4 -5
  185. package/src/renderable/nineslicesprite.js +17 -18
  186. package/src/renderable/renderable.js +26 -28
  187. package/src/renderable/sprite.js +29 -30
  188. package/src/renderable/trigger.js +16 -17
  189. package/src/renderable/ui/uibaseelement.js +8 -9
  190. package/src/renderable/ui/uispriteelement.js +8 -8
  191. package/src/renderable/ui/uitextbutton.js +15 -15
  192. package/src/state/stage.js +8 -9
  193. package/src/state/state.js +17 -17
  194. package/src/system/device.js +11 -11
  195. package/src/system/event.js +10 -10
  196. package/src/system/pooling.js +9 -9
  197. package/src/system/save.js +2 -2
  198. package/src/system/timer.js +10 -10
  199. package/src/text/bitmaptext.js +19 -20
  200. package/src/text/bitmaptextdata.js +3 -4
  201. package/src/text/glyph.js +1 -2
  202. package/src/text/text.js +24 -25
  203. package/src/text/textmetrics.js +9 -10
  204. package/src/tweens/tween.js +20 -21
  205. package/src/utils/agent.js +5 -5
  206. package/src/utils/array.js +4 -4
  207. package/src/utils/file.js +2 -2
  208. package/src/utils/function.js +6 -6
  209. package/src/utils/string.js +5 -5
  210. package/src/utils/utils.js +4 -4
  211. package/src/video/canvas/canvas_renderer.js +72 -73
  212. package/src/video/renderer.js +27 -28
  213. package/src/video/texture/atlas.js +22 -22
  214. package/src/video/texture/canvas_texture.js +9 -9
  215. package/src/video/video.js +17 -17
  216. package/src/video/webgl/buffer/vertex.js +1 -2
  217. package/src/video/webgl/glshader.js +12 -12
  218. package/src/video/webgl/webgl_compositor.js +42 -43
  219. package/src/video/webgl/webgl_renderer.js +76 -77
@@ -0,0 +1,483 @@
1
+ /*!
2
+ * melonJS Game Engine - v14.1.1
3
+ * http://www.melonjs.org
4
+ * melonjs is licensed under the MIT License.
5
+ * http://www.opensource.org/licenses/mit-license
6
+ * @copyright (C) 2011 - 2022 Olivier Biot (AltByte Pte Ltd)
7
+ */
8
+ import Vector2d from '../math/vector2.js';
9
+
10
+ /*
11
+ * Separating Axis Theorem implementation, based on the SAT.js library by Jim Riecken <jimr@jimr.ca>
12
+ * Available under the MIT License - https://github.com/jriecken/sat-js
13
+ */
14
+
15
+ /**
16
+ * Constants for Vornoi regions
17
+ * @ignore
18
+ */
19
+ const LEFT_VORNOI_REGION = -1;
20
+
21
+ /**
22
+ * Constants for Vornoi regions
23
+ * @ignore
24
+ */
25
+ const MIDDLE_VORNOI_REGION = 0;
26
+
27
+ /**
28
+ * Constants for Vornoi regions
29
+ * @ignore
30
+ */
31
+ const RIGHT_VORNOI_REGION = 1;
32
+
33
+
34
+ /**
35
+ * A pool of `Vector` objects that are used in calculations to avoid allocating memory.
36
+ * @type {Array.<Vector2d>}
37
+ * @ignore
38
+ */
39
+ var T_VECTORS = [];
40
+ for (var v = 0; v < 10; v++) { T_VECTORS.push(new Vector2d()); }
41
+
42
+ /**
43
+ * A pool of arrays of numbers used in calculations to avoid allocating memory.
44
+ * @type {Array.<Array.<number>>}
45
+ * @ignore
46
+ */
47
+ var T_ARRAYS = [];
48
+ for (var a = 0; a < 5; a++) { T_ARRAYS.push([]); }
49
+
50
+
51
+ /**
52
+ * Flattens the specified array of points onto a unit vector axis,
53
+ * resulting in a one dimensional range of the minimum and
54
+ * maximum value on that axis.
55
+ * @ignore
56
+ * @param {Array.<Vector2d>} points - The points to flatten.
57
+ * @param {Vector2d} normal - The unit vector axis to flatten on.
58
+ * @param {Array.<number>} result - An array. After calling this function,
59
+ * result[0] will be the minimum value,
60
+ * result[1] will be the maximum value.
61
+ */
62
+ function flattenPointsOn(points, normal, result) {
63
+ var min = Number.MAX_VALUE;
64
+ var max = -Number.MAX_VALUE;
65
+ var len = points.length;
66
+ for (var i = 0; i < len; i++) {
67
+ // The magnitude of the projection of the point onto the normal
68
+ var dot = points[i].dot(normal);
69
+ if (dot < min) { min = dot; }
70
+ if (dot > max) { max = dot; }
71
+ }
72
+ result[0] = min;
73
+ result[1] = max;
74
+ }
75
+
76
+ /**
77
+ * Check whether two convex polygons are separated by the specified
78
+ * axis (must be a unit vector).
79
+ * @ignore
80
+ * @param {Vector2d} aPos - The position of the first polygon.
81
+ * @param {Vector2d} bPos - The position of the second polygon.
82
+ * @param {Array.<Vector2d>} aPoints - The points in the first polygon.
83
+ * @param {Array.<Vector2d>} bPoints - The points in the second polygon.
84
+ * @param {Vector2d} axis - The axis (unit sized) to test against. The points of both polygons
85
+ * will be projected onto this axis.
86
+ * @param {Response=} response - A Response object (optional) which will be populated
87
+ * if the axis is not a separating axis.
88
+ * @returns {boolean} true if it is a separating axis, false otherwise. If false,
89
+ * and a response is passed in, information about how much overlap and
90
+ * the direction of the overlap will be populated.
91
+ */
92
+ function isSeparatingAxis(aPos, bPos, aPoints, bPoints, axis, response) {
93
+ var rangeA = T_ARRAYS.pop();
94
+ var rangeB = T_ARRAYS.pop();
95
+ // The magnitude of the offset between the two polygons
96
+ var offsetV = T_VECTORS.pop().copy(bPos).sub(aPos);
97
+ var projectedOffset = offsetV.dot(axis);
98
+
99
+ // Project the polygons onto the axis.
100
+ flattenPointsOn(aPoints, axis, rangeA);
101
+ flattenPointsOn(bPoints, axis, rangeB);
102
+ // Move B's range to its position relative to A.
103
+ rangeB[0] += projectedOffset;
104
+ rangeB[1] += projectedOffset;
105
+ // Check if there is a gap. If there is, this is a separating axis and we can stop
106
+ if (rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1]) {
107
+ T_VECTORS.push(offsetV);
108
+ T_ARRAYS.push(rangeA);
109
+ T_ARRAYS.push(rangeB);
110
+ return true;
111
+ }
112
+
113
+ // This is not a separating axis. If we're calculating a response, calculate the overlap.
114
+ if (response) {
115
+ var overlap = 0;
116
+ // A starts further left than B
117
+ if (rangeA[0] < rangeB[0]) {
118
+ response.aInB = false;
119
+ // A ends before B does. We have to pull A out of B
120
+ if (rangeA[1] < rangeB[1]) {
121
+ overlap = rangeA[1] - rangeB[0];
122
+ response.bInA = false;
123
+ // B is fully inside A. Pick the shortest way out.
124
+ } else {
125
+ var option1 = rangeA[1] - rangeB[0];
126
+ var option2 = rangeB[1] - rangeA[0];
127
+ overlap = option1 < option2 ? option1 : -option2;
128
+ }
129
+ // B starts further left than A
130
+ } else {
131
+ response.bInA = false;
132
+ // B ends before A ends. We have to push A out of B
133
+ if (rangeA[1] > rangeB[1]) {
134
+ overlap = rangeA[0] - rangeB[1];
135
+ response.aInB = false;
136
+ // A is fully inside B. Pick the shortest way out.
137
+ } else {
138
+ var option11 = rangeA[1] - rangeB[0];
139
+ var option22 = rangeB[1] - rangeA[0];
140
+ overlap = option11 < option22 ? option11 : -option22;
141
+ }
142
+ }
143
+
144
+ // If this is the smallest amount of overlap we've seen so far, set it as the minimum overlap.
145
+ var absOverlap = Math.abs(overlap);
146
+ if (absOverlap < response.overlap) {
147
+ response.overlap = absOverlap;
148
+ response.overlapN.copy(axis);
149
+ if (overlap < 0) {
150
+ response.overlapN.negateSelf();
151
+ }
152
+ }
153
+ }
154
+ T_VECTORS.push(offsetV);
155
+ T_ARRAYS.push(rangeA);
156
+ T_ARRAYS.push(rangeB);
157
+ return false;
158
+ }
159
+
160
+
161
+ /**
162
+ * Calculates which Vornoi region a point is on a line segment. <br>
163
+ * It is assumed that both the line and the point are relative to `(0,0)`<br>
164
+ * <pre>
165
+ * | (0) |
166
+ * (-1) [S]--------------[E] (1)
167
+ * | (0) |
168
+ * </pre>
169
+ *
170
+ * @ignore
171
+ * @param {Vector2d} line - The line segment.
172
+ * @param {Vector2d} point - The point.
173
+ * @returns {number} LEFT_VORNOI_REGION (-1) if it is the left region,
174
+ * MIDDLE_VORNOI_REGION (0) if it is the middle region,
175
+ * RIGHT_VORNOI_REGION (1) if it is the right region.
176
+ */
177
+ function vornoiRegion(line, point) {
178
+ var len2 = line.length2();
179
+ var dp = point.dot(line);
180
+ if (dp < 0) {
181
+ // If the point is beyond the start of the line, it is in the
182
+ // left vornoi region.
183
+ return LEFT_VORNOI_REGION;
184
+ } else if (dp > len2) {
185
+ // If the point is beyond the end of the line, it is in the
186
+ // right vornoi region.
187
+ return RIGHT_VORNOI_REGION;
188
+ } else {
189
+ // Otherwise, it's in the middle one.
190
+ return MIDDLE_VORNOI_REGION;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Checks whether polygons collide.
196
+ * @ignore
197
+ * @param {Renderable} a - a reference to the object A.
198
+ * @param {Polygon} polyA - a reference to the object A Polygon to be tested
199
+ * @param {Renderable} b - a reference to the object B.
200
+ * @param {Polygon} polyB - a reference to the object B Polygon to be tested
201
+ * @param {Response=} response - Response object (optional) that will be populated if they intersect.
202
+ * @returns {boolean} true if they intersect, false if they don't.
203
+ */
204
+ function testPolygonPolygon(a, polyA, b, polyB, response) {
205
+ // specific point for
206
+ var aPoints = polyA.points;
207
+ var aNormals = polyA.normals;
208
+ var aLen = aNormals.length;
209
+ var bPoints = polyB.points;
210
+ var bNormals = polyB.normals;
211
+ var bLen = bNormals.length;
212
+ // aboslute shape position
213
+ var posA = T_VECTORS.pop().copy(a.pos).add(a.ancestor.getAbsolutePosition()).add(polyA.pos);
214
+ var posB = T_VECTORS.pop().copy(b.pos).add(b.ancestor.getAbsolutePosition()).add(polyB.pos);
215
+ var i;
216
+
217
+ // If any of the edge normals of A is a separating axis, no intersection.
218
+ for (i = 0; i < aLen; i++) {
219
+ if (isSeparatingAxis(posA, posB, aPoints, bPoints, aNormals[i], response)) {
220
+ T_VECTORS.push(posA);
221
+ T_VECTORS.push(posB);
222
+ return false;
223
+ }
224
+ }
225
+
226
+ // If any of the edge normals of B is a separating axis, no intersection.
227
+ for (i = 0; i < bLen; i++) {
228
+ if (isSeparatingAxis(posA, posB, aPoints, bPoints, bNormals[i], response)) {
229
+ T_VECTORS.push(posA);
230
+ T_VECTORS.push(posB);
231
+ return false;
232
+ }
233
+ }
234
+
235
+ // Since none of the edge normals of A or B are a separating axis, there is an intersection
236
+ // and we've already calculated the smallest overlap (in isSeparatingAxis). Calculate the
237
+ // final overlap vector.
238
+ if (response) {
239
+ response.a = a;
240
+ response.b = b;
241
+ response.overlapV.copy(response.overlapN).scale(response.overlap);
242
+ }
243
+ T_VECTORS.push(posA);
244
+ T_VECTORS.push(posB);
245
+ return true;
246
+ }
247
+
248
+ /**
249
+ * Check if two Ellipse collide.
250
+ * @ignore
251
+ * @param {Renderable} a - a reference to the object A.
252
+ * @param {Ellipse} ellipseA - a reference to the object A Ellipse to be tested
253
+ * @param {Renderable} b - a reference to the object B.
254
+ * @param {Ellipse} ellipseB - a reference to the object B Ellipse to be tested
255
+ * @param {Response=} response - Response object (optional) that will be populated if
256
+ * the circles intersect.
257
+ * @returns {boolean} true if the circles intersect, false if they don't.
258
+ */
259
+ function testEllipseEllipse(a, ellipseA, b, ellipseB, response) {
260
+ // Check if the distance between the centers of the two
261
+ // circles is greater than their combined radius.
262
+ var differenceV = T_VECTORS.pop().copy(b.pos).add(b.ancestor.getAbsolutePosition()).add(ellipseB.pos)
263
+ .sub(a.pos).add(a.ancestor.getAbsolutePosition()).sub(ellipseA.pos);
264
+ var radiusA = ellipseA.radius;
265
+ var radiusB = ellipseB.radius;
266
+ var totalRadius = radiusA + radiusB;
267
+ var totalRadiusSq = totalRadius * totalRadius;
268
+ var distanceSq = differenceV.length2();
269
+ // If the distance is bigger than the combined radius, they don't intersect.
270
+ if (distanceSq > totalRadiusSq) {
271
+ T_VECTORS.push(differenceV);
272
+ return false;
273
+ }
274
+ // They intersect. If we're calculating a response, calculate the overlap.
275
+ if (response) {
276
+ var dist = Math.sqrt(distanceSq);
277
+ response.a = a;
278
+ response.b = b;
279
+ response.overlap = totalRadius - dist;
280
+ response.overlapN.copy(differenceV.normalize());
281
+ response.overlapV.copy(differenceV).scale(response.overlap);
282
+ response.aInB = radiusA <= radiusB && dist <= radiusB - radiusA;
283
+ response.bInA = radiusB <= radiusA && dist <= radiusA - radiusB;
284
+ }
285
+ T_VECTORS.push(differenceV);
286
+ return true;
287
+ }
288
+
289
+ /**
290
+ * Check if a polygon and an ellipse collide.
291
+ * @ignore
292
+ * @param {Renderable} a - a reference to the object A.
293
+ * @param {Polygon} polyA - a reference to the object A Polygon to be tested
294
+ * @param {Renderable} b - a reference to the object B.
295
+ * @param {Ellipse} ellipseB - a reference to the object B Ellipse to be tested
296
+ * @param {Response=} response - Response object (optional) that will be populated if they intersect.
297
+ * @returns {boolean} true if they intersect, false if they don't.
298
+ */
299
+ function testPolygonEllipse(a, polyA, b, ellipseB, response) {
300
+ // Get the position of the circle relative to the polygon.
301
+ var circlePos = T_VECTORS.pop().copy(b.pos).add(b.ancestor.getAbsolutePosition()).add(ellipseB.pos)
302
+ .sub(a.pos).add(a.ancestor.getAbsolutePosition()).sub(polyA.pos);
303
+ var radius = ellipseB.radius;
304
+ var radius2 = radius * radius;
305
+ var points = polyA.points;
306
+ var edges = polyA.edges;
307
+ var len = edges.length;
308
+ var edge = T_VECTORS.pop();
309
+ var normal = T_VECTORS.pop();
310
+ var point = T_VECTORS.pop();
311
+ var dist = 0;
312
+
313
+ // For each edge in the polygon:
314
+ for (var i = 0; i < len; i++) {
315
+ var next = i === len - 1 ? 0 : i + 1;
316
+ var prev = i === 0 ? len - 1 : i - 1;
317
+ var overlap = 0;
318
+ var overlapN = null;
319
+
320
+ // Get the edge.
321
+ edge.copy(edges[i]);
322
+ // Calculate the center of the circle relative to the starting point of the edge.
323
+ point.copy(circlePos).sub(points[i]);
324
+
325
+ // If the distance between the center of the circle and the point
326
+ // is bigger than the radius, the polygon is definitely not fully in
327
+ // the circle.
328
+ if (response && point.length2() > radius2) {
329
+ response.aInB = false;
330
+ }
331
+
332
+ // Calculate which Vornoi region the center of the circle is in.
333
+ var region = vornoiRegion(edge, point);
334
+ var inRegion = true;
335
+ // If it's the left region:
336
+ if (region === LEFT_VORNOI_REGION) {
337
+ var point2 = null;
338
+ if (len > 1) {
339
+ // We need to make sure we're in the RIGHT_VORNOI_REGION of the previous edge.
340
+ edge.copy(edges[prev]);
341
+ // Calculate the center of the circle relative the starting point of the previous edge
342
+ point2 = T_VECTORS.pop().copy(circlePos).sub(points[prev]);
343
+ region = vornoiRegion(edge, point2);
344
+ if (region !== RIGHT_VORNOI_REGION) {
345
+ inRegion = false;
346
+ }
347
+ }
348
+
349
+ if (inRegion) {
350
+ // It's in the region we want. Check if the circle intersects the point.
351
+ dist = point.length();
352
+ if (dist > radius) {
353
+ // No intersection
354
+ T_VECTORS.push(circlePos);
355
+ T_VECTORS.push(edge);
356
+ T_VECTORS.push(normal);
357
+ T_VECTORS.push(point);
358
+ if (point2) {
359
+ T_VECTORS.push(point2);
360
+ }
361
+ return false;
362
+ } else if (response) {
363
+ // It intersects, calculate the overlap.
364
+ response.bInA = false;
365
+ overlapN = point.normalize();
366
+ overlap = radius - dist;
367
+ }
368
+ }
369
+
370
+ if (point2) {
371
+ T_VECTORS.push(point2);
372
+ }
373
+ // If it's the right region:
374
+ } else if (region === RIGHT_VORNOI_REGION) {
375
+ if (len > 1) {
376
+ // We need to make sure we're in the left region on the next edge
377
+ edge.copy(edges[next]);
378
+ // Calculate the center of the circle relative to the starting point of the next edge.
379
+ point.copy(circlePos).sub(points[next]);
380
+ region = vornoiRegion(edge, point);
381
+ if (region !== LEFT_VORNOI_REGION) {
382
+ inRegion = false;
383
+ }
384
+ }
385
+
386
+ if (inRegion) {
387
+ // It's in the region we want. Check if the circle intersects the point.
388
+ dist = point.length();
389
+ if (dist > radius) {
390
+ // No intersection
391
+ T_VECTORS.push(circlePos);
392
+ T_VECTORS.push(edge);
393
+ T_VECTORS.push(normal);
394
+ T_VECTORS.push(point);
395
+ return false;
396
+ } else if (response) {
397
+ // It intersects, calculate the overlap.
398
+ response.bInA = false;
399
+ overlapN = point.normalize();
400
+ overlap = radius - dist;
401
+ }
402
+ }
403
+ // Otherwise, it's the middle region:
404
+ } else {
405
+ // Need to check if the circle is intersecting the edge,
406
+ // Get the normal.
407
+ normal.copy(polyA.normals[i]);
408
+ // Find the perpendicular distance between the center of the
409
+ // circle and the edge.
410
+ dist = point.dot(normal);
411
+ var distAbs = Math.abs(dist);
412
+ // If the circle is on the outside of the edge, there is no intersection.
413
+ if ((len === 1 || dist > 0) && distAbs > radius) {
414
+ // No intersection
415
+ T_VECTORS.push(circlePos);
416
+ T_VECTORS.push(edge);
417
+ T_VECTORS.push(normal);
418
+ T_VECTORS.push(point);
419
+ return false;
420
+ } else if (response) {
421
+ // It intersects, calculate the overlap.
422
+ overlapN = normal;
423
+ overlap = radius - dist;
424
+ // If the center of the circle is on the outside of the edge, or part of the
425
+ // circle is on the outside, the circle is not fully inside the polygon.
426
+ if (dist >= 0 || overlap < 2 * radius) {
427
+ response.bInA = false;
428
+ }
429
+ }
430
+ }
431
+
432
+ // If this is the smallest overlap we've seen, keep it.
433
+ // (overlapN may be null if the circle was in the wrong Vornoi region).
434
+ if (overlapN && response && Math.abs(overlap) < Math.abs(response.overlap)) {
435
+ response.overlap = overlap;
436
+ response.overlapN.copy(overlapN);
437
+ }
438
+ }
439
+
440
+ // Calculate the final overlap vector - based on the smallest overlap.
441
+ if (response) {
442
+ response.a = a;
443
+ response.b = b;
444
+ response.overlapV.copy(response.overlapN).scale(response.overlap);
445
+ }
446
+ T_VECTORS.push(circlePos);
447
+ T_VECTORS.push(edge);
448
+ T_VECTORS.push(normal);
449
+ T_VECTORS.push(point);
450
+ return true;
451
+ }
452
+
453
+ /**
454
+ * Check if an ellipse and a polygon collide. <br>
455
+ * **NOTE:** This is slightly less efficient than testPolygonEllipse as it just
456
+ * runs testPolygonEllipse and reverses the response at the end.
457
+ * @ignore
458
+ * @param {Renderable} a - a reference to the object A.
459
+ * @param {Ellipse} ellipseA - a reference to the object A Ellipse to be tested
460
+ * @param {Renderable} b - a reference to the object B.
461
+ * @param {Polygon} polyB - a reference to the object B Polygon to be tested
462
+ * @param {Response=} response - Response object (optional) that will be populated if
463
+ * they intersect.
464
+ * @returns {boolean} true if they intersect, false if they don't.
465
+ */
466
+ function testEllipsePolygon(a, ellipseA, b, polyB, response) {
467
+ // Test the polygon against the circle.
468
+ var result = testPolygonEllipse(b, polyB, a, ellipseA, response);
469
+ if (result && response) {
470
+ // Swap A and B in the response.
471
+ var resa = response.a;
472
+ var aInB = response.aInB;
473
+ response.overlapN.negateSelf();
474
+ response.overlapV.negateSelf();
475
+ response.a = response.b;
476
+ response.b = resa;
477
+ response.aInB = response.bInA;
478
+ response.bInA = aInB;
479
+ }
480
+ return result;
481
+ }
482
+
483
+ export { testEllipseEllipse, testEllipsePolygon, testPolygonEllipse, testPolygonPolygon };
@@ -0,0 +1,219 @@
1
+ /*!
2
+ * melonJS Game Engine - v14.1.1
3
+ * http://www.melonjs.org
4
+ * melonjs is licensed under the MIT License.
5
+ * http://www.opensource.org/licenses/mit-license
6
+ * @copyright (C) 2011 - 2022 Olivier Biot (AltByte Pte Ltd)
7
+ */
8
+ import Vector2d from '../math/vector2.js';
9
+ import { on, GAME_RESET, LEVEL_LOADED } from '../system/event.js';
10
+ import QuadTree from './quadtree.js';
11
+ import Container from '../renderable/container.js';
12
+ import collision from './collision.js';
13
+ import { collisionCheck } from './detector.js';
14
+ import state from '../state/state.js';
15
+
16
+ /**
17
+ * @classdesc
18
+ * an object representing the physic world, and responsible for managing and updating all childs and physics
19
+ * @augments Container
20
+ */
21
+ class World extends Container {
22
+ /**
23
+ * @param {number} [x=0] - position of the container (accessible via the inherited pos.x property)
24
+ * @param {number} [y=0] - position of the container (accessible via the inherited pos.y property)
25
+ * @param {number} [width=game.viewport.width] - width of the container
26
+ * @param {number} [height=game.viewport.height] - height of the container
27
+ */
28
+ constructor(x = 0, y = 0, width = Infinity, height = Infinity) {
29
+ // call the super constructor
30
+ super(x, y, width, height, true);
31
+
32
+ // world is the root container
33
+ this.name = "rootContainer";
34
+
35
+ // to mimic the previous behavior
36
+ this.anchorPoint.set(0, 0);
37
+
38
+ /**
39
+ * the application (game) this physic world belong to
40
+ * @public
41
+ * @type {Application}
42
+ */
43
+ this.app = null;
44
+
45
+ /**
46
+ * the rate at which the game world is updated,
47
+ * may be greater than or lower than the display fps
48
+ * @public
49
+ * @type {Vector2d}
50
+ * @default 60
51
+ * @name fps
52
+ * @memberof World
53
+ * @see timer.maxfps
54
+ */
55
+ this.fps = 60;
56
+
57
+ /**
58
+ * world gravity
59
+ * @public
60
+ * @type {Vector2d}
61
+ * @default <0,0.98>
62
+ * @name gravity
63
+ * @memberof World
64
+ */
65
+ this.gravity = new Vector2d(0, 0.98);
66
+
67
+ /**
68
+ * Specify the rendering method for tile layers. <br>
69
+ * if false visible part of the layers are rendered dynamically,<br>
70
+ * if true the entire layers are first rendered into an offscreen canvas.<br>
71
+ * the "best" rendering method depends of your game
72
+ * (amount of layer, layer size, amount of tiles per layer, etc.)<br>
73
+ * note : rendering method is also configurable per layer by adding this
74
+ * property to your layer (in Tiled).
75
+ * @type {boolean}
76
+ * @default false
77
+ * @memberof World
78
+ */
79
+ this.preRender = false;
80
+
81
+ /**
82
+ * the active physic bodies in this simulation
83
+ * @name bodies
84
+ * @memberof World
85
+ * @public
86
+ * @type {Set<Body>}
87
+ */
88
+ this.bodies = new Set();
89
+
90
+ /**
91
+ * the instance of the game world quadtree used for broadphase
92
+ * @name broadphase
93
+ * @memberof World
94
+ * @public
95
+ * @type {QuadTree}
96
+ */
97
+ this.broadphase = new QuadTree(this, this.getBounds().clone(), collision.maxChildren, collision.maxDepth);
98
+
99
+ // reset the world container on the game reset signal
100
+ on(GAME_RESET, this.reset, this);
101
+
102
+ // update the broadband world bounds if a new level is loaded
103
+ on(LEVEL_LOADED, () => {
104
+ // reset the quadtree
105
+ this.broadphase.clear(this.getBounds());
106
+ });
107
+ }
108
+
109
+ /**
110
+ * reset the game world
111
+ * @name reset
112
+ * @memberof World
113
+ */
114
+ reset() {
115
+ // clear the quadtree
116
+ this.broadphase.clear();
117
+
118
+ // reset the anchorPoint
119
+ this.anchorPoint.set(0, 0);
120
+
121
+ // call the parent method
122
+ super.reset();
123
+
124
+ // empty the list of active physic bodies
125
+ // Note: this should be empty already when calling the parent method
126
+ this.bodies.clear();
127
+ }
128
+
129
+ /**
130
+ * Add a physic body to the game world
131
+ * @name addBody
132
+ * @memberof World
133
+ * @see Container.addChild
134
+ * @param {Body} body
135
+ * @returns {World} this game world
136
+ */
137
+ addBody(body) {
138
+ //add it to the list of active body
139
+ this.bodies.add(body);
140
+ return this;
141
+ }
142
+
143
+ /**
144
+ * Remove a physic body from the game world
145
+ * @name removeBody
146
+ * @memberof World
147
+ * @see Container.removeChild
148
+ * @param {Body} body
149
+ * @returns {World} this game world
150
+ */
151
+ removeBody(body) {
152
+ //remove from the list of active body
153
+ this.bodies.delete(body);
154
+ return this;
155
+ }
156
+
157
+ /**
158
+ * Apply gravity to the given body
159
+ * @name bodyApplyVelocity
160
+ * @memberof World
161
+ * @private
162
+ * @param {Body} body
163
+ */
164
+ bodyApplyGravity(body) {
165
+ // apply gravity to the current velocity
166
+ if (!body.ignoreGravity && body.gravityScale !== 0) {
167
+ var gravity = this.gravity;
168
+
169
+ // apply gravity if defined
170
+ body.force.x += (body.mass * gravity.x) * body.gravityScale;
171
+ body.force.y += (body.mass * gravity.y) * body.gravityScale;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * update the game world
177
+ * @name reset
178
+ * @memberof World
179
+ * @param {number} dt - the time passed since the last frame update
180
+ * @returns {boolean} true if the word is dirty
181
+ */
182
+ update(dt) {
183
+ var isPaused = state.isPaused();
184
+
185
+ // clear the quadtree
186
+ this.broadphase.clear();
187
+
188
+ // insert the world container (children) into the quadtree
189
+ this.broadphase.insertContainer(this);
190
+
191
+ // iterate through all bodies
192
+ this.bodies.forEach((body) => {
193
+ if (!body.isStatic) {
194
+ var ancestor = body.ancestor;
195
+ // if the game is not paused, and ancestor can be updated
196
+ if (!(isPaused && (!ancestor.updateWhenPaused)) &&
197
+ (ancestor.inViewport || ancestor.alwaysUpdate)) {
198
+ // apply gravity to this body
199
+ this.bodyApplyGravity(body);
200
+ // body update function (this moves it)
201
+ if (body.update(dt) === true) {
202
+ // mark ancestor as dirty
203
+ ancestor.isDirty = true;
204
+ }
205
+ // handle collisions against other objects
206
+ collisionCheck(ancestor);
207
+ // clear body force
208
+ body.force.set(0, 0);
209
+ }
210
+ }
211
+ });
212
+
213
+ // call the super constructor
214
+ return super.update(dt);
215
+ }
216
+
217
+ }
218
+
219
+ export { World as default };