今天咋一看,发现很久没写博客了

的确,开学之后,写博客的时间越来越少了……

今天来做一个比较实用的小应用——平滑的人物走动,同时解决常见的闪屏问题、实现透明位图

这些技术在游戏开发中是很常见的

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、为了对比效果差异,我们先就用之前讲过的BitBlt函数来直接贴位图

先来看一看一些主要的代码:

变量说明:

static HBITMAP	hBk, hBmp;			//背景、人物位图句柄
static SIZE sBk, sBmp, sClient; //背景、人物位图大小 , 客户区大小
static POINT ptBmp; //人物位图位置

在WM_CREATE消息中做一些初始化工作:

case WM_CREATE:
{
//加载位图资源
BITMAP bmp;
hBmp = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
hBk = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, MAKEINTRESOURCE(IDB_BITMAP2)); GetObject(hBmp, sizeof(BITMAP), &bmp);
sBmp.cx = bmp.bmWidth;
sBmp.cy = bmp.bmHeight; GetObject(hBk, sizeof(BITMAP), &bmp);
sBk.cx = bmp.bmWidth;
sBk.cy = bmp.bmHeight;
}
//初始化人物位置
ptBmp.x = 100;
ptBmp.y = 100;
return 0;

在WM_SIZE消息中获取客户区大小

case WM_SIZE:
sClient.cx = LOWORD(lParam);
sClient.cy = HIWORD(lParam);
return 0;

在WM_PAINT消息中绘制位图

case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBk); //由于背景图片可能超过客户区大小 , 故采取缩放模式显示背景图片
SetStretchBltMode(hdc, COLORONCOLOR);
StretchBlt(hdc, 0, 0, sClient.cx, sClient.cy,
hdcMem, 0, 0, sBk.cx, sBk.cy, SRCCOPY); //绘制人物位置
SelectObject(hdcMem, hBmp);
BitBlt(hdc, ptBmp.x, ptBmp.y, sBmp.cx, sBmp.cy,
hdcMem, 0, 0, SRCCOPY);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
return 0;

在WM_MOUSEMOVE消息中控制人物位置

//鼠标移动时,这个消息会发送很多,
//因此用它来检验闪屏效果是很理想的
case WM_MOUSEMOVE:
ptBmp.x = LOWORD(lParam);
ptBmp.y = HIWORD(lParam); InvalidateRect(hwnd, NULL, TRUE);
return 0;

下面是BitBlt函数的实现效果:(可以发现人物周边出现了白色区域)

可见这和实际游戏中是有差别的

二、实现位图的透明

实现之前,先来看一看一个win32 sdk中的含api函数TransparentBlt

msdn:

BOOL TransparentBlt(
HDC
hdcDest, // handle to destination DC
int nXOriginDest, // x-coord of destination upper-left corner
int nYOriginDest, // y-coord of destination upper-left corner
int nWidthDest, // width of destination rectangle
int hHeightDest, // height of destination rectangle
HDC hdcSrc, // handle to source DC
int nXOriginSrc, // x-coord of source upper-left corner
int nYOriginSrc, // y-coord of source upper-left corner
int nWidthSrc, // width of source rectangle
int nHeightSrc, // height of source rectangle
UINT crTransparent // color to make transparent
);

前10个参数和BitBlt的差不多,不用多解释。主要是最后一个参数crTransparent,当前位图中需要透明的颜色(一般都是白色或者黑色)

==> 因此,你应该保证非透明区域不能包含透明颜色,否则会有一定的出入

另外还需要注意的一点:Transparent函数只适合低于32位色位图的透明,当然常见的都是RGB原色——24位的,因此它是够用的

只需要将WM_PAINT中的BitBlt换成Transparent就能实现久违的位图透明效果

TransparentBlt(hdc, ptBmp.x, ptBmp.y, sBmp.cx - 10, sBmp.cy - 10,
hdcMem, 0, 1, sBmp.cx, sBmp.cy - 1, RGB(255, 255, 255));

下面就是实现效果:

可以发现,透明效果是实现了,但是闪屏确实很厉害……

三、解决闪屏问题

要解决问题,需要知道问题的根源所在:

各位还记得WNDCLASS这个类型的结构体变量吗?

它在注册窗口前需要初始化,我们来看看初始化代码:

wndclass.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);

对,问题就出现在这里,我们设置了背景刷为白色的刷子,那么当你重绘客户区的时候,程序就会使用你默认设定的这个白色刷子来刷背景,由于鼠标移动消息很频繁,因此就会看到很厉害的闪屏

那么,解决方法就很简单了,主要有两种方式:

(1)将背景刷设定为NULL,空刷子——透明的刷子

wndclass.hbrBackground	= NULL;

(2)不改变背景刷(依然使用白色背景刷子),只是在试窗口无效时,我们选择不重绘背景,具体就是将InvalidateRect的最后一个参数设定为TRUE

case WM_MOUSEMOVE:
ptBmp.x = LOWORD(lParam);
ptBmp.y = HIWORD(lParam); InvalidateRect(hwnd, NULL, FALSE);//这里设为FALSE
return 0;

ok,来看看解决后的效果:

可见频繁的闪屏解决了^_^

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

今天到此为止吧(如果各位需要源代码或者相应资源,可以评论留下邮箱,我会发给你^_^)

<Win32_18>平滑的人物走动 —— 解决闪屏的更多相关文章

  1. C# CreateParams的使用(解决闪屏问题)

    <转载自:https://blog.csdn.net/xpwang/article/details/53427479> 窗体和控件的属性CreateParams(这真的是一个属性)很神奇, ...

  2. winform MDI子窗口闪动问题(本人测试100%有效解决闪屏问题)

    将下面的代码随便放到主窗体的任何一个地方 protected override CreateParams CreateParams //解决MDI闪屏 { get { CreateParams cp ...

  3. 使用fixed制作浮动广告(注意:解决闪屏问题,但适用于高版本浏览器,低版本的浏览器不适用)

    <script language="javascript" type="text/javascript"> //隐藏广告 function clos ...

  4. C#中利用双缓冲技术解决绘图闪屏问题。

    这段时间在做一个小型游戏,在界面显示的时候用到了一些图形.一开始涉及到的图形全都用控件的背景图片代替了.这样游戏运行的时候存在的一个很大的问题是游戏运行很慢.小组成员费尽周折,即将放弃,每一个成员都愁 ...

  5. 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)

    使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...

  6. vue cavnas绘制矩形,并解决由clearRec带来的闪屏问题

    起因:在cavnas绘制矩形时 鼠标移动一直在监测中,所以鼠标移动的轨迹会留下一个个的矩形框, 要想清除矩形框官方给出了ctx.clearRect() 但是这样是把整个画布给清空了,因此需要不断 向画 ...

  7. IOS客户端UIwebview下web页面闪屏问题

    基于ios客户端uiwebview下的web页面,在其内容高度大于视窗高度时,如果点击超过视窗下文档的底部按钮,收缩内容高度,会发生闪屏问题. 外因是由文档的高度大于视窗的高度所致,本质原因未知. 解 ...

  8. MDI窗体简单方法(调用,闪屏)

    调用方式: RibbonForm mdishow = new RibbonForm(); //实例化 midshow.MdiParent = this; //设置在主窗体,以MDI的方式显示,关键属性 ...

  9. MFC框架下Opengl窗口闪屏问题解决方案

    转自https://blog.csdn.net/niusiqiang/article/details/43116153 虽然启用了双缓冲,但是仍然会出闪屏的情况,这是由于OpenGL自己有刷新背景的函 ...

随机推荐

  1. ELF文件数据布局探索(1)

    作为一名Linux小白,第一次看到a.out这个名字,感觉实在是奇怪,搜了一下才知道这是编译器输出的默认可执行文件名 然后vi一下,哇,各种乱码,仔细看看,发现了三个清晰的字符ELF.继续搜索, 第一 ...

  2. Laravel 简单使用七牛云服务

    前言 路漫漫其修远兮,吾将上下而求索.学习 Laravel 之初觉得所有东西都很厉害的样子,现在看来就是很厉害啊!最近在写一个项目上传的模块,要上传图片到七牛云,昨天看了一下午七牛云官方的文档感觉还是 ...

  3. git配合tortoiseGit的基础使用

    转载自:http://www.cnblogs.com/ssor/archive/2012/02/04/2337823.html 一定要自己写出来才能牢记,所以我来写一下 git确实比svn好用的多了, ...

  4. 华为GVRP理解

    类似于CISCO的VTP 在大型的网络中,华为交换机之间的串联是很普遍的.一般交换机互联端口都是配置成Trunk,即允许透传多个VLAN的.对于用户来说,手工配置太麻烦.一个规模比较大的网络可能包含多 ...

  5. 如何配置和使用Tomcat访问日志

    配置位置在log下的server.xml,(tomcat容器) <Engine defaultHost="localhost" name="Catalina&quo ...

  6. 复习知识点:GCD多线程

    GCD的基础 #pragma mark - 使用GCD 创建一个 串行 队列 // 第一种:系统提供的创建串行队列的方法 // 在真正的开发中如果需要创建串行队列,比较习惯用这种 // dispatc ...

  7. 深入浅出 JSTL

    JSLT标签库,是日常开发经常使用的,也是众多标签中性能最好的.这个算是一个java程序员的一个基本功吧. JSP Standard Tag Library (JSTL) 的规范完成于2002年7月, ...

  8. AS3清空数组的四种方法

    第一种最简单的方法是: var arr:Array = ["a", "b", "c", "d", "e&quo ...

  9. applicationContext.xml详解

    http://blog.csdn.net/heng_ji/article/details/7022171

  10. USACO Party Lamps 【Binary code solvution】【规律】

    写这道题目的时候遇到了一个令人诧异的问题,就是平台上跑来的结果和我本机跑起来的结果不一样. 后来Debug了之后才发现是我数组开小了,只开到100 的数组竟然都去访问他170位的地址肯定要跪成翔啊.. ...