If you made a game with moving objects, but you're not familiar with the double buffering technique, your game graphics must flicker.
This unwanted effect makes your game look old and very amatuer.
The flickering occurs because you "let the player see" that you erase objects and redraw them in their new position.
Double buffering is not about avoiding erasing and redrawing, but about avoiding the player from noticing it.
When I said you let the player see the erasing and redrawing I meant that you erase and redraw directly to the video memory.
To avoid the flickering, you need to allocate a buffer of your own, the size of the video memory, make all your drawing and erasing in your buffer, and only then copy your whole buffer as one block to the video memory.
This process repeats itself every time you draw your objects (usually - every game loop).
We'll call the offscreen buffer the Double Buffer.
If your association of erasing is drawing over each object a duplicate of itself in the background color, you probably need to change your way of erasing.
Erasing each object separately is usually very inefficient when you have more than a few simple objects. The better alternative is to erase the whole buffer each time before you start drawing. This is done by setting your whole double buffer to the background color as a block before drawing.
Note: If you want to have a static background image (or even, a non-static one if you're creative enough), instead of a single color background, see: Triple Buffering.
Some clear-ups:
1. Double buffering is not about making your game faster. On the contrary! It even slows it down, but its big advantage is that it makes your animation look much more smooth.
2. You don't have to erase the whole double buffer, but this is usually recommended because it's almost always faster.
3. Erasing the double buffer or copying it to the video memory can be done using memset and memcpy, but it can get much faster using some nifty copying routines in ASM.
4. Don't forget to free your double buffer when closing the game down! (or your players will get very angry at you :) ).
So let's see the code:
unsigned char *dbuffer = NULL; // Will point to the double buffer
// Double buffer routines:
int init_virscr() // Allocate memory for the double buffer
{
dbuffer = (unsigned char *)malloc(320 * 200); // 320 columns, 200 rows in mode 13h
if (dbuffer == NULL) return(0);
return(1);
}
// Clear the double buffer
void clearscreen_db()
{
memset(dbuffer, 0, 320 * 200);
}
// Drawing a pixel on a 320X200X256 the buffer.
void plotpixel_db(int x, int y, unsigned char co)
{
dbuffer[(y << 6) + (y << 8) + x] = col;
}
// Copy the double buffer into the video memory
void drawscreen_db()
{
memcpy(VIDEO_ADDRESS, vbuffer, 320 * 200);
}
// Free the memory allocated for the double buffer
void free_virscr()
{
free(vbuffer);
}
// Usage of the Double-Buffering:
// (Take a look at the source codes too...)
init_virscr();
while(!GameOver())
{
...
Handle the player
...
clearscreen_db();
// Notice: WE DRAW ON THE BUFFER, NOT THE VIDEO MEMORY!!
plotpixel_db(Player.x, Player.y, 1);
drawscreen_db();
}
free_virscr();
|
That's it!
I think Double-Buffering really makes the game MUCH more FUN.
Now it's your time to kick ass :)
Good luck to you all!
Source Code:
Turbo C - dblbuf.cpp
DJGPP - dblbuf.c