C++游戏之透明贴图(四)
2015-03-22 11:25
429 查看
上一章,我们已经知道了如何实现游戏动画,是不是很简单哇,这一章,我们就来说说如何透明贴图,我们知道GDI只支持BMP的位图,所以图片本身是不具备透明的,那么,我们如何来实现透明效果呢?很简单,这里介绍两种方式。
第一种:遮罩法
这种方式需要两张图片,第一张为原图,背景为黑色,第二张图为遮罩图,背景为白色,比如有角色素材如下:
[align=center] [/align]
[align=left] [/align]
通过BitBlt函数的光栅操作即可实现图片背景的透明处理,说简单点就是BitBlt的最后一个参数,白色and任意色=任意色,黑色and任意色=黑色,黑色or任意色=任意色,第一步我们通过SRCAND运算先贴上遮罩图,也就是第二张图片。核心代码如下:
通过上述代码,得到以下效果图
第二步:通过SRCPAINT运算贴上彩色图即可实现透明,是不是很简单哇,说白了,整个透明绘制也就是两句话,对同一张图片绘制两次就行了
透明效果如下
第二种:颜色删除法
顾名思义,就是删除某个颜色即可,比如有以下素材图片
观察发现,我们只需要删除黑色颜色即可,删除某个颜色,我们可以使用TransparentBlt函数,使用这个函数,需要一个类库文件
TransparentBlt函数参数:
实列代码如下:
就这样一个透明就实现了,相比较前面一个,这个简单了许多
总结,第一个方法绘制的图形质量高,但是需要两张图片,第二个方法虽然简单了许多,但是缺点也很明显,质量不是很高,如果人物中有与背景相同的颜色,那么也会被去掉,就好很难看。
完整代码:
源码下载: http://pan.baidu.com/s/1nt1LwwD
第一种:遮罩法
这种方式需要两张图片,第一张为原图,背景为黑色,第二张图为遮罩图,背景为白色,比如有角色素材如下:
[align=center] [/align]
[align=left] [/align]
通过BitBlt函数的光栅操作即可实现图片背景的透明处理,说简单点就是BitBlt的最后一个参数,白色and任意色=任意色,黑色and任意色=黑色,黑色or任意色=任意色,第一步我们通过SRCAND运算先贴上遮罩图,也就是第二张图片。核心代码如下:
SelectObject(mm_hdc,role); BitBlt(m_hdc,100,50,254,480,mm_hdc,254,0,SRCAND);//AND运算
通过上述代码,得到以下效果图
第二步:通过SRCPAINT运算贴上彩色图即可实现透明,是不是很简单哇,说白了,整个透明绘制也就是两句话,对同一张图片绘制两次就行了
SelectObject(mm_hdc,role); BitBlt(m_hdc,100,50,254,480,mm_hdc,254,0,SRCAND);//AND运算,帖上遮罩图
BitBlt(m_hdc,100,50,254,480,mm_hdc,0,0,SRCPAINT);//或运算,帖上彩色图
透明效果如下
第二种:颜色删除法
顾名思义,就是删除某个颜色即可,比如有以下素材图片
观察发现,我们只需要删除黑色颜色即可,删除某个颜色,我们可以使用TransparentBlt函数,使用这个函数,需要一个类库文件
#pragma comment(lib,"Msimg32.lib")
TransparentBlt函数参数:
WINGDIAPI BOOL WINAPI TransparentBlt( __in HDC hdcDest,//需要绘制的设备环境 __in int xoriginDest,//开始绘制的X坐标 __in int yoriginDest,//开始绘制的Y坐标 __in int wDest,//绘制的宽 __in int hDest,//绘制的高 __in HDC hdcSrc,//源图片的设备环境 __in int xoriginSrc,//从原图的X坐标开始 __in int yoriginSrc,//从原图的Y坐标开始 __in int wSrc,//宽 __in int hSrc,//高 __in UINT crTransparent);//删除的颜色
实列代码如下:
SelectObject(mm_hdc,role2); TransparentBlt(m_hdc,320,50,500,700,mm_hdc,0,0,500,700,RGB(0,0,0));//RGB(0,0,0)代表黑色
就这样一个透明就实现了,相比较前面一个,这个简单了许多
总结,第一个方法绘制的图形质量高,但是需要两张图片,第二个方法虽然简单了许多,但是缺点也很明显,质量不是很高,如果人物中有与背景相同的颜色,那么也会被去掉,就好很难看。
完整代码:
#include <Windows.h> #include <string> #pragma comment(lib,"winmm.lib") #pragma comment(lib,"Msimg32.lib") using namespace std; //窗体的过程函数 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam); HDC g_hdc;//设备环境 HDC m_hdc;//兼容的设备环境 HDC mm_hdc;//三级兼容设备 HBITMAP bg;//背景图片 HBITMAP role;//素材图片 HBITMAP role2;//素材图片2 //初始化资源,用于初始化设备环境和加载背景图片 void Game_Init(HWND hwnd); //绘制图形,正式绘制 void Game_Paint(HWND hwnd); //清理资源,程序退出时,释放资源 void Game_Clear(HWND hwnd); //WinMain主函数 INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrivInstance,LPSTR lpCmdLine,int nShowCmd) { //设计一个窗体 WNDCLASSEX wndClass = {0}; wndClass.style = CS_HREDRAW|CS_VREDRAW; wndClass.cbSize = sizeof(wndClass); wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wndClass.hCursor = ::LoadCursor(hInstance,IDC_ARROW); wndClass.hIcon = (HICON)::LoadImage(NULL,L"",IMAGE_ICON,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE); wndClass.hInstance = hInstance; wndClass.lpfnWndProc = WndProc; wndClass.lpszClassName = L"Test"; wndClass.lpszMenuName = 0; //注册窗体 if (!RegisterClassEx(&wndClass)) { return -1; } //创建窗体 HWND hwnd = CreateWindow(L"Test",L"GDI",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,800,600,NULL,NULL,hInstance,NULL); if (hwnd == NULL) { return -1; } //初始化资源 Game_Init(hwnd); //显示与更新窗体 ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); //消息队列 MSG msg = {0}; while (msg.message != WM_QUIT) { if (PeekMessage(&msg,0,0,0,PM_REMOVE))//读取消息 { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//发送消息 } else { Game_Paint(hwnd);//绘制函数 Sleep(50);//绘制间隙50毫秒 } } UnregisterClass(L"Test",hInstance); return 0; } //窗口过程函数 LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) { switch(message) { case WM_PAINT: ValidateRect(hwnd,NULL);//重绘整个窗体 break; case WM_DESTROY: Game_Clear(hwnd);//退出程序时,清理资源 PostQuitMessage(0); break; default: return DefWindowProc(hwnd,message,wparam,lparam); } return 0; } //初始化资源 void Game_Init(HWND hwnd) { g_hdc = GetDC(hwnd);//获取设备环境DC m_hdc = CreateCompatibleDC(g_hdc);//建立兼容的设备环境 mm_hdc = CreateCompatibleDC(m_hdc); SelectObject(m_hdc,CreateCompatibleBitmap(g_hdc,800,600)); bg = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE); role = (HBITMAP)LoadImage(NULL,L"role.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE); role2 = (HBITMAP)LoadImage(NULL,L"role2.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTSIZE); //播放背景音乐 //第一个参数,文件路径 //第二参数,应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL //第三个参数为标示,SND_LOOP重复播放,SND_ASYNC异步播放,SND_FILENAME来自硬盘文件 //PlaySound(L"bg.wav",0,SND_LOOP | SND_ASYNC | SND_FILENAME); } //绘制图形 void Game_Paint(HWND hwnd) { SelectObject(mm_hdc,bg); BitBlt(m_hdc,0,0,800,600,mm_hdc,0,0,SRCCOPY);//拷贝到设备环境上 SelectObject(mm_hdc,role); BitBlt(m_hdc,100,50,254,480,mm_hdc,254,0,SRCAND);//AND运算,帖上遮罩图 BitBlt(m_hdc,100,50,254,480,mm_hdc,0,0,SRCPAINT);//或运算,帖上彩色图 SelectObject(mm_hdc,role2); TransparentBlt(m_hdc,320,50,500,700,mm_hdc,0,0,500,700,RGB(0,0,0)); BitBlt(g_hdc,0,0,800,600,m_hdc,0,0,SRCCOPY); } //清理内存 void Game_Clear(HWND hwnd) { ReleaseDC(hwnd,g_hdc); DeleteObject(bg); DeleteObject(role); DeleteObject(role2); DeleteObject(m_hdc); }
源码下载: http://pan.baidu.com/s/1nt1LwwD
相关文章推荐
- [游戏模版8] Win32 透明贴图
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现
- [游戏模版13] Win32 透明贴图 主角移动
- 2016多益网络春季实习校园招聘笔试回顾(C++游戏后台开发)
- 使用TexturePacker打包游戏贴图制作帧动画
- 公司技术管理角度看C++游戏程序员发展
- c++游戏设计四:采蘑菇
- 用C++控制台实现简单RPG游戏
- 技术管理角度看C++游戏程序员发展
- 背景透明后字体,贴图产生遮盖覆盖问题的解决方法。
- C++游戏界面不流畅的问题
- 游戏开发之在UE4中编写C++代码控制角色
- opencv3/C++视频中叠加透明图片
- Unity3D 游戏贴图(法线贴图,漫反射贴图,高光贴图)
- 【Visual C++】游戏开发笔记之九 游戏地图制作(一)平面地图贴图
- C++十六周任务-字符串游戏4