CLM logo Development Blog by CLM

Remote tweaking

A long time ago in 2010, I have read an interesting article about Remote game editing by Noel Llopis, but it was just last year that we have implemented something similar and I must admit it makes a big difference during development. Basic concept is the same, although we’ve made some implementation choices that I think are really interesting.

First of all, our primary intent was to tweak global constants. Let’s say that there is something like this in the code:

	const float EnemyKillRadius = 36.0f;

It might take a few “edit-compile-run” cycles to find an optimal value for that variable and it takes that precious development time that could be better spent. To speed it up, we can register it in Tweak Server like that:

	WOMBAT_TS_FLOAT(EnemyKillRadius, 36.0f);

But hey, what this line of code actually does? Well it depends. In release builds it evaluates to simple constant variable, but in debug/test builds it’s a little more complicated:

#define WOMBAT_TS_FLOAT(name, value) WOMBAT_TS_FLOAT_INTERNAL(__FILE__, __LINE__, name, value)
#define WOMBAT_TS_FLOAT_INTERNAL(file, line, name, value) \
	float name = value; \
	static Wombat::TS_RegisterFloat WOMBAT_COMBINE(registerFloat, __LINE__)(file, line, #name, &name, value);
class TS_RegisterFloat
	TS_RegisterFloat(const char* file, int line, const char* name, float* ptr, float value)
		TweakServer::Instance()->RegisterFloat(file, line, name, ptr, value);

TweakServer instance is created by the first Instance() call and it stores information about all registered variables (including variable name, source code file name, line number, pointer to the variable and initial value).

Communication between the server and a GUI client is handled with protobuf messages over network socket. When the Tweak Client is running, it looks like this:


One of the most important features is the magical Apply button — as each variable is registered with an additional information about the place in the source code, GUI tool can put the new value directly into the code, so it will be there during the next compilation.

First tab in the GUI tool allows us to pick files which should be included in the tweaking process. It helps to see only the things you are about to change and minimizes unnecessary scrolling.

Our Tweak Server / Client implementation allows us to use it with floats, ints, colors and also execute of simple actions. The next screen shows a little more real example of actions and variables:


There is still a lot that can be improved and added, but the current solution just works and we are very happy with it. It already saved us a lot of time and effort.

Portable audio with FMOD

I definitely need to start following gamedev news more closely — just a moment after we integrated openal-soft for Android version of our framework, Firelight Technologies has made FMOD Studio free for indie devs*! What does this mean for us? FMOD is used in thousands of commercial titles (and that should prove it’s quality), provides great documentation and has a very clean and simple portable API.

Our audio subsystem is using simple handle manager to provide multiple backends (OpenAL, XAudio2) so integration of FMOD should be pretty simple, right? It took me just about 3h to have it up and running at the same functional level as other backends, at least on Windows. With iOS build we faced very strange problems, it looks like the provided libraries contain duplicated object files and that caused duplicate symbols at the linking stage. To confirm this:

$ lipo libfmod_iphoneos.a -thin armv7 -output libfmod_iphoneos_armv7.a
$ ar -t libfmod_iphoneos_armv7.a | sort | uniq -d

After manual fix of the libraries I was able to complete the build. I hope that this will be fixed in the next FMOD Studio release, till then we need to use ‘fixed’ library.

* indie in this case means game budget under $100k.

Monitoring CPU usage on Android

Wow, almost year since the last entry? Time to fix that, especially when it’s such an important day — Anodia is available in the Apple AppStore for the exactly 1024 days! :)

Today I would like to share some of our experience with CPU usage on Android. As every platform is different, there are system specific aspects that we need to take care of. We noticed that Anodia on Android is using lots of CPU power when suspended, even though we’ve done the same logic as on iOS and Windows Phone. It turns out that we faced two problems:

First was related to our usage of OpenAL. Unfortunately there is no native support for OpenAL on Android, so we used apportable openal-soft port. It uses OpenSL as a backend, but as it turned out, OpenSL thread is quite busy even when all audio sources are suspended (~25% CPU usage on Sony Xperia Tipo) . Fortunately calls to alcSuspend/alcResume in game activity onPause / onResume methods solved this issue.

Second issue was related to listening for accelerometer data. On Android it’s required to unregister all listeners when suspending an activity. Otherwise it will consume CPU even when application is not used. In our case listening to accelerometer data caused ~3% CPU usage on Sony Xperia Tipo.

And that’s all, there is one simple lesson: adb shell top -m 10 and monitor tool from sdk are quite useful when it comes to monitoring CPU usage.

Hexbee for Windows 8

It’s amazing how time flies — there was no devlog entry in the last two and a half months!

In the last entry we told you that Direct3D 11 support isn’t a Windows game/port announcement. It’s time to change that, just a couple of days ago we released Hexbee for Windows 8!


It took some additional effort to adapt our framework for Windows 8 and probably we’ll make some posts about that in the near future. In the mean time, have fun and don’t forget to let us know if you encounter any issues.

Abstraction is your friend

We are quite busy with adding support for additional platforms in our 2D engine/framework, Wombat. One of the biggest issues is support of rendering. Recently, the only supported renderer was OpenGL ES 1.1 (with possibility to run on full fledged OpenGL on desktop machines). Now, I’m proud to say that it also supports the same rendering capabilities with Direct3D 11 (don’t get too excited though, this is no windows game/port announcement).

What is so hard about supporting different graphic APIs? Differences in concepts and data types, at least this is my personal opinion. For example, in OpenGL texture in client code is just one GLuint, but in Direct3D it’s ID3D11Texture2D*, ID3D11ShaderResourceView* and shared ID3D11SamplerState*. How to address this? Our approach is to use handles to hide concepts and underlying data types. Handle might be simply an integer, which is mapped to proper data in the subsystem that manages it — clients have no idea what it really means.

For example, part of texture handling in OpenGL renderer might look something like this:

TextureHandle Renderer::LoadTexture(const TextureData& td)
    GLuint textureHandle;

    //... texture loading ...

    return textureHandleManager.Register(textureHandle);

void Renderer::FreeResource(TextureHandle handle)
    GLuint texture = textureHandleManager.Map(handle);
    glDeleteTextures(1, &texture);

void Renderer::SetTexture(TextureHandle handle)
    GLuint texture = textureHandleManager.Map(handle);
    glBindTexture(GL_TEXTURE_2D, texture);

This way client code uses only TextureHandle and there are no dependencies to OpenGL API. Need Direct3D support? Just implement the same interface and you’re done (yup, I know that this is an oversimplification).

The lesson is to avoid being API dependent, which will allow changing the underlying implementation and libraries, and that is a great deal.

iOS 6 adaptation, part 2

It has been almost two months since iOS 6 became available. We already covered the iOS 6 adaptation after one week, but we promised to get back to you after information from couple of weeks is available.

The chart below shows OS versions in Anodia sessions from the last two months:

It’s surprising, but the most sessions are still from iOS 5 (46,7%), than from iOS 6 (42,9%) and the third place goes to iOS 4 (still almost 9,7%). We’ve suspected that till now iOS 6 will take over most of the iOS 5 share. One of the explanations might be that the first generation iPad hasn’t received the upgrade, but according to our statistics, this device is used by only 4% of the Anodia user base. What a conundrum!

Transparency Optimization

During the implementation of a 60 FPS support we noticed that a few levels were not working as fast as they should. After digging a little deeper we found out that our bottleneck was the rendering.

In one of those cases, the texture we used looked like that:

What’s wrong with it? It’s 128×128 (16384 pixels), but it’s quite easy to notice that lots of pixels on the sides of it are transparent. After a few moments of trimming it down we got 108×108 texture that looks like this:

108×108=11664, so the new texture contains almost 29% less pixels It’s a quite good optimization! When a few dozens of sprites are rendered on the screen this might make a significant difference for your fillrate.

It’s important to remember that transparency comes at a cost, there is no way to discard transparent pixels prior to the texture fetch. Trimming down textures also helps to reduce size of the rendered sprites, which might lead to nice performance increase in GPUs that use tiled rendering (like the PowerVR GPUs used in Apple mobile devices).

iOS 6 adaptation

It has been just a few days since iOS 6 became available, but we think that information about it adaptation by users is interesting.

This chart shows OS version in Anodia sessions from the last week:

It’s easy to notice that most of the users have one of the two most recent OS versions, which is great from the developer perspective. What is more important, it looks that iOS 6 share is almost the same as iOS 5.1.1 share.

Stat tuned! We’re going to provide similar chart when the data from a few weeks will be available.

In-App Purchases piracy

Today I want to discuss one issue that we noticed after introducing Anodia 2.0 version — piracy of In-App Purchases.

For quite some time, we’ve been using Localytics to gather statistics that help us improving our games. One of them counts the number of coin purchases. To be honest, I never supposed that the number of pirated IAP might be so high — just check the graph for Coins Purchase event:

Coins Purchase event was reported almost 10000 times, that’s huge. But, you know what? In the same time we had 150 IAP sales, it means that in our case 98,5% Coins Purchases events are due to piracy. Not to mention that not all players are visible in Localytics (because we send the events only when a player is playing Anodia and is on a wifi).

We’re probably a little bit guilty here as we’re not doing any kind of receipt validation, but I’m personally shocked by the scale of this problem. It’s a little bit sad too, as that additional income from IAP would make a big difference in going indie full time. Unfortunately it’s still not possible.

If you’re interested in per-country details, here they are:

As you can see China is the biggest IAP consumer (even though it’s one of the few countries where Anodia has a 4.5 star rating instead of a 5). If you are curious how many of those real 150 IAP sales were made in China, here’s your answer: 1. The cheapest of course ;) .

We’ll probably introduce receipt validation sometime soon, but I believe that this should be a little bit more protected by the App Store itself.

I would also like to thank everyone who resisted the urge to pirate the IAP and supported us. Thank you, it really means a lot to us!

BTW, Anodia 2.1 is available and it runs in 60 fps on devices with Retina Display and on all iPads. It’s really nice and smooth, you should check it out.

Living in a 60 FPS world

When we released the first version of Anodia we received a few questions about frame rate in our games. To be honest, our target was to have solid 30 FPS on almost every possible device (unfortunately first and second gen devices tend to be a little slower). It seemed that achieving more FPS would be very complicated, especially as some parts of our framework were not prepared for this (i.e. using frames instead of time deltas).

As a first step we decided to check if it’s worth effort at all. We changed hard-coded FPS from 30 to 60 and I personally was shocked — game was running at double speed, but all menus were perfectly smooth! GUI is completely time based so it was possible to make comparison on two devices.

Our logic was already decoupled from rendering, but it was driven by the same TaskManager class. The tricky part is that TaskManager updates were handled by NSTimer with 1 ms interval. It was time to finally use CADisplayLink and trigger rendering from there. After fixing some bugs in TaskManager and implementation changes in Renderer we were able to get 60 FPS without changing game logic (still updated 30 times per second).

This is when the real fun begins — at this point everything looks the same as in 30 FPS, time to interpolate. Framework required adaptation in GUI, ParticleSystem, FadeIn/FadeOut transitions. Just take value from the previous and the current logic update and do linear interpolation to get value in between.

When framework was ready for 60 FPS, updates in Anodia started — after changing bonus manager (those falling down bonuses) and game objects handling most levels are working perfectly fine. There are only a few that require some manual tweaking. As we were aiming in 30 FPS in the beginning, sometimes performance is a bottleneck, but it seems that this should be not so difficult to fix.

What does this mean for players? Anodia and Hexbee updates are coming soon, including smooth 60 FPS on iPhone/iPod with Retina Display and all generations of iPad. Unfortunately we are not able to test it on iPhone 3GS so no promises for this device.

If you are interested in this topic, Noel posted an interesting article that made our quest to 60 FPS a lot easier.