一、半透明效果

半透明效果在游戏世界里是用的很频繁的,比如鬼魂,隐形人物。

简单的说,半透明是前景图案和背景图案像素颜色的混合。可以简单的把半透明处理,整理为一个公式:

半透明图色彩 = 前景图色彩× 不透明度 + 背景图色彩 × (1 -不透明度)


半透明处理的步骤:

1.      获取位图结构。
GetObject()获取位图的结构后,可得到位图信息。

2.      建立暂存数组
获得了位图结构后,接下来需要先建立一个暂时存储位图像素的颜色值。这个暂存数组的大小有前一步获得位图信息的bmHeight, bmWidthBytes决定。

这里有必要提一下BITMAP结构,因为在之后将会用到。

typedef struct tagBITMAP {LONG   bmType; //位图类型LONG   bmWidth; //位图宽度LONG   bmHeight; //长度LONG   bmWidthBytes; //每一列像素所占Byte数WORD   bmPlanes; //颜色平面数WORD   bmBitsPixel; //像素位数LPVOID bmBits; //位图内存指针
} BITMAP, *PBITMAP;

3.      取得位图位值。
建立数组后,可以用GetBitmapBits()来获得位图位值。

4.      合成像素颜色值
获得位图的所有像素颜色值后,按照公式完成半透明颜色值的合成。

5.      重设位图颜色。
根据数组的内容来重新设位图的颜色。使用SetBitmapBits() 。

完成后,最后就是贴图了。

范例:

首先创建win32项目。让系统生成基本框架代码。

在程序开始处添加全局变量。

HBITMAP bg, girl;
HDC mdc;
//常量
const int xstart= 50;
const int ystart= 20;

然后在InitInstance()函数中添加代码

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;HDC hdc;hInst = hInstance; // 将实例句柄存储在全局变量中hWnd = CreateWindow(szWindowClass, szTitle, 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);mdc = CreateCompatibleDC(hdc);BITMAP bm1, bm2;unsigned char *px1,*px2;//用于存储位图额色彩值//处理背景bg = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 600, 450, LR_LOADFROMFILE);GetObject(bg, sizeof(BITMAP), &bm1);//将bg的位图信息获取到bm1px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];//动态定义数组,大小有获取位图决定GetBitmapBits(bg, bm1.bmHeight * bm1.bmWidthBytes, px1);//获得位图位值到px1girl = (HBITMAP)LoadImage(NULL, L"girl.bmp", IMAGE_BITMAP, 298, 329, LR_LOADFROMFILE);GetObject(girl, sizeof(BITMAP), &bm2);//将girl的位图信息获取到bm2px2 = new unsigned char [bm2.bmHeight * bm2.bmWidthBytes];GetBitmapBits(girl, bm2.bmHeight * bm2.bmWidthBytes, px2);int xend, yend;int x, y, i;int rgb_b;int PxBytes = bm1.bmBitsPixel / 8;xend = xstart + 298;//位图的大小为:*329yend = ystart + 329;//处理背景像素颜色//从(xstart,ystart)开始遍历半透明化位置的每个像素点for (y = ystart; y < yend; y++) {for (x = xstart; x < xend; x++) {//rgb_b用于找到位图在px1中的位置(px1为一维数组)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;}}//处理前景图像像素颜色//由于前景是从girl位图的(0,0)开始的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(girl, bm2.bmWidthBytes * bm2.bmHeight, px2);MyPaint(hdc);ReleaseDC(hWnd, hdc);delete [] px1;delete [] px2;return TRUE;
}void MyPaint(HDC hdc)
{SelectObject(mdc, bg);BitBlt(hdc, 0, 0, 600, 450, mdc, 0, 0, SRCCOPY);SelectObject(mdc, girl);BitBlt(hdc, xstart, ystart, 298, 329, mdc, 0, 0, SRCCOPY);
}

最后在WndProc函数的WM_PAINT消息中添加MyPaint()函数

二、透明半透明效果

看到上面例子中效果还不太好,因为前景图还可以看到原来位图矩形边框。这里我们要把它做得更好。这里使用一个内存DC和位图对象,在DC中先完成透明效果,再来取出DC内存位图进行半透明处理。这样就达到了目的。

这个范例中的前景图必须要有如下图所示:

下面的编码和上面类似。

添加全局变量

HBITMAP bg, girl;
HDC mdc;
const int xstart = 50;
const int ystart = 20;

在InitInstance()函数中,添加代码:

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;HDC hdc, bufdc;HBITMAP bmp;BITMAP bm1, bm2;hInst = hInstance; // 将实例句柄存储在全局变量中hWnd = CreateWindow(szWindowClass, szTitle, 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);bg = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 600, 450, LR_LOADFROMFILE);bmp = (HBITMAP)LoadImage(NULL, L"girlmask.bmp", IMAGE_BITMAP, 596, 329, LR_LOADFROMFILE);GetObject(bg, sizeof(BITMAP), &bm1);hdc = GetDC(hWnd);mdc = CreateCompatibleDC(hdc);bufdc = CreateCompatibleDC(hdc);girl = CreateCompatibleBitmap(hdc, 298, 329);SelectObject(mdc, girl);//前景图和背景图透明处理,保存在mdcSelectObject(bufdc, bg);BitBlt(mdc, 0, 0, 298, 329, bufdc, xstart, ystart, SRCCOPY);SelectObject(bufdc, bmp);BitBlt(mdc, 0, 0, 298, 329, bufdc, 298, 0, SRCAND);BitBlt(mdc, 0, 0, 298, 329, bufdc, 0, 0, SRCPAINT);//开始半透明处理unsigned char *px1,*px2;//处理背景图px1 = new unsigned char [bm1.bmHeight * bm1.bmWidthBytes];GetBitmapBits(bg, bm1.bmHeight * bm1.bmWidthBytes, px1);//处理前景图GetObject(girl, sizeof(BITMAP), &bm2);px2 = new unsigned char [bm2.bmHeight * bm2.bmWidthBytes];GetBitmapBits(girl, bm2.bmHeight * bm2.bmWidthBytes, px2);int x, y, xend, yend;int i;int rgb_b;int PxBytes = bm1.bmBitsPixel / 8;xend = xstart + 298;yend = ystart + 329;//处理背景图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(girl,bm2.bmHeight*bm2.bmWidthBytes,px2);MyPaint(hdc);//贴图ReleaseDC(hWnd, hdc);DeleteDC(bufdc);DeleteObject(bmp);delete [] px1;delete [] px2;return TRUE;
}
void MyPaint(HDC hdc)
{//将背景图和处理后的透明半透明图贴入SelectObject(mdc, bg);BitBlt(hdc, 0, 0, 600, 450, mdc, 0, 0, SRCCOPY);SelectObject(mdc, girl);BitBlt(hdc, xstart, ystart, 298, 329, mdc, 0, 0, SRCCOPY);
}

最后把MyPaint()函数写入消息循环中的WM_PAINT消息中:

case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: 在此添加任意绘图代码...MyPaint(hdc);EndPaint(hWnd, &ps);break;

这样,我们的程序就写好了。运行程序。

VC++游戏编程----游戏画面特效制作2相关推荐

  1. 【Unity Shaders】游戏性和画面特效——创建一个老电影式的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 【Unity Shaders】游戏性和画面特效——创建一个夜视效果的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  3. VC++游戏编程----游戏画面特效制作1

    透明效果 有时候,我们需要在画面上显示一张角色的图像,而这张图片是有自己的背景的,要是直接贴到了游戏的画面中,就会出项覆盖游戏画面.显示出的效果特别不好,这里我们可以用到透明效果来处理. 其中,原理就 ...

  4. 小人物走路、奔跑的VC++游戏特效,适合刚学习VC++游戏编程的朋友

    一个VC++游戏中的模块效果,小人物走路.奔跑效果,用方向键即可在控制小人的走动,当然了,源码还是比较基础的,适合于刚学习VC++游戏编程的朋友们. 界面效果展示: 源码目录结构图: 部分源码展示(由 ...

  5. 虚幻引擎5(UE5)实时VFX游戏特效制作入门到精通

    UE5 Niagara学习教程  课程获取:虚幻引擎5(UE5)实时VFX游戏特效制作入门到精通-云桥网 你会学到什么 我将通过创建各种各样的实时效果来教你虚幻引擎中强大的粒子系统. 我们将从简单的基 ...

  6. Unity3d 游戏特效制作实战教程 第二部

    本套教程是由多年特效制作经验的作者录制,通过多个案例, 演示了xffect粒子系统与unitu3d粒子系统的特效制作的全部流程 包含xffect基础教程,并附送全部项目文件打包和素材. 本教学适合于U ...

  7. VC++游戏编程基础无法找到“d3d9.h”问题

    经反复查阅是缺少Direct X SDK导致的,我用的是VC++6.0,支持Direct X SDK 9.0b及之前的版本,最新版DX SDK(JUNE)VC6驾驭不了...下面是我解决问题的思路(只 ...

  8. 最新cocos2d-x 3.0博客教学 小游戏[史上最坑爹的游戏] 001主画面以及关卡选择画面的制作

    cocs2d的开发环境我相信大家都能搭建好了,下面我们直接的进入正题,开始做我们的小游戏,如果对搭建环境还有不懂的童鞋请看我写的这篇博文 cocos2d-x 3.0游戏开发xcode5帅印博客教学 0 ...

  9. 游戏编程入门(7):使用子画面动画移动对象

    在几乎所有游戏中,图形的核心都是动画.如果没有动画,那么就没有移动.如果没有移动,那么我们就只能玩棋类游戏和纸牌类游戏. 本文介绍了与游戏中的动画有关的概念,并介绍如何设计和开发一个通用的子画面类,允 ...

最新文章

  1. POJ-1041 John's trip
  2. oracle中 关于触发器,oracle 闪回关于触发器的bug
  3. QT调用C#写的Dll
  4. Boost Asio总结(2)同步通信
  5. c语言股票最大收益_金斧子股票配资:股票配资的时候有哪些事项需要注意呢...
  6. windows下使用git管理github项目
  7. mongodb副本集架构搭建
  8. 如何搭建一个打印荣誉证书的网站_如何搭建一个免费的作品集网站
  9. python2和python3如何共存,如何安装多版本python python2和python3共存以及pip共存
  10. Spring的REST分页
  11. 阿里云AHAS Chaos:应用及业务高可用提升工具平台之故障演练
  12. hashmap扩容线程安全问题_HashMap在1.7 1.8中的线程安全问题
  13. python correlation_python scipy stats.random_correlation用法及代码示例
  14. OpenCV-图像NaN处理
  15. vim YouCompleteMe
  16. hive 下载和导入数据 hive -e
  17. Sentaurus Process Device
  18. 顶级期刊Nature、Science,如何一较高下?
  19. Windows运行及cmd常用命令
  20. mysql聚簇索引abc_索引优化_MySQL开发教程_IT技术个人博客

热门文章

  1. 如何搭建一个网站 -- 搭建一个网站需要多少钱
  2. iPhone Plus手机的分辨率到底是多少,是1080×1920还是1242×2208?
  3. JWT快速上手 | 黑马
  4. C/C++语言ODBC连接SqlServer数据库
  5. 2021届硕士生年初java春招实习面试和正式校招面试经验汇总(收割腾讯,百度,美团,网易等offer)
  6. 清华大学百年校庆给清华大学的一封信
  7. 纪念Dropbox君
  8. 实战智能推荐系统(1)-- 个性化推荐系统及其基本推荐算法
  9. PMP考试资料考试重点,不看可惜了
  10. [转...转] 国内软件破解下载网站列表!