BlackBerry’s two Graphics implementations: Can you use them both? In the same App?
When I first started programming for BlackBerry, one of the things that struck me as most odd was the two completely independent graphics APIs. For MIDlets, there’s javax.microedition.lcdui.Graphics, and for RIM’s own profile, there’s net.rim.device.api.ui.Graphics. The two versions are so similar to one another that — if you’re careful — you can write a game that can use either of the two graphics APIs interchangeably, just by swapping out the include statements (and using a different set of lifecycle classes). That’s what I illustrated in Chapter 3 of my book.
But I wondered: What if I want to use the javax.microedition.lcdui.game package? But I still want to take advantage of RIM’s proprietary UI component handling? Is that even possible? Note that you can’t just place an LCDUI Sprite onto a RIM Screen or use lcdui Images interchangeably with RIM Images. Yet, there’s nothing to stop you from instantiating many of the lcdui graphics-related classes in a RIMlet — either type of application has access to the whole API.
Through experimentation, I found that it’s quite possible to take a game that was written using lcdui game Layers and run it in a RIMlet. The trick is the following: To paint the Layer, call the paint() method yourself (instead of supposing the platform will do it). First create a mutable (lcdui) Image, get its Graphics instance, and send it to the Layer’s paint() method (to render the layer into an Image buffer). As I said, this Image can’t be placed directly into a RIM UI Component or Container, but its underlying RGB data array has the same format/structure as a RIM Bitmap. So you can use getRGB() to get the data, then use setARGB() to place the data into a Bitmap. Note that — despite the method name — the lcdui data array also includes the alpha channel, along with the red-green-blue. (To see a working example, look at the ImageTransfer class in this sample code bundle.)
Now, you’re probably asking: “Wow, isn’t that incredibly inefficient? Is it making a copy of the entire screen data array for every frame of your game (typically 20 per second)? Wouldn’t it be simpler just to re-implement the parts of the lcdui API that you want to use for your game?” The answers are yes, yes, and yes. In Chapters 6 and 9 my co-author and I simply re-implemented the features we needed from the lcdui Sprite class. (For more recent models, RIM has re-implemented the lcdui.game classes for you.)
Still, it turned out that it wasn’t quite as inefficient as I expected. For fun, I wrote a bunch of different versions of a rocketship in space game — using a bunch of different techniques — and compared their memory consumption using the BlackBerry JDE debugger. Here‘s the code bundle of my experiment, comparing an lcdui game implementation to a pure RIM proprietary implementation (plus I threw in an SVG implementation as well).