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 语句中放什么来检测角碰撞。
问题不在于您需要检测角碰撞。问题是当检测到碰撞时,您当前的碰撞检测不会将球移到一边。
调用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语句,它也解决了您的上述问题。