关于vue.js:lua脚本在游戏中的应用

55次阅读

共计 5476 个字符,预计需要花费 14 分钟才能阅读完成。

一,为什么要在游戏中应用脚本语言?

要解释这个问题首先咱们先来理解一下脚本语言的个性:

1,学习门槛低,疾速上手。

2,开发成本低,可维护性强。

3,动静语言,灵活性高。

绝对于 C /C++ 这类高复杂性、高风险的编译型语言来说,Lua 脚本做为一种轻量级的动静语言,简略的语言个性,精简的外围和根底库,使得语言的学习门槛大大的升高,即便是没有任何游戏教训的人都能疾速上手,开发游戏性能。实际上游戏设计是一种非常繁冗的工作,C/C++ 尽管给咱们带来极大的高效性,但同时也不能漠视其复杂性,极易产生 BUG,而且对于开发人员的要求十分高。从语言的的形象层面来说 C /C++ 的形象低更加适宜于底层逻辑的反对,而 Lua 脚本抽象层次高,更加适宜游戏逻辑的实现。脚本语言运行在虚拟机之上,而虚拟机运行在游戏逻辑之上,作为一种解释型语言,咱们能够随时批改并及时体现在游戏之中,疾速实现开发。C/C++ 却做不到,对一个微小的游戏工程,每次批改都须要从新编译,老本很高。构想一下,如果所有的性能都是应用 C /C++ 实现的话,那么对开发人员来说几乎是一场劫难。

二,如何在游戏中应用 Lua 脚本?

这里就不实践一大堆了,间接手把手教。

1,进入 Lua 官方网站下载 Source 源代码

2,在 Visual Studio 在新建一个解决方案名为 Lua2Game

3,在 Lua2Game 解决方案下新建一个空我的项目,命名为 LuaDll,将从 Lua 官网下载的源代码 src 中除 luac.c 文件之外的源代码拷贝到 LuaDll 工程,配置我的项目属性,惯例 -> 配置类型为动态库 (lib) 而后编译 LuaDll 我的项目。(luac.c 是编译器,lua.c 是解释器也就是 lua 虚拟机)

4,在 Lua2Game 解决方案下新建一个空我的项目,命名为 Game,配置我的项目属性,惯例 -> 配置类型为应用程序(.exe), 这就是游戏 demo。在我的项目属性中,链接器 -> 输出 -> 附加依赖项中退出../Debug/LuaDll.lib

5,在我的项目 Game 中实现脚本引擎 CLuaScript(实现 C /C++ 与 Lua 脚本的相互拜访)

LuaScript.h

#ifndef LUA_SCRIPT_H

#define LUA_SCRIPT_H

#include “GameDef.h”

class CLuaScript

{

public:

CLuaScript();

~CLuaScript();

public:

// 实现 C /C++ 对 Lua 脚本的调用

bool LoadScript(const char* szFileName); // 实现 lua 脚本加载和编译

// 调用 Lua 函数

bool CallFunction(char cFuncName, int nResults, char cFormat, va_list vlist);

bool CallFunction(const char cFuncName, int nResults, char cFormat, …);

private:

void RegisterLuaLib(); // 注册 lua 各种根底库

bool RegisterFunctions(TLua_Funcs Funcs[], int n);// 将游戏接口注册到 lua 脚本

private:

lua_State* m_LuaState; //state 脚本和 C\C++ 搞基就靠它了

bool m_IsLoadScript;

};

#endif

LuaScript.cpp

#include

#include “LuaScript.h”

CLuaScript::CLuaScript()

{

m_LuaState = luaL_newstate();

if (!m_LuaState)

{

std::cout << “m_LuaState new state failed!” << std::endl;

return;

}

RegisterLuaLib();// 注册 lua 规范库

RegisterFunctions(g_GameFunc, g_GetGameFuncSize());// 注册 c\c++ 脚本接口

m_IsLoadScript = false;

}

CLuaScript::~CLuaScript()

{

if (m_LuaState)

{

lua_close(m_LuaState);

m_LuaState = NULL;

}

m_IsLoadScript = false;

}

void CLuaScript::RegisterLuaLib()

{

if (!m_LuaState)

{

return;

}

luaL_openlibs(m_LuaState);

}

bool CLuaScript::RegisterFunctions(TLua_Funcs Funcs[], int n)

{

if (!m_LuaState)

{

return false;

}

for (int i = 0; i < n; i++)

lua_register(m_LuaState, Funcs[i].name, Funcs[i].func);

return true;

}

bool CLuaScript::LoadScript(const char* szFileName)

{

if (!szFileName || szFileName[0] == ‘\0’)

{

std::cout << “Lua script file illegal!” << std::endl;

return false;

}

if (!m_LuaState)

return false;

m_IsLoadScript = (www.cungun.comluaL_dofile(m_LuaState, szFileName) == LUA_OK);

if (!m_IsLoadScript)

{

std::cout << “”<< lua_tostring(m_LuaState, -1) << std::endl;

lua_pop(m_LuaState, 1);

}

return m_IsLoadScript;

}

bool CLuaScript::CallFunction(char cFuncName, int nResults, char cFormat, va_list vlist)

{

if (!m_LuaState || !m_IsLoadScript)

return false;

double nNumber = 0;

int nInteger = 0;

char* cString = NULL;

void* pPoint = NULL;

int i = 0;

int nArgnum = 0;

lua_CFunction CFunc = NULL;

lua_getglobal(m_LuaState, cFuncName); // 在堆栈中退出须要调用的函数名

while (cFormat[i] != ‘\0’)

{

switch (cFormat[i])

{

case ‘n’:// 输出的数据是 double 形 NUMBER,Lua 来说是 Double 型

{

nNumber = va_arg(vlist, double);

lua_pushnumber(m_LuaState, nNumber);

nArgnum++;

}

break;

case ‘d’:// 输出的数据为整形

{

nInteger = va_arg(vlist, int);

lua_pushinteger(m_LuaState, nInteger);

nArgnum++;

}

break;

case ‘s’:// 字符串型

{

cString = va_arg(vlist, char *);

lua_pushstring(m_LuaState, cString);

nArgnum++;

}

break;

case ‘N’://NULL

{

lua_pushnil(m_LuaState);

nArgnum++;

}

break;

case ‘f’:// 输出的是 CFun 形,即外部函数形

{

CFunc = va_arg(vlist, lua_CFunction);

lua_pushcfunction(m_LuaState, CFunc);

nArgnum++;

}

break;

case ‘v’:// 输出的是堆栈中 Index 为 nIndex 的数据类型

{

nNumber = va_arg(vlist, int);

int nIndex1 = (int)nNumber;

lua_pushvalue(m_LuaState, nIndex1);

nArgnum++;

}

break;

}

i++;

}

int nRetcode = lua_pcall(m_LuaState, nArgnum, nResults, 0);

if (nRetcode != 0)

{

std::cout << “” << lua_tostring(m_LuaState, -1) << std::endl;

lua_pop(m_LuaState, 1);

return false;

}

return true;

}

bool CLuaScript::CallFunction(const char cFuncName, int nResults, char cFormat, …)

{

bool bResult = false;

va_list vlist;

va_start(vlist, cFormat);

bResult = CallFunction((char*)cFuncName, nResults, cFormat, vlist);

va_end(vlist);

return bResult;

}

6,定义用于实现定义给 lua 脚本的游戏接口

GameDef.h

#ifndef GAME_DEF_H

#define GAME_DEF_H

extern “C”{

#include “../../LuaDll/src/lua.h”

#include “../../LuaDll/src/lauxlib.h”

#include “../../LuaDll/src/lualib.h”

}

struct TLua_Funcs

{

const char *name;

lua_CFunction func;

};

extern TLua_Funcs g_GameFunc[];

extern int g_GetGameFuncSize();

#endif

GameDef.cpp

#include “GameDef.h”

#include

#include

#include “Core.h”

using namespace std;

int LuaSayHello(lua_State* L)

{

cout << “Lua call c/c++:SayHello()” << endl;

cout << “Hello Everyone!” << endl;

if (lua_gettop(L) < 3)

return 0;

const char* szName = lua_tostring(L, 1);

int nParam1 = lua_tonumber(L, 2);

int nParam2 = lua_tonumber(L, 3);

cout << “My name is ” << szName << endl;

lua_pushnumber(L, nParam1 / nParam2);

return 1;

}

int LuaStopGame(lua_State* L)

{

cout << “Lua call c/c++:StopGame()” << endl;

cout << “Game is over!” << endl;

g_Core.SetRunState(false);

return 0;

}

// 脚本接口

TLua_Funcs g_GameFunc[] = {

{“SayHello”, LuaSayHello},

{“StopGame”, LuaStopGame},

};

int g_GetGameFuncSize()

{

return sizeof(g_GameFunc) / sizeof(TLua_Funcs);

}

7,模拟游戏主逻辑

Core.h

#ifndef CORE_H

#define CORE_H

#include “GameDef.h”

#include “LuaScript.h” 郑州妇科医院排名 http:/w.tongjink.com/

class CCore

{

public:

CCore();

~CCore();

public:

bool Initialize();

void Uninitialize();

bool Breathe();

void SetRunState(bool bRunning);

private:

CLuaScript* m_Script;

bool m_bIsRuning;

};

extern CCore g_Core;

#endif

正文完
 0