在3D游戏中“射击”目标的算法

时间:2012-09-10 15:57:44

标签: math graphics 3d game-engine

对于那些记得Descent Freespace的人来说,它有一个很好的功能,可以帮助你在射击非导弹或激光时瞄准敌人:它在船前显示了一个十字准线,你追逐告诉你在哪里射击,以便击中了移动目标。

我尝试使用来自AI algorithm to "shoot" at a target in a 2d game的答案,但它是针对2D的,所以我尝试调整它。

我首先分解计算以求解XoZ平面的交点并保存x和z坐标,然后求解XoY平面的交点并将y坐标添加到最终的xyz,然后我转换为剪辑空间并放置那些坐标处的纹理。但当然它不能正常工作,否则我就不会发布这个问题了。

从我注意到在XoZ平面中找到x后,在XoY中,x不一样,所以一定是错的。

    float a = ENG_Math.sqr(targetVelocity.x) + ENG_Math.sqr(targetVelocity.y) -
            ENG_Math.sqr(projectileSpeed);
    float b = 2.0f * (targetVelocity.x * targetPos.x + 
            targetVelocity.y * targetPos.y);
    float c = ENG_Math.sqr(targetPos.x) + ENG_Math.sqr(targetPos.y);
    ENG_Math.solveQuadraticEquation(a, b, c, collisionTime);

第一次,targetVelocity.y实际上是targetVelocity.z(对于targetPos是相同的),第二次是它实际上是targetVelocity.y。

XoZ之后的最终位置

    crossPosition.set(minTime * finalEntityVelocity.x + finalTargetPos4D.x, 0.0f, 
                minTime * finalEntityVelocity.z + finalTargetPos4D.z);

和XoY之后

    crossPosition.y = minTime * finalEntityVelocity.y + finalTargetPos4D.y;

我的方法是分成两个平面并计算任何好处吗?或者对于3D,有一种完全不同的方法?

  • sqr()是square而不是sqrt - 避免混淆。

2 个答案:

答案 0 :(得分:1)

如果你(0,0,0)t_0 = 0并以速度pv射击,并击中一个具有初始位置tp=(tpx,tpy,tpz)和恒定速度{{1}的目标在时间t,这意味着

tv=(tvx,tvy,tvz)

解决t的这个等式(tp * tv是tp和tv等的标量积):

Abs(tp+t*tv) == t*pv

所以你需要在t = - (tp*tv ± sqrt((tp*tv)^2+(tp * tp)*(pv^2-tv*tv))) / (tv*tv-pv*pv) 的位置进行射击。只需将其投影到视口中并在那里绘制十字准线。

希望这有帮助。

答案 1 :(得分:0)

3D情况的等式与I gave in the 2D case相同。唯一的区别是射击解决方案不是角度形式:你需要3D旋转。但是对于这个应用程序,你不需要一个触发解决方案,你只需要知道在哪里绘制标线。

例如,采用最简单的情况(可以立即旋转的固定式射击游戏):

让目标位于A位置并以速度VA移动,并且射击者在位置B处静止并且可以以速度 s 发射子弹。让射手在时间0开火。子弹击中时间 t 使得| A - B + t VA | = t s 。这是 t 中的二次方程式,您应该能够解决(或确定没有解决方案)。确定 t 后,您现在可以在与子弹击中的世界位置对应的屏幕位置绘制您的标线(即A + t VA)。

其他情况类似,就像在2D中一样。