Demo example:
 This is a somehow more thorough example but it is not yet a game. In this
example various issues are demonstrated including:
 - the clustering grids
 - the extended bounding system
 - the priority lists
 - the use of the timer
 - the (efficient) object oriented approach to game programming

----------------------------------------------------------------------------
Lets start with a description of the classes which are new in this example.

TOscroll class:
 This class tries to keep an object inside the view by scrolling the view
window every time the object is about to get out of the view. Notice that
TOscroll class is completely reusable. The only thing it needs is a pointer
to the object that must be kept in view. Note also that you may have just
one object of TOscroll in your program. There is no meaning in having more
TOscroll objects.

TOcloud class:
 This class represents a cloud that moves horizontally in a specific range
and throws thunders. The thunders are created dynamically and move vertically
until they hit a solid tile and die.

TOguy and TOele class:
TOguy implements the main character of the game. The little guy responds to
key presses and can walk and jump. TOele represents a vertical elevator.
The main character can jump on an elevator and in that case the elevator must
carry the little guy until the latter jumps out of the elevator. 
----------------------------------------------------------------------------

At the start of the main() function the bitmaps of our sprites are loaded
from the disk and inserted to the world by using the functions loadraw() and
TOworld::setbitmap().

Then the world data is loaded via a call to TOworld::loadlevel().
In this example the world is loaded from a WDD file instead of being created
in execution time. Although a WDD file can carry information about the
surface templates ,this particular file (level0.wdd) does not carry such
information, so 2 bounding surfaces are inserted in the world through calls
to TOworld::setsurface() in run time.
Unfortunately a world data description file (WDD) cannot be created easily
because of the lack of a level editor. Perhaps some time a level editor will
be created and become available to the public. You may 'd like to create one
:-)

Next the sprite frame descriptors are created in 2 ways:
- By using TOworld::make1bitmapdescr()
- and by usign the more general TOworld::dprintf()

After that the objects are initialized and inserted to the world and then
the VESA 2.00 system is initialized and queried about the available modes.

Finally the timer and the keyboard handler are initialized, a clustering
grid is created and TOworld::animate() is called.
----------------------------------------------------------------------------

There are some interesting things concerning some of the objects.

First we want the C1997 sprite to be displayed over all the rest sprites and
have a fixed position on the screen even if the view scrolls. To achieve that
we must take advantage of the useful characteristics of the priority lists.

Notice that the scroll object (scrollobj) is put in priority list 0 and the
C1997 object is put in priority list 9. The rest sprites are put in priorities
lists 0..8
The C1997 has an action function that always moves the logo to position
(TOworld::x+ (constant1), TOworld::y + (constant2)) So we can be sure that
the C1997 logo will be drawn over all sprites, because it belongs to list 9,
and have a fixed position on the screen, because scrolling is always performed
before the action function of C1997 has been called and so (TOworld::x,
TOworld::y) does not change in a particular frame.

----------------------------------------------------------------------------

Note the use of a sprite range for the cloud object number 0. A sprite range
is set and activated via a call to TOobject::setrange(). A range is nothing
more than a box. The active action function of cloud 0 will be called by the
game engine only if the view window intersects that box.
The sprite ranges can be used to decrease the amount of function calls and
proccesing. In most cases the active action functions of the objects have
to be called only when the view is near the object. In the other cases the
function call would be just a waste of time.
----------------------------------------------------------------------------

In this a example we use a clustering grid to perform collision detection of
the main character against the thunders. When the little guy intersects a
thunder then the color of the thunders cycles.

When we created the grid by calling TOworld::definegridlists() we defined
that the grid will cluster objects from object list 4 only. If you take a
look at cloud.cc, cloudgo() you will see that every new thunder is put in
object list 4.

The little guy in guyele.cc, generalaction() checks for collision by simply
calling TOworld::gridcollision()
----------------------------------------------------------------------------

The movement of the guy is restricted by the bounding system. The use of the
corresponding functions TOworld::howfarXX() is demonstrated in guyele.cc
Every time the guy wants to move towards a direction first queries the
bounding system by calling one of TOworld::howfarXX(). Each one of these
functions returns how many pixels actually the guy can move without getting
out of the bounds. Then the guy uses that value to arrange its movement.
----------------------------------------------------------------------------

BETATRON may work in a lot of different video modes. Not all video modes
have the same retrace period. Some of the them have fast cycle while other
have slow cycle. Because of that, in order to retain a steady animation speed
you have to use the TOworld built-in timer. The built-in timer runs at a
stable frequency and so it is ideal for time measurements.

In this example the timer is used to adjust the animation of the main character
and some other objects too.
Generally there are 2 ways to use the timer in order to simulate physical
movements:
1. Keep changing the position of an object in fixed steps for a fixed
   number of times. For example, keep increasing the x-coordinate of a
   bullet 10 times by 2 pixels each time. It must be obvious that the bullet
   will move 20 pixels. However in order to have the bullet accelerated or
   decelerated you must not increase it's x-coordinate at equal time spaces.
   Increase the time space if you want the bullet to slow down and decrease
   it if you want the bullet to speed up.
   This way should be always used, if you want to control exactly how far
   an object will move. For example when the little guy jumps, we would like
   it to move up a fixed number of pixels. However in this example i have used
   the second way to make the little guy jump.

2. Keep changing the position of an object every frame in some (non-fixed)
   steps for a fixed period of time. This method has the effect that the
   amount of the object's movement will vary depending on the (measured)
   time between two consecutive frames. For example, if TOworld::retraceticks
   becomes smaller then the object will move further. Try to set a smaller
   value for TOworld::retraceticks (after calling TOworld::inittimer() ) and
   watch the little guy jumping higher.











