1. 程式人生 > >Qt移動應用開發(三):使用精靈圖片實現幀動畫

Qt移動應用開發(三):使用精靈圖片實現幀動畫

       上一篇博文講到了Qt Quick對於動畫的一般支援,動畫的形式多樣,配合不同的插值函式,可以幾乎實現所有想要的動畫效果,而對於遊戲的一些特殊的效果比如說幀動畫,Qt更是有專門的類來實現。下面我們就來看看Qt Quick中究竟是對幀動畫是如何實現的吧。

原創文章,反對未宣告的引用。原部落格地址:http://blog.csdn.net/gamesdev/article/details/33743527

       一般2D的遊戲引擎都將幀動畫作為一項非常重要的功能特性加以宣傳,比如說cocos2d-x也有很強大的幀動畫效果,事實上,一個良好的設計可以讓幀動畫有無限的變種形式,從而給設計人員無限的靈感空間。Qt Quick的幀動畫做得很完善,不僅可以單獨渲染成動畫的形式,而且可以和粒子系統相搭配,獲得更炫的例子效果。

       事實上幀動畫為了節省視訊記憶體的空間,一般會採用一張大圖的形式來儲存一個角色的所幀資訊,下面兩個例子就是幀動畫圖片:


       幀動畫的實現通常需要狀態機系統的輔助。因為除了解析這張大圖的任務外,為角色的每個動作賦予相應的狀態也是幀動畫的重要任務。所以一款遊戲會將角色的某個動作的不同幀作為一組來分類播放,最後形成角色的行為動作。這是Qt自帶的例子bear whack的截圖:

下面我就使用一個例項來向大家介紹一下Qt如何使用Sprite和SpriteSequence來實現幀動畫的。

import QtQuick 2.2
import QtQuick.Controls 1.1

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Sprite測試")

    menuBar: MenuBar {
        Menu {
            title: qsTr("檔案")
            MenuItem {
                text: qsTr("退出")
                onTriggered: Qt.quit( );
            }
        }
    }

    SpriteSequence
    {
        id: spriteSequence
        anchors.centerIn: parent
        width: 256
        height: 256
        interpolate: false
        running: true
        sprites:
        [
            Sprite
            {
                name: "floating"
                source: "Bear1.png"
                frameCount: 9
                frameWidth: 256
                frameHeight: 256
                frameDuration: 80
            }
        ]
    }

    Text
    {
        anchors.top: spriteSequence.bottom
        anchors.horizontalCenter: spriteSequence.horizontalCenter
        text: qsTr("本例用來測試Sprite的使用情況。")
    }
}

我們直接將Qt例子中的小熊幀動畫拿過來了。下面是程式的截圖:

       SpriteSequence類的作用是為幀動畫提供一個顯示的容器,並且控制Sprite的執行情況。而Sprite呢,則類似於一個動作組,它可以指定角色的動作由哪些幀組成。上面的例子是通過使用frameCount、frameWidth、frameHeight和frameDuration來達到目的。Sprite的容器可以不是SpriteSequence,比如說將幀動畫應用在粒子系統上就需要ImageParticle作為Sprite的容器了,比如說Qt自帶的例子bear whack就使用了類似的手法。

       除了上面的方法外,還有一種將SpriteSequence和Sprite結合起來的更加簡單的方法來指定動畫,那就是AnimateSprite。還是上面的例子,我們這樣改寫:

AnimatedSprite
{
    id: animatedSprite
    anchors.centerIn: parent
    width: 256
    height: 256
    frameCount: 9
    frameWidth: 256
    frameHeight: 256
frameDuration: 80
interpolate: false
    source: "Bear1.png"
}

效果和上面一樣,而且語法更加簡單。其實正是Qt去掉了自定義transition(過渡)的效果而推出的一個簡單類,非常適合只有單個動作的角色。大多數情況下我們使用它就足夠了。

       在我製作的遊戲《吃藥了》中,我也受益於AnimatedSprite類,其實在時間緊迫的情況下,我只繪製出了兩幀:

於是在AnimatedSprite的幫助下,實現細菌的幀動畫就變得非常簡單:

// 細菌
import QtQuick 2.2
import "GameController.js" as Controller

Block
{
    id: bacterium
    type: Controller.TYPE_BACTERIUM
    property alias source: sprite.source

    AnimatedSprite
    {
        id: sprite
        width: parent.width
        height: parent.height

        frameWidth: 128
        frameHeight: 128
        frameCount: 2
        frameRate: 2
        running: true
    }

    function setSource( color )
    {
        var imageResources = ["bacterium-red.png",
                              "bacterium-yellow.png",
                              "bacterium-blue.png"];
        source = "../../images/" + imageResources[color];
    }

    function setInvisible( )
    {
        sprite.visible = false;
    }
}