Source: Physics/RigidShape_Collision.js

  1. /*
  2. * File: RigidShape_Collision.js
  3. * Detects RigidPoint collisions
  4. */
  5. /*jslint node: true, vars:true , white: true*/
  6. /*global RigidShape, vec2, LineRenderable, gEngine, gEngine.Particle */
  7. /* find out more about jslint: http://www.jslint.com/help.html */
  8. "use strict";
  9. /**
  10. * Clamp value to min and max
  11. * @param {Number} value to clamp
  12. * @param {Number} min Minimum value to clamp too
  13. * @param {Number} max Maximum value to clamp too
  14. * @returns {Number} clamped number of value
  15. * @memberOf RigidShape
  16. */
  17. RigidShape.prototype.clamp = function (value, min, max) {
  18. return Math.min(Math.max(value, min), max);
  19. };
  20. /**
  21. * Check for collision between RigidRectangle and RigidCircle
  22. * @param {RigidRectangle} rect1Shape Rectangle object to check for collision status
  23. * @param {RigidCircle} circ2Shape Circle object to check for collision status against
  24. * @param {CollisionInfo} collisionInfo Collision info of collision
  25. * @returns {Boolean} true if collision occurs
  26. * @memberOf RigidShape
  27. */
  28. RigidShape.prototype.collidedRectCirc = function(rect1Shape, circ2Shape, collisionInfo) {
  29. var rect1Pos = rect1Shape.getXform().getPosition();
  30. var circ2Pos = circ2Shape.getXform().getPosition();
  31. var vFrom1to2 = [0, 0];
  32. vec2.subtract(vFrom1to2, circ2Pos, rect1Pos);
  33. var vec = vec2.clone(vFrom1to2);
  34. var alongX = rect1Shape.getWidth() / 2;
  35. var alongY = rect1Shape.getHeight() / 2;
  36. vec[0] = this.clamp(vec[0], -alongX, alongX);
  37. vec[1] = this.clamp(vec[1], -alongY, alongY);
  38. var isInside = false;
  39. if (rect1Shape.containsPos(circ2Pos)) {
  40. isInside = true;
  41. // Find closest axis
  42. if (Math.abs(vFrom1to2[0] - alongX) < Math.abs(vFrom1to2[1] - alongY)) {
  43. // Clamp to closest side
  44. if (vec[0] > 0) {
  45. vec[0] = alongX;
  46. } else {
  47. vec[0] = -alongX;
  48. }
  49. } else { // y axis is shorter
  50. // Clamp to closest side
  51. if (vec[1] > 0) {
  52. vec[1] = alongY;
  53. } else {
  54. vec[1] = -alongY;
  55. }
  56. }
  57. }
  58. var normal = [0, 0];
  59. vec2.subtract(normal, vFrom1to2, vec);
  60. var distSqr = vec2.squaredLength(normal);
  61. var rSqr = circ2Shape.getRadius() * circ2Shape.getRadius();
  62. if (distSqr > rSqr && !isInside) {
  63. return false; //no collision exit before costly square root
  64. }
  65. var len = Math.sqrt(distSqr);
  66. var depth;
  67. vec2.scale(normal, normal, 1/len); // normalize normal
  68. if (isInside) { //flip normal if inside the rect
  69. vec2.scale(normal, normal, -1);
  70. depth = circ2Shape.getRadius() + len;
  71. } else {
  72. depth = circ2Shape.getRadius() - len;
  73. }
  74. collisionInfo.setNormal(normal);
  75. collisionInfo.setDepth(depth);
  76. return true;
  77. };
  78. /**
  79. * pushes a Particle out of a RigidCircle or a RigidRectangle.
  80. * @param {Particle} aParticle
  81. * @returns {Boolean}
  82. * @memberOf RigidShape
  83. */
  84. RigidShape.prototype.resolveParticleCollision = function(aParticle) {
  85. var status = false;
  86. switch (this.rigidType()) {
  87. case RigidShape.eRigidType.eRigidCircle:
  88. status = gEngine.Particle.resolveCirclePos(this, aParticle);
  89. break;
  90. case RigidShape.eRigidType.eRigidRectangle:
  91. status = gEngine.Particle.resolveRectPos(this, aParticle);
  92. break;
  93. }
  94. return status;
  95. };