Urbanoids: Technical stuff

The inexpensive vertical scrolling technique I used in Warp 1.5 only works when the screen moves in just one dimension. It can't be used for scrolling both horizontally and vertically, so I had to think up something else.

Not that scrolling in itself is particularly complicated. It's not, as long as you have plenty of processor power to spare. But this was for a Java game and then conservation of resources was essential. Otherwise I'd have to scrap my ambitions making it run tolerably fast on low-end machines.

As usual, I knew I needed two screen buffers -- one to hold the background and another to which the contents of the first buffer can be copied and have mobile objects added, before the whole thing is drawn on the screen. The first buffer would have to be shifted around a lot, but then I'd have to spend almost twice as much processor time on moving pixels as in my other games, where only marginal changes are made to the first buffer.

Eventually I came up with this algorithm:

The schematic illustrates the process of scrolling the screen one block unit to the right. In the game, the playing area (the same size as the second buffer) is 240x240 pixels, which can be thought of as 10x10 building blocks of 24x24 pixels each. Here the second buffer (the bottom row) is only 6x6 blocks for clarity.

The top row shows the first buffer, which has an extra "frame" of blocks. Now, my idea was to only scroll part of that buffer per animation cycle. In the game, scrolling is done 6 pixels at a time, which means that it takes 4 cycles to move one full block in any direction. Ideally, it should be possible to split the work into 4 parts and only do one per cycle. And it is possible.

It's not necessary for the first buffer to hold a perfectly aligned version of the background, provided the contents are put together correctly when they are copied to the second buffer. In each step I only scroll 25% of the first buffer (indicated by the brackets), but in steps 2-4 I copy the pixels to the second buffer as two separate segments (the outlined parts). The net result is, as you can see, that the background appears to be scrolling smoothly.

There's one heck of a lot of numbers and directions to keep track of, though. In the game I use several tables of pre-computed size and co-ordinate data.

For the quickest possible transfer of pixels, I'm using copyArea to do the updating of both buffers. This means I need to keep everything in a single Image object. To the left you can see how I've organized it.

The image is 528x432 pixels and basically consists of three fields: A) the second background buffer which holds the applet screen content that the user finally sees (including a place to draw the score and energy meter), B) the first background buffer and C) all the building blocks that are used to construct the scenery. Right below field A there is also a set of robot model numbers that will get copied onto the corresponding droids, and a "full" energy meter.

Regarding the control of the main character, I wanted Urbanoids to be less block-oriented than my other bird's-eye view games Iceblox and Adios, Amoebas!, where you can only move from the middle of one block to another. But that can cause a problem in Java, where you have to use a keyboard rather than an 8-way joystick and there are only about a dozen animation frames per second. The control becomes sluggish and it's difficult to get through narrow passages where you need to be perfectly aligned with the block pattern anyway.

I solved it by building some "intelligence" into the character. If the player wants to move forward along a basically open path but Erwin is misaligned by a few pixels so that he can't quite get past an obstacle, the program senses this and makes him take a sideways step before moving on. This is something I would definitely recommend other Java game programmers to try. It makes games of this type a lot less frustrating to play.