合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
### 3.4 求出九宫格 ##### A\)根据格子ID求出九宫格 现在我们根据格子ID`gid`求出周边的格子有哪些? 我们可能要考虑一些情况,比如格子的四周都有,如下图: ![](https://img.kancloud.cn/66/dd/66ddd2ac7a512b7d08e16c73876ed7e8_1024x768.jpeg)或者,格子所在AOI区域的四个顶角,如下图: ![](https://img.kancloud.cn/bd/11/bd1121dfaf9dc8be3c9828ffcfbbbbcb_1024x768.jpeg)或者给所在AOI边界,周边的格子缺少一列,或者缺少一行。 思考一下,我们是否可以想一个统一的方法,将所有的条件都满足。 如果求出一个gid的周边九宫格,那么可以先算出该gid所处一行左边和右边是否有,然后在分别计算这一行的上边和下边的格子是否有,就可以了。 思路如下: ![](https://img.kancloud.cn/b2/0a/b20afd1a1556427fb8fb9361d651cb68_1024x768.jpeg)![](/assets/10-Zinx游戏-AOI算法分析5.jpeg)![](/assets/11-Zinx游戏-AOI算法分析6.jpeg)参考代码如下: > mmo\_game/core/aoi.go ```go //根据格子的gID得到当前周边的九宫格信息 func (m *AOIManager) GetSurroundGridsByGid(gID int) (grids []*Grid) { //判断gID是否存在 if _, ok := m.grids[gID]; !ok { return } //将当前gid添加到九宫格中 grids = append(grids, m.grids[gID]) //根据gid得到当前格子所在的X轴编号 idx := gID % m.CntsX //判断当前idx左边是否还有格子 if idx > 0 { grids = append(grids, m.grids[gID-1]) } //判断当前的idx右边是否还有格子 if idx < m.CntsX - 1 { grids = append(grids, m.grids[gID+1]) } //将x轴当前的格子都取出,进行遍历,再分别得到每个格子的上下是否有格子 //得到当前x轴的格子id集合 gidsX := make([]int, 0, len(grids)) for _, v := range grids { gidsX = append(gidsX, v.GID) } //遍历x轴格子 for _, v := range gidsX { //计算该格子处于第几列 idy := v / m.CntsX //判断当前的idy上边是否还有格子 if idy > 0 { grids = append(grids, m.grids[v-m.CntsX]) } //判断当前的idy下边是否还有格子 if idy < m.CntsY - 1 { grids = append(grids, m.grids[v+m.CntsX]) } } return } ``` ##### B\)根据坐标求出九宫格 还有一种情况是玩家只知道自己的坐标,那么如何确定玩家AOI九宫格的区域都有哪些玩家呢,那就需要设计一个根据坐标求出周边九宫格中玩家的接口。 ![](/assets/12-Zinx游戏-AOI算法分析7.jpeg)我们首先应该根据坐标得到所属的格子ID,然后再走根据格子ID获取九宫格信息就可以了。 > mmo\_game/core/aoi.go ```go //通过横纵坐标获取对应的格子ID func (m *AOIManager) GetGIDByPos(x, y float32) int { gx := (int(x) - m.MinX) / m.gridWidth() gy := (int(x) - m.MinY) / m.gridLength() return gy * m.CntsX + gx } //通过横纵坐标得到周边九宫格内的全部PlayerIDs func (m *AOIManager) GetPIDsByPos(x, y float32) (playerIDs []int) { //根据横纵坐标得到当前坐标属于哪个格子ID gID := m.GetGIDByPos(x, y) //根据格子ID得到周边九宫格的信息 grids := m.GetSurroundGridsByGid(gID) for _, v := range grids { playerIDs = append(playerIDs, v.GetPlyerIDs()...) fmt.Printf("===> grid ID : %d, pids : %v ====", v.GID, v.GetPlyerIDs()) } return } ```