Home · All Classes · All Functions · Overviews

[Previous: QML Advanced Tutorial 1 - Creating the Game Canvas and Blocks] [QML Advanced Tutorial] [Next: QML Advanced Tutorial 3 - Implementing the Game Logic]

QML Advanced Tutorial 2 - Populating the Game Canvas

Now that we've written some basic elements, let's start writing the game. The first thing to do is to generate all of the blocks. Now we need to dynamically generate all of these blocks, because you have a new, random set of blocks every time. As they are dynamically generated every time the new game button is clicked, as opposed to on startup, we will be dynamically generating the blocks in the JavaScript, as opposed to using a Repeater.

This adds enough script to justify a new file, samegame.js, the intial version of which is shown below

 //Note that X/Y referred to here are in game coordinates
 var maxX = 10;//Nums are for tileSize 40
 var maxY = 15;
 var tileSize = 40;
 var maxIndex = maxX*maxY;
 var board = new Array(maxIndex);
 var tileSrc = "Block.qml";
 var component;

 //Index function used instead of a 2D array
 function index(xIdx,yIdx) {
     return xIdx + (yIdx * maxX);
 }

 function initBoard()
 {
     //Calculate board size
     maxX = Math.floor(background.width/tileSize);
     maxY = Math.floor(background.height/tileSize);
     maxIndex = maxY*maxX;

     //Initialize Board
     board = new Array(maxIndex);
     for(var xIdx=0; xIdx<maxX; xIdx++){
         for(var yIdx=0; yIdx<maxY; yIdx++){
             board[index(xIdx,yIdx)] = null;
             createBlock(xIdx,yIdx);
         }
     }
 }

 function createBlock(xIdx,yIdx){
     if(component==null)
         component = createComponent(tileSrc);

     // Note that we don't wait for the component to become ready. This will
     // only work if the block QML is a local file. Otherwise the component will
     // not be ready immediately. There is a statusChanged signal on the
     // component you could use if you want to wait to load remote files.
     if(component.isReady){
         var dynamicObject = component.createObject();
         if(dynamicObject == null){
             print("error creating block");
             print(component.errorsString());
             return false;
         }
         dynamicObject.parent = background;
         dynamicObject.x = xIdx*tileSize;
         dynamicObject.y = yIdx*tileSize;
         dynamicObject.width = tileSize;
         dynamicObject.height = tileSize;
         board[index(xIdx,yIdx)] = dynamicObject;
     }else{//isError or isLoading
         print("error loading block component");
         print(component.errorsString());
         return false;
     }
     return true;
 }

The gist of this code is that we create the blocks dynamically, as many as will fit, and then store them in an array for future reference. The initBoard function will be hooked up to the new game button soon, and should be fairly straight forward.

The createBlock function is a lot bigger, and I'll explain it block by block. First we ensure that the component has been constructed. QML elements, including composite ones like the Block.qml that we've written, are never created directly in script. While there is a function to parse and create an arbitrary QML string, in the case where you are repeatedly creating the same item you will want to use the createComponent function. createComponent is a built-in function in the declarative JavaScript, and returns a component object. A component object prepares and stores a QML element (usually a composite element) for easy and efficient use. When the component is ready, you can create a new instance of the loaded QML with the createObject method. If the component is loaded remotely (over HTTP for example) then you will have to wait for the component to finish loading before calling createObject. Since we don't wait here (the waiting is asyncronous, the component object will send a signal to tell you when it's done) this code will only work if the block QML is a local file.

As we aren't waiting for the component, the next block of code creates a game block with component.createObject. Since there could be an error in the QML file you are trying to load, success is not guaranteed. The first bit of error checkign code comes right after createObject(), to ensure that the object loaded correctly. If it did not load correctly the function returns false, but we don't have that hooked up to the main UI to indicate that something has gone wrong. Instead we print out error messages to the console, because an error here means an invalid QML file and should only happen while you are developing and testing the UI.

Next we start to set up our dynamically created block. Because the Block.qml file is generic it needs to be placed in the main scene, and in the right place. This is why parent, x, y, width and height are set. We then store it in the board array for later use.

Finally, we have some more error handling. You can only call createObject if the component has loaded. If it has not loaded, either it is still loading or there was an error loading (such as a missing file). Since we don't request remote files the problem is likely to be a missing or misplaced file. Again we print this to the console to aid debugging.

You now have the code to create a field of blocks dynamically, like below:

To hook this code up to the New Game button, you alter it as below:

         Button {
             id: btnA; text: "New Game"; onClicked: initBoard();
             anchors.left: parent.left; anchors.leftMargin: 3
             anchors.verticalCenter: parent.verticalCenter
         }

We have just replaced the onClicked: console.log("Implement me!") with onClicked: initBoard(). Note that in order to have the function available, you'll need to include the script in the main file, by adding a script element to it.

     Script { source: "samegame.js" }

With those two changes, and the script file, you are now dynamically creating a field of blocks you can play with. They don't do anything now though; the next chapter will add the game mechanics.

[Previous: QML Advanced Tutorial 1 - Creating the Game Canvas and Blocks] [QML Advanced Tutorial] [Next: QML Advanced Tutorial 3 - Implementing the Game Logic]


Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) Trademarks
Qt 4.7.0