计算游戏中NPC的朝向

时间:2021-04-26 14:56:22

今天有个任务,是使得NPC随着玩家转动,主要就是计算NPC的朝向问题。

在Ogre空间内(Y垂直向上,下面是XOZ平面),假设NPC在点P1(x1,z1),玩家在点P2(x2,z2);那么如果NPC面向玩家该怎么办呢?其实就是求NPC绕着Y轴逆时针旋转的成角(Yaw)问题,NPC初始方向是面向屏幕(即Z正半轴)。

 

解:

设P1与P2之间的连线为L(方向是P1指向P2,即NPC面朝向玩家);

假设L与Z正半轴的成角为θ, P1与P2之间的距离为dist。下面分情况讨论:

(1) 当 θ∈[0, PI/2) 时,

cosθ = (z2-z1)/dist

    ===>>> arccos((z2-z1)/dist) = θ ∈ [0, PI/2)  //ok,因为反余弦函数值域是[0,PI]

(2) 当 θ∈[PI/2, PI) 时,

这里δ是L与X正半轴的夹角(锐角)

cosθ = cos(PI/2 + δ) = - sinδ = - (z1-z2)/dist = (z2-z1)/dist

  ===>>> arccos((z2-z1)/dist) = θ ∈ [PI/2, PI)

(3) 当 θ∈[PI, 3/2*PI) 时,

这里δ是L与Z负半轴的夹角(锐角)

cosθ = cos(PI + δ) = - cosδ = - (z1-z2)/dist = (z2-z1)/dist

又因为:cos(2*PI-θ) = cos(-θ) = cosθ = (z2-z1)/dist

 ===>>> arccos((z2-z1)/dist) = 2*PI-θ ∈ (PI/2, PI]

(4) 当 θ∈[3/2*PI, 2*PI) 时,

这里δ是L与Z正半轴的夹角(锐角)

cosθ = cos(2*PI - δ) = cosδ = (z2-z1)/dist

又因为:cos(2*PI-θ) = cos(-θ) = cosθ = (z2-z1)/dist

===>>> arccos((z2-z1)/dist) = 2*PI-θ ∈ (0, PI/2]

 

上面中(1)和(2)类似,都满足x2 >= x1; (3)和(4)类似,都满足 x2 < x1.

****************************************************************

 

从程序计算角度,就可以这样做了:

设 arccos((z2-z1)/dist) = value;

if x2 >= x1

    value 就等于θ,即 θ = value;

else

    value 就等于2*PI-θ,即 θ = 2*PI - value;

 

求出θ 后,就可以调用CObject::SetRotate(θ)来设置NPC的朝向啦。

 

 也即:

if x2 >= x1

    CObject::SetRotate(value);

else

    CObject::SetRotate(2*PI - value) =  CObject::SetRotate( - value); //因为是旋转角度,所以可以加减任意个2*PI。