Qt动画框架的学习

Qt动画框架的学习


近一年,学习游戏开发遇到了瓶颈,主要是因为游戏中有很多复杂的状态要维护,以前使用的switch–if方法现在看来已经穷途末路了,因此,我开始学习游戏开发更加高级的内容。我觉得还是学习游戏人工智能部分是最迫切的。其实游戏的人工智能不仅仅是人工智能,还包含了游戏的架构方面的知识,尤其是当你面对一个非常复杂的系统时,该如何应对。

Qt作为一个优秀的跨平台开源框架,已经有了相关的研究成果。Qt4.6开始就引进了动画框架和状态机框架。这段时间觉得不得不学习Qt的动画框架了,因此写下这篇日志,希望能够帮得上对渴望学习游戏动画方面但是困惑的同学。(原创博客,原文地址:http://blog.csdn.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_H
Widget类定义了一个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如何将状态机框架和动画框架结合起来制作出一个简单的有限状态机动画。


“请帮助我“这个按钮并不自主地移动,它从按下它,将从左上角移动到右下角,在右下角的时候,再按下它,将重新地移动到左上角,耗时2秒。它只是在前一个程序的基础上添加了少部分功能。下面是类Widget的头文件。
#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和原来的一致,就不赘述了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值