圆形和矩形碰撞

1 processing collision-detection

我有一个处理弹跳球和矩形的程序。我可以正确地获得矩形边的碰撞,但我不知道如何获得角。这是我到目前为止:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

Kev*_*man 6

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

调用frameRate(5)您的setup()函数以更好地查看发生了什么:

坏碰撞

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

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

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

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

好碰撞

您必须为其他边添加类似的逻辑,但总体思路是相同的:确保球不会在下一帧中碰撞,否则它会像这样继续在边缘弹跳。

编辑:仔细看看你的碰撞逻辑,还是有一些问题:你只检查了三个边,而你真的应该检查所有四个边。

让我们以这个为例:

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

您正在检查球是否位于矩形顶部下方、矩形左侧的右侧以及矩形右侧的左侧。这将true适用于这种情况:

无碰撞

println()在您的每个语句中添加一个语句if(请参见if上面语句中的示例),并注意当球位于球拍下方或球拍右侧时会发生什么。

您需要重构您的逻辑,以便检查所有四个方面,而不仅仅是三个方面。如果我是你,我会编写一个函数来获取球的下一个位置并返回一个boolean值,true如果该位置与矩形碰撞。然后您可以在 X 轴和 Y 轴上移动球之前进行检查,这会告诉您如何弹跳。像这样的东西:

  if (collides(circleX + vx, circleY)) {
    vx*=-1;
  } 
  else {
    circleX += vx;
  }
  if (collides(circleX, circleY + vy)) {
    vy*=-1;
  } 
  else {
    circleY += vy;
  }
Run Code Online (Sandbox Code Playgroud)

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