このページでは

C

Qt Quick Ultralite sprite_animations サンプル

スプライトアニメーションの作成方法を示します。

概要

sprite_animations サンプルは、画像ファイルのフレームシーケンスからスプライトアニメーションを作成する方法を示しています。

この例の画像ソースは16フレームで構成されており、各フレームのサイズは180x160です。

対象プラットフォーム

画像フォーマット

Qt Quick Ultraliteでは、デフォルトの代わりにハードウェア画像デコーダを使用できます。AnimatedSprite およびAnimatedSpriteDirectory QML タイプの両方が、スプライト・アニメーション用に登録された画像フォーマットをサポートしています。

この例では、STM32F769iSTM32H750bRH850/D1M1A評価ボードInfineon TRAVEO T2G CYT4DNボードでの画像デコーダの使用例を示しています。これらのボードでは、プロジェクトはJPEGデコーダを設定し、ImageFilesノードでJPEGファイルの生画像データを使用します。画像デコーダーは、実行時に画像データをデコードしてレンダリングします。詳しくは、Qt Quick Ultralite imagedecoder Exampleと Using JPEG decoderを参照してください。

注: グラフィックス・ドライバの制限により、現在、ソースJPEG画像のサブサンプリング・モードとしてサポートされているのはYUV420のみです。詳細については、JPEGデコードドライバTRAVEO T2Gクラスタシリーズユーザマニュアルのサンプルアプリケーションユーザガイドを参照してください。ソース画像をYUV420サブサンプリング形式に変換するには、ImageMagick Convertツールを使用できます:convert input.jpg -sampling-factor 4:2:0 output.jpg

注意: Infineon TRAVEO T2G CYT4DNの場合、必須のCMake変数TVII_JPEG_DRIVER_DIR を設定してください。これはJPEGデコードドライバSDKのルートフォルダを指す必要があります。

RH850 プラットフォームでは、以下のコンパイル定義を追加して JPEG ドライバを構成します:

  • USE_OUTPUT_SPLIT_MODE

    デコードがチャンク単位で実行される分割モードで、Renesas JCUA ハードウェアを構成します。完全な画像が一度にデコードされる通常モードを使用する場合は、この定義をスキップできます。

  • DECODE_BUFFER_PIXEL_LINES

    USE_OUTPUT_SPLIT_MODE が有効な場合、DECODE_BUFFER_PIXEL_LINES は、1回の繰り返しで処理される出力バッファー画素行数を設定する。この値は16の倍数でなければならない。

    DECODE_BUFFER_PIXEL_LINES のデフォルト値は16である。

  • CHROMA_SUBSAMPLING

    使用する画像のクロマサブサンプリング形式を設定する。設定可能な値は以下のとおり:

    1. R_JCUA_JPEG_FORMAT_YCBCR420
    2. R_JCUA_JPEG_FORMAT_YCBCR411
    3. R_JCUA_JPEG_FORMAT_YCBCR422
    4. R_JCUA_JPEG_FORMAT_YCBCR444

    CHROMA_SUBSAMPLING のデフォルト値は R_JCUA_JPEG_FORMAT_YCBCR420 である。

    注意: 現在、クロマサブサンプリングは実行時に決定できないため、コンパイル時に指定する必要があります。アプリケーションで使用するすべてのJPEG画像は、同じクロマ・サブサンプリングで保存する必要があります。

他のボードやプラットフォームでは、プロジェクトはPNG画像ファイルを使用し、ビルド時にResource Compilerが画像をデコードします。

プロジェクトの構造

CMakeプロジェクトファイル

以下のCMakeの例は、JPEGデコーダーを使用しないプラットフォームで画像をデコードする方法を示しています:

qul_add_target(sprite_animations
    QML_PROJECT mcu_sprite_animations.qmlproject
    GENERATE_ENTRYPOINT
)

以下のQmlProjectの例では、必要な画像リソースプロパティとプラットフォーム設定を使ってJPEGデコーダを設定する方法を示しています:

qul_add_target(sprite_animations
    QML_PROJECT mcu_sprite_animations_jpeg.qmlproject
    os/${QUL_OS_LOWERCASE}/main.cpp
)
QmlProjectファイル

QmlProjectファイルには、必要なQmlファイルとImageファイルが含まれています。

import QmlProject 1.3

Project {
    mainFile: "sprite_animations.qml"
    QmlFiles {
        files: [
            "ToggleButton.qml"
        ]
    }
    ImageFiles {
        files: [
            "qt-image-sequence.png"
        ]
        MCU.resourceAnimatedSpriteFrameWidth: 180
        MCU.resourceAnimatedSpriteFrameHeight: 160
    }
}

QmlProjectは、ImageFiles.MCU.resourceAnimatedSpriteFrameWidthImageFiles.MCU.resourceAnimatedSpriteFrameHeightImageFiles.MCU.resourceAnimatedSpriteOptimizationsを提供し、画像ソースを最適化します。

Resource Compilerは、イメージ・ソースを内部で16フレームに分割し、クロッピング技術を適用して最適化することで、パフォーマンスとメモリ・フットプリントを向上させます。これにより、一連のフレーム間で変更された部分のみをレンダリングすることができます。

アプリケーションUI

sprite_animations.qml ファイルは、AnimatedSprite タイプを定義します。1フレームのサイズ、画像内のフレーム数、画像のソースを定義します。アニメーションはデフォルトで始まります。ユーザーが画像をクリックすると、現在のrunning の値に基づいてアニメーションを実行または停止します。

    AnimatedSprite {
        id: sprite
        anchors.centerIn: parent
        source: "qt-image-sequence.png"

        frameDuration: 80
        frameCount: 16
        frameWidth: 180
        frameHeight: 160

        loops: AnimatedSprite.Infinite

        onFinished: {
            txtMsg.text = "Finished"
        }

        onRunningChanged: {
            if (sprite.running) {
                txtMsg.text = ""
            }
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                if (sprite.running) {
                    sprite.stop()
                } else {
                    sprite.start()
                }
            }
        }
    }

UIの左上には、アニメーションの各フレームの番号と現在のフレームの時間(ミリ秒)が表示されます。

    Column {
        id: spriteInfo
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.margins: 16
        spacing: 4

        Text {
            id: txtFrameNo
            text: "frame: " + (sprite.currentFrame + 1) + " / " + sprite.frameCount
            font.pixelSize: 14
            color: "white"
        }
        Text {
            id: txtDuration
            text: "duration: " + sprite.frameDuration
            font.pixelSize: 14
            color: "white"
        }
        Text {
            id: txtMsg
            font.pixelSize: 14
            text: ""
            color: "white"
        }
    }

アプリケーションには、loops プロパティの値をAnimatedSprite.Infinite と 1 の間で切り替えるためのボタンが右上にあります。

    ToggleButton {
        id: toggleLoops
        width: parent.width / 4
        height: parent.height / 9
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.margins: 8
        checkedText: "Infinite"
        uncheckedText: "Once"
        onCheckedChanged: {
            if (toggleLoops.checked) {
                sprite.loops = AnimatedSprite.Infinite
            } else {
                sprite.loops = 1
            }
        }
    }

ToggleButtonは、RectangleMouseAreaTextRow などのシンプルなビジュアルQMLタイプを使用したカスタムコンポーネントです。

import QtQuick 2.15

Rectangle {
    id: control
    color: "white"

    property bool checked: true
    readonly property color foregroundColor: "black"
    readonly property int borderWidth: 1
    readonly property alias checkedText: txtChecked.text
    readonly property alias uncheckedText: txtUnchecked.text

    Row {
        x: control.borderWidth
        y: control.borderWidth
        spacing: control.borderWidth

        Rectangle {
            id: leftPart
            width: (control.width - control.borderWidth * 3) / 2
            height: (control.height - control.borderWidth * 2)
            color: control.checked? control.color : control.foregroundColor

            Text {
                id: txtChecked
                anchors.centerIn: parent
                color: control.checked? control.foregroundColor : control.color
                font.pixelSize: 14
            }
        }
        Rectangle {
            id: rightPart
            width: leftPart.width
            height: leftPart.height
            color: control.checked? control.foregroundColor : control.color

            Text {
                id: txtUnchecked
                anchors.centerIn: parent
                color: control.checked? control.color : control.foregroundColor
                font.pixelSize: 14
            }
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: control.checked = !control.checked
    }
}
JPEGデコーダーの使用

JPEGデコーダを使用するプラットフォームでは、MCU.resourceKeepRawDataQmlProjectプロパティを使用して、JPEGファイルを生の画像データとしてバンドルすることができます。また、MCU.Config.maxResourceCacheSizeを定義して、実行時にデコードされた画像データを保存するのに十分な容量を確保することもできます。

import QmlProject 1.3

Project {
    MCU.Config {
        // enough size to contain one decoded image
        maxResourceCacheSize: 153600
    }
    QmlFiles {
        files: [
            "ToggleButton.qml",
            "sprite_animations_jpeg.qml"
        ]
    }
    ImageFiles {
        files: [
            "qt-image-sequence/00.jpg",
            "qt-image-sequence/01.jpg",
            "qt-image-sequence/02.jpg",
            "qt-image-sequence/03.jpg",
            "qt-image-sequence/04.jpg",
            "qt-image-sequence/05.jpg",
            "qt-image-sequence/06.jpg",
            "qt-image-sequence/07.jpg",
            "qt-image-sequence/08.jpg",
            "qt-image-sequence/09.jpg",
            "qt-image-sequence/10.jpg",
            "qt-image-sequence/11.jpg",
            "qt-image-sequence/12.jpg",
            "qt-image-sequence/13.jpg",
            "qt-image-sequence/14.jpg",
            "qt-image-sequence/15.jpg"
        ]
        MCU.resourceAnimatedSprite: true
        MCU.resourceKeepRawData: true
    }
}

この例では、ハードウェア・デコードの利点を強調するために、AnimatedSpriteDirectory 、一連のフレーム画像を使用しています。これにより、スプライト・アニメーションのメモリ使用量とCPU負荷が軽減されます。

    AnimatedSpriteDirectory {
        id: sprite
        anchors.centerIn: parent
        sourcePath: "qt-image-sequence"

        frameDuration: 80
        loops: AnimatedSprite.Infinite

        readonly property int frameCount: 16
        ...

ファイル

画像:

リソースの管理も参照してください


Qt ライセンスによっては利用可能です。