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;
}
}