GameStudio支持用户自己编写引擎插件和在外部程序中调用引擎,前者是用这些语言编写一个引擎插件的DLL(增加新功能),后者是直接将引擎DLL(acknex.dll)作为游戏函数库来使用。这种机制使得人们可以利脱离GS脚本开发的平台只需提供若干引擎库函数就可以在其他开发环境中(如VC, Dephi等)实现3D游戏一类的程序。本文就主要介绍一下实现一个简单的引擎插件和引擎实现的基本方法。
n 引擎插件
一个DLL是一个向程序提供函数的外部库。而一个插件是作为向引擎和脚本语言增加新的特性的扩展性的特殊DLL。不同于通常只向外提供函数的普通DLL,插件可以访问所有引擎函数,变量以及用户所定义的函数、变量和对象。
在创建插件时,需要使用诸如VC++或Delphi一类的开发环境。DLL插件能与所有版本GameStudio都兼容,而且可以发布或卖给GameStudio的用户。在GS官方网站里可以找到很多有用的插件。
插件的SDK在开放源码协议下是免费的。这意味着只要在发布版中包含源码,开发、部署任何引擎插件都是免费的。而具有SDK证书(只在GS专业版中提供)的用户无需提供源码。推荐使用VC++ (2005 或 .NET)用来创建DLL插件。有些用户在网站上也提供了C++Builder或Dephi的库。
使用插件SDK
SDK文件位于GameStudio安装文件夹下的sdk_plugin文件夹内,sampledll.cpp是示例的源码,包含典型的DLL函数使用方法。通过学习该示例可以了解如何编写DLL函数和访问引擎参数,还可以将其作为你自己DLL的模板使用。
这里使用VC++作为开发平台。打开Microsoft Visual C++ 6.0。选择File->New Project,选择一个工程模板。注意这里不要选择MFC DLL。在VC++.NET中选择普通Win32 Project,在VC++6.0中选择Win32 Dynamic-Link Library来创建。当Win32工程向导弹出时,选择.DLL(.NET)或Simple DLL(6.0可)设置。现在,VC++就创建了一个新DLL工程。主cpp文件如下所示:
// plug-in.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } |
这是DLL主入口。将所有SDK文件拷入刚才由VC++创建的文件夹中。为了编译引擎的插件DLL,还需要链接adll.lib(SDK文件之一)到工程中:打开Project Setting -> Link Input -> Object/library modules,在该栏末尾加上“(空格)adll.lib”(添加内容不含引号);在Debug-> Working directory输入D:/Program files/GStudio7(GS的安装目录)。然后在Workspace--FileView中的文件夹树根节点右键加入所有SDK文件,并在Source Files中所有pp文件开头处加上:#include "stdafx.h"。(注意:GS A7.06的adll.lib和afuncs.h需要更新至最新版才能被正确编译)
(PS.:在VC++2005中,也得告知连接器不要使用libc.lib。因此在工程属性中设置忽略用来Debug & Release的库文件libc.lib,并添加到Linkers Additional Dependencies.。)
编写基本DLL
打开cpp源文件,定义DLL_USE并将adll.h包含进去(如下所示)。DLL_USE用于打开和关闭adll.h头文件的DLL模式。在sampledll.cpp文件中的过程如下。
adll.lib包含了一些有用的函数,如engine_getobj和 engine_getscript。DLL必须至少调用其中的一个库函数来确保连接到库上了,这是必做的一件事。将下面调用添加至Dllmain中。
#include "stdafx.h" #define DLL_USE #include "adll.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { engine_bind(); return TRUE; } |
现在开始在DLL中编写自己的函数然后由某个脚本或渲染器来调用这个DLL。为了导出到引擎,使用DLLFUNC宏声明一个函数,即
// returns the value of x * 2n DLLFUNC var ldexpc(var x,var n) { return (_VAR(_FLOAT(x)*pow(2.0,_FLOAT(n)))); } |
该函数则返回的是参数表达式的算术结果。DLLFUNC是用来声明DLL导出函数的一条简单办法。var是C-Sript的一个多用途的数目变量类型----一个长整型,比如22.10这样的定点数或指针。这些和一些函数都在头文件adll.h中有声明。看看它们会很有用处。 对于var类型引擎接受所有数字—coordinates、变量等。因此使用_VAR宏使得函数返回前将任何数字转换成var然后将其返回给引擎。
n 引擎实现
引擎—acknex.dll—可以供其它程序或程序语言使用,如VC++、Dephi或VB。调用引擎函数和访问引擎变量的方法与引擎插件部分介绍的内容相同。
SDK和库是由VC++2003创建的。当使用VC++2005时,需要让连接器不使用微软禁用的libc.lib。因此,在工程属性的Debug和Release里设置该库为忽略模式,并将libcmt.lib添加至Linkers Additional Dependencies。
引擎库和头部可在sdk_engine文件夹中找到。确定将acknex.lib连接到了你的程序上。在完成EXE的编译后,要么在GameStudio文件夹中执行,要么使用WED命令行调用针对可执行程序所创建的一个可部署的acknex.dll。GameStudio文件夹中的acknex.dll只是一个开发版本且不能进行部署。请遵照sdk_engine文件夹中readme文件里提到的license情况部署可执行程序。(PS.:本节所有示例的源码位于GStudio7/sdk_engine文件夹中的e_tutorial.cpp文件)
基本流程
使用acknex引擎编写一个2D或3D应用程序要比写一个普通Windows程序简单得多。只需知道三个函数:
ENGINE_VARS *engine_open(char * commandline)
初始化引擎,返回一个指向引擎变量结构体的指针(见avars.h),接受包含初始化时需要载入的脚本、实体文件、电影文件名称的命令行字符串(command line string),以及命令行选项。
BOOL engine_frame(void)
在执行碰撞检测、物理效果、I/O处理等情况时,在窗口和全屏幕模式下渲染(render)一个框架。该函数在主“游戏循环”中被调用并在引擎即将退出时返回0。目标渲染区域可由video_window函数获得----通过这种方式引擎可以完成任意窗口的渲染。第一次engine_frame调用打开了3D设备。之后才调用引擎和视频函数。
void engine_close(void)
关闭引擎。
VC++相关设置
打开File->New Project,选择一个工程模板。选择Win32 Application来创建,输入Project name。当Win32工程向导弹出时,选择A simple Win32 application设置。现在,VC++就创建了一个新Win32工程。主cpp文件如下所示:
// plug-in.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } |
这是主函数入口。将sdk_engine文件夹中的所有.h和.lib文件拷入刚才由VC++创建的文件夹中。为了编译引擎,还需要链接acknex.lib(SDK文件之一)到工程中:打开Project Setting -> Link Input -> Object/library modules,在该栏末尾加上“(空格)acknex.lib”(添加内容不含引号);在Debug-> Working directory输入D:/Program files/GStudio7(GS的安装目录)。然后在Workspace--FileView中的文件夹树根节点右键加入所有刚才拷入文件夹的文件。
在本例子中可以学习编写只有4行C++代码的一个3D程序的基本流程。
// Include the usual Windows headers #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <tchar.h>
// Include the engine data types, variables, and functions #include "adll.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { engine_open("arena.wmb"); //初始化引擎并打开一个关卡 while (engine_frame()); //关卡运行主循环,当退出时函数返回0 engine_close(); //关闭引擎 return 0; } |