このページでは

QML 上級チュートリアル 2 - ゲームキャンバスの生成

JavaScript でのブロックの生成

いくつかの型を定義したので、いよいよゲームの作成を始めましょう。

最初のタスクは、ゲームブロックを生成することです。「New Game」ボタンがクリックされるたびに、ゲームキャンバスにはランダムな新しいブロックのセットが表示されます。新しいゲームごとに動的に新しいブロックを生成する必要があるため、Repeater を使ってブロックを定義することはできません。代わりに、JavaScript でブロックを作成します。

以下は、新しいファイル「samegame.js 」に記述された、ブロックを生成するための JavaScript コードです。コードの説明は後述します。

var blockSize = 40;
var maxColumn = 10;
var maxRow = 15;
var maxIndex = maxColumn * maxRow;
var board = new Array(maxIndex);
var component;

//Index function used instead of a 2D array
function index(column, row) {
    return column + (row * maxColumn);
}

function startNewGame() {
    //Delete blocks from previous game
    for (var i = 0; i < maxIndex; i++) {
        if (board[i] != null)
            board[i].destroy();
    }

    //Calculate board size
    maxColumn = Math.floor(background.width / blockSize);
    maxRow = Math.floor(background.height / blockSize);
    maxIndex = maxRow * maxColumn;

    //Initialize Board
    board = new Array(maxIndex);
    for (var column = 0; column < maxColumn; column++) {
        for (var row = 0; row < maxRow; row++) {
            board[index(column, row)] = null;
            createBlock(column, row);
        }
    }
}

function createBlock(column, row) {
    if (component == null)
        component = Qt.createComponent("Block.qml");

    // Note that if Block.qml was not a local file, component.status would be
    // Loading and we should wait for the component's statusChanged() signal to
    // know when the file is downloaded and ready before calling createObject().
    if (component.status == Component.Ready) {
        var dynamicObject = component.createObject(background);
        if (dynamicObject == null) {
            console.log("error creating block");
            console.log(component.errorString());
            return false;
        }
        dynamicObject.x = column * blockSize;
        dynamicObject.y = row * blockSize;
        dynamicObject.width = blockSize;
        dynamicObject.height = blockSize;
        board[index(column, row)] = dynamicObject;
    } else {
        console.log("error loading block component");
        console.log(component.errorString());
        return false;
    }
    return true;
}

startNewGame() 関数は、前回のゲームで作成されたブロックを削除し、新しいゲームのゲームウィンドウを埋めるために必要なブロックの行数と列数を計算します。その後、すべてのゲームブロックを格納するための配列を作成し、createBlock() を呼び出して、ゲームウィンドウを埋めるのに十分な数のブロックを作成します。

createBlock() 関数は、Block.qml ファイルからブロックを作成し、その新しいブロックをゲームキャンバスの所定の位置に移動させます。これにはいくつかの手順が含まれます:

  • Qt.createComponent`Block.qml` からタイプを生成するために `()` が呼び出されます。コンポーネントの準備が整っていれば、`createObject() ` を呼び出して `Block ` アイテムのインスタンスを作成できます。
  • createObject() が null を返した場合(つまり、オブジェクトの読み込み中にエラーが発生した場合)、エラー情報を出力します。
  • ブロックをボード上の所定の位置に配置し、幅と高さを設定します。また、後で参照できるように、blocks配列に格納しておきます。
  • 最後に、何らかの理由(ファイルが見つからない場合など)でコンポーネントを読み込めなかった場合は、コンソールにエラー情報を出力します。
JavaScript コンポーネントを QML に接続する

次に、QMLファイルからsamegame.js 内のJavaScriptコードを呼び出す必要があります。そのためには、samegame.qml に以下の行を追加し、JavaScriptファイルをモジュールとしてインポートします。

import "samegame.js" as SameGame

これにより、「SameGame」をプレフィックスとして、samegame.js 内の任意の関数を参照できるようになります。例えば、SameGame.startNewGame() やSameGame.createBlock() などです。つまり、次のように、「New Game」ボタンのonClicked ハンドラをstartNewGame() 関数に接続できるようになります:

        Button {
            anchors { left: parent.left; verticalCenter: parent.verticalCenter }
            text: "New Game"
            onClicked: SameGame.startNewGame()
        }

したがって、「New Game」ボタンをクリックすると、startNewGame() が呼び出され、次のようなブロックのフィールドが生成されます:

ブロックのグリッドが配置されたゲームキャンバス

これでブロックの画面が完成したので、ゲームの仕組みを追加し始めることができます。

サンプルプロジェクト @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.