深入探索AOI算法实现(九宫格篇)

本文深入探讨游戏中的AOI算法,强调其作为游戏核心的重要性,并指出优化AOI对于提升游戏性能的关键作用。作者介绍了两种经典算法——网格法和双链表法,并分享了自己实现的九宫格算法,该算法支持不同半径的AOI需求。文章附带了代码实现和测试结果,展示初步实现的AOI功能。
摘要由CSDN通过智能技术生成

游戏的AOI算法应该算作游戏的基础核心了,许多逻辑都是因为AOI进出事件驱动的,许多网络同步数据也是因为AOI进出事件产生的。因此,良好的AOI算法和基于AOI算法的优化,是提高游戏性能的关键。
我在实践中所熟知的游戏AOI算法大致有两种,在此做一些总结,顺便梳理一下,打算设计出一套统一的接口封装不同的算法实现(网络上还有些其他算法,因为不熟悉不作记录了)。我所记录的这两种算法也算经典了,一个叫做网格法,一个叫做双链表法。具体细节可参考如下:https://zhuanlan.zhihu.com/p/201588990

根据 文章描述,自己动手初步实现了九宫格算法,该版本支持不同半径AOI。

grid.go代码如下:

package grid

import (
	"fmt"
)

type void struct{}

func newVoid() void {
	return struct{}{}
}

type Grid struct {
	GridId          int32
	SceneId         int32
	Players         map[int32]void
	FollowerPlayers map[int32]void // 关注本格子的player, 本格子在该player视距之内, 因为视距不同,需要增加该变量缓存
}

func newGrid(GridId int32, SceneId int32) *Grid {
	return &Grid{
		GridId:          GridId,
		SceneId:         SceneId,
		Players:         make(map[int32]void),
		FollowerPlayers: make(map[int32]void),
	}
}

type SceneAOIManager struct {
	SceneId int32
	Length  int32
	Width   int32
	Side    int32
	Grids   map[int32]*Grid
}

func Ceil(a int32, b int32) int32 {
	if a%b == 0 {
		return a / b
	}

	return a/b + 1
}

func NewSceneAOIManager(SceneId int32, Length int32, Width int32, Side int32) *SceneAOIManager {
	LengthNum := Ceil(Length, Side)
	WidthNum := Ceil(Width, Side)

	GridNum := WidthNum * LengthNum

	Scene := &SceneAOIManager{
		SceneId: SceneId,
		Length:  Length,
		Width:   Width,
		Side:    Side,
		Grids:   make(map[int32]*Grid),
	}

	var i int32
	for i = 0; i < GridNum; i++ {
		Scene.Grids[i] = newGrid(i, SceneId)
	}

	AllSceneManager[SceneId] = Scene
	return Scene
}

func (Scene *SceneAOIManager) getGridId(x int32, y int32) int32 {
	var GridId int32 = -1

	XNum := Max(x-1, 0) / Scene.Side
	YNum := Max(y-1, 0) / Scene.Side

	XMax := Ceil(Scene.Length, Scene.Side)

	GridId = XNum + YNum*XMax
	return GridId
}

// Player所能看到的玩家
func (Scene *SceneAOIManager) PlayerNeighbor(Entity *EntityAOI) (map[int32]void, map[int32]void) {
	Watching := make(map[int32]void)

	GridId := Scene.getGridId(Entity.X, Entity.Y)
	Range := Max(Entity.VisibleArea-1, 0)/Scene.Side + 1
	AOIGrids := Scene.VisibleGridByRound(GridId, Range)
	for GirdId := range AOIGrids {
		GridObj :&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值