• <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>

            勤能補(bǔ)拙,Expter

            成都游戲Coder,記錄游戲開(kāi)發(fā)過(guò)程的筆記和心得!

            #

            關(guān)于 warning C4715問(wèn)題。

            介紹:
             
               關(guān)于warning C4715:not all control paths return a value
              (不是所有的控件路徑都返回值).

            問(wèn)題:
                一個(gè)函數(shù),不是所有路徑都有返回值,如下:

                1) 基本數(shù)據(jù)類型
                對(duì)于函數(shù)的并不是每個(gè)分支都有返回值,那么這樣警告會(huì)提示不是所有路徑都有返回值。

            int   test( int value )
            {
                 
            if ( value > 0 ) return value;
            }


               調(diào)用 int value = test( -1 );

               看下test的匯編代碼.

            關(guān)于8個(gè)程序寄存器一般只有esp寄存器作為入棧,出棧,調(diào)用和返回指令作為棧指針,其余

            比如eax,exc等寄存器都沒(méi)有固定的含義和固定值.
            看下面test匯編代碼.
            int   test( int value )
            {

            ; 4個(gè)寄存器入棧
            ; ebp 用于存放函數(shù)棧的棧頂指針
            ; esp 用于存放函數(shù)棧的棧底指針

            004113A0  push        ebp              ;將寄存器ebp的內(nèi)容壓入程序棧
            004113A1  mov         ebp,esp             ;保留esp寄存器
            004113A3  sub         esp,0C0h             ;為該函數(shù)留出臨時(shí)存儲(chǔ)區(qū)
            004113A9  push        ebx  
            004113AA  push        esi  
            004113AB  push        edi  

            ; 用0CCCCCCCCh初始化堆棧                
            004113AC  lea         edi,[ebp
            -0C0h]        ;lea直接尋址
            004113B2  mov         ecx,30h             ;利用編譯器的offset立即尋址
            004113B7  mov         eax,0CCCCCCCCh         ;eax
            =0CCCCCCCCh
            004113BC  rep stos    dword ptr es:[edi]     ;根據(jù)edi的大小來(lái)重復(fù)指令執(zhí)行次數(shù)

            ; 如果 cmp為真則把value的值保存到eax寄存器中
            ; 否則跳轉(zhuǎn)到地址4113C7h,并沒(méi)有對(duì)eax做處理

                 
            if ( value > 0 ) return value;
            004113BE  cmp         dword ptr [value],
            0 
            004113C2  jle         test
            +27h (4113C7h) 
            004113C4  mov         eax,dword ptr [value] 
            }


            ;各指針出棧,對(duì)應(yīng)前面3條push

            004113C7  pop         edi              ;彈出edi
            004113C8  pop         esi              ;彈出esi
            004113C9  pop         ebx              ;彈出ebx
            004113CA  mov         esp,ebp             ;把esp重新指向ebp(函數(shù)棧的棧頂指

            針,test函數(shù)棧頂)
            004113CC  pop         ebp              ;ebp重新指向test調(diào)用函數(shù)返回地址
            004113CD  ret


            調(diào)用匯編代碼

            int value = test ( 1 );
            004113FE  push        
            1    
            00411400  call        test (4110AFh) 
            00411405  add         esp,4             ;Call test 函數(shù)時(shí)將壓入棧數(shù)據(jù),

            由于只有一個(gè)參數(shù),所以只有4字節(jié)
            00411408  mov         dword ptr [value],eax 

            當(dāng)test 調(diào)用小于0時(shí)最后value指向的eax是一個(gè)0CCCCCCCCh,而對(duì)于基本數(shù)據(jù)類型大多value得到的是0CCCCCCCCh值.
            如果我們的test函數(shù):

            int   test( int value )
            {
                 
            if ( value > 0 ) return value;
                 
            return 0;
            }

            那么匯編代碼會(huì)如下:

                 if ( value > 0 ) return value;
            004113EE  cmp         dword ptr [value],
            0 
            004113F2  jle         test
            +29h (4113F9h) 
            004113F4  mov         eax,dword ptr [value] 
            004113F7  jmp         test
            +2Bh (4113FBh) 
                 
            return 0;
            004113F9  xor         eax,eax   ;將eax清零,作為返回值



               2 )如果返回的是一個(gè)引用對(duì)象
                

            obj &  test( type value )
            {
                
            if( type2 ) return obj;
            }


            obj 
            & ob = test( type1 );

               如果ob是個(gè)空引用的話,就出出錯(cuò),關(guān)于這種出錯(cuò)是否可以通過(guò)什么方式避免呢?

               我覺(jué)得warning C4715就應(yīng)該是error C4715.讓開(kāi)發(fā)者從最開(kāi)始就避免這種錯(cuò)誤的發(fā)生。

             

            posted @ 2011-04-09 12:52 expter 閱讀(5820) | 評(píng)論 (3)編輯 收藏

            利用Win32消息來(lái)解決MyGui中文完整輸入

            date:  3/23/2011

            介紹:
                利用Win32 來(lái)處理MyGui 3.0.1的中文輸入。

            實(shí)現(xiàn):
                配置還是參考網(wǎng)上的配置,主要再加中文字體.
               如下:
            □ 更改配置文件MyGUI3.0\Media\MyGUI_Media下

            ☆ core_font.xml添加

            <Resource type="ResourceTrueTypeFont" name="font_Simhei">
                    
            <Property key="Source" value="simhei.ttf"/>
                    
            <Property key="Size" value="19"/>
                    
            <Property key="Resolution" value="50"/>
                    
            <Property key="Antialias" value="false"/>
                    
            <Property key="SpaceWidth" value="4"/>
                    
            <Property key="TabWidth" value="8"/>
                    
            <Property key="CursorWidth" value="2"/>
                    
            <Property key="Distance" value="6"/>
                    
            <Property key="OffsetHeight" value="0"/>
                    
            <Codes>
                        
            <Code range="33 126"/>
                        
            <Code range="19969 40869"/>
                        
            <Code hide="128"/>
                        
            <Code hide="1026 1039"/>
                        
            <Code hide="1104"/>
                    
            </Codes>
                
            </Resource>

            ☆ simhei.ttf要從系統(tǒng)目錄下的Fonts拷貝到當(dāng)前目錄。

            ☆ core_settings.xml中將默認(rèn)字體改成

                
            <MyGUI type="Font">
                    
            <Property key="Default" value="font_Simhei"/>
                
            </MyGUI> 


                 運(yùn)行Demo解決方案:   solution_directx。

                   給BaseManager添加Win32消息響應(yīng)函數(shù)void ProcIO(UINT messgae, WPARAM wParam, LPARAM lParam ).
                  
            case WM_CHAR:
                    
            case WM_KEYDOWN:
                    
            case WM_KEYUP:
                        
            {
                            
            base::BaseManager *baseManager = (base::BaseManager*)GetWindowLongPtr(hWnd, GWL_USERDATA);

                            
            if ( baseManager )
                                baseManager
            ->ProcIO( uMsg , wParam , lParam );
                            
            break;
                        }

               ProcIO主要是對(duì)
               WM_CHAR                                   字符響應(yīng)
               WM_KEYDOWN/WM_KEYUP  按鍵響應(yīng)

               在處理字符響應(yīng)的時(shí)候需要區(qū)分輸入法狀態(tài)和非輸入法狀態(tài)的字符響應(yīng)。
            case WM_CHAR:
                        
            {
                            
            if ( ImmIsIME( GetKeyboardLayout(0) ))
                                ProcChar( wParam , lParam );
                            
            else
                            
            {                     
                                MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(scan_code), code_point);
                            }
            ;
                        }

                        
            break;

            ProcChar函數(shù)主要處理中文。因?yàn)闈h字為8個(gè)字節(jié)會(huì)響應(yīng)WM_CHAR2次。需要進(jìn)行組合一次。
            WM_KEYDOWN:主要處理一些Widget字符輸入。同時(shí)還可以做全局鍵盤信息監(jiān)控(快捷鍵).

            判斷一個(gè)Widget是否可以進(jìn)行字符輸入:
            \MyGUIEngine\include\MyGUI_InputManager.cpp
            bool     InputManager::isKeyInputCapture()
                
            {
                    
            if!mWidgetKeyFocus ) return false;

                    std::
            string  strName = mWidgetKeyFocus->getTypeName();
                    
            if ( strName == "ComboBox" ||
                        strName 
            == "Edit" ||
                        strName 
            == "Message" ||
                        strName 
            == "List")
                    
            {
                        
            return true;
                    }

                    
            return false;
                }

            由于采用Win32鍵盤消息,應(yīng)該屏蔽自帶OIS的。
            Input\OIS\InputManager.cpp
            void InputManager::captureInput()
             
            {
              
            if (mMouse) mMouse->capture();
              
            //mKeyboard->capture();
             }

            在Demo中監(jiān)控按鍵消息( DemoKeeper功能是UIManager )。
            void DemoKeeper::injectKeyPress(MyGUI::KeyCode _key, MyGUI::Char _text)
                
            {
                    
            if (_key == MyGUI::KeyCode::Grave)
                    
            {
                        mConsole
            ->setVisible(!mConsole->isVisible());
                        
            return;
                    }
              
                    
            else if (_key == MyGUI::KeyCode::F2 )
                    
            {
                        MyGUI::Message::createMessageBox(
            "Message""Info""Press F2 ", MyGUI::MessageBoxStyle::Ok | MyGUI::MessageBoxStyle::IconInfo);
                        
            return;
                    }

                    
            else if (_key == MyGUI::KeyCode::F3 )
                    
            {
                        MyGUI::Message::createMessageBox(
            "Message""Info""Press F3 ", MyGUI::MessageBoxStyle::Ok | MyGUI::MessageBoxStyle::IconInfo);
                        
            return;
                    }


                    
            base::BaseManager::injectKeyPress(_key, _text);
                }


            最后附上源碼解決方案:
            /Files/expter/MyGuiDemo.rar

            圖片:

            posted @ 2011-03-23 15:20 expter 閱讀(3918) | 評(píng)論 (3)編輯 收藏

            根據(jù)子類類型訪問(wèn)其特有操作

                 摘要: 描述:   一個(gè)常見(jiàn)遇到的解決方案,下面記錄下來(lái)。   1個(gè)功能模塊,有一個(gè)簡(jiǎn)單的繼承體系,基類假設(shè)為Base.   然后通過(guò)一個(gè)接口,如何訪問(wèn)子類的特有操作?     /// 外部提供一個(gè)下面接口:   virutal   Base*  ...  閱讀全文

            posted @ 2011-02-24 23:23 expter 閱讀(2231) | 評(píng)論 (4)編輯 收藏

            針對(duì)一個(gè)內(nèi)存池測(cè)試相關(guān)介紹

            目的:
            針對(duì)自己的一個(gè)內(nèi)存池如何測(cè)試其性能.

            介紹:
            1.內(nèi)存池測(cè)試用例的選取.
            1.單線程的分配和釋放.
            2.內(nèi)存回收.
            3.性能關(guān)注.

            關(guān)于內(nèi)存池的設(shè)計(jì)和實(shí)現(xiàn)網(wǎng)上遍地都是,本文不具體介紹關(guān)于內(nèi)存池的具體實(shí)現(xiàn)和方式,主要是介紹設(shè)計(jì)一個(gè)內(nèi)存池怎樣去測(cè)試其性能和安全處理,有一個(gè)開(kāi)源的內(nèi)存池項(xiàng)目tcmalloc也有介紹很多,但是為了滿足多種需求,代碼過(guò)于龐大,最后我用來(lái)測(cè)試分配性能測(cè)試。

            1個(gè)內(nèi)存池的測(cè)試用例應(yīng)該包含:
            1)該項(xiàng)目?jī)?nèi)存分配概率隨機(jī)性.
            2)同時(shí)保證釋放的隨機(jī)性.
            3)可以支持多種分配方式(不同大小,不同對(duì)象參數(shù)等).


            要達(dá)到上面要求則可以設(shè)計(jì)
            1.一個(gè)數(shù)組來(lái)設(shè)定需要分配的大小。
               long  arr[ ] = { 16,32,64,128,256,512,1024,2048,5120,5130,7000,6000,10240,15000,20000};

            2.根據(jù)需求來(lái)指定各個(gè)大小的分配幾率,這好比有多少概率選中某個(gè)數(shù)(需特定的分配):
               

             A.針對(duì)這個(gè)需求可以設(shè)定定一個(gè)概率數(shù)組Odds,數(shù)組值arrArr的索引。
                B.針對(duì)Odds指定數(shù)組數(shù)據(jù),使其數(shù)據(jù)分配達(dá)到arr需要分配概率。
                   
            ///   被分配的概率
                   long  Odds[ ] = 0,0,0,1,1,2,2,2,3,3,4,4,4,4,5,5,5,5,6,6,,7,7,7,8,8,8,8,9,9,9,10,10,11,12,12};
                C.隨機(jī)Odds數(shù)組,然后得到其值分配,其值則為Arr的索引。
                    
            long  Asize= arr[ Odds[ rand()%size ] ] ;



            3.釋放保證隨機(jī)性。
                 什么時(shí)候釋放,以及分配了做什么用,都是又應(yīng)用層決定的,所以需要把分配出來(lái)的內(nèi)存通過(guò)一個(gè)容器來(lái)存儲(chǔ).
                 由于分配是隨機(jī)性,那么釋放的時(shí)候也保證了隨機(jī)性。

            4.支持多種分配方式。
                 A. 對(duì)象分配:     

            MemFactory  Memory;

                A
            * a = Memory.Alloc<A>( );
                B
            * b = Memory.Alloc<B,int>2 );

                Memory.FreeObj( a );
                Memory.FreeObj( b );

                B.直接分配

            void* p1 = Memory.Alloc( Asize );


            5.性能測(cè)試
               為了測(cè)試性能,我選擇了分配1000W次,其中用一個(gè)容器保存分配的數(shù)據(jù),然后當(dāng)容器到達(dá)100W的時(shí)候釋放60W數(shù)據(jù)(保證數(shù)據(jù)正在使用,隨機(jī)釋放)。
               下面的Alloc time 只是統(tǒng)計(jì)的Alloc時(shí)間累加,F(xiàn)ree time只是統(tǒng)計(jì)的Free 時(shí)間累加,Total time記錄這次測(cè)試總共花費(fèi)時(shí)間。

             1測(cè)試結(jié)果如下:
             2MemPool Alloc time 3242 ms  Free time: 2412 ms Total time 22535 ms
             3System    Alloc time 33616 ms Free time: 6676 ms Total time 55013 ms
             4TCMalloc Alloc time 3451 ms   Free time 1896 ms  Toal  time 21078 ms
             5
             6可以看到TCMalloc的分配和釋放都比較快。。
             7
             8其中arr每個(gè)分配的大小命中概率。
             9Count[ 1 ] = 2436395
            10Count[ 2 ] = 1281728
            11Count[ 3 ] = 1026009
            12Count[ 4 ] = 769123
            13Count[ 5 ] = 768911
            14Count[ 6 ] = 769335
            15Count[ 7 ] = 640757
            16Count[ 8 ] = 640974
            17Count[ 9 ] = 512378
            18Count[ 10 ] = 384841
            19Count[ 11 ] = 256135
            20Count[ 12 ] = 257367
            21Count[ 13 ] = 256047



            PS:
            1.內(nèi)存池的使用:
              

               一般情況下內(nèi)存池,是整理一整塊內(nèi)存,然后通過(guò)一個(gè)list串連起來(lái),然后分配的時(shí)候從鏈表中獲取,釋放也是插入到鏈表中。
                為了方便多對(duì)象的多參數(shù)以及無(wú)參數(shù)的分配,可以一些列宏和模板來(lái)實(shí)現(xiàn):
                
                具體的可以參考后面附帶的內(nèi)存池實(shí)現(xiàn)的代碼:
                
                
            #define DEFINE_CALL_CON( paramcount ) template <class T, DP_STMP_##paramcount( typename, tp ) >\
                inline T 
            * Alloc(DP_MTMP_##paramcount( tp, p ) ){\
                       unsigned 
            long lSize = sizeof(T);\
                       
            void* ptMem = Alloc(lSize);\
                     
            if!ptMem) return NULL; \
                      T 
            * pt = new(ptMem)T( LP_SNMP_##paramcount( p ) );\
                     
            return pt;\
                  }

                
                A. 對(duì)象分配:      
                MemFactory  Memory;

                A
            * a = Memory.Alloc<A>( );
                B
            * b = Memory.Alloc<B,int>2 );
                C* c = Memory.Alloc<C,int,const char*>(1,"dd");
                Memory.FreeObj( a );
                Memory.FreeObj( b );
                   Memory.FreeObj( c );

                B.直接分配
                
            void* p1 = Memory.Alloc( Asize );
                    memset(p1,0,ASize);


            2.內(nèi)存池的代碼:
               1)   實(shí)現(xiàn)全是利用的freelist,減少內(nèi)存開(kāi)銷,分配速度,直接定位。
               2)   管理都是通過(guò)工廠類來(lái)同一的管理。
               3)   指定分配策略.

               源碼為Vs2008版本...

               /Files/expter/Pool.rar

            關(guān)于實(shí)現(xiàn)有疑問(wèn)和建議,可以提出寶貴的意見(jiàn)。。

            posted @ 2011-01-18 21:20 expter 閱讀(3466) | 評(píng)論 (3)編輯 收藏

            一個(gè)關(guān)于容器選取的刪除問(wèn)題。


            問(wèn)題描述:
            1個(gè)容器有大量元素,需要進(jìn)行erase大部分?jǐn)?shù)據(jù)的時(shí)候,需要遍歷這些元素,然后釋放item的空間,還要erase刪除其item。

            一個(gè)庫(kù),為了測(cè)試其性能的時(shí)候,需要保存所有外部使用者的數(shù)據(jù),這里選取了map,vector和list.

            為了簡(jiǎn)化問(wèn)題,我寫(xiě)了下面測(cè)試代碼來(lái)測(cè)試各個(gè)操作:
            數(shù)據(jù)節(jié)點(diǎn):

            struct node
            {
                node(
            int i){data = i;}
                
            int data;
            }

             1int _tmain(int argc, _TCHAR* argv[])
             2{
             3    typedef std::map<long,node*> Mptable;
             4    typedef std::vector<node*>   Vec;
             5    typedef std::list<node*>     List;
             6    
             7    Mptable        mapnode;
             8    Vec            vecnode;
             9    List        listnode;
            10
            11    for(int i = 1 ; i <= 100000 ; i++ )
            12    {     
            13        mapnode [ i ] = new node(i);
            14        vecnode.push_back( new node(i) );
            15        listnode.push_back( new node(i));
            16    }

            17
            18    long time = timeGetTime( );
            19    
            20    for( Mptable::iterator itr = mapnode.begin() ; itr != mapnode.end() ;  )
            21    {
            22         delete itr->second;
            23         mapnode.erase( itr++ );
            24    }

            25
            26    std::cout <<"map : spend " << timeGetTime() - time << " msec " << std::endl;
            27
            28
            29    time = timeGetTime( );
            30    
            31    for( Vec::iterator itr = vecnode.begin() ; itr != vecnode.end() ;  )
            32    {
            33         delete *itr;
            34         itr = vecnode.erase( itr );
            35    }

            36
            37    std::cout <<"vector : spend " << timeGetTime() - time << " msec " << std::endl;
            38
            39
            40    time = timeGetTime( );
            41    
            42    for( List::iterator itr = listnode.begin() ; itr != listnode.end() ;  )
            43    {
            44         delete *itr;
            45         itr = listnode.erase( itr );
            46    }

            47
            48    std::cout <<"list : spend " << timeGetTime() - time << " msec" << std::endl;
            49
            50
            51    return 0;
            52}
            Release下運(yùn)行結(jié)果:
            map : spend 31 msec
            vector : spend 3734 msec
            list : spend 35 msec


            發(fā)現(xiàn)map的速度最快,vector最慢,list相當(dāng)。

            其實(shí)vector就是一個(gè)Array,只是Array是靜態(tài)大小,vector可以擴(kuò)展,然后查看vector的erase的源碼:
            iterator erase(const_iterator _Where)
                    
            {    // erase element at where
                    _Move(_VIPTR(_Where) + 1this->_Mylast,
                        _VIPTR(_Where));
                    _Destroy(
            this->_Mylast - 1this->_Mylast);
                    
            --this->_Mylast;
                    
            return (_Make_iter(_Where));
                    }
            有一個(gè)move操作,原來(lái)把當(dāng)前iterator+1的往前移了,這樣的話會(huì)遍歷iterator后面所有的元素。


            關(guān)于map的erase原理可以查看map的實(shí)現(xiàn)源碼:
            由于map的erase后有一個(gè)維護(hù)過(guò)程,其實(shí)map是一個(gè)RB-Tree,刪除算法相對(duì)比較麻煩,刪除某個(gè)item會(huì)查找下一個(gè)item替換刪除的節(jié)點(diǎn),同時(shí)還要考慮紅和黑的節(jié)點(diǎn)處理。同時(shí)還要保證map的erase后,平衡且有序。
            所以map的erase主要做:
            1.刪除item.
            2.讓樹(shù)平衡,且有序。

            list其實(shí)是一個(gè)雙向鏈表:
            關(guān)于刪除其實(shí)是0(1)的操作,我們查看list的erase的操作:
                iterator erase(const_iterator _Where)
                    
            {    // erase element at _Where
             #if _ITERATOR_DEBUG_LEVEL == 2
                    
            if (_Where._Getcont() != this || _Where._Ptr == this->_Myhead)
                        _DEBUG_ERROR(
            "list erase iterator outside range");
                    _Nodeptr _Pnode 
            = (_Where++)._Mynode();
                    _Orphan_ptr(
            *this, _Pnode);

             
            #else /* _ITERATOR_DEBUG_LEVEL == 2 */
                    _Nodeptr _Pnode 
            = (_Where++)._Mynode();
             
            #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

                    
            if (_Pnode != this->_Myhead)
                        
            {    // not list head, safe to erase
                        this->_Nextnode(this->_Prevnode(_Pnode)) =
                            
            this->_Nextnode(_Pnode);
                        
            this->_Prevnode(this->_Nextnode(_Pnode)) =
                            
            this->_Prevnode(_Pnode);

                        _Dest_val(
            this->_Alnod, _Pnode);
                        
            this->_Alnod.deallocate(_Pnode, 1);

                        
            --this->_Mysize;
                        }

                    
            return (_Make_iter(_Where));
                    }
            主要代碼刪除就是下面刪除部分:
            對(duì)prev和next節(jié)點(diǎn)進(jìn)行處理即可。

            關(guān)于list的移除竟然比map還要慢.

            PS:測(cè)試為單線程。

            當(dāng)為100W數(shù)據(jù)的時(shí)候:
            map : spend 300 msec
            list :   spend 385 msec

            咋list比map容器還要慢?
            還是上面的代碼不能說(shuō)明問(wèn)題。

            posted @ 2011-01-14 14:58 expter 閱讀(2586) | 評(píng)論 (2)編輯 收藏

            在CEGUI顯示GIF圖像,簡(jiǎn)單的聊天窗口實(shí)現(xiàn)方式.

                   author:expter
                   date:   2010/07/31
               
                上次寫(xiě)的超鏈接是重寫(xiě)了一個(gè)單獨(dú)的超鏈接控件,主要實(shí)現(xiàn)文本的鼠標(biāo)事件和文本下劃線,靜態(tài)圖像的顯示,主要寫(xiě)的渲染過(guò)程,這次為了解決動(dòng)態(tài)圖片(比如gif有多幀實(shí)現(xiàn)的解決方案).

                注:主要針對(duì)當(dāng)前CEGUI的最新庫(kù)0.7.1。

                目的:在游戲聊天框中可能有一個(gè)聊天表情,次表情是動(dòng)態(tài)的,需要顯示動(dòng)態(tài)表情圖片,同時(shí)可能有超鏈接等功能,我們約定一種解析格式,然后輸入表情代碼或者超鏈接內(nèi)容即可顯示我們需要的功能。
             
                實(shí)現(xiàn)方式: 
                    由于針對(duì)聊天窗口,所以這里聊天窗口內(nèi)容采用CEGUI::ListBox,每條消息內(nèi)容為L(zhǎng)istBoxTextItem,由于ListBox有滾動(dòng)horzScrollbar條,而一般聊天窗口沒(méi)有horzScrollbar此功能,所以假設(shè)一段話過(guò)長(zhǎng)我們需要才分內(nèi)容,可能一條消息包括多條ListBoxTextItem。每行里面可能有文本,表情,圖片,以及超鏈接等.
                  
                   由于CEGUi不能直接解析Gif文件,我們需要把gif的每一幀全部到出來(lái),然后實(shí)現(xiàn)一個(gè)當(dāng)前表情anim控制類,表情管理變量,文件解析類TalkRenderedStringParser。
                   Anim主要記錄當(dāng)前表情應(yīng)該為那幀的哪張圖片。
                  表情管理主要記錄當(dāng)前所有的動(dòng)態(tài)表情,每幀時(shí)間到達(dá)的時(shí)候開(kāi)始渲染。
                  TalkRenderedStringParser還是一個(gè)文本解析類。

             

            簡(jiǎn)單的ChatList的主要文本如下:
            [C FFFF0000]StaticTxt test1![\\ 1] [\\ 3]
            dasd[\\ 2] [\\ 3] [\\ 4] [\\ 1] [\\ 5]

            其實(shí)是動(dòng)態(tài)表情,只是切的圖片不能顯示了:

            要實(shí)現(xiàn)一個(gè)與游戲相關(guān)的聊天窗口基本功能都具備了,這里包括實(shí)現(xiàn)超鏈接,表情圖片,圖片的功能。

            然后只需要制定分頻道等功能分別顯示不同的聊天信息。



            源碼功能上相對(duì)比較簡(jiǎn)單,CEGUI庫(kù)做了相應(yīng)的修改。


                           

            posted @ 2010-07-31 11:58 expter 閱讀(3832) | 評(píng)論 (6)編輯 收藏

            基于CEGUI的StaticText的超級(jí)鏈接實(shí)現(xiàn)

                基本上實(shí)現(xiàn)一個(gè)基于靜態(tài)文本多任務(wù)的過(guò)程.

            注:主要針對(duì)當(dāng)前CEGUI的最新庫(kù)0.7.1。

            目的:游戲制作過(guò)程中一般打開(kāi)NPC會(huì)彈出一個(gè)對(duì)話框,一般對(duì)話框就是顯示一段話,有圖片,超鏈接,文字,同時(shí)文本分別有不同的顏色!
            那么只要我們輸入一段文本,對(duì)話框的控件解析文本定義好的標(biāo)簽然后顯示所有文本內(nèi)容和圖片即可。

            實(shí)現(xiàn)方式: 
            1.超鏈接控件既要響應(yīng)點(diǎn)擊消息,又要有超級(jí)鏈接標(biāo)記的下劃線。實(shí)現(xiàn)方式主要參考了Button的Clicked事件,StaticText的render渲染過(guò)程,重新寫(xiě)的一個(gè)基于超級(jí)鏈接組件。
            2.文本解析利用了當(dāng)前CEGUI的版本的BasicRenderedStringParser類,我們只需要繼承此類,然后設(shè)置系統(tǒng)默認(rèn)的文本解析類為我們當(dāng)前的類。
            3.寫(xiě)超級(jí)鏈接組件的渲染過(guò)程主要方便支持CELayoutEditor的可視化編輯。

            實(shí)現(xiàn)結(jié)果:
            1.文本顯示顏色。
            2.換行操作。
            3.支持超級(jí)鏈接的顯示,以及事件響應(yīng)和事件處理,事件響應(yīng)為CEGUI::HyperText::EventClicked。
            4.超鏈接的下劃線繪制。
            5.支持圖片顯示和支持圖片事件響應(yīng)。


            假設(shè)我們的解析文本如下:
            標(biāo)簽定義如下
            [N]則是換行字符
            [C]字體顏色
            [A]超級(jí)鏈接
            [M]圖片

            相對(duì)來(lái)說(shuō)編寫(xiě)此文本比較簡(jiǎn)單.

            具體用法
            xxx             顯示文本xxx
            [C  XX]      xx表示32位的字體顏色
            [A 1: XX]   xx 超級(jí)鏈接顯示內(nèi)容。
            [M  xx]       xx表示圖片名字

            colorTest:[N]
            StaticTxt test1![N]
            [C FFFF0000]StaticTxt test2!    [N]
            [C FFFFFF00]StaticTxt test3!   [N] [N] [N]

            [C FFFF0000]HyperLink Test:  [N]
            [A 1:this is the Hyperlink!this is the  Hyperlink!][N]
            [A 2:this is the second Hyperlink! this is hyperlink!!!][N]
            [A 3:this is the third hyperlink!this is hyperlink!this is hyperlink!this is hyperlink!]
            [N] [N] [N]
            Image Text:[M 381] [M 286] [M 669]


            具體過(guò)程:


            后期目標(biāo)支持動(dòng)畫(huà)的顯示,比如GIF格式圖片.

            實(shí)現(xiàn)過(guò)程相對(duì)繁瑣,而且涉及datafiles配置一些處理。

            可能真正游戲界面上的實(shí)現(xiàn)可能會(huì)更豐富,其實(shí)也就是增加幾個(gè)標(biāo)簽然后解析即可。


            注:上次聽(tīng)蓋老板說(shuō)有本書(shū)專門介紹足球AI,然后專門去買了,看其介紹他實(shí)現(xiàn)上足球仿真AI專門實(shí)現(xiàn)比較智能,先學(xué)習(xí)學(xué)習(xí)他的在繼續(xù)寫(xiě)我的了。。

            posted @ 2010-07-22 22:12 expter 閱讀(2775) | 評(píng)論 (9)編輯 收藏

            一個(gè)基于足球AI仿真機(jī)的模擬實(shí)現(xiàn)

                   author:expter
                   date   2010/06/30
             
                   介紹:  世界杯現(xiàn)在如此的備受矚目和關(guān)注,本文介紹如何實(shí)現(xiàn)一個(gè)基于足球AI的實(shí)現(xiàn),而作為程序員我們關(guān)注的不是目標(biāo)用其贏得世界杯,而是創(chuàng)造一個(gè)把球踢好的智能體,加上最近上班輕松,晚上較閑,加上去年實(shí)現(xiàn)的一個(gè)AI模型與平時(shí)寫(xiě)的游戲智能算法,想組織起來(lái)完成一個(gè)足球模擬玩玩。
                  
                  本文會(huì)首先介紹一種基于AI仿真機(jī)的實(shí)現(xiàn)流程圖,后面我將會(huì)用大量的篇幅詳細(xì)介紹各個(gè)實(shí)現(xiàn)細(xì)節(jié),與具體足球戰(zhàn)術(shù),此足球AI主要是主動(dòng)攻擊性AI,所以還需要具體完善加強(qiáng)防御性的AI,所以具體代碼現(xiàn)在將不會(huì)現(xiàn)在放出。以后實(shí)現(xiàn)完整過(guò)后會(huì)完整公開(kāi),現(xiàn)在主要設(shè)計(jì)描述如下。
              
                    足球的游戲規(guī)則不是很復(fù)雜,就是2個(gè)球隊(duì),然后每個(gè)球隊(duì)一個(gè)守門員與幾名球員,目的就是踢進(jìn)對(duì)方的球門。簡(jiǎn)單的足球是沒(méi)有傻子的,也就沒(méi)有犯規(guī),越位,頭球,點(diǎn)球以及烏龍球。以后可能會(huì)增加上面幾種。

                    一個(gè)簡(jiǎn)單的游戲的具體環(huán)境如下:
                     1.一個(gè)足球場(chǎng)(FootBallPitch)
                     2.一個(gè)足球     FootBall
                     3.二個(gè)球門     Goal
                     4.二個(gè)球隊(duì)     FootBallTeam
                     5.場(chǎng)上12名足球隊(duì)員(每隊(duì)6名,期中5名為球員2名后衛(wèi)3名前鋒,還有1名守門員)
                     6.球員             FootBaller    守門員  GoalKeeper
              
                 然后只要理清上面的描述然后把具體的實(shí)現(xiàn)封裝到每個(gè)類中,就實(shí)現(xiàn)了1個(gè)簡(jiǎn)單的足球仿真模擬,實(shí)現(xiàn)上面的功能代碼還是簡(jiǎn)單,但是如何組織強(qiáng)大攻擊性強(qiáng)大,防御性強(qiáng)的AI還是挺復(fù)雜的。
                
                   下面將給出具體UML實(shí)現(xiàn)類圖:   
                   
                      
                     由于是基于智能體的足球AI所以還是借鑒了FSM模型,我們可以把每個(gè)Player處于不同的狀態(tài)進(jìn)行不同的操作,具體把操作類型和事件處理都放在具體的狀態(tài)中。
                     基于球場(chǎng)上運(yùn)球的FootBaller有下列狀態(tài)ChaseBall 追球狀態(tài),Dribble運(yùn)球  Gohome 歸位   KickBall 踢球  ReceviveBall傳球 
                     基于守門員GoalKeeper有InterceptBall 攔截  PutBallBackInPlay發(fā)球.
              
                    這里為了區(qū)分隊(duì)員是前鋒還是后衛(wèi),我們給隊(duì)員增加一個(gè)行為Behaviors,讓其根據(jù)自己的行為做相應(yīng)的事情.。

                    其中所有的圖像處理都是用的GDI的繪制,程序采用的Win32編寫(xiě)方式。

                   上面的設(shè)計(jì)基本是現(xiàn)在程序的設(shè)計(jì)方案和流程圖。

                    后期完善部分:
                    1.引入基于事件響應(yīng),F(xiàn)ootBaller 可以通知同隊(duì)FootBaller 的接收響應(yīng)的消息處理,比如A發(fā)現(xiàn)B的位置很好,A可以通知B我要傳球到一個(gè)坐標(biāo)點(diǎn)。
                   2.加強(qiáng)防御和攻擊AI。
                   3.完成具體方案后,公布所有的方案設(shè)計(jì)和具體算法,后期引入腳本機(jī)制,通過(guò)外部編寫(xiě)腳本實(shí)現(xiàn)不同隊(duì)伍AI模擬。       

                      

            posted @ 2010-06-30 23:36 expter 閱讀(2973) | 評(píng)論 (7)編輯 收藏

            基于策略的一種高效內(nèi)存池的實(shí)現(xiàn)

                 摘要: 一.XXX      1)概念說(shuō)明          這里不再具體描述內(nèi)存池的概念和作用,需要了解請(qǐng)看http://baike.baidu.com/view/2659852.htm?fr=ala0_1_1。   &nbs...  閱讀全文

            posted @ 2010-04-14 23:23 expter 閱讀(5469) | 評(píng)論 (11)編輯 收藏

            一個(gè)高效的定時(shí)器分析及設(shè)計(jì)

                 摘要:        對(duì)于一個(gè)游戲而言,定時(shí)器是必須的,而它一般作為一個(gè)游戲基本公共組件,而定時(shí)器在游戲邏輯中運(yùn)用是非常明顯的(比如吃藥回血,每幾秒回血多少),而對(duì)于游戲邏輯而言需要開(kāi)發(fā)一個(gè)高效率高精度(毫秒級(jí)別)的定時(shí)器。      一:分析Ace庫(kù)定時(shí)器實(shí)現(xiàn)方式   1.Ace種定...  閱讀全文

            posted @ 2010-03-05 16:28 expter 閱讀(9112) | 評(píng)論 (12)編輯 收藏

            僅列出標(biāo)題
            共7頁(yè): 1 2 3 4 5 6 7 
            久久AV高潮AV无码AV| 日本五月天婷久久网站| 国产欧美一区二区久久| 午夜不卡久久精品无码免费| 一本一本久久aa综合精品| 亚洲午夜久久久久妓女影院| 伊人久久精品无码二区麻豆| 亚洲国产精品18久久久久久| 漂亮人妻被黑人久久精品| 久久婷婷成人综合色综合| 国产精品毛片久久久久久久| 伊人久久免费视频| 精品久久久久久久久久久久久久久| 久久99亚洲综合精品首页| 亚洲国产成人精品女人久久久| 久久久久久久波多野结衣高潮| 欧美喷潮久久久XXXXx| 9久久9久久精品| 精品欧美一区二区三区久久久| 伊人久久大香线蕉综合5g| 久久人人爽人人爽人人片AV不| 日本精品久久久久中文字幕| 久久人人爽人人爽人人片AV东京热| 亚洲精品无码久久久久AV麻豆| 久久综合久久自在自线精品自| 精品久久777| 久久久久久免费视频| 97超级碰碰碰久久久久| 国产精品亚洲综合专区片高清久久久| 久久国内免费视频| 国产精品视频久久久| 国产精品免费久久久久影院| 久久精品国产亚洲av麻豆图片 | 久久久国产打桩机| 久久久国产精品福利免费 | 国产亚洲精品久久久久秋霞| 国产精品久久久久久| 久久人人青草97香蕉| 亚洲天堂久久精品| 99精品国产综合久久久久五月天| 热re99久久精品国产99热|