我的家園

          我的家園

          本系列文章由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;
          HDC		hdc,mdc,bufdc;
          HWND	hWnd;
          DWORD	tPre,tNow;
          int		num,x,y;
          
          //全局函數聲明
          ATOM				MyRegisterClass(HINSTANCE hInstance);
          BOOL				InitInstance(HINSTANCE, int);
          LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
          void				MyPaint(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:					//窗口結束消息,撤銷各種DC
          			DeleteDC(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




          作者:zhmxy555 發表于2012-3-21 4:27:21 原文鏈接
          閱讀:11410 評論:106 查看評論

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 揭阳市| 肥乡县| 澎湖县| 宝清县| 南平市| 林甸县| 从江县| 铜鼓县| 理塘县| 保亭| 大余县| 甘孜县| 盐边县| 吴忠市| 黎城县| 科尔| 南开区| 井陉县| 盱眙县| 介休市| 铜川市| 偃师市| 乐东| 罗田县| 蛟河市| 无极县| 壤塘县| 建昌县| 资中县| 昌平区| 滨州市| 新营市| 宁明县| 阿拉善左旗| 揭东县| 通渭县| 渭源县| 高雄县| 青冈县| 仙游县| 牡丹江市|