引擎是一个游戏辅助工具的核心,尤其是嵌入引擎,它可以算得上是最有技术含量的模块。大家知道,写外挂最难的部分就是怎样去破解游戏程序,例如:定位游戏数据的基址,搞清楚游戏的通信协议,确定游戏界面元素的显示位置等等。所有这些是需要花大量时间和精力的,有时候即便如此,也还可能是摸不到头绪。很多外挂开发人员恐怕都有这样经历吧,绞尽脑汁却仍然不得其解。然而,一旦经过不懈的努力最终发现破解的钥匙,那份成就感也是任何其他人都无法体会的。
开发出一个好的引擎价值不菲,在它的基础上可以派生出很多应用。例如:对于一个能够解析游戏协议的封包处理引擎,理论上,使用它甚至可以写出一个自己的游戏客户端出来,既然如此,用它来做一个机器人外挂岂不是易如反掌吗!?
游戏帮手不仅会提供一个优秀的引擎框架,同时它也会提供许多有用的API协助你去做那些跟破解游戏相关的最困难的工作,使你更加有效的开发出好的引擎。
创建一个引擎需要创建一个动态库工程,而且这个动态库必须是一个MFC标准(Regular DLL)或扩展(Extension DLL)的动态库,这是因为引擎中使用到了很多MFC的接口。
与创建对话框工程类似,有三种方法可以创建一个GameBs引擎工程。
这种方法是首选,可以极大地提高开发效率。如何安装GameBs工程向导?请参考: 安装GameBs工程向导
使用以下两个向导创建引擎工程:
下面我们分别创建一个主控引擎(TestHostEng)和一个嵌入引擎(TestEmbedEng)。
新建项目 --> 选择GameBsHostEngine AppWizard --> 选择路径(如:D:\source) --> 输入项目名TestHostEng --> 点OK按钮完成项目创建,如图1所示。

图1
此时如果直接编译会出现一些链接错误,这是因为工程所依赖的几个库没有配置。请把以下库文件配置到该工程的依赖库中,
GmbsEngine.lib wtermin.lib
在VC6.0中,如何配置工程的依赖库?请参考: 配置工程的依赖库 。
TestHostEng.cpp是实现引擎类的源文件,打开它查看源代码:
#include "stdafx.h"
#include "TestHostEng.h"
#include "wtermin.h"//Provide the external interface for container to retrieve engine instance (also add it into .def) static CTestHostEng *m_pSingletonEngine = NULL;
void* Gmbs_GetEngineInstance(LPCSTR strEngineName)
{
if (m_pSingletonEngine != NULL)
return m_pSingletonEngine;
m_pSingletonEngine = new CTestHostEng("TestHostEng");
return m_pSingletonEngine;
}CTestHostEng::CTestHostEng(LPCSTR lpEngineName)
: CGmbsHostEngine(lpEngineName)
{
}CTestHostEng::~CTestHostEng()
{
}BOOL CTestHostEng::InitInstance()
{
CGmbsHostEngine::InitInstance();
//add your code below
return TRUE;
}int CTestHostEng::ExitInstance()
{
//add your code below
return CGmbsHostEngine::ExitInstance();
}//engine message handler
int CTestHostEng::OnMessageProc(LPCSTR lpMsgName, PBYTE pMsgData, int nMsgDataLen, BOOL bNeedReturn)
{
return 0;
}//user message handler
int CTestHostEng::OnUserMessageProc(LPCSTR lpMsgName, PBYTE pMsgData, int nDataLen)
{
return 0;
}
每个引擎都必须实现一个对外的输出接口Gmbs_GetEngineInstance,它用于返回该引擎的单实例指针。在上面代码的Gmbs_GetEngineInstance中创建了一个CTestHostEng的实例,其引擎名为“TestHostEng”。引擎名是引擎的唯一标识,例如在给某一引擎发送消息时,需要指定目标引擎名。
必须把该接口添加到工程的.def文件中,以达到输出该接口的目的。下面是TestHostEng.def的内容:
EXPORTS Gmbs_GetEngineInstance
现在,类CTestHostEng的方法都还没有实现,这也正是后续的开发工作要做的事,我们应该根据产品需求和程序设计逐步地完善该引擎类。
该工程编译成功后,会在Debug目录下生成一个动态库TestHostEng.dll,这就是我们稍后将要装配到产品中的一个主控引擎模块。
新建项目 --> 选择GameBsEmbedEngine AppWizard --> 选择路径(如:D:\source) --> 输入项目名TestEmbedEng --> 点OK按钮完成项目创建,如图2所示。

图2
直接编译链接会出现相同的错误,同样把以下库文件配置到工程的依赖库中,
GmbsEngine.lib wtermin.lib
在VC6.0中,如何配置工程的依赖库?请参考: 配置工程的依赖库 。
查看引擎类CTestEmbedEng的源代码,会发现它与前面创建的主控引擎类非常相似。只是CTestEmbedEng的基类是CGmbsEmbedEngine,而CTestHostEng的基类是CGmbsHostEngine,而这两个基类CGmbsHostEngine和CGmbsEmbedEngine同样都是继承自CGmbsEngine。
该工程编译成功后,会在Debug目录下生成一个动态库TestEmbedEng.dll,稍后我们会将它装配到产品的嵌入容器去。
打开VC6.0 --> 新建项目(New) --> 选择MFC AppWizard (dll) --> 选择路径(如:D:\source)--> 输入Project name (如:TestHostEng)--> 点OK按钮(图3)
在弹出的新对话框中:选择Regular DLL --> 点Finish按钮完成(图4)

图3

图4
创建工程后,通过编译链接可以生成一个动态库,但此时它全部是由MFC向导帮你做的,只是一个空壳。为了实现一个引擎模块,你需要选择继承合适的引擎基类来创建新的引擎:
接下来的工作,建议你参考开发包中的示例程序创建和实现你的引擎类,或参考前面贴出的CTestHostEng的代码。
选择开发包中的一个示例程序,复制它的引擎工程的代码到你的产品中,然后把它改成你想要的工程名。
如何把一个VC6.0的工程改名?请参考: 修改工程名称。