#
介紹:
關(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ā)生。
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
圖片:
摘要: 描述: 一個(gè)常見(jiàn)遇到的解決方案,下面記錄下來(lái)。 1個(gè)功能模塊,有一個(gè)簡(jiǎn)單的繼承體系,基類假設(shè)為Base. 然后通過(guò)一個(gè)接口,如何訪問(wèn)子類的特有操作? /// 外部提供一個(gè)下面接口: virutal Base* ...
閱讀全文
目的:
針對(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é)果如下:
2
MemPool Alloc time 3242 ms Free time: 2412 ms Total time 22535 ms
3
System Alloc time 33616 ms Free time: 6676 ms Total time 55013 ms
4
TCMalloc Alloc time 3451 ms Free time 1896 ms Toal time 21078 ms
5
6
可以看到TCMalloc的分配和釋放都比較快。。
7
8
其中arr每個(gè)分配的大小命中概率。
9
Count[ 1 ] = 2436395
10
Count[ 2 ] = 1281728
11
Count[ 3 ] = 1026009
12
Count[ 4 ] = 769123
13
Count[ 5 ] = 768911
14
Count[ 6 ] = 769335
15
Count[ 7 ] = 640757
16
Count[ 8 ] = 640974
17
Count[ 9 ] = 512378
18
Count[ 10 ] = 384841
19
Count[ 11 ] = 256135
20
Count[ 12 ] = 257367
21
Count[ 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)。。
問(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;
}
1
int _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) + 1, this->_Mylast,
_VIPTR(_Where));
_Destroy(this->_Mylast - 1, this->_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)題。
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)的修改。
基本上實(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ě)我的了。。
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模擬。
摘要: 一.XXX 1)概念說(shuō)明 這里不再具體描述內(nèi)存池的概念和作用,需要了解請(qǐng)看http://baike.baidu.com/view/2659852.htm?fr=ala0_1_1。 &nbs...
閱讀全文
摘要: 對(duì)于一個(gè)游戲而言,定時(shí)器是必須的,而它一般作為一個(gè)游戲基本公共組件,而定時(shí)器在游戲邏輯中運(yùn)用是非常明顯的(比如吃藥回血,每幾秒回血多少),而對(duì)于游戲邏輯而言需要開(kāi)發(fā)一個(gè)高效率高精度(毫秒級(jí)別)的定時(shí)器。
一:分析Ace庫(kù)定時(shí)器實(shí)現(xiàn)方式 1.Ace種定...
閱讀全文