1

I'm developing a game and I've found (a problem) and, to solve it, I need to return the intersection position and size.

Here's the rectangle collision detection code:

for (var i = 0; i < rects.length; i++) {
    for (var others = 0; others < rects.length; others++) {
        if (others != i) {
            if (rects[others].y + rects[others].height >= rects[i].y &&
                rects[others].x + rects[others].width >= rects[i].x &&
                rects[others].x <= rects[i].x + rects[i].width &&
                rects[others].y <= rects[i].y + rects[i].height) {
                // They're intersecting!
                intery = 0; // Intersection Y
                interx = 0; // Intersection X
                interw = 0; // Intersection Width
                interh = 0; // Intersection Height
            }
        }
    }
}

Tiago Marinho
  • 2,146
  • 17
  • 37
  • I have covered a bit more advanced scenario in http://stackoverflow.com/questions/32104083/calculate-collision-and-area-of-intersection-of-two-rotated-rectangles-polygons/32104084#32104084. – Gajus Aug 19 '15 at 19:32

2 Answers2

6

A Demo: http://jsfiddle.net/m1erickson/TqRxG/

If you have 2 rects defined like this:

enter image description here

var r1={
  x:40,
  y:40,
  w:50,
  h:30,
}

var r2={
  x:60,
  y:60,
  w:50,
  h:30,
}

Then you can calculate their intersection rectangle (if any) like this:

enter image description here

function intersectingRect(r1,r2){
  var x=Math.max(r1.x,r2.x);
  var y=Math.max(r1.y,r2.y);
  var xx=Math.min(r1.x+r1.w,r2.x+r2.w);
  var yy=Math.min(r1.y+r1.h,r2.y+r2.h);
  return({x:x,y:y,w:xx-x,h:yy-y});
}

[ Addition: detect circle-rectangle collision ]

If you have a circle defined like this:

var c={
    x:50,
    y:50,
    r:15
}

Then you can determine if the circle and rectangle are colliding like this:

function RectCircleColliding(circle,rect){
    var distX = Math.abs(circle.x - rect.x-rect.w/2);
    var distY = Math.abs(circle.y - rect.y-rect.h/2);
    if (distX > (rect.w/2 + circle.r)) { return false; }
    if (distY > (rect.h/2 + circle.r)) { return false; }
    if (distX <= (rect.w/2)) { return true; } 
    if (distY <= (rect.h/2)) { return true; }
    var dx=distX-rect.w/2;
    var dy=distY-rect.h/2;
    return (dx*dx+dy*dy<=(circle.r*circle.r));
}
markE
  • 102,905
  • 11
  • 164
  • 176
1

This jsfiddle will give you the intersecting rectangle for two rectangle. Width will be zero for no intersection.

function rectangle(left,top, width, height) {
    this.left=left;
    this.top=top;
    this.width=width;
    this.height=height;
    this.right=this.left+this.width;
    this.bottom=this.top+this.height;

    //method
    this.intersect=intersect;
}

function intersect(rect) {
    if(this.left>rect.left) {
        var rightRect=this;
        var leftRect=rect;
    }
    else {
        var rightRect=rect;
        var leftRect=this;
    }
    if(this.top>rect.top) {
        var topRect=rect;
        var botRect=this;
    }
    else {
        var topRect=this;
        var botRect=rect;
    }
    if(this.right>rect.right) {
        var furtherRect=this;
        var nearerRect=rect;
    }
    else {
        var furtherRect=rect;
        var nearerRect=this;
    }
    if(this.bottom>rect.bottom) {
        var lowerRect=this;
        var upperRect=rect;
    }
    else {
        var lowerRect=rect;
        var upperRect=this;
    }
    if(rightRect.left>leftRect.left+leftRect.width || botRect.top>topRect.top+topRect.height) {
        var intersection=new rectangle(0,0,0,0);
    }
    else {
        var intersection=new rectangle(rightRect.left,botRect.top,nearerRect.right-rightRect.left,upperRect.bottom-botRect.top);
    }
    return intersection;

}

However if there are more than two rectangles where do you want the collision to be disabled. For example which of the two yellow areas below?

EDIT Image corrected enter image description here

Of course there are then various ways that 3 rectangles, R1, R2 an R3 can intersect

R1 with R2 but neither with R3

R1 with R2 and R1 with R3 but with the intersections of R1 with R2 and R1 with R3 not intersecting

and various other ways.

The more rectangles the more possibilities.

jing3142
  • 1,821
  • 1
  • 11
  • 16
  • What I want to do is disable the hero collision (that's a circle) inside the rectangle collision, as you can see in this image http://i.imgur.com/YLw8ToC.png because if I don't do this, the circle collision calculation don't know if this collision is possible or not. I've done the left and top intersection sides calculation using this: `if(rects[i].y <= rects[others].y){intertop[i] = rects[i].y+rects[i].height-rects[others].y;}else{intertop[i] = rects[others].y+rects[others].height-rects[i].y;}` but I still having problems calculating the bottom and right sides. – Tiago Marinho Mar 16 '14 at 17:08
  • You have an array of rectangles presumably this means more than two rectangles so I am still not clear how you are interpreting the many intersections. The logic I have presented using rectangles and that of markE show different ways of calculating bottom and right sides for Two rectangles. If you just have two rectangles then either answer should give you the solution you want. For more than two more detail is needed from you. – jing3142 Mar 16 '14 at 17:55
  • The problem is that I actually have only 2 rects because I'm just testing, but I'll put a lot of them later. This is why I'm using an array of rectangles and a function for rectangle creation. – Tiago Marinho Mar 16 '14 at 18:02
  • so which of the yellow areas in my picture do you need to be the intersection for multiple rectangles? Many rectangles will mean it gets very difficult. Perhaps a fundamental re-think is needed. – jing3142 Mar 16 '14 at 18:08
  • I think it's over-complicated too, but it's the only method I've found to correct this bug: http://stackoverflow.com/questions/22344784/easeljs-bounce-collision-detection-issue. – Tiago Marinho Mar 16 '14 at 18:16
  • Do I see that new rects are added during the game but that existing rects don't move? If so, you only have to test the one newly added rectangle against all existing rectangles. Then save any intersections in an intersectingRects[] array. That way you don't have to test all rects against each other during every tick. – markE Mar 16 '14 at 18:35
  • Aplogies - original image of rectangles had non-intersecting areas coloured yellow. The image now corrected. – jing3142 Mar 17 '14 at 08:27