2

我有一个测试应用程序,我正在使用 Raphael.js 在矩形之间创建碰撞检测。

我能够让碰撞检测正常工作,但我必须慢慢拖动它......当我移动鼠标太快时会出现问题。似乎刷新速度不够快,无法检测到可拖动的矩形。

紫色方块是唯一拖拽的方块。

JS小提琴

我想我的问题是如何改进检测/解决我的问题?

提前致谢。

4

1 回答 1

7

由于move在每个像素移动时都会被调用,因此您没有时间在计算方式上做很多事情来保持它的平滑。首先,我用更标准的函数替换了用于确定重叠的函数:

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);
};

这只是检查一个矩形是否完全位于另一个矩形的左侧、右侧、顶部或底部。如果不是,那么它们一定是重叠的。由于这只是给出了一个真值或假值,我仍然必须弄清楚碰撞发生在哪一侧。

为了弄清楚这一点,我将碰撞分为两个部分,一个x碰撞和一个y碰撞,假装首先只dx改变然后只dy改变。一旦我知道哪个方向导致了重叠,我就可以使用方向的变化来确定重叠发生在哪一侧。例如,如果x导致碰撞并且先前dx大于当前dx,则碰撞在右侧。

  // 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.

于 2012-09-23T12:07:51.980 回答