Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Sunday, August 18, 2013

Developing 3d game for Android - part 2

Well, it is done!

I finished version 1.0 of my 3D space arcade game based on  Rajawali framework and published it on  Google Play.

You can check it out here: https://play.google.com/store/apps/details?id=com.mabuga.gravity.android.before4&hl=en

And here is gameplay video on youtube:





I enjoyed developing with Rajawali, it was very fun and the issues I run into were not critical.
Issue that I spent most time dealing with is rendering explosions. I wanted to use simple animated sprites for explosions and Rajawali supports that via Particle primitive. Basically, you set spritesheet texture to a Particle, define how many tiles spritesheet has, and Rajawali shader will render the particle using given spritesheet creating animation from it's tiles.

What I wanted is just one big animated sprite to render explosion. And that was where the problem appears - the size of single particle.  Actually there are two problems related to particle size.

1. There is a bug in Particle code that is causing particle look smaller as as the distance from world origin gets bigger, regardless of camera position.

2. Particle is rendered as textured point and unfortunately OpenGL implementations limit the size of the rendered point. Even worse, different implementation has different values for point size limit. OpenGL specification doesn't guarantee point size bigger then 1 px.

My workaround for first problem was to update particle code (GL shader and java) to fit my needs. Unfortunately, my solution did not solve the bug in generic way (since the problem is not just bug in calculation but conceptual as well) so I could not commit it back to the project.

Second problem actually can not be really solved since it it hardware specific, so I just accepted imposed point size limit. Quick test on few devices I own showed me that point size limit is around 100 px on my HTC Explorer with 480x320 px screen and around 500 px on my Samsung Galaxy Tab 2 with 1280x800 px screen. That was ok for my explosions, however, there are probably devices with big screen and small point size limit and my explosions probably look bad on those.

Also, I experienced some weird rendering issues when returning from RajawaliActivity with RajawaliRendered to normal Activity, but that was solved by setting android:hardwareAccellerated to false on activity elements in android manifest.

So, there were actually very few problems with Rajawali framework.
Besides the issues, I would like to share some thoughts about challenges of optimizing the game for low CPU powered devices.

Crucial part of almost any game is collision detection. Rajawali already has built in collision detection features, but checking collisions too often can have significant CPU cost causing glitches in gameplay.
In every frame (about 30 times per second) we have to check collision of every moving object with all other objects on the scene. Let's say that we have 30 moving objects (ships + bullets) and about 20 - 30 static objects (meteors) on the scene at the same time, this means we have to handle ~ 30 * 50 = 1500 checks per frame which makes 45 000 per second. And that's a lot.
In order to minimize number of collision checks per frame, I divided game space into "sectors". For static objects I only calculate in which sector they are in game init phase, and for moving objects I had to calculate in which sector they are every time they move.
Also, I added global sector map that maps sector name to a list of objects currently in that sector. This map is also updated on every object sector calculation.
So, now for every moving object we only need to check collisions with objects currently in same sector , and this is usually 0-5 objects. This reduces CPU usage big time. This way number of collision checks doesn't increase at all if we add more static (non moving) objects.

Another thing I optimized in order to achieve better game performance is to handle object creation little bit smarter then just create them when ever I need them. Actually, I recycle them.
Whenever new bullet is fired or new ship should appear, it should be added to scene, and whenever ship is destroyed or bullet hits something, it should be removed from the scene.  But adding and removing new objects can also be costly, especially if it happens often. If we instantiate new bullet every time ship fires, we spend CPU cycles on initiation of the bullet. After that we have to add it to a scene (renderer), and this also takes some CPU time since renderer must register new object to it's list of objects in synchronized way. Rajawally uses synchronized "copy on write" list for this purpose.

So, instead of creating and destroying new objects all the time, I used well known technique called "object pooling" . It boils down to creating certain number of objects and store them in a pool (a list or a map) , then take it from that pool when we need new object and return it when the object should be destroyed/removed.
In my case, I had two different pools, one for bullets, another for explosions. Using two pools for specific object types instead using one generic pool also makes things faster since we don't have to do any type checking.
If new object is required and the pool is empty, we simple create new object and add it to the pool, so our pool will grow depending on demands.

When object need to be removed from the scene, I don't actually remove it, I just hide it by setting visibility to false and by setting its position far out of the camera view. I also remove it from my internal list of movable objects, so I don't move it or check collisions for it while it is in the pool (kind of object passivation).

When taken from the pool, object is set to visible, its position/rotation is updated as needed, and it is added to movable objects list, so it can be managed by game logic (moving and collision checking).
And that's it. Simple, but effective.

OpenGL handles rendering in most optimized way it can, and besides the few tricks described above there are several other things developer can do to make the game run smooth:
- use low poly 3D models
- keep number of objects on the scene as low as you can
- keep objects static (non movable) whenever possible

I covered some basic and common things related to game optimization, but every game is specific and it has specific things that can be optimized.

Sunday, June 23, 2013

Developing android apps with Kotlin

For those who haven't heard yet, Kotlin is new JVM language developed by JetBrains, creators of IntelliJ IDEA, which many people consider the best java IDE.

Kotlin is still in development, beta should be released in following months, according to Kotlin forum, but it is already stable enough to do some real work in it.

Being java programmer for a long time, I always liked it for simplicity of the language itself, stability, large ecosystem of frameworks and libraries, cross-platform support etc...

But sometimes I missed few things that other languages have and Java doesn't.  Mostly things that would boost my productivity and make me write less code that is still elegant and readable.

One of those things is passing a function as an argument to another function (feature known as higher order functions or closures).  Writing listeners every time you need to use some kind of callback function can be really tedious. If you can pass callback function as an argument to another function/method it can really save time and lines of code. Javascript and Actionscript, languages that I used for some client side development, and that I considered inferior to java in many ways , have this for a long time.
Kotlin, as almost every other modern language has this feature.

Another thing that can save code and time is having default values of method arguments, so passing those arguments can be omitted in method call. This reduces, if not removes, the need for method overloading since it is more flexible way of having different combinations of arguments. 
I liked this feature in ActionScript , but Kotlin goes one step further: it supports default argument values, but it also supports passing arguments by name. This means, for example,  that you can pass only first and fourth argument, skipping second and third if they have default values. In action script if you want to pass forth argument you also need to pass all arguments before it.

There are lots of other features that make Kotlin code shorter and more elegant then Java code. 

Elegance and ease of use is not  Kotlin's only advantage over Java,   there are also features that make Kotlin more powerful, although with greater power comes more responsibility so in general it requires programmer to be more careful. 
To mention just few of them: null-safety, immutability, extension functions, lambdas, inline functions, operator overloading, range expressions... etc.
To see full list of Kotlin features check out docs page and  don't miss comparison to Java.

Many modern languages have very similar feature list like Kotlin: Java 8, Scala, Ceylon, Clojure (clojure is little bit different animal since it's Lisp dialect). So why to choose Kotlin?

For Java programmer Kotlin should be the easiest to switch to (except of course Java 8), since one of main goals of Kotlin is to be Java-compatible. This means that Kotlin should provide much better interoperability with Java then Scala, Clojure, Ceylon... 
Also, Kotlin compiles as fast as java , that is another goal of Kotlin authors.

Scala is Kotlin's main competitor so it is good to know what are similarities and differences between them.

Since Android apps run on Java and Kotlin is highly interoperable with Java it is possible to write android apps using Kotlin.

Here are some useful links on how to start with it:



For now, using IntelliJ IDEA is the easiest way to develop with Kotlin. 

I look forward to make myself more familiar with Kotlin using it on my new android app and I will share my experience here soon.








Friday, January 25, 2013

How much memory do images in android apps really use?

Recently I had some OutOfMemory issues in one my apps.
After analyzing logcat I could see that one image used as background is taking more then 2MB even though the image in png format was less then 200KB.

At the first look it was confusing, but it is actually only logical when you make yourself think about it little bit more.
Image size in compressed format such as (jpg,png) is one thing , and Bitmap decoded from it and used for actually drawing on screen is something completely different.

After quick research I found exact formula to calculate memory required for bitmap.

Memory required by bitmap image depends on image dimensions and bitmap type.

M =  WIDTH * HEIGHT * 4    (for ARGB_8888 Bitmap -  if you need transparency)
M =  WIDTH * HEIGHT * 2    (for RGB_565 Bitmap - no transparency)

where result M is in bytes and WIDTH and HEIGHT are in pixels.

So using few large images as backgrounds in your layouts can quickly lead to OutOfMemory exception on devices with low memory per app limit.

Tuesday, October 2, 2012

Can android app be protected from piracy?

If you are android developer , you know how much skill, effort, creativity and innovation is required to make competitive android application.

After investing your knowledge, creativity and time, you probably don't want your app to be copied, repackaged, and sold by unauthorized parties.

So, what can we do to protect our work?

There are many methods,like those suggested in this presentation, that could be used for this purpose.
Unfortunately, there are tools available that allow people to crack many of this protection methods, even people with very little or no knowledge at all of android development and java programming in general.

In my apps , I use simple technique that can be described in one sentence.
Check if app was tampered with, and if so, make it stop working properly.

I prefer this method since it doesn't require connection to google market server or any other server on the  net.

Checking the signature is trivial, but it will not be of much use if the attacker can easy find the part of your code that does the checking and remove it.
So the hardest part of protecting application this way is to hide the code that does the checking best we can.

Using obfuscator is basic stuff, so we use it as a first line of defence. It will make decompiled code very hard to read and to follow program flow. The problem is that attacker doesn't actually need to understand how your app works in general, he just needs to find your protection and disable it.
Since all methods for checking app authenticity (signature checking that we use is one of these methods) are well known, attacker will probably focus on finding them in your code. Obfuscated code will rename your variables and methods to some meaningless names, throw in bunch of junk stuff etc., but calls to android framework methods will remain unchanged and easy to find in decompiled code.

Here is an example of the code for getting app signature:

Signature[] myAppSignatures = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES).signatures;

More advanced obfuscators such as Dexguard can help hiding this code by using reflection to call getPackageInfo method instead of directly calling this. You also want to encrypt method name strings like "getPackageInfo" so that attacker can not simply search decompiled code for it.
Dexguard even comes with configuration template that already contains settings for doing this, you only need to uncomment few lines to use it.

After using reflection in combination with string encryption it is very hard for attacker to find this method call in decompiled code.

However, this level of protection is still not good enough. Why?
Because  tools like anti-lvl intercept getPackageInfo() method even if you use reflection with encrypted strings.

It  does it by replacing all method.invoke(...) calls with it's own code (hook) that checks method name after the method object is already initiated. If method name equals "getPackageInfo" hook returns PackageInfo with fake signatures (your original signatures instead of repackaged app signature). Otherwise, if the method is not relevant for checking app authenticity, hook will just call method.invoke method as you originally intended.

Can we do something about this?

We can encrypt whole class instead of only encrypting string used for method invocation via reflection. With encryption applied,  Method.invoke(...) calls become invisible for cracking tool so it can not replace it with hook.
So, encrypting the class containing signature checking will stop anti-lvl tool (current version at least) to crack the app.

You should be aware of the fact that  encrypted classes can be decrypted, actually intercepted after decryption, but as far as I know anti-lvl doesn't yet do that.

This means that with some additional manual work of decrypting classes before applying anti-lvl, signature checking method still can be cracked.