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

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

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

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

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

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

一、为了对比效果差异,我们先就用之前讲过的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. Java基础之编程语法(二)

    1.常量: 整型:整数,4个字节. 长整型:整数,8个字节.以L结尾. 单精度浮点数:小数,4个字节.以F结尾. 双精度浮点数:小数,8个字节. 布尔:只有两个值,真(true)或假(false),1 ...

  2. Python:爬取乌云厂商列表,使用BeautifulSoup解析

    在SSS论坛看到有人写的Python爬取乌云厂商,想练一下手,就照着重新写了一遍 原帖:http://bbs.sssie.com/thread-965-1-1.html #coding:utf- im ...

  3. NSNumber与NSInteger的区别

    Objective-C 支持的类型有两种:基本类型 和  类. 基本类型,如同C 语言中的 int 类型一样,拿来就可以直接用. 而类在使用时,必须先创建一个对象,再为对象分配空间,接着做初始化和赋值 ...

  4. Eclipse中DTD验证导致无法进行代码提示的问题(转)

    eclipse的xml插件进行dtd验证的时候由于找不到dtd或请求主机相应超时,会出现黄色的警告 The file cannot be validated as the host "www ...

  5. 405 HTTP method GET is not supported by this URL

    孙鑫java web开发详解P285里面提交Get网站弹出提示405 HTTP method GET is not supported by this URL 原因父类doGet()方法未覆盖. 应写 ...

  6. Code one 码

    Code one是一种用成像设备识别的矩阵式二维条码.Code one符号中包含可由快速性线性探测器识别的识别图案.每一模块的宽和高的尺寸为X.  Code one符号共有10种版本及时14种尺寸.最 ...

  7. android linearlayout 把控件view置底部(放在页面最下方)

    <LinearLayout android:id="@+id/recLayout" android:layout_width="fill_parent" ...

  8. python Unable to find vcvarsall.bat 错误

    今天遇到了这个方面的问题,目前找到两种办法.一种是换编译器如mingw,另一种是装vc.第一种方法没成功,现在正在等第二种. 第一种: 首先安装MinGW: 把MinGW的路径添加到环境变量path中 ...

  9. MySQL server has gone away 解决方法

    应用程序(比如PHP)长时间的执行批量的MYSQL语句.执行一个SQL,但SQL语句过大或者语句中含有BLOB或者longblob字段.比如,图片数据的处理.都容易引起MySQL server has ...

  10. linux内核源码阅读之facebook硬盘加速flashcache之三

    上一节讲到在刷缓存的时候会调用new_kcahed_job创建kcached_job,由此我们也可以看到cache数据块与磁盘数据的对应关系.上一篇:http://blog.csdn.net/lium ...