Qt開発のケースコンバット:QMLの高度なチュートリアル4-ゲームプログラムを生き生きとさせる

 

Qtはクロスプラットフォームフレームワークであり、通常はグラフィカルツールキットとして使用されます。CLIアプリケーションの作成に非常に役立つだけではありません。また、3つの主要なデスクトップオペレーティングシステムとモバイルオペレーティングシステム(Symbian、Nokia Belle、Meego Harmattan、MeeGo、BB10など)、組み込みデバイス、Android(Necessitas)、iOSポートでも実行できます。今、私たちはあなたに無料の試用版を提供します。

Qt6の最新の試用版をダウンロードする

Qtコンポーネントの推奨事項:

  • QtitanRibbonダウンロードして試す:QtテクノロジのMicrosoftリボンUIパラダイムに準拠し、Windows、Linux、およびMac OSX用のフル機能のリボンコンポーネントの提供に取り組んでいるリボンUIコンポーネント。
  • QtitanChart  | ダウンロードして試す :は、アプリケーションに美しく豊富なグラフをすばやく提供できるようにする一連のコントロールを表すC ++ライブラリです。そして、すべての主要なデスクトップをサポートします。
  • QtitanNavigation  | ダウンロードして試す :Microsoft Dynamics CRM-2016 / Office365ナビゲーションインターフェイスとQt.C ++アプリケーションのユーザーエクスペリエンスを向上させるための一連のコントロールをシミュレートするQtitanNavigationコンポーネント。

次に、ゲームをアクティブ化するために2つのことを行う必要があります。ブロックをアニメートすることとハイスコアシステムを追加することです。

また、アプリケーションファイルのディレクトリ構造もクリーンアップしました。これで多くのファイルが作成されたため、samegame.qml以外のすべてのJavaScriptファイルとQMLファイルが「content」という名前の新しいサブディレクトリに移動されました。

新しいブロックアニメーションを歓迎するために、Block.qmlファイルの名前がBoomBlock.qmlに変更されました。

アニメーションブロックの動き

まず、ブロックをアニメーション化して、滑らかに移動させます。QMLには、流体モーションを追加する多くの方法があります。この場合、Behaviorタイプを使用してSpringAnimationを追加します。BoomBlock.qmlでは、SpringAnimationビヘイビアーをxプロパティとyプロパティに適用します。これにより、ブロック本体がスプリングのように指定された位置に移動します(値はsamegame.jsによって設定されます)。以下は、BoomBlock.qmlに追加されたコードです。

property bool spawned: false

Behavior on x {
    enabled: spawned;
    SpringAnimation{ spring: 2; damping: 0.2 }
}
Behavior on y {
    SpringAnimation{ spring: 2; damping: 0.2 }
}

スプリングとダンピングの値を変更して、アニメーションのスプリングのようなアクションを変更できます。

有効:スポーン設定は、samegame.jsのcreateBlock()から設定されたスポーン値を参照します。これにより、createBlock()がブロックを正しい位置に設定した後にのみ、x上のSpringAnimationが有効になります。それ以外の場合、ゲームの開始時に、ブロックは連続して上から落ちるのではなく、コーナー(0,0)からスライドします。有効にコメントアウトしてみてください:スポーンして自分の目で確かめてください)。

アニメーションブロックの不透明度の変更

次に、スムーズな終了アニメーションを追加します。このために、Behaviorタイプを使用します。これにより、プロパティが変更されたときにデフォルトのアニメーションを指定できます。この場合、ブロックの不透明度が変化すると、不透明度の値をアニメーション化して、完全に表示されている状態と表示されていない状態の間で突然変化するのではなく、徐々にフェードインおよびフェードアウトします。これを行うには、BoomBlock.qmlのImageタイプのopacityプロパティにBehaviorを適用します。

Image {
    id: img

    anchors.fill: parent
    source: {
        if (type == 0)
            return "../../shared/pics/redStone.png";
        else if (type == 1)
            return "../../shared/pics/blueStone.png";
        else
            return "../../shared/pics/greenStone.png";
    }
    opacity: 0

    Behavior on opacity {
        NumberAnimation { properties:"opacity"; duration: 200 }
    }
}

不透明度:0に注意してください。これは、ブロックが最初に作成されたときに透明であることを意味します。ブロックを作成および破棄するときにsamegame.jsで不透明度を設定できますが、これは次に追加するアニメーションに役立つため、stateを使用します。最初に、これらの状態をBoomBlock.qmlのルートタイプに追加しました。

property bool dying: false
states: [
    State{ name: "AliveState"; when: spawned == true && dying == false
        PropertyChanges { target: img; opacity: 1 }
    },
    State{ name: "DeathState"; when: dying == true
        PropertyChanges { target: img; opacity: 0 }
    }
]

これで、ブロックアニメーションを実装したときにspawnをtrueに設定したため、ブロックは自動的にフェードインします。フェードアウトするには、ブロックが破棄されたときに不透明度を0に設定する代わりに、deathをtrueに設定します(floodFill()関数で)。

パーティクルエフェクトを追加する

最後に、ブロックが破壊されたときに、クールなパーティクルエフェクトをブロックに追加します。これを行うには、最初に次のようにパーティクルシステムをBoomBlock.qmlに追加します。

 

これを完全に理解するには、「Qt Fast Particle Systemの使用」を読む必要がありますが、パーティクルが正常に放出されないように、emitRateがゼロに設定されていることに注意してください。さらに、パーティクルタイプでburst()メソッドを呼び出すことにより、パーティクルのバーストを作成する染色状態も拡張しました。現在の状態のコードはこんな感じです。

states: [
    State {
        name: "AliveState"
        when: spawned == true && dying == false
        PropertyChanges { target: img; opacity: 1 }
    },

    State {
        name: "DeathState"
        when: dying == true
        StateChangeScript { script: particles.burst(50); }
        PropertyChanges { target: img; opacity: 0 }
        StateChangeScript { script: block.destroy(1000); }
    }
]

これで、ゲームのアニメーションは非常に美しく、すべてのプレーヤーのアクションに微妙な(またはそれほど微妙ではない)アニメーションが追加されます。最終的な効果を下の図に示します。基本的なテーマを示すために、さまざまな写真を使用しています。

 

ここでのテーマの変更は、ブロック画像を置き換えることによってのみ生成されます。これは、実行時にImage sourceプロパティを変更することで実行できるため、さらに課題が発生した場合は、ボタンを追加して、さまざまな画像のテーマを切り替えることができます。

ハイスコ​​アを維持する

ゲームに追加したいもう1つの機能は、ハイスコアを保存および取得する方法です。

これを行うには、ゲームの最後にダイアログボックスを表示して、プレーヤーの名前を要求し、それをハイスコアテーブルに追加します。これには、Dialog.qmlにいくつかの変更を加える必要があります。Textタイプに加えて、キーボードのテキスト入力を受け取るためのTextInputサブアイテムが追加されました。

 

長方形{ 
    id:コンテナ
    ... 
    TextInput { 
        id:textInput
        アンカー{verticalCenter:parent.verticalCenter; left:dialogText.right} 
        width:80 
        text: "" 

        onAccepted:container.hide()// Enterキーが押されたときにダイアログを閉じる
    } 
    ... 
}

 

また、showWithInput()関数を追加します。show()の代わりにこの関数を呼び出すことによってのみ、テキスト入力が表示されます。ダイアログボックスを閉じると、closed()シグナルが送信され、他の種類のダイアログボックスでは、inputTextプロパティを介してユーザーが入力したテキストを取得できます。

 

Rectangle { 
    id:コンテナ
    プロパティ文字列inputText:textInput.text
    シグナル
        閉関

    数show(text){ dialogText.text = text; 
        container.opacity = 1; 
        textInput.opacity = 0; 
    }

    関数showWithInput(text){ 
        show(text); 
        textInput.opacity = 1; 
        textInput.focus = true; 
        textInput.text = "" 
    } 

    function hide(){ 
        textInput.focus = false; 
        container.opacity = 0; 
        container.closed(); 
    } 
    ... 
}

 

このダイアログは、samegame.qmlで使用できるようになりました。

 

ダイアログ{ 
    id:nameInputDialogアンカー
    .centerIn:親
    z:100 

    onClosed:{ 
        if(nameInputDialog.inputText!= "")
            SameGame.saveHighScore(nameInputDialog.inputText); 
    } 
}

 

ダイアログボックスが終了信号を発行すると、samegame.jsで新しいsaveHighScore()関数を呼び出して、ローカルSQLデータベースにハイスコアを格納し、可能であれば、スコアをオンラインデータベースに送信します。

samegame.jsのvictoryCheck()関数で、nameInputDialogがアクティブ化されます。

 

function VictoryCheck(){ 
    ... 
    //ゲームが終了したかどうかを確認する
    if(deservesBonus ||!(floodMoveCheck(0、maxRow -1、-1))){ 
        gameDuration = new Date()-gameDuration; 
        nameInputDialog.showWithInput( "勝ちました!名前を入力してください:"); 
    } 
}

 

ハイスコ​​アをオフラインで保存する

次に、ハイスコアテーブルを実際に保存する機能を実装する必要があります。

これがsamegame.jsのsaveHighScore()関数です。

 

function saveHighScore(name){ 
    if(scoresURL!= "")
        sendHighScore(name); 

    var db = Sql.LocalStorage.openDatabaseSync( "SameGameScores"、 "1.0"、 "ローカルSameGameハイスコア"、100); 
    var dataStr = "INSERT INTO Scores VALUES(?、?、?、?)"; 
    var data = [name、gameCanvas.score、maxColumn + "x" + maxRow、Math.floor(gameDuration / 1000)]; 
    db.transaction(function(tx){ 
        tx.executeSql( 'CREATE TABLE IF NOT EXISTS Scores(name TEXT、score NUMBER、gridSize TEXT、time NUMBER)'); 
        tx.executeSql(dataStr、data); 

        var rs = tx。 executeSql( 'SELECT * FROMスコアWHEREgridSize = "12x17" ORDERBYスコアdescLIMIT 10'); 
            r + =(i + 1)+ "。" + rs.rows.item(i).name + 'は' + rs.rowsを取得しました。 item(i).score + 'は' + rs.rows.item(i).time + '秒を指します。\ n'; 
        } 
        dialog.show(r); 
    }); 
}

 

まず、ハイスコアをオンラインデータベースに送信できる場合は、sendHighScore()(次の章で説明)を呼び出します。

次に、ローカルストレージAPIを使用して、このアプリケーションに固有の永続的なSQLデータベースを維持します。openDatabaseSync()を使用して、ハイスコア用のオフラインストレージデータベースを作成し、ハイスコアを保存するために使用するデータとSQLクエリを準備します。オフラインストレージAPIは、データの操作と取得にSQLクエリを使用します。db.transaction()呼び出しでは、3つのSQLクエリを使用してデータベースを初期化し(必要な場合)、ハイスコアを追加して取得します。返されたデータを使用するために、データを文字列に変換し、1行に1行を返し、その文字列を含むダイアログボックスを表示します。

これは、ハイスコアをローカルに保存して表示する方法ですが、それが唯一の方法ではありません。より複雑なオプションは、高スコアのダイアログコンポーネントを作成し、その結果を処理と表示のために渡すことです(Dialogを再利用するのではありません)。これにより、よりテーマの高いダイアログが可能になり、ハイスコアをより適切に表示できます。QMLがC ++アプリケーションUIの場合は、スコアをC ++関数に渡して、SQLや別のSQLデータベースを使用しない単純な形式など、さまざまな方法でローカルに保存することもできます。

ハイスコ​​アをオンラインで保存する

ハイスコ​​アをローカルに保存する方法を見てきましたが、ネットワーク対応のハイスコアストレージをQMLアプリケーションに統合するのも簡単です。彼女の実装は非常に簡単です。特定のサーバーで実行されているphpスクリプトにハイスコアデータを公開すると、サーバーはそれを保存して訪問者に表示します。スコアを含み表示する同じサーバーからXMLまたはQMLファイルをリクエストすることもできますが、これはこのチュートリアルの範囲を超えています。ここで使用したphpスクリプトは、examplesディレクトリにあります。

プレイヤーが名前を入力すると、データをWebサービスに送信できます。

プレーヤーが名前を入力すると、samegame.jsでこのコードを使用して、データをサービスに送信します。

 

function sendHighScore(name){ 
    var postman = new XMLHttpRequest()
        var postData = "name =" + name + "&score =" + gameCanvas.score + "&gridSize =" + maxColumn + "x" + maxRow + "&time =" + Math.floor(gameDuration / 1000); 
    postman.open( "POST"、scoresURL、true); 
    postman.setRequestHeader( "Content-Type"、 "application / x-www-form-urlencoded"); 
    postman.onreadystatechange = function(){ 
        if(postman.readyState == postman.DONE){ 
            dialog.show( "スコアがアップロードされました。"); 
        } 
    } 
    postman.send(postData); 
}

 

このコードのXMLHttpRequestは、標準のブラウザーJavaScriptのXMLHttpRequest()と同じです。同じメソッドを使用して、WebサービスからXMLまたはQMLを動的に取得し、ハイスコアを表示できます。この場合、応答について心配する必要はありません。ハイスコアデータをWebサーバーに公開するだけです。QMLファイル(またはQMLファイルのURL)が返される場合は、ブロックと同じ方法でインスタンス化できます。

おすすめ

転載: blog.csdn.net/qq_42444778/article/details/115299731