AI for Game Developers -- Bresenham 算法大揭秘
我在看这本书的英文版时的chapter2部分,看到了此算法,当时很是郁闷,有很多地方都不明白为什么要那么编写代码,到底是什么意思.后来就把那本书丢在那里,没在看了,直到昨天我家也装了宽带,yeah,我立刻马上赶紧去网上搜索了一把这个算法,不过发现都是在宏观上的讲解,没有细化到每一个语句上,我简要看了一下思想,就爬在床上?拿了张纸,画了个图,认真研究了一下,没想到我还真搞明白了,好开心啊,所以今天晚上回来我把我的这个成果写下来,为了还在为这个算法迷茫的人点燃一盏小明灯. :)
把这本书的这个算法写下来,清楚地就不解释了,不清楚的解释下,不过是我自己的理解,对不对,各有所见吧.
void ai_Entity::BuildPathToTarget(void)
{
//初始化开始路径
int nextCol = col; //这个col在画面上就是x
int nextRow = row; //这个row在画面上就是y
//算出delta值(x和y所要走的路程)
int deltaRow = endRow - row;
int deltaCol = endCol - col;
//此段for循环和算法无关,只是清空储存要走的路径的数组
for(currentStep = 0; currentStep < kMaxPathLength; currentStep++)
{
pathRow[currentStep] = -1;
pathCol[currentStep] = -1;
}
currentStep = 0;
//设置目标位置
pathRowTarget = endRow;
pathColTarget = endCol;
//判断走的步长的方向
if(deltaRow < 0) stepRow = -1; else stepRow = 1;
if(deltaCol < 0) stepCol = -1; else stepCol = 1;
//同乘以2等于没乘,步长(stepRow/stepCol)跟此也无关,不知为何*2,保证精度?
deltaRow = abs(deltaRow * 2);
deltaCol = abs(deltaCol * 2);
//记录开始路径
pathRow[currentStep] = nextRow;
pathCol[currentStep] = nextCol;
currentStep++ ;
/*
下面开始 Bresenham algorithm 的主体部分
*/
//这个变量是一个关键点,它主要记录的是把fraction/dx(或fraction/dy)[可以把比值看作斜率,比值>=1时,fraction代表的方向需要走一个stepLength]转换为加减法的标志值.
//fraction其实为delta值较弱的一方的累积值.
int fraction = 0;
//如果x要走的部分比y要长
if(deltaCol > deltaRow)
{
//此处我开始看,怎么也不明白为什么要乘以2,为啥要乘以2呢.
//其实是为了让row(y)方向的路径在此算法开始时就有反映(如果此方向必须有反映的话)
//因为既然deltaRow < deltaCol,所以*2 在 deltaRow >= deltaCol,可以做出立刻改变坐标的行为.
//如果不*2,使 fraction = deltaRow - deltaCol,依然可以达到此算法的目的,只是第一个移动的反映比*2要晚一步.
//坚决不能让 fraciton = 0, 因为一开始此标志作为delta小方是否要移动的标志,会造成走直线时,开始就多走一步,偏离某一方向一步;如果在此基础上改变if(fraction>=0)为if(fraction>0),则会造成在走对角线的路线时,最后在某一方向上缺少一步.
//坚决不能*3或以上,因为*2造成的影响只有一步,如果超过*2,在某些情况则造成不准确的偏离.
fraction = deltaRow * 2 - deltaCol;
while(nextCol!=endCol)
{
//此处为fraction[即斜率的代表] (累积的fraction Row(y)/deltaCol(x) >=1 ) [画图会更直接的表现出来]
if(fraction >= 0)
{
nexRow = nextRow + stepRow;
//削弱Row(y)的积累程度[画图会更直接的表现出来]
fraction = fration - deltaCol;
}//if
nextCol = nextCol + stepCol;
//因为每一次Col都在变化,而fraction Row只有在积累到>=Col的时候才能走一步,这里为积累的动作. [画图会更直接的表现出来]
fraction = fraction + deltaRow;
pathRow[currentStep] = nextRow;
pathCol[currentStep] = nextCol;
currentStep ++;
}//while
}
//此下部分与上面原理相同,故略掉了啊
else
{
fraction = deltaCol*2 - deltaRow;
while(nextRow!=endRow)
{
if(fraction>=0)
{
nextCol = nextCol + stepCol;
fraction = fraction + deltaRow;
}
nextRow = nextRow + stepRow;
fraction = fraction + deltaCol;
pathRow[currentStep] = nextRow;
pathCol[currentStep] = nextCol;
currentStep++;
}//while
}//else
}//ai_Entity