
                        Berzerk Sprite Engine
                        =====================

Back to normal with a nice and simple sprite engine for my new game, an
implementation of "Berzerk". This uses a 12 byte x 64 rows memory space
to contain the graphics memory ; this is the normal Graphic Workspace
used by a TI-83.

Sprites
=======
+0      Horizontal position (in pixels).
+1      Vertical position (in pixels).
+2      Next Tile to be drawn.
+3      Current Tile drawn. ($FF means "not drawn")

Each sprite either has a four tile sequence produced by cycling the lower
2 bits of the "next tile" ID, or a single tile. The most significant bit
controls whether or not the tile is cycled, or not. (1=Animated).

Sprite positions are centred on the centre of the tile. To convert a
coordinate to a screen address, both coordinates need to have four
subtracted first.

The sprite "moving" routine is as follows :-

function MoveSprite(NewX,NewY)
begin
        Collision := False

        if CurrentTile <> $FF then
                XORDrawSprite at X,Y position.
                If any bits were CLEAR then Collision := True
                CurrentTile := $FF
        end if

        if not Collision then
                if NextTile bit 7 then Rotate 2 LSBs of NextTile
                CurrentTile := NextTile
                X := NewX ; Y := NewY
                XORDrawSprite at X,Y Position.
        end if

        MoveSprite := Collision
end if

Note that the "XORDrawSprite" function clips the sprite accurately for
being off the top, or bottom, of the sprite area.

The core drawing routine (RAWXorDraw) is in RawXor.Z80, the sprite
engine is in Engine.Z80. The CopyToScreen routine used in Berzerk is
a special one which has a 64 byte "invalid" table for each line ;
lines are only copied to the LCD if they have been changed. This makes
it much faster, but functions writing to the display have to remember
to set the flags, otherwise it "won't work".

Engine Functions
================

ENClearScreen()
        Clears the screen completely. Deletes all sprites.

ENCopyScreen()
        Copy the entire screen.

ENAddSprite(A)
        Add a new sprite using tile A. Returns sprite ID in A
        (sprite is positioned off screen, not drawn). Aborts if none
        available (there is space for 128 !!)

ENDelSprite(A)
        Delete sprite whose ID is in A

ENMove(A,B,C)
        Move sprite A to location (B,C), and animate the tile if appropriate.
        Returns Carry Set if a collision has taken place.

ENSetTile(A,B)
        Set the drawing tile to B. If this is an animation the current
        animation position is preserved.

