UserAPI使用说明
注:当前C/C++API文档还未更新,可能有部分函数为1.1版本的旧函数,有问题请在群里询问。
概览
class UserAPI {
public:
UserAPI(UserAPI &) = delete;
//禁用构造函数
bool operator=(const UserAPI &) = delete;
//禁用函数符'='重载
static UserAPI &Singleton(lua_State *L = nullptr);
// 初始化一个类成员函数的执行,参数为类名和函数名
void init_func_call(std::string class_name, std::string func_name);
// 执行lua_State栈顶的函数,参数分别为参数个数与返回值个数
void execute_func_call(int param_num = 0, int ret_num = 0);
// 向lua_State中压入一个字符串
void lua_pushstring(std::string str);
// 获取lua表中的元素(可以是函数),两个参数分别为全局表名和数据项名
void get_lua_property(std::string class_name, std::string property_name);
// 执行移动操作(仅列出,不建议使用)
void move_to(VECTOR dest, double moveNum);
// 另一种方式执行移动操作
void move_by_direction(VECTOR src, double moveNum, int direction)
// 又一种方式执行移动操作
void move_by_coordinates(VECTOR src, VECTOR dest, double moveNum)
// 判断两个点是否相连
bool is_connected(int posX1, int posY1, int posX2, int posY2);
// 获取King的位置
VECTOR king_pos();
// 获取当前的step数
int get_current_step();
// 获取当前选中的位置(1.1版本)
VECTOR selected_pos();
// 设置当前选中位置(1.1版本)
void selected_pos(VECTOR pos);
// 获取当前选中的位置(新版)
VECTOR UserAPI::getSelectedPos()
// 设置当前选中位置(新版)
void UserAPI::setSelectedPos(VECTOR pos)
private:
lua_State *luaState;
UserAPI(lua_State *L) : luaState(L) {}
};
部分函数详解
1 .static UserAPI &Singleton
UserAPI(UserAPI &) = delete;
bool operator=(const UserAPI &) = delete;
static UserAPI &Singleton(lua_State *L = nullptr)
{
static bool has_init = false;
if (!has_init && L == nullptr)
printf("ERROR: argument lua_State not given for initialization");
static UserAPI singleton(L);
has_init = true;
return singleton;
}
这个函数用于获取UserAPI单一实例的一个引用,在首次调用时需要传入一个lua_State 指针,此后可以不传。
这是由于一次游戏中,用户只有一份SDK,因此我们使用单一实例模式来进行实现。用户调用Singleton()可以获取一份SDK实例。注意,在第一次调用时,需要用户手动提供lua_State
指针来初始化SDK。这里提供了一份最小的userMain()
实现
static int userMain(lua_State *luaState) {
UserAPI &API = UserAPI::Singleton(luaState); // 初始化并获取单例
// ...
return 0; // 必须返回0作为参数(代表正确退出),否则程序会崩溃
}
有关单例模式详细情况请查看此博客
2 .init_func_call
void init_func_call(std::string class_name, std::string func_name)
{
lua_getglobal(luaState, class_name.c_str());
if (!lua_istable(luaState, -1))
throw "AI SDK -- not a table error";
lua_pushstring(func_name);
lua_gettable(luaState, -2);
}
这个接口主要用于初始化调用 对接的lua文件中存在的. 表结构成员函数
例如:
void selected_pos(VECTOR pos)
{
init_func_call("AI_SDK", "setSelected");
......
}
对应lua文件中的表叫做"AI_SDK",表中有一个函数叫"setSelected",调用此接口对函数初始化以使用此函数。
3 .execute_func_cal
void execute_func_call(int param_num = 0, int ret_num = 0) {
int iRet = lua_pcall(luaState, param_num, ret_num, 0);
if (iRet) {
throw lua_tostring(luaState, -1);
}
}
这个接口用于执行lua_State栈顶的函数,参数param_num和ret_num分别为参数个数与返回值个数。具体的过程由lua_pcall函数执行,此函数会执行栈顶的函数,若执行过程中出现错误,则会返回一个非0值。此时我们用抛出异常函数throw将其抛出,以待之后处理。
4 .lua_pushstring
void lua_pushstring(std::string str) {
::lua_pushstring(luaState, str.c_str());
}
这个接口用于向lua_State中压入一个字符串。
5 .get_lua_property
void get_lua_property(std::string class_name, std::string property_name) {
lua_getglobal(luaState, class_name.c_str());
if (!lua_istable(luaState, -1)) {
std::cout << "Error: not a table" << std::endl;
throw "not a table" + class_name;
}
lua_getfield(luaState, -1, property_name.c_str());
}
这个接口用于获取lua表中的元素(可以是函数),两个参数分别为全局表名和数据项名
6 .move_to
void move_to(VECTOR dest, double moveNum) {
init_func_call("AI_SDK", "MoveTo");
lua_pushnumber(luaState, dest.x);
lua_pushnumber(luaState, dest.y);
lua_pushnumber(luaState, moveNum);
execute_func_call(3);
}
这是移动军队的接口,( dest.x , dest.y )为目标点坐标,用户调用moveTo函数之前需要提前用函数selected_pos设定好选中的点。
moveNum为移动兵力,其中,其值为0时只在原地留一个士兵;大于1时移动其值数量的兵力;小于1时按比例移动,如0.5为移动一半。
使用示例:
UserAPI &API = UserAPI::Singleton();
double x , y , x1 , y1 ; // 分别设置选中位置和目标位置
... // 赋值
API.selected_pos() = {x, y}; // 设置现在选中位置
API.move_to({x1, y1}, 0.5); // 执行移动操作,从(x,y)–>(x1,y1),移动(x,y)一半的兵力
7 .move_by_direction
void move_by_direction(VECTOR src, double moveNum, int direction) {
init_func_call("AI_SDK", "MoveByDirection");
lua_pushnumber(luaState, src.x);
lua_pushnumber(luaState, src.y);
lua_pushnumber(luaState, moveNum);
lua_pushnumber(luaState, direction);
execute_func_call(4);
}
这个函数是对moveTo的封装,用户调用此函数时只需传入起始点坐标src,移动兵力moveNum和方向direction(正六边形自右上边顺时针方向分别为1~6)。moveNum参考moveTo中的moveNum。
8 .move_by_coordinates
void move_by_coordinates(VECTOR src, VECTOR dest, double moveNum) {
init_func_call("AI_SDK", "MoveByCoordinates");
lua_pushnumber(luaState, src.x);
lua_pushnumber(luaState, src.y);
lua_pushnumber(luaState, dest.x);
lua_pushnumber(luaState, dest.y);
lua_pushnumber(luaState, moveNum);
execute_func_call(5);
}
这个函数是对moveTo的封装,用户调用此函数时只需传入起始点坐标src,终点坐标dest和移动兵力。
9 .is_connected
bool is_connected(int posX1, int posY1, int posX2, int posY2) {
...
}
这个接口用于判断两个选定坐标的格子(X1,Y1)与(X2,Y2)是否相邻。
10.king_pos
VECTOR king_pos() {
get_lua_property("AI_SDK", "KingPos");
if (!lua_istable(luaState, -1)) {
throw "not a table: KingPos";
}
lua_getfield(luaState, -1, "x");
int x = lua_tonumber(luaState, -1);
lua_getfield(luaState, -2, "y");
int y = lua_tonumber(luaState, -1);
return {x, y};
}
这个接口用于获取王的位置,返回的是一个形式为{ X , Y }的VECTOR变量。
11.get_current_step
int get_current_step() {
get_lua_property("ReplayGame", "step");
return lua_tonumber(luaState, -1);
}
这个接口用于获取当前的步数。
12.selected_pos(1.1版本)
VECTOR selected_pos() {
get_lua_property("AI_SDK", "SelectPos");
if (!lua_istable(luaState, -1)) {
throw "not a table: SelectPos";
}
lua_getfield(luaState, -1, "x");
int x = lua_tonumber(luaState, -1);
lua_getfield(luaState, -2, "y");
int y = lua_tonumber(luaState, -1);
return {x, y};
}
这个接口用于获取选中点的位置,返回的是一个形式为{ X , Y }的VECTOR变量。
13.getSelectedPos(新版)
VECTOR UserAPI::getSelectedPos() {
...
return {x, y};
}
这个接口用于获取选中点的位置,返回的是一个形式为{ X , Y }的VECTOR变量。
14.selected_pos(1.1版)
void selected_pos(VECTOR pos) {
...
}
这个接口用于将当前传入的点pos设置为选中状态,一般与moveto配合使用,不用moveto可以不关注。
15.setSelectedPos(新版)
void UserAPI::setSelectedPos(VECTOR pos) {
...
}
这个接口用于将当前传入的点pos设置为选中状态,一般与moveto配合使用,不用moveto可以不关注。