前言
在看本教程之前,笔者默认你已经熟读并学会了创建扩展,你应该学会如何使用 GML 编写扩展——这是一切的前提,请使用 GML 编写你的第一个扩展而不是 DLL。
在本教程中,笔者将教会你使用我们的制作工具——Visual Studio 2017 来编译一个基本的 DLL,我们的目标是制作一种能够检测两个实例之间的碰撞的插件。
此页面底部有一个可供下载的DEMO,但我们强烈建议您按照本教程进行操作。
重要提示 I:本教程假定您对 C/C++ 编程有一点了解并基本熟悉 Visual Studio 2017。我们不教你 C/C++ 也不会教会你 IDE 的使用,请自行查阅教程。
重要提示 II:为什么我们一定要使用 Visual Studio 2017 而不是 Visual Studio 2022 之类的版本呢?这是因为 2017 目前 GMS2 中支持最广泛的 VS 版本。尽管其他版本用的可能更舒服,但请相信,兼容性最好的仍然是 2017,希望您已经安装的也是如此。
我们为什么要创建 DLL 扩展
在制作 Windows 游戏时,你有时会遇到 GML 无法解决的棘手问题,这些问题我们必须先骂一下 yoyogames,然后再来考虑我们应该怎么办——很明显,DLL 扩展是最好的出路之一。
(虽然 GMS2 已经提供了很好的碰撞方法,但请让我们假设:假如 GML 中不存在碰撞相关的函数,我们应该怎么办。)
创建您的 Visual Studio 项目
PS:我用的英文版VS,所以部分涉及到文件操作的地方就不翻译了,因为不同版本的汉化肯定存在差异。
首先,从 Visual Studio 中的 File > New 对话框创建一个空的 C++ 项目。
确保为项目选择合适的名称和保存位置,然后继续保存项目。注意:本教程中的项目名和插件名均为“ DLLExtension ”,如果你在后续代码中看到了此字样请不要惊慌,酌情改为自己的项目名和插件名。
创建项目后,需要更改设置以便让我们编译时生成一个 DLL 文件。这是在项目的属性中完成的,可以在解决方案资源管理器中项目的右键菜单中找到。
然后,您将看到应用程序设置窗口。要更改为 DLL 输出,请选择“配置类型”下拉菜单并选择动态链接库 (.dll)。
Apply/OK 后,我们要生成一个包含我们代码的源文件。
您可以从解决方案资源管理器中执行此操作,方法是右键单击 Source Files 文件夹并选择 Add > New Item。从此对话框中,您可以选择“c++ 文件 (.cpp)”然后进行重命名。在本教程中为“Collisions.cpp”。
现在,我们要开始写代码了。
编写你的 DLL
你是不是以为我们马上要开始实现功能了?NO NO NO。为了方便,我们要添加一行代码:
#define func extern "C" __declspec(dllexport)
这行代码看起来很复杂,但我们可以一个词一个词的帮你解析一下:
"#define func" 可以理解为“替换”,该关键词的意思是将代码中的所有 “func” 字样替换成 “extern "C" __declspec(dllexport)” 后编译。
“extern "C" 是一个编译器标志,这相当于告诉编译器:”我想要编译成C语言DLL的风格!“。这样做是因为 C++ 可能会在函数声明中添加我们不想要的额外信息。
"__declspec(dllexport)" 的意思是标志着这个函数是公开的,可以让GMS2调用。
添加完这一行后,当我们想要声明一个新函数时,我们只需要使用关键字“func”,而不是上面那一大堆。比如下面这样(这只是比如啊啊,千万不要写到你代码里,写了也没用)
func double TestFunction() {
return 1;
}
现在,我们可以开始实现功能了。
我们的目标是实现检测碰撞的功能,所以我们可以先制作一个最简单的检测碰撞示例——”点是否在圆内(IsPointInCircle)“。
func double IsPointInCircle(double xx, double yy, double cx, double cy, double cr){
// (xx,yy)是点的坐标,(cx,cy) 是圆心的坐标,cr 是圆的半径。
// 因为勾股定理,我们可以得出如果点在圆心内, 则x^2 + y^2 < r^2。
// 因此,我们便得到了以下这行代码。
return ((xx - cx)*(xx - cx) + ((yy - cy) * (yy - cy)) < cr*cr);
}
没看懂?可以参考这张图。
从这张图中我们可以知道,|xx-cx| = x,|cy - yy| = y,为什么要用绝对值呢,懒得说了,自己品吧。
因为勾股定理, aa = x^2+y^2。我们很明了的能看出,当这个点在圆内时,a < r,当这个点在圆边上时,a = r,当这个点在圆外面时,a > r。
因此便可推理一下得到以下结果:
因此便得到了上面那行代码。
话说回来,为什么我们的数据类型使用的都是 double 呢?这是因为 GMS2 的 DLL 扩展只支持 double 和 string 这两种类型。
接下来,你只需要编译 DLL 文件,然后按照创建扩展走就行了。
后记
请记住,DLL 只能用于 Windows 平台。
GMS2 2.3.1 及更高版本可以支持64位 DLL,而旧版本仅支持 32 位 DLL。但是,我们鼓励您尽可能多地支持 64 位扩展,尤其是在制作 Marketplace 的内容时,因为 32 位支持最终将被淘汰。
以上信息保持不变,除了您需要在 Visual Studio 中选择 64 位输出(“x64”)类型。