Archive

Archive for September, 2011

Qt And Custom Networking Protocols, Or: The Holy Grail Of The Internet

September 27, 2011 5 comments

In the previous installment I talked about combining UPnP’s IGD features with Qt. This culminated for me in a few days of programming and debugging in order to get a functional program working.

Let’s be short about one thing: if you intend to use Qt with custom networking protocols, meaning something other than the standard HTTP, FTP and other such generic protocols, be aware that you shouldn’t use anything more of Qt than QTcpSocket and QTcpServer. QNetworkAccessManager doesn’t work unless you want to extend its range of protocols, while it’s easier to implement the protocol outside it. Avoid QByteArrays for received data and go as low-level as possible. Unsigned integers in Qt, such as quint8 are excellent to use with a standard C/C++ array. It makes data conversion so much easier, assuming you’re using a binary protocol, like I was.

Also brush up on your bitwise operators. You’ll need to know your way with the & AND operator for masking and the << and >> bitwise shifts, such as when converting an integer to bytes for adding them to an array:

QByteArray output;
for (quint32 i = sizeof(ourInt); i > 0; --i) {
    output.append((ourInt >> ((i - 1) * 8)) & 0xFF);
}

Earlier today I finished the first alpha build of the application. It was inspired by a recent XKCD comic:

File transfers

Why not have a basic application which allows one to just transfer files without any accounts, messing with NAT router forwardings, firewalls, setting up servers and other unpleasantness? With all of the raw power available, why can’t we just give someone a link (URI/URL) which allows that person to download a file straight from our own PC? It was the original concept behind the World Wide Web after all.

May I present to you, as the first stage in making this dream a reality, the Universal Data Share (UDS) application:

UDS

For those who want to give it a try, it’s available from here, as a Windows .exe: http://www.mayaposch.com/downloads/Universal_Data_Share.exe. It’s statically compiled against the Qt libraries, so no DLLs are required. UPX was used to compress the EXE (10 MB down to 3.25 MB).

Quick usage tutorial: after starting, go to Shares -> Go Online. This initiates the UPnP IGD discovery and port mapping. Port 11310 is hard-coded in this version. Under File you can add files to the local list. Under Remote you can copy the global (external) IP to the clipboard, which will then allow another person also running UDS to connect to you and obtain a list of your shares. These can then be downloaded via a menu option as well.

In the future I’d like to add URL-based downloads, maybe even add HTTP support so that it can act like a web server, allowing anyone with a browser to connect to it. Anyway, give it a whirl and let me know how it works for you. Feature requests are also quite welcome.

For the usual disclaimer, I’ll just say that this Alpha-level software. I have tested it for the past two days on my Windows 7 Enterprise system via the loopback network. The port mapping was not directly tested and may have issues with some NAT routers. I can not take responsibility for any damage which may be caused to routers, computers, files or other hardware or software. Use of this experimental software is completely at your own risk.

Now go have fun 🙂

Maya

Advertisements
Categories: programming, Qt, Software, UPnP

Setting Up MiniUPnPc With Qt

September 18, 2011 7 comments

Recently I decided to give a feature of Universal Plug ‘n’ Play (UPnP) a whirl: Internet Gateway Device protocol (IGD) [1]. This is a feature which has become commonplace in network devices, specifically routers. Previously one would have to manually set port forwardings in the router’s administration panel in order to allow programs outside the LAN to talk to programs inside it. With UPnP’s IGD functionality the LAN-based program can now take care of those port mappings/forwardings itself. Many games, chat and other programs already use it. One could say that it is now an essential skill for anyone doing serious network programming.

If you need more than just IGD, you can go with one of the more expansive SDKs [2], but otherwise you should be perfectly happy with the extremely light-weight and easy to use MiniUPnPc library [3] which implements the IGD client functionality in ANSI C. This allows it to be used with a variety of languages, in this particular case C++.

The popular C++-based framework Qt doesn’t have native support for UPnP, thus one has to use an external library to add such support. I am currently using MiniUPnPc 1.6 with the Qt 4.7.4 libraries using the MinGW compiler.

Compiling MiniUPnPC is a quick and painless process. On Windows it’s as easy as executing the provided BAT file with MinGW in the PATH and within ten seconds you are left with an .a and .lib library. There’s also MSVC project support if you want to use MSVC, although I haven’t tested it yet.

At this point we can add the first bits of IGD support to our application. Most crucial is adding these parts to the top of the source file:

#define STATICLIB
#include <miniupnpc.h>

Next we have to initialize the network socket library, in this case Winsock2:

WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR) {
    QMessageBox::critical(this, "Error", "WSAStartup() failed.");
    return;
}

With that out of the way, we can verify that all is working using the simple demo code below:

UPNPDev* devlist;
UPNPUrls urls;
IGDdatas data;
char lanaddr[64]; // IP address on the LAN
const char* multicastif = 0;
const char* minissdpdpath = 0;
int error;
devlist = upnpDiscover(1000, multicastif, minissdpdpath, 0, 0, &error);
if (error > 0) {
    QMessageBox::critical(this, "Error", "UPnP discovery failed: " + QString::number(error));
}
else {
    error = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    freeUPNPDevlist(devlist);
    if (error == 0) {
        QMessageBox::critical(this, tr("Devices"), tr("No IGD found."));
    }
    else if (error == 1) {
        QMessageBox::critical(this, tr("Devices"), tr("A valid connected IGD has been found."));
    }
    else if (error == 2) {
        QMessageBox::critical(this, tr("Devices"), tr("A valid IGD has been found, but it reported as not connected."));
    }
    else if (error == 3) {
        QMessageBox::critical(this, tr("Devices"), tr("An UPnP device was found, but wasn't recognized as an IGD."));
    }
}

As defined in the source code, the error codes for the upnpDiscover() function are as follows:

#define UPNPDISCOVER_SUCCESS (0)
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
#define UPNPDISCOVER_SOCKET_ERROR (-101)
#define UPNPDISCOVER_MEMORY_ERROR (-102)

Now, to get it all to compile so that we can test it. In our Qt project we need to add a few items to the Pro file. First, depending on whether the library file we intend to use is already in a known location (MinGW lib folder or Qt SDK’s lib folder) we may have to add its location using

LIBS += D:/dev/miniupnpc/miniupnpc.a

Personally I prefer to put the library files I use a lot in projects directly into the compiler’s lib folder. This means I only have to add the following to the Pro file for it:

LIBS += -lminiupnpc -liphlpapi

Note hereby that the library itself is called ‘libminiupnpc.a’, but we prefix with -l and omit the ‘lib’ and extension. Finally we must include the libiphlpapi.a library as it contains a number of functions used by MiniUPnPc’s network functionality.

At this point we should be able to compile the project and have it run successfully. If there’s a device on the network (router) with IGD (UPnP) enabled, it will respond to the discovery broadcast and be identified. You can verify the output using the commandline test application provided with MiniUPnPc ‘upnpc-static.exe’. Detailed sample code can be found in upnpc.c, which is the source for the test application. There isn’t much available in terms of documentation, but with some puzzling and liberal use of said sample source code, it shouldn’t be too hard to figure out how to do something.

Until next time,

Maya

[1] http://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol
[2] http://upnp.org/sdcps-and-certification/resources/sdks/
[3] http://miniupnp.free.fr/

Categories: MiniUPnP, programming, Qt, UPnP

Basic AndEngine And Box2D Extension Project

September 5, 2011 3 comments

For those waiting for me to resume my jPCT-AE project, I’m still working on it. I just got delayed a bit by my personal life demanding attention, as well as figuring out some details of the jPCT-AE API. I hope to release the next article on it later this or maybe next week.

Anyway, a few days ago someone on IRC’s Freenode network mentioned a game idea which we discussed for a bit before he suggested that I could develop it for Android. It is a simple 2D game and aside from being a possible and much-needed income source for me, it would also be a fun opportunity to explore the 2D engine options for Android a bit more. My earlier research on an Android 3D game engine had already led me to AndEngine [1], which is a very feature-complete 2D game engine with useful extensions including physics using the Box2D 2D physics engine.

There’s one major hurdle with using AndEngine, however, as I soon discovered after picking it. There is no documentation. Nothing. No API reference. No Hello World sample. All you get are random tutorials on the forum and scattered around the internet using which you have to piece together how to do things. And many of those tutorials will be outdated, wrong, or both. Ergo it took me a few days just to sort through the mess and get a basic physics sample working. Since I’m a very generous person, I’ll be sharing my experiences with you all 🙂

The fun starts with just obtaining AndEngine. Previous the core project [2] and Box2D extension [3] were distributed as JAR libraries and pre-compiled native code libraries. Very recently this all changed and you now have to get the source and link the source into your own project. The easiest way to handle this is by using the Eclipse IDE with the ADT plugin [4]. Install the Mercurial plugin for Eclipse (Help -> Install New Software…), and then choose import in Eclipse, pick Mercurial as source and input the address of the source repository. For the core project this is https://code.google.com/p/andengine/ and for the Box2D extension this is http://code.google.com/p/andenginephysicsbox2dextension.

In your project’s properties, go to the build path, then the source tab and link the source folder of each of the projects you have imported. Don’t forget to rename the src folder in the imported project to something else when you link them, or it’ll complain about duplicate folders in your project. You now have added AndEngine successfully to your project. If you also want to use the Box2D extension there is one additional thing to do. As it uses native code for the actual physics calculations, it uses the Native Development Kit (NDK, available on the Android development site). To use the Box2D extension you have to get the NDK and extract it somewhere, then also ensure you got Cygwin with the MingW compiler and make tool installed. This assuming you are on Windows.

Go into the Box2D extension project’s folders and enter the /jni folder. Inside it you’ll see two important files: build.sh and build.bat. Open both files in an editor and change the paths in there to point to the Cygwin bin and the NDK’s ndk-build folder, overwriting the existing paths. Also make sure that in build.bat it changes to the right drive. Now execute build.bat and it should start compiling the extension project for the ARM architecture. After this completes, you will see that the extension project folder has a new /libs folder with in it a number of folders, the most important one being /libs/armeabi, which contains a number of files, the important one being the .so file which is the actual library we needed. In the /libs/armeabi-v7a folder also created, rename or remove the gdbserver instance, or you will get errors. I renamed it to gdbserver.bak, just in case I need it for debugging later on.

Copy the /libs/armeabi folder to a /libs folder in the root folder of your own project. You now have the AndEngine’s Box2D extension installed and ready to be used.

Putting an example together was harder than I thought, but the basics of it are as follows:

public class Main extends BaseGameActivity implements IAccelerometerListener {
DisplayMetrics metrics;

private Camera mCamera;
private Scene mScene;
private PhysicsWorld mPhysicsWorld;
private BitmapTextureAtlas mBitmapTextureAtlas;
private TextureRegion mCircleFaceTextureRegion;

private static final int CAMERA_WIDTH = 480;
private static final int CAMERA_HEIGHT = 800;

private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);

@Override
public Engine onLoadEngine() {
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
this.mCamera = new Camera(0, 0, CAMERA_WIDTH,  CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
this.mCamera));
}

We make use of the BaseGameActivity class instead of Activity for our application. We implement the IAccelerometerListener because we want to make use of the accelerometer sensor of the phone. We declare the resources and the fixed values such as the size of the game window, which I have set here to the height and width of the screen of my phone, which has a 480×800 resolution. A FixtureDef is used with the physics engine. It sets the density of the object, its elasticity and friction values. This will affect the behaviour of an object while it’s inside the physics world.

I obtain the display metrics object so that I can use the values of it later in converting from pixels to display independent pixels. A Camera is created with the previously determined width and height. Finally an Engine is created with the screen orientation set to portrait and with the ratio fixed to the one determined by the camera width and height, as well as linking the Engine to the Camera.

@Override
public void onLoadResources() {
/* Textures. */
this.mBitmapTextureAtlas = new BitmapTextureAtlas(64, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mCircleFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(mBitmapTextureAtlas, this, "face_circle.png", 0, 0);
this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);
}

In OnLoadResources we load all of the textures and other resources we will be using later. For OpenGL ES it is most efficient to use a single, large texture (1024×1024 on older phones, 2048×2048 on newer) instead of many small ones, as OpenGL ES can only hold one texture in memory at any time, making switching between textures an unnecessary burden. We use a single texture (texture atlas, previously called Texture in AndEngine) with all of the textures we will use copied onto it. TextureRegions are used to read sections from this unified texture. In the above code we create a TextureRegion while adding its contents to the texture atlas. We then tell the Engine’s texture manager to load the texture atlas resource into memory.

@Override
public Scene onLoadScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
mScene = new Scene();
mScene.setBackground(new ColorBackground(0, 0, 0));
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);

// create demo scene
final Sprite face;
final Body body;

face = new Sprite(0.0f, 0.0f, this.mCircleFaceTextureRegion);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);

Line line_top = new Line(0, 0, CAMERA_WIDTH, 0, 5.0f * metrics.density);
Line line_left = new Line(0, 0, 0, CAMERA_HEIGHT, 5.0f * metrics.density);
Line line_right = new Line(CAMERA_WIDTH, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 5.0f * metrics.density);
line_top.setColor(1, 1, 1); // RGB
line_left.setColor(1, 1, 1);
line_right.setColor(1, 1, 1);
Body wall_top = PhysicsFactory.createLineBody(mPhysicsWorld, line_top, FIXTURE_DEF);
Body wall_left = PhysicsFactory.createLineBody(mPhysicsWorld, line_left, FIXTURE_DEF);
Body wall_right = PhysicsFactory.createLineBody(mPhysicsWorld, line_right, FIXTURE_DEF);

this.mScene.attachChild(face);
this.mScene.attachChild(line_top);
this.mScene.attachChild(line_left);
this.mScene.attachChild(line_right);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_top, wall_top, true, true));
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_left, wall_left, true, true));
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_right, wall_right, true, true));

this.enableAccelerometerSensor(this);
mScene.registerUpdateHandler(mPhysicsWorld);

return mScene;
}

OnLoadScene is where the scene is set up. If your games uses levels you would make this part a lot more complex, but since we are just setting up a basic example here, we do just that here. We create a new Scene, set the background to black and create a new PhysicsWorld, which is essentially a Box2D World [6]. This PhysicsWorld is given a gravity vector (downwards Y vector is set to ~1 G, or Earth gravity), with allow sleep set to false.

Next a texture we loaded previously from /assets/gfx is now used to create a new Sprite, essentially a bitmap image. A body is created as well, which is required for the PhysicsWorld. We make this a Dynamic Body, meaning that it will be affected by the PhysicsWorld without requiring external input. We also apply the FixtureDef we previously created to it.

Finally we create three lines which create the boundaries of the screen. These are set to a white colour, with a width adapting to the screen’s density. They also get the same FixtureDef. After completing all four objects this way, we add their faces to the Scene and their Bodies to the PhysicsWorld, using a PhysicsConnector. The latter is the link between the visual and physics representations and ensure that the results of the PhyicsWorld update the Scene.

Next we enable the accelerometer and register the PhysicsWorld as being responsible for handling updates for the Scene.

@Override
public void onLoadComplete() {
// TODO Auto-generated method stub

}

@Override
public void onAccelerometerChanged(final AccelerometerData pAccelerometerData) {
final Vector2 gravity = Vector2Pool.obtain(pAccelerometerData.getX(), pAccelerometerData.getY());
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}

}

In onLoadComplete we can do something after the resources finish loading, but here we have no need to do so. Instead we move on to implementing the accelerometer listener. Upon changing its input, we change the gravity vector of the PhysicsWorld to the vector created by the accelerometer data. This has as result that when you move the phone into a particular direction, the ball will follow. Tilting the phone also has the same result.

Since we didn’t put in a bottom line, the ball is free to bounce between the three lines and vanish into the unlimited Scene beyond the screen’s boundaries. By detecting this last condition, we could indicate a ‘game over’ status in a game.

Hopefully this brief tutorial was useful and informative. If there are any questions about AndEngine or related, please don’t hesitate to ask them in the comments. I may be a beginner with AndEngine, but I am a quick study and love helping fellow developers 🙂

Maya

[1] http://www.andengine.org/
[2] http://code.google.com/p/andengine/
[3] http://code.google.com/p/andenginephysicsbox2dextension/
[4] http://www.andengine.org/forums/tutorials/to-everyone-looking-for-jar-files-t4686.html
[5] http://www.andengine.org/forums/tutorials/build-the-examples-and-box2d-extension-t4720.html
[6] http://www.box2d.org/manual.html#_Toc258082968

 

Categories: AndEngine, programming