博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Visual C++】游戏开发笔记之六——游戏画面绘图(三)透明特效的制作方法
阅读量:5082 次
发布时间:2019-06-13

本文共 4151 字,大约阅读时间需要 13 分钟。

本系列文章由zhmxy555编写,转载请注明出处。 

作者:毛星云    邮箱: 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; }

最后程序的运行结果为:

通过BitBlt()贴图函数及Raster运算值的设定,很简单地就做出了想要的透明效果,这种方法在设计2D游戏的一些画面内容时使用相当频繁。

最后我说明一个非常关键的问题(多谢yao050421103 的提醒),而这点由恰恰依赖于美工设计师们。我们在准备位图资源的时候,前景图部分绝对不能包含背景图的颜色,否则,就不会得到我们预期的结果。

还要指出的一个地方是,前景图的需要还原为背景色的部分一定要为黑色(多谢infoworld的指出)。

笔记六到这里就结束了。

本节源代码请点击这里下载:

请大家继续关注【Visual C++】游戏开发笔记系列。

非常希望能与大家一起交流,共同学习和进步。

最后,谢谢大家的支持~~~

 

The end

转载于:https://www.cnblogs.com/dyllove98/archive/2012/03/09/2461885.html

你可能感兴趣的文章
angularJS 移动端焦点图
查看>>
jvm 这我就能会了 擦
查看>>
实战技能:小小微信支付业务,何必虚惊一场
查看>>
17-1 djanjo进阶-路由,视图,模板
查看>>
Shell脚本8种字符串截取方法总结
查看>>
P3254 圆桌问题
查看>>
MapReduce的运行原理
查看>>
Leetcode: Partition List
查看>>
故障转移
查看>>
清空dataset中的某行某列的数据
查看>>
盒模型
查看>>
js中闭包和作用域
查看>>
关键词提取
查看>>
装饰器,迭代器与生成器
查看>>
endpoint 理解-1
查看>>
Lambad表达式树(转)
查看>>
15 SharePreference
查看>>
24点
查看>>
各种米的营养价值
查看>>
php 处理数字为金钱格式
查看>>