游戏编程基础(二)GDI透明半透明效果

半透明在游戏中通常用于若隐若现的特殊效果,如雾,隐形单位。半透明的原理是通过前景图片与背景图片像素的混合来实现的。

用公式表示即为:半透明色 = 前景色X不透明度 + 背景色X(1-不透明度)

为了制作半透明效果,需要先了解一些基本的知识:

windows 位图结构

typedef struct tagBITMAP{ 

  LONG bmType; //位图类型,必须为0 

  LONG bmWidth; //位图宽度 

  LONG bmHeight; //位图高度 

  LONG bmWidthBytes; //每一行像素所占的byte数 

  WORD bmPlanes; //颜色平面数 

  WORD bmBitsPixel; //像素的位数 

  LPVOID bmBits; //位图内存指针 

  }BITMAP;


步骤:

  • 获取位图结构
函数原型:int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
HBITMAP hBitmapImag;   
BITMAP bitmap ;    
hBitmapImag = LoadBitmap (hInstance, TEXT ("D:\\photos\\sample.bmp")) ;   
GetObject (hBitmapImag, sizeof (BITMAP), &bitmap) ; 


 

  • 建立暂存数组
unsigned char * px = new unsigned char[bm.bmHeight * bm.bmWidthBytes];
  • 取得位图位
函数原型:LONG GetBitmapBits(HBITMAP hbmp, LONG cbBuffer, LPVOID lpvBits); 
BITMAP bitmap;   
GetObject(hBitmap, sizeof(BITMAP), &bitmap);   
DWORD dwSize = bitmap.bmHeight * bitmap.bmWidthBytes;   
unsigned char* pBits = new unsigned char[dwSize];   
LONG dl = GetBitmapBits(hBitmap, dwSize, pBits); 


 

  • 合成像素半透明颜色

             这一步根据需要透明的效果,根据上面的公式计算即可。

  • 重设位图颜色
函数原型:LONG SetBitmapBits(HBITMAP hmbp, DWORD cBytes, CONST VOID (lpBits); 

 

再结合之前GDI透明效果,就能实现透明半透明效果了。

主要是通过多使用一张内存DC与位图对象,先在内存DC上完成透明,再取此DC的位图来进行半透明处理即可

关键代码:

bg = (HBITMAP)LoadImage(NULL,"testbg.bmp",IMAGE_BITMAP,512,384,LR_LOADFROMFILE); //背景图
	bmp = (HBITMAP)LoadImage(NULL,"sample2.bmp",IMAGE_BITMAP,276,232,LR_LOADFROMFILE);//屏蔽图

	GetObject(bg,sizeof(BITMAP),&bm1);	  //获取背景位图结构	
	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc); //而外创建的内存DC
	test = CreateCompatibleBitmap(hdc,276,232); //内存位图

	SelectObject(mdc,test);

	// 先进行透明处理
	SelectObject(bufdc,bg);
	BitBlt(mdc,0,0,276,232,bufdc,xstart,ystart,SRCCOPY);
	SelectObject(bufdc,bmp);
	BitBlt(mdc,0,0,276,232,bufdc,0,0,SRCAND);
	bmp = (HBITMAP)LoadImage(NULL,"sample1.bmp",IMAGE_BITMAP,276,232,LR_LOADFROMFILE);
	SelectObject(bufdc,bmp);
	BitBlt(mdc,0,0,276,232,bufdc,0,0,SRCPAINT);

	unsigned char *px1,*px2;

	//背景位图的位数组
	px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];
	GetBitmapBits(bg,bm1.bmHeight * bm1.bmWidthBytes,px1);

	//透明位图的位数组
	GetObject(test,sizeof(BITMAP),&bm2);
	px2 = new unsigned char [bm2.bmHeight * bm2.bmWidthBytes];
	GetBitmapBits(test,bm2.bmHeight * bm2.bmWidthBytes,px2);

	int x,y,xend,yend;
	int i;
	int rgb_b;
	int PxBytes = bm1.bmBitsPixel / 8 ;

	xend = xstart + 276;
	yend = ystart + 232;

	//背景色不透明度处理
	for(y=ystart;y<yend;y++) 	
	{
		for(x=xstart;x<xend;x++) 
		{
			rgb_b = y * bm1.bmWidthBytes + x * PxBytes ;

			px1[rgb_b] = px1[rgb_b] * 0.5;		
			px1[rgb_b+1] = px1[rgb_b+1] * 0.5;		
			px1[rgb_b+2] = px1[rgb_b+2] * 0.5;		
		}
	}

	//前景色不透明度处理
	for(y=0;y<(bm2.bmHeight); y++) 	
	{
		for(x=0;x<bm2.bmWidth; x++) 
		{
			rgb_b = y * bm2.bmWidthBytes + x * PxBytes ;
			i = (ystart+y) * bm1.bmWidthBytes + (xstart+x) * PxBytes;

			px2[rgb_b]	 = px2[rgb_b] *0.5 + px1[i];	
			px2[rgb_b+1] = px2[rgb_b+1] *0.5 + px1[i+1];	
			px2[rgb_b+2] = px2[rgb_b+2] *0.5 + px1[i+2];	
		}
	}

	SetBitmapBits(test,bm2.bmHeight*bm2.bmWidthBytes,px2);
	..............................................
	SelectObject(mdc,bg);
	BitBlt(hdc,0,0,512,384,mdc,0,0,SRCCOPY);
	SelectObject(mdc,test);
	BitBlt(hdc,xstart,ystart,276,232,mdc,0,0,SRCCOPY);

 最终效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值