[PicWin] Manual double buffering by Epsilon


#1

Version: 1.0

Required level: intermediate

Author: Epsilon

1) Intro

When doing your drawing directly to a picture window, it’s entirely possible that the screen will get updated before you’re done.

For example after that you’ve /drawpic the background of a game and before you /drawpic the sprite of a character over it, the user might see a flicker of the background before your script has a chance to draw over the character.
The slower your computer and the more drawing operations that you do, the more flicker will be apparent and eventually it will look like a big mess.

To prevent this “flickering effect”, you can use mIRC’s internal double buffering: the -n switch, available with every /draw command.

But its a good idea to forget about /drawpic and /draw* -n in the main loop of your animation/game. Why ? Because /drawpic is slow, and the cached bitmap (/drawpic -c) are limited to 30 bitmaps. Furthermore, another script could delete the bitmap cache during the execution of your script.

So we will create our own double buffering method, with the fastest /draw command available in mIRC: /drawcopy

2) Creating the buffer

The buffer consist of an hidden, borderless picture window. We will draw directly on it, without any -n flags, and after all the drawing part, we will simply /drawcopy the content of the buffer in the visible picture window.
To create the buffer, use this code:

/window -phB +d @MyBuffer 0 0 0 0
/window @MyBuffer 0 0 200 300

Why 2 /window ? Because of a mIRC bug: if the main mIRC window is smaller than the desired width or height of the picwin, the picwin will be truncated, so it will be smaller than what we want.
The second /window force it to the desired size.

The flags:
-p : for picture window.
-h : to hide the window.
-B +d : to remove the internal and external borders of the window.

Now you can draw on the buffer.

Example:

/drawpic @MyBuffer 0 0 flower.png

3) Using the buffer

Using the buffer is as easy as /drawpic, but 1000 times faster. We will use /drawcopy. It is very, very fast. It consists of a bit by bit copy from one window to another.
You can choose to copy the entire buffer, or just a small part, and you can place the content on another picwin (the visible one).

Example:

/drawcopy -t @MyBuffer $rgb(255,0,255) 0 0 100 100 @MyGame 0 0

In this example we take a square of 100 pixels, beginning at the (0,0) coordinates of the buffer, and we draw it on the @MyGame window, at the (0,0) coordinates.

The flags:
-t : specify that $rgb(255,0,255) is the transparency color (so the pink part will not be copied).

As you can see, its really easy.

4) Closing the buffer

To close the buffer, you just need to /window -c

/window -c @MyBuffer

Remember to close all your buffers in the ON CLOSE event of the visible window (ex: @MyGame)

5) When to use manual double buffering

Everytime that you want to repeatedly use slow /draw methods, like /drawpic.

Example:

In a mIRC game, you need to draw the background and the characters a lot of time (e.g. 20 times per seconds).
Using /drawpic everytime will be very, very, very slow. But /drawcopy the background from the background-buffer into a “game buffer”, then drawcopy the characters from the sprites-buffer into the “game buffer”, and eventually /drawcopy the “game buffer” into the visible picwin will be very smooth and fast.

Like this:

alias start.game {

   window -p @game 0 0 0 0

   window @game 0 0 200 200 ;bug fix



   ;a buffer that contains the background picture

   window -phB +d @game.background.buffer 0 0 0 0

   window @game.background.buffer 0 0 200 200

  

   ;a buffer that contains the characters (2 sprites of 25*50 pixels)

   window -phB +d @game.sprites.buffer 0 0 0 0

   window @game.sprites.buffer 0 0 50 50



   ;a display buffer, we will draw on it

   window -phB +d @game.display.buffer 0 0 0 0

   window @game.display.buffer 0 0 200 200



   drawpic @game.background.buffer 0 0 background.bmp

   drawpic @game.sprites.buffer 0 0 characters_sprites.bmp



   .timer -ho 1 0 main.game.display

}

As you can see, I opened 3 buffers, and a visible window. We will use drawpic on the buffers, and now we can forget about that slow command, since we will not use it anymore, we will use the buffers instead.

now the main alias that is called 20 timers per second (for example):

alias main.game.display {

;this alias is the main animation alias. For example in this alias we could increment the x coord of a sprite, to make it move to the right.



   ;first we draw the background on the buffer at (0,0) coords.

   drawcopy @game.background.buffer 0 0 200 200 @game.display.buffer 0 0



   ;then we draw the first sprite of 25*50 pixels at (10,40) coords.

   drawcopy @game.sprites.buffer 0 0 25 50 @game.display.buffer 10 40



   ;then we draw the second sprite of 25*50 pixels at (120,70) coords.

   drawcopy @game.sprites.buffer 25 0 25 50 @game.display.buffer 120 70



   ;now the drawing part is finished, we can copy the result to the visible window, without any flicker.

   drawcopy @game.display.buffer 0 0 200 200 @game 0 0



   ;now we process the alias again 

   .timer -ho 1 0 main.game.display 

}

6) Enjoy

That’s all folks.
Now you can make your own double buffering, and you have much more controls than what you have with /draw -n.


The previous tutorial was written by Epsilon for picwin.tk.