游戏中的人工智能系统

可以结合此文共同观看
人工智能-基于位置的触发器管理

之前的一个月的某一段时间,私在为公司一款游戏的免费体验版本编写本地人工智能系统。 准确的说,是RPG即时战斗部分的人工智能。

先来确定智能战斗系统的中的AI思考类型

友好型 – 无法被攻击,也无法攻击别人
中立型 – 不主动攻击,被攻击后开始反击
进攻型 – 同阵营之外,范围内主动攻击

之后确定AI状态机中的几个状态

RESET – 脱离战斗,复位,刷新时用到的状态
RUN – 跑动状态
ATTACK – 攻击状态
SEARCH – 索敌状态
STAND – 发呆状态
WANDER – 漫游状态

以 进攻型 AI为例,各状态的衔接如下
默认 WANDER 每N毫秒间隔 切换至 SEARCH , 如果索敌成功 切换至 RUN, 索敌失败 切换回 WANDER。
当进入 RUN 时 每N毫秒间隔 判断目标是是否进入攻击范围 , 如果是,切换至 ATTACK, 如果否 保持 RUN。
当进入 RUN 时 每N毫秒间隔 判断目标是否脱离索敌区域, 如果是,切换至 RESET, 如果否 保持 RUN。
当进入 ATTACK时 每N毫秒间隔 判断目标是否在攻击范围 , 如果是, 攻击, 如果否,切换回 RUN。
当进入 ATTACK时 每N毫秒间隔 判断目标是否死亡, 如果是, 切换至 RESET, 如果否, 保持 ATTACK。
当进入 RESET 时 AI 重置(移动)到出生点,刷新状态后,切换至 WANDER

当上述状态转换过程中,将会出现一种临界状态,即目标刚好在索敌区域边缘,而目标同时在移动, 会导致AI反复进入ATTACK后,由于目标反复脱离 攻击范围,导致 AI 反复追击停顿,无法成功攻击。

解决方案可以为, 当进入 ATTACK 时,已知是 RUN 状态切换过来的,因此此时目标肯定在攻击范围内, 所以进入状态后先进行一次攻击后,再做范围判断。

下面是 攻击型 AI的实现伪代码

[挖个坑,每日填]

3D引擎中的面性能优化

在3D引擎中,影响到性能的主要是材质和面,大量的高分辨率的高色彩的材质十分占用内存,而大量的面会影响CPU的计算速度。
这一次只讨论如何来削减面数。

看到很多朋友削减面数的方式都是从模型身上下手,削减多余的面,看不见的面。那么即使如此,如果这个模型需要旋转,那么模型的背后的面肯定不能剔除。
那么,这时候就可以考虑从3D引擎的底层渲染机制下手了。

才3D引擎中,摄像机捕捉的画面实际上是由一个 近截面 和 一个 远截面 构成的一个多边形,所有近于近截面的物体不渲染,所有远与远截面的物体不渲染。 因此,从此部开始就可以把视野外的物体全部移除, 但这还不够。

我们为什么不能把,即使在视野内,但是此刻看不到的面也移除呢?

摄像机的本质就是向量,而 向量 * 顶点 有这么一个性质:
1。 当向量 U 和 顶点 V 的夹角为 90°时, 他们的乘积为0
2。 当向量 U 和 顶点 V 的夹角大于 90°时,乘积<0 3。 当向量 U 和 顶点 V 的夹角小于 90°时,乘积>0

那么对于一个立方体(8个顶点) 可以做如下判断,来知道哪个顶点是可视的

var viewList : Vector.<Point3D> = new Vector.<Point3D>();
for each(var v : Point3D in Cube)
{
    if(v * u > 0) viewList.push(v);
}

当取得所有可见顶点后,就可以把他们关联的面推入待渲染列表了。

而对于一个处于临界区域的多边形来说,上面的方式是不够的。 那么可以以该多边形的中心点为圆心,最远顶点长度为半径构建一个球体。然后判断该球体是否与 近截面 和 远截面 构成的多边形相交,如果不相交,则整个多边形完全不渲染。
对于相交区域再次采用上面的向量算法来判断。