|
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.
|