﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-3D图形编程-随笔分类-3D图形编程</title><link>http://www.cppblog.com/nightsky0911/category/19578.html</link><description>学无止尽</description><language>zh-cn</language><lastBuildDate>Thu, 05 Jul 2012 07:02:50 GMT</lastBuildDate><pubDate>Thu, 05 Jul 2012 07:02:50 GMT</pubDate><ttl>60</ttl><item><title>(转) BeginPaint&amp;&amp;GetDc</title><link>http://www.cppblog.com/nightsky0911/archive/2012/07/05/181464.html</link><dc:creator>Nightsky</dc:creator><author>Nightsky</author><pubDate>Thu, 05 Jul 2012 06:20:00 GMT</pubDate><guid>http://www.cppblog.com/nightsky0911/archive/2012/07/05/181464.html</guid><wfw:comment>http://www.cppblog.com/nightsky0911/comments/181464.html</wfw:comment><comments>http://www.cppblog.com/nightsky0911/archive/2012/07/05/181464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/nightsky0911/comments/commentRss/181464.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/nightsky0911/services/trackbacks/181464.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<p>这是个windows编程问题。<br />第一种情况显示出来的字很正常。<br />case WM_PAINT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gdc = BeginPaint (hwnd, &amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextOut (gdc, 0, 0, s, strlen (s));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndPaint (hwnd, &amp;ps);<br />break;<br />第二种情况显示的字不停闪烁。<br />case WM_PAINT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gdc = GetDC (hwnd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextOut (gdc, 0, 0, s, strlen (s));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReleaseDC (hwnd, gdc);<br />break;<br />请教两种函数的作用？<br /></p>
<p>BeginPaint() 和EndPaint() 可以删除消息队列中的WM_PAINT消息，并使无效区域有效。<br />GetDC()和ReleaseDC()并不删除也不能使无效区域有效，因此当程序跳出 WM_PAINT 时 ，无效区域仍然存在。系统就回不断发送WM_PAINT消息，于是程序不断处理WM_PAINT消息。</p>
<p>相当于BeginPaint、EndPaint会告诉GDI内部，这个窗口需要重画的地方已经重画了，这样WM_PAINT处理完返回给系统后，系统不会再重发WM_PAINT，而GetDC没有告诉系统这个窗口需要重画的地方已经画过，在你把程序返回给系统后，系统一直以为通知你的重画命令你还没有乖乖的执行或者执行出错，所以在消息空闲时，它还会不断地发WM_PAINT催促你画，导致程序卡死。</p>
<p>无效区域 ：</p>
<p>无效区域就是指需要重画的区域，无效的意思是：当前内容是旧的，过时的。<br />假设A是新弹出的一个对话框或被激活的现有对话框，A对话框置于原来的活动对话框B前面，造成对话框B的部分或全部被覆盖，当对话框A移开或关闭后，使对话框B原来被覆盖的地方重新可见。那部分被覆盖的地方就称为无效区域。<br />只有当一个窗口消息空闲时，系统才会抽空检查一下这个窗口的无效区域是否为非空（WM_PAINT的优先级是最低的。这也就是为什么系统很忙时窗口和桌面往往会出现变白、刷新不了、留拖拽痕迹等现象的原因），如果非空，系统就发送WM_PAINT。所以一定要用BeginPaint、EndPaint把无效区域设为空，否则WM_PAINT将一直被发送。<br /></p>
<p>为什么WINDOWS要提出无效区域的概念？</p>
<p>这是为了加速。<br />因为BeginPaint和EndPaint用到的设备描述符只会在当前的无效区域内绘画，在有效区域内的绘画会自动被过滤，大家都知道，WIN GDI的绘画速度是比较慢的，所以能节省一个象素就节省一个，不用吝啬，这样可以有效加快绘画速度。<br />可见BeginPaint、EndPaint是比较&#8220;被动&#8221;的，只在窗口新建时和被摧残时才重画。<br />而GetDC用于主动绘制，只要你指到哪，它就打到哪。它不加判断就都画上去，无效区域跟它没关系。对话框没被覆盖没被摧残，它很健康，系统没要求它重画，但开发者有些情况下需要它主动重画：比如一个定时换外观的窗口，这时候就要在WM_TIMER处理代码用GetDC。这时候再用BeginPaint、EndPaint的话，会因为无效区域为空，所有绘画操作都将被过滤掉。</p>
<p>eg:</p>
<p>PAINTSTRUCT ps;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hdc = BeginPaint(hWnd,&amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Create a DC that matches the device<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hdcMem = CreateCompatibleDC(hdc);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Load the bitmap<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Select the bitmap into to the compatible device context<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get the bitmap dimensions from the bitmap<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BITMAP bmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetObject(hBmp,sizeof(BITMAP),&amp;bmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get the window area<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RECT rc;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetClientRect(hWnd,&amp;rc);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Copy the bitmap image from the memory DC to the screen DC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Restore original bitmap selection and destroy the memory DC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem,hOldSel);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hdcMem);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndPaint(hWnd,&amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br /></p>
<p>/////////////////////////</p>
<p>下面是更加详细的介绍</p>
<p>&nbsp;</p>
<p>//========================================================================<br />//TITLE:<br />//&nbsp;&nbsp;&nbsp;&nbsp; EVC绘制位图--BeginPaint()与GetDC()的区别<br />//AUTHOR:<br />//&nbsp;&nbsp;&nbsp;&nbsp; norains<br />//DATE:<br />//&nbsp;&nbsp;&nbsp;&nbsp; Tuesday&nbsp;&nbsp; 29-August-2006<br />//========================================================================<br />1.BeginPaint()和GetDC()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在EVC中绘制位图比较方便,有不少现成的函数可供调用,我们所要注意的只是BeginPaint()或GetDC()的使用即可.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为代码比较简单,所以不做更多解释.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是消息循环函数:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch(wMsg)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_PAINT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnPaintMainWnd(hWnd,wMsg,wParam,lParam);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return DefWindowProc(hWnd,wMsg,wParam,lParam);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 响应WM_PAINT消息的函数,在这里进行位图的绘制:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT OnPaintMainWnd(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PAINTSTRUCT ps;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hdc = BeginPaint(hWnd,&amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Create a DC that matches the device<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hdcMem = CreateCompatibleDC(hdc);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Load the bitmap<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Select the bitmap into to the compatible device context<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get the bitmap dimensions from the bitmap<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BITMAP bmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetObject(hBmp,sizeof(BITMAP),&amp;bmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get the window area<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RECT rc;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetClientRect(hWnd,&amp;rc);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Copy the bitmap image from the memory DC to the screen DC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Restore original bitmap selection and destroy the memory DC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem,hOldSel);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hdcMem);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndPaint(hWnd,&amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们都知道BeginPaint()和EndPaint()需要配套使用,并且这两个函数也只能用在WM_PAINT消息的相应函数当中.如果我们在WM_PAINT的响应函数中将以上两个绘制函数相应替换为GetDC()和ReleaseDC()会有什么结果呢?<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 即:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HDC hdc = BeginPaint(hWnd,&amp;ps);&nbsp;&nbsp;&nbsp;&nbsp; --&gt;&nbsp;&nbsp;&nbsp; HDC hdc = GetDC(hWnd);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EndPaint(hWnd,&amp;ps);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;&nbsp;&nbsp;&nbsp; ReleaseDC(hWnd,hdc);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编译并运行程序,我们发现窗口一片空白,好像没有绘制位图.但其实不尽然,我们采用单步调试,可以发现其实位图已经绘制出来,只不过又被背景颜色抹掉了.由此可知,如果需要使用GetDC(),我们对消息循环函数必须要加上对WM_ERASEBKGND的处理:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch(wMsg)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_PAINT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnPaintMainWnd(hWnd,wMsg,wParam,lParam);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_ERASEBKGND&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return DefWindowProc(hWnd,wMsg,wParam,lParam);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至此我们可以看出BeginPaint(),EndPaint()和GetDC(),ReleaseDC()的区别.前一对只能用在WM_PAINT响应函数中,并且绘制背景时不会被抹掉;后一对随处可用,但如果用在WM_PAINT响应函数中,那么接下来将会被WM_ERASEBKGND消息的响应函数的背景绘制给抹掉.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />2.绘图闪烁问题&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; 有时候我们大量绘制屏幕时,可能会出现屏幕闪烁问题,这时候可以采用双缓冲的做法.步骤首先是创建一个内存DC,然后往内存DC中绘图,最后把内存DC的内容复制到显示DC中,完成绘制.具体过程并不复杂,结合代码来说明一下.<br />&nbsp;&nbsp;&nbsp;&nbsp; PS:这段代码也是相应WM_PAINT 消息的.<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; PAINTSTRUCT ps;<br />&nbsp;&nbsp;&nbsp;&nbsp; HDC hdc;<br />&nbsp;&nbsp;&nbsp;&nbsp; //获取屏幕显示DC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; hdc = BeginPaint (hWnd, &amp;ps);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; //创建内存DC<br />&nbsp;&nbsp;&nbsp;&nbsp; HDC hdcMem = CreateCompatibleDC(hdc);<br />&nbsp;&nbsp;&nbsp;&nbsp; //创建一个bmp内存空间<br />&nbsp;&nbsp;&nbsp;&nbsp; HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);<br />&nbsp;&nbsp;&nbsp;&nbsp; //将bmp内存空间分配给内存DC<br />&nbsp;&nbsp;&nbsp;&nbsp; HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; //这是使用者需要绘制的画面,全部往内存DC绘制<br />&nbsp;&nbsp;&nbsp;&nbsp; Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);<br />&nbsp;&nbsp;&nbsp;&nbsp; DrawMenuButton(hdcMem);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; //将内存DC的内容复制到屏幕显示DC中,完成显示<br />&nbsp;&nbsp;&nbsp;&nbsp; BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY);<br />&nbsp;&nbsp;&nbsp;&nbsp; //清除资源<br />&nbsp;&nbsp;&nbsp;&nbsp; SelectObject(hdcMem,hOldSel);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; DeleteDC(hdcMem);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; EndPaint(hWnd,&amp;ps);</p></div> <img src ="http://www.cppblog.com/nightsky0911/aggbug/181464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/nightsky0911/" target="_blank">Nightsky</a> 2012-07-05 14:20 <a href="http://www.cppblog.com/nightsky0911/archive/2012/07/05/181464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何学好3D游戏引擎编程</title><link>http://www.cppblog.com/nightsky0911/archive/2012/07/02/181140.html</link><dc:creator>Nightsky</dc:creator><author>Nightsky</author><pubDate>Mon, 02 Jul 2012 06:35:00 GMT</pubDate><guid>http://www.cppblog.com/nightsky0911/archive/2012/07/02/181140.html</guid><wfw:comment>http://www.cppblog.com/nightsky0911/comments/181140.html</wfw:comment><comments>http://www.cppblog.com/nightsky0911/archive/2012/07/02/181140.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/nightsky0911/comments/commentRss/181140.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/nightsky0911/services/trackbacks/181140.html</trackback:ping><description><![CDATA[<div id="read_tpc" class="f14">
<div align="right"><span style="color: #ff0000"><font size="3"><span style="font-size: 14pt">此文为转载，但是值得一看。</span></font></span><br /></div><font size="3"><span style="font-size: 14pt">此篇文章献给那些为了</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_5" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=游戏',this.id)">游戏</span><span style="font-size: 14pt">编程不怕困难的热血青年，它的神秘要我永远不间断的去挑战自我，超越自我，这样才能攀登到游戏技术的最高峰&nbsp; &nbsp;</span><br /></font>
<div align="right"><font size="3"><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&#8212;&#8212;阿哲VS自己 QQ79134054多希望大家一起交流与沟通</span><br /></font></div><font size="3"><span style="font-size: 14pt">这篇文章是我一年半前，找工作时候写的，那时是发到学校的BBS上。现在我工作了，想法和以前也有不同，但对</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_1" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=游戏引擎',this.id)">游戏<span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_4" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=引擎',this.id)">引擎</span></span><span style="font-size: 14pt">编程理念还是基本差不多。在我没遇到U3以前，一直研究WILDMAGIC，可以说是GAMEBRYO的前身吧，他们基本框架都差不多，是完全面向对象，代码容易读，但它发展存在严重的弊端，这个也是它为什么不是牛B引擎的原因。但从渲染和动画方面来看，U3的 MATERIAL TREE 和 ANIM TREEE 是2个飞跃的，当我对我自己引擎渲染材质和光照一筹莫展的时候，MATERIAL TREE带来的希望。对比 zfx (wildmagic)gamebryo 和ogre 还有U3，各有优缺点，而且你可以看到一个引擎发展，从一个以多边形为渲染单元，变成以mesh做为渲染单元（现在很少有引擎场景管理分割多边形来做的 我始终喜欢zfx引擎，它是00-02之间的引擎，完全让你可以理解那时候显卡不是很强的时候，一个引擎应该具备的特征。对于架构来讲，(wildmagic)gamebryo 和ogre 做的很好，u3的特点就是架构乱，没有什么可读性的技术文档，研究起来十分吃力。做为一个商业引擎，对于渲染方面，我认为(wildmagic)gamebryo 输给了ogre，框架设计还有弊端，ogre确实是一个好引擎。而U3对于渲染过程，光照，阴影，就是一帧的渲染过程，处理的十分得当。动态生成shader是一个引擎的发展的必然趋势，而往往动态生成最多的，也就是材质和光照，它们不能分开，分开谈无意义，MATERIAL TREE 我始终认为是个太好的想法了，任何特效不需要程序员过多参与，美术可以搞定一切，什么水，反射，折射，这些效果，编写起来易如反掌，还可以实时光看效果。其他动态生成，也就是根据配置不同，来做处理，动态编译shader弊端太大，不能做到所有，而且不灵活，如果动态生成和动态编译合起来，简直牛B透顶了。现在我的引擎已经有了MATERIAL TREE这个功能，ANIM TREEE在制作中。</span><br /><span style="font-size: 14pt">这里面我重点谈的是图形方面，略带些动画方面，一个引擎最基本的是内核，包含内存管理，文件读写，资源管理等等吧，也十分重要，我的引擎这些写的都很简单,基本都是wildmagic里面的。</span><br /><span style="font-size: 14pt">我总结</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_7" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=3D引擎',this.id)">3D引擎</span><span style="font-size: 14pt">编程的4个阶段</span><br /><span style="font-size: 14pt">第一阶段是了解3D原理和数学基础，大学里面学的线性代数，概率统计和高等数学完全足够，在3D中都有充分体现。最好自己能做一个软引擎，这样整个3D流水线自己完全可以掌控，然后在学DX之类的API很容易。</span><br /><span style="font-size: 14pt">第二阶段不要看引擎，还是应该以实现各种效果和基本算法为基础，包括各种图形特效，场景管理，剪裁算法，各种动画算法，等等，所有那些单一的算法，如果这些都不是了解很好，那么做引擎时引擎框架的接口也不会设计好！再添加这些算法和效果时 会很困难，效率也不会很高。</span><br /><span style="font-size: 14pt">第三阶段，就是看大量的引擎，对引擎有很深刻的概念，3D引擎只是引擎的一部分，引擎主要是框架，如果框架搭建好了，那么引擎的效率是很显著的，其他底层细节优化，也会有明显的优势体现。</span><br /><span style="font-size: 14pt">第四阶段，再好的引擎没有成功的游戏支撑都是白费，你不仅仅是做引擎，而是做的有</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_8" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=开发',this.id)">开发</span><span style="font-size: 14pt">价值的引擎，可以很好的为游戏服务的引擎。</span><br /><span style="font-size: 14pt">下面这段话写于一年半前～～</span><br /><br /><br /><span style="font-size: 14pt">前言</span></font>&nbsp;&nbsp;<font size="3"><br /><span style="font-size: 14pt">本人不才，姑且以自己经验来谈如何学游戏编程，这个话题我酝酿了很久，它确实很难写，因为我也不是资深高手，才刚刚登堂入室，游戏编程大师功力一般都十几年左右，所以让我这样的小卒写的深入浅出更何谈容易，错误出现并不奇怪，高手见笑也在所难免，请大家指正，我会欣然笑纳。但这几年走过的路，让我知道这么学是正确的，大体过程经验告诉我，这样做是对的，高手的指引告诉我，这样做是对的。</span><br /><span style="font-size: 14pt">这篇文章主要讨论如何学习游戏图形编程和游戏引擎编程，告诉没有接触游戏过编程或者现在关于怎么学好游戏编程还迷惑的PEOPLE所要走的方向，完全抛开技术和代码实现进行谈论。至于游戏逻辑这几年重点没有发到这个上面上，很难总结。</span><br /><span style="font-size: 14pt">经验的限制，对于如何编写一个好的引擎（至于&#8220;好&#8221;这个词都是相对而言，能做的满意就是我所期望的），至今为止我还没有这个能力，但我相信经过我的努力，不久的将来，我会实现这个愿望，因为我的一个愿望就是实现一个好的引擎。</span><br /><br /><span style="font-size: 14pt">我从下面几个方面来说明如果学习，记住只是如何学习，要想学好就要靠你自己。</span></font> <font size="3"><br /><span style="font-size: 14pt">1。 你真的喜欢游戏编程吗？</span><br /><span style="font-size: 14pt">2。 要了解游戏编程</span><br /><span style="font-size: 14pt">3。 学会读书，自学与思考，交流与合作</span><br /><span style="font-size: 14pt">4。 游戏编程需要的基础知识</span><br /><span style="font-size: 14pt">5。 2D游戏编程</span><br /><span style="font-size: 14pt">6。 3D游戏编程</span><br /><span style="font-size: 14pt">7。 游戏引擎编程</span><br /><span style="font-size: 14pt">8。浅谈游戏物理和AI</span><br /><br /><br /><span style="font-size: 14pt">一。游戏编程，你真的爱她吗？</span></font><font size="3"><br /><span style="font-size: 14pt">当你听完我的介绍后，你就要决定游戏编程是否适合你。</span><br /><span style="font-size: 14pt">游戏编程可简单可复杂，简单的2D 《蛇吃豆》，复杂的现在流行的3D游戏。咱们不说简单的，因为你不想学习游戏编程就为了做一个简单的游戏。确实每个人对他所向往的东西都想彻底了解清楚，可是我给你的第一个警告，复杂的3D游戏，复杂到难以想象。</span><br /><br /><span style="font-size: 14pt">1 你思想需要改变吗？</span></font><font size="3"><br /><br /><span style="font-size: 14pt">打开话题，游戏是一个结合体，她是一个音乐，美术，技术，创意相结合的艺术品，你要用艺术的眼光去欣赏的，因为好的游戏是用艺术的眼光来设计，除了某国的</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_6" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=网游',this.id)">网游</span><span style="font-size: 14pt">不算外，很多经典的游戏流芳百世，成为真正游戏玩家佳话。</span></font><font size="3"><br /><span style="font-size: 14pt">中国的游戏为什么这么落后，你要联想下，当年中国为什么会被八国联军所侵略。腐朽的思想是根本原因，从而导致了腐朽的社会制度。游戏行业也是这样，看待游戏的中国人，始终带着眼镜，用腐朽思想看待游戏，所以现在出现腐朽的游戏行业，导致中国游戏发展缓慢，有人曾经说中国游戏不久就赶超日本和美国，我认为是扯淡，而且不是一般的扯淡，具体原因后面我会详细说明。</span><br /><span style="font-size: 14pt">从小的时候，国外的电子游戏产品就跑进了我的空间，废寝忘食的玩个没玩，因为耽误学习，从此电子游戏被老师和家长全部封杀，任何事物都有利有弊，鲁迅的《拿来主义》曾说过&#8220;去其糟粕，取其精华&#8221;。在中国，电子游戏被视为过街老鼠。确实要承认电子游戏有负面影响，但这些负面影响是谁产生的，本质上是我们自己，最后本来是精华的东西从我们身边擦肩而过，从小霸王以后的国外游戏机没有任何仿造，导致了游戏机技术从此断代，现在却又想起来赶超。</span><br /><span style="font-size: 14pt">而现在，国人知道努力了，国家看到有钱可赚开始支持了，腐朽的游戏思想却还在蔓延，网络游戏就是这样环境下成长的新生儿，国内网络游戏每年要大批量生产，但存活的基本没几个。不能否定，没有利益的事情没人干，但你还不能否定，有些事情即使没有利益，但还是有人干，哪怕知道自己并不能得到什么。国内的人，很少是第2种人，他们把游戏做为赚钱工具，垃圾游戏隔三差五的纷纷涌出。相比来讲，我只拿日本举例子，虽然小日本和咱们有愁，但我们不得不承认小日本在游戏这方面思想层次完完全全超越我们，他们有严格游戏教育背景，他们做一款游戏，要按照严格的流程，从设计到编程，以至最后的测试，都有着干一行敬一行的精神，否则《生化危机》这样游戏你是永远看不到的。</span><br /><span style="font-size: 14pt">所以你要改变自己的思想，游戏是一种艺术品，你要有一种艺术境界来去欣赏她。</span><br /><br /><span style="font-size: 14pt">2 你有毅力爱她爱到底吗？</span></font><font size="3"><br /><br /><span style="font-size: 14pt">也许我上面的话，你还能接受，残酷的在下面，以我的经验告诉我，如果你编程和游戏理论起步是零，你要对游戏编程达到略有小成的水平最少要4到5年，我比较蠢，花了6年。这6年来，几乎每天平均学习4-5个小时左右，当然假期都要算上。头3年半基本学习计算机基础知识，包括数学，数据结构，计算机体系结构，</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_2" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=人工智能',this.id)">人工智能</span><span style="font-size: 14pt">，汇编，编译原理，操作系统，网络，软件工程，离散数学，算法分析。我们大学4年基本就学这东西，这些都是基础，游戏编程都需要，还有一个就高等物理我没有学，导致我现在对于一些物理微积分方程很难理解，当然这里并不一定是问题，只要你肯努力，没有学不会的。完全把这些学好，花4年时间真的不容易。我曾经抱怨自己没保研而痛苦的经历考研，现在我却认为是值得的，我很难有时间在集中精力的复习这些专业课了，尤其是数学。</span></font><font size="3"><br /><span style="font-size: 14pt">在游戏编程中，上面的基本知识都可以用到，所以我说游戏编程很复杂一点不假。就拿游戏中最难的部分&#8212;&#8212;一个好的游戏引擎来说（这里说的好引擎），世界上能把她做出来的人很少，中国更是寥寥无几。</span><br /><span style="font-size: 14pt">上面只是理论基础，要走进游戏编程最基本的。过硬的编程技能更是需要的，其实这些理论学习可以和编程相结合，在编程中学习理论，为了学习理论而增长编程经验。</span><br /><span style="font-size: 14pt">有了基础，你才能进一步学习游戏编程，2D游戏和3D游戏理论都要学，这又要花费很长时间，这个是我下面要详细说的。</span><br /><span style="font-size: 14pt">看完我写的，你可能心惊胆寒，所以你要爱她，深深的爱她，否则你承受痛苦的时候享受不到暗含的乐趣。</span><br /><br /><span style="font-size: 14pt">3 爱她请从游戏开始。</span></font><font size="3"><br /><br /><span style="font-size: 14pt">很多人可能不解，游戏编程为什么要从游戏开始，玩游戏时，有很多潜移默化的东西影响着我们编写游戏程序，很多灵感确实从游戏中得来。一般的游戏编程高手，都是从小由于游戏对他们巨大吸引，从而走上游戏道路，虽然不是绝对，但按统计学角度讲可以说是一个事实。一个不爱玩游戏的人，爱上游戏编程的几率是很小的。其实很多人小的时候都爱玩游戏，他们都是从游戏厅张大，只有一少部分，走向了</span><span style="border-bottom: #fa891b 1px solid; font-size: 14pt; cursor: pointer" id="rlt_3" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=游戏开发',this.id)">游戏开发</span><span style="font-size: 14pt">这个行业，他们之间有着明显不同，走向游戏开发的人，是真的被游戏背后那种神秘东西所吸引，并想要揭开它，而另一些人，则是完全迎合了游戏开发的需要&#8212;&#8212;玩的高兴。</span></font><font size="3"><br /><span style="font-size: 14pt">我想说的是，一个游戏编程高手，必定是一个游戏玩家，他们都是从玩游戏而爱上游戏，从而走上游戏编程道路。这条路充满了荆棘，不是一般人能走到最后的。所以你一定要爱她！</span><br /><span style="font-size: 14pt">当然任何事情都不绝对的，你可能就是那不爱游戏但爱游戏编程（或者和游戏性无关的那部分编程）小概率的人。</span><br /><br /><span style="font-size: 14pt">二。游戏编程，你真的了解她吗？</span></font><font size="3"><br /><br /><span style="font-size: 14pt">游戏编程，这个概念包含了很多深层次的东西。</span></font><font size="3"><br /><br /><span style="font-size: 14pt">1.广义上，我给的定义是，游戏引擎开发和游戏逻辑开发。</span></font><font size="3"><br /><br /><span style="font-size: 14pt">游戏逻辑开发是集中力量只开发游戏中剧情部分，你只需要做的是什么时候显示什么，什么时候放出什么声音，什么时候通过网络传输什么数据，什么时候这个物体或者人物做什么动作。至于底层怎么显示，声音如何处理，网络如何传输，物体动作怎么实现的，你不用关心，关心这些的是游戏引擎。所以说游戏引擎负责技术方面，而游戏逻辑负责游戏文化内涵。</span></font><font size="3"><br /><span style="font-size: 14pt">成功的游戏是以好的游戏逻辑为基础的，而游戏引擎并不是成功游戏主要条件，但好的游戏配上好的游戏引擎，确实会给人一种震撼，相比同样的游戏逻辑，好的游戏引擎显示效果会给人一种全新视觉和听觉感受。</span><br /><span style="font-size: 14pt">至于游戏逻辑我不想过多解释，但并不是说游戏逻辑简单，游戏逻辑也可以复杂的要命，这取决与游戏复杂程度和游戏引擎与这个游戏的关联程度。为了解释这句话，我不得不从游戏引擎解释开始。</span><br /><span style="font-size: 14pt">早期的游戏是没有游戏引擎这个概念，都是一个游戏一套代码，随着游戏越来越多，大家发现开发有些游戏中，有很多可重用的代码，逐渐把这些重用代码封状起来，这就是早期的引擎。对于引擎没有明确的概念，只有好坏和适应程度之分，所谓的好坏，就是引擎支持功能和显示特性等是否strong,而适应程度是指一个引擎是否适合开发这个游戏，开发这个游戏是否要自己再编写一些额外的代码。</span><br /><span style="font-size: 14pt">我举个例子</span><br /><span style="font-size: 14pt">如果我用开发混斗罗的引擎（假如它有引擎）来开发RPG，和开发RPG游戏的&#8220;RPG游戏开发大师&#8221;相比，我们还要做很多工作，才能完成玩法功能一样的游戏。</span><br /><span style="font-size: 14pt">所以说很难有明确的界限划分这一堆代码是否是游戏引擎，但游戏引擎的任务是不用质疑的，它的任务就是尽量不用负责底层处理，而专心到游戏逻辑上来。</span><br /><br /><span style="font-size: 14pt">2.从狭义上分，我只分解游戏引擎部分，基本包括(1)游戏图形引擎(2)声音引擎(3)网络引擎(4)脚本引擎(5)GUI(6)人工智能引擎(7)物理引擎。</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">(6)(7)两个不是必须的，而前5个是一个好的游戏引擎要基本具备的，其实每个游戏引擎中都具备物理引擎，只不过很多游戏对于物理要求不是很高，所以就集成到了图形引擎中或者游戏逻辑中。</span></font><font size="3"><br /><span style="font-size: 14pt">图形引擎是引擎中最难的，它基本要处理游戏引擎中70-80%的工作量，它的主要任务是负责图形高效显示，包括速度和精度。后面我会集中并详细解释。至于声音和网络引擎大家通过字面就可以知道它干什么。本人对声音处理和网络传输知道甚少，说出来只能误人子弟。</span><br /><br /><span style="font-size: 14pt">至于脚本我还略有研究，我想解释下什么是脚本，游戏中为什么用脚本。脚本有时很难给出一个定义，但大家都知道那些是脚本语言，我给出的解释是用软件</span></font> <font size="3"><span style="font-size: 14pt">CPU(虚拟CPU)来运行的编程语言就是脚本语言，软件CPU和所说硬件CPU是对立的，也就是说脚本运行与否先是关联到这个虚拟CPU，在虚拟CPU上运行，然后再又映射到真正CPU，来真正运行。这个过程很抽象，我觉2个例子，第一个就是JAVA语言，它有一个虚拟机，这个虚拟机就是软件CPU。再举一个例子，我现在要编写这样一个指令、</span><br /><span style="font-size: 14pt">PRINT S&nbsp;&nbsp;这个指令表示打印S</span><br /><span style="font-size: 14pt">S代表一个万能类型。</span><br /><span style="font-size: 14pt">为了实现这个指令，你首先要有一个函数来负责处理打印</span><br /><span style="font-size: 14pt">比如是这样的函数</span><br /><span style="font-size: 14pt">void print(S)</span><br /><span style="font-size: 14pt">{</span><br /><span style="font-size: 14pt">&nbsp; &nbsp; cout&lt;&lt;S;</span><br /><span style="font-size: 14pt">}</span><br /><span style="font-size: 14pt">这里只是伪代码，只是表示这个意思。</span><br /><span style="font-size: 14pt">你首先要找出PRINT这个单词，读入到一个buffer1，然后把参数读入buffer2</span><br /><span style="font-size: 14pt">if(buffer1 == PRINT)</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;print(buffer2);</span><br /><span style="font-size: 14pt">这里段代码其实就是一个软件CPU，它负责虚拟运行PRINT S&nbsp;&nbsp;这个指令。</span><br /><br /><span style="font-size: 14pt">那么游戏中为什么要用脚本呢！最简单解释就是灵活性好。拿一个RPG游戏例子来说，游戏中有大量物品，每个物品有大量的属性，如果我把这些属性值直接写到游戏中，每一个小小的改变就要编译整个游戏，花费很多时间，灵活性很差。</span></font> <font size="3"><br /><span style="font-size: 14pt">如果我把这些写到一个文件中，用脚本语言来编辑，只需要编译脚本文件就可以了，当然如果你脚本是解释型的语言，不用编译直接可以运行。</span><br /><span style="font-size: 14pt">当然脚本还有很多好处，主要目的还是方便性和灵活性。</span><br /><span style="font-size: 14pt">其实GUI(图形用户接口)是一个重要部分。3D游戏中，出现的是大量的3D模型，这些模型是先用文件的形式存放好的，而文件里面包括的是3D数据和这些数据的组织方式。</span><br /><span style="font-size: 14pt">至于数据怎么组织是你引擎要规定好的，这样也方便读取，最后把3D数据加载到内存。现在问题是3D数据上，我们怎么能有效的得到这些3D模型的数据，手工写进文本里？我靠，那是奴隶社会，SB的做法。我想你不会这么做。人类很聪明，这就是为什么人把其他动物关进笼子里，而不是其他动物把人关进笼子里的原因。既然我们很聪明，就要想一个办法快速的定义3D数据，然后保存成文件。这样一个3D编辑器就产生了。3D编辑器就是类似于3DMAX那种，但引擎中的编辑器是有特殊目的的，使用者要按照引擎指定要求编辑3D数据，这样引擎高效的显示和处理数据比较容易，至于3D数据是怎么组织的，是一个设计上的问题，由你引擎来决定，设计好坏，决定你引擎加载数据是否容易，关系到最后渲染。所以一般好的游戏引擎都有自己GUI，但你也可以用3DMAX这样的软件，然后读3DMAX文件变成自己可以利用的数据形式。</span><br /><span style="font-size: 14pt">说到这里，不知道上面的概念大家是否理解，我想如果你没接触过引擎，可能真的不理解。其实我很难用简短的语言把这么复杂的问题说清楚，如果有一天你把3D学的融会贯通，你发现我说的是对的。我不知道大家是否发现一个共性的问题，有时你读一本书，无论你怎么认真把它看完一遍，你都很难掌握里面的知识，当你再认真看第二遍的时候，你突然觉得这本书没有第一次看那么晦涩难懂。有些知识都是前后呼应的，它们之间相互联系，要想完整的理解它们缺一不可。游戏编程的知识也是这样。我前面介绍的如果你看懂了，那你perfect，如果你没有看懂，也不要灰心，这里介绍的只是一个大纲，让你对游戏编程有一个了解，最基础层面的了解。</span><br /><br /><span style="font-size: 14pt">三。游戏编程，你准备好了吗？</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">这个部分讲解如果你想开始游戏编程应该具备那些基础知识，这样你才能接下来游戏编程学习，当然下面的有些知识，我开始学习游戏编程时，也不是都具备，但这些知识都是很容易学的知识，如果你基础好，在游戏编程中随时学就可以，不耽误你学习游戏编程的进度。我在这段最后会指出那些是必须掌握的，因为这些知识如果你在游戏编程时学习再学，时间上真的不允许。</span></font> <font size="3"><br /><br /><br /><span style="font-size: 14pt">1。书，永远是你的好朋友！</span></font>&nbsp;&nbsp;<font size="3"><br /><span style="font-size: 14pt">书，是你了解她最直接途径，当然我说的书还包括所有游戏编程资料。书，有好有坏，想要深刻了解她，你必须挑选精妙的好书，而且还有循序渐进的，合理次序的去读它们。游戏编程书籍大量风起云涌的出现是在2000年以后，当然2000以前也有，只是很少一部分，从2000或者以前开始就研究3D游戏的中国大哥们，现在可以说是现在中国游戏行业的鼎梁支柱。现在出版有关游戏方面的书籍大约有200左右本，中国人自己原著的书几乎没有，大多数都是翻译国外的，就有几本翻译的质量很好（翻译大哥大姐确实很辛苦，我承认这点，但拜托你们翻译前要看懂再翻译，否则望文生义，不如让我们自己看英文原版）要么自己写的也是东挪西凑的，写出来估计是想骗钱，谁叫中国人这么老实，这么好欺负了。其中大部分书籍是3D游戏的，3D游戏确实要比2D游戏难一个数量级别，如果你足够聪明，其实这些书看个几十本，写出一个在中国可以立足的3D引擎足够了。但好象这样聪明的人真的很少，有黄金的这个地方大家都知道，可是前往这块宝地的道路太荆棘，很少有人走下来。</span><br /><span style="font-size: 14pt">书，大家从出生时就接触，学会读书，这四个字，很少有人能领会，你看一本书，要么否定，要么肯定，如果你还是很迷糊，要么是书写的不好，要么就是你知识水平层次有限，要么就是你根本没学会读书。我在这里只说一句话&#8220;要读好书，思而不学则罔，学而不思则怠，温故而知新&#8221;，我想高手很容易体会这句话。</span><br /><span style="font-size: 14pt">想要学好游戏编程，学会读书是你要掌握的，也是你获取知识最快的途径，开始时，建议还是读一些中文的游戏编程书，因为游戏编程中充斥大量术语和名词，没有任何游戏编程概念的人，直接看英文，即使你是老外，我估计你看一会就会爬在书上，眼皮一关，口水把它淹没了。</span><br /><span style="font-size: 14pt">看书后，代码一定要仔细读，而且对于初学者一定要亲自去实现，这样你才能加深理解，有时看书看不懂，一看代码就全明白了。&#8220;纸上得来终觉浅，觉知此事必躬行&#8221;，我始终坚信这句话，只有你经历了，你才能感受，就象你没有失去过，就不会知道珍惜是什么东西。</span><br /><span style="font-size: 14pt">我相信既然你都看到这里了，就应该知道我上面为什么给你打好的警钟。看完书，就要写代码，最好不要一味的效仿，要有你自己的独道之处，这样才说明你认真考虑了这个问题，你也真正了解了，这个问题是什么，应该怎么解决，怎么解决最有效果。</span><br /><span style="font-size: 14pt">E文书，以后就要是你老婆（同性恋除外），天天都要见面，除非你离婚了，也就是游戏编程这个爱情你不想要了，你提前离开了这个努力走到最后才能见到美好果实的幸福家庭。中文翻译一般都很慢，中文翻译出来，国外这个技术基本过时了，而且有能力翻译的人本来就少，有时间干这事的说他有病，也不足为奇，因为翻译一本太浪费时间了。所以要适应去看E文，现在没钱，就看电子的，很多国外新书，没有电子的，但电子的够我们初学的人玩很长时间，等有钱了，就直接去买国外正中的洋版，然后弄到家中，天天啃，工作时也啃，人家都会说你很有激情的。看电子的如果闲麻烦，就打印下来，打印下来还是花不了几个钢币的，和买一本中文差不多（大家不要哭穷，一本好书100元我认为很值得，里面技术如果你掌握了，你想想，大把大把的票子就进你口袋里，很多人买来不看，天天还抱怨书贵。）</span><br /><span style="font-size: 14pt">这几年来，我读过很多游戏编程方面的书，中文的基本都读过了，现在我一直在读E文书，有时到觉得看中文有些不适应，还有好多好书，我还没有读。读E文书时，如果没读懂，自己一定要去网上查查相关资料，然后集中精力把它弄懂，现在很少有看不懂的E文游戏编程书（知道我6级没过的，别用砖仍我），有些还是看不懂，确实自己水平有限，但不是因为英语问题，关于高深而复杂数学问题，即使翻译成中文，我也很难看明白。</span><br /><span style="font-size: 14pt">我在后面会把所有好的游戏编程书籍都列出来，告诉大家那些可以买到，那些只有电子的。不好的书，我就不列出来了，只会浪费大家以后的时间。</span><br /><span style="font-size: 14pt">2。游戏编程所需要的基础知识</span><br /><br /><span style="font-size: 14pt">我这里介绍下要做一个好的，称职的，游戏程序员所需要。学习就和盖楼一样，要想上层建筑牢固，你就要有坚实的基础，我这里介绍的基础是你从事游戏编程最基础，基础的不能再基础的东西。</span></font> <font size="3"><br /><span style="font-size: 14pt">2。1 数学</span><br /><span style="font-size: 14pt">数学是游戏中支柱，没有了它，任何都不要谈，在你编写你游戏的时候，你就会知道，世界抽象成一堆数学是多么的神奇，突然你会觉得以前枯燥无味的数学现在是一顿大餐，但这个是霸王餐。国外人写关于引擎方面书的人，都可以说是数学高手，他们理论和实践都很厉害，让我崇拜的不得了。大学里是你学好数学的最好机会，一定要弄明白它的现实意义，任何理论都不是凭空出来的，它一定有现实基础，这个现实基础，就可以帮助你很好理解这个理论。</span><br /><span style="font-size: 14pt">2。1。1高等数学&#8212;&#8212;微积分理论</span><br /><span style="font-size: 14pt">在游戏引擎中，很多游戏特效都是通过微积分方程来解得的，高度仿真是现在游戏的追求，真实感越强就需要越多的计算量。极限，一元微积分，多元微积分，级数，微分方程等等在游戏图形图象和物理上都有明显体现。有时一个硕士或者一个博士为了拟真一个效果要花费几个月或者几年的时间，做为一个游戏程序员，微积分到达什么层次我很难给出定义，但起码如果别人给出了原理我们能看明白，并把它实现，我觉得就很可贵了。</span><br /><span style="font-size: 14pt">2。1。2线性代数和空间解析几何</span><br /><span style="font-size: 14pt">在大学课本中，空间解析几何是放在高等数学书里面讲的，但游戏中，它和线性代数放到一起我认为更加合适。线性代数所有知识都要掌握，在游戏中它们比微积分体现的更淋漓尽致，理解上我个人认为相对微积分更容易。</span><br /><span style="font-size: 14pt">空间解析几何主要讲向量，平面，线，体，这些东西并通过线形代数矩阵进行空间变换，最后达到游戏想要的目标。</span><br /><span style="font-size: 14pt">2。1。3四元数</span><br /><span style="font-size: 14pt">这个在大学里面不学数学的，估计很少有人接触，它也是来用来变换空间，理解起来不是那么容易，但最常用的就是用四元数来表示旋转。</span><br /><span style="font-size: 14pt">我这里只是一概而过，上面任何知识在游戏中都有应用，但大学里的数学不是为了游戏而开设的，所以和游戏中用的数学在知识分列和讲解上还是有很大差异，尤其是线性代数和空间解析几何，不用担心，我在后面介绍给大家一些好的游戏书籍，对大家学习游戏编程和有帮助的。</span><br /><span style="font-size: 14pt">2。2语言</span><br /><span style="font-size: 14pt">编写游戏c和c++是你首选，相对来讲C++是你更应该掌握的。</span><br /><span style="font-size: 14pt">2。2。1 其他语言为什么不是当今流行的编写游戏程序语言？</span><br /><span style="font-size: 14pt">VB，JAVA，C#，等等其他语言，并不是说它们不能做游戏，它们能做，由于语言本身设计机理的限制，只能做一些对游戏速度要求低的游戏，对于运行速度要求高的游戏，它们被判成死刑。当然这个也取决于硬件的发展，以前8bit FC游戏都用C语言和汇编来写，现在由于硬件速度提高，用VB，JAVA，C#来写这些游戏运行也是可以的，例如现在兴起的WebGame(网页游戏)。但如果你真想做游戏的话，你一定想要了解现在最流行游戏编写，C和C++是你最好的选择，也是你走上真正的游戏编程道路的重要武器。</span><br /><span style="font-size: 14pt">2。2。2 C和C++应该选择那一个？</span><br /><span style="font-size: 14pt">C和C++，这里面我还要说一说，我个人更看好C++。大家都知道C是面向过程的，而C++是面向对象的，虽然C++的面向对象特性还不是很完善，但出于对大型软件设计上的考虑，因为游戏引擎是大的工程，框架设计远远要比编程重要，一般框架设计用面向对象方式更直接，所以C++比C更有优越性性，而且如果你合理用好C++，并不见得C++比C速度慢。有时一个软件架构和软件运行上问题，很难取舍，对于大应用程序来说，都是一点点牺牲速度来获得好的架构，是利大于弊的事情，这里确实体现软件工程的重要性质。</span><br /><span style="font-size: 14pt">2。3。3 汇编，很重要吗？</span><br /><span style="font-size: 14pt">汇编语言也是你要掌握的，你说你语言学的好，但却不会汇编，是一个天大的笑话。现在很少有汇编高手能写出比编译器优化出来的汇编代码运行效率要高，因为语言的不同，思考问题的方式就会有不同，就象最早纸带机上的原语言一样（可计算性与计算复杂性就讲这东西）。如果游戏都用汇编来写，写代码效率很低，所以我们都用高级语言来写，同时还要与底层有密切联系的，C和C++担任大部分工作量。对于游戏速度频颈问题，有时我们用C和C++即使优化很多，代码精简很多，算法也改良很多，但由于语言本身设计上问题，和高效汇编来编写还是有不同的，这时就要是汇编高手来做速度最快，内存和寄存器使用最少汇编程序。所以汇编还是很重要的。</span><br /><span style="font-size: 14pt">2。3。4 其他CPU硬件指令</span><br /><span style="font-size: 14pt">这里只是说 INTER 和 AMD CPU 都支持的指令集，也是最常用指令集。</span><br /><span style="font-size: 14pt">MMX和SSE SSE2是游戏编程中最常用的指令集，这个指令集是 SIMD（single instruction multiple data），也就是单指令多数据流指令集，一个指令可以处理多个数据流运算。汇编CPU指令，一个指令只能执行一个数据流运算。</span><br /><span style="font-size: 14pt">例如：</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;汇编中</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;ADD EAX，EBX</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;这是一个加法指令，EAX，EBX是寄存器，是32位的。这个指令就是 EAX = EAX + EBX。这个过程只有一个数据流相加。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;而SIMD思想是，如果现在有2个指令</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;ADD EAX，EBX&nbsp;&nbsp;</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;ADD ECX，EDX </span><br /><span style="font-size: 14pt">&nbsp;&nbsp;能不能让他们一起执行？所以SIMD 指令提供这样的功能，他用很大的寄存器，前一部分装EAX值，后一部分装ECX值，再用一个寄存器，前一部分装EBX，后一部分装EDX.</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;SIMD 寄存器分成2部分[1部分][2部分]</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;SIMD ADD 指令&nbsp;&nbsp;积存器1&nbsp;&nbsp;，积存器2 </span><br /><span style="font-size: 14pt">&nbsp;&nbsp;运算过程为 寄存器1 [1部分] = 寄存器1&nbsp;&nbsp;[1部分] + 寄存器2&nbsp;&nbsp;[1部分] ；</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;寄存器1 [2部分] = 寄存器1&nbsp;&nbsp;[2部分] + 寄存器2&nbsp;&nbsp;[2部分] ；</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;这2个运行是在一个SIMD积寄存器用硬件来执行ADD 同时运行的。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;这里只是说了SIMD思想，现在简单介绍下 MMX，SSE，SSE2。</span><br />&nbsp;&nbsp;<br /><span style="font-size: 14pt">&nbsp;&nbsp;MMX寄存器是32位的，所以它可以执行4个8bit数据同时运算，也可以执行2个16bit数据同时运算，具体要看使用哪个指令，在早期没有SSE指令时，就用MMX，但MMX有缺点，它和FPU（浮点运算单元，专门执行浮点数运算）共用同样寄存器，所以当你指令有中断，从浮点运算跳到MMX运算，要告诉CPU，从MMX跳到FPU 也要告诉CPU，这样数据要临时保存，降低了处理速度。早期2D游戏经常用这个。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;现在SSE，SSE2有自己单独的寄存器可以使用，而且它们是128位的，支持4个32位整数或者浮点数同时运算。</span><br /><span style="font-size: 14pt">&nbsp;&nbsp;这些指令都没有分支，所以使用时效率要我们掌握，因为执行都是并行的，一个指令完成多个计算，所以即使你编写SIMD代码很差，速度也会提高几倍，游戏中经常用SIMD处理颜色和数学运算问题。在游戏速度瓶颈地方用这样的代码，公德无量。</span><br /><br /><span style="font-size: 14pt">2。3。5&nbsp;&nbsp;ASM SHADER语言 和 高级SHADER 语言</span></font> <font size="3"><br /><span style="font-size: 14pt">开始学游戏编程时，这个知识不一定要具备，因为你不了解3D流水线内部细节学起来还是比较困难，所当你做完&#8220;软引擎&#8221; 了解3D流水线，在学这个语言很容易，接下来的语言发挥，就靠你自己了。</span><br /><span style="font-size: 14pt">早期的游戏，所有的图形图象处理基本都由CPU来完成，然后把处理完的数据传到显存，用显卡来显示。现在的设计理念尽量解放CPU，把与图形图象有关的运算用显卡来完成。但早期显卡只支持固定流水线，所谓的固定流水线就是所有3D数据处理过程都是事先用硬件实现好的，这个过程是一个大过程，里面封状了很多小过程细节，用户只需要输入数据，显卡负责输出数据，至于用户无法干预这个大过程，小过程更是接触不到。再说的通俗一点，一个空间3D三角形要想显示到计算机屏幕上，基本要经历2个大过程，顶点处理和象素处理，顶点处理封状了很多空间变换的小过程，象素处理包括象素混合小过程。这个过程是不可以访问的，我们只能通过显卡提供的接口来控制，而且改变方式很单一。（刚接触这些可能不明白，现在你知道的不用太详细，就知道大过程是不可以干预的就可以了，或者是只有很少一部分可以干预）为了让图形图象处理更加完善话，让人们可以参与到整个3D流水线中，实现更多丰富的效果，显卡开始出现GPU单元（图形处理单元），这时的3D流水线从固定流水编成了可编程流水线，有了早期的GPU 指令，大家都称为 SHADER指令，也就是ASM SHADER，和汇编一样，这些指令都是和GPU指令一一对应的，随着硬件更新，GPU越来越强大，支持指令越来越多，ASM SHADER 从1。0 到 1。4 ，到现在3。0版本。由于ASM SHADER 用起来不方便，就象我们用汇编写程序一样，所以又出现了高级SHADER语言，有DirectX3D下支持HLSL（high level shader language）和 OPGL下支持的GLSL（opengl shader language）这些语言都是面向过程。由于硬件设计限制，这些语言不能象C语言那样随意使用，SHADER语言有自己的使用规范，大家学习时一定要弄明白3D流水线内部实现过程，再使用SHADER简直很容易。</span><br /><span style="font-size: 14pt">还有一个要说的是，GPU现在还不支持分支预测，但GPU编程语言现在已经提供了丰富的条件判断，条件判断还是会影响到速度的。</span><br /><br /><span style="font-size: 14pt">重点你要掌握的是，数学，c和c++，汇编，数据结构，基本掌握的是计算机体系结构，离散数学，编译原理，计算机网络，操作系统，软件工程，数据库，人工智能。可以说这些是计算机最基础的学科，你只有掌握了它们，无论你专研计算机哪个领域，你的基础都是足够的，游戏编程中这些学科都可以用到，我们不用每个学科都精通的要命，我们要精通的是游戏编程，也就是接触到和游戏相关的，我们有这些基础完全可以看懂，然后我们在用自己时间来去专研这些学科在游戏领域的应用。</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">四。游戏编程，她的大门已经为你打开。 </span></font><font size="3"><br /><br /><span style="font-size: 14pt">1。 颜色之迷</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">计算机怎么显示图形的，这个你必须要弄明白，计算机显示彩色图象是经历了一个什么样的发展过程。</span></font> <font size="3"><br /><span style="font-size: 14pt">1。1 象素和屏幕显示点</span><br /><span style="font-size: 14pt">计算机显示一个图象是由象素组成，我们通常说的分辨率就是屏幕上显示多少个象素。如果一个屏幕最大可以支持1024*768那么它也可以支持800*600，当你屏幕分辨率是800*600时，一个象素占据了屏幕多个屏幕显示点，也就是说，只有当你分辨率调节到最大时，屏幕显示点和象素点才是一一对应的，至于一个象素占据多个屏幕显示点后颜色怎么显示这个是硬件的事，我也不是很了解。象素都是2进制存储，然后由硬件根据显存中当前象素值，根据颜色显示模式的设定，来显示指定颜色。</span><br /><span style="font-size: 14pt">1。2 颜色组成和模式</span><br /><span style="font-size: 14pt">计算机要显示颜色，每个象素都有自己的颜色，通常颜色有3种模式，一个是调色板模式，一个是16bit模式，一个是32bit模式,我这里说的通常，早期也有4bit模式,我要讲出里面的细节，让看的人真正理解，不是死记硬背，你就会发现实质上只有2种模式，一个是调色版模式和bit显示模式。</span><br /><span style="font-size: 14pt">我先介绍位显示模式，从4bit开始，早期颜色显示很单调，硬件只支持16个颜色，当然这16个可以是黑白的，也可以是彩色的。总之硬件就支持16个颜色。所以用4bit表示4bit 2进制正好可以代表16个。</span><br /><span style="font-size: 14pt">随着硬件发展支持的颜色越来越多，发展到16bit，16bit开始有了严格限制，颜色是有三种色彩基元组成，也就是红绿蓝，人送江湖称号RGB，16bit分成1555格式和565格式，1555就是1位给ALPHA（表示透明）分给RGB分别5bit，5bit可以表示色彩基元颜色是32种，RGB组合起来就是15bit，就是2的15次方，可以表示很多颜色了。而565格式没有ALPHA位置，直接分给RGB位数为565，也就是绿色多了一位，传说中，专家说人眼对绿色明感，所以给绿色多分了一位。</span><br /><span style="font-size: 14pt">而32bit分给 ALPHA 和 RGB 分别是 8888，每个都是8bit。</span><br /><span style="font-size: 14pt">其实标准的颜色都是每个分量都是8bit，每个色彩基元都是256种，而16bit模式不能显示出真实世界色彩。</span><br /><span style="font-size: 14pt">调色板模式一般都是针对每个分量是8bit，也就是颜色组成是32位的。调色板模式有一个映射表数组，这个映射表数组每个元素都存放的是32位的颜色，而显存存放的是一个索引，但硬件读出显存当前象素值时，然后用这个值当作索引去映射表数组里面查对应的颜色，然后显示到屏幕上。 </span><br /><span style="font-size: 14pt">相比较而言，调色板模式是最早期的，例如早期FC 8bit机 每个象素只占8bit，只能表示256种颜色，而我们彩电可以表示很多颜色，为了节省显存，增加处理速度，还显示出多种颜色，FC用调色板模式，而我们想换颜色时，其实只换调色板映射表数组某一个值就可以了，索引都不用变，毕竟索引是写在显存中的，一般改写显存还是速度很慢的。16bit模式也是在处理速度上，节省存储空间上得以应用。毕竟这些显示模式都是为了应付以前硬件速度太慢而设计的，现在一般都用32bit模式。而且无论颜色基元的数字越大表示这个基元颜色越浅。</span><br /><span style="font-size: 14pt">还有一个要说的就是ALPHA，这个分量是表示透明度的，这个分量如果是8bit，那么它可以表示256种透明程度，255表示不透明，0表示完全透明。</span><br /><span style="font-size: 14pt">现在大家知道你设置屏幕或者游戏时1024*768*32 什么意思了吧！每个象素占32bit，屏幕显示1024*768个象素。</span><br /><br /><span style="font-size: 14pt">1。3 颜色的运算</span></font> <font size="3"><br /><span style="font-size: 14pt">计算机支持颜色运算都是无符号颜色运算，颜色没有负数，而且颜色运算有CLAMP和MOD</span><br /><span style="font-size: 14pt">如果每个颜色占8bit，颜色表示范围为0-255</span><br /><span style="font-size: 14pt">这里CLAMP指的是</span><br /><span style="font-size: 14pt">if(x&lt;0) x=0;</span><br /><span style="font-size: 14pt">if(x&gt;255) x=255;</span><br /><span style="font-size: 14pt">这里MOD指</span><br /><span style="font-size: 14pt">if(x&gt;255) x = x%255;</span><br /><span style="font-size: 14pt">Color1(a1,r1,g1,b1) Color2(a2,r2,g2,b2) </span><br /><span style="font-size: 14pt">颜色加减都是向量加减，每个分量做加减</span><br /><span style="font-size: 14pt">1。3。1颜色加法</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Color3(a3,r3,g3,b3) = Color1(a1,r1,g1,b1) + Color2(a2,r2,g2,b2)&nbsp; &nbsp;</span><br /><span style="font-size: 14pt">a3 = a1 + a2;</span><br /><span style="font-size: 14pt">r3 = r1 + r2;</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;g3 = g1 + g2;</span><br /><span style="font-size: 14pt">b3 = b1 + b2;</span><br /><span style="font-size: 14pt">颜色加法一般都用CLAMP</span><br /><span style="font-size: 14pt">1。3。2颜色乘法</span><br /><span style="font-size: 14pt">Color3(a3,r3,g3,b3) = Color1(a1,r1,g1,b1) * Color2(a2,r2,g2,b2)&nbsp; &nbsp;</span><br /><span style="font-size: 14pt">a3 = a1 * a2;</span><br /><span style="font-size: 14pt">r3 = r1 * r2;</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;g3 = g1 * g2;</span><br /><span style="font-size: 14pt">b3 = b1 * b2;</span><br /><span style="font-size: 14pt">颜色乘法一般都用MOD</span><br /><span style="font-size: 14pt">颜色加法和乘法在象素混合效果上经常用，有时为了到达一个效果，加法和减法混合用，至于什么时候用加法，什么时候用乘法，没有严格的规定，还是要看效果，一般对于全局光照模型颜色之间要用加法的，但其他光照模型可能不同，纹理混合或者纹理和颜色混合，加法和乘法都有各自用途。</span><br />&nbsp;&nbsp;<br /><span style="font-size: 14pt">2。Directx OpenGL到底用来干什么？</span><br /><br /><span style="font-size: 14pt">这里只说他们支持图形和图象部分，其他部分不说。</span></font> <font size="3"><br /><span style="font-size: 14pt">很多人都听过这2个名词，其实他们是一个函数库，这个函数库为我们做了一些最基本的和底层打交道的处理，其他它们还提供了一些常用的3D函数库，算是一个2次开发，其实2次开发一般和底层没有关系，所以在游戏引擎中很多都自己来做，微软做了很多2次开发，可以算是一个引擎。我前面说了，引擎没有明确概念，只有适应程度之分，用它这个提供的来做游戏，还是差很远，做小游戏当然没问题。</span><br /><span style="font-size: 14pt">我主要说说和底层打交道那部分，DX和OPGL最大功劳在于充分调度和发挥了显卡性能，把显卡的特性用接口的形式提供出来，他们各自都有自己的管理层次，管理方法，管理管线，至于怎么管理，我也不是很清楚，但当你使用和显卡资源相关的API时，你要仔细看这个函数各个参数说明，它会根据你的指定，来管理显卡。但他的管理只是一部分，还有很大一部分要引擎里面自己处理。</span><br /><span style="font-size: 14pt">如果你不想自己写驱动的话，那么你还想控制显卡，你就要用这些API，D3D（DX中主要处理3D的）和OPGL使用上还是有很大不同，所以学习他们也还要花费一些时间。我当初学习时，由于不了解3D渲染流程，学起来特别困难，很难看懂，我就放弃了他的学习，学习制作&#8220;软引擎&#8221;（用CPU来实现显卡提供的硬件功能），然后再学D3D，很容易的。有时后放弃是为了选择更好的，并不是真正的放弃。</span><br /><span style="font-size: 14pt">至于学习D3D还是OPGL，我个人认为无所谓的，但好象OPGL越更新越混乱，没有DX那么清晰，我也是听别人说的，毕竟我不是很了解OPGL。</span><br /><br /><span style="font-size: 14pt">3。游戏编程中的常用术语</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">游戏编程充着大量常用术语，我不打算把它们都列出来，实在太多，我想对于初学者是来说，我希望，你在学习游戏编程时，自己多查下资料究竟这些术语都有什么含义，记住一定在学习游戏编程时去查，也就是说，针对问题去查，而不是在没有遇到任何问题时去查。其实我们的教育有个弊端，任何知识我们学了，不知道怎么用。其实很多知识都是我们遇到问题时再去查资料，去找解决方式，而不是在不知道这个解决方式用来解决什么的情况下吓学。</span></font> <font size="3"><br /><span style="font-size: 14pt">最好大家把这些术语的中文和英文名称看见都能知道是怎么回事，因为你到以后看英文书时，如果你知道这个术语的含义，看起来会很容易。</span><br /><br /><br /><span style="font-size: 14pt">五 游戏编程中的2D游戏，你首先要做到的。</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">通往神殿的第一个考验就是这个，不知道你是否能走下来，相信自己会成功，你的信念一定要不可动摇，当你走过这段路的时候，想想你现在所得到的，付出的其实不算什么。</span></font> <font size="3"><br /><span style="font-size: 14pt">很多人可能会问，我想做3D游戏，2D游戏学它干什么。其实3D游戏处理可以分成2个部分，一个是3D空间数据处理，经过纹理映射把象素写到屏幕缓冲，接下来其他特效处理都是归结到2D问题。</span><br /><span style="font-size: 14pt">所以你想真正了解游戏图象处理过程，还是要学2D的。2D原理相对3D来说简单很多，学起来也不是很难。我建议去看《WINDOWS游戏编程大师技巧》里面的代码都读明白，它用C语言实现一个小的游戏引擎，我希望你用C++封状成类的形式，重新按照自己规划来实现，最后做出个游戏。用引擎做出的游戏和直接做游戏还是有很大区别的，这样你引擎也就符合引擎的概念，代码重用性更强。这本书用的DirectX中DDraw接口来实现的，你一定要了解你使用的工具，它能用来干什么，它不能用来干什么，这样你才能很好的游戏编程。如果你不了解C语言，怎么用C语言编程，都是一个道理的。我不想在过多详细介绍DDraw为我们提供了什么特性，你自己去看书。</span><br /><span style="font-size: 14pt">2D游戏中，最常用的概念就是贴图，把一个图象贴到另一个上。2D游戏中一种处理模式是在各个图片上的处理，还有就是在象素上的处理，其实这些都可以归结到象素上的处理，象素处理，就是处理显存数据。</span><br /><span style="font-size: 14pt">颜色模式，《WINDOWS游戏编程大师技巧》这本书讲的很详细。</span><br /><span style="font-size: 14pt">2D动画系统，《WINDOWS游戏编程大师技巧》这本书没有详细介绍，但你看它的代码，代码写的很清楚而详细，你就知道的。</span><br /><span style="font-size: 14pt">GDI 我不知道大家听说过没有，它是WINDOW自带的图形图象接口，我希望大家也能了解下，当时我是GDI和DDRAW一起学的，然后分别做了引擎，2个引擎接口也一样，游戏移植非常容易。 </span><br /><br /><span style="font-size: 14pt">一个最重要的问题就是调试，8BIT模式下的游戏，用编译器带的单步调式是不可能的，我机器死机N回。我现在也没有发现好的办法，最好的办法就是自己做一个LOG日志系统，把所有调式信息都写到文件里，用任务管理器把当前程序关掉，然后看文件写的信息。</span></font> <font size="3"><br /><span style="font-size: 14pt">2D游戏制作细节我没有详细介绍，毕竟我不是在讲怎么制作2D游戏，我是讲你应该注意什么，怎么学，我想《WINDOWS游戏编程大师技巧》会给你想要的一切。当然我在学这本书前已经有了一些2D游戏基础，以前用VB做过游戏，用GDI也做过，所以学起来还算容易，如果你以前没有任何游戏编程基础就直接用DDraw，那么我希望你多下点工夫，把它制作游戏的流程都搞清楚，记住什么时候用自己的双手做出了自己2D游戏，你才算2D游戏编程过关了。这本书仔细看吧！直到把它所有的精髓都掌握。</span><br /><span style="font-size: 14pt">还有一个要说的就是，图象处理常用算法，大家可以多看看图象处理的书，游戏中特效经常用到，其实如果你真想一心搞3D，2D上做一个坦克大战这样的游戏就可以了，很多2D处理详细东西，在学3D游戏时，都可以接触的。</span><br /><span style="font-size: 14pt">六。游戏编程中的3D游戏，考验你耐力和勇气的时候到了！</span><br /><br /><span style="font-size: 14pt">前面你所遇到的一切都是小小测试，证明你有能力接受这个挑战，在3D游戏这个广阔无垠的天地里，它比2D游戏更有让你想象余地的空间，因为3D游戏不仅仅包括2D游戏所有，而且还包括很多其他东西。努力吧！朋友们，无论遇到什么挫折，都不要放弃，因为她最后会给你想要的。</span></font> <font size="3"><br /><span style="font-size: 14pt">我不知道其他人学习3D游戏是一个什么样的过程，这里我只介绍我自己的学习过程，因为我是从挫败中走过来的。</span><br /><span style="font-size: 14pt">开始学3D，脑袋里一片模糊，只有一点点大学里学的计算机图形学相关的知识，我不得不说学校里讲的计算机图形学和游戏还是大相径庭的。</span><br /><span style="font-size: 14pt">（这里允许我抱怨一下，国外很多大学都开设了3D游戏编程的课程，而且很专业，我看过老外的PPT。相对于国内，也有些，但不专业，我说游戏学院骗钱你不要打我，它确实能让你找到工作，但你做的永远是下手，学不到底层的东西。我看过游戏学院开设的课程，没有一个是有技术含量的，用&#8220;外包&#8221;形容在贴切不过。道理也很简单，中国现在牛人很少，我说搞引擎的高手全国有1000人都是保守的，真正能搞出名堂的，也不多于200人，这200人里面学习游戏编程经验10年就很多了，中国3D游戏起步很晚，相对国外，中国人爱跳槽的习惯，让任何公司都没有技术积累，发展更是困难，所以人才积累的少，而且这些人都很忙，在加上现在学校教育约束，即使他们想去高校教授游戏课程也是不可能，何况人家都不愿意去，这样中国积累的人才更少）</span><br /><br /><span style="font-size: 14pt">所以你要系统学习游戏中图形学理论。</span></font> <font size="3"><br /><span style="font-size: 14pt">这里我经历了游戏学习编程一次比较大的挫败，当时自己是初学者，问过很多人学3D，应该从什么入手。很多人都说从D3D开始入手，于是我做了。我不得不说的是，如果你不了解3D流水线过程，学D3D简直是看天书，当时我以为自己反复的看书，写程序，最后会理解的，浪费了我大量的时间，最后还是无法灵活掌握D3D，如果你无法掌握D3D，想做游戏可能真的很困难。我终于认识到，我选择的路是错误的，那些所谓的高手难道就学D3D学过来的？那么他们花费的时间是可想而知的。因为有些细节你无法掌握，你使用时就觉得匪夷所思。</span><br /><span style="font-size: 14pt">《3D游戏编程大师技巧》这本书是每个学3D的人都应该看的，这本书把显卡硬件实现的功能都用软件来做，真正让你理解一个3D东西到最后的屏幕显示，是一个什么样的过程。作者实现了一个软引擎，软引擎就是所有的3D功能都是用代码自己写的，没有用什么显卡来做处理的引擎。这本书是一个经典巨著，如果你想学3D，即使死也要把这本书弄明白，这样不辜负作者写这本书留下的汗水，写一本书，尤其这么PERFECT，太不容易了，国内人翻译的也很出色，感谢他们。</span><br /><br /><span style="font-size: 14pt">《3D游戏编程大师技巧》继承了《WINDOWS游戏编程大师技巧》里面2D函数，然后3D功能以及流水线和引擎都是自己完成，这本书的代码量要有十几万，我当时用C++重新封装了《3D游戏编程大师技巧》代码，自己设计了一个面向对象固定流水线模式，代码量13W左右，这个过程很艰辛，这本书我看了2遍，最后一共零零散散花费了大约9。10个月的时间。你会感觉你立刻升级了，HP，MP，CP都增长了，当然也包括RP，哈哈！（不知道这些术语的，大家多玩玩RPG游戏吧！）</span></font> <font size="3"><br /><span style="font-size: 14pt">好东西去追求，不要怕浪费时间，浪费精力，你想想，你得到的最后会大于你的付出，这些都不算什么。很多人问我怎么学3D，我建议他们不能着急，要从学《3D游戏编程大师技巧》开始，大约要8，9个月时间，把每个细节都弄明白，闭上眼睛，怎么实现就很清楚，书上每一页写什么都很明确。他们都觉得浪费时间，那么这样是永远学不好的</span><br /><br /><span style="font-size: 14pt">1 3D数学是你要攻克的</span></font> <font size="3"><br /><span style="font-size: 14pt">虽然你数学学的好，但国内的教科书还是和游戏中用的有些不同，毕竟没有上过专门讲解游戏中数学知识的课程。这需要你系统学习游戏编程中数学，3*3矩阵为什么有的人用，而有的人用4*4矩阵，为什么有的用矩阵转置有的用矩阵的逆。《3D游戏编程大师技巧》这本书介绍的很详细，还有一本书就是《3D数学基础：图形与游戏开发》很不错（有中文的），先系统学习下，然后在学习游戏编程时，不懂的时候，再回头看看这些书，把所有的东西都彻底弄清。你如果数学基础好，学这些都很容易，以后游戏编程中最深奥的地方之一就是数学。</span><br /><br /><span style="font-size: 14pt">基本上我总结下，你要知道的是：</span></font> <font size="3"><br /><span style="font-size: 14pt">向量&nbsp;&nbsp;4维 和 3维向量有什么不同 </span><br /><span style="font-size: 14pt">矩阵&nbsp;&nbsp;4*4 和 3*3 矩阵有什么不同</span><br /><span style="font-size: 14pt">四元数</span><br /><span style="font-size: 14pt">ELUER角</span><br /><span style="font-size: 14pt">以后有机会深入研究碰撞中的各种算法，还会遇到很多关于数学的问题，上面只是渲染有关系。</span><br /><span style="font-size: 14pt">2 3D流水线的实现过程</span><br /><span style="font-size: 14pt">我无法用言语来表明这个过程的重要性，整个3D流水线是是3D游戏的脊柱，你的基础知识牢固与否，主要看你这里。3D流水线每一个细节我希望大家都要搞清楚，这个过程对初学者是要花费大量的时间专研与琢磨，D3D的固定流水线都是由硬件完成，如果你的硬件不支持，它会用软件模拟，好，关键就在这里，软件模拟是怎么回事，而《3D游戏编程大师技巧》的流水线是自己用C语言写的，也就是用软件完成，这样你能了解整个流水线的细节，同时你在学D3D时，对照着来学，你会发现，D3D学起来很容易。现在D3D和硬件都支持可编程流水线，而且DX10没有固定流水线，所有变换过程都用SHADER语言控制显卡完成，这个过程是3D流水线的缩影，所以3D流水线的重要性是是可想而知的。</span><br /><span style="font-size: 14pt">我说了这么多，3D流水线对你是一个新鲜的名词，我也没有去解释它，我不想去解释，完全留给你自己去，我始终坚持着，我只告诉你去的路，路上有什么困难，应该怎么走，你自己去体会这条路上的酸甜苦辣。我希望大家多花些时间在这上面，真真正正的自己写代码实现一下，基础对你真的很重要，记住我说的话，很多人学习时，认为自己理解了，没有去实现，其实还是那句话&#8220;纸上得来终觉浅，绝知此事必躬行&#8221;，相信我，没错的。</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;基本上我总结下，你要知道的是：</span><br /><span style="font-size: 14pt">3D中的顶点结构，每个分量都用来干什么，三角形是基本渲染单元。</span><br /><span style="font-size: 14pt">模型空间&#8212;&#8212;》世界空间&#8212;&#8212;》相机空间&#8212;&#8212;》投影空间&#8212;&#8212;》屏幕空间&#8212;&#8212;》光栅化 这个过程和运行原理</span><br /><span style="font-size: 14pt">材质究竟是什么？</span><br /><span style="font-size: 14pt">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;常用的宏光照模型原理，光源类型</span><br /><span style="font-size: 14pt">光源和材质和法向量关系</span><br /><span style="font-size: 14pt">光照在哪个空间去执行（其实不是很严格）</span><br /><span style="font-size: 14pt">纹理寻址，纹理映射方式，纹理混合，纹理过滤。</span><br /><span style="font-size: 14pt">1D 2D 3D CUBE 纹理</span><br /><span style="font-size: 14pt">Z 1/Z缓冲</span><br /><span style="font-size: 14pt">2种相机模型</span><br /><span style="font-size: 14pt">ALPHA 透明</span><br /><span style="font-size: 14pt">关于光栅化三角形要特别注意，他最后混合纹理和光照颜色和ALPHA透明，还要判断深度缓冲，最后是插值填写每个象素。</span><br /><span style="font-size: 14pt">3 D3D究竟要如何学习</span><br /><span style="font-size: 14pt">《3D游戏编程大师技巧》和D3D流水线过程还是有些差别的，比如在投影矩阵上，其实它们都是大同小异，只不过表现形式不同，原理都一样。我希望大家自己可以找出来，深刻理解里面原理。</span><br /><span style="font-size: 14pt">还有一个重要的东西，就是哪些是D3D开发游戏必须有的，哪些是D3D自己扩展的。必须有的，就是同硬件打交道的部分，而D3D中自己扩展了很多库函数，例如数学库，这个完全可以没有，我们自己来实现，还有D3D中的EFFECT接口，它自己定义的。X文件所有函数接口。也就是说，你要理解，哪些是游戏开发中必须有的，哪些是游戏开发中自己完全可以不接触底层来实现的。</span><br /><span style="font-size: 14pt">游戏编程中有3个缓冲区，颜色缓冲，深度缓冲，模板缓冲，前2个《3D游戏编程大师技巧》中，都详细的介绍，而模板对初学者可能很晦涩，大家先弄明白模板的机制，然后多看些例子，我想你会深刻理解它的含义的。</span><br /><span style="font-size: 14pt">D3D的学习，可以看D3D SDK的例子，也可以找一些书籍，很多的。</span><br /><br /><span style="font-size: 14pt">基本上我总结下，你要知道的是：</span></font> <font size="3"><br /><span style="font-size: 14pt">D3D提供基本常用底层接口，那些是是D3D为了编程必须提供的，那些是不用提供的，比如数学库我们完全可以自己写。</span><br /><span style="font-size: 14pt">D3D顶点 索引BUFFER</span><br /><span style="font-size: 14pt">颜色缓冲，模版缓冲，深度缓冲 以及对这些缓冲的操作</span><br /><span style="font-size: 14pt">目标渲染对象、</span><br /><span style="font-size: 14pt">D3D 中的3D流水线</span><br /><span style="font-size: 14pt">单通道渲染，多通道渲染。</span><br /><span style="font-size: 14pt">熟练操作上面的所有，这些都足够了，其他的都是D3D中多余的，如果你要自己做引擎，很多都要自己实现，当然初学者可以就用它扩展的函数库，也很方便的。</span><br /><br /><span style="font-size: 14pt">4 其他要知道的游戏知识</span></font> <font size="3"><br /><span style="font-size: 14pt">下面知识都属于很强的游戏技术范畴，他们只属于单单游戏中技术支持，引擎就是用合理的方式，把所有3D相关包括流水线和下面这些都整和到一起，但这种整和是有效的管理。</span><br /><span style="font-size: 14pt">场景管理算法 ：BSP OCTREE QUADTREE PORTAL PVS</span><br /><span style="font-size: 14pt">动画系统 ：骨骼动画，蒙皮骨骼动画，渐变动画，和这些动画的混合</span><br /><span style="font-size: 14pt">阴影&nbsp;&nbsp;：阴影体 投影阴影 阴影影射</span><br /><span style="font-size: 14pt">剔除算法 ：包围球 OBB AABB BHV算法</span><br /><span style="font-size: 14pt">LOD系统&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;：视点无关LOD 视点相关LOD</span><br /><span style="font-size: 14pt">广告牌&nbsp;&nbsp;：跟踪相机方向 和 只围绕y轴旋转 粒子系统</span><br /><span style="font-size: 14pt">这些是比较常用的，常常碰到的，根据基本的颜色运算，空间运算还能衍生出很多游戏特效，等待你自己去看书，去解决。</span><br /><br /><br /><br /><span style="font-size: 14pt">七。3D引擎编程，令你的挑战达到了极限</span></font>&nbsp;&nbsp;&nbsp;&nbsp;<font size="3"><br /><span style="font-size: 14pt">就象我前面说的，引擎没有严格定义划分，但对于当代的引擎，似乎大家都趋向于越好的东西，越健壮的支持，才称上引擎。现在游戏玩家对画面拟真程度要求很高，这就要求引擎能更好的处理3D世界中大量数据，一个好的引擎，起码要做到以下几点（引用《3D.Game.Engine.Architecture.Engineering.RealTime.Applications.with.Wild.Magic》里面的话）</span><br /><span style="font-size: 14pt">1。如何把3D世界中大量数据，让它实时快速处理。</span><br /><span style="font-size: 14pt">2。引擎中的渲染器（用来管理数据，进行渲染处理的）接口应该怎么定义。</span><br /><span style="font-size: 14pt">3。如何让使用引擎的人，能很容易的使用引擎。</span><br /><span style="font-size: 14pt">4。当引擎中添加新特性时，如果让引擎改动最小。</span><br /><span style="font-size: 14pt">我感觉这4句话，概括的很精辟，如果让我来概括，好象我现在还没这个能力。这是一个当代引擎的新的定义，虽然不是全面，但它一语道破天机，如果你的引擎能达到上面4点，我想它已经足够的优秀，同时说明你也很优秀了。下面我就分别解刨这4句话，让大家对引擎有一个深刻的了解。我只是分析，这4句话要求高手才可以完全去达到，我现在还不具备这个能力，所以只能帮大家分析。</span><br /><span style="font-size: 14pt">1。如何把3D世界中大量数据，让它实时快速处理。</span><br />&nbsp;&nbsp;<br /><span style="font-size: 14pt">3D世界中充满了大量得数据，有效的处理只可以看见的，能感受到的就可以了。</span><br /><span style="font-size: 14pt">3D引擎中，很多时候都在处理剪裁和剔除的问题，把不可见的或者和碰撞无关的数据用最快的方法弄掉，不让它进入显卡，一切还是停留在3D空间中。剪裁，剔除还有碰撞处理，永远是3D引擎中最常见的话题，现在有很多成型的方法，大家自己通过学习就可以了解的。</span><br /><span style="font-size: 14pt">2。引擎中的渲染器（用来管理数据，进行渲染处理的）接口应该怎么定义。</span><br /><span style="font-size: 14pt">即使你把3D数据给了显卡，还是不能达到最快显示，我们要把这些数据分类，重新组织，这里面还涉及到存储管理的问题。你的渲染器的接口要定义的和底层提供的DX或者OPGL相通，因为最后你要调用的是这2个库里面的函数。</span><br />&nbsp;&nbsp;<br /><span style="font-size: 14pt">3。如何让使用引擎的人，能很容易的使用引擎。</span><br /><span style="font-size: 14pt">这是一个经验问题，一个软件设计给用户使用，怎么让用户很容易上手。但无论什么样的用户，你必须对3D有了解才可以使用，否则神仙也没法完成这个引擎。</span><br /><span style="font-size: 14pt">4。当引擎中添加新特性时，如果让引擎改动最小。</span><br /><br /><span style="font-size: 14pt">经常说的一句话就是&#8220;计划没有变化快&#8221;，怎么能让引擎跟上时代的步伐，当硬件有革新，我们引擎就有革新，出现新的处理方法，引擎也要改进，用户需求改变，引擎接口也要改变，我们要求引擎的所有改动最小，这样才是一个完美的引擎。</span></font> <font size="3"><br /><span style="font-size: 14pt">引擎是软件设计+算法+编程的结合体，难点在软件设计上，一个好的引擎，代码几百万很正常，没有一个好的设计来规范它们，混乱是不可避免的。</span><br /><br /><span style="font-size: 14pt">对于一个引擎，从设计到编程都很重要，一个人完成一个好的引擎是不可能的，多人协作来完成引擎，在大家相互配合的同时，每个人对自己的要完成的任务必须精通，还要有人协调这些工作。</span></font> <font size="3"><br /><span style="font-size: 14pt">好的引擎，要有一个抽象层次，然后是渲染API层次，还要支持多操作系统平台，我在这里没有过多介绍各种技术细节，因为很多细节在书中都可以找到，加上你的聪明，很多技术算法可以自己创造的。</span><br /><span style="font-size: 14pt">对于游戏中大量算法，引擎中到处都是，碰撞，场景管理，光照，纹理混合，动画系统，粒子系统，内存管理，资源管理等等大家要多实践，多思考，多看书，多看资料，把握每一个细节，把握每一个整体。看书时要带着问题去看，同时也要带出问题，因为没有一个方法是完美的，必定会有或多或少的缺陷。</span><br /><br /><span style="font-size: 14pt">现在开源的引擎确实不少，其实程序员都有一个共性，看别人代码有时不如自己写，确实这样，有时只看代码去体会别人的思想真的很难，但有时为了去学习也要硬着头皮去看的，跟踪代码。开始时，如果你不了解引擎究竟是什么，这时最好集中看一个开源引擎，一定要把它的工作原理都弄明白，这样你会得到很大的提升，你就会明白引擎是什么，为什么不用D3D直接编写游戏，还有一点就是，有机会一定要去实现，这样你的体会会更深。</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">八 浅谈物理与人工智能</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">这2个都不是中国游戏中的优势，它们和图形一样，要求一定能力积累才可以胜任。如果我没有预测的话，未来中国游戏中大量的需求将来自物理和人工智能，传统的网络RPG会慢慢不能满足大家需要，而被时代所抛弃的。</span></font> <font size="3"><br /><br /><span style="font-size: 14pt">这2方面的编程我只是略知一二，还算一个小白，在此简单谈谈。</span></font> <font size="3"><br /><span style="font-size: 14pt">10。1 物理</span><br /><span style="font-size: 14pt">游戏中大部分物理模拟都集中在力学和运动学上，本来它们就是一个整体。因为最后效果是大家看到的，而看到的都是物体在屏幕上的移动，所以所有的计算最终都归结到物体移动上。</span><br /><span style="font-size: 14pt">因</span>为游戏毕竟是游戏，人也毕竟是人，没有必要模拟的那么精确，同时人也是感觉不出来的。<br />所以要想做好物理上的编程，必须对力学和运动学有系统的了解，高中学的力学部分还不是很足够，对于旋转部分，也就是处理力矩和转动惯量上，高中物理书都没有讲（我那时是没有讲，而且很多直线线形运动方程推倒其实是用微积分推倒的，高中书上都没有明确推倒）<br />物理上的模拟也没有逃脱物理计算基本规则，先是受力分析，然后计算合力，计算加速度，计算速度，最后计算位置，也可能涉及到动能和动量等知识，还有些流体力学等等吧。<br />物理其实处理的问题基本就是检测物体碰撞，碰撞后的反映，物体运动情况。<br />至于理论，大家弄本大学物理，力学部分就足够，如果数学好的话加上高中的物理知识，应该学起来不难的。<br />《游戏开发物理学》这本书很好，可惜绝版了，但有电子版的，也有中文版。<br />10。2 AI<br />相对物理的编程书籍来说，AI的书很多。<br />AI是研究生必须学的课程，包括传统的AI和计算智能。游戏中常用的传统AI包括自动机理论，A* 算法，回溯，图搜索，剪枝等等吧。计算智能包括的是：遗传算法，模糊计算，人工神经网络。<br />我答UBI笔试的时候，里面很多题都是A*算法，可见FPS游戏中大量存在的都是AI的路径搜索问题，让电脑更加智能。<br />AI的游戏编程书很多，我就看过几本。《WINDOWS游戏编程》中有一部分讲的AI，《游戏开发中人工智能》 《游戏编程中的人工智能技术》这3本都有中文的，而且都有大量的实例，对于那些大量理论的书籍来说，看看它们还是很通俗的。还有很多好书，都是英文的。</font> </div> <img src ="http://www.cppblog.com/nightsky0911/aggbug/181140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/nightsky0911/" target="_blank">Nightsky</a> 2012-07-02 14:35 <a href="http://www.cppblog.com/nightsky0911/archive/2012/07/02/181140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>