一、數據分析
1、窗口顯示
基本的思路是:讓GameApp從WinApp派生,裏面有一個m_pMainWnd指針,然後在InitInstance()中new一個GameWnd對象,m_pMainWnd指向它。
然後m_pMainWnd調用顯示窗口、更新窗口的函數。
2、全局數據及讀取
GameWnd::GameWnd()//進行相關的數據初始化
{
Create(NULL,"創建窗口");
bitmap->m_hObject=LoadImage()//加載位圖數據
....
}
二、行走分析
OnKeyDown()來處理人物上、下、左、右的走動。它會做這樣的處理,case vk_**,比如**=3,當方向不是這個方向時,dir = **,index = 0; 置初始圖片bitmap[dir,index],這樣的話,從A方向跳到B方向,這時是B方向初始圖片的第一個位置。
參考15.32
用鏈表保存行走路徑並回放的方法:
struct list
{
int m;//入口格的行數
int n;//入口格的列數
int x;//x方向移動的值
int y;//y方向移動的值
struct list *next;//前節點
struct list *back;//後節點
CBitmap* bitmap;//保存人物圖像的地址
}list* ptr,*preptr,*first;//當前節點地址,上一個節點的地址,第一個節點的地址
//--------------------
//在窗口類構造函數,初始化
ptr->m = m;//全局變量,人物的初始格子所在行
ptr->n = n;//人物初始格子所在列
ptr->bitmap = bitmap[0][0];//人物的初始圖片
ptr->next = NULL;
prt->back = NULL;
first = prt;//鏈表的首節點
//-----------------
//OnKeyDown中,用ptr記錄當前人物的位置
//下面之前的代碼已經計算了,方向鍵按下時,x,y的值,還有索引圖片的dir,index值
ptr->next = (list*)malloc(sizeof(list));
prt->next->m = m;//初始值
ptr->next->n = n;
ptr->next->x=x;
ptr->next->y=y;
ptr->next->bitmap=bitmap[dir][index];
preptr=ptr;//上一個節點值,first
ptr->next->next=NULL;//ptr-next是當前要加入的節點
ptr = ptr->next;//preptr已經指向了當前節點,ptr可正式指向要加入的節點
ptr ->back=preptr;//ptr當前節點的上一個節點是preptr
//----------------
//回放功能實現:在OnKeyDown出口判斷處,置bool變量go=TRUE;在OnTimer函數中,作爲一個判斷的標誌,再調用回放功能函數Go();
//回放函數Go()的實現,裏面會由OnTimer自動調用
m = first->m
n = first->n
x = first->x
y = first->y;
mdc->SelectObject(wall);//選背景圖到內存dc
for()//循環遍歷maze[i][j],=1時,說明是牆壁,
dc.BitBlt(j*93,i*100,93,100,mdc,0,0,SRCCOPY);
mdc->SelectObject(first->bitmap)
if(first->back !=NULL)
dc.BitBlt(first->back->n*93+first->back->x,first->back->m*100+first->back->y,93,100,mdc,0,0,WHITENESS);//顯示白色,塗抹掉前面的圖片
dc.BitBlt(first->n*93+first->x,first->m*100+first->y,93,100,mdc,0,0,SRCCOPY);
if(first->next=NULL)
{
go = false;
}
else
first = first->next;//取下一個節點值,first已經是記錄最後的一個節點了,再次走時,走到出口處,將從這裏開始再次回放。
2、判斷障礙功能的實現
void GameWnd::OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags)
{
nChar==VK_DOWN;//根據這個標記,判斷方向鍵是否按下
//1. 計算下一步的顯示的位置,即改變x,y,
//2. 通過x,y計算其所在maze[8][8]的格,獲取maze[Index_x][Index_y]的索引值
//3. 判斷索引值是否是空格標記,如果不是,在不改變x,y
}
三、其他分析
第一次響應WM_PAINT,應該是創建窗口之後的,UpdateWindow()發送的,其調用OnPaint(),必須調用CPaintDC dc(this);其中構造函數中有,EndPaint,來通知系統無效區域解除,否則系統將WM_PAINT移除隊列,會不斷髮送WM_PAINT消息。
CClientDC局部變量在析構時,不會向窗口發送WM_PAINT。在該遊戲中,CClientDC在繪製時,只不過是時間落後與OnPaint()而已。CPaintDC會調用EndPaint,而改成CClientDC不會,從而在局部銷燬時不斷髮送WM_PAINT消息
BeginPaint獨佔顯示卡,最後必須調用EndPaint釋放掉獨佔的顯示卡
1.1~1.4,下走4幅圖片
2.1~2.4,左走4幅圖片
3.1~3.4,右走4幅圖片
4.1~4.4,向上走4副圖片
char ch[8];保存圖片名稱
sprintf(ch,"%d.%d.bmp",i+1,j+1);//這樣將圖片的文件名轉化成字符串ch[8]中,
三、總結
1、在窗口類GameWnd的構造函數中,就把所有數據加載到內存當中,並對全局數據進行初始化。
2、在窗口結束時,都沒有釋放掉句柄,最終由操作系統來釋放。
3、將鏈表list的數據結構直接寫到了遊戲的代碼中,這樣不用去寫一個鏈表list類。
參考:1、從新手到高手:C++全方位學習15.1