翻译/彭硕,姜沂,reason_W
编校/reason_W

DeepMind开源《星际2》AI平台,OpenAI人工智能系统打败Dota2游戏玩家......越来越多的科技巨头开始进入到游戏AI的领域,并相继开放了他们的接口和数据集。复杂的训练数据,即时多变的对战环境,对多智能体协作能力的要求等等使得《星际争霸》这样的游戏被称为通用智能的关键,预示着AI将在越来越真实的混乱环境里向人类的心智靠近。

那么小白玩家该如何入坑游戏AI呢?游戏AI到底是如何和游戏进行接互,判断角色状态,执行动作,规划策略的呢?

本期推送精选了国外一位博主游戏AI系列的文章,教你手把手开始搭建一个游戏AI。
 



基于深入学习和其他机器学习技术,我们将为“之路”(以下简称PoE)打造一个游戏AI。本篇教程总共分为5个阶段,下面是原贴列表。

第一部分:概述
第二部分:为《流放之路》标定投影矩阵
第三部分:移动和导航
第四部分:实时屏幕捕捉及底层命令
第五部分:基于TensorFlow的CNN实时障碍物和敌对目标检测

(由于我们把五部分整合成了一篇文章,因此本文共分5部分,20小节,8300+字,阅读花费约17分钟。)

我们这个项目的目标是打造一个基于视觉输入的游戏AI,它可以成功地在游戏地图中进行自主巡航和自主防御。当然,你也可以在这个过程中一边玩游戏,一边学习打造游戏AI的乐趣。

 

 



第一部分:概述

本部分共2节,原post链接

A Deep Learning Based AI for Path of Exile: A Series

https://nicholastsmith.wordpress ... -of-exile-a-series/

PoE是一款和暗黑破坏神、泰坦之旅等的暗黑型RPG类似的动作类游戏,游戏截图如下图1所示:

101656nxxy0dydizdyt28w.png人工智能逻辑的流程图
AI程序的主循环会不停滴从游戏中获取一个静态的图像,并将它传递给一个CNN。CNN会预测这幅静态的图像中正在发生什么。这些预测随后被传递给世界内部地图,并根据最新的预测更新世界内部地图。接下来,游戏AI会根据当前世界内部地图的状态,进行一系列的动作。最后,这些动作被转换成鼠标和键盘输入,然后发送给鼠标和键盘。这个循环是在不停重复的。是不是听起来很容易?没错。

我们选择Python(3.6)作为这次的编程语言。主要使用的库是

scikit-learn
TensorFlow
PyUserInput
win32gui
scikit-image

接下来几部分,我们将研究如何进一步分解上述任务并一步步实现它们。

2.免责声明

PoE的logo、美工均属于游戏开放商Grinding Gear Games(GGG)的财产,作者与GGG没有任何关系,作者的思想和观点并不代表GGG的观点。本文的目的是探索人工智能和深度学习,没有侵犯版权或服务条款的行为。

 

 



第二部分:为《流放之路》标定投影矩阵

本部分共5节,原post链接:

Calibrating a Projection Matrix for Path of Exile

https://nicholastsmith.wordpress ... -for-path-of-exile/

在这一部分中,我们将探索如何利用游戏静态画面,更新其世界的内部表征。

1.视觉输入的挑战

让游戏AI与视觉输入进行交互的一个难点在于图像数据是2D的,但是(游戏)世界是3D的。所以最可能的是,游戏引擎在3D环境中使用它自己的世界内部表征,然后使用投影技术将游戏渲染为2D并显示在屏幕上。通过逆向工程,从游戏世界的表征中获得数据非常有用,但是因为我们的最终目的是要打造游戏AI,所以暂时不对这个逆向工程进行深入的探索。

为了更精确地模拟世界,游戏的投影矩阵要和世界尽可能地相似。这个矩阵被用来确定与屏幕上的2D坐标相对应的3D坐标,(再进行一些假设)反之亦然。图3说明了投影映射的基本概念。左矩形表示屏幕,而右坐标轴代表世界坐标。灰线(投影映射)将蓝点从世界坐标映射到屏幕上的位置。

101658fovz1msg3s1r1ooz.png表1:数据映射
接下来,我们构建一个转换矩阵A,将3D点投射到2D的点上。

3.执行拟合

我们通过TensorFlow构建一个非线性拟合,注意:将标定问题看成一个齐次最小二乘问题的方法是比较常见的;Adam 方法看起来可以为这个特殊的图像提供更好的结果。

101659zmpknmztivl8tmxx.png
方程式2:得到的投影矩阵

用等式3给的公式,可以在世界坐标中恢复出相机上的位置C。注意,Q是一个3x3矩阵,m是一个3x1矩阵。

方程式3:相机位置的恢复

下面的代码对投影矩阵进行拟合,恢复出来的相机位置用变量CP表示。

101659v8z9ug3uwhu4gcq7.png
4.结果

恢复出来的的相机位置是 (5.322,-4.899,10.526)。现在再回头看看一开始的截图,这个值和我们直觉上感受的方向是一致的。世界空间坐标分别以一个箱子的高度、宽度和深度作为单位长度。因此,相机位置大概是在x轴正方向上5个箱子长度,y轴负方向4个箱子长度,z轴正方向上10个箱子长度处。 利用这个投影矩阵,我们就可以把点投影到原始图像上了。下图展示了怎样把一个xy平面表示的网格点投影到原始图像上。

101700sp66b6rs6y65b626.png
5.假设和平移

如果假定角色仅在xy平面上移动,那么角色的3D位置就可以通过角色的像素坐标恢复。我们假设z=0,然后在投影方程中解出x和y,就可以给出这个角色的像素坐标。完成此任务的代码如下。

102415bhe26mg2qyhwh3h7.png
在上述两个函数中,投影矩阵的转置计算是影响效率的主要因素。有了以上两个函数之后,我们就可以用下面的代码计算在800*600屏幕上xy平面的网格点。下面这个函数将是后面跟踪玩家在一级平面上位置的关键。

101701kbbbrz8yzb1jb9ob.png
在PoE中,当玩家移动时,相机也会移动(相机角度固定)。为了跟踪移动的相机和玩家,世界点在被投影之前会被转平移回原始位置。在实际中,这是通过将投影矩阵乘以一个平移矩阵得到最终的投影矩阵来实现的。方程4中显示了一个平移矩阵,它可以用向量(x,y,z)来表示一组点的平移。

101701hjjoa5355oa5brj5.png
方程式4:一个平移矩阵

我们可以利用matplotlib(https://matplotlib.org/)来构造一个XY平面的动画,它模拟了世界中角色的运动。在下面的动画中,相机通过几个随机产生的点进行线性移动。

101703gnqnyqlnzcmlzk7q.png表2:内部地图
地图会记录已访问的位置及其类型。这个类型标记的是,玩家能否移动到该位置。位置类型分别为“开放”类型或“障碍”类型。有了这样的地图,就可以使用广度优先遍历找到从一个位置到另一个位置的最短路径。

2.维度之间的映射

现在,我们假设玩家在位置(0,0,0),并且要移动到(1,1,0)。应该怎么用鼠标在屏幕上进行操作呢?想一下前几部分的内容,一个标定好的投影矩阵,能让我们在3D坐标中更准确地逼近玩家的位置。因此,利用投影矩阵来变换该点(1,1,0)就可以确定其在屏幕上的位置。这就是鼠标要点击的位置。

在实际中,我发现,在玩家为角色指定移动的目标点时,位移技能其实很不准确。特别是当我们在障碍物上单击时。在这种情况下,角色通常会移动到单击位置的附近。下面这幅图就是一个这样的例子。

101706m2or27u15olzh7d2.pngAI逻辑流程图
1.可用的库

有很多Python库都可以用来捕捉游戏截图,比如 pyscreenshot(https://pypi.python.org/pypi/pyscreenshot)和 ImageGrab from PIL(http://pillow.readthedocs.io/en/3.1.x/reference/ImageGrab.html)。这里有一个简单的程序可以来测试图像捕捉的效果。代码如下:

101708fkktldltcppdzg1l.png
101708vjujarj04oreert4.png
不幸的是,测试的效果看起来实在差强人意。要是没有其他处理的话,顶多只能盼着这程序每秒处理5到6帧的画面。此外,在上面的代码中,屏幕捕捉要在主线程上运行。所以整个程序要等待获取到图像,在此期间不会和游戏发生处理或交互。另一个问题是,捕捉到的应该只有游戏画面(在窗口模式下),而不应该包括电脑桌面上其余的部分。

2.使用Windows API

我们可以通过调用几个Windows API来减轻这些问题,并提高程序性能。

101709khep9s55g50g0h5h.png
4.结果

为了对新的代码进行计时,应该在ScreenUpdateT函数中进行测量。这里有一个快速但不考虑后果的方法,最终计时程序如下:

101710bfj3mm93311611vp.png
101710d4di9re4qybwvze8.png
时间变快了一个数量级。 现在,AI处理速度的理论最大值大约为64 FPS。 主AI程序使用与以下代码相似的ScreenViewer类型的数据成员访问画面图像。

101711x1r1rqjx0crxtcrz.png
本系列的最后一部分将介绍如何使用卷积神经网络(CNN)来处理画面的图像以更新AI的状态。(小编注:终于快完了...)

 

 



第五部分:基于TensorFlow的CNN实时障碍物和敌对目标检测

本节是文章的第五小节:AI Plays Path of Exile Part 5: Real-Time Obstacle and Enemy Detection using CNNs in TensorFlow

原post链接

https://nicholastsmith.wordpress ... -cnns-in-tensorflow

正如我们在本系列第一部分中说的那样,AI程序会获取游戏的屏幕截图,并使用它来进行预测,以更新其内部状态。这部分中,我们将讨论从游戏画面获取视觉输入,并对信息进行分类和识别的方法。我已经把源码放到了我的github(https://github.com/nicholastoddsmith/poeai)上,开心O(∩_∩)O~~

1.分类系统架构图

101711gazj4sbqajemjs1a.pngAL逻辑流程图
回忆一下第三部分的文章,移动地图维持了一个从3D点到标签的字典。例如,在给定时间内,机器人在内部地图上可能具有表3所示的数据。

世界点坐标 投影点

101712l3gnnsg2u3itbus3.png表3:内部地图
回忆一下第二部分的内容,投影地图类允许画面上的任何像素映射到3D坐标(假设玩家总是在xy平面上,然后该3D坐标会被量化为某个任意精度,让AI的世界地图变成均匀间隔网格的点)。

因此,我们需要的是能够识别屏幕上的给定像素到底是障碍物的一部分、敌人还是物品等的方法。这个任务本质上是目标检测。而实时目标检测其实是一个困难且计算复杂度很高的问题。 这里我们会介绍一种简化的方案,可以在性能和精度之间实现很好的平衡。

为了简化目标检测任务,游戏画面被划分成相等大小的矩形区域。对于800×600分辨率的画面,我们选择由m = 7行和n = 9列组成的网格。从画面的底部,左侧和右侧边缘分别移除十二个,四个和四个像素,使得所得到的尺寸(792和588)能够分别被9和7整除。因此,屏幕网格中的每个矩形的宽度和高度分别为88和84像素。图2展示出了使用上述方案分割的游戏画面图像。

101712x4zc6n2tb466hux6.png图像单元格标签
识别物品和敌人的任务第二次使用了CNN。给定画面上的单元格,CNN将单元格分类为包含敌人,物品还是什么也不包含。

为了只瞄准活着的敌人,判断是否发生移动的二进制分类器第三次使用了CNN。 给定画面上的单元格,第三个CNN确定单元格中是否发生移动。只有包含移动的单元格才能传入第二个CNN。这个CNN然后预测这些单元格是否包含物品或敌人。通过在连续画面截图中切换物品的突出显示来检测物品标签的移动。

用于移动检测的图像数据是通过快速连续地捕获画面的2帧图像并且仅保留图像中显著不同的区域得到的。这是使用numpy.where函数实现的(16是任意选择的阈值)。

101713kz8p1glopwjfeo2o.png
总而言之,从游戏画面中捕获的截图将输入到3个CNN中的每一个之中。第一个CNN检测画面单元格中的障碍物。然后在运动图中相应地标记画面上每个单元格内的3D网格点。内部地图保留每个单元格的预测结果,并在查询单元格时报告预测最频繁的类别。第二和第三个CNN需要联合使用以检测敌人和物品。

2.数据集

使用ScreenViewer类获取的画面截图,来手动构建训练数据集。目前,该数据集仅包含游戏行为4中的“Dried Lake”级数据。数据集由11个文件夹中的14,000多个文件组成,大小为164MB。 数据集的截图如图4所示。

101715dzo4zsx4wwslxm1p.pngCNN架构
match

整个数据集大约20到30次epochs交叉验证的准确率在从中升高到90%之间。 通过从训练数据中随机抽取大小为32的batch来执行epochs,直到绘制出适当数量的样本。 NVIDIA GTX 970的培训大概需要5到10分钟。训练在NVIDIA GTX 970上大概花费5到10分钟。

4.使用并行以获得更好的表现

为了提高AI的性能,CNN检测要并行执行。这个程序允许加速,因为numpy和TensorFlow代码避免了普通Python代码的全局解释器锁定问题。针对敌方分类线程的启动代码如下。

101716bedxike4xxjxm05o.png 线程逻辑组织
因此,并行执行分类,并且使用互斥锁以线程安全的方式将包含预测的数据成员提供给主线程。图6说明了线程和互斥锁的逻辑组织。在图中,ecp和pct分别是包含敌方单元格位置和预测单元格类型的Bot类的数据成员。

5.结果

下面这个6分钟多的视频对该项目进行了总结,并且其中有长达四分钟的时间展示了AI如何玩流放之路(PoE)。

none.gifPoE AI素材

 



视频地址(需翻墙):https://youtu.be/UrrZOswJaow

更多最新游戏AI的视频可以到作者的Youtube主页观看。

作者介绍:Nicholas T Smith,从事AI和机器学习软件开发,加利福尼亚州立大学计算机硕士毕业生。

原文链接Github地址

via:AI科技大本营(微信ID:rgznai100)



锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛