我正在研究台球在相互碰撞中的简单行为。一切正常,但面对一些简单的球是一个问题是耦合球的效果,他们彼此凉爽。告诉我如何防止这种情况。
bool MGBilliard::CollisingBall(CCPoint curr_point, CCPoint next_point)
{
float dx = next_point.x - (curr_point.x + dvdt.x);
float dy = next_point.y - (curr_point.y - dvdt.y);
float d = dx*dx+dy*dy;
return d <= BALL_RADIUS * BALL_RADIUS;
}
double MGBilliard::angleCollisionBalls(Ball* current, Ball* next)
{
double na;
double dx = fabs(next->location.x - current->location.x);
double dy = fabs(next->location.y - current->location.y);
na = atan(fabs(dy/dx));
if(atan(fabs(current->location.y/current->location.x)) < atan(fabs(next->location.y/next->location.x)))
na = current->angle - na;
else if(atan(fabs(current->location.y/current->location.x)) > atan(fabs(next->location.y/next->location.x)))
na = current->angle + na;
return na;
}
for(unsigned int i = 0;i<BALL_COUNT;++i)
{
if(vBalls[i]->speed > 0){
vBalls[i]->speed += vBalls[i]->acceleration;
float dsdt = vBalls[i]->speed*dt;
dvdt.x = dsdt*cos(vBalls[i]->angle);
dvdt.y = dsdt*sin(vBalls[i]->angle);
vBalls[i]->location.x += dvdt.x;
vBalls[i]->location.y += dvdt.y;
for(unsigned int j = 1; j < BALL_COUNT; ++j)
{
if(i == j) continue;
if(CollisingBall(vBalls[i]->spriteBall->getPosition(),vBalls[j]->spriteBall->getPosition()))
{
vBalls[j]->speed = 600;
double angle;
angle = angleCollisionBalls(vBalls[i],vBalls[j]);
vBalls[i]->angle = (float)-angle;
vBalls[j]->angle = (float)angle;
}
}
}
}
答案 0 :(得分:6)
通过快速查看代码,我会注意到两个直接的错误。
首先,这个:
vBalls[i]->angle = (float)-angle;
vBalls[j]->angle = (float)angle;
不是计算反角的正确方法。例如,当angle
为零(或180度,就此而言)时,它不会执行您希望它执行的操作。
其次,您多次遍历整个vBalls
数组,一次使用索引i
,一个内部循环使用索引j
。这意味着碰撞将被计算两次,并且两个球的speed
将被设置为600!改变你的内循环:
for(unsigned int j = i + 1; j < BALL_COUNT; ++j)
应该防止这种情况发生。
还有一个更微妙的错误。您的碰撞检测不会考虑时间。每个球在游戏循环的每次迭代中移动特定距离。这意味着如果一个'tick'中没有发生碰撞,则球可以直接穿过另一个球,然后触发球远端的碰撞代码 。在这种情况下,您不能进行简单的基于半径的碰撞测试,就好像一个球的移动次数超过(BALL_RADIUS * BALL_RADIUS),您的系统会表现得很奇怪或根本不能正常工作。
我个人会使用向量来描述每个球的速度和方向,而不是角度和速度,但重构你的代码来做这个有点超出了这个问题的范围。