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) }