C++工具箱(三)——动画类之基类
来源:互联网 发布:淘宝店铺招牌图片素材 编辑:程序博客网 时间:2024/06/05 20:22
OK,我们已经讨论了单件和定时器了,该来点真格的了。这次我们来看看如何通过前面所述的定时器实现动画。我目前想到的动画有大小更改、Alpha 透明度更改、窗口位置更改等几种,后续会逐步加上。
我们先来思考动画的实质。动画其实就是通过定时器,一步步逼近一个期望结果的过程。我们期望的动画类是这样的:
1、接口简单、使用方便;
2、可扩展。比如我们后续加上新的动画类时不必太费力;
3、添加新动画类时不必操心动画共有的部分;(如计时器、回调等等)
一个动画有以下共有性质:
1、两次动画间的时间间隔(ms 为单位);
2、动画是否已经开启了;
3、整个动画展示完成后的回调(可选);
4、动画对象的管理。
第四个尤为重要,因为我们可能在一个如何一个函数(全局函数、类成员方法、某一个线程处理函数)中启用一个动画,如果还需手动管理动画对象的生命周期的话,那就太不Fashion了!(你可以思考下如果让你来设计,你会怎么设计这个动画的基类)
好的,我们来看我设计的动画基类,如果你有更好的点子,可以找我沟通。你可能需要定时器、Boost相关的知识。如下:
/** * \file frameanimation.h * \authorarnozhang * \date2012.9.13 * \brief窗口动画基类. */#ifndef__FRAME_ANIMATION_BASE_H__#define__FRAME_ANIMATION_BASE_H__#include "wnd.h"#include "timer.h"namespace Util{template <typename _Co_Animation> class CFrameAnimation{public: // 动画完成回调. typedef _Co_Animation this_class; typedef boost::function<void(void)> AnimationFinishCallback; // 获取一个动画对象. static _Co_Animation& GetAnimation(CWnd* targetFrame) { return *(new _Co_Animation(targetFrame)); } // 启动动画. void StartAnimation() { if (m_bAnimationStarted || !m_targetFrame) { return ; } m_bAnimationStarted = TRUE; if (_PrepareAnimation()) { Util::SetTimerCallback( m_targetFrame, m_dwTimeInterval, TIMER_CALL_BIND(this_class, AnimationHandler_Bind_Proc) ); } } // 设置动画时间间隔. void SetTimeInterval( DWORD dwTimeInteval = DEFAULT_ANIMATION_TIME_INTERVAL ) { m_dwTimeInterval = dwTimeInteval; }// 设置动画帧数.void SetFrameCount(DWORD dwFrameCnt){m_dwFrameCount = dwFrameCnt;} // 设置整个动画完成后的回调. void SetFinishedCallback(const AnimationFinishCallback& finishedCbk) { delete m_pFinishedCallback; m_pFinishedCallback = new AnimationFinishCallback(finishedCbk); }private: // 动画处理器. void AnimationHandler_Bind_Proc() { _AnimationHandler(); }protected: virtual bool _PrepareAnimation() = 0; virtual void _AnimationHandler() = 0; // 动画执行完毕. void _AnimationFinished() { // 清除计时器. Util::KillTimerCallback(m_targetFrame); // 调用完成回调. if (m_pFinishedCallback) { (*m_pFinishedCallback)(); } // 删除动画对象. delete this; } CFrameAnimation(CWnd* targetFrame) { m_targetFrame = targetFrame; m_dwTimeInterval = DEFAULT_ANIMATION_TIME_INTERVAL; m_dwFrameCount= 0; m_bAnimationStarted = FALSE; m_pFinishedCallback = 0; } virtual ~CFrameAnimation() { delete m_pFinishedCallback; } CWnd*m_targetFrame; DWORDm_dwFrameCount;private: AnimationFinishCallback* m_pFinishedCallback; DWORD m_dwTimeInterval; BOOL m_bAnimationStarted; static const int DEFAULT_ANIMATION_TIME_INTERVAL = 30;};#define BIND_ANIMATION_FINISHED_PROC(class_name, method_name) \ boost::bind(&class_name::method_name, this)} /*namespace Util ends here.*/#endif /*__FRAME_ANIMATION_BASE_H__*/
我们定义了一个抽象模版基类 CFrameAnimation。其中模版参数 _Co_Animation是实现动画类的具体类(如CFrameBlendAnimation、CFrameSizeAnimation等)。如果我们要实现新的动画类,只需继承该类就行了,并且重写_PrepareAnimation和_AnimationHandler这两个虚方法即可。其中_PrepareAnimation为开启动画前的初始化及准备工作——因为不同的动画类有不同的属性和初始化方法;_AnimationHandler正如其名,是动画处理过程,因为不同的动画类对应的动画处理也不尽相同。这两个方法都是模版方法。
我们将 CFrameAnimation的构造和析构均设为protected属性(CFrameAnimation的子类亦如此),让它们只能通过静态方法GetAnimation得到一个动画对象,让动画对象只能在堆上构造,然后在动画完成后通过delete this; 这句来释放掉——完全保证了动画对象生命周期的独立管理,不需要用户操一点心思。
我们定义了一个 _AnimationFinished方法,每个新的动画类在_AnimationHandler中完成所有动画的处理后,必须调用该函数删除定时器、释放资源。考虑 DEFAULT_ANIMATION_TIME_INTERVAL 为什么为30?因为人眼中,当动画、游戏等帧数为每秒30帧左右的时候,看起来是连贯的。所以这个值为 1000ms / 30 帧,大约等于30。所以,动画对象的 SetTimerInterval 方法一般不需要调用,我们一般通过SetFrameCount 方法来控制动画的播放帧数。
比如我们实现了一个CFrameBlendAnimation来完成窗口的透明度渐变,那么使用方法也很简单:
#include "frameblendanimation"void animationFinished(){cout<<"hello! Animation Finished!"<<endl;}void foo(){CWnd wnd;wnd.Create();// ...CFrameBlendAnimation& animation = CFrameBlendAnimation::GetAnimation(&wnd);animation.SetStartAlpha(255);animation.SetEndAlpha(0);// 设置播放帧数.animation.SetFrameCount(10);// 完成回调可要可不要,根据需求来.animation.SetFinishedCallback(animationFinished);// 启动动画.animation.StartAnimation();}
可以看出,我们只需通过 GetAnimation 方法获取一个动画对象,然后做相应的设置,最后调用StartAnimation启动动画就行了,完全不用我们操心。解耦的好处在这里得到了充分体现。
下一章将实现一个实现上述窗口透明度渐变的动画类 CFrameBlendAnimation。将会有一份实现好的源代码示例可供下载。大家也可趁机想想如何实现这样一个CFrameBlendAnimation类。
- C++工具箱(三)——动画类之基类
- C++工具箱(四)——动画类之透明度渐变 & 大小渐变
- Android 动画之三 Property Animation—— 属性(Property)动画 【Animator提供基类】
- C++工具箱(一)——单件模版类
- DirectX游戏编程入门——第二部分(游戏编程工具箱) ——精灵编程之动画的精灵
- 【Visual C++】游戏开发笔记之十 基础动画显示(三) 透明动画的实现
- 【Visual C++】游戏开发笔记之十 基础动画显示(三) 透明动画的实现
- 【Visual C++】游戏开发笔记之十 基础动画显示(三) 透明动画的实现
- 【Visual C++】游戏开发笔记之十 基础动画显示(三) 透明动画的实现
- 【Visual C++】游戏开发笔记之十 基础动画显示(三) 透明动画的实现
- Android动画之帧动画(三)
- Java工具箱之配置文件加载类
- Java工具箱之字符编码工具类
- 数据仓库工具箱——维度建模(Dimensional Modeling)摘要(三)
- Android 三类动画
- MATLAB学习笔记06——无约束一维极值问题(三)优化工具箱及工具箱函数fminbnd的改进
- Android动画学习笔记(三)—基础动画小结
- 自定义控件三部曲之动画篇(三)—— 代码生成alpha、scale、translate、rotate、set及插值器动画
- 好资料
- 高斯消元+枚举自由变量
- Linux进程间通信分类 以及 pipe的原理实现
- js 级联菜单
- DOM(DHTML)
- C++工具箱(三)——动画类之基类
- opencv 保存灰度图像的像素值
- ANR相关处理
- 在路上
- 《C++ Primer》十章练习题单词转换word_transform.cpp
- hdu 1395
- java笔记-io字符流
- 第二周JAVA上机实验(一)输出26个希腊字母
- Wikimedia server setup on cent os 5