Welcome

首页 / 软件开发 / VC.NET / C++游戏开发笔记十一 平滑动画:不再颤抖的小雪花

C++游戏开发笔记十一 平滑动画:不再颤抖的小雪花2014-11-04在上一节雾央讲解了一下平面的障碍物判定,本来打算讲解一下斜坡的障碍物判定,但是有朋友推荐了一片文章,对障碍物判定讲解的非常好,雾央就直接把地址贴出来,就不重复了。2D游戏中的障碍判定

这篇文章讲解了2D游戏的很多东西,大家可以好好看看,雾央也很希望研究游戏开发的朋友们可以推荐下好文章,一起进步,在此谢过。

另外,从本节笔记开始,雾央决定把系列名称改为《C++编程》,具体原因请移步笔记一。

在之前雾央讲解了背景滚动,不知道大家发现了没有,在人物移动的时候,画面是一卡一卡的,原因是由于大家按下方向键移动后,人物突然移动一段距离,而背景也跟随着移动一段距离,突然变化的画面给大家带来的就是一种卡的感觉。在之后的粒子系统中有同学提到颤抖的小雪花同样是这样,在每次绘制的时候,都让雪花增加了一段确定的位移,但是由于计算机状态的不断变化,每两帧之间的时间差不同,所以雪花的移动也就不规律。有颤抖的感觉。

由上面的讨论,大家应该能知道,在游戏中,通过增加确定的位移来改变某个事物的位置往往是不准确的,也会导致画面不流畅。但是思考这种抖动产生的原因,我们可以受到很多启发,我们是不是可以减少每次移动的距离,而增加移动的频率来达到同样的位置呢?这样就可以大大降低画面的违和感,而最高的频率也就是和画面绘制的频率一致了,因此我们可以在每次绘制画面的时候进行较小幅度的更新,而为了摆脱两次绘制之间的时间差的波动,我们需要计算时间差,更新幅度和时间差关联起来。

最直接的实现方式当然就是通过时间和速度来达到上述效果了。

比如对于人物,我们给予他x和y方向上的速度,通过时间乘以速度来更新他的位置。玩家的操作会改变人物的方向和速度。粒子系统亦然。

大家知道了原理之后,在实现之前,我们首先要解决几个问题

首先是获取两帧之间的时间差。这个要求我们记录下上次绘制的时间,在每次绘制时候获取当前时间,两者之间差值即为所求。大家可以使用全局变量来记录上次绘制的时间,在这里雾央使用的是静态变量。

static float lastTime=timeGetTime(); static float currentTime=timeGetTime();currentTime=timeGetTime();//状态更新lastTime=currentTime;
这样之后即可以得到平滑的动画了,雾央仍然是以之前的粒子系统中的雪花为例,这样大家就可以和以前的方式进行一下对比,就可以更清楚的看出差别了。

另外,像这样获取帧之间的时间差后,大家就可以计算出FPS了,帧数的计算很简单,就是画面绘制的次数除以绘制花费的时间即可,为了不让帧数不断的跳动,大家可以隔一段时间比如1秒计算一次。

//获取当前FPSfloat CalculateFPS(){static floatfps = 0; //FPS值 static intframeCount = 0;//帧数 static floatcurrentTime =0.0f; static floatlastTime = 0.0f;//每绘制一次,帧数加1frameCount++; currentTime = timeGetTime()/1000.0f; //大家是可以每绘制一次就计算一次帧数,即1/时间即可,这样得到的是实时帧数,//但是由于时间间隔太短,帧数变化太快,显示在窗口上也看不清,所以每隔一段时间计算一次 if(currentTime - lastTime > 1.0f) //将时间控制在1秒钟 {fps = frameCount /(currentTime - lastTime);//计算这1秒钟的FPS值 lastTime = currentTime; frameCount= 0;}return fps;}
在之前的笔记中,涉及到动画都使用了定时器,雾央在初学游戏的时候,代码里是一大堆的定时器,呵呵。但是现在我们就可以不再使用这么多的定时器,如果大家直接使用WIN32,可以完全不使用定时器了,但是用MFC的话,大家需要使用一个定时器驱动OnPaint绘图,剩余的动画大家就可以利用计算时间差来更新了

比如每100毫秒更新一帧的动画

if(currentTime-lastTime>100.0f) 更新下一帧
更多精彩内容:http://www.bianceng.cn/Programming/VC_NET/