您现在的位置是:首页 >技术交流 >【GameMaker】C++ 插件制作进阶:YYRunnerInterface网站首页技术交流

【GameMaker】C++ 插件制作进阶:YYRunnerInterface

Ceyase 2025-03-31 00:01:03
简介【GameMaker】C++ 插件制作进阶:YYRunnerInterface

前言

如题目所示,本文章将讲解GameMaker自带的C++头文件:YYRunnerInterface.h

该头文件可实现以下功能:

  • 向 GameMaker 的 Log 窗口输出内容
  • 为 C++ 加入 GameMaker 数据类型(如 struct 和 ds系列 )。

注意,以下将把所有提到的 GameMaker 数据类型简称为 YYRValue。
这是一个通用数据类型,可以持有多种数据类型,如实数、字符串、数组、对象、整数、指针、向量、矩阵等。

  • 可使用 YYRValue 作为函数的参数和返回值。
  • 使用 C++ 代码调用所有 GML 函数。

正如我们所知,YoYoGames 一如既往的不把插件作者当人看。该头文件没有任何官方文档,其制作的目的也只是为了 GM 官方的 GDKExtension。

所以,我们如果想要在不修改头文件的情况下使用它,就必须将自己的插件伪装成 GDKExtension。

初始化

本文不会去讲开发 C++ 应用程序的基本操作。笔者所使用的环境如下:

操作系统建构系统开发IDE
Windows 10CMakeVisual Studio 2022

首先,我们需要知道这个头文件在哪。

C:ProgramDataGameMakerStudio2Cache untimes版本号yycinclude

一步步找就能找到这个文件夹,注意要使用和你游戏相匹配的版本,而不是盲目使用最新版。

文件夹及其子文件夹中有好几个头文件,除了 YYGML.h 以外都是有用的头文件,请复制到你的工程目录。

使用以下代码即可导入 YYRunnerInterface。

// 伪装成 GDKExtension
#define GDKEXTENSION_EXPORTS
#define __YYDEFINE_EXTENSION_FUNCTIONS__
#define YYEXPORT __declspec(dllexport)

// 导入头文件
#include "YYRunnerInterface.h"
#include "Ref.h"
#include "YYRvalue.h"

// 初始化函数
YYRunnerInterface gs_runnerInterface;
YYRunnerInterface* g_pYYRunnerInterface;
YYEXPORT void YYExtensionInitialise(const struct YYRunnerInterface* _pFunctions, size_t _functions_size) {
	memcpy(&gs_runnerInterface, _pFunctions, sizeof(YYRunnerInterface));
	g_pYYRunnerInterface = &gs_runnerInterface;
	if (_functions_size < sizeof(YYRunnerInterface)) YYError("Runner interface size mismatch");
	DebugConsoleOutput("Successfully initialized runner interface
");
	return;
}

编译时可能出现报错,请自行修补一下。
我相信,这些错误都是你能够自行解决的。
我无法在此列出有那些错误,因为随着 GameMaker 的版本更新,越来越多的兼容性错误出现。

定义函数

如下代码定义了一个 GameMaker 风格的函数。

YYEXPORT void my_add(RValue& Result, CInstance* selfinst, CInstance* otherinst, int argc, RValue* arg) {
	int result = 0;
	if (argc == 0) {
		Result.kind = VALUE_UNDEFINED;
		YYError("This function requires at least one parameter.");
		return;
	}
	for (int i = 0; i < argc; i++) {
		int value = YYGetReal(arg,i);
		result += value;
	}
	Result.kind = VALUE_REAL;
	Result.val = result;
	return;
}

这段代码的用处是定义了一个参数数量可变的累加函数。

我们用以下测试代码证明其支持无限参数,而这在以往的插件开发中是难以做到的。

难以做到 ≠ 不能做到。以往可以用 buffer 回传数据,但是太麻烦了。

show_message(my_add(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1));

运行后弹出了 58的弹窗,验证了其可用性。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。