visual C++游戏绘图之透明效果制作原理

作者:晋文格墨    邮箱: chairperson@sina.cn   

透明效果

由于所有的图文件都是以矩形来储存的,我们也许会需要把一张易拉罐图片贴到窗口的背景图上,而这种情况下如果直接进行贴图,结果如下图:

这似乎不是我们想要的结果。

为了得到透明效果,我们需要运用到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"运算:

经过这一运算后所显示的画面就是所需的透明图了,如下图所示:

下面我们来看看实现上述透明贴图效果的源代码

[cpp] view
plain
copyprint?

  1. #include "stdafx.h"  
  2. //全局变量声明  
  3. HINSTANCE hInst;  
  4. HBITMAP bg,sprite;        //声明两个位图对象,分别存储背景图与前景易拉罐  
  5. HDC  mdc;       //声明一个内存DC"mdc",用来暂存位图  
  6. //全局函数声明  
  7. ATOM     MyRegisterClass(HINSTANCE hInstance);  
  8. BOOL     InitInstance(HINSTANCE, int);  
  9. LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);  
  10. void     MyPaint(HDC hdc);  
  11. ////****Winmain函数,程序入口点函数**************************************  
  12. int APIENTRY WinMain(HINSTANCE hInstance,  
  13.                      HINSTANCE hPrevInstance,  
  14.                      LPSTR     lpCmdLine,  
  15.                      int       nCmdShow)  
  16. {  
  17. MSG msg;  
  18. MyRegisterClass(hInstance);  
  19. if (!InitInstance (hInstance, nCmdShow))   
  20. {  
  21. return FALSE;  
  22. }  
  23. //消息循环  
  24. while (GetMessage(&msg, NULL, 0, 0))   
  25. {  
  26. TranslateMessage(&msg);  
  27. DispatchMessage(&msg);  
  28. }  
  29. return msg.wParam;  
  30. }  
  31. //****设计一个窗口类,类似填空题,使用窗口结构体*************************  
  32. ATOM MyRegisterClass(HINSTANCE hInstance)  
  33. {  
  34. WNDCLASSEX wcex;  
  35. wcex.cbSize = sizeof(WNDCLASSEX);   
  36. wcex.style   = CS_HREDRAW | CS_VREDRAW;  
  37. wcex.lpfnWndProc    = (WNDPROC)WndProc;  
  38. wcex.cbClsExtra  = 0;  
  39. wcex.cbWndExtra  = 0;  
  40. wcex.hInstance   = hInstance;  
  41. wcex.hIcon   = NULL;  
  42. wcex.hCursor     = NULL;  
  43. wcex.hCursor     = LoadCursor(NULL, IDC_ARROW);  
  44. wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  
  45. wcex.lpszMenuName   = NULL;  
  46. wcex.lpszClassName  = "canvas";  
  47. wcex.hIconSm     = NULL;  
  48. return RegisterClassEx(&wcex);  
  49. }  
  50. //****初始化函数*************************************  
  51. // 1.建立与窗口DC兼容的内存DC  
  52. // 2.从文件加载背景图与恐龙图  
  53. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  
  54. {  
  55. HWND hWnd;  
  56. HDC hdc;  
  57. hInst = hInstance;  
  58. hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,  
  59. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);  
  60. if (!hWnd)  
  61. {  
  62. return FALSE;  
  63. }  
  64. MoveWindow(hWnd,10,10,600,450,true);  
  65. ShowWindow(hWnd, nCmdShow);  
  66. UpdateWindow(hWnd);  
  67. hdc = GetDC(hWnd);                     //获得窗口DC  
  68. mdc = CreateCompatibleDC(hdc);           //创建与窗口兼容的内存DC(mdc)  
  69. bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,600,450,LR_LOADFROMFILE);   
  70. //J加载背景图到bg中  
  71. sprite = (HBITMAP)LoadImage(NULL,"sprite.bmp",IMAGE_BITMAP,170,99,LR_LOADFROMFILE);   
  72. //加载易拉罐图到sprite中  
  73. MyPaint(hdc);  
  74. ReleaseDC(hWnd,hdc);  
  75. return TRUE;  
  76. }  
  77. //****自定义绘图函数*********************************  
  78. //透明贴图  
  79. void MyPaint(HDC hdc)  
  80. {  
  81. SelectObject(mdc,bg);  
  82. BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY);    //先将背景图贴到显示窗口中  
  83. SelectObject(mdc,sprite);                      //选用易拉罐图到"mdc"中  
  84. BitBlt(hdc,50,50,225,225,mdc,225,0,SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张易拉罐图中,最左上角起始位置点得坐标为(225,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。  
  85. BitBlt(hdc,50,50,225,225,mdc,0,0,SRCPAINT);//进行制作透明贴图的第二步骤,即将前景图与背景图做"OR"运算,前景图在整张易拉罐图中,最左上角起始位置的坐标为(0,0),BitBlt()函数最后一个参数值设置为SRCPAINT。  
  86. }  
  87. //****消息处理函数**********************************  
  88. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  89. {  
  90. PAINTSTRUCT ps;  
  91. HDC hdc;  
  92. switch (message)  
  93. {  
  94. case WM_PAINT:   //窗口重绘消息  
  95. hdc = BeginPaint(hWnd, &ps);  
  96. MyPaint(hdc);  
  97. EndPaint(hWnd, &ps);  
  98. break;  
  99. case WM_DESTROY:     //窗口结束消息  
  100. DeleteDC(mdc);  
  101. DeleteObject(bg);  
  102. DeleteObject(sprite);  
  103. PostQuitMessage(0);  
  104. break;  
  105. default:     //其他消息  
  106. return DefWindowProc(hWnd, message, wParam, lParam);  
  107.    }  
  108.    return 0;  
  109. }  

最后程序的运行结果为:

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

时间: 2024-10-24 17:22:11

visual C++游戏绘图之透明效果制作原理的相关文章

VC++实现位图显示透明效果--实现原理

我们在进行程序的界面设计时,常常希望将位图的关键部分,也既是图像的前景显示在界面上,而将位图的背景隐藏起来,将位图与界面很自然的融合在一起,本文介绍了透明位图的制作知识,并将透明位图在一个对话框中显示了出来.本文所使用的原始位图及程序编译运行后的界面效果如下图所示: 图一.原始位图 图二.对话框界面上透明显示位图 一.实现方法 绘制"透明"位图是指绘制某一位图中除指定颜色外的其余部分,我们称这种颜色为"透明色".通过将位图的背景色指定为"透明色"

wps演示教程:艺术字闪动效果制作

wpp演示中艺术字的使用十分广泛,辅以闪动效果,定能为演示增色不少. 新建空白的wpp文档,选择名为"流光溢彩"的模版,内容板式设为空白.在"绘图"工具栏上,单击"插入艺术字" 按钮,打开"艺术字库"对话框. 选择左侧最下艺术字样式,单击"确定"按钮,打开"编辑"艺术字"文字"对话框,在"文字"框中输入文字"新年快乐".单击字体

Photoshop绘制五彩透明效果的圆球形图标

  Photoshop绘制五彩透明效果的圆球形图标         分类: PS鼠绘教程 ps图标制作教程

C# 透明窗体制作实现方法比较分析_C#教程

制作透明窗体办法有好几种,各有优缺点. 我们先来看看C#本身提供的办法 1:通过设置窗体的 TransparencyKey实现 例:窗体中的白色会变成透明 复制代码 代码如下: this.BackColor =Color.White; this.TransparencyKey = Color.White; 2:通过设置窗体的 Opacity 实现 例:窗体的透明度为50% 复制代码 代码如下: this.Opacity = 0.5; 为了更好说明问题,我们先看一个实例. (1)新建一个winfo

Illustrator设计晶莹剔透小字体效果制作教程

给各位Illustrator软件的使用者们来详细的解析分享一下设计晶莹剔透小字体效果的制作教程. 教程分享: 首先我们用钢笔勾出想要设计的内容,这里我们要注意的是曲线的平滑度,这样做出来的才好看.   我们用渐变填充上颜色,不需要描边.   我们再复制一层(ctrl+c)放在这层的下面(ctrl+b),并且描边(参考值2pt)为紫色       现在我们来制作高光部分,还记得上节我们做的水汪汪字体中高光的制作吗`?今天我们制作另外一种高光形式,相比上次的来说`,这次的感觉会可爱,卡通些! 首先我

CAGradientLayer实现图片渐变透明效果

CAGradientLayer实现图片渐变透明效果 要实现的效果如下: 源码: // // RootViewController.m // CAGradientLayer // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "YXGCD.h" @interface RootViewController () @property (n

使窗体拥有透明效果的API

一.背景 FlashGet的透明效果大家羡慕吧.传统的Windows应用程序想实现半透明效果,一般来说需要处理自己的窗口的WM_Paint消息窗口,很麻烦.现在好了,SetLayeredWindowAttributes是windows的新api,win2000以上才支持,它能使使窗体拥有透明效果.我在Google搜了下,介绍SetLayeredWindowAttributes的文章大多是delphi的和vb的.好不容易找到一篇vc的,依法炮制后,vc的IDE却说我SetLayeredWindow

CSS3 HTML5使用 RGBA 实现透明效果实例

目前,Web 设计中的透明效果主要靠 PNG 图片实现(但在 IE 浏览器支持得并不好 - 译者),在 CSS3,可以直接实现透明效果. rgba(200, 54, 54, 0.5); background: rgba(200, 54, 54, 0.5); color: rgba(200, 54, 54, 0.5); color: #000; opacity: 0.5; 支持的浏览器: Firefox, Safari, Chrome, Opera (opacity) 以及 IE7 (opacit

CSS实现分页效果制作实例

CSS实现分页效果制作实例,教程和代码如下:  这个教程要说明的是如何为搜索结果或更长记录列表设计分页.因为经常有人问我这个问题,所以我决定发一个帖子来说明如何用少量的 HTML 和 CSS 代码设计出完美的分页样式. 这个教程也包含有实现Flickr.Digg式的简洁分页样式的HTML/CSS代码,随时可以应用于你的WEB项目中. Update as March 17, 2008: My friends Simone Saveri solved some issuse with IE6 and