我想找到静态和移动球之间发生碰撞的时间,但我想出的算法,有时候没有检测到碰撞而移动的球经过静态球。移动球受重力影响,而静态球不受重力影响。
这是我的碰撞检测代码:
GLfloat whenSpheresCollide(const sphere2d &firstSphere, const sphere2d &secondSphere)
{
Vector2f relativePosition = subtractVectors(firstSphere.vPosition, secondSphere.vPosition);
Vector2f relativeVelocity = subtractVectors(firstSphere.vVelocity, secondSphere.vVelocity);
GLfloat radiusSum = firstSphere.radius + secondSphere.radius;
//We'll find the time when objects collide if a collision takes place
//r(t) = P[0] + t * V[0]
//
//d^2(t) = P[0]^2 + 2 * t * P[0] * V[0] + t^2 * V[0]^2
//
//d^2(t) = V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2
//
//d(t) = R
//
//d(t)^2 = R^2
//
//V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2 - R^2 = 0
//
//delta = ( P[0] . V[0] )^2 - V[0]^2 * (P[0]^2 - R^2)
//
// We are interested in the lowest t:
//
//t = ( -( P[0] . V[0] ) - sqrt(delta) ) / V[0]^2
//
GLfloat equationDelta = squaref( dotProduct(relativePosition, relativeVelocity) ) - squarev( relativeVelocity ) * ( squarev( relativePosition ) - squaref(radiusSum) );
if (equationDelta >= 0.0f)
{
GLfloat collisionTime = ( - dotProduct(relativePosition, relativeVelocity) - sqrtf(equationDelta) ) / squarev(relativeVelocity);
if (collisionTime >= 0.0f && collisionTime <= 1.0f / GAME_FPS)
{
return collisionTime;
}
}
return -1.0f;
}
这是调用碰撞检测的更新函数:
void GamePhysicsManager::updateBallPhysics()
{
//
//Update velocity
vVelocity->y -= constG / GAME_FPS; //v = a * t = g * 1 sec / (updates per second)
shouldApplyForcesToBall = TRUE;
vPosition->x += vVelocity->x / GAME_FPS;
vPosition->y += vVelocity->y / GAME_FPS;
if ( distanceBetweenVectors( *pBall->getPositionVector(), *pBasket->getPositionVector() ) <= pBasket->getRadius() + vectorLength(*vVelocity) / GAME_FPS )
{
//Ball sphere
sphere2d ballSphere;
ballSphere.radius = pBall->getRadius();
ballSphere.mass = 1.0f;
ballSphere.vPosition = *( pBall->getPositionVector() );
ballSphere.vVelocity = *( pBall->getVelocityVector() );
sphere2d ringSphereRight;
ringSphereRight.radius = 0.05f;
ringSphereRight.mass = -1.0f;
ringSphereRight.vPosition = *( pBasket->getPositionVector() );
//ringSphereRight.vPosition.x += pBasket->getRadius();
ringSphereRight.vPosition.x += (pBasket->getRadius() - ringSphereRight.radius);
ringSphereRight.vVelocity = zeroVector();
GLfloat collisionTime = whenSpheresCollide(ballSphere, ringSphereRight);
if ( collisionTime >= 0.0f )
{
DebugLog("collision");
respondToCollision(&ballSphere, &ringSphereRight, collisionTime, pBall->getRestitution() * 0.75f );
}
//
//Implement selection of the results that are first to collide collision
vVelocity->x = ballSphere.vVelocity.x;
vVelocity->y = ballSphere.vVelocity.y;
vPosition->x = ballSphere.vPosition.x;
vPosition->y = ballSphere.vPosition.y;
}
为什么100%的情况下都没有检测到碰撞?仅在70%的情况下检测到它。 感谢。
更新:当我将FPS从30更改为10时,问题似乎得到解决.FPS如何影响我的碰撞检测?
答案 0 :(得分:1)
球体有多大,移动速度有多快?一个球体可以在一帧内“跳跃”在第二个球体上(即它的速度矢量是否比它的宽度长?)。
沿着这些方向,如果你在这里删除上限会发生什么:
if (collisionTime >= 0.0f && collisionTime <= 1.0f / GAME_FPS)
{
return collisionTime;
}
如果球体移动得太快,也许你的算法会检测到超过一帧之前发生的碰撞..(?)
答案 1 :(得分:1)
delta = ( P[0] . V[0] )^2 - V[0]^2 * (P[0]^2 - R^2)
不应该是delta = b 2 - 4 ac?
[编辑] 哦,我明白了,你考虑了4分。在这种情况下,你确定你正在考虑两个解决方案吗?
t = ( -( P[0] . V[0] ) - sqrt(delta) ) / V[0]^2
和
t = ( -( P[0] . V[0] ) + sqrt(delta) ) / V[0]^2