Tube: Technical stuff
Tube was a lot less complicated to build than most of my other recent games.
It is roughly on par with Don's Dugout or
Adios, Amoebas!, which is not to say it was
Normally in a game like this you
would use a 2D array to internally represent the playing field -- in our
case with a block size of 24x24 pixels. But that won't work for Tube, because
the pipe overlaps itself in some places, so the playing field essentially gets
a third dimension. Although it might be possible to use a 3D array instead,
it is far more efficient to represent the tube with some sort of linked list.
Each element in that list represents a block and can have a maximum of
four neighbors -- above, below, to the right and to the left. I also let the
list contain information about the screen co-ordinates of the block, whether
it is obscured and where its nuts and bolts are, if it has any.
You may have noticed some elements of artificial intelligence in the game.
To be more precise,
Starting with the last one, I achieve that by assigning an integer to each
block of the maze. First I give both the exit tubes the value 0. Then I
give their immediate neighbors the value 1. Then I find all their
neighbors that haven't been numbered yet and give them the value 2, and
so on. The image to the right illustrates this.
- the monsters following the player around,
- scared monsters avoiding the player,
- zapped monsters finding the quickest path to the exit.
In order to get to the exit, the monsters just need to keep track of which
block they are located at and move to the neighboring block that has the
lowest number. (The numbering is done before a level starts, so it doesn't
slow the game down.) I keep a similar number for each cell telling how
far it is from the player's current location, but not for the entire maze --
just within, say, 15 blocks. That saves a bit of time. Scared monsters
obviously try to get to the neighboring block with the highest
player distance number.
Only the red and green monsters actually chase the player. The blue ones
are more harmless in that sense and just follow a simple rule: pick any
available direction at random, except back to where you came from,
unless there is no other way. It works pretty well and even gives the
illusion of purpose.
Mobile objects going under pipes or into covered segments took a bit of
extra work that wouldn't have been necessary if only the "clipping rectangle"
functionality of Java had been fully reliable. Instead, I had to do the
||First I copy a square portion the same size as the
mobile object to
an offscreen place, using the copyArea method.
||Having determined how much of the object is supposed
obscured, I draw the entire object on the offscreen portion and only
copy back the part that should be visible.
To save some time, I skip that three-step procedure when the object is either
fully visible or fully obscured. Then I either draw the object directly
on the playing area or not at all. Those situations make up the
vast majority, so very few extra graphics operations need to be performed
during an average animation frame.