• <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++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              37 Posts :: 1 Stories :: 12 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(9)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            2016年5月10日 #

             

            Nginx開發(fā)第三方模塊實(shí)例

            Ø 序言

            Nginx是一個(gè)極具擴(kuò)展性的服務(wù)器,這顯著體現(xiàn)在對第三方模塊的支持,開發(fā)者能夠?qū)⒆约洪_發(fā)的模塊,按照nginx既有的規(guī)則,完美地融合進(jìn)http框架中,以實(shí)現(xiàn)開發(fā)者定制功能的作用。

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

            Ø 如何將HTTP模塊嵌入nginx

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

             

            1)      Config文件+configure腳本

            Config文件

            這個(gè)是指提供config文件,并且在文件里面給出三個(gè)配置項(xiàng),就可以達(dá)到效果。這三個(gè)配置項(xiàng)是指:

            A.      Ngx_addon_name就是自己要開發(fā)的這個(gè)模塊名字。

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

            HTTP_MODULES = “$HTTP_MODULES ngx_http_helloworld_module”

            C.        NGX_ADDON_SRCS這個(gè)顧名思義,就是指定新添加文件的路徑,不過這個(gè)都是相對路徑,因?yàn)樵?/span>configure的時(shí)候就指定了上層路徑,比如--add-modules=PATH

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

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

            Configure腳本

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

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

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

            a)      Auto/modules

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

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

            b)         生成模塊信息

            一、生成模塊數(shù)組

            根據(jù)需要開啟的模塊加載對應(yīng)的模塊,下面是開啟http模塊后的所需要的模塊
             

            二、生成ngx_modules.c文件

             

            b)      Auto/make

            顯而易見,這個(gè)就是負(fù)責(zé)編譯相關(guān)的模塊。

            1)         生成第三方源碼

            2)         生成鏈接代碼,并將目標(biāo)文件,庫文件鏈接成二進(jìn)制程序


            2)      手動(dòng)方式

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

            Ø 開發(fā)第三方模塊注意事項(xiàng)

            首先,要確定針對那個(gè)模塊進(jìn)行開發(fā),nginx的模塊是有順序性的,比如: HTTP_MODULES = “$HTTP_MODULES ngx_http_helloworld_module”

            其次,因?yàn)?/span>nginx是異步非阻塞的,在編制代碼時(shí),一定要注意不能阻塞nginx進(jìn)程.

            Ø 示例

            見附件/Files/jolleydtan/test.zip

             

             參考:

            深入理解nginx. 

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

            2016年4月16日 #

            游戲服務(wù)器框架設(shè)計(jì)

            Ø  序言

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

            文章主要目標(biāo)人群是,對服務(wù)器框架設(shè)計(jì)感興趣,有從事過游戲框架設(shè)計(jì)的同學(xué)。

            文章內(nèi)容,介紹五大設(shè)計(jì)原則以及給出兩個(gè)示例,最后做總結(jié)。

            Ø  設(shè)計(jì)原則

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

            1.         業(yè)務(wù)邏輯開發(fā)

            a)         比如游戲?yàn)榱嗽黾哟鎯?chǔ),你就需要考慮使用內(nèi)存數(shù)據(jù)庫還是弄個(gè)數(shù)據(jù)庫網(wǎng)關(guān)服務(wù)器來處理。

            b)         比如游戲?yàn)榱斯芾碛螒蛲婕屹~號,以及支持對平臺賬號的接入,那么就需要賬號服務(wù)器。

            c)         比如游戲?yàn)榱斯芾碛螒蛲婕矣唵魏透櫢顿M(fèi)情況,可能就需要支付服務(wù)器,如果游戲類型是計(jì)時(shí)收費(fèi)的話,那么可能會(huì)需要計(jì)時(shí)服務(wù)器。

            2.         運(yùn)營維護(hù)

            a)         配置

            這里牽涉到靜態(tài)配置和動(dòng)態(tài)配置的問題,假設(shè)現(xiàn)在有一臺網(wǎng)關(guān)服務(wù)器和三臺游戲邏輯服務(wù)器,靜態(tài)配置的話,就是網(wǎng)關(guān)服務(wù)器這邊寫死只連接這三臺服務(wù)器,然后讓網(wǎng)關(guān)服務(wù)器主動(dòng)去連接,動(dòng)態(tài)配置的話,就是讓這三臺服務(wù)器知道這個(gè)網(wǎng)關(guān)服務(wù)器的地址,然后自己在啟動(dòng)的時(shí)候去連接。

            b)         開啟或者關(guān)閉順序

            這主要是看各個(gè)服務(wù)器上面負(fù)責(zé)什么功能以及服務(wù)器上面的相關(guān)功能,拿游戲登陸服務(wù)器,游戲邏輯服以及數(shù)據(jù)庫網(wǎng)關(guān)服務(wù)器這三個(gè)服務(wù)器的架構(gòu)來說,比如開啟的時(shí)候,你盡可能地跟玩家登陸連接的順序相反, 一般都是數(shù)據(jù)庫網(wǎng)關(guān)服務(wù)器,然后才是游戲邏輯服,最后才是游戲登陸服務(wù)器,其實(shí)就是防止玩家過早地登陸進(jìn)來,卻發(fā)現(xiàn)數(shù)據(jù)還沒有準(zhǔn)備好。

            關(guān)閉的順序其實(shí)就是相反的,主要原則就是讓數(shù)據(jù)盡可能地保存好,并且讓玩家不再進(jìn)來。

            c)         動(dòng)態(tài)增刪改

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

            d)         服務(wù)器管理

            服務(wù)器的管理主要在服務(wù)器的在線離線狀態(tài)的管理,中心服務(wù)器(用來管理其它服務(wù)器)必須實(shí)時(shí)知道所管理服務(wù)器的狀態(tài),比如網(wǎng)關(guān)服務(wù)器必須要實(shí)時(shí)知道游戲邏輯服的狀態(tài),這樣才好更新到登陸服務(wù)器上面,更改服務(wù)器狀態(tài)。基本上在眾多同級服務(wù)器上面基本上都會(huì)有個(gè)中心服務(wù)器。

            3.         性能效率

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

             

            4.         負(fù)載均衡

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

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

            5.         安全性

            這里說下網(wǎng)關(guān)服務(wù)器,其它地方也叫前置服務(wù)器,front-end servers,,這個(gè)有幾個(gè)好處:1)隱藏游戲邏輯服的連接信息. 2) 統(tǒng)籌游戲邏輯服的負(fù)載信息。

            Ø  服務(wù)器框架示例

            1)         無中心服務(wù)器架構(gòu)

            2)         有中心服務(wù)器架構(gòu)

            Ø  結(jié)論

            服務(wù)器框架設(shè)計(jì)更像一門藝術(shù),需要在解決問題的同時(shí),又需要注意平衡得失。

             




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

            2016年4月2日 #

            實(shí)現(xiàn)這個(gè)有這三種辦法:
            1)隨機(jī)排序,按照順序先后取出M個(gè)數(shù)字。
             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 }
            這個(gè)呢,不會(huì)影響源數(shù)組,這個(gè)
            2)取M次,每次做個(gè)事情就是隨機(jī)出一個(gè)數(shù),添加到目標(biāo)數(shù)組里面,然后從源數(shù)組中刪除。。
            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 }
            這個(gè)呢,會(huì)影響源數(shù)組。
            3)取M次,借助一個(gè)輔助數(shù)組記錄哪個(gè)數(shù)據(jù)被取過,隨機(jī)出一個(gè)數(shù),添加到目標(biāo)數(shù)組里面,然后將這個(gè)值添加到輔助數(shù)組里面.
             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--;// 如果已經(jīng)取過了,這次不算.
            177         }
            178
            179     }
            180     return desVec;
            181 }
            posted @ 2016-04-02 11:51 jolley 閱讀(1277) | 評論 (0)編輯 收藏

            2016年3月23日 #

            這個(gè)是改良版的二分查找樹,是通過閱讀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日 #

            現(xiàn)在nginx的版本已經(jīng)到了1.9.12,不過在1.9.0的時(shí)候,就開始了對TCP代理服務(wù)器的支持。
            之前也有一些早期的做法,比如就有寫了nginx_tcp_module模塊的https://github.com/yaoweibin/nginx_tcp_proxy_module,
            以及nginx_stream_lua模塊的
            https://github.com/openresty/stream-lua-nginx-module
            本來就想著用這兩個(gè)的,后來發(fā)現(xiàn)已經(jīng)有支持了,就先來試試看看這個(gè)了。
            默認(rèn)的話,nginx是沒有開啟對tcp的支持的.如果要支持的話,需要用--with-stream去指定。
            我這邊只要需要三個(gè)IP,一個(gè)是nginx進(jìn)程所在的機(jī)器,我這邊用192.168.1.4表示,
            另外兩臺就是TCP上游業(yè)務(wù)服務(wù)器,我們分別用192.168.1.5和192.168.1.21來表示,
            基于這樣的考慮是因?yàn)閚ginx充當(dāng)tcp代理服務(wù)器后,自身也會(huì)占用一個(gè)端口。
            并且從目前來說,貌似一個(gè)nginx進(jìn)程也就只能listen一個(gè)端口。
            我用的版本是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 }
            這個(gè)大部分是官網(wǎng)支持的,所以其實(shí)我也沒有修改太多,就設(shè)置了幾個(gè)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
            當(dāng)然也可以通過telnet來查看。
            接下來,寫個(gè)簡單的cs程序來驗(yàn)證下吧.

            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發(fā)起一個(gè)TCP連接時(shí),接下來192.168.1.4會(huì)連接到192.168.1.21,
            192.168.1.21的server端會(huì)顯示, connected by ('192.168.1.4',58559)
            后面的端口應(yīng)該是隨機(jī)的臨時(shí)端口。
            其實(shí)它的確起到了轉(zhuǎn)發(fā)作用,這個(gè)nginx進(jìn)程相當(dāng)于一個(gè)通用網(wǎng)關(guān),如果有兩個(gè)client向nginx進(jìn)程發(fā)起連接,一旦nginx那邊調(diào)度到同一個(gè)上游TCP服務(wù)器,那么只需要從NGINX進(jìn)程建立一個(gè)TCP連接到上游TCP服務(wù)器即可。
            之前我自己設(shè)計(jì)網(wǎng)關(guān)的時(shí)候,不是依賴于用戶的,而是通過靜態(tài)配置來建立連接的,比如上游邏輯服務(wù)器跟網(wǎng)關(guān)有連接,那都是在啟動(dòng)服務(wù)器的時(shí)候,就建立起來了。
            這樣有個(gè)好處就是可以省事,不過也可以采用這種方式,有玩家連接進(jìn)某個(gè)上游TCP服務(wù)器才讓網(wǎng)關(guān)跟這個(gè)TCP服務(wù)器建立連接,否則無需處理。因?yàn)椴簧贂r(shí)候還是會(huì)有不少服務(wù)器處于空閑的.

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

            2011年6月8日 #

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

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

             }
             getchar();

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

            2009年4月10日 #

            gamma系數(shù)就是灰度系數(shù),改變gamma系數(shù)的值就是相當(dāng)于改變色階(圖象亮度強(qiáng)弱的指數(shù)標(biāo)準(zhǔn)),gamma值越少,圖象越亮.
            調(diào)試d3d,將控制面板中D3DDebugging打開,進(jìn)行調(diào)試,在選擇調(diào)試信息輸出等級的時(shí)候,可以選擇more來獲得更加多得詳細(xì)信息。
            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)
            這里是檢測出內(nèi)存泄露了.
            一般是內(nèi)存信息什么的沒有releasing和deleting掉.
            之前遇到的一個(gè)問題lock is not supported when multi-sampling is enabled是因?yàn)閟hader debugging打開了,之后關(guān)閉了,就沒有事情了。
            剛才編譯hlsl的時(shí)候,發(fā)現(xiàn)了x3025錯(cuò)誤,后來的dx版本要使用D3DXSHADER_ENABLE_BACKWARDS_COMPATIABLITY|D3DXSHADER_DEBUG才能編譯,特別是2008年的dx版本。

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

            投影意味著降維操作,有一種投影方法是在某個(gè)方向上用零做縮放因子,這種情況下,所有點(diǎn)都被拉平至垂直的軸(2D)或平面(3D),這種類型的投影稱做正交投影,或者平行投影,因?yàn)閺脑瓉淼狞c(diǎn)到投影點(diǎn)的直線相互平行.
            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坐標(biāo)被坐標(biāo)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物體->像機(jī) = M物體->世界M世界->像機(jī)
            P->像機(jī) = P物體 M物體->像機(jī)
            線形變換: 如果滿足下式,那么映射f(a)就是線性的:
            f(a+b) = f(a) + f(b)
            以及F(ka) = kf(a).
            仿射變換: 線性變換后接著平移,因此仿射變換的集合是線性變換的超集.任何線性變換都是仿射變換,但不是所有仿射變換都是線性變換.
            如果存在一個(gè)逆變換可以"撤消"原變換,那么該變換是可逆的.
            如果變換前后兩向量夾角的大小和方向都不改變,該變換是等角.只有平移,旋轉(zhuǎn)和均勻縮放是等角變換.
            等角變換將會(huì)保持比例不變.
            平移,旋轉(zhuǎn)和鏡像是僅有的正交變換.長度,角度,面積,和體積都保持不變.
            剛體變換只改變物體的位置和方向,不包括形狀,所有長度,角度,面積和體積都不變.平移和旋轉(zhuǎn)是僅有的剛體變換,鏡像并不被認(rèn)為是剛體變換.
            假設(shè)矩陣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日 #

            這幾天安裝這個(gè)sql server 2000,花掉了很多時(shí)間,希望以后安裝的時(shí)候,盡量避免出現(xiàn)這些情況,其它的錯(cuò)誤情況就不說明了,現(xiàn)在只說明我遇到的問題的解決辦法:將原來的安裝目錄刪除掉,將c:\program files\Microsoft SQL Server下面的80目錄給刪除掉,將注冊表里面的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server以及HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer里面的鍵值信息刪除掉。我機(jī)器上面并沒有HKEY_LOCAL_USER\SOFTWARE\Microsoft\Microsoft SQL Server這個(gè)目錄的。
            application verifier 的信息可以從這里獲得:http://technet.microsoft.com/en-us/library/bb457063.aspx
            application verifier主要用來檢測指針引起的內(nèi)存錯(cuò)誤.在程序運(yùn)行期間進(jìn)行跟蹤內(nèi)存使用情況.
            application verifier的log信息包括錯(cuò)誤所在的調(diào)用堆棧,并且要注意及時(shí)地清除上次的錯(cuò)誤記錄,我之前遇到的問題是,我用application verifier檢測到某個(gè)錯(cuò)誤,而之后再用這個(gè)exedebug啟動(dòng)的時(shí)候,就報(bào)錯(cuò),后來在application verifier里面清除了記錄才可以正常運(yùn)行.
            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日 #

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

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


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

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

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

            今天寫了代碼去改寫強(qiáng)制動(dòng)作的處理,結(jié)果發(fā)現(xiàn)很多處是有問題的,其中原因是沒有將原來的代碼作用看仔細(xì)造成了,感到羞愧呢,

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

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

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

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

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

            在調(diào)試邏輯沒有發(fā)現(xiàn)什么錯(cuò)誤提示的時(shí)候,試著去調(diào)試引擎,可能問題發(fā)生得更加深,不在邏輯層面上,而在引擎內(nèi)部,這樣就要直接調(diào)試引擎了.

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

            連接錯(cuò)誤:IID_IDirectSound3DBuffer,其實(shí)加上dxguid.lib就好了。
            紋理尋址模式包括:
            wrap, border color, clamp,和mirror以及mirror once.
             pDrawPrimInternal->SetTexture(hTex);
            之前遇到的一個(gè)問題是,顯示玩家在小地圖上面到地圖邊界了,還能重復(fù)繪制地圖,給人的感覺好像是走不到邊界,走地圖好像是在卷軸里面一樣。
            后來才知道一般默認(rèn)的紋理尋址模式是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有時(shí)候不如重寫
            盡量讓策劃去管理邏輯,邏輯程序員盡量將重心放在具體技術(shù)問題上面,不懂的地方應(yīng)該主動(dòng)跟策劃溝通,而不是自己想。
            代碼可以先模擬出來,然后再放到具體的環(huán)境里面測試,獨(dú)立寫個(gè)demo之后再去測試,這樣往往會(huì)比較快捷和省事情。
            學(xué)會(huì)模擬機(jī)器執(zhí)行代碼的次序,并且提高閱讀代碼的問題,之前的時(shí)候,我使勁去調(diào)試,每次調(diào)試只為了解決一個(gè)問題,但是事實(shí)上,如果從閱讀代碼開始的話,那么我可以省掉1天的時(shí)間。
            學(xué)會(huì)調(diào)節(jié)編寫代碼時(shí)候的心情和心態(tài),這樣有助于進(jìn)行高效編程,當(dāng)心情不好的時(shí)候,一定要集中全部的注意力,并且將思路和流程作出圖記載在紙上面,這樣可以強(qiáng)迫自己全神貫注。

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

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

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

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

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

            根據(jù)正常情況和非正常情況來獲得數(shù)據(jù)比較,以確定正確的流程和結(jié)構(gòu)。如果遇到錯(cuò)誤的亂值,那么就看看正常的數(shù)值,然后根據(jù)這個(gè)比較來獲得一些提示信息。

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

            在發(fā)送消息的時(shí)候,有時(shí)候?yàn)榱朔乐诡l繁發(fā)送消息,要加入一個(gè)cd時(shí)間,防止因?yàn)榫W(wǎng)絡(luò)問題,服務(wù)端收到玩家連續(xù)的信息。

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



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

            久久精品国产亚洲av高清漫画 | 一级a性色生活片久久无 | 亚洲国产香蕉人人爽成AV片久久| 精品久久久久久国产牛牛app | 丁香久久婷婷国产午夜视频| 久久综合九色欧美综合狠狠| 亚洲日本va中文字幕久久| 亚洲国产成人久久精品动漫| 人妻少妇精品久久| 久久久久亚洲av无码专区| 久久久人妻精品无码一区| 久久久久久国产精品免费无码| 久久久人妻精品无码一区| 久久综合亚洲欧美成人| 日日狠狠久久偷偷色综合96蜜桃 | 久久精品一区二区三区AV| 93精91精品国产综合久久香蕉| 一级a性色生活片久久无| 天天爽天天爽天天片a久久网| 亚洲色大成网站www久久九| 久久久久国色AV免费看图片| 99热成人精品热久久669| 97精品伊人久久大香线蕉| 久久精品国产精品亚洲| 国产精品久久久福利| 久久久久亚洲精品无码蜜桃| 婷婷国产天堂久久综合五月| 精品国产一区二区三区久久蜜臀| 69国产成人综合久久精品| 色欲综合久久中文字幕网| 一级做a爰片久久毛片看看| 久久久久国产一级毛片高清板| 国产国产成人精品久久| 久久久久久久人妻无码中文字幕爆 | 一个色综合久久| 亚洲色欲久久久久综合网 | 无码精品久久久久久人妻中字| 亚洲午夜福利精品久久| 一极黄色视频久久网站| 亚洲欧美成人久久综合中文网 | 办公室久久精品|