Qt动画片框架的学习
Qt动画框架的学习
近一年,学习游戏开发遇到了瓶颈,主要是因为游戏中有很多复杂的状态要维护,以前使用的switch–if方法现在看来已经穷途末路了,因此,我开始学习游戏开发更加高级的内容。我觉得还是学习游戏人工智能部分是最迫切的。其实游戏的人工智能不仅仅是人工智能,还包含了游戏的架构方面的知识,尤其是当你面对一个非常复杂的系统时,该如何应对。
实现文件中使用 QpropertyAnimation类来实现一个属性动画,即通过线性插值(lerp)来对按钮的属性进行设置。注意上面的”geometry”名字是按钮的属性之一,Qt内置类的各种属性可以在Qt Creator的帮助中每一个类的Property中可以看到。随后通过 QpropertyAnimation::setStartValue和QpropertyAnimation:: setEndValue来设置起始和终止状态的值。最后通过QpropertyAnimation::start( )来开始动画。
最后简简单单地完成main.cpp就完工了。
Qt动画框架的学习
近一年,学习游戏开发遇到了瓶颈,主要是因为游戏中有很多复杂的状态要维护,以前使用的switch–if方法现在看来已经穷途末路了,因此,我开始学习游戏开发更加高级的内容。我觉得还是学习游戏人工智能部分是最迫切的。其实游戏的人工智能不仅仅是人工智能,还包含了游戏的架构方面的知识,尤其是当你面对一个非常复杂的系统时,该如何应对。
Qt作为一个优秀的跨平台开源框架,已经有了相关的研究成果。Qt4.6开始就引进了动画框架和状态机框架。这段时间觉得不得不学习Qt的动画框架了,因此写下这篇日志,希望能够帮得上对渴望学习游戏动画方面但是困惑的同学。(原创博客,原文地址:http://blog.****.net/jiangcaiyang123/article/details/8680816)
源代码下载地址:这里
最为入门,我想制作一个可以动的按钮。下面是这个程序的截图:
名为”请帮助我”的按钮将从窗口的左上角移动到右下角,耗时5秒。下面是这个程序源代码:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> class Widget: public QWidget { Q_OBJECT public: explicit Widget( void ); private: QPushButton* m_pButton; }; #endif // WIDGET_HWidget类定义了一个QPushButton对象的指针,用来显示一个按钮。下面是实现文件:
#include <QtGui> #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( ); }
实现文件中使用 QpropertyAnimation类来实现一个属性动画,即通过线性插值(lerp)来对按钮的属性进行设置。注意上面的”geometry”名字是按钮的属性之一,Qt内置类的各种属性可以在Qt Creator的帮助中每一个类的Property中可以看到。随后通过 QpropertyAnimation::setStartValue和QpropertyAnimation:: setEndValue来设置起始和终止状态的值。最后通过QpropertyAnimation::start( )来开始动画。
最后简简单单地完成main.cpp就完工了。
#include <QApplication> #include <QTranslator> #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 <QWidget> #include <QPushButton> #include <QPropertyAnimation> #include <QStateMachine> class Widget: public QWidget { Q_OBJECT public: explicit Widget( void ); private: QStateMachine* m_pMachine; QPushButton* m_pButton; }; #endif // WIDGET_H在第一个例子的基础上,添加了QStateMachine类,用来表示一个有限状态机。下面是Widget.cpp的代码:
#include <QState> #include <QSignalTransition> #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和原来的一致,就不赘述了。
- 1楼jiangcaiyang123昨天 18:56
- 注意,第二个例子的pAnimation在窗口销毁后并没有释放空间。需要手动释放空间或者使用智能指针。