编辑推荐
游戏AI可以很容易地拆分成决策制定、动画处理和战术等各种组件,但各个系统间的平衡和交互决定了良好的AI和糟糕的AI之间的区别。
本书首先介绍AI沙箱,然后依次介绍、实现和扩展了游戏AI的各个新领域。更进一步,读者还将学习使用一些开源库,如Ogre3D、Bullet物理引擎、OpenSteer、Recast、Detour以及Lua,并利用一个可以扩展和运行的完整代码库来创建AI沙箱。
本书采用一种循序渐进的方法,从学习移动一个简单物体开始,到实现一个带有完整动画的战士。学习完本书,你的AI将能够导航、寻路、管理动画回放、彼此交流并能感知它所处的环境。
如果你是游戏开发者,或者是一位想专注于实现自己的游戏AI系统和技术,而又不想创建游戏引擎的底层接口的普通程序员,这本书正是为你量身打造的。C++语言知识对于调试整个AI沙箱和扩展本书提供的功能十分有用,但并非必需的。
读完本书,你将能够:
■ 创建动画状态机以便在Lua代码中驱动AI动画;
■ 构建导航网格并在其中寻路;
■ 使用全功能的Lua IDE编写和调试Lua脚本;
■ 使用行为树、状态机和决策树开发决策逻辑,构建模块化、可重用的AI;
■ 使用黑板数据结构管理短期和长期的知识表示;
■ 添加感官知觉让AI能看能听;
■ 基于影响力地图开发多个AI的高级战术。
内容简介
游戏人工智能(游戏AI)是游戏开发的一个重要方面,在很大程度上决定了游戏产品的逼真程度和对玩家的吸引力,由此也得到游戏开发工程师越来越多的重视。
本书秉承把动画和运动系统直接集成到AI系统的方法,详细介绍了如何使用Lua语言及相关的技术和工具,编写和实现高质量的游戏AI。全书共9章,分别介绍了沙箱基础、创建和移动智能体、角色动画、意识控制、导航、决策制定、知识表达、感知和策略等主题。
本书适合于游戏开发工程师,特别是想要详细了解游戏AI开发的程序员阅读参考。
作者简介
游戏开发人员、编程爱好者游戏开发人员、编程爱好者游戏开发人员、编程爱好者游戏开发人员、编程爱好者游戏开发人员、编程爱好者游戏开发人员、编程爱好者
目录
- 第1章 从构建沙箱开始 1
- 1 AI沙箱简介 1
- 1.1 理解沙箱 2
- 1.2 项目文件组织 2
- 1.3 预先做好的构建 4
- 1.4 使用Visual Studio 2008/2010/2012/2013编译沙箱项目 5
- 1.5 开源库 5
- 1.6 开源工具 6
- 1.7 Lua IDE-Decoda 6
- 1.8 在Decoda中运行AI沙箱 6
- 1.9 创建一个新的Decoda项目 7
- 1.10 调试Lua脚本 8
- 1.11 Decoda的Watch窗口 9
- 1.12 Decoda的Call Stack窗口 9
- 1.13 Decoda的Virtual Machines窗口 9
- 1.14 同时调试Lua与C++代码 10
- 1.15 Visual Studio-附加到进程 10
- 1.16 Decoda-附加到进程 11
- 1.17 Decoda-附加到系统调试器 11
- 1.18 关联Lua脚本代码到Decoda 12
- 1.19 Lua虚拟机 12
- 1.20 Lua堆栈 13
- 1.21 Lua基础类型 13
- 1.22 元表 14
- 1.23 元方法 14
- 1.24 自定义类型 15
- 1.25 C/C++调用Lua函数 15
- 1.26 Lua调用C/C++函数 16
- 1.27 创建自定义数据类型 18
- 1.28 Demo框架 20
- 2 小结 24
- 第2章 创建并移动智能体 25
- 1 新建一个沙箱项目 25
- 2 创建文件结构 26
- 3 扩展SandboxApplication类 26
- 4 首次运行你的沙箱 28
- 5 新建一个Decoda项目 29
- 6 配置Decoda运行的可执行程序 29
- 7 创建一个沙箱Lua脚本 30
- 7.1 创建地板 31
- 7.2 添加光源 31
- 7.3 添加天空盒 32
- 7.4 在沙箱中添加网格 33
- 7.5 创建沙箱对象 34
- 8 发射方块 35
- 9 创建智能体Lua脚本 37
- 9.1 创建视觉表象 38
- 9.2 更新智能体的位置 39
- 9.3 更新智能体的朝向 39
- 10 智能体的属性 40
- 10.1 朝向 40
- 10.2 定位 40
- 10.3 大小 41
- 10.4 物理 41
- 10.5 知识 42
- 10.6 智能体的移动 43
- 10.7 智能体转向力 44
- 10.8 规避 56
- 10.9 规避障碍物和其他智能体 57
- 10.10 群组移动 59
- 10.11 创建一群追随者 59
- 10.12 转向力合计 63
- 11 小结 64
- 第3章 角色动画 65
- 1 骨骼和网格 65
- 1.1 网格骨骼 66
- 1.2 加载一个动画网格 66
- 1.3 显示骨骼 66
- 2 附加网格到骨骼上 67
- 给战士附加武器 67
- 3 动画片段 69
- 3.1 播放战士动画 69
- 3.2 战士动画 70
- 4 战士的姿势 72
- 武器姿势 74
- 5 操作动画 75
- 5.1 启用和禁用动画 75
- 5.2 循环动画 75
- 5.3 动画的长度 76
- 5.4 动画时间 76
- 5.5 归一化时间 76
- 5.6 重新开始动画 76
- 5.7 播放非循环动画 77
- 5.8 动画速率 78
- 6 动画混合 78
- 6.1 动画权重 79
- 6.2 混合窗口 79
- 6.3 混合曲线 79
- 6.4 线性混合 79
- 6.5 处理混合权重 80
- 7 动画状态机(ASM) 83
- 7.1 状态 83
- 7.2 转换 84
- 7.3 创建动画状态机 84
- 7.4 创建辅助函数 85
- 7.5 添加状态 86
- 7.6 添加转换 86
- 7.7 添加外部辅助函数 87
- 7.8 强制设置状态 88
- 7.9 请求状态 89
- 7.10 更新动画状态机 89
- 7.11 处理状态转换和状态请求 89
- 7.12 更新运行中的动画 91
- 7.13 动画状态机实例 92
- 8 构造一个武器动画状态机 92
- 9 构建战士的动画状态机 95
- 10 更新动画状态机 97
- 11 处理状态 98
- 12 小结 100
- 第4章 意识体控制 101
- 1 创建身体 101
- 1.1 创建战士 102
- 1.2 附加动画网格到智能体 104
- 1.3 创建障碍训练场 105
- 2 为动画状态机添加回调 107
- 2.1 处理回调 108
- 2.2 为ASM添加回调 108
- 2.3 更新ASM以调用回调函数 109
- 3 让战士射击 111
- 3.1 骨骼位置 111
- 3.2 骨骼旋转 111
- 3.3 创建粒子效果 111
- 3.4 粒子方向 112
- 3.5 对象删除 112
- 3.6 碰撞效果回调 112
- 3.7 发生子弹 113
- 3.8 处理子弹碰撞效果 113
- 3.9 射击 114
- 4 让战士奔跑 116
- 4.1 设置穿越障碍训练场的路线 116
- 4.2 跑过障碍训练场 117
- 5 创建大脑 118
- 实现意识体控制的方法 118
- 6 直接动画控制 119
- 6.1 死亡状态 119
- 6.2 空闲状态 121
- 6.3 下落状态 122
- 6.4 移动状态 123
- 6.5 射击状态 124
- 7 一个简单的有限状态机 125
- 7.1 初始化智能体 126
- 7.2 智能体FSM状态处理 127
- 8 间接动画控制 128
- 8.1 动画控制器 129
- 8.2 命令 129
- 8.3 命令队列 130
- 8.4 操作命令 131
- 8.5 姿势改变命令 131
- 8.6 死亡命令 132
- 8.7 下落命令 133
- 8.8 空闲命令 134
- 8.9 移动命令 136
- 8.10 射击命令 137
- 8.11 赋值成员函数 139
- 8.12 初始化控制器 139
- 8.13 添加命令处理函数 140
- 8.14 更新控制器 141
- 9 运行障碍训练场 142
- 9.1 创建直接控制智能体 143
- 9.2 创建间接控制智能体 144
- 9.3 间接控制智能体初始化 145
- 9.4 间接控制智能体更新 145
- 9.5 间接控制智能体的控制 146
- 9.6 产生一个间接控制的智能体 146
- 10 动作延迟 147
- 11 小结 148
- 第5章 导航 149
- 1 寻路 149
- 2 创建导航网格 149
- 2.1 配置导航网格 150
- 2.2 可通行高度 151
- 2.3 可通行半径 152
- 2.4 可通行的攀爬高度 153
- 2.5 可通行的斜坡角度 154
- 2.6 最小区域面积 154
- 2.7 构建导航网格 156
- 2.8 绘制导航网格 156
- 3 在导航网格中寻路 157
- 3.1 路径查询 157
- 3.2 查询结果 157
- 3.3 随机导航路点 158
- 4 路径信息 158
- 5 为战士添加随机寻路 158
- 5.1 更新智能体的路径 159
- 5.2 绘制路径 160
- 5.3 初始化导航网格 160
- 5.4 随意移动的智能体 162
- 6 创建更多的导航网格 163
- 7 小结 163
- 第6章 决策制定 164
- 1 创建自定义类型 164
- 2 智能体动作 165
- 2.1 添加数据成员 166
- 2.2 动作初始化 167
- 2.3 动作更新 167
- 2.4 动作清理 168
- 2.5 动作的成员函数 168
- 3 创建动作 169
- 3.1 空闲动作 169
- 3.2 死亡动作 170
- 3.3 换弹药动作 171
- 3.4 射击动作 172
- 3.5 随机移动动作 174
- 3.6 移动动作 175
- 3.7 逃跑动作 178
- 3.8 追逐动作 181
- 4 求值器 184
- 5 创建求值器 184
- 5.1 常数求值器 185
- 5.2 是否拥有弹药求值器 185
- 5.3 是否有生命危险求值器 185
- 5.4 是否有敌人求值器 186
- 5.5 是否移动求值器 187
- 5.6 是否存活求值器 187
- 5.7 能否射击敌人求值器 188
- 5.8 50比50机会求值器 188
- 6 决策结构 189
- 7 决策树 189
- 7.1 分枝 190
- 7.2 决策叶节点 191
- 7.3 分枝求值 191
- 8 构造一棵决策树 192
- 创建分枝 193
- 9 创建一个决策树智能体 196
- 9.1 决策树的优点 198
- 9.2 决策树的缺点 198
- 10 有限状态机 198
- 10.1 状态 198
- 10.2 转换 199
- 10.3 有限状态机结构 199
- 10.4 辅助函数 200
- 10.5 添加状态和转换 201
- 10.6 更新有限状态机 202
- 10.7 添加实例函数 203
- 11 构造有限状态机 204
- 11.1 空闲状态 204
- 11.2 移动状态 205
- 11.3 随机移动状态 206
- 11.4 射击状态 207
- 11.5 逃跑状态 208
- 11.6 死亡状态 209
- 11.7 追逐状态 209
- 11.8 换子弹状态 210
- 12 创建一个有限状态机智能体 211
- 13 有限状态机的优点 212
- 14 有限状态机的缺点 212
- 15 行为树 212
- 15.1 行为树结点 213
- 15.2 辅助函数 213
- 15.3 更新行为树结点 214
- 16 动作 215
- 17 条件 215
- 18 选择器 216
- 19 序列 216
- 20 创建行为树对象 216
- 20.1 行为树辅助函数 217
- 20.2 选择器计算 217
- 20.3 序列计算 219
- 20.4 结点计算 221
- 20.5 继续行为树计算 221
- 20.6 行为树的更新循环 222
- 20.7 更新行为树 223
- 21 构造一颗行为树 224
- 21.1 死亡行为 225
- 21.2 逃跑行为 226
- 21.3 战斗行为 226
- 21.4 换子弹行为 227
- 21.5 射击行为 228
- 21.6 追逐行为 228
- 21.7 移动行为 229
- 21.8 随机移动行为 230
- 21.9 空闲行为 230
- 22 创建行为树智能体 231
- 23 行为树的优点 232
- 24 行为树的缺点 232
- 25 小结 232
- 第7章 知识表达 233
- 1 知识源 233
- 1.1 创建知识源 233
- 1.2 知识源求值 234
- 2 黑板 235
- 2.1 创建黑板 235
- 2.2 添加和删除知识源 235
- 2.3 知识源求值 236
- 2.4 设置和返回黑板属性 237
- 2.5 黑板的成员函数 237
- 3 创建战士的知识源 238
- 3.1 选择敌人 238
- 3.2 选择逃离位置 239
- 4 构造战士的黑板 240
- 5 更新决策求值器 242
- 6 更新行为动作 243
- 6.1 死亡动作 243
- 6.2 逃离动作 243
- 6.3 空闲动作 244
- 6.4 移动动作 245
- 6.5 追逐动作 246
- 6.6 换子弹动作 246
- 6.7 射击动作 247
- 7 小结 247
- 第8章 感知 248
- 1 事件 248
- 1.1 属性 248
- 1.2 发送事件 249
- 1.3 接收事件 249
- 2 管理事件 250
- 2.1 分配智能体团队 250
- 2.2 处理智能体通讯 251
- 2.3 事件类型 253
- 3 创建智能体的官能 253
- 3.1 初始化官能 253
- 3.2 更新官能 253
- 4 智能体可见性 254
- 检测其他可见智能体 255
- 5 智能体视觉事件 257
- 5.1 看到新敌人的事件 257
- 5.2 看到新的敌人死尸事件 257
- 5.3 看到新的死亡队友事件 258
- 6 处理新看到的智能体 259
- 6.1 间歇性可见的智能体 260
- 6.2 限制智能体可视性的更新 261
- 6.3 创建事件处理 261
- 6.4 添加事件处理函数 263
- 7 智能体的听觉 263
- 8 听觉事件 264
- 8.1 子弹发射事件 264
- 8.2 子弹碰撞事件 264
- 9 处理听觉事件 265
- 10 清理黑板中的事件 266
- 11 清理听觉事件 267
- 12 团队交流 268
- 12.1 选择敌人事件 268
- 12.2 位置更新事件 269
- 12.3 撤退位置事件 269
- 13 更新智能体行为 270
- 13.1 选择敌人 270
- 13.2 评估危险位置 272
- 13.3 计算最佳逃离位置 275
- 14 小结 276
- 第9章 策略 277
- 1 影响力地图 277
- 1.1 单元格高度 278
- 1.2 单元格宽度 279
- 2 构造影响力地图 281
- 2.1 配置 281
- 2.2 导航网格的立体像素化 282
- 3 绘制影响力地图 283
- 4 访问影响力 284
- 4.1 设置影响力 284
- 4.2 获取影响力 285
- 5 清除影响力 285
- 6 传播影响力 286
- 6.1 单元格惯性 287
- 6.2 单元格衰减 289
- 7 影响力地图的图层 290
- 8 更新影响力地图 292
- 9 战士的策略 293
- 初始化和更新策略 294
- 10 团队影响力评分 295
- 10.1 初始化团队影响力 295
- 10.2 更新团队影响力 296
- 10.3 配置团队影响力 297
- 11 危险区域评分 298
- 11.1 利用智能体事件 298
- 11.2 添加事件处理器 300
- 11.3 初始化危险影响力 300
- 11.4 更新危险影响力 301
- 11.5 配置团队影响力 302
- 12 小结 303
- 后记 305