QML高级教程2 - 填充游戏画布#

在JavaScript中生成方块#

现在我们已经编写了一些类型,让我们开始编写游戏。

第一个任务是生成游戏方块。每次点击“新游戏”按钮时,游戏画布就会用一组新的、随机的方块填充。由于我们需要为每个新游戏动态生成新的方块,因此我们不能使用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(即加载对象时出现了错误),打印错误信息。

  • 将方块放置在棋盘上它的位置,设置其宽度和高度。同时,将其存储在方块数组中供未来参考。

  • 最后,如果有某种原因无法加载组件(例如,文件丢失),将打印错误信息到控制台。

将JavaScript组件连接到QML#

现在我们需要从我们的QML文件中调用samegame.js中的JavaScript代码。为此,我们向samegame.qml添加以下行,它将JavaScript文件作为一个模块导入

import "samegame.js" as SameGame

这使我们能够使用“SameGame”作为前缀来引用samegame.js中的任何函数:例如,SameGame.startNewGame()SameGame.createBlock()。这意味着我们现在可以将“新游戏”按钮的onClicked处理程序连接到startNewGame()函数,如下所示

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

因此,当您点击“新游戏”按钮时,调用startNewGame()并生成一个方块场,如下所示

../_images/declarative-adv-tutorial2.png

现在,我们有一个方块屏幕,并且我们可以开始添加游戏机制。

项目示例 @ code.qt.io