我遇到圆圈碰撞检测问题。我使用了以下算法
func collision(id,other.id)
{
var vaP1,vaP2,dis,va1,vb1,va2,vb2,vp1,vp2,dx,dy,dt;
if (id!=other.id)
{
dx=other.x-x;
dy=other.y-y;
dis=sqrt(sqr(dx)+sqr(dy));
if dis<=radius+other.radius
{
//normalize
dx/=dis;
dy/=dis;
//calculate the component of velocity in the direction
vp1=hspeed*dx+vspeed*dy;
vp2=other.hspeed*dx+other.vspeed*dy;
if (vp1-vp2)!=0
{
dt=(radius+other.radius-dis)/(vp1-vp2);
//move the balls back so they just touch
x-=hspeed*dt;
y-=vspeed*dt;
other.x-=other.hspeed*dt;
other.y-=other.vspeed*dt;
//projection of the velocities in these axes
va1=(hspeed*dx+vspeed*dy);
vb1=(vspeed*dx-hspeed*dy);
va2=(other.hspeed*dx+other.vspeed*dy);
vb2=(other.vspeed*dx-other.hspeed*dy);
//new velocities in these axes. take into account the mass of each ball.
vaP1=(va1+bounce*(va2-va1))/(1+mass/other.mass);
vaP2=(va2+other.bounce*(va1-va2))/(1+other.mass/mass);
hspeed=vaP1*dx-vb1*dy;
vspeed=vaP1*dy+vb1*dx;
other.hspeed=vaP2*dx-vb2*dy;
other.vspeed=vaP2*dy+vb2*dx;
//we moved the balls back in time, so we need to move them forward
x+=hspeed*dt;
y+=vspeed*dt;
other.x+=other.hspeed*dt;
other.y+=other.vspeed*dt;
}
}
}
x=ball 1 x-position
y=ball 1 y-position
other.x= ball 2 x position
other.y=ball 2 y position
当我的球像为40 x 40像素且球中心为(20,20)表示图像仅包含球时,此算法效果很好。但是当图像大小为80 x 80时出现问题。球中心位置为(60,60),表示球是右下角,半径为20。
在这种情况下,发生多次碰撞,意味着部分
x+=hspeed*dt;
y+=vspeed*dt;
other.x+=other.hspeed*dt;
other.y+=other.vspeed*dt;
无法分离球/速度不会因碰撞而改变。 我已经改变了x的值,它是图像中心40,40到60,60球的中心,但是结果是一样的。任何人都可以告诉我是什么问题。我认为算法是正确的,因为它有效很好地在所有其他情况下很多人使用这个算法。问题是从图像中心到球中心的位置改变。我应该做什么校正?或任何想法。如果有人想帮助PLZ给我电子邮件地址,以便我可以发送我的完整项目。
答案 0 :(得分:3)
我没有精力来消化你的整个问题,但这里有2美分如何解决你的问题
1)检测与另一个圆圈碰撞的最简单方法是检查它们的距离是否小于组合圆的半径。 (我可能错了数学,如果我错了,请纠正我)
Circle c1,c2;
float distance = DISTANCE(c1.center,c2.center);
if(distance < c1.radius + c2.radius)
{
// collision .. BOOOOOOM
}
2)尝试使用准确的数据类型。尽量不要将浮点数转换为整数而不检查溢出,下溢和小数点。更好的是,只需使用花车。
3)写一个日志并追踪你的值。看看是否有任何明显的数学错误。
4)将代码分解为最简单的部分。尝试删除所有速度计算,以获得最简单的动作来帮助您进行调试。
答案 1 :(得分:-1)
我不会给你你正在寻找的答案,我不确定别人会怎样。为了得到答案而必须被解除的代码数量可能无法保证奖励。我建议的是放弃算法中的耦合。上面的功能正在做太多的工作。
理想情况下,您的碰撞检测仅集中在碰撞而不是推进球。类似于下面显示的功能,如果您仍有问题,可以让其他开发人员更轻松地帮助您。
function(firstCircleCenterX, firstCircleCenterY, secondCircleCenterX, secondCircleCenterY, firstCircleRadius, secondCircleRadius)
{
...this code should concentrate on logic to determine collision
...use pythagoran theory to find distance between the two centers
...if the distance between the two centers is less than ((2*firstCircleRadius)+(2*secondCircleRadius) then you have a collision
...return true or false depending on collision
}