Click here if you are stuck in someone else's frames.

If this page looks like garbage then you need one of these browsers...

Microsoft Internet Explorer

Netscape Navigator

Please sign my programmer's page guestbook.

Please sign my guestbook

View my guestbook entries

Drawing sprites via bit blitting

I guess the statement "drawing the sprite" is a bit misleading. We do not actually draw the sprites during their rendering, instead we actually copy the pixels from the bitmaps to the screen memory; a process known as bit blitting. There are some precautions we must take when it comes to blitting a sprites image on the screen.

  • If we are about to draw sprite images on top of a complex background, we better have a mechanism for restoring that part of the background that we overwrote with the sprite's image before moving it. Otherwise we will eventually obliterate the entire background. Our sprites will appear to "eat up" the background.
  • We must take care when part or all of the sprite's image goes "off screen." That is, we must make sure that we do not draw outside of the boundaries of the video memory (and later on our cache buffer). Our sprites could easily crash the system by overwrite memory that it is not suppose to if care is not taken.

Fortunately, we built in mechanism that can account for both of these which is good news for us. The mechanism for restoring the background is built in with the memory allocated to the background pointer of the sprite struct. The mechanism for preventing overwrites is the sprites image clipping mechanism that will use the elements minX, maxX, minY, maxY and lenXcopy, lenYcopy, startXoff, startYoff of the sprite structure.

First, let's write code that will show the sprite on the screen. We will leave out the clipping code in this example for simplicity and speed of execution. There is another way to ensure that a sprite's image does not go outside the boundaries of the screen without using clipping and since the calculations for clipping a sprite's image can complicate the code, I wanted to show it to you in the simplest way first.

void SpriteShow(struct Sprite *thisSpr)
{
    char far *src, *dest;
    int i, t;

    if (thisSpr->visible || thisSpr->frames == NULL ||
        thisSpr->frames[thisSpr->currFrame] == NULL) return;

    if (thisSpr->background != NULL && thisSpr->width && thisSpr->height) {
        /* Copy background before drawing sprite */
        src  = &thisSpr->displayMem[(thisSpr->Y<<8)+(thisSpr->Y<<6)+thisSpr->X];
        dest = thisSpr->background;
        for (i=0; i<thisSpr->height; i++) {
            _fmemcpy(dest, src, thisSpr->width);
            src  += ScreenWidth;
            dest += thisSpr->width;
        }
    }

    if (thisSpr->width && thisSpr->height) {
        /* Prepare to copy the sprite's image to the screen */
        src  = thisSpr->frames[thisSpr->currFrame];
        dest = &thisSpr->displayMem[(thisSpr->Y<<8)+(thisSpr->Y<<6)+thisSpr->X];
        if (thisSpr->backTransparent) {
            /* Copy the image, accounting for transparency */
            for (i=0; i<thisSpr->height; i++) {
                for (t=0; t<thisSpr->width; t++)
                    if (src[t]) dest[t] = src[t];
                src  += thisSpr->width;
                dest += ScreenWidth;
            }
        } else {
            /* Copy all pixels, even transparent ones */
            for (i=0; i<thisSpr->height; i++) {
                _fmemcpy(dest, src, thisSpr->width);
                src  += thisSpr->width;
                dest += ScreenWidth;
            }
        }
    }
    thisSpr->visible = 1;  /* Flag the sprite as visible */
}
    

Let's examine the code a bit, I won't go into way too much detail over thhe code because we still have quite a bit of grouund to cover here.

First it checks to see if the sprite is already visible or if the frames array contains no frames (thisSpr->frames == NULL) or if the current frame contains no image (thisSpr->frames[thisSpr->currFrame] == NULL) in which it will abort the function if it finds any of this to be true.

Next it copies the area of the screen that the sprite is about to occupy onto it's background buffer. It only does this though if the background has a buffer (thisSpr->background != NULL) and if the width and height are set to non-zero values. This background buffer allows us to restore the previous background when it is time to move or erase the sprite.

I won't go into too much detail over how it copies the lines from the screen to the background buffer. Basically it starts by taking the address of the upper left corner of the sprite's image on the screen and copies that area of memory (using _fmemcpy) to the background buffer.

Next it copies the actual image of the sprite onto the screen. The technique here is the same as the one used to copy the screen into the background buffer (except in reverse). However, it takes into account transparency before copying.

Well, that's the SpriteShow function in a nutshell. Now that we have the code to display sprites we now need to write code that erases sprites also.


Send your questions, comments, or ideas to: wilkeg@gamewood.net

This page hosted by GeoCities Get your own Free Home Page
 Next Back |