小时候玩过叫“打蜜蜂”的游戏。当然只是我们一厢情愿的称呼,游戏的名字叫“Galaga”。游戏的目的就是操作一架只能左右移动的战机,消灭成群的“小蜜蜂”,并且还有躲避不停非向战机的子弹和“蜜蜂”。我最喜欢里面的“嗡嗡”声。不过能及时躲过“跟踪弹”的追击才是我引以为豪的事情。可以想象如果游戏中的敌人不能跟踪我的位置,游戏将变得多么乏味。 追逐 追逐有很多种方式,这里仅讨论自然环境中的视线追逐,即追击者在看到猎物所在方位进行跟踪。这种方式很符合真实情况。 假设场景中有一个追击者A和猎物B,某时刻,追击者以速度向量u运动,猎物以速度向量v运动,B为追击者速度向量的末端点。 从追击者A的角度来看,猎物C在向量AB的左侧,向量AB与向量AC夹角为θ,追击者A只需要将自己的速度向量u逆时针旋转角度θ,即可将自身面对猎物C并向其靠近。如果C在向量AB的右侧,则需要将u顺时针旋转一定角度。由此,面临的问题就是判断猎物是在追击者速度向量左侧还是右侧。 上面的问题可以简化为判断平面上向量某一点在已知向量左侧还是右侧。当然这个问题已经有一个很好的解法。定义平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3)的面积量为: 当P1,P2,P3逆时针时S为正的,当P1,P2,P3顺时针时S为负。 对于上图三点A,B,C,可以判断C与向量AB的位置关系: 如果S(A,B,C)为正数,则C在矢量AB的左侧; 如果S(A,B,C)为负数,则C在矢量AB的右侧; 如果S(A,B,C)为0,则C在直线AB上。 class PursueSimulator:Simulator { private PointF preyPos = new PointF(BGC.WindowSize.Width, BGC.WindowSize.Height/5);//猎物位置 private PointF predatorPos = new PointF(0, 10);//追击者位置 private PointF purposePos = PointF.Empty;//目的点 private Vector3 u = new Vector3(0.7, 0.7,0);//追击者速度向量 private Vector3 v = new Vector3(-1, 0.6,0);//猎物速度向量 private Vector3 vectorAC = new Vector3();//猎物C与追击者A方位向量 private Vector3 [...]