<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Fri, 18 Oct 2002 12:36:09 +0100
From   : Richard_Talbot-Watkins@...
Subject: Re: Software sprites

james watson <james@...> wrote:

> How do games like firetrack and especially galaforce which has about
> ten large software sprites of 16/16 on the screen moving very fast with
> out any flicking. I have a routine which is taken out of the micro user
> from a series called how to write arcade games, written by Kevin Edwards
> from 1985. The routine uses zero page locations for variables and direct
> screen addressing. I have adapted it so the sprite print routine is
> called under a interrupt right at the start of vertical synchronisation.
> so you don't get any flicker at the top. But even with this i can only
> get 4 or 5 small  sprites about 10/8 to move about most of the screen
> without any flicker. Has anybody a faster sprite print routine or can
> anybody advise on how to get better results.

The trick with flicker-free sprites is to ensure that:

1) The erase/redraw does not happen whilst that part of screen is being
   rasterised, as this would possibly lead to parts of the sprite
   disappearing or "tearing";
2) The time gap between erase and redraw is as small as possible;
3) You don't over-indulge in numbers of sprites for your preferred frame
   rate - there's obviously only so much the machine can deal with.  You
   need to accept that if you want it to run (for example) in 1 frame
   (50Hz), that there's going to be a limit on how many sprites you can
   display.  Running at a lower frame rate allows for more ambitious
   specs, but also would probably require a slightly different approach to
   guarantee minimal flicker.

Taking each point in turn then....

1)

We need to ensure that we avoid rasterising at a point on the screen where
a sprite is being plotted.  The trick, obviously, is to use the time after
the main game window has been rasterised to update the main game window!
Waiting for VSync is not going to give us our best results as that will
only give us 3 character rows' time worth of flyback (3072 clock cycles)
before we're back to rasterising the main game window, at which point we're
competing with the TV rasterisation at a rate of 1024 clock cycles per
character row.

The best thing is to have a VIA timer interrupting at the moment we hit the
bottom of the game window (if you are using the rupture technique to
provide a smooth scroll, with some status at the bottom, you probably
already have an interrupt happening here anyway).  In the game I started to
write, this gave me 19 character rows before the screen rasterisation
started again, which was clearly much better.  I figured I could also make
use of the time *during* rasterisation with a bit of cunning, by sorting
all the sprites by vertical position before plotting them.  If you plot the
vertically highest sprites first, this buys you a bit more time in order to
plot the ones further down.

2)

Erase/redraw...  There are better and worse ways of doing this:

Simplest way is EOR-plotting.  Advantages are that it's easy to write, you
can use the same routine to plot and unplot, and it doesn't matter what
order you plot/unplot all your sprites in.  This means you can do an unplot
followed directly afterwards by a plot in the new position, which fulfils
the criterion of there being as little time as possible between the two.
Disadvantages of this method are that it looks a bit crap, and (more
subtlely) that you immediately double your sprite plotting time by using
the same routine to unplot it as to plot it.  It ought to be possible to
erase a sprite a little more quickly than it is to plot it.....

Next way is to do a proper masked sprite plot.  This looks visually *much*
better, but comes with its trials - unplotting the sprite (i.e. restoring
the background) is more involved, but two methods spring to mind:

a) Unplotting could be done by simply using your background plotting
   routines to replot the background over the top (could be quite
   intensive), or,

b) if you have the memory space, getting the sprite plotter to take a copy
   of the background as it plots, and then just blatting this saved copy
   back over the top in order to literally restore what was there before.

The problems arise when two sprites overlap - it would be easy to end up
with the unplotting code writing over an overlapping sprite which had been
previously plotted if we weren't careful.  If method (a) is used, it is
pretty much essential (unless you can guarantee that no sprites will
overlap), that *all* the unplotting happens in one block, followed straight
afterwards by *all* the plotting in the new positions.  If the unplotting
is so quick that we can still beat the TV raster position as we replot all
the sprites, then this isn't a problem.

If method (b) is used, we still have the option to unplot everything in
batch, followed by plotting everything afterwards.  However, with method
(b), it'd also be possible to do an adjacent unplot/plot per sprite
provided each update we reverse the order we plot all the sprites in -
this would ensure that we restored pieces of overlapping sprites correctly
as the "copy to buffer" technique would capture pieces of overlapping
sprite which had been already plotted ot the screen.  [I'll explain this
better if it makes no sense].  Of course, this method loses us the ability
to sort the sprites first to buy us more time during plotting.

3)

Knowing our limits....  Obviously, the first thing is to ensure we have as
fast a sprite routine as possible.  If the sprites need only move in
character row blocks, it is best to write a simple memory copy routine
which does little clever.... it's even advantageous to repeat code like

     LDA (screen),Y
     AND (mask),Y
     EOR (sprite),Y
     STA (screen),Y
     INY

as many times as it needs to loop, rather than branching every time round,
as this can make a significant difference to performance.  (Remember a
taken branch is 3 clock cycles... if the sprite is 128 bytes big, that's
384 clock cycles... if you have 10 sprites, that's nearly 4 character rows'
worth of rasterisation time we can get back!)

This is the quickest type of sprite routine there is... if it's at all
possible to engineer your graphics so that the sprites move sub-8-pixel
vertical amounts purely by offseting the animation frames by different
vertical amounts, so you can still plot them using a character row block
plotter, this is also a good thing!

Note that it's also desirable to have your sprite unplotter (background
restorer) using this type of routine.

If you need a "proper" (slower) sprite plotter that can plot at any
vertical line, then so be it... I had a very fast sprite plotter of this
type which lived in the zero page for additional speed - it was kinda
difficult to use (required a reasonable bit of thinking to set up its
entry parameters) but I'm sure was the best solution for the job.  If I
dig out my old Beeb sometime, I could try sending you a copy of it.  I
have to admit, I really don't remember how it worked at the moment!

As I mentioned, if you want lots of sprites and decide you have to lower
your frame rate, then I'd suggest that it's best to be in complete control
of what gets plotted where, and ensure that you keep the frame rate locked
to 25Hz - split the task evenly between the two frames, doing one half of
the sprites in the first frame, and the other half in the second.  If you
rely on the "sorting" method, my trick would be to take every other sprite
in the first frame, and do the remaining ones in the second.

Hope any of that's of help - these were the main issues I came across when
writing a game, so I'm guessing I probably wasn't the only one...

Cheers,
Rich
--
Rich Talbot-Watkins
SCEE Cambridge
Richard_Talbot-Watkins@...     




**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
postmaster@...     

This footnote also confirms that this email message has been checked
for all known viruses.

**********************************************************************
 SCEE 2002
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>