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.