Unity学习(九)Bresenham快速画直线算法

在游戏中求直线,一般情况会想到通过斜率计算,但是这会涉及到大量的浮点运算,一旦玩家过多,还是会有比较大的消耗。

通常在电脑中画直线,圆形等各种形状并不是真正的直线,因为屏幕的像素非常小,所以肉眼看起来很像直线,其实都是由格子组成的。底层的算法比较多,这里就先学习Bresenham算法,它是光栅化的画直线算法。直线光栅化是指用像素点来模拟直线,如下图:
Unity学习(九)Bresenham快速画直线算法_第1张图片
以上图为例,进行推导模拟:
1.起点为x1,y1时:y轴误差量为e1,e1+m=0.7>0.5,那么e2=e1+m-1=-0.3,y=y1+1=y2。
2.起点为x2,y2时:y轴误差量为e2,e2+m=-0.3+0.7=0.4,那么e3=e2+m=0.4,y=y2。
3.起点为x3,y2时:y轴误差量为e3,e3+m=0.4+0.7=1.1>0.5,那么e4=e3-1=0.1,y=y2+1=y3。
4.起点为x4,y3时:以此类推...知道x轴到达终点。
其中e+m>0.5,可以表示为2*(e+m) > 1
根据起点和终点可以得出x轴增量:dx。将上面的公式都乘以dx。
可以得到:
e= e*dx+m*dx = eps + dy
e= e+m-1 = eps+dy-dx

实现流程:
1.首先判断x,y的增量,谁大就累加谁。(上面是坐标系的左上方向)
2.循环累加x,累加误差量eps+dy
3.判断eps+dy是否大于dx,如果小于不做处理,如果大于等于dx,那么 新的y=y+1新的eps=eps-dx
为了兼容xy坐标系的各个方向,我们可以先算出增量的方向,比如上面如果是坐标系的 左下方向,y=y-1

代码如下:
  1. public bool LinePath(int x1, int y1, int x2, int y2, ref List mpaths)  
  2. {  
  3.     int dx = x2 - x1;  
  4.     int dy = y2 - y1;  
  5.     int ux = (dx > 0) ? 1 : -1; 
  6.     int uy = (dy > 0) ? 1 : -1;
  7.     int x = x1, y = y1, eps;
  8.     x2 += ux; y2 += uy;  
  9.     eps = 0; dx = Mathf.Abs(dx); dy = Mathf.Abs(dy);  
  10.     if (dx > dy)  
  11.     {  
  12.         for (x = x1; x != x2; x += ux)  
  13.         {  
  14.             mpaths.Add(new Vector2(x, y));  
  15.             eps += dy;  
  16.             if ((eps << 1) >= dx)  
  17.             {  
  18.                 y += uy;  
  19.                 eps -= dx;  
  20.             }  
  21.         }  
  22.     }  
  23.     else  
  24.     {  
  25.         for (y = y1; y != y2; y += uy)  
  26.         {  
  27.             mpaths.Add(new Vector2(x, y));  
  28.             eps += dx;  
  29.             if ((eps << 1) >= dy)  
  30.             {  
  31.                 x += ux; eps -= dy;  
  32.             }  
  33.         }  
  34.     }  
  35.     return true;  

你可能感兴趣的:(unity3d,Bresenham,快速画直线算法)