0

我正在研究台球在相互碰撞中的简单行为。一切正常,但是面对几个轻松的球时,有一个问题是耦合球的效果,它们彼此很酷。告诉我如何防止这种情况。

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;
                }
            }
        }
    }
4

1 回答 1

6

通过快速查看您的代码,有两个直接的错误引起了我的注意。

首先,这个:

vBalls[i]->angle = (float)-angle; 
vBalls[j]->angle = (float)angle; 

不是计算对角的正确方法。angle例如,当它为零(或 180 度,就此而言)时,它不会做你想让它做的事情。

vBalls其次,您多次迭代整个数组,一次使用 index ,一次使用 indexi内部循环j。这意味着碰撞将被计算两次,speed两个球的值将设置为 600!将您的内部循环更改为:

for(unsigned int j = i + 1; j < BALL_COUNT; ++j)

应该防止这种情况发生。

还有一个更微妙的错误。您的碰撞检测不考虑时间。在游戏循环的每次迭代中,每个球都会移动特定的距离。这意味着如果一个“滴答”中没有发生碰撞,一个球可以直接穿过另一个球,然后在球的另一侧触发碰撞代码。在这种情况下你不能做一个简单的基于半径的碰撞测试,如果一个球在一个步骤中移动超过 (BALL_RADIUS * BALL_RADIUS),你的系统会表现得很奇怪或者根本不工作。

我个人会使用向量来描述每个球的速度和方向,而不是角度和速度,但是重构你的代码来做到这一点有点超出了这个问题的范围。

于 2012-09-07T09:53:33.860 回答