前言
这算是平面游戏里非常常见的一种需求了。
对某个物品或者角色,判定其周围环境的一些属性、交互。
我在开发修仙模拟器的mod时接触过这个算法。
由于这个需求过于常见,单独拎出来。
需求定义&解法
以自身坐标为0. 遍历所有网格。
见上图,定义两个控制量。
从0出发,初始方向为下,步长为1。
每经历两次“进—转”,需要更新步长。现将步长设为2。
又经历两次“进—转”,更新步长为3。
其中转向的规律是相同的,一共只有上下左右四个方向。
想逆时针,下转左,左转上,上转右,右转下。
一个list获得所有的offset(x,y)。
class MY : Object
{
public void GetGridXY(ref int X, ref int Y, g_emGridDir dir)
{
if (dir == g_emGridDir.Left || dir == g_emGridDir.LeftUp || dir == g_emGridDir.LeftDown)
{
X--;
}
if (dir == g_emGridDir.Right || dir == g_emGridDir.RightDown || dir == g_emGridDir.RightUp)
{
X++;
}
if (dir == g_emGridDir.Up || dir == g_emGridDir.LeftUp || dir == g_emGridDir.RightUp)
{
Y++;
}
if (dir == g_emGridDir.Down || dir == g_emGridDir.RightDown || dir == g_emGridDir.LeftDown)
{
Y--;
}
}
private void AroundGrids()
{
int radius = 3;
int numTotalGrids = (radius * 2 + 1) * (radius * 2 + 1);
int stride = 1; //步长
int counter = 2; //变长计数器,总是2
g_emGridDir g_emGridDir = g_emGridDir.Down;
int offsetX = 0;
int offsetY = 0;
List<int[]> listOffsets = new List<int[]>();
listOffsets.Add(new int[]
{
offsetX,
offsetY
});
int j = 1;
while (j < numTotalGrids)
{
while (counter > 0)
{
for (int k = 0; k < stride; k++)
{
GetGridXY(ref offsetX, ref offsetY, g_emGridDir);
listOffsets.Add(new int[]
{
offsetX,
offsetY
});
j++;
if (j >= numTotalGrids)
{
return; //出口
}
}
//改变方向
if (g_emGridDir == g_emGridDir.Right)
{
g_emGridDir = g_emGridDir.Down;
}
else if (g_emGridDir == g_emGridDir.Down)
{
g_emGridDir = g_emGridDir.Left;
}
else if (g_emGridDir == g_emGridDir.Left)
{
g_emGridDir = g_emGridDir.Up;
}
else if (g_emGridDir == g_emGridDir.Up)
{
g_emGridDir = g_emGridDir.Right;
}
counter--; //改变了方向,更新变长计数器
}
//每两次变长计数,步长+1
counter = 2;
stride++;
}
return listOffsets;
}
}
这种写法存的是 offset(x,y)
想直接存全局坐标,只需要改中间的部分就行了。