用Hge && Lua写游戏(1)

      声明:本文章经由作者本人同意转载到此,如果您有任何问题或意见需要向作者请教,请您到文章的源出处http://blog.sina.com.cn/u/4b7f61c90100076a交流您的意见,谢谢!

     开始吧,首先从网上下载Lua(我是5.1.1),Luabind(我是0.7),Hge(我是1.6)和Boost库。由于我用的是VC8,但原来的库是VC6或7编译的,所以需要将这些库的源代码重新编译,得到lib和dll文件。然后按着教程写些代码,链上库,保证能够顺利执行。这里注意几点:
     1.luabind似乎应该分别用debug和release模式编译,我得到的是luabindd.lib和luabindr.lib,使用时若是debug模式就链luabindd.lib,release就luabindr.lib
     2.VC8取消了单线程模式和以往会不兼容,所以你的工程及依赖的库应该保证编译链接的一致性,就是用同一个编译链接选项。
     3.Lua5.1和之前版本有很多不同,具体自己去网上搜。
     4.也许还会遇到其他问题,我当时就差点放弃,坚持下来,多试试,遇到不懂的先google再问人。
 
     确认这3个库可以正常工作后就可以开始写游戏了,你还需要做的是找一些参考资料(lua,luabind,hge的官方手册及其他文档)和加入几个相关的技术群,这里推荐"中国HGE"(QQ:14159676)。
     建一个Win32工程,把该载的头文件载进去。

// Windows 头文件:
#include

// C 运行时头文件
#include
#include
#include
#include

//hge头文件
#include
#include
#include
#include
#include

//stl头文件
 
//lua头文件
extern "C"
{
 #include "lua.h"
 #include "lualib.h"
 #include "lauxlib.h"
}

//luabind头文件
#include
#include
#include

    由于我的方案是用luabind将hge类及相关函数映射到lua中,所以你需要按照luabind的方法进行包装,要注意的是由于hge类是个虚基类,所以你还得另外写个类对其进行包装。映射函数时注意参数或返回值为指针的情况,还有不定参数,都是不行的。

   Bind.h

namespace tg
{

namespace Bind
{
 //绑定hge
 void Bind_HgeSys(lua_State* L);  
 //绑定hgeFont
 void Bind_HgeFont(lua_State* L);
 //绑定hgeSprite
 void Bind_HgeSprite(lua_State* L);
 }

}

Bind.cpp

//绑定hge
void Bind::Bind_HgeSys(lua_State* L)
{
 module(L)
 [  
 class_("HgeSys") 
  .def(constructor<>())   
  .scope
  [    
   def("System_Start",&HgeSys::System_Start),       

   def("System_SetStateBool", &HgeSys::System_SetStateBool),
   def("System_SetStateInt", &HgeSys::System_SetStateInt),
   def("System_SetStateString", &HgeSys::System_SetStateString),   

   //def("Resource_Load",&HgeSys::Resource_Load), //这两个有问题
   //def("Resource_Free",&HgeSys::Resource_Free),     
   def("Resource_AttachPack",&HgeSys::Resource_AttachPack),   

   ......

  ]
 ];
}

//绑定hgeFont
void Bind::Bind_HgeFont(lua_State* L)
{
 module(L)
    [
 class_("HgeFont")
   .def(constructor())
   .def(constructor())
   .def("Render",&hgeFont::Render)
   ......  
 ];
}

//绑定hgeSprite
void Bind::Bind_HgeSprite(lua_State* L)
{
 module(L)
    [
 class_("HgeSprite")
   .def(constructor())
   .def(constructor())
   .def("Render",&hgeSprite::Render)
   ......   
 ];
}

注意,这里我绑定的是HgeSys而非Hge类,因为Hge是个虚基类,不能直接用luabind,所以在其上包装了一层。

HgeSys.h

namespace tg
{

class HgeSys
{
public:
 HgeSys();
 ~HgeSys();

 static void System_Start(); //启动hge循环 

 //设置hge状态
 static void System_SetStateBool(hgeBoolState state, bool value);
 static void System_SetStateInt(hgeIntState state, int value);
 static void System_SetStateString(hgeStringState state, const char* value); 

  //其他函数

  //HGE interface
 static HGE* hge;  

};

}

还得建一个脚本引擎类来负责lua脚本的打开,初始化,执行等。

//ScriptEngine.h

namespace tg
{

class ScriptEngine
{
public:
 ScriptEngine();
 ~ScriptEngine();

 void Init();    //初始化
 void Release(); //结束
 bool Render();  //图像绘制
 bool Update();  //消息处理和逻辑更新

private:
 lua_State* L;
};

}

//---------------ScriptEngine.cpp里---------------------

//构造函数
ScriptEngine::ScriptEngine()
{
 L = luaL_newstate();
 lua_cpcall(L, luaopen_base, 0);
 lua_cpcall(L, luaopen_io, 0);
 lua_cpcall(L, luaopen_string, 0);
 lua_cpcall(L, luaopen_table, 0);
 lua_cpcall(L, luaopen_math, 0);
 lua_cpcall(L, luaopen_debug, 0); 
 lua_cpcall(L, luaopen_os, 0);

 open(L);
 //邦定C++到Lua
 Bind::Bind_HgeSys(L);
 Bind::Bind_HgeFont(L); 
 Bind::Bind_HgeSprite(L);
 Bind::Bind_DebugConsole(L);

 int s = luaL_loadfile(L, "Script//GameInit.lua");
 if ( s==0 )
 {  
  s = lua_pcall(L, 0, LUA_MULTRET, 0); //启动lua初始文件
    } 
}

//析构函数
ScriptEngine::~ScriptEngine()
{
 lua_close(L);
}
//初始化
void ScriptEngine::Init()

 luabind::call_function(L,"EngineInit"); //脚本引擎初始化
}

//结束
void ScriptEngine::Release()
{
 luabind::call_function(L,"EngineRelease"); //脚本引擎结束 
}

//图像绘制
bool ScriptEngine::Render()
{
 return luabind::call_function(L,"EngineRender");
}

//消息处理和逻辑更新
bool ScriptEngine::Update()
{
 return luabind::call_function(L,"EngineUpdate");
}

C++部分还剩下的就是main函数了,这里建立了HgeSys,ScriptEngine的对象,绑定RenderFunc和FrameFunc函数到Hge,然后启动Hge,执行相关函数。。

#include "stdafx.h"
#include "HgeSys.h"
#include "ScriptEngine.h"
#include  "DebugConsole.h"
using namespace tg;

DebugConsole debugConsole;   //这个是开console窗口调试用的
tg::HgeSys hgeSys;              //封装Hge接口的类
tg::ScriptEngine scriptEngine;  //脚本引擎


/
bool FrameFunc()

 return scriptEngine.Update(); 
}

bool RenderFunc()
{
 // Render scene 
 HgeSys::hge->Gfx_BeginScene();  
  
 scriptEngine.Render(); 

 HgeSys::hge->Gfx_EndScene();
 return false;
}


//Main
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

 HgeSys::hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
 HgeSys::hge->System_SetState(HGE_RENDERFUNC, RenderFunc); 

 if(HgeSys::hge->System_Initiate())
 {
  scriptEngine.Init();         //脚本引擎初始化    
  HgeSys::hge->System_Start(); //hge执行,进入游戏引擎循环
  scriptEngine.Release();      //脚本引擎结束 
 } 
 
 return 0;
}

最后说下Lua部分,我的是GameInit.lua进行初始化工作,GameEngine.lua是游戏6引擎部分,也有Init,Render,Update,Release等方法。

------------GameInit.lua---------------------

---------------------初始化hge状态---------------------------------
HgeSys.System_SetStateString(16, "GameEngine.log")  --HGE_LOGFILE
HgeSys.System_SetStateString(7, "GameEngine")       --HGE_TITLE
HgeSys.System_SetStateBool(18, false)          --HGE_USESOUND
HgeSys.System_SetStateBool(11, true)           --HGE_WINDOWED
HgeSys.System_SetStateBool(25, false)          --HGE_HIDEMOUSE
HgeSys.System_SetStateInt(8, 800)              --HGE_SCREENWIDTH
HgeSys.System_SetStateInt(9, 600)              --HGE_SCREENHEIGHT
HgeSys.System_SetStateInt(10, 32)              --HGE_SCREENBPP


---------------------游戏引擎-------------------------------------
dofile("Script//GameEngine.lua")

gameEngine = GameEngine()  --全局游戏引擎对象


---------------------Globa function--------------------------------游戏引擎初始化,由C++调用
function EngineInit()
    gameEngine:Init()   
end

--绘制图像
function EngineRender()
    return gameEngine:Render()
end

--消息处理和逻辑更新
function EngineUpdate()
    return gameEngine:Update()
end

--资源释放
function EngineRelease()
    gameEngine:Release()
end

----------GameEngine.lua游戏引擎,由Hge调用-------------------


class 'GameEngine'   --这种语法是需要luabind才能写的!

function GameEngine:__init()   
end

function GameEngine:Init() --初始化   
end

function GameEngine:Render() --图像绘制            
    return false    
end

function GameEngine:Update()  --消息处理 & 逻辑更新     
    return false       
end

function GameEngine:Release() --资源释放 
end

本来还有很多,但一一贴出来太杂,还不如去直接看源代码,可以到我E盘上下载:

http://free.ys168.com/?sftk  程序还很粗糙,还望见谅,需要交流的话可加我QQ

你可能感兴趣的:(游戏开发)