本系列文章由zhmxy555編寫,轉載請註明出處。 http://blog.csdn.net/zhmxy555/article/details/7376281
作者:毛星雲 郵箱: happylifemxy@qq.com 歡迎郵件交流編程心得
"透明動畫”是遊戲中一定會用到的基本技巧,它通過圖案的連續顯示及圖案本身背景的透明化處理,在背景圖上產生出栩栩如生的動畫效果。
看過之前筆記的朋友們應該知道,在筆記六裡我們介紹了使位元影像背景透明的方法,在筆記八裡我們講解了使用遊戲迴圈顯示動畫的技巧,而這節筆記的內容,剛好是兩者的一個綜合。
如果有沒看過之前筆記系列的朋友,為了便於理解本節的內容,可以先瀏覽一下之前的筆記六和筆記八,下面我給出連結。
【Visual C++】遊戲開發筆記之六——遊戲畫面繪圖(三)透明特效的製作方法
【Visual C++】遊戲開發筆記之八——基礎動畫顯示(二)遊戲迴圈的使用
為了實現透明動畫的效果,我們採用了一個如所示的恐龍跑動的連續圖,每一張跑動圖的寬高都為95*99。我們知道,透明動畫製作的前提是,必須在一個暫存的記憶體DC上完成每一張跑動圖的透明,然後再貼到視窗上,這樣畫面更新時才不會出現在透明貼圖過程中產生的閃爍現象。
中每一個小恐龍的尺寸為95*99,這個資料在寫代碼過程中比較關鍵。
實現這個程式的關鍵點,當然是MyPaint函數的寫法。
而在MyPaint函數裡面我們主要實現了兩個功能:
1.恐龍跑動圖案的透明背景化
2.更新貼圖的座標,實現動畫效果
下面我們給出MyPaint函數的寫法:
num = 0; //顯示圖號x = 640;//貼圖起始X座標y = 360; //貼圖起始Y座標void MyPaint(HDC hdc){if(num == 8)num = 0;//在mdc中貼上背景圖SelectObject(bufdc,bg);BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY);//在mdc中進行透明處理SelectObject(bufdc,dra);BitBlt(mdc,x,y,95,99,bufdc,num*95,99,SRCAND);BitBlt(mdc,x,y,95,99,bufdc,num*95,0,SRCPAINT);//將最後的畫面顯示在視窗中BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);tPre = GetTickCount(); //記錄此次繪圖時間num++;x-=20; //計算下次貼圖的座標if(x<=-95)x = 640;}
關鍵點的說明:
▲7~17行, 在mdc上進行透明操作並將最後的結果顯示在視窗中。
▲13~14行,進行透明時,按照目前的圖號來取出對應的跑動圖案或者屏蔽圖。
▲22~24行,計算下次恐龍圖貼圖座標,由於我們的程式設定動畫是由右向左跑動的,在Y軸座標不變化,而X軸座標每次向左遞減20,直到圖案跑到左邊視窗外時再將座標設回最右邊,這樣可以看到恐龍不斷由右向左迴圈跑動的效果。
同樣我們利用一個完整的執行個體來瞭解實現透明動畫的具體過程:
#include "stdafx.h"//全域變數聲明HINSTANCE hInst;HBITMAP dra,bg;HDChdc,mdc,bufdc;HWNDhWnd;DWORDtPre,tNow;intnum,x,y;//全域函式宣告ATOMMyRegisterClass(HINSTANCE hInstance);BOOLInitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);voidMyPaint(HDC hdc);//***WinMain函數,程式進入點函數************************************** int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){MSG msg;MyRegisterClass(hInstance);//初始化if (!InitInstance (hInstance, nCmdShow)) {return FALSE;}//訊息迴圈GetMessage(&msg,NULL,NULL,NULL); //初始化msg while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); }else{tNow = GetTickCount();if(tNow-tPre >= 100)MyPaint(hdc);} }return msg.wParam;}//****設計一個視窗類別,類似填空題,使用視窗結構體************************* ATOM MyRegisterClass(HINSTANCE hInstance){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc= (WNDPROC)WndProc;wcex.cbClsExtra= 0;wcex.cbWndExtra= 0;wcex.hInstance= hInstance;wcex.hIcon= NULL;wcex.hCursor= NULL;wcex.hCursor= LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName= NULL;wcex.lpszClassName= "canvas";wcex.hIconSm= NULL;return RegisterClassEx(&wcex);}//****初始化函數*************************************// 載入位元影像並設定各對象的初始值BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){char filename[20] = "";HBITMAP bmp;hInst = hInstance;hWnd = CreateWindow("canvas", "動畫示範" , WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);if (!hWnd){return FALSE;}MoveWindow(hWnd,10,10,640,480,true);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);hdc = GetDC(hWnd);mdc = CreateCompatibleDC(hdc);bufdc = CreateCompatibleDC(hdc);bmp = CreateCompatibleBitmap(hdc,640,480);SelectObject(mdc,bmp);dra = (HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,760,198,LR_LOADFROMFILE);bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,640,480,LR_LOADFROMFILE);num = 0; //顯示圖號x = 640;//貼圖起始X座標y = 360; //貼圖起始Y座標MyPaint(hdc);return TRUE;}//****自訂繪圖函數*********************************// 1.恐龍跑動圖案的透明背景化// 2.更新貼圖座標,實現動畫效果void MyPaint(HDC hdc){if(num == 8)num = 0;//在mdc中貼上背景圖SelectObject(bufdc,bg);BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY);//在mdc中進行透明處理SelectObject(bufdc,dra);BitBlt(mdc,x,y,95,99,bufdc,num*95,99,SRCAND);BitBlt(mdc,x,y,95,99,bufdc,num*95,0,SRCPAINT);//將最後的畫面顯示在視窗中BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);tPre = GetTickCount(); //記錄此次繪圖時間num++;x-=20; //計算下次貼圖的座標if(x<=-95)x = 640;}//****訊息處理函數***********************************LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){switch (message){case WM_DESTROY://視窗結束訊息,撤銷各種DCDeleteDC(mdc);DeleteDC(bufdc);DeleteObject(dra);DeleteObject(bg);ReleaseDC(hWnd,hdc);PostQuitMessage(0);break;default://其他訊息return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}
這個程式的運行結果為:
筆記十到這裡就結束了。
本節原始碼請點擊這裡下載: 【Visual C++】Code_Note_10
感謝一直支援【Visual C++】遊戲開發筆記系列專欄的朋友們,也請大家繼續關注我的部落格,我一有空就會把自己的學習心得,覺得比較好的知識點寫出來和大家一起分享。
精通遊戲開發的路還很長很長,非常希望能和大家一起交流,共同學習和進步。
大家看過後覺得有啟發的話可以頂一下這篇文章,讓更多的朋友有機會看到它。也希望大家可以多留言來和我探討編程相關的問題。
最後,謝謝大家一直的支援~~~
The end