【转】C++游戏之透明贴图

转载文章,原文链接:
https://blog.csdn.net/qq969422014/article/details/44536375

           上一章,我们已经知道了如何实现游戏动画,是不是很简单哇,这一章,我们就来说说如何透明贴图,我们知道GDI只支持BMP的位图,所以图片本身是不具备透明的,那么,我们如何来实现透明效果呢?很简单,这里介绍两种方式。

           第一种:遮罩法

                     这种方式需要两张图片,第一张为原图,背景为黑色,第二张图为遮罩图,背景为白色,比如有角色素材如下:

 
          

                  通过BitBlt函数的光栅操作即可实现图片背景的透明处理,说简单点就是BitBlt的最后一个参数,白色and任意色=任意色,黑色and任意色=黑色,黑色or任意色=任意色,第一步我们通过SRCAND运算先贴上遮罩图,也就是第二张图片。核心代码如下:


   
   
  1. SelectObject(mm_hdc,role);
  2. BitBlt(m_hdc, 100, 50, 254, 480,mm_hdc, 254, 0,SRCAND); //AND运算

通过上述代码,得到以下效果图

第二步:通过SRCPAINT运算贴上彩色图即可实现透明,是不是很简单哇,说白了,整个透明绘制也就是两句话,对同一张图片绘制两次就行了


   
   
  1. SelectObject(mm_hdc,role);
  2. BitBlt(m_hdc, 100, 50, 254, 480,mm_hdc, 254, 0,SRCAND); //AND运算,帖上遮罩图
  3. BitBlt(m_hdc, 100, 50, 254, 480,mm_hdc, 0, 0,SRCPAINT); //或运算,帖上彩色图

透明效果如下

 

             第二种:颜色删除法

                     顾名思义,就是删除某个颜色即可,比如有以下素材图片

 

观察发现,我们只需要删除黑色颜色即可,删除某个颜色,我们可以使用TransparentBlt函数,使用这个函数,需要一个类库文件

#pragma comment(lib,"Msimg32.lib")
   
   

 

TransparentBlt函数参数:


   
   
  1. WINGDIAPI BOOL WINAPI TransparentBlt(
  2. __in HDC hdcDest,//需要绘制的设备环境
  3. __in int xoriginDest,//开始绘制的X坐标
  4. __in int yoriginDest,//开始绘制的Y坐标
  5. __in int wDest,//绘制的宽
  6. __in int hDest,//绘制的高
  7. __in HDC hdcSrc,//源图片的设备环境
  8. __in int xoriginSrc,//从原图的X坐标开始
  9. __in int yoriginSrc,//从原图的Y坐标开始
  10. __in int wSrc,//宽
  11. __in int hSrc,//高
  12. __in UINT crTransparent); //删除的颜色

 

实列代码如下:


   
   
  1. SelectObject(mm_hdc,role2);
  2. TransparentBlt(m_hdc, 320, 50, 500, 700,mm_hdc, 0, 0, 500, 700, RGB( 0, 0, 0)); //RGB(0,0,0)代表黑色


就这样一个透明就实现了,相比较前面一个,这个简单了许多


 

总结,第一个方法绘制的图形质量高,但是需要两张图片,第二个方法虽然简单了许多,但是缺点也很明显,质量不是很高,如果人物中有与背景相同的颜色,那么也会被去掉,就好很难看。

 

完整代码:


   
   
  1. #include <Windows.h>
  2. #include <string>
  3. #pragma comment(lib,"winmm.lib")
  4. #pragma comment(lib,"Msimg32.lib")
  5. using namespace std;
  6. //窗体的过程函数
  7. LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
  8. HDC g_hdc; //设备环境
  9. HDC m_hdc; //兼容的设备环境
  10. HDC mm_hdc; //三级兼容设备
  11. HBITMAP bg; //背景图片
  12. HBITMAP role; //素材图片
  13. HBITMAP role2; //素材图片2
  14. //初始化资源,用于初始化设备环境和加载背景图片
  15. void Game_Init(HWND hwnd);
  16. //绘制图形,正式绘制
  17. void Game_Paint(HWND hwnd);
  18. //清理资源,程序退出时,释放资源
  19. void Game_Clear(HWND hwnd);
  20. //WinMain主函数
  21. INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrivInstance,LPSTR lpCmdLine,int nShowCmd)
  22. {
  23. //设计一个窗体
  24. WNDCLASSEX wndClass = { 0};
  25. wndClass.style = CS_HREDRAW|CS_VREDRAW;
  26. wndClass.cbSize = sizeof(wndClass);
  27. wndClass.cbClsExtra = 0;
  28. wndClass.cbWndExtra = 0;
  29. wndClass.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH);
  30. wndClass.hCursor = :: LoadCursor(hInstance,IDC_ARROW);
  31. wndClass.hIcon = (HICON):: LoadImage( NULL, L"",IMAGE_ICON, 0, 0,LR_LOADFROMFILE|LR_DEFAULTSIZE);
  32. wndClass.hInstance = hInstance;
  33. wndClass.lpfnWndProc = WndProc;
  34. wndClass.lpszClassName = L"Test";
  35. wndClass.lpszMenuName = 0;
  36. //注册窗体
  37. if (! RegisterClassEx(&wndClass))
  38. {
  39. return -1;
  40. }
  41. //创建窗体
  42. HWND hwnd = CreateWindow( L"Test", L"GDI",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 800, 600, NULL, NULL,hInstance, NULL);
  43. if (hwnd == NULL)
  44. {
  45. return -1;
  46. }
  47. //初始化资源
  48. Game_Init(hwnd);
  49. //显示与更新窗体
  50. ShowWindow(hwnd,nShowCmd);
  51. UpdateWindow(hwnd);
  52. //消息队列
  53. MSG msg = { 0};
  54. while (msg.message != WM_QUIT)
  55. {
  56. if ( PeekMessage(&msg, 0, 0, 0,PM_REMOVE)) //读取消息
  57. {
  58. TranslateMessage(&msg); //翻译消息
  59. DispatchMessage(&msg); //发送消息
  60. }
  61. else
  62. {
  63. Game_Paint(hwnd); //绘制函数
  64. Sleep( 50); //绘制间隙50毫秒
  65. }
  66. }
  67. UnregisterClass( L"Test",hInstance);
  68. return 0;
  69. }
  70. //窗口过程函数
  71. LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
  72. {
  73. switch(message)
  74. {
  75. case WM_PAINT:
  76. ValidateRect(hwnd, NULL); //重绘整个窗体
  77. break;
  78. case WM_DESTROY:
  79. Game_Clear(hwnd); //退出程序时,清理资源
  80. PostQuitMessage( 0);
  81. break;
  82. default:
  83. return DefWindowProc(hwnd,message,wparam,lparam);
  84. }
  85. return 0;
  86. }
  87. //初始化资源
  88. void Game_Init(HWND hwnd)
  89. {
  90. g_hdc = GetDC(hwnd); //获取设备环境DC
  91. m_hdc = CreateCompatibleDC(g_hdc); //建立兼容的设备环境
  92. mm_hdc = CreateCompatibleDC(m_hdc);
  93. SelectObject(m_hdc, CreateCompatibleBitmap(g_hdc, 800, 600));
  94. bg = (HBITMAP) LoadImage( NULL, L"bg.bmp",IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_DEFAULTSIZE);
  95. role = (HBITMAP) LoadImage( NULL, L"role.bmp",IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_DEFAULTSIZE);
  96. role2 = (HBITMAP) LoadImage( NULL, L"role2.bmp",IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_DEFAULTSIZE);
  97. //播放背景音乐
  98. //第一个参数,文件路径
  99. //第二参数,应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL
  100. //第三个参数为标示,SND_LOOP重复播放,SND_ASYNC异步播放,SND_FILENAME来自硬盘文件
  101. //PlaySound(L"bg.wav",0,SND_LOOP | SND_ASYNC | SND_FILENAME);
  102. }
  103. //绘制图形
  104. void Game_Paint(HWND hwnd)
  105. {
  106. SelectObject(mm_hdc,bg);
  107. BitBlt(m_hdc, 0, 0, 800, 600,mm_hdc, 0, 0,SRCCOPY); //拷贝到设备环境上
  108. SelectObject(mm_hdc,role);
  109. BitBlt(m_hdc, 100, 50, 254, 480,mm_hdc, 254, 0,SRCAND); //AND运算,帖上遮罩图
  110. BitBlt(m_hdc, 100, 50, 254, 480,mm_hdc, 0, 0,SRCPAINT); //或运算,帖上彩色图
  111. SelectObject(mm_hdc,role2);
  112. TransparentBlt(m_hdc, 320, 50, 500, 700,mm_hdc, 0, 0, 500, 700, RGB( 0, 0, 0));
  113. BitBlt(g_hdc, 0, 0, 800, 600,m_hdc, 0, 0,SRCCOPY);
  114. }
  115. //清理内存
  116. void Game_Clear(HWND hwnd)
  117. {
  118. ReleaseDC(hwnd,g_hdc);
  119. DeleteObject(bg);
  120. DeleteObject(role);
  121. DeleteObject(role2);
  122. DeleteObject(m_hdc);
  123. }

 

源码下载: http://pan.baidu.com/s/1nt1LwwD

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值