A Guide to Writing Games with QML

Published Thursday August 12th, 2010
8 Comments on A Guide to Writing Games with QML
Posted in Qt, Qt Quick

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.

Of course, the distinction I’ve drawn between simple and complex blurs more every day. Those of you who read the recent QML/3D labs blog will be quite confused by my emphasis on 2D. With QML/3D, you will be able to make simple games with 3D visuals (so long as you don’t end up having complex 3D logic too such as realistic physics), using just QML and Javascript (QML/JS). You can also make simple games with pre-existing C++ parts, like using the WordGame module, despite my grouping of C++ with complex games. You can even make complex games using my simple game formula, although that would lead to rather messy and long code. Of course in the real world they all seem simple to start with. A key point is that, with QML, you can adapt to increased complexity without having to scrap either your code or your vision to make it work.

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.

A QML/JS game, at least the ones I’ve written, have the following structure: A main file, containing a GameBoard element and the surrounding UI, a JavaScript file, containing all the game logic, and some QML elements for the game pieces (and UI elements). The main file contains the whole game UI in QML, including the game board appropriately sized and positioned.

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 logic file, a .js file with all the game logic, is the imperative logic part. If you try to do something too complex without being a javascript master it gets ugly, and this is the main reason I only recommend pure QML/JS for simple games. Since it does all the imperative stuff, it follows a much more imperative flow than the QML. So I tend to have an init() in the .js called on Component.onCompleted in the main .qml, and a newGame() called from the new game button. You may also want a gameOver state in the UI, and the imperative flow from JS sets these properties (on the GameBoard object, which is preferably the only object it knows about) so that the UI can respond.

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.
Samegame, all in QML and JS
Snake, all in QML and JS

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.

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Qt, Qt Quick


zoniq says:

Thanks for writing this blog post together. But what I would really like to see is a tutorial like the one that has been written for Samegame http://doc.trolltech.com/4.7-snapshot/declarative-tutorials-samegame-samegame1.html but doing the same with C++/QML, e.g. by using the Minehunt example.

I have been looking at the Minehunt example, but I wasn’t able to compile it and make it run. So a step-by-step tutorial would really be appreciated, with a focus on how to setup and configure a combined C++ and QML project as well as showing the interaction points between these two.

scorp1us says:

Now I can begin my work on TrollCraft, a story of three warring factions:
The Trolls, which specialize in sharp weapons and quick wits,
The Androids, which specialize in blunt-force instruments and have enslaved a low but hefty race called called the Javas,
And the Jobs, who has a loyal army of followers called lemmings. Their greatest power is a bum-rush and waiting in line.

All the battles take place on the Troll’s & Androids home world called Linuxia, of which the Jobs are invading. The Trolls however can impersonate Jobs and Androids, using their “Lighthizzy” feature and can even take the battle to the home world of the Jobs, when the grand arbiter, known as the FTC, allows it.

scorp1us says:

I forgot to mention, that the disadvantage with the trolls is there are so few of them.

John Ryland says:

@scorp1us, I love it, nice analogy.

Danny Pope says:

Alan: nice tutorial/blog. I’ll have to do a similar one for QML/3D. As previously mentioned a tutorial including the C++ side of coding for QML would be nice (eg. for minehunt).

@scorp1us: nice… very nice.

Everest says:

Really interesting explanation of QML for games! I did not know it was such powerful. I do not if this is the right place to ask, but it would be nice if anybody could shed some light on a small issue. I am wondering if i can use QML to make the UI and use PyQt or Pyside in the backend? If so, is it possible that i can use it for Windows XP, or Windows 7 desktop appliactions?

scorp1us says:

@Everest, yes, and yes. Though you’ll need to wait for PyQt to support the QDeclaritiveEngine class… At this point though, I have to ask, why you would want to basically be using 2 scripting languages?

You’d basically have one python script with A declaritive engine/view and your backend code.

Everest says:

@scorp1us, Thanks for your reply and interesting insight!. I am only a hobbyist in python using it for some web applications and playing around a bit with PyQt sometimes, though i m desperately waiting for stable complete PySide to be released. May be i m wrong, but from what i see it seems to be much easier and faster to create the smooth UI with QML which looks like CSS and javascript and use PyQt/PySide in the backend!

Commenting closed.

Get started today with Qt Download now