PalmOS Warp 0.5: Technical stuff

Below is a sketch that explains the basic techniques behind the scrolling background.

I have two Bitmap objects, marked "1" and "2", and outlined with a green and blue border, respectively. They are 160x144 pixels in size and get drawn onto the visible region (outlined with a red border) every screen update. Each time I draw them a little bit further to the left, until one is completely outside. Then I move it back all the way to the right.

I keep track of which parts are visible and draw new building blocks on the Bitmap object that currently holds a vertical block line which will soon be scrolled into view (denoted by a purple arrow). This is a special technique in itself, since the KVM Java for PalmOS doesn't allow you to draw directly onto Bitmap objects. But you can manipulate them by treating them as arrays of 16-bit data and simply changing the entries, one by one, to new values. This is very processor-intense on the Palm, but I only need to change between 16 and 32 entries per scroll step, so the workload is managable. I keep a special array of 16-bit values corresponding to various building block objects, from which I simply copy data to the Bitmap arrays using a FOR loop.

Here is an example of a KVM Java Bitmap constructor call and what the image looks like:

Bitmap life = new Bitmap(new short[] { // Life indicator
15, 15, 2, 0, 0, 0, 0, 0,
4032, 4400, 8462, 16642, 16670, -31788, -31532, -31276,
-30764, -31788, 16670, 20802, 11182, 5488, 4032 });

The constructor builds the Bitmap out of a 16-bit word array, where the first 8 entries contain the header information (height, width, etc.) and the rest are the pixels (rounded up to the nearest 16 bits for each row) in reading order. What's interesting is that the system refers to this data directly, so if you modify it the changes will be seen immediately the next time the image is drawn. There is no need to call the constructor again.

The same approach to draw mobile objects would not have worked. I tried it in an early, discarded version of PalmOS Iceblox, but it was way too slow. The technique I used for drawing the flames, however, was very handy.

In a game like Warp, pixel transparency is essential. The background is highly complex and has to work together with non-rectangular mobile objects. Since the KVM doesn't support transparency, the only way to achieve this is to do two drawing operations, with different image data -- one OR operation to set the black pixels and one AND operation to clear the "white" pixels. The KVM can only do OR/AND when moving data between the onscreen and offscreen image buffers. This is fine in the Warp case, since I don't need the offscreen buffer for anything else. While the game is running, that buffer looks like this:

If I want to draw, for example, the main spaceship, I OR the 19x20-pixel data block starting at co-ordinates (19,0) onto its destination, on the scrolling background drawn just before. Then I AND the 16x16-pixel block starting at (0,73) onto the same spot. Doing it in the reverse order would work too, but I figured that the black pixels are more important (and have to be drawn first, so that they get to be visible the longest time before the next screen update).

People who take a close look at the source code will notice that I'm occasionally using XOR operations as well. Those are for the bullets, which have to be fully visible against all backgrounds. But I'm compromising a little. Every other screen update I do an ordinary AND (i.e. I draw them completely white).

Unfortunately, the KVM is not fully compatible with older system versions. You need at least PalmOS 3.5 (or possibly 3.3?) installed on your handheld device for the "transparency" trick to work. Otherwise some objects may not show up at all. This isn't too much of a problem for Palm owners, but some of the cheaper clones, like the Handspring Visor, lack system upgrade capability.