It's no secret that today mobile games are very popular. The ability to write one of these games is every developer, even a beginner. Often the question arises with the choice of platform. Of course, I want the game to be everywhere at once: on iOS and Android, on WP7 and MeeGo, on the desktop and in the browser. And so that all this can be easily implemented using free tools.
')
In this article I will tell you how to make the bulk of the code platform-independent, and for the rest use convenient development tools for each specific platform. The goal of the game shown in the picture above is to have time to hit the apple while it is flying down. Over time, the number of apples increases, and not to miss them is becoming increasingly difficult. The apples fall at an arbitrary angle, rotating and bouncing realistically from the borders thanks to the physics engine Box2D . The game will run on Android, Qt-enabled platforms (Symbian, Maemo, MeeGo, Windows, Linux, Mac OS X) and Google Chrome browser.
Selection of convenient tools
Since I will write the main part of the code in pure C ++ (why, read at the end of the article), any IDE is suitable for this. I will choose Qt Creator, although nothing prevents me from using Microsoft Visual Studio or Eclipse, for example.
For the Android platform, I will focus on the libgdx library. With it, you can easily draw textures, play sounds and do other necessary things.
As a tool for developing games on the desktop, I will take Qt. I have long been acquainted with this library, and it never ceases to please me. When using Qt, I will also get a nice bonus in the form of support for Symbian, Maemo and MeeGo mobile operating systems.
Also, especially for this article, using HTML5, javascript and Google Native Client, I will make the game run in Google Chrome browser. I will use HTML5 Canvas and Audio, and you will see how easy and simple it is.
The implementation of the logic is not complicated, so I will not write about it (anyone can take a look at the code ). Instead, I will focus on how to make the game work on all operating systems.
Abstracting from the final platform
As I said, the main part of the code will be common to all platforms. Let's call it "engine". I will need to solve two problems. The first is calling the engine methods on each platform: For this, the engine will provide the platforms with the following interface:
Calling the drawing and input handlers on different platforms will call methods from the Application class, for example, when using Qt, it will look like this:
When using Native Client in javascript browser, you cannot directly access C ++, instead you need to send messages to the module, for example, the lines:
functiononTouch(e) { var coords = getCursorPosition(e); var x = coords[0]; var y = canvas.height - coords[1]; var message = "touch " + x.toString() + " " + y.toString(); FruitclickModule.postMessage(message); } functionsimulate() { FruitclickModule.postMessage('render'); setTimeout("simulate()", 16); }
In C ++, messages are analyzed, and depending on the content, one or another method is called:
void NaclPlatform::HandleMessage(const pp::Var& var) { if (!var.is_string()) return; std::stringstreamstream(var.AsString()); std::string type; stream >> type; if (type == "render") { m_app.render(); } elseif (type == "touch") { int x; int y; stream >> x >> y; m_app.touch(x, y); } }
As a result, the engine does not matter which platform the call was from; it was abstracted from it. But he knows that the screen has been touched at the point (x, y) or the time has come to process physics and display images on the screen.
Reverse Interaction
The second task is the reverse interaction of the engine with the platform: This is necessary in order for the engine to command when to display images and text on the screen, play sound, vibrate. To do this, all platforms must implement a common interface. Let's call this interface Platform:
At the engine level, I do not attach to any specific platform, I do not upload pictures or audio files, instead I use numeric identifiers. When I want to display an image on the screen, or play a sound, I do the following:
Thus, the engine abstracts from the details of the implementation of various operations on each platform. I give for clarity the class diagram: Is it difficult to do all this? You make sure that no. Time, of course, will have to be spent, but in most cases it can be neglected in comparison with the time spent on programming the application logic. I will provide code for the Android, Qt and Native Client platforms for each required operation: Drawing image, Android (libgdx):
publicvoiddraw(int id, float x, float y, float angle){ TextureRegion region = null; switch (id) { case BACKGROUND: region = background; break; case APPLE: region = apple; break; default: break; } float w = region.getRegionWidth(); float h = region.getRegionHeight(); batch.draw(region, x - w/2, y - h/2, w/2, h/2, w, h, 1, 1, angle); }
Drawing an image, Qt:
void QtPlatrom::drawImpl(Texture id, float x, float y, float angle) { QPixmap* pixmap = NULL; switch(id) { case FruitClick::Platform::APPLE: pixmap = &m_apple; break; case FruitClick::Platform::BACKGROUND: pixmap = &m_background; break; default: break; } y = height() - y; m_painter->translate(x, y); m_painter->rotate(-angle); int w = pixmap->width(); int h = pixmap->height(); m_painter->drawPixmap(-w/2, -h/2, w, h, *pixmap); m_painter->rotate(angle); m_painter->translate(-x, -y); }
This simple game is called Catch an Apple. I propose to start and try to hold out for a couple of minutes, at first I did not succeed: - Native Client version (make sure you have the latest version of the Google Chrome browser, and the Native Client is included with about: plugins and about: flags). The size of the nexe executable file is 4.2Mb for 32-bit systems and 4.9Mb for 64-bit, with a slow connection, you will have to wait a bit; - Windows version - for those who do not like Google Chrome.
Video:
The game runs perfectly on the Android emulator and my LG Optimus. The same situation with Qt Simulator (screenshot from Nokia N9 at the very beginning of the topic).
Code
The code can be taken here , I think it can be useful to someone, especially the sites that are responsible for a bunch of Java and C ++, javascript and C ++ (if you have questions about this, ask, do not hesitate to answer with pleasure).
Why all this?
Many of you will think, why write a bicycle? If there is Marmalade or Unity , for example. There are, but they cost money, and why such heavyweights for a simple 2D toy? Some people also say that Qt starts on Android and iOS, but in fact on Android it doesn’t start like that very much, without sound and OpenGL, and on iOS in general, only YouTube videos. I really like Qt, and I hope that in the near future, applications for iOS and Android can be written as easily as now for MeeGo, but for now it is better to use other tools for these platforms.
Benefits
Using the approach described in this article, you are not tied to the platform, you can use the tools you want, and later you can easily change them. On the desktop - Qt or GTK, on Android - libgdx or AndEngine, on iOS - cocos2d, the choice is yours. You can completely refuse engines using the API provided by the platform. Most of the time, you can write and debug code in your favorite IDE on a great and powerful C ++.
disadvantages
There are drawbacks, of course, for example, you will not be able to use ready-made UI components - you will need to implement them in C ++. Or take out the UI part of the application in each platform. Also, you will definitely have to get to know each platform closely, but as practice shows, it is never possible to completely escape from this acquaintance.
To be continued?
Do you still think that a game for mobile platforms in C ++ is a bad idea? Look at the Angry Birds . Listen to the wonderful performance of Gerb Sutter. Think about the fact that C ++ support is almost everywhere, and that after the new C ++ 11 standard is implemented in all NDKs, it will be even better.