widnows游戏编程大师技巧 Draw_Line 的学习
2014-09-29 20:22
591 查看
最近在学习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;
这样我们就又可以将该点作为已知点推算下一点了,因为都是一样的算法,所以可以作循环 。这里我们只需要得出循环算法即可。
代码初成:
根据以上推算,我们已经初步得出了该函数 ,其中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 ;
继续优化代码
情况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;
得出循环:
代码初成:
根据以上推算,我们已经初步得出了该函数 ,其中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 ;
继续优化代码
这里仅仅只是作了dx>dy时的情况分析,dx<dy时,其实也是一样的,无非就是x,y换了下
网上对该算法的解释很多,也很全,我就纯粹看过后练练手,写写自己的理解。
画线条无非就是在屏幕上点“点”, 连续的像素点就是线。我们将画线过程简化为画两个点,假设已知一个点,推出下一个点的位置,以此类推就能画出所有点,最后画成一条线。
先解释下上图,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换了下
相关文章推荐
- 开始利用CSDN做学习笔记,从windows 游戏编程大师技巧和3D游戏编程大师开始
- BLACKBOX.OBJ : error LNK2001: unresolved external symbol _DirectDrawCreateEx@16(游戏编程大师技巧)
- 3D 游戏编程大师技巧系列 读书笔记(-)
- 游戏编程大师技巧—windows程序的基本构造
- Windows 游戏编程大师技巧第四章第4个例子
- Windows 游戏编程大师技巧第四章第6个例子---定时器的使用
- Windows 游戏编程大师技巧第四章第9个例子
- 随便读读:Windows 游戏编程大师技巧 (第二版) 关于BOB
- Windows 游戏编程大师技巧第四章第9个例子
- Windows 游戏编程大师技巧第四章第一个例子
- windows游戏编程技巧大师第二章
- 创建一个主显示表面 (Windows游戏编程大师P210)
- 学习D3D游戏编程的资源
- 学习游戏编程的资料
- 学习FPGA verilog的心得--编程技巧--如何写代码减少逻辑单元的使用数量
- 收集整理了一些开发技巧专题,并汇集成一个编程学习网站
- 2D 游戏编程技巧
- 学习笔记 : Lua 编程技巧
- 游戏编程学习之项目历程
- 内核编程学习笔记(004) 对某某游戏的驱动双开的分析及其学习