一、图书详情

《Lua游戏AI开发指南》,原作名: Learning Game AI Programming with Lua。

豆瓣:https://book.douban.com/subject/30268009/

出版社图书详情:https://www.ptpress.com.cn/shopping/buy?bookId=23e4c970-5ad8-4dfa-a850-8da889927e89

二、前言

本文为此书的学习笔记,笔记顺序不与书籍内容一一对应。大概是记录碰到的问题及衍生的学习资料,以作备忘。

各种第三方模块的编译和集成是一件很繁琐的事情,作者为了便于教学,预先组装了一个相对容易构建的“沙箱”,以使读者能够专注于游戏AI开发。但书籍出版于2014年,“沙箱”本身的构建也因为运行环境的变动而出现了各种编译错误。

本节记录一些环境搭建过程中碰到的构建错误,主要是书本第一章的内容。

三、运行环境

  1. Windows 10
  2. Visual Studio 2019

四、生成 Visual Studio 解决方案

(一)随书代码获取

从“出版社图书详情”链接可下载随书代码资源,解压后目录结构如下:

├── bin
├── decoda
├── media
├── premake
├── src
├── tools
├── CHANGES.txt
├── LICENSE.txt
├── README.txt
├── vs2008.bat
├── vs2010.bat
├── vs2012.bat
└── vs2013.bat

(二)premake 替换

运行 vs20xx.bat 文件会调用的主要命令行如下,4个bat文件的区别只是 premake 的参数不同:

// vs2013.bat
...
// 调用 premake5 程序
// 使用 premake/premake.lua 作为构建配置清单,生成 vs2013 项目
tools\premake\premake5 --os=windows --file=premake/premake.lua vs2013 %ARGUMENTS%
...

要生成 vs2019 的解决方案,需要从 premake 官网 下载最新的 premake5,替换掉 tools\premake\premake5。

然后拷贝创建一份 vs2019.bat 文件:

// vs2019.bat
...
tools\premake\premake5 --os=windows --file=premake/premake.lua vs2019 %ARGUMENTS%
...

运行 vs2019.bat,将在 build 目录下生成 Learning Game AI Programming.sln 及一系列项目文件。

五、各种编译错误解决

使用 vs2019 打开 Learning Game AI Programming.sln,可以从解决方案资源管理器看到整体的项目结构。

生成解决方案,提示各种编译错误:
[Lua游戏AI开发指南] 笔记零 - 框架搭建-LMLPHP

(一)编译器错误 C2220

C2220 - 警告被视为错误

右键属性 - 配置属性 - C/C++ - 常规 - "将警告视为错误"

[Lua游戏AI开发指南] 笔记零 - 框架搭建-LMLPHP

但教学解决方案中包含了十几个项目文件,不可能一个一个修改,所以要修改的是前面提到的构建配置清单:premake/premake.lua

注释掉 premake.lua 中的 “FatalWarnings”,运行 vs2019.bat 重新生成解决方案,编译错误数量从 321 -> 161。

(二)编译器错误 C2440

C2440 无法从"type1"转换为"type2"

Unicode 字符问题,同样在项目右键属性 - 配置属性 - 高级 - "字符集",可进行修改,从 Unicode 改为 多字节字符集

对应到 premake.lua 中,添加 characterset 配置:

...
solution( "Learning Game AI Programming" )
	location( "../build/" )
	configurations( { "Debug", "Release" } )
	platforms( { "x32", "x64" } )
	characterset ("MBCS")
-- configuration shared between all projects
	language( "C++" )
	includedirs( { "../src/%{prj.name}/include/" } )
    warnings( "Extra" )
	flags( {
--		"FatalWarnings",
...

运行 vs2019.bat,重新生成解决方案

(三)Cannot open include file "d3dx9.h"

Windows 10 不包含D3D9相关的工具库,最新的 D3D12 则似乎是与 Windows Kit一起安装在 Program Files (x86)\Windows Kits\10\。

参考:https://stackoverflow.com/questions/63287230/how-to-find-directx-loctation-for-d3dx9-h-error

https://www.microsoft.com/en-us/download/details.aspx?id=6812 下载安装 DirectX SDK,通常会安装在 Program Files (x86)\Microsoft DirectX SDK (June 2010),安装程序会自动设置 $(DXSDK_DIR) 环境变量

(四)#error: Macro definition of snprintf conflicts with Standard Library function declaration

#error 是自抛出的错误,按照错误提示,大意是重复定义了 snprintf 宏,因为在 VS2015 以上版本已经对 snprintf 提供了官方支持。

所以全文搜索 define snprintf _snprintf 进行注释,大约有4处。

(五)LNK2019: 无法解析的外部符号 __vsnprintf

修改完错误(四)后大概会报这个错误,大意是找不到 __vsnprintf 这个函数,因为我们刚把宏定义注释了,而这些静态库又找不到官方支持的内联函数(?),所以我们需要引用依赖 legacy_stdio_definitions.lib 这个库

具体说明可参考:

  1. https://www.cnblogs.com/cnxkey/articles/8319812.html
  2. https://stackoverflow.com/questions/31053670/unresolved-external-symbol-vsnprintf-in-dxerr-lib

如果你是使用 Visual Studio Installer 安装的 VS2019,那么这个库的位置是在“Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\lib\”,这是每个项目会自动搜索的路径,所以不需要填写依赖的绝对路径,只需添加库名字即可。

在项目右键属性 - 配置属性 - 链接器 - 输入 - "附加依赖项" 中添加 “legacy_stdio_definitions.lib”。

可以看到附加依赖项中已经有许多被依赖的库了,你可能会意识到这些是在 premake.lua 中配置的,新增一行即可:

	configuration( { "windows" } )
	buildoptions( { "/I \"$(DXSDK_DIR)/Include/\"" } )
    links( {
        "d3d9",
        "dinput8",
        "dxguid",
        "d3dx9",
        "DxErr",
-- 新增 legacy_stdio_definitions 依赖
        "legacy_stdio_definitions.lib"
    } )

运行 vs2019.bat,重新生成解决方案

(六)LNK2019: 无法解析的外部符号 _WinMain

原因参考:https://www.cnblogs.com/imzhstar/p/4110870.html

_WinMain 是 Windows 程序的入口函数,而教学代码里的只有 main(),说明其实是个控制台程序。

检查项目右键属性 - 配置属性 - 链接器 - 系统 - "子系统",从 "/SUBSYSTEM:WINDOWS" 改成 "SUBSYSTEM:CONSOLE"

修改 premake.lua 的 kind 配置,从 kind( "WindowedApp" ) 改为 kind( "ConsoleApp" )

运行 vs2019.bat,重新生成解决方案

(七)其他

期间有少量函数参数数量不相符的问题,直接简单粗暴地传0或者去掉某个参数进行修复,总之先跑起来再说。

六、运行项目

编译无报错后,设置 chapter_1_introduction 为启动项目,菜单选择调试 - 执行。

[Lua游戏AI开发指南] 笔记零 - 框架搭建-LMLPHP

运行成功!

七、后记

说来惭愧,单这些构建错误就花了整一天才处理完毕,对目前阶段的自己来说确实琐碎难解,曾一度望着错误列表想放弃本书。甚至在撰写本文的过程中一度忘记昨日是如何处理的某个错误。

好在最终也算运行成功,赶忙记录,以作备忘。

后续学习中也许会尝试做的事情:

  1. 将教学项目的 Lua5.1 替换为 Lua5.4
  2. 使用 Vscode 替代 Decoda 调试 Lua 代码
  3. 替换 ogre,ogred3d9 为最新的 dx12 版本
  4. 替换 opensteer,Recast 等第三方库为最新版本
03-29 19:31