| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- package astar6
- import "fmt"
- // Node A*寻路节点
- // 采用预计算策略,空间换时间,初始化时计算好所有坐标
- // 优化后的内存布局:将bool字段移到末尾,使用静态数组替代slice
- type Node struct {
- x, y int32 // 网格坐标(offset坐标系)
- // 预计算的坐标(空间换时间)
- pixelX, pixelY float64 // 像素坐标,用于视觉距离计算
- pixelXInt, pixelYInt int64 // 预计算的整数像素坐标(×1000),优化calLinearityPenalty
- cube [3]int32 // cube坐标(x,y,z),用于启发式距离计算
- // 邻居节点信息(优化:使用静态数组替代slice,内联数据)
- neighborNodes [6]*Node // 邻居节点指针
- neighborCosts [6]int32 // 邻居移动代价
- neighborCount int32 // 实际邻居数量(0-6)
- // bool字段移到末尾,减少内存填充
- isWalkable bool // 节点是否可行走
- isOdd bool // 是否奇数列,影响邻居关系和像素坐标
- }
- // NewNode 创建新节点并预计算各种坐标
- // 初始化时就计算好所有坐标,避免寻路时重复计算
- // 坐标系说明:
- // - offset坐标(x,y): 网格坐标,直接用于地图索引
- // - pixel坐标: 像素坐标,用于视觉距离计算(考虑奇偶列偏移)
- // - cube坐标(x,y,z): 三维立方体坐标,用于计算启发式距离,x+y+z=0
- func NewNode(x, y int32, isWalkable bool) *Node {
- n := &Node{
- x: x,
- y: y,
- isWalkable: isWalkable,
- isOdd: (x & 0x1) == 0x1, // 位运算判断奇偶
- }
- // 预计算像素坐标
- // odd-q坐标系:奇数列向上偏移半个六边形高度
- n.pixelX = float64(x) * HEX_WIDTH
- n.pixelY = float64(y) * HEX_HEIGHT
- if n.isOdd {
- n.pixelY -= HEX_HEIGHT / 2 // 奇数列Y坐标上移
- }
- // 优化:预计算整数像素坐标(×1000),避免运行时浮点运算
- n.pixelXInt = int64(n.pixelX * 1000)
- n.pixelYInt = int64(n.pixelY * 1000)
- // 预计算cube坐标(offset -> cube转换)
- // 公式参考: https://www.redblobgames.com/grids/hexagons/#conversions-offset
- n.cube[0] = x // cube.x = offset.x
- n.cube[2] = y - (x-(x&1))/2 // cube.z = offset.y - (offset.x - offset.x&1) / 2
- n.cube[1] = -n.cube[0] - n.cube[2] // cube.y = -cube.x - cube.z (保证x+y+z=0)
- return n
- }
- // AddNeighbor 添加邻居节点
- // 只添加可行走的邻居,距离为移动代价
- // 优化:使用静态数组,避免动态内存分配
- func (p *Node) addNeighbor(node *Node, distance int32) {
- if node != nil && node.isWalkable && p.neighborCount < 6 {
- p.neighborNodes[p.neighborCount] = node
- p.neighborCosts[p.neighborCount] = distance
- p.neighborCount++
- }
- }
- // X 获取节点X坐标
- func (p *Node) X() int32 { return p.x }
- // Y 获取节点Y坐标
- func (p *Node) Y() int32 { return p.y }
- // IsOdd 判断是否在奇数列
- func (p *Node) IsOdd() bool { return p.isOdd }
- // IsEven 判断是否在偶数列
- func (p *Node) IsEven() bool { return !p.isOdd }
- // SetWalkable 设置节点的可行走状态
- // 用于动态修改节点,例如在寻路过程中设置障碍
- func (p *Node) SetWalkable(walkable bool) {
- p.isWalkable = walkable
- }
- // PixelX 获取像素X坐标
- func (p *Node) PixelX() float64 { return p.pixelX }
- // PixelY 获取像素Y坐标
- func (p *Node) PixelY() float64 { return p.pixelY }
- // Cube 获取节点的cube坐标数组
- func (p *Node) Cube() [3]int32 {
- return p.cube
- }
- // String 实现fmt.Stringer接口,方便调试输出
- func (p *Node) String() string {
- return fmt.Sprintf("{%d, %d}", p.x, p.y)
- }
|