基于cfadmin实现的纯Lua版九宫格Aoi算法.
localaoi=require"lua-aoi"导入后必须先使用Aoi类来创建一个实例.
functionAoi:new({
x=xor65535,
y=yor65535,
radius=radiusor100,
})
endx - X轴的最大值, 起始值为0, 默认值为65535.
y - Y轴的最大值, 起始值为0, 默认值为65535.
radius - 指定半径大小, 默认值为100.
使用Aoi类创建实例, 创建后的实例可用于下面的操作.
---comment @Player Enter---@paramuidany @UID---@paramxinteger @Y Position---@paramyinteger @X Position---@paramfastboolean @don't care response.functionAoi:enter(uid, x, y, fast) return { uid1, uid2, uid3 } end返回值为进入后, 需要通知的单位数组.
如果指定fast为true, 那么将不会有返回值.
---comment @Player Move---@paramuidany @UID---@paramxinteger @Y Position---@paramyinteger @X PositionfunctionAoi:move(uid, x, y) return { uid1, uid2, uid3 } end返回值为移动后, 需要通知的单位数组.
---comment @Player Leave---@paramuidany @UIDfunctionAoi:leave(uid) return { uid1, uid2, uid3 } end返回值为离开后, 需要通知的单位数组.
---comment @Player Get all units around `uid`---@paramuidany @UIDfunctionAoi:around(uid) return { uid1, uid2, uid3 } end返回值为指定uid周围需要通知的单位数组.
---comment @Player Get all units around `X` and `Y` position---@paramxinteger @Y Position---@paramyinteger @X PositionfunctionAoi:aroundx(x, y) return { uid1, uid2, uid3 } end返回值为指定X与Y位置周围需要通知的单位数组.
---comment Get uid position.---@paramuidany @UID---@returntable @Position{ x = xxx, y = yyy }functionAoi:get_uid(uid) return { x=y, y=x } end返回值为指定uid的X与Y值.
---comment Get all units amount.---@returnintegerfunctionAoi:count() returnthe_number_of_unitsend返回值内部单位总数
localaoi=require"lua-aoi"localsys=require"sys"localnow=sys.now-- 地图大小localmax_x, max_y=5000, 5000-- 地图内的人数localmax_humen=1000-- 指定半径范围localradius=100localAmap=aoi:new {
x=max_x,
y=max_y,
radius=radius,
}
fori=1, max_humendo-- 指定人数进入到随机的位置Amap:enter("user-" ..i, math.random(0, max_x), math.random(0, max_y), true)
end-- 启动每隔0.5秒触发一次的周期定时器require"cf".at(0.5, function ()
localret= {}
localuid="user-" ..math.random(1, max_humen)
locals=now()
-- -- 玩家移动后需要通知的人-- ret = Amap:move(uid, x, y)-- -- 玩家离开后需要通知的人-- ret = Amap:leave(uid)-- -- 根据指定UID, 获取其周边有多少人-- ret = Amap:around(uid)-- -- 根据指定位置, 获取周边有多少人-- local x, y = math.random(0, max_x), math.random(0, max_y)-- ret = Amap:aroundx(x, y)locale=now()
localposition=Amap:get_uid(uid)
print(string.format("uid为: %s(%d, %d), 数量为: %d, 耗时为: %.4f秒", uid, position.x, position.y, #ret, e-s))
end)uid为unique ID的缩写, 是用来代指Aoi结构内部唯一ID而不是User ID.- 支持
integer/string类型的uid值, 但建议自行构造成:player::pid、npc::nid、creep::cid等. - 数组下标查表是非常高效的, 所以一般是不会有性能问题的. 但请尽可能将聚集度设计的更松散, 避免大量单位聚集在格子内.
- 可自行根据示例代码测试不同大小、范围、人数等等情况下的效率.