• interested in more? sign up to the newsletter

     

Android canvas and gamecode tricks

Tweet about this on TwitterShare on RedditShare on Facebook

After my OpenGL adventures people wondered how I managed to have my games run so well on Android Canvas all this time. So here are some of the, possibly obvious, tricks I used.

First trick is using the right drawBitmap calls. Since games usually use a single bitmap for multiple sprites, you need a way to render only the specific part of that bitmap. You can use clipping for this, but that is actually pretty damn slow compared to rendering specified rectangles.

drawBitmap(Bitmap sprite, Rect src, Rect dest, Paint myPaint)  is the call you want to use for rendering the fastest possible images. I usually create a global Rect src = new Rect() at the top of my class file, and reuse that with src.set(x1,y1, x2,y2) to define what part of the bitmap I want to render, and then  dest.set(x1,y1, x2,y2) to tell drawBitmap where to render it to.

Using the Rect objects as global means I don’t have to create and destroy them every time saving a lot of Garbage-collection (another bottleneck for games).  Where ever you can avoid allocating and deallocating objects!  Re-using is the way to go.

Another positive thing of being able to specify the destination rectangle is simple scaling! You could draw the source onto a bigger or smaller destination and Android will take care of simple but fairly fast scaling.

As mentioned above, you want to avoid allocating/deallocating objects in your game cycle. So the second trick (not just for Canvas but for any game) is pre-allocate arrays of objects at the start.  I usually create like 128 “Monster” objects and another 128 “FX” objects.  The objects have a “deleted=true” flag and when I need to add a monster to the game, I simply find the first object in the array with this flag set to true, and call a reinit method setting the default values and, very important, the deleted=false flag so that the update loop will process and render it.

Further more I also do a lot of pre rendering, the one thing that is commonly available on all phones is memory. So my background scenery (in most cases a tilemap) is pre-rendered onto one big bitmap at the start of a level, and after that I only have to draw area’s of that bitmap onto the screen. As you can imagine that is a HUGE speed boost, cause instead of rendering the hundreds of tiles, you now only have to render a single bitmap!

With pre rendering, this also includes any “flipping” or “mirroring” of sprites. In my case I actually draw the sprites in two directions in my bitmaps. Another method would be to pre-flip/mirror the images in code saving some file-size but slightly increasing the initialization of your game.  In any case: don’t flip or mirror images while drawing, it’s a waste of cycles!

Final trick of the top of my head, and this is not usable for all games, but usually I render everything to a bitmap before rendering to the screen like an extra frameBuffer.  Especially for games running in a pixel-art mode, where you basically use a 240×160 screen resolution, this is a very fast method. You can just render everything within the 240×160 screen, and then scale that buffer bitmap onto the canvas to the full screen size.

Bookmark the permalink.
  • I too have been using the set function for drawing rects. It really does cut out some of the GC. I’m glad you posted it because you mainly see the use of cutting a new one each time. Even though I am still baffled from time to time at how the GC acts.

  • storm

    Nice tipps!
    prerendering the whole map onto a single bitmap is a really good idea, and it gave a huge speed boost when i was using bigger maps.

    although drawing bitmaps by Rects sounds pretty good, wouldnt it be faster to prerender each frame and store them all in an array, and upon drawing them just use drawBitmap(Bitmap,x,y,…);? why is drawing using rects so fast, in case you dont need to scale the bitmap?

  • orangepascal

    it would probably be faster having each frame in it’s own Bitmap object.. but it means a lot of file loading, and a lot of extra resources having so many separate bitmap objects in memory.

    the overhead using Rects is probably less then the overhead of having hundreds of images to deal with.

    current day phone’s have no problem rendering at 60fps anyway

  • storm

    alright, thanks for the answer :)

  • Alex van Oostenrijk

    Here are some more tips for speeding up Android canvas.drawBitmap():
    http://www.independent-software.com/android-speeding-up-canvas-drawbitmap/