Use the QT animation framework to design a two-dimensional animation for a role

Source: Internet
Author: User

Use the QT animation framework to design a two-dimensional animation for a role

The QT animation framework is an important new feature added to qt4.6. With it, developers can make exciting animation interfaces without having to limit themselves to monotonous fixed windows. It can be said that, qt animation framework is a rare feature in other interface libraries, and it brings a major advantage of QT. Recently, I spent about three or four days studying the content of the QT animation framework. This made me feel that the elaborate design of QT gave us a set of very standard and easy-to-understand code, if another developer also has some knowledge about the QT animation framework, he can easily understand my code and understand the design idea from the code.

Demo program: here

Source code: here

The following is the program's:

Here, I used a well-known primary speaker for demonstration. We can use the [w] [s] [a] [d] key to control its operations. However, this program still has some minor issues and will be improved later.

How to introduce it? First, to understand how role animation works, or to understand the QT state machine framework. Here is an English introduction, and here is an English introduction.

After learning about the QT State framework, I will introduce the simplest two-dimensional animation: Walking animation. In fact, the demo program uses the walking diagram of the first speaker, as shown in:

We use the scenario-view framework (scene-view framework) of QT to draw two-dimensional images, which is very simple. After the success, I thought, how can I make the voice of the first speaker dynamic? After several days of attempts and failures, I drew a finite state diagram.

In this figure, standing and walking are two states in the state machine, and they can be converted to each other. Such a conversion is completed by pressing the response. In QT, there is a class responsible for key response and transition between States: qkeyeventtransition. It obtains key events by binding a qwidget, and starts switching between States once the corresponding key conditions are met. Therefore, you can create a walking animation for a role as follows: first, the role is in the standing state. When it captures the upper and lower right keys, a qkeyeventtransition Object Pointer is responsible for converting it into the walking state. There are two animations attached to the conversion. One is the frame animation of the role, that is, the movement of one frame and one frame of the initial audio. The other is the position animation of the role, which changes the position of the role. It is impossible for us to stay on our own! After the conversion, the role actually enters the walking state. By setting another qiniacttransition pointer, the role quickly returns to the standing state from the walking State, so that it can wait for the next response of the button.

In my implementation, let the character class implement this function. It is a subclass of gameobject, And the gameobject class is the base class of all game objects. Generally, a role (character) basically has a walking function, while other objects belonging to a gameobject do not, such as trees.

The following is the content of character. h:

# Ifndef character_h # define character_h # include <qrect> # include <qkeyeventtransition> # include <qpropertyanimation> # include <qwidget> # include "gameobject. H "/* Subject */class character: Public gameobject {q_object q_property (qrect framerect read framerect write setframerect) Public: explicit character (const qstring & filename, gameobject * parent, qwidget * pwidget = 0); // qgraphicsitem must implement the function qrectf boundingrect (void) const; void paint (qpainter * ppainter, const interval * poption, qwidget * pwidget = 0 ); // The virtual void Init (void) function to be implemented by the subclass; Public slots: void slotsetdirection (void); protected: // enumerate Enum direction // The control key {_ up _ = QT: key_w, _ down _ = QT: key_s, _ left _ = QT: key_a, _ right _ = QT: key_d}; // function void setdirection (int dir) of this class; void setframeanimation (int dir); void setposanimation (int dir ); // members of this class and the read/write function random (qrect, framerect) random (INT, animatetime) qstate * m_pstandstate, * m_pwalkstate; qpropertyanimation * m_ppa; qpropertyanimation * m_pfpa [4]; qwidget * m_pwidget;};/* optional */# endif // character_h

The content of character. cpp is as follows:

# Include <qdebug> # include <qpoint> # include <qpainter> # include <qeasingcurve> # include <qpropertyanimation> # include <qsequentialanimationgroup> # include <qparallelanimationgroup> # include "Character. H "/* character */character: character (const qstring & filename, gameobject * parent, qwidget * pwidget): gameobject (parent) {m_animatetime = 1000; // m_pwidget = pwidget; m_image.load (filename); // load the image m_framerect.setrect (0, 0, m_image.width ()/4, m_image.height ()/4 ); setdirection (_ right _); // orientation to right Init ();}/* Subject */void character: paint (qpainter * ppainter, const qstyleoptiongraphicsitem * poption, qwidget * pwidget) {ppainter-> drawpixmap (qpoint (0,-1 6), m_image, m_framerect); gameobject: paint (ppainter, poption, pwidget);}/* counter */qrectf character: boundingrect (void) const {return qrect (0,-16, 32, 48); // if there are no other special effects, the returned Frame Box}/* blank */void character :: setdirection (int dir) {int recty = 2; Switch (Dir) {Case _ up _: recty = 3; break; Case _ down _: recty = 0; break; Case _ left _: recty = 1; break; Case _ right _: recty = 2; break;} m_framerect = qrect (m_framerect.x (), recty * m_image.height ()/4, m_framerect.width (), m_framerect.height ());} /* --------------------------------------------------------------------------- */static qreal oneeasingfunction (qreal progress) {q_unused (Progress) retu Rn 1.0;}/* role */void character: setframeanimation (int dir) {int recty = 2; Switch (DIR) {Case _ up _: recty = 3; break; case _ down _: recty = 0; break; Case _ left _: recty = 1; break; Case _ right _: recty = 2; break;} qrect rect [4]; qeasingcurve curve (qeasingcurve: custom); curve. setcustomtype (oneeasingfunction); For (int I = 0; I <4; ++ I) {rect [I] = qrect (m_framerect.width () * I, recty * m_image.height ()/4, m_framerect.width (), m_framerect.height () ;}for (INT I = 0; I <4; ++ I) {m_pfpa [I]-> setstartvalue (rect [I]); m_pfpa [I]-> setendvalue (rect [(I + 1) % 4]); m_pfpa [I]-> seteasingcurve (curve ); m_pfpa [I]-> setduration (m_animatetime/4 );}}/*----------------------------------------------------- ---------------------- */Void character: setposanimation (int dir) // set the position animation {qpointf point = pos (), deltapt; Switch (DIR) {Case _ up _: deltapt = qpointf (0.0,-32.0); break; Case _ down _: deltapt = qpointf (0.0, 32.0); break; Case _ left _: deltapt = qpointf (-32.0, 0.0); break; Case _ right _: deltapt = qpointf (32.0, 0.0); break;} m_ppa-> setstartvalue (point); point + = deltapt; m_ppa-> setend Value (point);}/* direction */void character: slotsetdirection (void) {qkeyeventtransition * eventtrans = qobject_cast <qkeyeventtransition *> (sender ()); setdirection (eventtrans-> key (); setframeanimation (eventtrans-> key (); setposanimation (eventtrans-> key ();}/* specify ());}/*-------------------------------------------------------------- ------------- */Void character: Init (void) {// initialize the station and its status m_pstandstate = new qstate (& m_machine); m_pwalkstate = new qstate (& m_machine ); // initialize and set the Frame Animation qsequentialanimationgroup * pfion= new qsequentialanimationgroup (this); For (INT I = 0; I <4; ++ I) {m_pfpa [I] = new qpropertyanimation (this, "framerect", this); pf1_-> addanimation (m_pfpa [I]);} // initialize and set the animation m_ppa = new qpropertyanimat Ion (this, "POS", this); m_ppa-> setduration (m_animatetime); // you can specify a concurrent animation group, call the two animations simultaneously * ppag = new qparallelanimationgroup (this); ppag-> addanimation (pfanimation); ppag-> addanimation (m_ppa); qkeyeventtransition * pkeypresstrans [4]; qkeyeventtransition * pkeyreleasetrans [4]; int keys [4] = {_ up _, _ down _, _ left _, _ right _}; For (INT I = 0; I <4; ++ I) {pkeypresstrans [I] = new Values (m_pwidget, qevent: keypress, keys [I], m_pstandstate); pkeypresstrans [I]-> settargetstate (m_pwalkstate); pkeypresstrans [I]-> addanimation (ppag ); // "standing? The "Walking" conversion requires animation connect (pkeypresstrans [I], signal (triggered (), this, slot (slotsetdirection ())); // call the pkeyreleasetrans [I] = new qkeyeventtransition (m_pwidget, qevent: keyrelease, keys [I], m_pwalkstate) when the conversion is triggered ); pkeyreleasetrans [I]-> settargetstate (m_pstandstate);} // start the finite state machine m_machine.setinitialstate (m_pstandstate); m_machine.start ();}

Note: In my sketch, when the conversion is triggered, a signal is sent to the character class instance, which is received through the slotsetdirection () slot function, it is used to set different frames for different buttons and move different positions. It can also be said that the slot function sets the orientation (frame), frame animation, and position animation of the role.

The program runs normally, but the error "qeasingcurve: Invalid curve type 45" may occur (in the console). It seems like a ghost of my custom interpolation function. Although I asked a question on the Forum, no one knows the question.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.