【饥荒研究随笔】使用VSCode和LuaPanda调试饥荒代码

您所在的位置:网站首页 饥荒查看地图代码 【饥荒研究随笔】使用VSCode和LuaPanda调试饥荒代码

【饥荒研究随笔】使用VSCode和LuaPanda调试饥荒代码

2024-05-24 01:54| 来源: 网络整理| 查看: 265

虚假的目录,并不能跳转

0. 简要介绍

为什么要调试饥荒的代码?

为了开发独立游戏,想要研究一下饥荒的系统实现,例如动画、地图生成、以及Mod系统。饥荒的主要逻辑源代码都写在Lua脚本中,Klei Entertainment直接将其开放给了玩家,非常便于学习。在读代码的过程中,如果能够添加断点逐步调试的话,对我这样的小白来说会友好很多。

为什么要写这篇文档?

这其实并不算是一篇教程或者说文档,只是对自己学习过程的记录,作为备忘。中途也踩了一些坑,因此发出来分享给需要的人。如果后续离职之后有时间和精力,或是有人看的话,会考虑整理成详细的文档(虽然这么说,不知道2013年的老游戏还有没有人想研究的)。

什么人看了可能会有用?

首先你需要对Lua和调试有一定了解,而且有调试饥荒代码的想法,但是不知道怎么下手的话,可以来看看。工具会使用到到VSCode,没有使用过的同学建议先去了解一下。

1. 原料准备

Don't Starve 饥荒游戏安装

VSCode安装

LuaPanda下载

最基本的就是要安装好饥荒游戏,游戏的主要代码都放在安装目录下的data/scripts文件夹下,这些后缀名为lua的文件就是饥荒的源代码。

VSCode是一款编辑器,可以下载各种插件来附加额外的功能。利用VSCode打开scripts文件夹就可以开始读代码了。

LuaPanda是腾讯开发的基于VSCode的Lua代码工具。首先需要从GitHub下载LuaPanda,需要其Debugger下的LuaPanda.lua文件。然后在VSCode插件商店中搜索LuaPanda并安装。

2. 初次尝试

先在VSCode中打开scripts文件夹观察一下,发现main.lua文件,推测应该是入口文件,那么调试的入口也就放在main.lua里好了。

main.lua的开始有这样的声明:

说明data/scripts和data/scriptlibs目录下的lua文件都可以被游戏程序找到,因此我把调试需要的LuaPanda.lua文件拷贝到data/scriptlibs目录下。

接下来可以发现关于socket的代码:

可以看到饥荒的程序里已经静态链接了luasocket的内容,luasocket也是LuaPanda调试需要的依赖,需要建立TCP连接来控制运行。那么我根据上述代码认为LuaPanda所需的依赖都完成了,因此可以开始进行调试了。(其实并不是这样的,PLATFORM的值应该为"WIN32_STEAM",但应该在可执行文件内部已经加载了类似于这几行代码的内容)

在上述代码后面加上一行:

其中8818端口是LuaPanda默认的端口号,可以在LuaPanda的设置里修改,但是要保持代码里和设置里的端口号一致。

在VSCode的Run界面运行LuaPanda,可以看到VSCode在等待连接。

嗯,万事俱备,在Steam中启动游戏,等待连接。

然后果然失败了。VSCode一直处于等待的状态,没有连接成功。

3. 排查问题

为了排查问题,需要用到饥荒自带的日志。下面的代码初始化了日志输出函数。

使用print函数可以输出日志,可以在"C:\Users\用户名\Documents\Klei\DoNotStarve\log.txt"中查看日志。当然也可以在游戏中按~调出控制台查看。

3.1 未声明的变量

那么将require("LuaPanda").start("127.0.0.1",8818)剪切到上面那块代码后面。再次运行,比上次有进步,游戏直接闪退。查看日志发现是由于require("strict")使得后续代码中不允许使用未声明的全局变量,而LuaPanda为了支持ue4 luasocket而使用了lua_extension这一未声明的全局变量。(而第一次尝试是在strict引入之前,所以没有闪退)

3.2 确实没有socket

在require("LuaPanda").start("127.0.0.1",8818)之前加上lua_extension = nil,再次执行。(LuaPanda里未声明的全局变量比较多,推荐还是在require("strict")前加上--来注释掉)

报错显示未获取到luasocket,看来之前判断的socket的情况有误。

查看了饥荒的scriptlibs/socket.lua之后,我认为之前的dofile("socket.lua")会生成一个名为socket的全局变量。而LuaPanda里则是利用require("socket.core").tcp()来调用socket,因此LuaPanda与饥荒自带的socket需要适配一下。

3.3 自定义的调用函数

首先要确认饥荒自带的socket是有tcp的。

还是在刚才的代码前,饥荒日志初始化之后加入代码打印出socket的情况。

可以从日志中查看socket的情况,其中包含了tcp函数:

那么接下来只要用饥荒自带的socket调用替换LuaPanda默认的调用就可以了。用VSCode打开LuaPanda.lua文件,可以找到下面这行:

这意味着我们可以自己设置如何调用luasocket,将上面这行代码改成如下之后保存。

运行游戏之后发现没有报错。再次尝试调试,VSCode启动调试,运行游戏。

断点中断成功!程序中断在连接LuaPanda的下一行,接下来就可以在左侧窗口查看变量和堆栈,并进行单步调试了。

成功进入调试状态3.4 总而言之

这章前面是按照我的踩坑情况写过来的,整体实用的部分不多,总结要修改的地方如下:

修改LuaPanda.lua中的customGetSocketInstance

注释掉main.lua中的require("strict")

添加下面代码到data/scripts/main.lua中socket加载之后的位置(经过尝试,Steam版本中可以将下面的代码放在main.lua一开始的位置,即package.path赋值的后面,可以调试到前面更多的内容):

先运行VSCode调试,再启动游戏即可开始调试。

4. 地图生成

由于我对饥荒生成随机地图的方式比较感兴趣,于是决定加上断点调试一下,但是当我新建角色开始游戏,在创建地图的时候发现调试中断。

关于这一点,我推测是创建地图使用了不同的lua虚拟机或者说线程导致的。因为在等待地图创建成功的时候,加载界面还是在不断更新的,位于主线程的前端和调用生成地图函数的并不是同一个lua虚拟机。(将来有时间看看LuaPanda源码,到底为什么连接中断)。

找到地图生成的函数为worldgen_main.lua中的GenerateNew函数,检查socket环境,配置不同的端口(例如8819,和main.lua中的错开),调试成功。需要注意的一点是worldgen_main.lua中的package.path只包含了data/scripts路径,还需要加上data/scriptlibs才能让游戏程序发现LuaPanda.lua文件。还有别忘了注释掉worldgen_main.lua中的rquire("strict")。

5. 未来打算

来年打算辞掉工作,专心开发独立游戏。在那之前,只能安心当个社畜了。

之后还打算研究一下饥荒的动画系统和Mod系统。在我看来能激发玩家创造力的Mod系统真的可以大大提高一款游戏的生命力。总之饥荒作为一款成功的游戏,非常有参考的价值,而且作为主要逻辑的lua代码没有打包和加密,真的是难能可贵。

Polygonal Map Generation for Games

最近发现了一篇讲地图生成的文章Polygonal Map Generation for Games,虽然也是10年前的老文章了,但是不规则多边形组成的地图,而不是全部由正方形Tile组成的地图,里面用到的算法好像和饥荒的也有些类似,虽然饥荒是正方形Tile。好文章抽时间研究一下,而且地图分块生成之后怎么填充纹理也是一个对我来说不小的问题。而且地图只是游戏开发的一部分,甚至是可有可无的一部分,游戏开发真的是“路漫漫其修远兮”啊。

6. 相关链接

饥荒,Don't Starve,

https://store.steampowered.com/app/219740/Dont_Starve/

Visual Studio Code 编辑器,

https://code.visualstudio.com/

LuaPanda,

https://github.com/Tencent/LuaPanda

多边形游戏地图生成,Polygonal Map Generation for Games,

http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3