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\$
1
  • \$\begingroup\$ BTW, I believe you mean "ellipse". \$\endgroup\$ Dec 7, 2017 at 15:53

2 Answers 2

0
\$\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\$
2
  • \$\begingroup\$ But what does it do? Could you add some sort of explanation? At least comments? \$\endgroup\$
    – Anko
    Aug 7, 2016 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\$ Mar 3, 2017 at 16:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .