圆和矩形碰撞

时间:2016-07-25 03:18:13

标签: processing collision-detection

我在Processing中有一个用于弹跳球和矩形的程序。我可以得到矩形边的碰撞正确,但我不知道如何获得角落。这就是我到目前为止所做的:

 
int radius = 20;
float circleX, circleY;    //positions
float vx = 3, vy = 3;  //velocities    float boxW, boxH;  //bat dimensions

void setup(){
  size(400,400);
  ellipseMode(RADIUS);
  rectMode(RADIUS);
  circleX = width/4;
  circleY = height/4;
  boxW = 50;
  boxH = 20;
}

void draw(){
  background(0);

  circleX += vx;
  circleY += vy;

  //bouncing off sides
  if (circleX + radius > width || circleX < radius){ vx *= -1; }   //left and right
  if (circleY + radius > height || circleY < radius){ vy *= -1; }  //top and bottom
  if (circleY + radius > height){ 
    circleY = (height-radius)-(circleY-(height-radius)); }  //bottom correction

  //bouncing off bat
  if (circleY + radius > mouseY - boxH && circleX > mouseX - boxW && circleX < mouseX + boxW){ 
      vy *= -1; //top
  }
  if (circleX - radius < mouseX + boxW && circleY > mouseY - boxH && circleY < mouseY + boxH){ 
      vx *= -1; //right
  }
  if (circleY - radius > mouseY + boxH && circleX > mouseX - boxW && circleX < mouseX + boxW){ 
      vy *= -1; //bottom
  }
  if (circleX + radius < mouseX - boxW && circleY > mouseY - boxH && circleY < mouseY + boxH){ 
      vx *= -1; //left
  }

  if ([CORNER DETECTION???]){
    vx *= -1;
    vy *= -1;
  }

  ellipse(circleX,circleY,radius,radius);

  rect(mouseX,mouseY,boxW,boxH);
}

我不知道在if语句中放入什么来检测角落碰撞。

1 个答案:

答案 0 :(得分:3)

问题不在于您需要检测角落碰撞。问题是,当检测到碰撞时,您当前的碰撞检测不会将球移动到一侧。

frameRate(5)功能中拨打setup(),以便更好地了解正在进行的操作:

bad collision

请注意,球与框的顶部相交,因此您将vy变量乘以-1。这导致圆圈开始向上移动。但是下一帧,圆圈仍然与矩形相撞,因为它还没有向上移动。因此,您的代码会检测到该冲突,再次将vy乘以-1,然后球向下移动。下一帧发生同样的事情,直到球最终停止与矩形碰撞。

要解决此问题,当您检测到碰撞时,您需要移动球,使其不再与下一帧中的矩形发生碰撞。

以下是如何为顶端执行此操作的示例:

if (circleY + radius > mouseY - boxH && circleX > mouseX - boxW && circleX < mouseX + boxW) { 
    vy *= -1; //top
    circleY = mouseY-boxH-radius;
}

good collision

你必须为对方添加类似的逻辑,但总体思路是一样的:确保球不会在下一帧中发生碰撞,否则它会继续弹跳这样的边缘。

编辑:仔细查看您的碰撞逻辑,仍有一些问题:当您真正应该检查时,您只会检查三个方面所有四个方。

让我们以此为例:

if (circleY + radius > mouseY - boxH && circleX > mouseX - boxW && circleX < mouseX + boxW){ 
    println("top");  
    vy *= -1; //top
}

您要检查球是否位于矩形顶部下方,矩形左侧右侧以及矩形右侧左侧。对于这种情况,这将是true

no collision

在每个println()语句中添加if语句(请参阅上面if语句中的示例)并注意球在球拍下方或桨的右侧。

你需要重构你的逻辑,以便你检查所有四个方面,而不仅仅是三个方面。如果我是你,我会编写一个函数,该函数接受球的下一个位置,如果该位置与矩形发生碰撞,则返回booleantrue 。然后你可以在X和Y轴上移动球之前检查,它告诉你如何反弹。像这样:

  if (collides(circleX + vx, circleY)) {
    vx*=-1;
  } 
  else {
    circleX += vx;
  }
  if (collides(circleX, circleY + vy)) {
    vy*=-1;
  } 
  else {
    circleY += vy;
  }

这取代了您的四个单独的if语句,它也解决了您的上述问题。