2

I have a test application where I am creating collison detection between to rectangles using Raphael.js.

I am able to get collison detection working properly, but I have to drag it around slooowly.... the issue arises when I move the mouse too quickly. It seems that it is not refreshing quick enough to detect the draggable rect.

The purple square is the only one that drags.

JS Fiddle

I guess my question is how can I improve detection/fix my issue?

Thanks in advance.

1 Answer 1

7

Since move is getting called on each pixel move, you don't have time to do much in the way of calculations to keep it smooth. First, I replaced you function for determining overlap with a more standard one:

var rect_collision = function (x1, y1, size1, x2, y2, size2) {
  var a = {top: y1, bottom: y1+size1, left: x1, right: x1+size1};
  var b = {top: y2, bottom: y2+size2, left: x2, right: x2+size2};

  // this is the general way to figure out if two rects are overlapping
  return !(a.left >= b.right || a.right <= b.left ||                           
           a.top >= b.bottom || a.bottom <= b.top);
};

This just checks to see if one rectangle is completely to the left, right, top, or bottom of the other one. If it isn't, then they must be overlapping. Since this just gives a true or false value, I still had to figure out which side the collision occurred on.

To figure that out, I broke the collisions into two components, an x collision and a y collision by pretending that first only dx changed then only dy changed. Once I knew which direction was causing the overlap I could then use the change in direction to determine which side the overlap occurred on. For example, if x caused the collision and the previous dx was greater than the current dx then the collision was on the right side.

  // check the x and y directions separately                                        
  var x_collide = rect_collision(r2_x, r2_y, rectSize, x, r1_y, rectSize);

  // see if we are currently overlapping
  if (!x_collide) {
    // not colliding, update our x position normally
    this.attr({x:x});
    this.pdx = dx;                          
  }
  else {
    // we are, stick the moving rect to the correct side of the stationary one
    // based on the drag direction that got us stuck
    this.attr({x: this.pdx > dx ? r2_x + rectSize + 1 : r2_x - rectSize - 1});                       
  }

I then added a little bit of extra logic to match the functionality that you had which prevent the user from dragging the rectangle directly through the stationary one. Basically I ended up just seeing if the move would place the moving rectangle directly on the opposite side of the stationary one, and if so, prevent it.

I also cleaned up your checks for the border to get rid of all of the Math.min and Math.max calls since you didn't really need those. That's more of a preference thing though since I doubt there were causing much of the performance issues.

You can see the results at http://jsfiddle.net/X7H9G/3/. I'm not sure if this is the best solution, but it seems to do the job.

Sign up to request clarification or add additional context in comments.

1 Comment

hey bill this is wonderful! i tired the rect_collision they way you did beforei submitted the question, but I couldnt figure out where the collision was coming from, like you said it only returns a true or false. Thanks for taking the time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.