首先,我们要知道LUA是个什么东西,至于官方怎么说可以百度去查,但我想告诉你的是LUA就是一种可以在不必修改C++代码的情况下实现逻辑处理的手段。稍微讲的再明白一点,就是你用指定语法写一些逻辑处理函数然后保存成文本格式,这个文件称为脚本文件,可以被游戏执行。经过若干年的发展,现在在LUA中写逻辑,除了调用注册到LUA的静态C函数外,也已经可以方便的访问到C++工程中的类的成员函数。这是游戏开发史上最重要的技术之一。其改变了很多设计方案,使游戏变的灵活强大而极具扩展性。
在Cocos2d-x中,有两个类来完成对于LUA脚本文件的处理。
1. CCLuaEngine:LUA脚本引擎
2. CCScriptEngineManager:脚本引擎管理器。
CCLuaEngine类的基类是一个接口类,叫做CCScriptEngineProtocol,它规定了所有LUA引擎的功能函数,它和CCScriptEngineManager都存放在libcocos2d下的script_support目录中的CCScriptSupport.h/cpp中。
首先我们来看一下CCScriptEngineProtocol:
[cpp]
class CC_DLL CCScriptEngineProtocol : public CCObject
{
public:
//取得LUA的全局指针,所有的LUA函数都需要使用这个指针来做为参数进行调用。
virtual lua_State* getLuaState(void) = 0;
//通过LUA脚本ID移除对应的CCObject
virtual void removeCCObjectByID(int nLuaID) = 0;
//通过函数索引值移除对应的LUA函数。
virtual void removeLuaHandler(int nHandler) = 0;
//将一个目录中的LUA文件加入到LUA资源容器中。
virtual void addSearchPath(const char* path) = 0;
//执行一段LUA代码
virtual int executeString(const char* codes) = 0;
//执行一个LUA脚本文件。
virtual int executeScriptFile(const char* filename) = 0;
//调用一个全局函数。
virtual int executeGlobalFunction(const char* functionName) = 0;
//通过句柄调用函数多种形态。
//通过句柄调用函数,参数二为参数数量。
virtual int executeFunctionByHandler(int nHandler, int numArgs = 0) = 0;
//通过句柄调用函数,参数二为整数数据。
virtual int executeFunctionWithIntegerData(int nHandler, int data) = 0;
//通过句柄调用函数,参数二为浮点数据。
virtual int executeFunctionWithFloatData(int nHandler, float data) = 0;
//通过句柄调用函数,参数二为布尔型数据。
virtual int executeFunctionWithBooleanData(int nHandler, bool data) = 0;
//通过句柄调用函数,参数二为CCObject指针数据和其类型名称。
virtual int executeFunctionWithCCObject(int nHandler, CCObject* pObject, const char* typeName) = 0;
//将一个整数数值压栈做为参数。
virtual int pushIntegerToLuaStack(int data) = 0;
//将一个浮点数值压栈做为参数。
virtual int pushFloatToLuaStack(int data) = 0;
//将一个布尔数值压栈做为参数。
virtual int pushBooleanToLuaStack(int data) = 0;
//将一个CCObject指针和类型名压栈做为参数。
virtual int pushCCObjectToLuaStack(CCObject* pObject, const char* typeName) = 0;
// 执行单点触屏事件
virtual int executeTouchEvent(int nHandler, int eventType, CCTouch *pTouch) = 0;
//执行多点触屏事件。
virtual int executeTouchesEvent(int nHandler, int eventType, CCSet *pTouches) = 0;
// 执行一个回调函数。
virtual int executeSchedule(int nHandler, float dt) = 0;
};
这个接口类的功能函数的具体实现,我们要参看CCLuaEngine类。
现在我们打开CCLuaEngine.h:
[cpp]
//加入lua的头文件,约定其中代码使用C风格
extern "C" {
#include "lua.h"
}
//相应的头文件。
#include "ccTypes.h"
#include "cocoa/CCObject.h"
#include "touch_dispatcher/CCTouch.h"
#include "cocoa/CCSet.h"
#include "base_nodes/CCNode.h"
#include "script_support/CCScriptSupport.h"
//使用Cocos2d命名空间
NS_CC_BEGIN
// 由CCScriptEngineProtocol派生的实际功能类。
class CCLuaEngine : public CCScriptEngineProtocol
{
public:
//析构
~CCLuaEngine();
//取得LUA的全局指针,所有的LUA函数都需要使用这个指针来做为参数进行调用。
virtual lua_State* getLuaState(void) {
return m_state;
}
…此处省略若干字。
// 加入一个多线程加载LUA脚本的实时回调函数,此函数用于ANDROID
virtual void addLuaLoader(lua_CFunction func);
//取得当前单件实例指针
static CCLuaEngine* engine();
private:
//构造,单例,你懂的。
CCLuaEngine(void)
: m_state(NULL)
{
}
//初始化函数。
bool init(void);
//将一个句柄压栈
bool pushFunctionByHandler(int nHandler);
//唯一的LUA指针
lua_State* m_state;
};
NS_CC_END
分析其CPP实现:
[cpp]
//本类的头文件。
#include "CCLuaEngine.h"
//这里用到了tolua++库,tolua++库是一个专门处理LUA脚本的第三方库,可以很好的完成LUA访问C++类及成员函数的功能。如果没有tolua++,这块要处理起来可是麻烦死了。
#include "tolua++.h"
//加入lua库的相应头文件。
extern "C" {
#include "lualib.h"
#include "lauxlib.h"
#include "tolua_fix.h"
}
//加入Cocos2d-x所用的相应头文件。
#include "cocos2d.h"
#include "LuaCocos2d.h"
#include "cocoa/CCArray.h"
#include "CCScheduler.h"
//如果是ANDROID平台,加上对多线程加载LUA脚本的支持,使用相应的头文件。