
                                    Objects
                                    =======

Every moving object in the game (Player, Enemies, Bullets, Otto) is an object.
Each object has a class which defines how it behaves, and an 8 byte data space
which contains its current status.

Why is it done like this ? Well, it makes the game extensible. And if you
are ever unfortunate enough to work developing for Windoze ; this is how
it works (if you lose all the MFC stuff that makes the programs 20 times
bigger !)

These objects are sent messages to make them do things. There is no other way
to access objects. Programs should NOT access the data in the object
record directly (outside the methods).

There is a function OBCreate() which takes the parent object in B and creates a
new object based on that object but of the class in 'C'.

It sets up the default values, most of which are inherited from the parent,
creates a sprite for it and sends the object the OM_OPEN message.

There is another function OBSend() which sends a message C to object B. All
control of the object is done with these functions.

Another function OBDelete() deletes the object (sending it the OM_DESTROY
message).

A final function OBReset() destroys all objects without any method calls
or anything ; it basically initialises the object data record.

It is a convention that during all method execution the object record is
pointed to by IX, and the object ID is kept in B.

Classes
=======
There are 6 Game object Classes and 7 Handlers (including the default one) :-

        CL_PLAYER       Player Class
        CL_DEADPLAYER   Player who has been hit (flashing) class
        CL_BULLET       Bullet Class
        CL_ENEMY        Enemy class
        CL_EXPLOSION    Explosion Class
        CL_OTTO         Otto Class
                
Each of these has a "Handler" which is at address CL_xxxx_HANDLER. There
is also a default handler routine called CL_DEFAULT_HANDLER which
provides default behaviour for the objects.

Object Methods
==============

Object methods are called with IX pointing to the object record, B containing
the ID of the Object, and C containing the method number. Each class has
a method handler.

Methods should preserve all registers EXCEPT "A" which is used to return
values in certain circumstances. The value of A on other methods is
undefined.

Each method (where it exists is labelled) CL_xxxxx_MT_yyyy:

OM_CLOSE                Called just before an object is due to be closed. This
                        can create explosions, increment the score and so on.
                        Default behaviour is do nothing.

OM_COLLIDE              Called when the object collides with the background.
                        Default behaviour calls OM_DESTROY to delete the
                        object.

OM_DESTROY              Call this to destroy an object. Calls its OM_CLOSE
                        method, removes its sprite,and deletes itself. It also
                        checks through the records looking for any children
                        of this object, and orphans them.

OM_EXIT                 Called when the position is set at the edge of the
                        screen (i.e. player has left area)
                                                
OM_GETDIR               Get the direction an object is to be moved in. This is
                        called by OM_MOVE. Default behaviour does nothing.

OM_ISALIVE              Return a non-zero value in A if the object is alive.
                        This *ONLY* works if you haven't created an object
                        after the previous one was destroyed, so it should
                        really only be used straight after OM_MOVE.

OM_MOVE                 Calls OM_GETDIR to get the new direction, OM_SELTILE
                        to set the appropriate tile and then moves object using
                        OM_SETPOS. This can involve further calls to OM_COLLIDE,
                        OM_CLOSE and OM_DESTROY.

OM_OPEN                 Called when an object is first created. All the fields
                        are initialised either with their parents value, or
                        with the appropriate values before this is called.
                        Default behaviour is to do nothing.

OM_SELTILE              Select the appropriate tile for the current
                        direction (direction in D), and set using OM_SETTILE.

OM_SETDIR (D)           Default behaviour sets direction to D, and changes
                        the "LASTX" bit appropriately.
 
OM_SETPOS (D,E)         Default behaviour sets the position of the object, and
                        redraws the sprite. It calls OM_COLLIDE if a collision
                        has occurred between it and another object (and
                        possibly OM_CLOSE then OM_DESTROY), and possibly
                        OM_EXIT if the position is outside the area.

OM_SETTILE (D)          Set the graphic tile for the sprite. Does not redraw
                        it.

Object Data Record
==================

+0  I   Parent ID               $FF : Record Unused, $FE : No Parent (Orphaned)
+1  P   Class ID                ID of class this object belongs to.
+2  I   X                       X Position (sprite units)
+3  I   Y                       Y Position (sprite units)
+4  I   Direction               Y : [Bits 5:3] X : [Bits 2:0] LastXRt : [Bit 7]
+5  I   Speed                   Masked with frame counter ; if zero move
+6  G   Sprite ID               ID of Sprite.
+7  G   User Value              Initialised to $00, but can be object specific.

I       inherited from parent (or the parent ID !), or a default value.
P       Passed as a parameter
G       Generated as part of "new object" function.

