QuickBASIC/QBASIC newsletter

 
Tricks of the Trade
by Richard Russo
 

      Many QB programmers rely on assembly language libraries to
create performance graphics.  Don't get me wrong, I am in no way
degrading that.  I think assembly is good for the QB community in
making QB programs more powerful; however, somewhere out there
on the Net there is someone like me, who, by a matter of principle,
likes to program in pure BASIC [sometimes].  If you are one of these
people, and you've done a fair amount of graphics programming, I'm
sure you've written code similar to this before because it is faster
than good ol' PSET:

DEF SEG = &HA000
POKE x% + 320& * y%, clr%

Well, I'm going to go over one particular graphics trick that can be
accomplished fairly easily in QB, and that is double-buffering
graphics.

Double buffering is a concept that I guess is as old as computer
graphics.  It is a technique designed to eliminate an undesirable
graphics phenomenon referred to as flickering, or flashing.  It
happens when a picture is drawn on the screen, erased, and a new
picture is drawn in its place quickly to achieve the effect of
animation.

A theoretical way to solve this problem is to not draw directly to the
screen but to somehow create the image before hand and then copy
this to the screen.  That would eliminate the need to erase the
screen, which is the root of the problem.

Those of you who have written QB code similar to that above will say,
"no problem."  That is because they are familiar with the concept of
video memory.  The graphics that are drawn on your screen are just
particular area of memory interpreted by the graphics card.  If you
are not familiar with the concept of video memory, there are plenty
of small tutorials on that subject.  You will find one in the tutorials
section of the VirtuaSoft website.

Now to get to the real secret of the trick: the PUT statement.  Yeah,
you know the one, GET an image from the screen into an array, and
then paste it anywhere you want via the PUT statement.  Well, QB
never said that you couldn't GET or PUT the entire screen at once.
So what I'm going to explain is how to draw your graphics into an
array, and then PUT the whole thing on the screen at once.  You will
notice that flashing is eliminated, and if you've got at least a
pentium, [or at least something faster than a 486] you will be able to
create some decent animation.

The first hurdle is to create the buffer [I'll call it a logical screen].
In 320x200 mode (which is what I'll assume you use because it is
the best graphics mode for QB programs), the screen takes up
64000 bytes, as noted above.  A PUT array just holds a copy of video
RAM, so this is just about all you'll need.  However, the PUT array
has 4 initial bytes describing the length and width of the image
stored in the array.  So the total space needed for the logical screen
is 64004 bytes.  I'm going to use an integer array to allocate this
memory.  Each integer is 2 bytes, so the array will have to have
32002 elements.  So the code to get the memory for the logical
screen is:

DIM logicalScreen(32001) AS INTEGER

Okay, now to create those 4 header bytes.  The first two bytes, which
you can think of as one 16-bit integer variable, contain the number
width * bits-per-pixel.  In screen 13, the bits-per-pixel [bpp] is 8, so
to create that first header byte:

logicalScreen(0) = widthOfPic * 8

And the next 2 bytes are just the height:

logicalScreen(1) = heightOfPic

Now, try doing just that much and then (after SCREEN 13) do a
PUT (0, 0), logicalScreen.  Notice that you *don't* get the dreaded
Illegal function call error? Nice job.

Well, now you're gonna be on familiar territory.  Remember that
POKE code above?  You're still gonna get to use that.  Only this
time, you need to alter it just a little.  Instead of of using &HA000 as
your segment, you need to use the segment of the logical screen.

DEF SEG = VARSEG(logicalScreen(0))

And instead of the offset being calculated by just a coordinate value,
you need to throw in the offset for the logical screen.

screenOffset% = VARPTR(logicalScreen(0))
POKE screenOffset% + x% + 320& * y%, clr%

Then, when you've finished drawing your graphics, just:

PUT(0,0), logicalScreen, PSET

And you've drawn a frame of animation.  Splendid.  Also note that you
don't have to make a PUT array as big as the screen to draw in it, you
can make a PUT array of any size, and then selectively put it to the
screen to double buffer only a small portion of the screen on which
animation is taking place.  This is a much more efficient approach,
but you will have to alter the pixel offset calculations:

POKE screenOffset% + x% + logScrnWidth% * y%, clr%

Anyway, I'm just trying to share an idea, not necessarily write code
for you.  So just take the idea for what it is worth, improve it, and
implement it the way you want to.

Thanks for reading my newsletter.  I enjoy giving writing about QB,
and you will probably see my articles in the VS newsletter from time
to time.
 

Contact Richard via:
e-mail:  rr91834@pegasus.cc.ucf.edu
AIM:  OORichard [not zeros]
 

 
 
Back