My last post on QML had a lot of people asking for an example, as opposed to a general discourse. In my opinion, if you want concrete examples you need to move from blogs into real code. Given that I have written a, hopefully simple, application demonstrating the points in my last post (designing C++ code for QML use), this post (writing games with QML), and the next QML post I plan to write (QML’s versioning system, when I’ll use version 2 of this example). It’s a C++ module containing word-game related logic designed for use from QML, plus a QML game using it, and they can be found in the qt-qml-demo-playground repository in the wordgame and longwords folders, respectively. They are merely intended to provide some concrete examples, and you don’t have to play with them before reading the rest of this post (but it is a game, so you can ). Now onto the topic of this post, writing games with QML.
QML is designed for smooth application UIs, and it does that job very well. I’ve found that it is also flexible enough to implement a game inside that UI. So for simple games, where the intuitive and smooth user interface is often as hard as the game part, QML works surprisingly well for creating the whole thing. I’m going to arbitrarily split games into two groups here: Simple games, and Complex games. Simple games being the ones that are 2D, tile-based or with very simple geometry, and with fairly simple logic. Complex games are everything else (3D, or large maps, or with complex geometry or with a lot of collision detection or physics…). Since you can do everything with QML you can obviously construct both types with QML. However, simple games can be easily produced using just QML and JS. If you want to just write simple games for your mobile devices, like Symbian and Meego which will in time have Qt 4.7 shipped on them, QML will likely be sufficient.
I’ll now provide a basic guide on how to put QML pieces together to form a simple QML/JS game. For further details try the Samegame tutorial in the Qt Quick docs. Note that this isn’t a definitive guide, it’s just my rambling of how I’ve manage to do it so far.
The GameBoard element is usually just an Item type, with a background image as a child. However I give it an id that I use from within the logic file, and often I set the size of the game tiles based on its size. This allows you to make that element size itself to make the most of the available space, and thus be resizeable (but this really doesn’t matter on mobile).
The game elements, like the stones in samegame, I prefer to create from the imperative side. This means that, in the newGame() function, you create, initialize and position instances of your game pieces, from the QML files that define their look and feel, and then position them on the game board. They will also need to import the game state logic file, so as to call methods that alter the game state (when they’re clicked, for example). Last time I checked, it was safe to save state in the logic JS file, and then when the pieces or main file call the JS file, they operate on the same variables. So as long as you store all the game state in the logic JS file, and manipulate it via functions in that file, then you’ll all be operating on the same state from all your various components. An extra advantage of making the game elements separate components is easy theming. You can have a different QML file for a differently themed stone for samegame and all you need to do is switch the file loaded in the JS logic; everything else can still work if you used QML components correctly. These different elements can be more than just different images, but have different animations as well.
So, to sum up, simple games can be easily written in QML/JS by combining the following three things.
- A central element in the UI to parent all the game items to.
- QML files defining the look and feel of the game elements, so that they can be fluid in their movements.
- A JS file with all the imperative logic and game state.
Unfortunately, it’s hard to be more specific than that because every game is different. Even QML cannot come up with a brilliant game idea for you. You can check out the Samegame and Snake demos (pictured below, as examples) in the Qt demos for some examples, and the minehunt demo is similar but with the logic in a C++ plugin instead. There is also the WordGame example, mentioned above, which provides a C++ module that you can write your own QML game with as well as one game using it.
To return to the complex games as a postscript, the way to start writing them in QML is more like the minehunt example. You do the game logic and complex parts in C++, and expose them to a QML front end. For example, you can have the C++ just know where the ‘player’ sprite is, do all the complex logic manipulating that position to move it, and the QML file could optionally cycle through sprites for a walking animation or not; this gives the designer a lot more flexibility. Unfortunately, there is not so great a dummy data solution for this approach as with other QML UIs. If your game is too complex for QML in the main part (for example, a modern 3D RTS or FPS with thousands of actors and realistic physics), QML would still work great for the UI overlay on top. It’s unfortunate that I don’t have the time to write an epic RTS just to prove that last point .
The new Qt DevNet beta is great, and has forums for both Qt Quick development and game development with Qt. I recommend that comments or questions not specifically about this post go there instead of the comments on labs, as they’ll get seen a lot easier and by more people.