- 注册时间
- 2015-10-21
- 最后登录
- 2024-6-6
- 在线时间
- 3 小时
编程入门
- 魔鬼币
- 64
|
最近在学习lua多任务, 用于智辅游戏服务器消息的处理, 因为脚本消息很多,
每分钟有几十条到上百条, 如果不能多任务并行处理, 会拖慢游戏,也不实用
整理下, 做个笔记, 以免忘了, 代码也是百度来的, 改改能用
lua用5.3.1版, 和我原来的5.1版本有不兼营, 按网上的方法改成支持中文变量
这样挺好的, 代码也不用注释, 取名字方便,也短, 不然如果用英文
背包-->bag 血-->HP 兰-->MP 还好翻译好记
怪物-->monster 人物-->human 就不有点长,不好记
地面物品-->dropeditem 装备-->useitem 狂欢应典活动-->KHQD 太不直观了
xx地图 xxNPC xx任务 就十分难翻译了,
闲话结束, 正文开始
----------------------------------------------
--LUA协程和多任务
--3个同时运行的协程为例
--每隔一定的间隔输出文字, 协程状态
--第1个 隔101毫秒 输出5次
--第2个 隔101毫秒 输出2次
--第3个 隔101毫秒 输出3次
--实现协程的关键是要 延时 = mylib.delay 这个函数
--标准库里没有这个函数 用C扩展为DLL库来使用
--先启用定时器, 然后把协程挂起(yield), 定时器时间到了再唤醒(resume)
--这样就能实现多个任务同时运行
--协程一次只能有1个运行(running), 其它都是在挂起状态(suspended)
--当协程运行结束后, 就是停止状态(dead)
--协程挂起(yield), 唤醒(resume), 应用有一定限制,就是不能在C和LUA间交叉使用
--即在C中挂起的,就要在C中唤醒, Lua中挂起的,也要在LUA中唤醒
--协程的开销不大, 初略估计了下, 开启运行2万多个协程,结束后故意不消毁,内存约增加20多M
--1个协程的开销约1k多内存
--Lua脚本
延时 = mylib.delay
function 显示(a,b)
print(a,b,'co1='..coroutine.status(co1),'co2='..coroutine.status(co2),'co3='..coroutine.status(co3))
end
function 协程(序号,次数,毫秒)
for i=1,次数 do
延时(毫秒) 显示(序号,i*毫秒 )
end
显示(序号,'结束' )
end
co1=coroutine.create(协程) coroutine.resume(co1, '脚本1', 5, 101)
co2=coroutine.create(协程) coroutine.resume(co2, '脚本2', 2, 301)
co3=coroutine.create(协程) coroutine.resume(co3, '脚本3', 3, 501)
--运行结果
036CBF54 脚本1 101 co1=running co2=suspended co3=suspended
036CBF54 脚本1 202 co1=running co2=suspended co3=suspended
036CC01C 脚本2 301 co1=suspended co2=running co3=suspended
036CBF54 脚本1 303 co1=running co2=suspended co3=suspended
036CBF54 脚本1 404 co1=running co2=suspended co3=suspended
036CC0E4 脚本3 501 co1=suspended co2=suspended co3=running
036CBF54 脚本1 505 co1=running co2=suspended co3=suspended
036CBF54 脚本1 结束 co1=running co2=suspended co3=suspended
036CC01C 脚本2 602 co1=dead co2=running co3=suspended
036CC01C 脚本2 结束 co1=dead co2=running co3=suspended
036CC0E4 脚本3 1002 co1=dead co2=dead co3=running
036CC0E4 脚本3 1503 co1=dead co2=dead co3=running
036CC0E4 脚本3 结束 co1=dead co2=dead co3=running
--延时 = mylib.delay 的C代码 用C++Builder 6环境
--调用delay时,首先创建1个定时器
int id = SetTimer(NULL, NULL, ms, (TIMERPROC)LuaTimerProc);
--然后保存协程句柄,定时器id到TList LuaTimerList,到定时器回调时有用
LuaTimerList->Add((void*)L);
LuaTimerList->Add((void*)id);
--然后,挂起协程
--时间到了,定时器回调函数运行
--因为定时器只用一次就够了, 故销毁之
KillTimer(hWnd, uIDEvent);
--在TList LuaTimerList找到对应的记录,获得协程句柄,唤醒之
lua_resume(L, 0, 0);
--注意, 在dll退出时, 记得销毁LuaTimerList, 不然内存略有泄漏
case DLL_PROCESS_DETACH:
delete LuaTimerList;
break;
--在lua中使用方法, (编译后的库名为mylib.dll)
mylib = require('mylib')
mylib.delay(100) --延时100ms
--函数只能在协程内使用, 在主线程使用会出错
--不过没关系, 可以让所有脚本都在协程运行,按下列方式即可
function f()
--------------------
--这里插入要执行的内容
--------------------
end
co=coroutine.create(f)
coroutine.resume(co)
//---------------------------------------------------------------------------
//Lua扩展库测试
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma package(smart_init)
#include <vcl.h>
#include <math.h>
#include <windows.h>
#include "LuaMylib.h"
TList *LuaTimerList;
//void _stdcall LuaTimerProc(int hwnd, int uMsg, int idEvent, int time)
void CALLBACK LuaTimerProc(HWND hWnd, UINT nMsg, UINT uIDEvent, DWORD dwTime)
{
KillTimer(hWnd, uIDEvent);
for (int i=(LuaTimerList->Count / 2) -1;i>=0; i--)
{
UINT id = (UINT)LuaTimerList->Items[i*2+1];
if (id == uIDEvent)
{
lua_State *L = (lua_State*)LuaTimerList->Items[i*2];
LuaTimerList->Delete(i*2);
LuaTimerList->Delete(i*2);
lua_resume(L, 0, 0);
}
}
}
static int delay (lua_State *L) {
if (lua_gettop(L) == 0) return 0;
int ms = lua_tointeger(L, 1);
int id = SetTimer(NULL, NULL, ms, (TIMERPROC)LuaTimerProc);
if (LuaTimerList == NULL )LuaTimerList = new(TList);
LuaTimerList->Add((void*)L);
LuaTimerList->Add((void*)id);
lua_pop(L, 1);//弹出参数
return lua_yield(L, 0);
}
static const luaL_Reg mylib[] = {
{"delay", delay},
{NULL, NULL}
};
/*
** Open test library
*/
LUALIB_API int luaopen_mylib (lua_State *L) {
luaL_newlib(L, mylib);
return 1;
}
|
|