widnows游戏编程大师技巧 Draw_Line 的学习

    最近在学习windows游戏大师编程技巧这本书,看到画线条部分由于作者对具体算法并未详解,导致我看了半天硬是没看懂,后来在网上查了下,原来该算法是赫赫有名的Bresenham算法。好吧,只能怪自己孤陋寡闻了。没办法,只能花时间简单理解下该算法以便继续看我的书。
    网上对该算法的解释很多,也很全,我就纯粹看过后练练手,写写自己的理解。 

 

    画线条无非就是在屏幕上点“点”, 连续的像素点就是线。我们将画线过程简化为画两个点,假设已知一个点,推出下一个点的位置,以此类推就能画出所有点,最后画成一条线。

 

            

先解释下上图,4个黑点为屏幕上的相邻像素点,2个蓝点为点的实际物理位置(由于像素是整数,我们只能点在黑点上,所以会产生误差),E为误差,m为斜率(因为一格为单位1,所以斜率 = m/1 = m )。左下黑点坐标为(x,y),左上为(x,y+1),右下为(x+1,y),右上为(x+1,y+1)。
开始理解该图:假设左边蓝点是已知的,那么,可以知道右边蓝点位置为(x+1,y+E+m)。 当蓝点位置高于单元格一半也就是0.5时,我们将点画在右上黑点,当小于0.5时,点在右下黑点:
    情况1:
    1、当 y+E+m > y+0.5  ==>  E+m>0.5 ==> 2E+2m > 1 时 所画点为(x+1,y+1);
    2、这个时候,我们再来看看该点误差是多少:E=y+E+m-(y+1) ==> E=E+m-1; 
    这样我们就又可以将该点作为已知点推算下一点了,因为都是一样的算法,所以可以作循环 。这里我们只需要得出循环算法即可。
    代码初成:

 

    for(int i=0;i<dx;i++)
    {   
        x+=1; 
        if(2E+2m>1)
        {
            y += 1;
            E=E+m-1;
        } 
        else
        {
               ...;
        }
        DrawPixel(x,y,color);        //画该像素
    } 

   根据以上推算,我们已经初步得出了该函数 ,其中dx为两点之间横坐标的模
    再分析:1、m = dy/dx;(斜率) ==> 2E+2m>1 ==> 2E+2dy/dx > 1 ==>2Edx + 2dy > dx;对于确定的两点作线,dx是定值,
                        设E' = 2Edx得到 E' >dx-2dy;
                  2、E=E+m-1 ==> E=E+dy/dx -1 ==> Edx=Edx+dy-dx ==> 2Edx=2Edx+2dy-2dx ==> E'=E'+2dy-2dx ; 


    继续优化代码

int dx = x1-x0;
        int dy = y1-y0;
        int e = 2*0*dx;   //(E'=2Edx) 因为第一个点是没有误差的,所以E=0;
        for(int i=0;i<dx;i++)
        {   
            x+=1; 
            if(e>(dx-2dy))
            {
                y += 1;
                e += 2dy-2dx;
            } 
            else
            {
                   ...;
            }
            DrawPixel(x,y,color);
        } 

这段代码离宝典上的代码还有点距离,我们继续分析其他情况
    情况2:
    1、当 y+E+m < y+0.5  ==>  E+m<0.5 ==> 2E+2m < 1 时 所画点为(x+1,y);

    2、这个时候,我们再来看看该点误差是多少:E=y+E+m-y ==> E=E+m; 
    得出循环:
    代码初成:

    for(int i=0;i<dx;i++)
    {   
        x+=1; 
        if(2E+2m<1)
        {
            //y=y;  //y不变
            E=E+m;  
        } 
        else
        {
               ...;
        }
        DrawPixel(x,y,color);        //画该像素
    } 

 

    根据以上推算,我们已经初步得出了该函数 ,其中dx为两点之间横坐标的模
    再分析:1、m = dy/dx;(斜率) ==> 2E+2m<1 ==> 2E+2dy/dx < 1 ==>2Edx + 2dy < dx;对于确定的两点作线,dx是定值,
                        设E' = 2Edx得到 E' < dx-2dy;
                  2、E=E+m==> E=E+dy/dx ==> Edx=Edx+dy==> 2Edx=2Edx+2dy ==> E'=E'+2dy ; 


    继续优化代码

        int dx = x1-x0;
        int dy = y1-y0;
        int e = 2*0*dx;   //(E'=2Edx) 因为第一个点是没有误差的,所以E=0;
        for(int i=0;i<dx;i++)
        {   
            x+=1; 
            if(e<(dx-2dy))
            {
                e += 2dy;
            } 
            else
            {
                   ...;
            }
            DrawPixel(x,y,color);        //画该像素
        } 

合并两种情况可得

        int dx = x1-x0;
        int dy = y1-y0;
        int e = 2*0*dx;   //(E'=2Edx) 因为第一个点是没有误差的,所以E=0;
        for(int i=0;i<dx;i++)
        {   
            x+=1; 
            if(e>(dx-2dy))
            {
                y+=1;
                e += 2dy-2dx;
            } 
            else
            {
                  e += 2dy;
            }
           DrawPixel(x,y,color);        //画该像素
        }     

让我们往书中的代码再靠近一步

        int dx = x1-x0;
        int dy = y1-y0;
        int dx2 = dx<<1;//(2*dx)
        int dy2 = dy<<1;//(2*dy)
        int e = 2*0*dx;   //(E'=2Edx) 因为第一个点是没有误差的,所以E=0;
        for(int i=0;i<dx;i++)
        {   
            x+=1; 
            if(e>(dx-dy2))
            {
                y+=1;
                e += dy2-dx2;                // 情况1
            } 
            else
            {
                  e += dy2;                    // 情况2
            }
           DrawPixel(x,y,color);        //画该像素
        }     

情况1和情况2都要加dy2,只不过情况1还要减dx2,所以继续靠近书中代码

        int dx = x1-x0;
        int dy = y1-y0;
        int dx2 = dx<<1;//(2*dx)
        int dy2 = dy<<1;//(2*dy)
        int error = 2*0*dx;   //(E'=2Edx) 因为第一个点是没有误差的,所以E=0;
        for(int i=0;i<dx;i++)
        {   
            x+=1; 
            if(error>(dx-dy2))
            {
                y+=1;
                error-= dx2;                // 情况1
            } 
            error+= dy2; 

           DrawPixel(x,y,color);        //画该像素
        }     


这里仅仅只是作了dx>dy时的情况分析,dx<dy时,其实也是一样的,无非就是x,y换了下

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙语者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值