En esta página

QML Tutorial Avanzado 2 - Rellenando el Lienzo del Juego

Generando los Bloques en JavaScript

Ahora que hemos escrito algunos tipos, empecemos a escribir el juego.

La primera tarea es generar los bloques del juego. Cada vez que se pulsa el botón Nuevo Juego, el lienzo del juego se rellena con un nuevo conjunto aleatorio de bloques. Dado que necesitamos generar dinámicamente nuevos bloques para cada nueva partida, no podemos utilizar Repeater para definir los bloques. En su lugar, crearemos los bloques en JavaScript.

He aquí el código JavaScript para generar los bloques, contenido en un nuevo archivo, samegame.js. El código se explica a continuación.

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;
}

La función startNewGame() borra los bloques creados en el juego anterior y calcula el número de filas y columnas de bloques necesarios para llenar la ventana de juego del nuevo juego. Luego, crea un array para almacenar todos los bloques del juego, y llama a createBlock() para crear suficientes bloques para llenar la ventana del juego.

La función createBlock() crea un bloque desde el archivo Block.qml y mueve el nuevo bloque a su posición en el lienzo del juego. Esto implica varios pasos:

  • Qt.createComponent() es llamada para generar un tipo desde Block.qml. Si el componente está listo, podemos llamar a createObject() para crear una instancia del elemento Block.
  • Si createObject() devuelve null (es decir, si se ha producido un error al cargar el objeto), imprime la información del error.
  • Coloca el bloque en su posición en el tablero y fija su anchura y altura. Además, guárdalo en la matriz de bloques para futuras referencias.
  • Por último, imprima la información de error en la consola si el componente no se ha podido cargar por algún motivo (por ejemplo, si falta el archivo).
Conexión de componentes JavaScript a QML

Ahora necesitamos llamar al código JavaScript en samegame.js desde nuestros archivos QML. Para ello, añadimos esta línea a samegame.qml que importa el archivo JavaScript como un módulo:

import "samegame.js" as SameGame

Esto nos permite referirnos a cualquier función dentro de samegame.js usando "SameGame" como prefijo: por ejemplo, SameGame.startNewGame() o SameGame.createBlock(). Esto significa que ahora podemos conectar el manejador del botón Nuevo Juego onClicked a la función startNewGame(), así:

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

Así, al pulsar el botón Nuevo Juego, se llama a startNewGame() y se genera un campo de bloques, así:

Ahora, tenemos una pantalla de bloques, y podemos empezar a añadir la mecánica del juego.

Proyecto de ejemplo @ 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.