Qt动画框架的学习
近一年,学习游戏开发遇到了瓶颈,主要是因为游戏中有很多复杂的状态要维护,以前使用的switch–if方法现在看来已经穷途末路了,因此,我开始学习游戏开发更加高级的内容。我觉得还是学习游戏人工智能部分是最迫切的。其实游戏的人工智能不仅仅是人工智能,还包含了游戏的架构方面的知识,尤其是当你面对一个非常复杂的系统时,该如何应对。
Qt作为一个优秀的跨平台开源框架,已经有了相关的研究成果。Qt4.6开始就引进了动画框架和状态机框架。这段时间觉得不得不学习Qt的动画框架了,因此写下这篇日志,希望能够帮得上对渴望学习游戏动画方面但是困惑的同学。(原创博客,原文地址:http://blog.youkuaiyun.com/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_H
- #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
- #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( );
- }
FROM: http://blog.youkuaiyun.com/gamesdev/article/details/8680816