1
\$\begingroup\$

I am trying to implement checkCollision function in my game, I used AABB method but the problem is that my sprites are rotated so it's not really precise. I could finely describe my Sprites with rotated ellipses. Is there any more precise way of detecting the collision if I have the following attributes of entities:

entity.x
entity.y
entity.width
entity.height
entity.angle

Here is what I have coded so far (x and y are in the middle of my sprite):

this.checkCollision = function(entity1, entity2) {
  return (entity1.x - (entity1.width*this.COLLISION_EPSILON_WIDTH)/2 < entity2.x + (entity2.width * this.COLLISION_EPSILON_WIDTH)/2 &&
   entity1.x + (entity1.width*this.COLLISION_EPSILON_WIDTH)/2 > entity2.x - (entity2.width * this.COLLISION_EPSILON_WIDTH)/2 &&
   entity1.y - (entity1.height*this.COLLISION_EPSILON_HEIGHT)/2 < entity2.y + (entity2.height*this.COLLISION_EPSILON_HEIGHT)/2 &&
   (entity1.height*this.COLLISION_EPSILON_HEIGHT)/2 + entity1.y > entity2.y - (entity2.height*this.COLLISION_EPSILON_HEIGHT)/2)
}

PS: my cousin told me to do it with three circles (which creates a shape very similar to the ellipse) but I do not really know how to do it.

\$\endgroup\$
  • \$\begingroup\$ BTW, I believe you mean "ellipse". \$\endgroup\$ – Acccumulation Dec 7 '17 at 15:53
1
\$\begingroup\$

The common method to use is the Separating Axis Theorem. There's an explanation with visuals here:

https://gamedev.stackexchange.com/a/60225/98134

The guys behind N+ created a great interactive tutorial (with code!) about it here:

http://www.metanetsoftware.com/technique/tutorialA.html

\$\endgroup\$
-1
\$\begingroup\$

I've used the separating axis theorem and I've come up with this huge code:

this.checkCollision = function(entity1, entity2) {

  var width1 = (entity1.width * this.COLLISION_EPSILON_WIDTH)/2;
  var height1 = (entity1.height * this.COLLISION_EPSILON_HEIGHT)/2;
  var width2 = (entity2.width * this.COLLISION_EPSILON_WIDTH)/2;
  var height2 = (entity2.height * this.COLLISION_EPSILON_HEIGHT)/2;

   if(typeof entity1.angle == 'undefined')
    entity1.angle = 0;

  if(typeof entity2.angle == 'undefined')
    entity2.angle = 0;

   var radius1 = Math.sqrt((height1 * height1)+(width1 * width1));
   var radius2 = Math.sqrt((height2 * height2)+(width2 * width2));

   var angle1 = Math.asin(height1/radius1);
   var angle2 = Math.asin(height2/radius2);

   var x1 = [];
   var x2 = [];
   var y1 = [];
   var y2 = [];

   x1[0] = entity1.x + radius1 * Math.cos(entity1.angle - angle1);
   y1[0] = entity1.y + radius1 * Math.sin(entity1.angle - angle1);
   x1[1] = entity1.x + radius1 * Math.cos(entity1.angle + angle1);
   y1[1] = entity1.y + radius1 * Math.sin(entity1.angle + angle1);
   x1[2] = entity1.x + radius1 * Math.cos(entity1.angle + Math.PI - angle1);
   y1[2] = entity1.y + radius1 * Math.sin(entity1.angle + Math.PI - angle1);
   x1[3] = entity1.x + radius1 * Math.cos(entity1.angle + Math.PI + angle1);
   y1[3] = entity1.y + radius1 * Math.sin(entity1.angle + Math.PI + angle1);


   x2[0] = entity2.x + radius2 * Math.cos(entity2.angle - angle2);
   y2[0] = entity2.y + radius2 * Math.sin(entity2.angle - angle2);
   x2[1] = entity2.x + radius2 * Math.cos(entity2.angle + angle2);
   y2[1] = entity2.y + radius2 * Math.sin(entity2.angle + angle2);
   x2[2] = entity2.x + radius2 * Math.cos(entity2.angle + Math.PI - angle2);
   y2[2] = entity2.y + radius2 * Math.sin(entity2.angle + Math.PI - angle2);
   x2[3] = entity2.x + radius2 * Math.cos(entity2.angle + Math.PI + angle2);
   y2[3] = entity2.y + radius2 * Math.sin(entity2.angle + Math.PI + angle2);


   var axisx = [];
   var axisy = [];

   axisx[0] = x1[0] - x1[1];
   axisy[0] = y1[0] - y1[1];
   axisx[1] = x1[2] - x1[1];
   axisy[1] = y1[2] - y1[1]

   axisx[2] = x2[0] - x2[1];
   axisy[2] = y2[0] - y2[1];
   axisx[3] = x2[2] - x2[1];
   axisy[3] = y2[2] - y2[1]

   for(var k = 0; k < 4; k++) {

     var proj = x1[0] * axisx[k] + y1[0] * axisy[k];

     var minProj1 = proj;
     var maxProj1 = proj;

     for(var i = 1; i < 4; i++) {
       proj = x1[i] * axisx[k] + y1[i] * axisy[k];

       if(proj < minProj1)
        minProj1 = proj;
       else if(proj > maxProj1)
        maxProj1 = proj;
     }

     proj = x2[0] * axisx[k] + y2[0] * axisy[k];

     var minProj2 = proj;
     var maxProj2 = proj;

     for(var j = 1; j < 4; j++) {
        proj = x2[j] * axisx[k] + y2[j] * axisy[k];

        if(proj < minProj2)
          minProj2 = proj;
        else if(proj > maxProj2)
          maxProj2 = proj;
     }

     if(maxProj2 < minProj1 || maxProj1 < minProj2)
      return false;

   }

   return true;
}
\$\endgroup\$
  • \$\begingroup\$ But what does it do? Could you add some sort of explanation? At least comments? \$\endgroup\$ – Anko Aug 7 '16 at 1:14
  • \$\begingroup\$ there are nice youtube videos explaining this theorem. you should check that out. I didn't write this code myself I copied it and rewrited to javascript. \$\endgroup\$ – Juraj Carnogursky Mar 3 '17 at 16:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.