Blackberry Programming: Increasing Video Speed Through Prerendering

As I finishing up the full version of Galactic Blast (screenshots on this soon, its a fully fleshed out game inspired by the demo, to be released on App World) – I ran into an issue in a strange area. The animation was smooth throughout the game, except oddly enough, on the instructions screen.

The instructions screen in Galactic Blast includes some text describing the storyline, some text describing the keyboard controls, bitmaps showing each of the enemies and power ups with description text, and some credits at the end. Since there’s much more than can fit on a single screen, the user can scroll up and down – nothing fancy, just your basic instructions screen. However, the scrolling was anything but smooth. As I debugged more, I found out that redrawing all the bitmaps and text at each scroll was simply taking too long – all the function and helper calls involved in rendering everything was just too much for the processor.

The Solution

As I thought more about it, I realized that it would be much better to simply render one item instead of 20-30 items each time. And since instructions are static in nature (they don’t change or animate), it was a prime candidate for prerendering all the text and bitmaps to a single, big bitmap. However, I wanted the program to prerender the items automatically at runtime – I didn’t want to have to create the bitmap manually (which would be a huge pain anytime I needed to edit something – like adding a new line of text in). The code below achieves this by creating a bitmap in memory and rendering all the desired text/images to it at the start of the program, and then simply displays (and scrolls) this bitmap on the instructions screen.

The Code

I’ve removed the specific text, bitmaps, and positioning from the code to make things a little clearer:

// _instructionsBM is the large bitmap we will be rendering all our text
// and images to. This is the bitmap we will actually
// display on the instructions screen, thereby increasing efficiency
// since we're only redrawing one bitmap each time the
// player scrolls instead of a bunch of bitmaps.
private static Bitmap _instructionsBM;
public static void prerenderInstructions() {
Graphics tempGraphics;
String objectiveString;
Bitmap tempBitmap;
Object castArray[][];
// Populate a string with the objective of the game
objectiveString = "Text describing the objective of the game ";
// Populate an array with the enemy bitmaps, their names,
// and how many points they are
castArray = new Object[2][];
castArray[0] = new Object[] { enemyBitmap1, "Enemy 1", "50 Points" };
castArray[1] = new Object[] { enemyBitmap2, "Enemy 2", "75 Points" };
// Initialize the bitmap, and then give it an alpha channel for
// transparency, allowing the background to show through
// behind the text and bitmaps
_instructionsBM = new Bitmap(Bitmap.ROWWISE_16BIT_COLOR, WIDTH, HEIGHT);
_instructionsBM.createAlpha(Bitmap.ALPHA_BITDEPTH_8BPP);
// Start with a blank, completely transparent image
_instructionsBM.setARGB(new int[_instructionsBM.getWidth()*_instructionsBM.getHeight()], 0,
_instructionsBM.getWidth(), 0, 0,
_instructionsBM.getWidth(), _instructionsBM.getHeight());
// The Graphics object acts a surface that drawing operations
// can be performed on. By calling the Graphics constructor
// with the bitmap as an argument, all drawing operations
// will be performed upon the bitmap itself.
tempGraphics = new Graphics(_instructionsBM);
// All operations to follow will be fully opaque (so pixels not
//acted upon will stay transparent, while any text/images drawn
// will be solid.
tempGraphics.setGlobalAlpha(255);
// Draw the text onto the bitmap
tempGraphics.setColor(Color.YELLOW);
tempGraphics.drawText(objectiveString, 5, 5);
// Draw enemy bitmaps onto the bitmap
for (int lcv = 0 ; lcv < castArray.length ; lcv++) {
tempBitmap = (Bitmap) castArray[lcv][0];
tempGraphics.drawBitmap(Utils.getDimension(5, 50+lcv*50,
tempBitmap.getWidth(), tempBitmap.getHeight(), tempBitmap, 0, 0);
tempGraphics.drawText((String) castArray[lcv][1], 100, 50+lcv*50);
tempGraphics.drawText((String) castArray[lcv][1], 200, 50+lcv*50);
}
}