圆和矩形碰撞 [英] Circle and Rectangle collision

查看:80
本文介绍了圆和矩形碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a program in Processing for a bouncing ball and a rectangle. I can get the collision for the sides of the rectangle correct, but I have no idea how to get the corners. This is what I have so far:

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语句中放置什么来检测拐角

I don't know what to put in the if statement to detect the corner collisions.

推荐答案

问题不是您需要检测角碰撞。问题是您当前的碰撞检测功能无法在检测到碰撞时将球移到一侧。

The problem isn't that you need to detect the corner collision. The problem is that you current collision detection doesn't move the ball to a side when a collision is detected.

setup() frameRate(5) >函数以更好地了解发生了什么:

Call frameRate(5) in your setup() function to better see what's going on:

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

Notice that the ball intersects the top of the box, so you multiply the vy variable by -1. That causes the circle to start moving up. But the next frame, the circle is still colliding with the rectangle, because it hasn't moved up enough yet. So your code detects that collision, multiples vy by -1 again, and the ball moves back down. Next frame the same thing happens, until the ball eventually stop colliding with the rectangle.

要解决此问题,当检测到碰撞时,需要移动球,以便

To fix this problem, when you detect a collision, you need to move the ball so that it's no longer colliding with the rectangle in the next frame.

这里是一个如何在顶部完成该操作的示例:

Here is an example of how to do that for the top side:

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

您必须为另一端添加类似的逻辑,但总体思路是相同的:请确保否则该球将不会在下一帧中发生碰撞,否则它将不断在边缘反弹。

You'll have to add similar logic for the other sides, but the general idea is the same: make sure that the ball will not be colliding in the next frame, otherwise it'll keep bouncing on the edge like that.

编辑:仔细查看碰撞逻辑,仍然存在一些问题:您只需要检查三个面,而实际上您应该检查所有四个面。

Taking a closer look at your collision logic, something is still off: you're only ever checking three sides, when you really should be checking all four sides.

让我们以这个为例:

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

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

You're checking that the ball is below the top of the rectangle, to the right of the left of the rectangle, and to the left of the right of the rectangle. That's going to be true for this case:

println()语句中添加您的每个 if 语句(请参见上面的 if 语句中的示例)并注意当球在下面时会发生什么

Add a println() statement to each of your if statements (see the example in the if statement above) and notice what happens when the ball is below the paddle, or to the right of the paddle.

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

You need to refactor your logic so that you're checking all four sides, not just three. If I were you, I'd write a function that takes the next position of the ball and returns a boolean value of true if that position collides with the rectangle. Then you can check before moving the ball on the X and Y axis, which tells you how to bounce. Something like this:

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

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

This takes the place of your four separate if statements, and it solves your above problem as well.

这篇关于圆和矩形碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆