【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
来源:互联网 发布:mysql列转行函数 编辑:程序博客网 时间:2024/05/16 18:26
本系列文章由zhmxy555编写,转载请注明出处。http://blog.csdn.net/zhmxy555/article/details/7338082
作者:毛星云 邮箱: happylifemxy@qq.com 欢迎邮件交流编程心得
从这节开始我们来讲解制作一般2D游戏画面经常要使用到的绘图特效。
笔记六我们主要介绍“透明”特效的制作方法。
透明效果
由于所有的图文件都是以矩形来储存的,我们也许会需要把一张怪兽图片贴到窗口的背景图上,而这种情况下如果直接进行贴图,结果如下图:
这似乎不是我们想要的结果。
为了得到透明效果,我们需要运用到BitBlt()贴图函数以及其参数Raster的值来将图片中不必要的部分去掉(又称去背),使得图中的主题可以与背景完美融合。
制作透明效果有很多种方法,但是基本上都是利用贴图时不同的Raster运算,通过转换而产生相同的透明效果。在这里先来介绍一种透明运算的方法。
我们以图中的恐龙为例子,首先准备一张位图,如下图。
图中的左边的图是要去背并贴到背景上的前景图。右边的黑白图称为“屏蔽图”,在透明的过程中会用到它。要把去背的位图与屏蔽图合并成同一张图,透明的时候再按照需要来进行裁切。可以把它分成两张图,但是这样程序必须运行两次图文件加载的操作。
有了屏蔽图就可以利用贴图函数来产生透明效果了,所需的贴图步骤如下:
<1>将屏蔽图与背景图做"AND"运算,Raster值为SRCAND,贴到目的地DC中。
<2>将前景图与背景图做"OR"运算,Raster值为SRCPAINT,贴到目的地DC中。
为什么经过上面两个操作就能产生透明的效果呢?看下图就理解了:
下面具体说明上面两个步骤所产生的图点色彩的变化。
1.屏蔽图与背景图做"AND"运算
<1>屏蔽图中的黑色部分与背景图做"AND"运算:
<2>屏蔽图中的白色部分与背景图做"AND"运算:
进过这一运算所产生的结果如下图
2.前景图与背景图做"OR"运算
<1>前景图中的彩色部分与图第一步得到的“黑色恐龙”图做"OR"运算:
<2>前景图中的黑色部分与第一步得到的“黑色恐龙”图做"OR"运算:
经过这一运算后所显示的画面就是所需的透明图了,如下图所示:
下面我们来看看实现上述透明贴图效果的源代码
- #include "stdafx.h"
- //全局变量声明
- HINSTANCE hInst;
- HBITMAP bg,dra; //声明两个位图对象,分别存储背景图与前景恐龙图
- HDC mdc; //声明一个内存DC"mdc",用来暂存位图
- //全局函数声明
- 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;
- }
- //消息循环
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- 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);
- }
- //****初始化函数*************************************
- // 1.建立与窗口DC兼容的内存DC
- // 2.从文件加载背景图与恐龙图
- BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
- {
- HWND hWnd;
- HDC hdc;
- 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,600,450,true);
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- hdc = GetDC(hWnd); //获得窗口DC
- mdc = CreateCompatibleDC(hdc); //创建与窗口兼容的内存DC(mdc)
- bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,600,450,LR_LOADFROMFILE);
- //J加载背景图到bg中
- dra = (HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,170,99,LR_LOADFROMFILE);
- //加载恐龙图到dra中
- MyPaint(hdc);
- ReleaseDC(hWnd,hdc);
- return TRUE;
- }
- //****自定义绘图函数*********************************
- //透明贴图
- void MyPaint(HDC hdc)
- {
- SelectObject(mdc,bg);
- BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY); //先将背景图贴到显示窗口中
- SelectObject(mdc,dra); //选用恐龙图到"mdc"中
- BitBlt(hdc,280,320,85,99,mdc,85,0,SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张恐龙图中,最左上角起始位置点得坐标为(85,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。
- BitBlt(hdc,280,320,85,99,mdc,0,0,SRCPAINT);//进行制作透明贴图的第二步骤,即将前景图与背景图做"OR"运算,前景图在整张恐龙图中,最左上角起始位置的坐标为(0,0),BitBlt()函数最后一个参数值设置为SRCPAINT。
- }
- //****消息处理函数**********************************
- LRESULT CALLBACK WndProc(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
- {
- PAINTSTRUCT ps;
- HDC hdc;
- switch (message)
- {
- case WM_PAINT: //窗口重绘消息
- hdc = BeginPaint(hWnd, &ps);
- MyPaint(hdc);
- EndPaint(hWnd, &ps);
- break;
- case WM_DESTROY: //窗口结束消息
- DeleteDC(mdc);
- DeleteObject(bg);
- DeleteObject(dra);
- PostQuitMessage(0);
- break;
- default: //其他消息
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }
#include "stdafx.h"//全局变量声明HINSTANCE hInst;HBITMAP bg,dra; //声明两个位图对象,分别存储背景图与前景恐龙图HDC mdc; //声明一个内存DC"mdc",用来暂存位图//全局函数声明ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACKWndProc(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;}//消息循环while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);}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);}//****初始化函数*************************************// 1.建立与窗口DC兼容的内存DC// 2.从文件加载背景图与恐龙图BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){HWND hWnd;HDC hdc;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,600,450,true);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);hdc = GetDC(hWnd); //获得窗口DCmdc = CreateCompatibleDC(hdc); //创建与窗口兼容的内存DC(mdc)bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,600,450,LR_LOADFROMFILE); //J加载背景图到bg中dra = (HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,170,99,LR_LOADFROMFILE); //加载恐龙图到dra中MyPaint(hdc);ReleaseDC(hWnd,hdc);return TRUE;}//****自定义绘图函数*********************************//透明贴图void MyPaint(HDC hdc){SelectObject(mdc,bg);BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY); //先将背景图贴到显示窗口中SelectObject(mdc,dra); //选用恐龙图到"mdc"中BitBlt(hdc,280,320,85,99,mdc,85,0,SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张恐龙图中,最左上角起始位置点得坐标为(85,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。BitBlt(hdc,280,320,85,99,mdc,0,0,SRCPAINT);//进行制作透明贴图的第二步骤,即将前景图与背景图做"OR"运算,前景图在整张恐龙图中,最左上角起始位置的坐标为(0,0),BitBlt()函数最后一个参数值设置为SRCPAINT。}//****消息处理函数**********************************LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){PAINTSTRUCT ps;HDC hdc;switch (message){case WM_PAINT: //窗口重绘消息hdc = BeginPaint(hWnd, &ps);MyPaint(hdc);EndPaint(hWnd, &ps);break;case WM_DESTROY: //窗口结束消息DeleteDC(mdc);DeleteObject(bg);DeleteObject(dra);PostQuitMessage(0);break;default: //其他消息return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}
最后程序的运行结果为:
通过BitBlt()贴图函数及Raster运算值的设定,很简单地就做出了想要的透明效果,这种方法在设计2D游戏的一些画面内容时使用相当频繁。
最后我说明一个非常关键的问题(多谢yao050421103 的提醒),而这点由恰恰依赖于美工设计师们。我们在准备位图资源的时候,前景图部分绝对不能包含背景图的颜色,否则,就不会得到我们预期的结果。
还要指出的一个地方是,前景图的需要还原为背景色的部分一定要为黑色(多谢infoworld的指出)。
笔记六到这里就结束了。
本节源代码请点击这里下载:【Visual C++】Code_Note_6
请大家继续关注【Visual C++】游戏开发笔记系列。
非常希望能与大家一起交流,共同学习和进步。
最后,谢谢大家的支持~~~
The end
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- 【Visual C++】游戏开发笔记之十四 游戏画面绘图(四) 华丽的CImage类
- 【Visual C++】游戏开发笔记之四——游戏画面绘图(一)基本图形绘制
- HibernateDaoSupport详解
- 【Visual C++】游戏开发笔记之五——游戏画面绘图(二)绘制位图
- FTP断点续传
- POJ3037 滑雪(单源最短路径)
- 【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
- 【Visual C++】游戏开发笔记之七——基础动画显示(一)定时器的使用
- (转)SQL语句增加列、修改列类型、修改列、删除列
- 【Visual C++】游戏开发笔记之八——基础动画显示(二)游戏循环的使用
- HTTP工作原理及HTTP请求、响应报文解读
- FTP协议命令
- AH快递单打印查询软件V3.68
- hdu 1087 Super Jumping! Jumping! Jumping!
- jQuery判断复选框(checkbox)是否被选中(每多学一点知识,就少些一行代码)