Qt作为一个优秀的跨平台开源框架,已经有了相关的研究成果。Qt4.6开始就引进了动画框架和状态机框架。这段时间觉得不得不学习Qt的动画框架了,因此写下这篇日志,希望能够帮得上对渴望学习游戏动画方面但是困惑的同学。(原创博客,原文地址:http://blog.csdn.net/jiangcaiyang123/article/details/8680816)
源代码下载地址:这里
最为入门,我想制作一个可以动的按钮。下面是这个程序的截图:
名为”请帮助我”的按钮将从窗口的左上角移动到右下角,耗时5秒。下面是这个程序源代码:
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
class Widget: public QWidget
{
Q_OBJECT
public:
explicit Widget( void );
private:
QPushButton* m_pButton;
};
#endif // WIDGET_H
Widget类定义了一个QPushButton对象的指针,用来显示一个按钮。下面是实现文件:
#include
#include "Widget.h"
/*---------------------------------------------------------------------------*/
Widget::Widget( void ): QWidget( 0 )
{
// 初始化类的成员
resize( 640, 360 );
setWindowTitle( tr( "Qt_EasyAnimation" ) );
m_pButton = new QPushButton( tr( "Please Help" ), this );
// 设置动画
QPropertyAnimation* pAnimation =
new QPropertyAnimation( m_pButton, "geometry" );
pAnimation->setDuration( 5000 );
int textWidth = fontMetrics( ).width( m_pButton->text( ) );
int textHeight = fontMetrics( ).height( );
pAnimation->setStartValue( QRect( 0, 0, textWidth, textHeight ) );
pAnimation->setEndValue( QRect( width( ) - textWidth,
height( ) - textHeight,
textWidth, textHeight ) );
pAnimation->start( );
}
#include
#include
#include "Widget.h"
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QTranslator trans;
trans.load( ":/zh_CN.qm" );
app.installTranslator( &trans );
Widget w;
w.show( );
return app.exec( );
}
下面我来展示一下Qt如何将状态机框架和动画框架结合起来制作出一个简单的有限状态机动画。
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
class Widget: public QWidget
{
Q_OBJECT
public:
explicit Widget( void );
private:
QStateMachine* m_pMachine;
QPushButton* m_pButton;
};
#endif // WIDGET_H
在第一个例子的基础上,添加了QStateMachine类,用来表示一个有限状态机。下面是Widget.cpp的代码:
#include
#include
#include "Widget.h"
/*---------------------------------------------------------------------------*/
Widget::Widget( void ): QWidget( 0 )
{
// 设置窗口的成员
resize( 640, 360 );
setWindowTitle( tr( "Qt_EasyAnimation2" ) );
m_pButton = new QPushButton( tr( "Please Help" ), this );
int textWidth = fontMetrics( ).width( m_pButton->text( ) );
int textHeight = fontMetrics( ).height( );
// 设置动画和有限状态机
m_pMachine = new QStateMachine( this );
QState* pState1 = new QState( m_pMachine );
QState* pState2 = new QState( m_pMachine );
pState1->assignProperty( m_pButton, "geometry",
QRect( 0, 0, textWidth, textHeight ) );
pState2->assignProperty( m_pButton, "geometry",
QRect( width( ) - textWidth,
height( ) - textHeight,
textWidth, textHeight ) );
QSignalTransition* transition1 = pState1->addTransition(
m_pButton, SIGNAL( clicked( ) ), pState2 );
QSignalTransition* transition2 = pState2->addTransition(
m_pButton, SIGNAL( clicked( ) ), pState1 );
QPropertyAnimation* pAnimation =
new QPropertyAnimation( m_pButton, "geometry" );
pAnimation->setDuration( 2000 );
transition1->addAnimation( pAnimation );
transition2->addAnimation( pAnimation );
m_pMachine->setInitialState( pState1 );// 设置初始的状态
m_pMachine->start( );
}
这一段代码首先创建状态机,然后在逐个地创建状态,这样可以保证传入的状态机指针是一个有效的指针。通过QState::assignProperty()函数来指定对哪种Qt类的那一个属性进行动画化。随后通过创建一个QSignalTransition来设置从state1到state2的动画转换。这里要保证QPropertyAnimation所指定的属性和QState::assignProperty()中的一致。最后设置一下初始的状态和启动有限状态机就行了。main.cpp和原来的一致,就不赘述了。