• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            concentrate on c/c++ related technology

            plan,refactor,daily-build, self-discipline,

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              37 Posts :: 1 Stories :: 12 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(9)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            2016年5月10日 #

             

            Nginx開發第三方模塊實例

            Ø 序言

            Nginx是一個極具擴展性的服務器,這顯著體現在對第三方模塊的支持,開發者能夠將自己開發的模塊,按照nginx既有的規則,完美地融合進http框架中,以實現開發者定制功能的作用。

            這篇文章主要用于結合如何開發一個簡單的第三方模塊,目標人群為想了解nginx開發第三方模塊的同學,文章內容主要包括三個部分,如何將HTTP模塊嵌入nginx和如何開發第三方模塊以及一個例子。

            Ø 如何將HTTP模塊嵌入nginx

            Nginx目前來說提供了二種方式,config文件+configure 腳本,手動方式,后面手動方式是更加復雜的,且容易出錯,在常規的nginx開發中,基本上都是用config文件+configure腳本方式比較多。接下來分別介紹這兩種方式。

             

            1)      Config文件+configure腳本

            Config文件

            這個是指提供config文件,并且在文件里面給出三個配置項,就可以達到效果。這三個配置項是指:

            A.      Ngx_addon_name就是自己要開發的這個模塊名字。

            B.        Nginx模塊名:這有點像設置環境變量啥的,首先要知道自己開發啥模塊,nginx對應的模塊有,$HTTP_MODULES(常規的http模塊), $HTTP_FILTER_MODULES(HTTP過濾模塊)$HTTP_HEAD_FILTER_MODULES(HTTP 頭部過濾模塊) $CORE_MODULES(nginx的核心模塊)$EVENT_MODULES(nginx的事件模塊)等,然后在后面添加你所要添加的模塊名字,以空格隔開,比如這次我們開發添加的模塊:

            HTTP_MODULES = “$HTTP_MODULES ngx_http_helloworld_module”

            C.        NGX_ADDON_SRCS這個顧名思義,就是指定新添加文件的路徑,不過這個都是相對路徑,因為在configure的時候就指定了上層路徑,比如--add-modules=PATH

            比如我們這次開發要添加的源文件:

            NGX_ADDON_SRCS = “$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_helloworld_module.c”

            Configure腳本

            這里需要用- -add-module=PATH將第三方模塊的路徑加入,

            比如configure - -add-module=~/ngx_3rd_modules/

            那我們能分析下這背后做了什么呢?我們從下面兩個部分來展開說明

            a)      Auto/modules

            這個主要是說明將定制的第三方模塊添加到生成的ngx_modules.c里面。

            a)         指定模塊下面的配置文件.

            b)         生成模塊信息

            一、生成模塊數組

            根據需要開啟的模塊加載對應的模塊,下面是開啟http模塊后的所需要的模塊
             

            二、生成ngx_modules.c文件

             

            b)      Auto/make

            顯而易見,這個就是負責編譯相關的模塊。

            1)         生成第三方源碼

            2)         生成鏈接代碼,并將目標文件,庫文件鏈接成二進制程序


            2)      手動方式

            分兩步來做,第一,修改obj/ngx_modules.c, 在里面增加對應的第三方模塊,第二,修改obj/Makefile,在里面增加第三方模塊的編譯,這種直接修改的方法不太可取,易出錯,一般都是用上面的第二種方法。

            Ø 開發第三方模塊注意事項

            首先,要確定針對那個模塊進行開發,nginx的模塊是有順序性的,比如: HTTP_MODULES = “$HTTP_MODULES ngx_http_helloworld_module”

            其次,因為nginx是異步非阻塞的,在編制代碼時,一定要注意不能阻塞nginx進程.

            Ø 示例

            見附件/Files/jolleydtan/test.zip

             

             參考:

            深入理解nginx. 

            posted @ 2016-05-10 08:25 jolley 閱讀(1857) | 評論 (2)編輯 收藏

            2016年4月16日 #

            游戲服務器框架設計

            Ø  序言

            人們在認識事物的時候,一般都是先從大致的骨架開始,然后再到具體的細節,金字塔原理中用的比較多的就是自上而下的分析方法,這個方法放在放之四海而皆準。那么回到我們游戲服務器開發上面,也是如此。那么如何設計和選擇服務器架構以及有啥需要注意的呢? 這是本文章要解決的問題。

            文章主要目標人群是,對服務器框架設計感興趣,有從事過游戲框架設計的同學。

            文章內容,介紹五大設計原則以及給出兩個示例,最后做總結。

            Ø  設計原則

            設計原則其實也是在設計時需要考慮的因素,過度設計是加重工作量的元兇,設計本質就是為了解決問題而存在的,下面列出了5大比較典型的原則。

            1.         業務邏輯開發

            a)         比如游戲為了增加存儲,你就需要考慮使用內存數據庫還是弄個數據庫網關服務器來處理。

            b)         比如游戲為了管理游戲玩家賬號,以及支持對平臺賬號的接入,那么就需要賬號服務器。

            c)         比如游戲為了管理游戲玩家訂單和跟蹤付費情況,可能就需要支付服務器,如果游戲類型是計時收費的話,那么可能會需要計時服務器。

            2.         運營維護

            a)         配置

            這里牽涉到靜態配置和動態配置的問題,假設現在有一臺網關服務器和三臺游戲邏輯服務器,靜態配置的話,就是網關服務器這邊寫死只連接這三臺服務器,然后讓網關服務器主動去連接,動態配置的話,就是讓這三臺服務器知道這個網關服務器的地址,然后自己在啟動的時候去連接。

            b)         開啟或者關閉順序

            這主要是看各個服務器上面負責什么功能以及服務器上面的相關功能,拿游戲登陸服務器,游戲邏輯服以及數據庫網關服務器這三個服務器的架構來說,比如開啟的時候,你盡可能地跟玩家登陸連接的順序相反, 一般都是數據庫網關服務器,然后才是游戲邏輯服,最后才是游戲登陸服務器,其實就是防止玩家過早地登陸進來,卻發現數據還沒有準備好。

            關閉的順序其實就是相反的,主要原則就是讓數據盡可能地保存好,并且讓玩家不再進來。

            c)         動態增刪改

            增刪改分為三部分:1)增加一臺服務器,2)減少一臺服務器,3)修改服務器信息,比如前面提到的靜態配置,就是不太方便增加服務器,要增加一臺服務器,需要更新網關服務器的配置表,然后讓網關服務器重新連接到新的服務器,而動態配置的話,就非常方便,讓新增的服務器發起到網關服務器就好了。無需更改配置。

            d)         服務器管理

            服務器的管理主要在服務器的在線離線狀態的管理,中心服務器(用來管理其它服務器)必須實時知道所管理服務器的狀態,比如網關服務器必須要實時知道游戲邏輯服的狀態,這樣才好更新到登陸服務器上面,更改服務器狀態。基本上在眾多同級服務器上面基本上都會有個中心服務器。

            3.         性能效率

            這需要權衡利弊和性能優劣,比如在ARPG游戲邏輯服務器里面大量的消耗在AI上面,那么就要考慮給弄個線程還是進程,這同樣適用于聊天功能,有一些聊天功能,或許可以選擇使用UDP來作為網絡層通訊方式。是否將功能模塊設計成單獨進程,這需要權衡,雖然可能在運營中會部署內網,相互之間是通過發消息的,類似于共享內存,但是還是會產生一些消耗的。

             

            4.         負載均衡

            這里包括兩個部分,硬件負載均衡,和軟件負載均衡。硬件負載均衡主要是指路由器。軟件負載均衡主要有幾種軟件,nginx/lvs/haproxy/dns, 負載均衡的策略,可以參考nginx 的負載均衡,主要有round-robin, least-connected, 以及ip-hash等。

            一般來說,游戲中大都是二級負載,首先是在登陸這邊負載一次,然后再在進入游戲邏輯服那邊負載一次,這樣就夠了。

            5.         安全性

            這里說下網關服務器,其它地方也叫前置服務器,front-end servers,,這個有幾個好處:1)隱藏游戲邏輯服的連接信息. 2) 統籌游戲邏輯服的負載信息。

            Ø  服務器框架示例

            1)         無中心服務器架構

            2)         有中心服務器架構

            Ø  結論

            服務器框架設計更像一門藝術,需要在解決問題的同時,又需要注意平衡得失。

             




            posted @ 2016-04-16 17:33 jolley 閱讀(1246) | 評論 (0)編輯 收藏

            2016年4月2日 #

            實現這個有這三種辦法:
            1)隨機排序,按照順序先后取出M個數字。
             IntVec shuffle(IntVec& vec)
            133 {
            134 int size = vec.size();
            135 IntVec::iterator first = vec.begin();
            136 IntVec::iterator last = vec.end();
            137 for(IntVec::iterator i = first + 1; i != last; ++i)
            138 {
            139 std::iter_swap(i, first + rand()%((i - first)+ 1));
            140 }
            141 return vec;
            142 }
            這個呢,不會影響源數組,這個
            2)取M次,每次做個事情就是隨機出一個數,添加到目標數組里面,然后從源數組中刪除。。
            143
            144 IntVec shuffle(IntVec& vec, int count)
            145 {
            146     IntVec desVec;
            147     for(int i = 0; i < count;i++)
            148     {
            149         int random = rand()%vec.size();
            150         desVec.push_back(vec[random]);
            151         vec.erase(remove(vec.begin(),vec.end(),vec[random]),vec.end());
            152     }  
            153     return desVec;
            154 }
            這個呢,會影響源數組。
            3)取M次,借助一個輔助數組記錄哪個數據被取過,隨機出一個數,添加到目標數組里面,然后將這個值添加到輔助數組里面.
             IntVec shuffle2(IntVec& vec, int count)
            158 {
            159     IntVec desVec;
            160     IntVec flagVec;
            161     for(int j = 0; j < count; j++)
            162     {
            163         flagVec.push_back(0);
            164     }
            165     for(int i = 0; i < count;i++)
            166     {
            167
            168         int random = rand()%vec.size();
            169         if (flagVec[random] == 0)
            170         {
            171             desVec.push_back(vec[random]);
            172             flagVec[random] = 1;
            173         }
            174         else
            175         {
            176             i--;// 如果已經取過了,這次不算.
            177         }
            178
            179     }
            180     return desVec;
            181 }
            posted @ 2016-04-02 11:51 jolley 閱讀(1276) | 評論 (0)編輯 收藏

            2016年3月23日 #

            這個是改良版的二分查找樹,是通過閱讀nebula device意外獲得,這邊先記下來。。
            typedef vector<int> IntVec;
             16 int binarysearch(const IntVec& vec, int element)
             17 {
             18     int num = vec.size();
             19     int begin = 0;
             20     int end = num - 1;
             21     int half;
             22     int mid;
             23     int count = 0;
             24     printf("binarysearch--- vec count=%d, element=%d\n",num, element);
             25     while(begin <= end)
             26     {
             27         count++;
             28         if((half = num / 2))
             29         {
             30             if (element == vec[begin])
             31             {
             32                 printf("count=%d\n", count);
             33                 return begin;
             34             }
             35             if (element == vec[end])
             36             {
             37                 printf("count=%d\n", count);
             38                 return end;
             39             }
             40             mid = begin + ((num & 1)? half : (half - 1));
             41             printf("vec[%d]=%d\n",mid, vec[mid]);
             42
             43             if(element < vec[mid])
             44             {
             45                 end = mid - 1;
             46                 num = (num & 1)? half: half - 1;
             47                 printf("element < vec[mid]-- end, num\n", end, num);
             48             }
             49             else if (element > vec[mid])
             50             {
             51                 begin = mid + 1;
             52                 num = half;
             53                 printf("element < vec[mid]-- end, num\n",end, num);
             54             }
             55             else
             56             {
             57                 printf("count=%d\n", count);
             58                 return mid;
             59             }
             60         }
             61         else if(num)
             62         {
             63             if (element != vec[begin])
             64             {
             65                 return -1;
             66             }
             67             else
             68             {
             69                 return begin;
             70             }
             71         }
             72         else
             73         {
             74             break;
             75         }
             76     }
             77     return -1;
             78 }
            posted @ 2016-03-23 22:16 jolley 閱讀(153) | 評論 (0)編輯 收藏

            2016年3月11日 #

            現在nginx的版本已經到了1.9.12,不過在1.9.0的時候,就開始了對TCP代理服務器的支持。
            之前也有一些早期的做法,比如就有寫了nginx_tcp_module模塊的https://github.com/yaoweibin/nginx_tcp_proxy_module,
            以及nginx_stream_lua模塊的
            https://github.com/openresty/stream-lua-nginx-module
            本來就想著用這兩個的,后來發現已經有支持了,就先來試試看看這個了。
            默認的話,nginx是沒有開啟對tcp的支持的.如果要支持的話,需要用--with-stream去指定。
            我這邊只要需要三個IP,一個是nginx進程所在的機器,我這邊用192.168.1.4表示,
            另外兩臺就是TCP上游業務服務器,我們分別用192.168.1.5和192.168.1.21來表示,
            基于這樣的考慮是因為nginx充當tcp代理服務器后,自身也會占用一個端口。
            并且從目前來說,貌似一個nginx進程也就只能listen一個端口。
            我用的版本是nginx 1.9.9.
            我在/usr/local/nginx/conf下面新建了nginx_stream_tcp.conf作為本次的測試。
            worker_processes auto;
              2 error_log /usr/local/nginx/logs/error.log info;
              3 events {
              4     worker_connections  1024;
              5 }
              6
              7 stream {
              8     upstream loadbalance {
              9 # Specifies a load balancing method for a server group where client-server mapping is based on the hashed key value
             10         hash $remote_addr consistent;
             11 # sets the weight of the server, by default, 1.
             12         server 192.168.1.21:8001 weight=5;
             13 # by default, the parameter is set to 10 seconds.
             14         server 192.168.1.5:9001  max_fails=3 fail_timeout=30s;
             15
             16 
             17     }
             18
             19 server {
             20 # listen 8001.
             21         listen 8001;
             22 # Defines a timeout for establishing a connection with a proxied server.
             23         proxy_connect_timeout 1s;
             24 # Sets the timeout between two successive read or write operations on client or proxied server connections
             25         proxy_timeout 3s;
             26 # Sets the address of a proxied server
             27         proxy_pass loadbalance;
             28     }
             29
             30 }
            這個大部分是官網支持的,所以其實我也沒有修改太多,就設置了幾個IP和端口。
            在編譯好nginx后,可以用/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx_stream_tcp.conf
            就可以起來了,可以通過netstat -tlnp查看是否起來,大致顯示這樣的:
            tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      7744/nginx_stream_t
            當然也可以通過telnet來查看。
            接下來,寫個簡單的cs程序來驗證下吧.

            server端:
            if __name__ == '__main__':
             import socket
             import commands
             sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             sock.bind(('192.168.1.21', 8001))
             sock.listen(5)
             while True:
              connection,address = sock.accept()
              print "connected by",address
              while 1:

                buf = connection.recv(1024)
                if buf != "" :
                 print "connection buffer", buf
                 connection.sendall(buf)
             connection.close()

            client端:
            if __name__ == '__main__': 
                import socket
                HOST='192.168.1.4'
                PORT=8001
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
                sock.connect((HOST, PORT))
                while 1:
                    cmd = raw_input("please input cmd:")
                    sock.sendall(cmd)
                    data = sock.recv(1024)
                    print data
                sock.close()

            在client向192.168.1.4發起一個TCP連接時,接下來192.168.1.4會連接到192.168.1.21,
            192.168.1.21的server端會顯示, connected by ('192.168.1.4',58559)
            后面的端口應該是隨機的臨時端口。
            其實它的確起到了轉發作用,這個nginx進程相當于一個通用網關,如果有兩個client向nginx進程發起連接,一旦nginx那邊調度到同一個上游TCP服務器,那么只需要從NGINX進程建立一個TCP連接到上游TCP服務器即可。
            之前我自己設計網關的時候,不是依賴于用戶的,而是通過靜態配置來建立連接的,比如上游邏輯服務器跟網關有連接,那都是在啟動服務器的時候,就建立起來了。
            這樣有個好處就是可以省事,不過也可以采用這種方式,有玩家連接進某個上游TCP服務器才讓網關跟這個TCP服務器建立連接,否則無需處理。因為不少時候還是會有不少服務器處于空閑的.

            posted @ 2016-03-11 08:44 jolley 閱讀(839) | 評論 (0)編輯 收藏

            2011年6月8日 #

            struct A
            {
             int a;// 裝備
             int b;// 角色數據
             char c;
            };
            void main( void )
            {
             //printf("hello world!");
             char buffer[] = "This is a test of the memset function";

             A aStruct;
             // 發現數據相同。
             memset(&aStruct,'*',sizeof(aStruct));
             printf( "Before: %s\n", buffer );
             memset( buffer, '*', 4 );
             printf( "After:  %s\n", buffer );
             if (buffer[2] == '*')
             {
              printf("hello,world\n");
             }
             // 判斷這個是否要保存。
             if (aStruct.a == 0x2a2a2a2a)
             {
              // 發送給DBSERVER.
              printf("hello char\n");
             }
             if (aStruct.c == 0x2a)
             {

             }
             getchar();

            posted @ 2011-06-08 20:30 jolley 閱讀(307) | 評論 (0)編輯 收藏

            2009年4月10日 #

            gamma系數就是灰度系數,改變gamma系數的值就是相當于改變色階(圖象亮度強弱的指數標準),gamma值越少,圖象越亮.
            調試d3d,將控制面板中D3DDebugging打開,進行調試,在選擇調試信息輸出等級的時候,可以選擇more來獲得更加多得詳細信息。
            http://nexe.gamedev.net/directKnowledge/default.asp?p=Debugging
            Direct3D9: (INFO) :MemFini!
            Direct3D9: (WARN) :Memory still allocated!  Alloc count = 152
            Direct3D9: (WARN) :Current Process (pid) = 00000fb8
            Direct3D9: (WARN) :Memory Address: 00c95988 lAllocID=1 dwSize=000047f8, (pid=00000fb8)
            這里是檢測出內存泄露了.
            一般是內存信息什么的沒有releasing和deleting掉.
            之前遇到的一個問題lock is not supported when multi-sampling is enabled是因為shader debugging打開了,之后關閉了,就沒有事情了。
            剛才編譯hlsl的時候,發現了x3025錯誤,后來的dx版本要使用D3DXSHADER_ENABLE_BACKWARDS_COMPATIABLITY|D3DXSHADER_DEBUG才能編譯,特別是2008年的dx版本。

             DX默認的是D3DFILL_SOLID,如果出現D3DFILL_WIREFRAME的情況一定要設置回去。
            CD3DArcBall:允許你將用戶的輸入解釋為旋轉或者平移.我們所要做的是將鼠標消息傳遞給這個類,并且將視圖矩陣設為類的旋轉或者平移矩陣就可以了.
            點乘: a.b = ||a|| *||b|| * cosA, 一般用來判斷為0,那么表明正交,>0,方向基本相同,<0,方向基本相反.使用點乘來計算投影.
            給定兩向量v,n,將其分解為v平和v垂,分別平行于和垂直于n,并且滿足 v = v平+v垂,一般成平行分量v平為v在n 上的投影.
            V平 = n * ||V平|| / ||n||.
            cosA = ||V平||/||V|| cosA||V|| = ||V平||
            V平= n*n*v/( ||n||*||n||).
            叉乘得到的向量垂直于原來的兩個向量.
            a *b指向該平面的正上方,垂直于a和b.
            ||a*b|| = ||a|| * ||b|| * sinA.
            ||a*b|| 也等于以a和b為兩邊的平行四邊形的面積.
            如果a,b平行或任意一個為0,則a*b = 0,叉乘對零向量的解釋是它平行于任意其他向量,點乘的解釋是和任意其他向量垂直.
            任意對角矩陣D,都有D轉置矩陣= D,包括單位矩陣.
            DirectX使用的行向量.
            v = xp+yq+zr,向量v就表示成p,q,r的線性變換了,向量p,q,r稱做基向量.這里基向量是笛卡爾坐標系
            變換物體相當于以相反的量變換描述這個物體的坐標系.
            2d里面是這樣設置的:
            逆時針旋轉經常(不是必須)被認為是正方向,順時針方向是負方向.
            繞x軸旋轉:
            [ 1 0 0        
            0 cosA sinA
            0 -sinA cosA]
            繞y軸旋轉:
            [cosA 0 -sinA
            0  1 0
            sinA 0 cosA]
            繞z軸旋轉:
            [ cosA sinA 0
            -sinA cosA 0
            0 0 1]
            繞軸n旋轉角度A,那么獲得的矩陣是:
            [nx*nx*(1-cosA)+cosA     nx*ny*(1-cosA)-nz * sinA  nx*nz*(1-cosA) + ny*sinA
            nx * ny *(1-cosA) - nz *sinA ny*ny*(1-cosA)+cosA  ny*nz*(1-cosA) - nx* sinA
            nx * nz *(1-cosA)+ny * sinA ny * nz *(1-cosA) + nx* sinA nz*nz*(1-cosA)+cosA]
            縮放:通過基向量構造矩陣,得到以單位向量n為縮放方向,k為因子的縮放矩陣:
            s(n,k) = [ p]     [ 1 + (k-1)nx2  (k-1)nxny   (k-1)nxnz]
                                =
                         [ q]     [ (k -1)nxny   1+(k-1)ny2   (k-1)nxnz]
                         [ r]     [(k-1)nxnz  (k-1)nzny   1+(k-1)nz2]

            投影意味著降維操作,有一種投影方法是在某個方向上用零做縮放因子,這種情況下,所有點都被拉平至垂直的軸(2D)或平面(3D),這種類型的投影稱做正交投影,或者平行投影,因為從原來的點到投影點的直線相互平行.
            n垂直于投影直線,而不是平行,3D中,向垂直于n的平面投影的矩陣如公式:
            p(N) =   [1-nx2 -nxny -nxnz]
                          [-nxny 1-ny2 -nynz]
                          [-nxnz -nzny 1-nz2]
            鏡像: 將物體沿直線(2D中)或平面(3D中)翻折.
            P(n) = [ 1-2nx2 -2nxny -2nxnz]
                      [-2nxny 1-2ny2 -2nynz]
                      [-2nxnz -2nzny 1-2nz2]
            Hxy的意義是x,y坐標被坐標z改變
            Hxy(s,t) = [1 0 0]
                            [0 1 0]
                            [s  t 1 ]

            Hxz(s,t) = [ 1 0 0]
                            [s  1 t]
                            [0 0 1]

            Hyz(s,t) = [1 s t]
                            [0 1 0]
                            [0 0 1] 

            M物體->像機 = M物體->世界M世界->像機
            P->像機 = P物體 M物體->像機
            線形變換: 如果滿足下式,那么映射f(a)就是線性的:
            f(a+b) = f(a) + f(b)
            以及F(ka) = kf(a).
            仿射變換: 線性變換后接著平移,因此仿射變換的集合是線性變換的超集.任何線性變換都是仿射變換,但不是所有仿射變換都是線性變換.
            如果存在一個逆變換可以"撤消"原變換,那么該變換是可逆的.
            如果變換前后兩向量夾角的大小和方向都不改變,該變換是等角.只有平移,旋轉和均勻縮放是等角變換.
            等角變換將會保持比例不變.
            平移,旋轉和鏡像是僅有的正交變換.長度,角度,面積,和體積都保持不變.
            剛體變換只改變物體的位置和方向,不包括形狀,所有長度,角度,面積和體積都不變.平移和旋轉是僅有的剛體變換,鏡像并不被認為是剛體變換.
            假設矩陣M有r行,c列,記法Mij表示從M中除去第i行和第j列后剩下的矩陣.顯然,該矩陣有r-1行,c-1列,矩陣Mij稱為M的余子式.
            posted @ 2009-04-10 16:56 jolley 閱讀(397) | 評論 (0)編輯 收藏

            2009年3月30日 #

            這幾天安裝這個sql server 2000,花掉了很多時間,希望以后安裝的時候,盡量避免出現這些情況,其它的錯誤情況就不說明了,現在只說明我遇到的問題的解決辦法:將原來的安裝目錄刪除掉,將c:\program files\Microsoft SQL Server下面的80目錄給刪除掉,將注冊表里面的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server以及HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer里面的鍵值信息刪除掉。我機器上面并沒有HKEY_LOCAL_USER\SOFTWARE\Microsoft\Microsoft SQL Server這個目錄的。
            application verifier 的信息可以從這里獲得:http://technet.microsoft.com/en-us/library/bb457063.aspx
            application verifier主要用來檢測指針引起的內存錯誤.在程序運行期間進行跟蹤內存使用情況.
            application verifier的log信息包括錯誤所在的調用堆棧,并且要注意及時地清除上次的錯誤記錄,我之前遇到的問題是,我用application verifier檢測到某個錯誤,而之后再用這個exedebug啟動的時候,就報錯,后來在application verifier里面清除了記錄才可以正常運行.
            posted @ 2009-03-30 08:46 jolley 閱讀(471) | 評論 (0)編輯 收藏

            2009年2月17日 #

            computer display = a single graphics adapter + a display monitor.
            graphics adapter contains the hardware needed store and display images on a monitor or other display device.
            all of these adapters stored a representation of the displayed image in a bank of dual-ported memeory called a frame buffer.
            the system uses one of the ports to read and write images into the frame buffer.the second port is used by the video scan out circuitry of the adapter to create a signal for the monitor.Direct3D only supports VGA compatible adapters.

            Frame                               Color Lookup
            Buffer                               Table


            2D Pixel                           D/A
            Engine                              Converter

            Host CPU                        CRT Monitor

            Direct3D abstractions include :device, swap chains, surfaces, and resource .

            an application enumerates the devices available on each adapter, examining their capablities and supported display modes to find an acceptable device.
            device is the object that expose the rendering operations of the hardware. its properties control the rendering behavior or provide information about rendering, while the device's methods are used to perform the rendering itself.

            devices always contain at least one swap chain and a collection of resources used for rendering.
            resources are application specific data stored in or near the device hardware for use during rendering Direct3D provides resources for scene geometry(vertices and indices) and appearance(images, textures, and volumes).

            a surface is a resource containing a rectangular collection of pixel data such as color, alpha, depth/stencil or texture information.
            a swap chain contains one or more back buffer surfaces where scenes are rendered and presented for display on the monitor, is a collection of back buffers.

            a device's render target is the back buffer surface, with an optional depth/stencil surface, in which rendering will occur.

            while all back buffers are valid render targets, not all render targets are back buffers.
            it is also possible to have a texture as a render target allowing dynamic rendering effects.

            to obtain a device object, Direct3D provides an object for device enumeration and creation. all other objects are created through the device. an application first obtains the runtime interface, then selects and creates a device from those available, and using the device creates the necessary resources for rendering.

            most COM methods return HRESULT to indicate success or failure.
            in windowed mode: the results of graphic rendering are presented for display insidei the client area of a window on the desktop.
            Direct3D cooperates with GDI to make the results of rendering visible, using a ::StretchBlt operation to present a back buffer in the window's client region
            in exclusive mode: Direct3D communicates directly with the display driver avoiding GDI. when an exclusive mode application is running, no other applications have access to display hardware and no GDI is visible on the screen.

            HAL(hardware abstraction layer): has hardware acceleration of graphics rendering, making it fastest device type.

            reference device: useful for debugging, when developing software applications that target new features not yet common in hardware, the reference device maybe your obly choice for generating an image with those Direct3D features.

            the null reference device: does nothing and all rendering will result in a black screen.useful for manipulating resources on a machine that provides no hardware or software  implementation of the runtime.

            the pluggable software device: RegisterSoftwareDevice method,

            each resource has Type, Pool, Format, and Usage attributes, each of these attributes of a resource are specified at the time the resource is created and remain constant for the lifetime of the resource object.
            type attributes describes the kind of resource and is defined by D3DRESOURCETYPE.
            pool attribute of a resource describes how it is managed by the Direct3D runtime and is defined by the D3DPOOL enumeration.
            resources in the default pool exist only in device memory.
            resources in the managed pool exist in system memory and will be copied into the device's memory by the runtime when needed.
            resource in the system memory pool exist only in system memory
            resource in the scratch pool reside only in system memory and are not bound  by format constraints of the device
            when a device is lost, all resources in the default pool are lost and should be released and recreated by the application when the device is regained.
            Format attribute of a resource describes the layout of the resources's data in memory and is defined by the D3DFORMAT enumeration.

            all resources have a format, but most of the format enumerants define the memory layout for pixel data.
            D3DFMT_D24S8: D:depth buffer, S:stencil buffer.

            Usage attribute describes how the application will be use the resource and is defined by a collection of flag bits. static reources are typically loaded with data once and used repeatedly without change, while dynamic resources are repeatedly modified bu the application.
            a direct3D application starts by obtaining the IDirect3D9 COM interface pointer by calling Direct3DCreate9.
            GetAdapterCount is to determine the number of adapters in the system. each adapter provides a number of video display modes. each display mode contains a screen dimention, refresh rate and pixel format and is described by D3DDISPLAYMODE structure.
            the back buffer surface format of a device must be compatible with the display mode's format. CheckDeviceFormat method can be used to discover compatible formats.
            GetAdapterModeCount: the number of display modes.
            EnumAdapterModes: the display mode information.
            GetAdapterDisplayMode: the display mode currently in use by the adapter.
            two display modes can have the same width, height and format values but different values for the RefreshRates.
            the CheckDeviceType method tells us if a particular combination of display format and back buffer format are valid for a device of a given type operating in windowed or exclusive mode.
            with a valid device type, we can check the device's capabilities for rendering required by our application with GetDeviceCaps.

            we can validate all the resources required by our application with the CheckDeviceFormat, checkDeviceFormat should be used to validate all the format of all resources used by the application: back buffer surfaces, depth/stencil surfaces, texture surfaces, and volume texture formats. if the application requires a depth buffer for viaiblitiy determination, it should use CheckDepthStencilMatch to find a depth buffer that can be used with its render target formats in a given display mode.
            CheckDeviceMultiSampleType: check multisampling needs.
            GetAdapterIdentifier: allows an application to identify a specific brand of adapter from a specific vendor.
            D3DCREATE_ADAPTERGROUP_DEVICE: allows an application to drive both video outputs through a single device interface, allowing resources to be shaed for both outputs.
            Direct3D uses single precision floating point computations. if an application requires higher precision from FPU.there are two choices, either the application can ensure that the FPU is in single precision mode when calling into Direct3D, or ir can request that the device preserve the application's FPU precision before Direct3D performs any floating -point operations and restore the precision before returning to the application.
            D3DCREATE_SOFTWARE_VERTEXPROCESSING: select software vertex processing, which is always available from the runtime.the runtime used an efficient implementation of software vertex processing that is optimized for the CPU.
            D3DCREATE_MIXED_VEVERTEXPROCESSING: select a combination of software and hardware vertex processing selected by SetSoftwareVertexProcessing mixed vertex processing is incompatible with a pure device and will fail if both are requested together.

            D3DPRESENTFLAG_DEVICECLIP: restricts the results of a present operation to the client area of the device window in windowed mode.
            D3DPRESENTFLAG_DISCARDDEPTHSTENCIL: instructs the runtime to discard the contents of the depth stencil surface after a call to Present, or when a new depth stencil surface is set on the device.
            D3DPRESENTFLAG_LOCKABLEBACKBUFFER: requests a default swap chain with back buffer surfaces that can be directly accessed by the application.
            in windowed mode: hDeviceWindow specifies the window whose client area will be used for presentation in windowed operation  if hDeviceWindow is zero, then the focus window willbe used for presentation.
            in exclusive mode, hDeviceWindow specifies the top-level window used by the application

            D3DPRESENT_RATE_DEFAULT: instructs the runtime to choose a suitable refresh rate in exclusive mode, and uses the current refresh rate in windowed mode.
            an application may wish to create a full-screen display on a specific monitor.
            GetAdapterMonitor: return an HMONITOR handle for an adapter, once you have the handle to the device 's montior, u can determine what part of the virtual desktop is covered by the monitor.

            a scene is a collection of three dimensional objects that are projected onto the render target surface from the viewpoint of a syntheitic camera
            each object in a scene is described by a collection of geometric primitives, such as points, lines, and triangles, with the device's action methods. 
            the pipeline converts geometric descriptions into pixels on the render target surface through the process of rasterization. graphic primitives are rendered in the order in which they are described to the devices similar to the way a CPU executes binary instructions sequentially through memory.
            the entire graphics pipeline is controlled through the properties of the device.
            the properites are manipulated through the Get/Set methods of the device.
            every device has a distinct set of capabilities. Direct3D specifies an abstract machine interface, but does not provide a software emulation for a feature not provided directly by the hardware's driver.
             a device provides specific information on its capabilities to allow an application to adapt to the capabilities of the device.
            much of the behavior of the graphics pipeline is controlled by render states.
            groups of device properties, including render states, can be cached and set as a group with state blocks.
            the device object represents the rendering pipeline, we get images from the pipeline by supplying it with scene data and instructing it to render scenes into images.
            scene data consists of geometric data defining shapes in space and data defining the appearance of the shapes.
            we can break the pipeline up into large sections consisting of vertex data assembly, vertex processing, promitive assembly and rasterization, pixel processing, the frame buffer,a dn video scan out.

            vertex data assembly section gathers together vertex components from a collection of data streams to assemble a compute vertex and its associated data.
            vertex processing performs computations on each vertex such as the transformation and lighting of vertices.the processed vertex data is then assembled into graphic primitives and rasterized into a stream of pixels.
            pixel processing performs a computations on each rasterized pixel to determine the final color of the pixel that will be written into the frame buffer.
            frame buffer performs a read/modify/write operations combining processed pixels from the rasterizer with the existing pixels in the render ttarget.
            video scan out reads the pixels out of the frame buffer for conversion into video signals displayed by the monitor.

            scenes are rendered to the render target selected on the device. if the render target is part of a swap chain, the render target can be made viaible on the device through presentation.
            the render target may not be part of a swap chain if the render target is a texture resource.
            you present renderings for display through a swap chain as the last thing you do when rendering a scene.
            a swap chain consists of one or more back color buffers into which images are rendered. a device is always associated with at least one swap chain and in windowed mode additional swap chains can be created to obtain multiple presentable surfaces.
            the philosophy of the Direct3D object is to expose the capabilities of the hardware to the application programmer and let the application adapt to the hardware.
            GetDeviceCaps: return the capabilities of an actual device, while GetDeviceCaps method on the Direct3D object returns the generic capabilities of a device.
            IUnknown 
                  IDirect3DVolume9
                  IDirect3DResource9
                       IDirect3DIndexBuffer9
                       IDirect3DVertexBuffer9
                       IDirect3DSurface9
                       IDirect3DBaseTexture9
                           IDirect3DTexture9
                           IDirect3DCubeTexture9
                           IDirect3DVolumeTexture9
            resource objects are used as containers for the scene data rendered by the device such as primitive vertices, indices intto vertex arrays, surface textures and volumes. 
            two and three dimensional textures expose their contents as collections of sutfaces and volumes, respectively. the back buffer, depth/stencil buffer and render target properties of the device are also exposed as surfaces.
            volume objects do not inherit from IDirect3DResoutce9 and therefore do not participate in the resource management exposed by this interface.
            managed resources are assigned an unsigned integer priority, with higher priority taking precedence so that resources with a lower priority are discarded from device memory first.
            non-managed resources always return a priority of zero. within the same priority, Direct3D uses a least-recently used strategy to discard old resoucrs in preference to newly created resources.
            when the application attempts to use more resources than the card can hold while rendering a scene, Direct3D switches to a most-recently used first strategy for discarding memory.
            resources in D3DPOOL_DEFAULT are not managed and are never discarded from device memory by the resource manager.
            if u need to allocate new resources in the default pool after managed resources have been loaded, you should evict all managed resources before allocating new resources in the default pool.
            resources in pool D3DPOOL_SYSTEMMEM are never located in device memory, so that they do not participate in resource management.
            GetAvailableTextureMem: obtain an estimate of the available texture memory.
            the GetDevice method returns the device with which this resource is associated. resources cannot be shared across devices.
            GetPrivateData/SetPrivateData: allow an application to associate its own arbitrary chunks of data with any Direct3D erouces.
            each distinct item of private data is identified by a GUID. all private data associated with a resource is freed when the associated resource itself is freed.
            methods and functions in Direct3D that create COM objects, such as CreateDevice, add a reference to the object for the caller before they return the interface pointer, the application must release these objects when they are no longer needed to avoid a memory leak.
            Device queries allow you to obtain information from the driver layer of the device, the two main uses for driver queries are for obtaining rendering statistics and event notifications from the device.
            D3DQUERYTYPE enumeration gives the possible kinds of queries: vertex cache description queries, resource manager statistics queries, vertex statistics queries, event queries, occlusion queries, timestamp queries, time queries and cache utilization queries.
            a query exists in one of three state: signaled, building, or issued.
            Issue: used by the application to signal a state transition on the query.
            the device driver can also change the state of a query when it has returned the data requested by the query.
            the query will report the results for primitives issued between the begining of the query and the end of the query.
            occlusion queries return the number of pixels that passed the depth test for primitives rendered between the begin and end of the query.
            the resource manager statistics query returns a D3DDEVINFO_RESOURCEMANAGER structure, which contains an array of D3DRESOURCESTATS structure, one for each resource type.
            the vertex cache is a memory cache close to the GPU that avoids access to vertex memory for a small number of recently used vertices.
            PIX: is a performance measurement tool for DirectX applications. the remaining query types return data for performance measurements with tools like PIX.
            the device object's properties control the behavior of the rendering pipeline while its methods supply data for the pipeline to render.

            state blocks are COM objects that provide a way for your application to cache a group of device properties for later use.
            each state block is associated with a device, returned by the GetDevice method.once  a state block has been created, the state block can be applied to the device by calling apply on the state block, calling capture on an existing state block captures the current values of the device properties into the state block.
            there are two ways to create a state block object and fill it with specific device property values.
            the first way: call CreateStateBlock with D3DSTATEBLOCKTYPE value identifying the kind of state you  want recorded in the block.
            the second way of obtaining a state block object is to call BeginStateBlock, set device properties and then call EndStateBlock.
            when EndStateBlock is called, each device property marked for capture is recorded into the state block. if a device property is set multiple times between BeginStateBlock and EndStateBlock, only the last value set in the property is captureed into the state block.
            release the state block COM object when you are finished with a state block.
            a pure device has a performance advantage because the runtime and driver do not have to keep a copy of the non-queryable state for the application.
            scenes contain one or more objects that are positioned relative to each other and to the virtual camera that views the scene. such objects are called "models", and contain data that define their shape and apperance. the shape of a model is described by a collection of a simple geometric shapes, called graphic primitives.
            when we draw a three dimensional scene, we need to solve the problem of visibility: objects in the foreground should occlude objects in the background. Two- dimensional applications use a painter's algorithm to determine visibility. Direct3D can use depth/stencil surfaces to resolve visibility.

            using either a flexible vertex format or a vertex shader declaration, Direct3D describes colors, textures corrdinates,vertex blending weights and arbitrary shader data at each vertex.the vertex data is supplied to the device through a collection of streams, each associated with a vertex buffer.
            the streams can be driven through a level of indirection with an index buffer.the streams can be driven though a level of indirection with an index buffer.
            the scene is described to the device one primitive at a time. each primitive  is rasterized into a collection of pixels written to the render target property of the device.
            All Direct3D rendering is done within a scene. each successive frame draws the models at successive moments in time, as in cel animation used for cartoons.
            frame rates of greater than 15 fps can be preceived as "real-time", the z-buffer algorithm solution to the visibility problem works at each pixels on the render target instead of on models, as models are rasterized, each pixel that is associated with z value is used to determine which pixel is cloest to the camera.the closer pixels are stored into the render target, while pixels farther away are discarded. the depth/stencil buffer holds each pixel's depth from the camera. to use the Z-buffer for resolving visibility, set RS_Z Enable to D3DZB_TRUE, RS_Z Write Enable to TRUE, and RS_Z Func to D3DCMP_LESS.

            if the D3DPRASTERCAPS_ZBUFFERLESSHSR bit of D3DCAPS9:RasterCaps is set, it indicates the device has an alternative visivility algorithm for hidden surface removal that doesn't use a Z-buffer. how visibility is determined is hardware dependent and application transparent. 

            all back buffers on swap chains are valid render targets, but render targets are not restricted to back buffer surfaces, when the device is created or reset, the render target is back buffer zero of the device's default swap chain. when present is called on the device, the render target  advances to the next back buffer so that after present returns, render target is back buffer zero again.

            setting the render target to a surface other than a back buffer surface allows the device to render directly into an imanage surface instead of rendering into a swap chain's back buffer and using stretchrect to obtain the results of the rendering, which could stall the pipeline.

            D3DPT_POINTLIST draws a collection of points,
            D3DPT_LINELIST draws a squence of possibly disjoint line segments.
            posted @ 2009-02-17 15:49 jolley 閱讀(692) | 評論 (0)編輯 收藏

            2009年1月31日 #

             // 接受密聊對方名稱,將焦點設置到聊天輸入框中,并且將光標設置為第一個位置
             // 參數1:密聊用戶名,參數2:頻道信息
             static bool ChangeChannelAndSetFocus(char* username,Channel channel);
            這段代碼看起來是沒有事情的,但是在接口設置上面存在不好的做法,如果是私密頻道的話,是有用username做私聊對象的,如果是非私聊頻道的話,就沒有這個私聊對象了.但是如果要調用這個接口的話,還得給個這樣的值.
            比如這樣的用法:->ChangeChannelAndSetFocus("",public_channel),
            其實如果稍微改變一下接口設置的話,就好了.
             static bool ChangeChannelAndSetFocus(Channel channelchar* username = "");
            這樣使用默認參數就好了.
            之前的調用就可以這樣使用了.
            :->ChangeChannelAndSetFocus(public_channel),看起來舒服多了.哎感覺編程功底還有待加強,這么簡單的問題,拿出來想想,還有這么多學問呢.

            這幾天寫了一段函數代碼,后來被一個家伙調用了,他直接在我的函數里面修改,這樣造成了原來我函數里面的邏輯出現錯誤,現在想來,如果以后是這樣的情況,就不能允許他在我的函數里面修改我的邏輯和相關調用,但是要留出接口給它調用,至于具體的操作,要我自己允許才能添加,當然我可以幫他看看原來他添加的代碼,但是這樣也就沒有什么意義了.這種合作性的工作尤其要講究這些,不然很麻煩的.


            突然想起來要記錄點什么,調試引擎的時候,可以采用這樣的方式,打開上層邏輯的工程,然后將引擎相關的代碼拖拽到上層邏輯所在的工程里面去,然后在這個代碼里面可以設置相關斷點,以前總不知道怎么找上層邏輯與底層引擎的入口,最近終于知道了.呵呵.通過這樣的方法,就可以在上層邏輯做某些操作,然后關聯這些邏輯相關的引擎代碼.

            今天一直在被單態困擾著,事情是這樣的:大廳和戰斗場景里面都有兩個類似的chatroom,并且他們各自使用的協議是不一樣的.現在想把他合并起來做成類似singleton的東西. 之前就遇到一個問題,大廳和戰斗場景不能在相互之間發送信息,后來我的處理方法是將戰斗場景里面添加大廳里面的響應事件,這樣的話,在大廳里面發送私聊信息到戰斗場景里面,就可以接受到了,但是后來發現在戰斗場景里面發送信息到大廳里面,卻接受不到,并且這個時候,在大廳和戰斗場景里面已經存在很多冗余代碼了,這樣的處理讓我感覺很不爽,我在想有沒有其它辦法,后來請教了老大,老大幫忙解釋了一下,后來,在協議處理方式上面修改了一下,才可以的。chatroom在不同的時候發送不同的協議就好了,并且在接受的時候分開大廳和戰斗場景處理就好了,這樣還是用了接受、和發送這兩段廢代碼。對于singleton的了解還是不夠好。 

            之前遇到的問題,是聊天發送消息并不立即顯示在本地,而要先將信息轉到服務端,服務端進行查詢,如果能夠找到這個私聊對象,那么就返回給信息,否則就顯示說該用戶不存在,在戰斗場景里面向大廳的某個玩家發送私聊信息以后,退出戰斗場景以后,發現大廳里面還顯示著在戰斗場景里面發送的聊天信息。這樣即使我按照常規思路去把網絡接受端的相關代碼注釋掉也不能達到消除大廳里面的聊天信息的目的,感覺很郁悶。后來查看私聊信息方面的代碼,發現沒有將信息有效地攔截,私聊信息在本地上面還可以被顯示,沒有經過網絡方面的驗證就直接發送過來了。在私聊信息方面做一些處理并且在退出戰斗場景的時候做一些信息刪除處理,這樣就可以達到目的了。
            因為玩家對象位置數據是從服務器那邊發送過來的,玩家從服務器獲得數據需要一段時間,所以需要加入一個插值,來將現在的位置過渡到下一個的位置.這里可以采用多種插值方法.

            今天寫了代碼去改寫強制動作的處理,結果發現很多處是有問題的,其中原因是沒有將原來的代碼作用看仔細造成了,感到羞愧呢,

            另外在編寫交互性比較強的代碼時,一定要考慮自己的代碼可能帶來的影響。

            更新某個文件比較麻煩的話,那么可以先采用原始文件刪除,并且重新全部更新的做法去做,而不是用更新某個字段的方法去做.

            如果沒有初始化聲音設備成功的話,那么應該可以彈出提示信息框,并且將原始聲音音量設置為0.

            之前在修改一個bug(在人物控制面板打開以后,一直克隆object,造成了在引擎底層無法鎖定vertexBuffer的問題),開始以為是內存泄露了,在打開控制面板10分鐘以后,游戲就突然出錯了,還一度想用一些輔助工具來查找內存的信息是否出錯,后來發現在人物控制面板里面克隆了過多的人物object,而這些object卻沒有及時地刪除,造成占用過多的資源,到最后連鎖住vertex buffer也不行了.在分析這個問題上面的時候,我還是一個勁地挖底層而沒有考慮太多的邏輯層面的東西,實在有點南轅北轍的味道.值得反省.

            在輸入的使用上面,一般的游戲都采用directInput,即使是U2,上次遇到的問題是,在一同事機器上面運行輸入的時候就進入不了,但是在別人的機器上面卻可以運行好好的,后來經常查訪發現:1)用配置文件寫入的,之后再綁定到某個特定鍵的快捷鍵都不能用,因為這些是讀入內存以后,然后用add_binding來綁定到directInput設備上面的,2) 在游戲里面使用windows message的卻可以正常使用.進入游戲的時候,你不能輸入,而只能回車,按tab鍵以后,就可以在登陸界面輸入,如果不能按tab鍵,則不能輸入,進入游戲以后卻可以按不是從配置文件里面讀取的信息,比如技能,人物面板,倉庫,以及地圖等.
            其中我個人建議是,盡量不要用directInput.1)首先是directInput依賴于機器,如果機器好的話,那么沒事情,如果有事情的話,那么也很難解決,2)directInput里面采用了hook,來攔截消息,這樣,還不如直接用windows message來的快?
            http://www.gamedev.net/community/forums/topic.asp?topic_id=520366
            詳細的討論見上面.

            在調試邏輯沒有發現什么錯誤提示的時候,試著去調試引擎,可能問題發生得更加深,不在邏輯層面上,而在引擎內部,這樣就要直接調試引擎了.

            在涉及到渲染方面的bug,盡量借用d3ddebugging來輔助查錯.這樣可以方便解決問題.

            連接錯誤:IID_IDirectSound3DBuffer,其實加上dxguid.lib就好了。
            紋理尋址模式包括:
            wrap, border color, clamp,和mirror以及mirror once.
             pDrawPrimInternal->SetTexture(hTex);
            之前遇到的一個問題是,顯示玩家在小地圖上面到地圖邊界了,還能重復繪制地圖,給人的感覺好像是走不到邊界,走地圖好像是在卷軸里面一樣。
            后來才知道一般默認的紋理尋址模式是wrap方式。
             get_device()->SetSamplerState(0,D3DSAMP_BORDERCOLOR,0x00ffffff);
             get_device()->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
             get_device()->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);

            解決bug有時候不如重寫
            盡量讓策劃去管理邏輯,邏輯程序員盡量將重心放在具體技術問題上面,不懂的地方應該主動跟策劃溝通,而不是自己想。
            代碼可以先模擬出來,然后再放到具體的環境里面測試,獨立寫個demo之后再去測試,這樣往往會比較快捷和省事情。
            學會模擬機器執行代碼的次序,并且提高閱讀代碼的問題,之前的時候,我使勁去調試,每次調試只為了解決一個問題,但是事實上,如果從閱讀代碼開始的話,那么我可以省掉1天的時間。
            學會調節編寫代碼時候的心情和心態,這樣有助于進行高效編程,當心情不好的時候,一定要集中全部的注意力,并且將思路和流程作出圖記載在紙上面,這樣可以強迫自己全神貫注。

            今天遇到的文件打開問題是文件名路徑有空格造成的,值得指出的是對于文件打開報錯,一般很難獲得返回值信息,但是可以通過GetLastError或者@Err,以及hr等來獲得一些錯誤返回值信息。

            對字符串操作,盡量要檢查是否有空格,如果字符串長度前面有空格的話,那么將被認為所提供的字符串是空的。要避免這種情況的發生。對于字符串匹配要注意部分匹配的情況,比如"Tex", "Text",這里如果只匹配前面三個字符的話,那么兩者是相等的,之前就遇到一個這樣的問題,就是texture的信息被text信息所覆蓋了,導致控件找不到正確的texture而不能顯示出來。 

            今天遇到的問題是這樣的,之前遇到的狀態切換問題,是與狀態切換無關,而與插值有關,在切換狀態以后,收到一個插值位置,這樣又給角色一個新的位置,給別人看的效果就是角色先落地了,之后又上升了,像坐電梯一樣。不過從這里說明了一個問題:我在思考問題的時候,有欠周全的因素。

            今天跟蹤一個bug,在戰斗的時候,出現卡死的情況,后來發現狀態切換出現了問題,后來一直去查看戰斗方面的狀態,但是還沒有發現什么結果,現在在想在戰斗中的標志或者狀態的時候應該設立一些標志集合,這樣便于在某個時候檢查一些狀態的信息。現在很多的標志在游戲里面,局部的,全局的,標志在角色上面的,標志在物體上面的,這些都需要好好地管理。

            全方面,多角度地思考問題,而不能將思維局限在某處.學會從大局或者小處去分析問題,大處不行的話,就小處,將相關的信息串起來.所有的信息應該是個串型或者鏈型的.之前在處理問題的時候,把思路限制在太小的范圍內了.以至于花了很多時間才找到問題所在.

            根據正常情況和非正常情況來獲得數據比較,以確定正確的流程和結構。如果遇到錯誤的亂值,那么就看看正常的數值,然后根據這個比較來獲得一些提示信息。

            今天犯了錯誤,自己有最新版本,但是沒有上傳,結果vss上面的版本把自己的最新版本給覆蓋了。

            在發送消息的時候,有時候為了防止頻繁發送消息,要加入一個cd時間,防止因為網絡問題,服務端收到玩家連續的信息。

            物理系統, v = v0 - gt. 玩家上跳的速度表示,而在下降,則是v = gt,按照自由落體運動來進行.并且速度是個向量,這樣如果在X,Z軸上面有初速度的話,那么就可能出現拋物線的情況.



            posted @ 2009-01-31 08:23 jolley 閱讀(468) | 評論 (2)編輯 收藏

            26uuu久久五月天| 嫩草影院久久99| 亚洲综合伊人久久大杳蕉| 国产激情久久久久久熟女老人| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 大蕉久久伊人中文字幕| 久久亚洲中文字幕精品一区| 婷婷五月深深久久精品| 91精品免费久久久久久久久| 亚洲AV伊人久久青青草原| 99久久久精品免费观看国产| 亚洲午夜久久久| 久久99精品综合国产首页| 要久久爱在线免费观看| 国产一久久香蕉国产线看观看| 女人高潮久久久叫人喷水| 国产成人精品久久亚洲| 久久久久无码精品国产不卡| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 久久久久AV综合网成人| 伊人久久大香线蕉综合网站| 亚洲国产成人久久精品动漫| 久久精品国产亚洲77777| 无码国内精品久久综合88| 国产国产成人久久精品| 久久国产精品国产自线拍免费| 伊人久久大香线焦AV综合影院 | 亚洲AV无码一区东京热久久| 久久久久久久综合综合狠狠| 国产午夜久久影院| 欧美亚洲另类久久综合| 精品久久久久香蕉网| 国产精品对白刺激久久久| 99久久人妻无码精品系列蜜桃| 亚洲午夜久久久久久噜噜噜| 久久人妻AV中文字幕| 久久久久免费精品国产| 一级a性色生活片久久无少妇一级婬片免费放 | 97久久久久人妻精品专区| 久久精品天天中文字幕人妻| 日韩乱码人妻无码中文字幕久久|