Home Reference Source

src/Collisions.mjs

  1. import BVH from './modules/BVH.mjs';
  2. import Circle from './modules/Circle.mjs';
  3. import Polygon from './modules/Polygon.mjs';
  4. import Point from './modules/Point.mjs';
  5. import Result from './modules/Result.mjs';
  6. import SAT from './modules/SAT.mjs';
  7.  
  8. /**
  9. * A collision system used to track bodies in order to improve collision detection performance
  10. * @class
  11. */
  12. class Collisions {
  13. /**
  14. * @constructor
  15. */
  16. constructor() {
  17. /** @private */
  18. this._bvh = new BVH();
  19. }
  20.  
  21. /**
  22. * Creates a {@link Circle} and inserts it into the collision system
  23. * @param {Number} [x = 0] The starting X coordinate
  24. * @param {Number} [y = 0] The starting Y coordinate
  25. * @param {Number} [radius = 0] The radius
  26. * @param {Number} [scale = 1] The scale
  27. * @param {Number} [padding = 0] The amount to pad the bounding volume when testing for potential collisions
  28. * @returns {Circle}
  29. */
  30. createCircle(x = 0, y = 0, radius = 0, scale = 1, padding = 0) {
  31. const body = new Circle(x, y, radius, scale, padding);
  32.  
  33. this._bvh.insert(body);
  34.  
  35. return body;
  36. }
  37.  
  38. /**
  39. * Creates a {@link Polygon} and inserts it into the collision system
  40. * @param {Number} [x = 0] The starting X coordinate
  41. * @param {Number} [y = 0] The starting Y coordinate
  42. * @param {Array<Number[]>} [points = []] An array of coordinate pairs making up the polygon - [[x1, y1], [x2, y2], ...]
  43. * @param {Number} [angle = 0] The starting rotation in radians
  44. * @param {Number} [scale_x = 1] The starting scale along the X axis
  45. * @param {Number} [scale_y = 1] The starting scale long the Y axis
  46. * @param {Number} [padding = 0] The amount to pad the bounding volume when testing for potential collisions
  47. * @returns {Polygon}
  48. */
  49. createPolygon(x = 0, y = 0, points = [[0, 0]], angle = 0, scale_x = 1, scale_y = 1, padding = 0) {
  50. const body = new Polygon(x, y, points, angle, scale_x, scale_y, padding);
  51.  
  52. this._bvh.insert(body);
  53.  
  54. return body;
  55. }
  56.  
  57. /**
  58. * Creates a {@link Point} and inserts it into the collision system
  59. * @param {Number} [x = 0] The starting X coordinate
  60. * @param {Number} [y = 0] The starting Y coordinate
  61. * @param {Number} [padding = 0] The amount to pad the bounding volume when testing for potential collisions
  62. * @returns {Point}
  63. */
  64. createPoint(x = 0, y = 0, padding = 0) {
  65. const body = new Point(x, y, padding);
  66.  
  67. this._bvh.insert(body);
  68.  
  69. return body;
  70. }
  71.  
  72. /**
  73. * Creates a {@link Result} used to collect the detailed results of a collision test
  74. */
  75. createResult() {
  76. return new Result();
  77. }
  78.  
  79. /**
  80. * Creates a Result used to collect the detailed results of a collision test
  81. */
  82. static createResult() {
  83. return new Result();
  84. }
  85.  
  86. /**
  87. * Inserts bodies into the collision system
  88. * @param {...Circle|...Polygon|...Point} bodies
  89. */
  90. insert(...bodies) {
  91. for(const body of bodies) {
  92. this._bvh.insert(body, false);
  93. }
  94.  
  95. return this;
  96. }
  97.  
  98. /**
  99. * Removes bodies from the collision system
  100. * @param {...Circle|...Polygon|...Point} bodies
  101. */
  102. remove(...bodies) {
  103. for(const body of bodies) {
  104. this._bvh.remove(body, false);
  105. }
  106.  
  107. return this;
  108. }
  109.  
  110. /**
  111. * Updates the collision system. This should be called before any collisions are tested.
  112. */
  113. update() {
  114. this._bvh.update();
  115.  
  116. return this;
  117. }
  118.  
  119. /**
  120. * Draws the bodies within the system to a CanvasRenderingContext2D's current path
  121. * @param {CanvasRenderingContext2D} context The context to draw to
  122. */
  123. draw(context) {
  124. return this._bvh.draw(context);
  125. }
  126.  
  127. /**
  128. * Draws the system's BVH to a CanvasRenderingContext2D's current path. This is useful for testing out different padding values for bodies.
  129. * @param {CanvasRenderingContext2D} context The context to draw to
  130. */
  131. drawBVH(context) {
  132. return this._bvh.drawBVH(context);
  133. }
  134.  
  135. /**
  136. * Returns a list of potential collisions for a body
  137. * @param {Circle|Polygon|Point} body The body to test for potential collisions against
  138. * @returns {Array<Body>}
  139. */
  140. potentials(body) {
  141. return this._bvh.potentials(body);
  142. }
  143.  
  144. /**
  145. * Determines if two bodies are colliding
  146. * @param {Circle|Polygon|Point} target The target body to test against
  147. * @param {Result} [result = null] A Result object on which to store information about the collision
  148. * @param {Boolean} [aabb = true] Set to false to skip the AABB test (useful if you use your own potential collision heuristic)
  149. * @returns {Boolean}
  150. */
  151. collides(source, target, result = null, aabb = true) {
  152. return SAT(source, target, result, aabb);
  153. }
  154. };
  155.  
  156. export {
  157. Collisions as default,
  158. Collisions,
  159. Result,
  160. Circle,
  161. Polygon,
  162. Point,
  163. };