QML(Qt)のアニメーション中のエレメントの情報

Qt Quickでは、アニメーション関連のエレメントを使うと簡単に移動させたりと動きを作れます。

アニメーションをスタートさせた後、stopやpauseメソッドで停止したりなどの制御ができるのはすぐに分かるのですが動いているエレメントの途中の状況は取得できるのか?

できます。
ちゃんとバインディングも働きます。

サンプル作ってみました。
青の四角をドラッグ&ドロップすると元の位置まで回転しながら戻ります。
上部に、四角の座標と回転角を表示しています。
アニメーション中もちゃんと更新されます。
スクリーンショットは動いてる途中です。
 

この動いてる途中をプロファイラで見てみると
 
シグナルが発生していないのに、バインディングが発生しています。
今回は、「x, y, rotation」をバインディングしているので3回発生しています。
また、下の全体図のオレンジの四角の中がマウスでドラッグしているところで、細い線が一番したまでいっているのでシグナル(onMousePositionChanged)がセットで発生しているのがわかります。


で、これができると何が嬉しいのか。
先日、ゲームを作りました。「Qt Quickアプリ「Space Incubator」
これで活用されてます。

敵の動きや弾の発射をタイマーの定期処理で行なっています。
ですが、弾についてはエレメントを配置した後にアニメーションの開始だけです。
定期処理でいちいち座標の変更をしていません。やっているのは、当たり判定のみ。
実際の「弾」のエレメントは「EnemyBullet.qml」こんな感じで配置後にアニメーションを開始させるだけです。
継承しているエレメントには当たり判定を計算するメソッドがいる程度。
(アニメーションだとつらい動きをさせたい場合はmoveメソッドに記述すると定期的に呼ばれて動かせる設計。)

非常に楽です。


/// サンプル ///
四角をひっぱると回りながら元にもどるサンプル。
import QtQuick 1.0

Rectangle {
    width: 360
    height: 360
    // 四角の情報
    Text {
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        text: "x=" + Math.ceil(_rect.x) + ", y=" + Math.ceil(_rect.y)
              + ", rotation=" + Math.ceil(_rect.rotation)
    }
    // アニメーションする四角
    Rectangle{
        id: _rect
        x: 10
        y: 10
        width: 50
        height: 50
        color: "#0000ff"
        smooth: true
        MouseArea{
            anchors.fill: parent
            property real press_x: 0
            property real press_y: 0
            onPressed: {
                press_x = mouse.x;
                press_y = mouse.y;
                parent.rotation = 0;
            }
            onMousePositionChanged: {
                parent.x += mouse.x - press_x;
                parent.y += mouse.y - press_y;
            }
            onReleased: {
                _anim.start();
            }
        }
        // 放したときのアニメーション
        ParallelAnimation{
            id: _anim
            NumberAnimation { target: _rect; property: "x"; duration: 1000; to: 10 }
            NumberAnimation { target: _rect; property: "y"; duration: 1000; to: 10 }
            RotationAnimation { target: _rect; property: "rotation"; duration: 1000; to: 90; }
        }
    }
}