【Visual C++】游戏编程学习笔记之一:五毛钱特效之透明和半透明处理
本系列文章由@二货梦想家张程 所写,转载请注明出处。
本文章链接:http://blog.csdn.net/terence1212/article/details/44163799
作者:ZeeCoder 微博链接:http://weibo.com/zc463717263
我的邮箱:michealfloyd@126.com 欢迎大家发邮件来和我交流编程心得
you are what you read!与大家共勉!
--------------------------------------------------------------------------------------分割线ZeeCoder------------------------------------------------------------------------------------------
由于本科的专业不是计算机,但对计算机有很大的兴趣,也一直在自学C语言和VC++,MFC编程,所以接触VC++游戏编程上手不算太难,刚做好了传说中的五毛特效透明和半透明处理,所以写下这篇笔记。
OK,下面归入正题。
1.透明效果
P话就不多说了, 直接讲解代码。
透明效果需要用到万能的贴图函数BitBlt
- BOOL BitBlt(
- HDC hdc; //目的DC
- int x; //目的DC的x坐标
- int y; //目的DC的y坐标
- int nWidth; //贴到目的DC的宽度
- int nHeight;//贴到目的DC的高度
- HDC mdc; //来源DC
- int xSrc; //来源DC的x坐标
- int ySrc; //来源DC的y坐标
- DWORD dwRop;//贴图方式
- );
dwRop贴图方式有下面N种:
- BLACKNESS 使用黑色填充目标区域
- DSTINVERT 目标矩阵区域颜色取反
- MERGECOPY 使用与运算组合原设备矩形区域的颜色和目标设备的画刷
- MERGEPAINT 使用或运算将反向的源矩形区域的颜色和目标矩形区域的颜色合并
- NOTSRCCOPY 复制源设备区域的反色到目标设备中
- NOTSRCERASE 使用或运算组合源设备区域与目标设备区域的颜色,然后对结果颜色取反
- PATCOPY 复制源设备当前选中的画刷到目标设备
- PATINVERT 使用异或运算组合目标设备选中的画刷和目标设备区域的颜色
- PATPAINT 通过或运算组合目标区域当前选中的画刷和源设备区域反转的颜色
- SRCAND 使用与运算组合源设备和目标设备区域的颜色
- SRCCOPY 直接复制源设备区域到目标设备中
- SRCERASE 使用与运算组合目标设备区域的反色与源设备区域的颜色
- SRCINVERT 使用异或运算组合源设备区域颜色和目标设备区域颜色
- SRCPAINT 使用或运算组合源设备区域颜色和目标设备区域颜色
- WHITENESS 使用白色填充目标区域
透明效果需要用到SRCAND 和SRCPAINT这两种贴图方式。
好了,下面直接上代码。(本笔记均在VS2010平台下编程)
1、首先定义全局变量
- <pre name="code" class="cpp">//全局变量
- HINSTANCE hInst;
- HBITMAP bg , character; // 这里两个位图对象分别储存背景图和人物图
- HDC mdc; //声明一个DC来暂存位图
- void MyPaint(HDC hdc); //声明自定义的函数
2、初始化函数
- //****初始化函数*************************************
- // 1.建立与窗口DC兼容的内存DC
- // 2.从文件加载背景图与恐龙图
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
- HWND hWnd;
- HDC hdc;
- hInst = hInstance; // Store instance handle in our global variable
- hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
- if (!hWnd)
- {
- return FALSE;
- }
- MoveWindow(hWnd , 10 ,10 , 650 , 600 ,true);
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- hdc = GetDC(hWnd);//获得窗口DC
- mdc = CreateCompatibleDC(hdc);////创建与窗口兼容的内存DC(mdc)
- bg = (HBITMAP)LoadImage(NULL , _T("res.bmp") , IMAGE_BITMAP , 640 , 360 ,LR_LOADFROMFILE);//加载背景图到bg中
- character = (HBITMAP)LoadImage(NULL , _T("dra.bmp"), IMAGE_BITMAP , 170 , 99 , LR_LOADFROMFILE);//加载恐龙图到character中
- MyPaint(hdc);
- return TRUE;
- }
3、自定义贴图函数
- //****自定义绘图函数*********************************
- //透明贴图
- void MyPaint(HDC hdc)
- {
- SelectObject(mdc , bg);
- BitBlt(hdc , 0 , 0 , 650 ,360 , mdc , 0 ,0 ,SRCCOPY );//先将背景图贴到显示窗口中
- SelectObject(mdc , character);//选用character图到"mdc"中
- BitBlt(hdc , 200 , 200 , 85 , 128 , mdc , 85 , 0 , SRCAND);//进行制作贴图的第一步骤,即将屏蔽图与背景图做"AND"运算,屏蔽图在整张恐龙图中,最左上角起始位置点得坐标为(85,0),BitBlt()函数中最后一个Raster参数值设置为SRCAND。
- BitBlt(hdc , 200 ,200 ,85 ,128 , mdc , 0 ,0 , SRCPAINT);//进行制作透明贴图的第二步骤,即将前景图与背景图做"OR"运算,前景图在整张恐龙图中,最左上角起始位置的坐标为(0,0),BitBlt()函数最后一个参数值设置为SRCPAINT。
- }
4.效果图:
2.半透明效果
半透明效果主要分为以下几个步骤:
(1)取得位图结构
- int GetObject(
- HGDIOBJ hgdiobj, //取得GDI结构对象
- int cbBuffer, //结构大小
- LPVOID lpvObject //结构变量
- );
上面这个函数在此处为了取得位图的信息,则输入一个位图结构的地址,windows Api 中所定义的位图结构(BITMAP)如下:
- typedef struct tagBITMAP
- {
- LONG bmType; //位图类型必须设为0
- LONG bmWidth;//位图宽度
- LONG bmHeight;//位图长度
- LONG bmWidthBytes;//每一列像素所占Bit数
- WORD bmPlanes;//颜色平面数
- WORD bmBitsPixel;//像素的位数
- LPVOID bmBits;//位图内存指针
- } BITMAP;
所以要取得位图信息的话,程序代码如下
- GetObject( bitmap , sizeof(BITMAP) , &bm);
(2)建立暂存数组
用动态指针来建立一个暂存数组来存储位图中所有像素的颜色值。
程序代码如下:
- unsigned char *px1 = new unsigned char [bm.bmHeight * bm.bmWidthBytes];
(3)取得位图位值
取得位图中所有的颜色值,需要用到如下函数:
- GetBitmapBits(
- HBITMAP hbit, //取得位图位值
- LONG cb, //要取得的bit数
- LPVOID lpvBits // 存储的数组指针
- );
(4)合成像素颜色值
按照不透明度来设定半透明区域的每个像素的颜色
(5)重设位图颜色
根据上个步骤中获得的暂存数组的半透明颜色值来重设位图的颜色值
这里用到windowsApi提供的函数:
- SetBitmapBits(
- HBITMAP hbm, //位图
- DWORD cb, //颜色数组的大小
- CONST VOID *pvBits //数组指针
- );
OK,全部的步骤就介绍到这里,下面看具体怎么实现。
1、全局变量设定
- HINSTANCE hInst; // current instance
- HBITMAP bg , dra ;
- HDC mdc;
- //常数定义
- const int xstart = 50 ;
- const int ystart = 20 ;
2、初始化函数
- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
- {
- HWND hWnd;
- HDC hdc;
- hInst = hInstance; // Store instance handle in our global variable
- hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
- if (!hWnd)
- {
- return FALSE;
- }
- MoveWindow(hWnd , 10 ,10 , 650 , 600 ,true);
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- hdc = GetDC(hWnd);
- mdc = CreateCompatibleDC(hdc);
- BITMAP bm1 , bm2 ;
- unsigned char *px1 , *px2 ;
- //处理背景图
- bg = (HBITMAP)LoadImage(NULL , _T("res.bmp") , IMAGE_BITMAP , 640 , 360 ,LR_LOADFROMFILE);
- GetObject(bg , sizeof(BITMAP) , &bm1);
- if (bm1.bmBitsPixel != 32 && bm1.bmBitsPixel != 24)
- {
- MessageBox(NULL, _T("此程序只能在32bit或24bit显示模式中运行" ), _T("警告") , 0);
- return FALSE;
- }
- px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];
- GetBitmapBits(bg , bm1.bmHeight * bm1.bmWidthBytes , px1);
- //处理前景图
- dra = (HBITMAP)LoadImage(NULL , _T("14.bmp"), IMAGE_BITMAP , 120 , 128 , LR_LOADFROMFILE);
- GetObject(dra , sizeof(BITMAP) , &bm2);
- px2 = new unsigned char [bm2.bmHeight * bm2.bmWidthBytes];
- GetBitmapBits(dra , bm2.bmHeight * bm2.bmWidthBytes , px2);
- int xend ,yend ;
- int x ,y , i ;
- int rgb_b;
- int PxBytes = bm1.bmBitsPixel / 8 ;
- xend = xstart + 120 ;
- yend = ystart + 128 ;
- //处理背景图像素颜色
- for ( y = ystart ; y < yend ; y++)
- {
- for (x = xstart ; x < xend ; x++)
- {
- rgb_b = y * bm1.bmWidthBytes + x * PxBytes ;
- px1[rgb_b] = px1[rgb_b] * 0.7;
- px1[rgb_b + 1] = px1[rgb_b + 1] * 0.7;
- px1[rgb_b + 2] = px1[rgb_b + 2] * 0.7;
- }
- }
- //处理前景图颜色
- for ( y = 0 ; y < (bm2.bmHeight) ; y++)
- {
- for (x = 0 ; x < bm2.bmWidth ; x++)
- {
- rgb_b = y * bm2.bmWidthBytes + x * PxBytes ;
- i = (ystart + y )* bm1.bmWidthBytes + (xstart + x )*PxBytes;
- px2[rgb_b] = px2[rgb_b] * 0.3 + px1[i];
- px2[rgb_b + 1] = px2[rgb_b + 1] * 0.3 + px1[i+1];
- px2[rgb_b + 2] = px2[rgb_b + 2] * 0.3 + px1[i+2];
- }
- }
- SetBitmapBits(dra , bm2.bmHeight * bm2.bmWidthBytes , px2);
- MyPaint(hdc);
- ReleaseDC(hWnd ,hdc);
- delete [] px1;
- delete [] px2;
- return TRUE;
- }
3、自定义绘图函数
- void MyPaint(HDC hdc)
- {
- SelectObject(mdc , bg);
- BitBlt(hdc , 0 , 0 , 650 ,360 , mdc , 0 ,0 ,SRCCOPY );
- SelectObject(mdc , dra);
- BitBlt(hdc , xstart , ystart , 120 , 128 , mdc , 0 , 0 , SRCCOPY);
- }
程序运行效果图
写到这里这篇博客也算完工了,第一次写,很多地方做的不够好,希望各位路过的看客多给我提意见。
end!
【Visual C++】游戏编程学习笔记之一:五毛钱特效之透明和半透明处理的更多相关文章
- 【Visual C++】游戏编程学习笔记之四:透明动画实现
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
- 【Visual C++】游戏编程学习笔记之七:键盘输入消息
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
- 【Visual C++】游戏编程学习笔记之六:多背景循环动画
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44264153 作者:ZeeCod ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- DirectX 11游戏编程学习笔记之6: 第5章The Rendering Pipeline(渲染管线)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- 【Visual C++】游戏编程学习笔记之五:单一背景滚动
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之三:游戏循环的使用
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44208419 作者:Zee ...
- 【Visual C++】游戏编程学习笔记之九:回合制游戏demo(剑侠客VS巡游天神)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.com ...
随机推荐
- activiti节点跳转
分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业 ...
- 2.cocos2dx 3.2中语法的不同之处,lambada表达式的使用和function和bind函数的使用
1 打开建好的T32 Cocos2dx-3.2的一个项目 2 设置Cocos显示窗口的位置是在AppDelegate.cpp中: 3 设置自适应窗口大小的代码是在上面的 ...
- 13常用sql语句
创建语句 CREATE table if not exists b(id INTEGER PRIMARY KEY AUTOINCREMENT,waijian int ,FOREIGN KEY (wai ...
- iOS下JS与OC互相调用(二)--WKWebView 拦截URL
在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互. 由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView. 同样的用WKWebVie ...
- C++对象模型的那些事儿之一:对象模型(上)
前言 很早以前就听人推荐了<深入理解C++对象模型>这本书,从年初买来到现在也只是偶尔翻了翻,总觉得晦涩难懂,放在实验室上吃灰吃了好久.近期由于找工作对C++的知识做了一个全面系统的学习, ...
- android EventBus 3.0使用指南
Enventbus的作用和好处我就不多说了,这里介绍下怎么使用. 2.+版本的使用方法 public void onEvent(MessageEvent event) { log(event.mess ...
- MySQL聚簇索引的使用介绍
MySQL聚簇索引保证关键字的值相近的元组存储的物理位置也相同(所以字符串类型不宜建立聚簇索引,特别是随机字符串,会使得系统进行大量的移动操作),且一个表只能有一个聚簇索引.因为由存储引擎实现索引,所 ...
- UNIX网络编程——客户/服务器程序设计示范(四)
TCP预先派生子进程服务器程序,accept使用线程上锁保护 我们使用线程上锁保护accept,因为这种方法不仅适用于同一进程内各线程之间的上锁,而且适用于不同进程之间的上锁. ...
- 【OpenGL】理解一些基本问题
写在前面 啦啦啦,搞了很久的Unity Shaders,越学越觉得基础知识很重要.学Unity Shader的时候,总会想,shader到底是什么呢?shader的pipeline是什么呢?它们是怎么 ...
- 通过邮件找回密码功能的Java实现
1.有个需求就是,忘记密码后通过邮箱找回.现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回.通过java发送邮件的功能我就不说了,重点讲找回密码. 2.参考别人 ...