前面简述了HelloWorld程序的编写过程,使用到了GM的虚拟机gmMachine,下面我们将对GM进行一些简单的包装使得其适应到我们自己的项目中,使其可以很方便的执行脚本函数。
基本接口gmMachine::ExecuteString,我们要做的就是读取脚本文件的内容然后交给改接口去编译执行,同时我们需要进行一些错误处理。
GMScriptDrv为我包装的GameMonkey执行脚本文件的基础类,代码如下(GMScriptDrv.h):
#pragma
once
#include " gmThread.h " // game monkey script
class GMScriptDrv
... {
public:
GMScriptDrv(void);
virtual ~GMScriptDrv(void);
/**//// Get the GM machine
gmMachine* GetMachine() ...{ return m_pGMMachine; }
/**//// 创建虚拟机,初始化
virtual void InitGM();
/**//// 释放资源
virtual void DestroyGM();
/**//// Update the virtual machine.
int Update(unsigned int deltaTime);
/**//// 加载并执行执行脚本文件
bool ExecuteFile(const char* fileName);
/**//// 运行一个脚本字符串,可以用来调用某个脚本语句
bool ExecuteString(const char* str);
/**//// 错误处理
/// 允许子类重载以不同的方式记录LOG
virtual void LogError(const char *a_str, ...);
/**//// Log any machine error messages that may be waiting
void LogAnyMachineErrorMessages();
private:
//! GM 虚拟机
gmMachine* m_pGMMachine;
} ;
#include " gmThread.h " // game monkey script
class GMScriptDrv
... {
public:
GMScriptDrv(void);
virtual ~GMScriptDrv(void);
/**//// Get the GM machine
gmMachine* GetMachine() ...{ return m_pGMMachine; }
/**//// 创建虚拟机,初始化
virtual void InitGM();
/**//// 释放资源
virtual void DestroyGM();
/**//// Update the virtual machine.
int Update(unsigned int deltaTime);
/**//// 加载并执行执行脚本文件
bool ExecuteFile(const char* fileName);
/**//// 运行一个脚本字符串,可以用来调用某个脚本语句
bool ExecuteString(const char* str);
/**//// 错误处理
/// 允许子类重载以不同的方式记录LOG
virtual void LogError(const char *a_str, ...);
/**//// Log any machine error messages that may be waiting
void LogAnyMachineErrorMessages();
private:
//! GM 虚拟机
gmMachine* m_pGMMachine;
} ;
1、InitGM(); 初试化,就是new一个gmMachine
2、Update(unsigned int deltaTime); 调用gmMachine::Execute函数,需要放在程序循环中调用
3、DestroyGM(); 销毁gmMachine实例,一般在退出程序时调用
4、ExecuteString(const char* str); 执行指定的字符串
bool
GMScriptDrv::ExecuteString(
const
char
*
str)
... {
GM_ASSERT(m_pGMMachine);
int threadId = GM_INVALID_THREAD;
int errors = m_pGMMachine->ExecuteString(str, &threadId, true);
if (errors)
...{
LogAnyMachineErrorMessages();
}
return true;
}
... {
GM_ASSERT(m_pGMMachine);
int threadId = GM_INVALID_THREAD;
int errors = m_pGMMachine->ExecuteString(str, &threadId, true);
if (errors)
...{
LogAnyMachineErrorMessages();
}
return true;
}
5、ExecuteFile(const char* fileName); 加载并执行GM脚本文件,使用C API实现
bool
GMScriptDrv::ExecuteFile(
const
char
*
fileName)
... {
FILE* scriptFile = NULL;
char* fileString = NULL;
int fileSize = 0;
GM_ASSERT(m_pGMMachine);
if( !(scriptFile = fopen(fileName, "rb")) )
...{
LogError("File Open Failed:%s.",fileName);
return false;
}
fseek(scriptFile, 0, SEEK_END);
fileSize = ftell(scriptFile);
fseek(scriptFile, 0, SEEK_SET);
fileString = new char [fileSize+1];
fread(fileString, fileSize, 1, scriptFile);
fileString[fileSize] = 0; // Terminating null
fclose(scriptFile);
//-- 执行字符串
ExecuteString(fileString);
delete [] fileString;
return true;
}
... {
FILE* scriptFile = NULL;
char* fileString = NULL;
int fileSize = 0;
GM_ASSERT(m_pGMMachine);
if( !(scriptFile = fopen(fileName, "rb")) )
...{
LogError("File Open Failed:%s.",fileName);
return false;
}
fseek(scriptFile, 0, SEEK_END);
fileSize = ftell(scriptFile);
fseek(scriptFile, 0, SEEK_SET);
fileString = new char [fileSize+1];
fread(fileString, fileSize, 1, scriptFile);
fileString[fileSize] = 0; // Terminating null
fclose(scriptFile);
//-- 执行字符串
ExecuteString(fileString);
delete [] fileString;
return true;
}
6、LogAnyMachineErrorMessages(); 错误处理,如果gmMachine::ExecuteString返回的不是0时就是执行字符串时出错啦,根据需要记录出错信息的LOG。
void
GMScriptDrv::LogAnyMachineErrorMessages()
... {
bool first = true;
const char * message;
while((message = m_pGMMachine->GetLog().GetEntry(first)))
...{
LogError("%s", message);
}
m_pGMMachine->GetLog().Reset();
}
... {
bool first = true;
const char * message;
while((message = m_pGMMachine->GetLog().GetEntry(first)))
...{
LogError("%s", message);
}
m_pGMMachine->GetLog().Reset();
}
工作完成啦,可以开始使用我们的GM包装类啦。一切都是这么简单:
int
main(
int
argc,
char
*
argv[])
... {
int m_lastTime = timeGetTime();
GMScriptDrv gms;
// 初始化
gms.InitGM();
// todo something
gms.ExecuteFile("C://Hello.gm");
const char *myScript = "fruits = table ( "apple", "pear", "orange" ); "
"foreach ( frt in fruits ) { print(frt); } ";
gms.ExecuteString(myScript);
while(true)
...{
int curTime = timeGetTime();
int deltaTime = curTime - m_lastTime;
m_lastTime = curTime;
// Update GM 虚拟机
while (gms.Update(deltaTime))
...{
}
}
// 销毁退出
gms.DestroyGM(); return 0;
}
... {
int m_lastTime = timeGetTime();
GMScriptDrv gms;
// 初始化
gms.InitGM();
// todo something
gms.ExecuteFile("C://Hello.gm");
const char *myScript = "fruits = table ( "apple", "pear", "orange" ); "
"foreach ( frt in fruits ) { print(frt); } ";
gms.ExecuteString(myScript);
while(true)
...{
int curTime = timeGetTime();
int deltaTime = curTime - m_lastTime;
m_lastTime = curTime;
// Update GM 虚拟机
while (gms.Update(deltaTime))
...{
}
}
// 销毁退出
gms.DestroyGM(); return 0;
}