Skip to content

Lua grid AOI algorithm.

License

Notifications You must be signed in to change notification settings

cfadmin-cn/lua-aoi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 

Repository files navigation

lua-aoi

基于cfadmin实现的纯Lua版九宫格Aoi算法.

API Introduce

local aoi = require "lua-aoi"

导入后必须先使用Aoi类来创建一个实例.

0. Aoi new

function Aoi:new({
    x = x or 65535,
    y = y or 65535,
    radius = radius or 100,
  })
end

x - X轴的最大值, 起始值为0, 默认值为65535.

y - Y轴的最大值, 起始值为0, 默认值为65535.

radius - 指定半径大小, 默认值为100.

使用Aoi类创建实例, 创建后的实例可用于下面的操作.

1. Aoi Enter

---comment @Player Enter
---@param uid  any      @UID
---@param x    integer  @Y Position
---@param y    integer  @X Position
---@param fast boolean  @don't care response.
function Aoi:enter(uid, x, y, fast) return { uid1, uid2, uid3 } end

返回值为进入后, 需要通知的单位数组.

如果指定fasttrue, 那么将不会有返回值.

2. Aoi Move

---comment @Player Move
---@param uid any      @UID
---@param x   integer  @Y Position
---@param y   integer  @X Position
function Aoi:move(uid, x, y) return { uid1, uid2, uid3 } end

返回值为移动后, 需要通知的单位数组.

3. Aoi Leave

---comment @Player Leave
---@param uid any      @UID
function Aoi:leave(uid) return { uid1, uid2, uid3 } end

返回值为离开后, 需要通知的单位数组.

4. Aoi Around

---comment @Player Get all units around `uid`
---@param uid any      @UID
function Aoi:around(uid) return { uid1, uid2, uid3 } end

返回值为指定uid周围需要通知的单位数组.

5. Aoi Aroundx

---comment @Player Get all units around `X` and `Y` position
---@param x   integer  @Y Position
---@param y   integer  @X Position
function Aoi:aroundx(x, y) return { uid1, uid2, uid3 } end

返回值为指定XY位置周围需要通知的单位数组.

6. Aoi get_uid

---comment Get uid position.
---@param uid any   @UID
---@return table    @Position{ x = xxx, y = yyy }
function Aoi:get_uid(uid) return { x = y, y = x } end

返回值为指定uidXY值.

7. Aoi Count

---comment Get all units amount.
---@return integer
function Aoi:count() return the_number_of_units end

返回值内部单位总数

Test

local aoi = require "lua-aoi"

local sys = require "sys"
local now = sys.now

-- 地图大小
local max_x, max_y = 5000, 5000
-- 地图内的人数
local max_humen = 1000
-- 指定半径范围
local radius = 100

local Amap = aoi:new {
  x = max_x,
  y = max_y,
  radius = radius,
}

for i = 1, max_humen do
  -- 指定人数进入到随机的位置
  Amap:enter("user-" .. i, math.random(0, max_x), math.random(0, max_y), true)
end

-- 启动每隔0.5秒触发一次的周期定时器
require "cf".at(0.5, function ()
  local ret = {}
  local uid =  "user-" .. math.random(1, max_humen)
  local s = 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)
  local e = now()
  local position = Amap:get_uid(uid)
  print(string.format("uid为: %s(%d, %d), 数量为: %d, 耗时为: %.4f秒", uid, position.x, position.y, #ret, e - s))
end)

Advice

  • uidunique ID的缩写, 是用来代指Aoi结构内部唯一ID而不是User ID.
  • 支持integer/string类型的uid值, 但建议自行构造成: player::pidnpc::nidcreep::cid等.
  • 数组下标查表是非常高效的, 所以一般是不会有性能问题的. 但请尽可能将聚集度设计的更松散, 避免大量单位聚集在格子内.
  • 可自行根据示例代码测试不同大小、范围、人数等等情况下的效率.

Releases

No releases published

Packages

No packages published

Languages