半透明在游戲中通常用來呈現若隱若現的特殊效果。事實上這種效果的運用相當頻繁,比如薄霧、鬼魂或隱形任務等,有時會以半透明的手法來表現。本篇隨筆就來介紹半透明效果的制作方法,下圖23是一張位圖經過半透明處理后顯示在背景上的效果。
1、半透明的制作原理 簡單地說,半透明效果就是前景圖案與背景圖案像素顏色的混合。從圖23中觀察半透明效果呈現的區(qū)域,可以看到背景圖案,也可看到前景的人物圖案。什么是前景圖案與背景圖案像素顏色的混合呢?這就要從位圖的基本結構開始談起了。
一張位圖是由許多的像素所組成的,每一個像素中都包含紅(R)、綠(G)、藍(B)三原色的色彩值,由這三種原色值來決定該像素的色彩。而要呈現半透明效果,必須將前景圖與背景圖彼此對應像素的顏色依某一比例來進行調配,這個比例就叫做“不透明度”。
以沒有進行半透明處理,單純地將一張前景圖貼到背景圖上的一塊區(qū)域來說,前景圖的不透明度是100%,而背景圖在這一塊區(qū)域上的不透明度則是0%(完全透明,所以看不見背景),也就是說在這塊區(qū)域上,背景圖的色彩完全派不上用場。
可是如果想要有半透明的效果,讓前景圖看起來稍微透明一點,那就需要確定不透明度的值。假設確定不透明度是70%,也就是說前景圖像素顏色按照一定的不透明度比例進行合成,那么最后整個區(qū)域所呈現出來的就是所要的半透明效果了。綜合上面的說明,可以整理出一個建檔的公式如下:
半透明圖色彩 = 前景圖色彩 × 不透明度 + 背景圖色彩 ×(1 - 不透明度)2、半透明的操作步驟 清楚了半透明制作的原理后,接下來說明程序產生半透明效果的實際步驟。
步驟一:取得位圖結構
位圖結構包含了一些位圖的基本信息,由于我們在制作半透明效果時會用到,因此在從文件加載位圖后,必須先取得該位圖的結構,而取的位圖結構的函數如下:
int GetObject( HGDIOBJ GDI對象, //取得GDI對象結構
int 結構大小,
LPVOID 結構變量,);
上面這個函數用于取得GDI對象的信息,包含這里所談的位圖,其中第3個參數是一個結構變量,如果是用于取得位圖的信息,則輸入一個位圖結構的地址,而Windows API所定義的位圖結構(BITMAP)如下:

typedef struct tagBITMAP
{
LONG bmType; // 位圖類型,必須設為0
LONG bmWidth; // 位圖寬度
LONG bmHeight; //位圖長度
LONG bmWidthBytes; //每一列像素所占Byte數
WORD bmPlanes; //顏色平面數
WORD bmBitsPixel; //像素的位數
LPVOID bmBits; //位圖內存指針
}BITMAP;
后面將會用到bmWidth、bmHeight、bmWidthBytes及bmBitsPixel這幾個結構成員的信息。
在此舉個例子來說明取得位圖結構的方法,假設現在有一個位圖名稱為“bitmap”,位圖結構變量名稱為“bm”,則使用GetObject()函數取得BITMAP結構的程序代碼如下:
GetObject(bitmap,sizeof(BITMAP),&bm);
這樣,位圖結構bm中的各個結構成員便包含了位圖bitmap的基本信息。
步驟二:建立暫存數組 取得位圖的結構,接下來必須先建立一個暫存數組準備存儲位圖中所有像素的顏色值。這個暫存數組的大小是由前一個步驟中所取得位圖的bmHeight與bmWidthBytes信息來決定的,因此,必須利用指針來動態(tài)建立。延續(xù)前一個例子,若要建立一個可存儲bitmap所有像素顏色值的暫存數組,程序代碼如下:
unsigned char *px = new unsigned char [bm.bmHeight * bm.bmWidthBytes];
這里,因為unsigned char變量類型大小是1Byte,所以這個數組的每個元素大小也就是1Byte(8bits)。以一張24bits色彩的位圖來說,它的每個像素是以24bits來表示顏色的,其中B(藍)、G(綠)、R(紅)三原色各占8個bits。
因此,在下面的步驟中,當取出位圖的所有顏色并存儲在這個數組中時,每一個像素會占用3個數組元素來存儲B、G、R的顏色值。
步驟三:取得位圖位置 建立了暫存數組之后,要取出位圖的所有顏色值存儲到數組中就簡單多了,有一個現成的API函數可以使用。
LONG GetBitmapBits( HBITMAP 位圖, // 取得位圖位值
LONG 要取得的Byte數,
LPVOID 存儲的數組指針);
使用此函數取得位圖位值的程序代碼如下。
GetBitmapBits(bitmap, bm.bmHeight * bm.bmWidthBytes, px);
下面以圖來說明像素顏色值存儲在數組中的對應關系,如下圖所示:
步驟四:合成像素顏色值
取得了位圖的所有像素顏色值之后,接下來的工作就是按照不透明度來設定半透明區(qū)域內每個像素的顏色了。
此時應該會有兩個像素顏色數組,一個是前景圖的,一個則是背景圖的。根據實際要顯示半透明區(qū)域的坐標,將這兩個數組算出對應的元素進行簽名講過的顏色合成運算,再存回暫存數組中,anemia數組中所存儲的便是已經完成半透明的顏色值了。這個步驟的實際處理過程,將在代碼中做詳細說明。
步驟五:重設位圖顏色 處理完暫存數組中半透明的顏色值之后,最后一個操作就是根據數組的內容來重設位圖的顏色。這個操作同樣可以使用一個API的函數來完成。
LONG SetBitmapBits( HBITMAP 位圖, //設定位圖位值
DWORD 顏色數組大小,
CONST VOID 數組指針 );//為什么是CONST VOID?
以上5個步驟都完成之后,所要的半透明圖也就完成了,剩下的就只有貼圖操作了。
范例ch2_7:取得前景圖與背景圖的顏色值,以前景圖的不透明度30%和背景圖的不透明度70%進行半透明處理,制作半透明效果。
下載地址:
ch2_7(上傳到windows live空間,可能需要MSN賬號登陸)
說明:程序源代碼中有相關的注釋。
程序運行結果如下圖:
PS:如想獲得更多關于Visual C++游戲開發(fā)的內容,可點擊隨筆
:《Visual C++游戲編程基礎》學習筆記——索引隨筆。