Thread: How do I do double buffering in console?

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    21

    How do I do double buffering in console?

    I got my character moving on my main map but everytime the character moves (or as a matter of fact, anything moves) I do a system("cls") and redraw the entire screen. Thus, I am getting a LOT of flickers on the screen and it's a big case of headache. I was told to have two screen buffers, and when one is being displayed, the next screen is being drawn on the other buffer. Please teach me how to do that for console, thanks.

  2. #2
    Slave MadCow257's Avatar
    Join Date
    Jan 2005
    Posts
    735
    Just replace the system("cls") with something from http://faq.cprogramming.com/cgi-bin/...&id=1043284385
    system("cls") is very slow, I assure you.

  3. #3
    ---
    Join Date
    May 2004
    Posts
    1,379
    lol I dont think you can a secondary buffer on a console window. It's not made for graphics it's made for displaying text.

  4. #4
    Registered User
    Join Date
    Apr 2005
    Posts
    21
    ok, maybe I cannot do it in the same sense as in a graphical window but something similiar to that effect can be done because I've seen people's console games without the mad flickering that appears in my game. Is there any way to save my entire screen output from a single game loop to an array or a file or something? Then just call the saved one to display onto the screen in the next game loop?
    Last edited by pliang; 04-13-2005 at 12:11 AM.

  5. #5
    Chief Code Coloniser!
    Join Date
    Apr 2005
    Posts
    121
    Generally double buffering is used to avoid things like shearing, which I doubt you're having problems with in console mode. I recommend following MadCow's suggestion - his comments are spot on.

    If you then have issues with shearing (ie. drawing the content while it's being updated), then create two buffers, and keep a pointer to the current one that's been updated and render from the other.

    I would be suprised if you really need to double buffer in a console though. Cheers.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The reason for double buffering has absolutely nothing to do with shearing.

    Shearing happens when you are drawing the screen during the refresh period. There is a port you can keep an eye on to track when the blanking signal goes high (refresh starts) and when it goes low (refresh is over). This is what is commonly known as vsync or vertical synchronization. Shearing can happen in double buffer mode and quite honestly will probably be noticed most in double buffer mode since any other type of refresh will cause flicker, save for page flipping.

    The reason FOR double buffering is exactly what you are seeing. If you do not use double buffer there will always be a period of time at which the screen data is not there. It does not matter how fast you clear the screen, you will always notice flicker. With double buffering you essentially have 2 screens. One buffer acts as the off-screen or next image and the screen acts as the current image. So you draw to memory or to the off-screen buffer and then when it is ok to copy all the data to the screen (see refresh and blanking signal above) you copy byte for byte every piece of data from the buffer to the screen.
    This process goes on and on until the game or application is shut down. This method produces absolutely no flicker at all.

    But since you cannot double buffer in console, you could write a small class that would handle updating only certain areas of the screen. This is the same idea in Windows GUI when you don't need to redraw the entire image just a portion of it. In Windows you would use InvalidateRect() which flags the rectangle specified as a region that needs to be updated. Now when paint is called, it only updates within that rectangle. This is all transparent to the programmer and the Windows GUI handles the clipping and rasterizing inside of the invalidated rectangle. You could use somewhat of the same principle to reduce the overall flicker.

  7. #7
    Registered User
    Join Date
    Apr 2005
    Posts
    21
    Right now the only known way for me to reduce flickering is to use the use coordinates to move the cursor around on the screen and update only what I need to, like Bubba mentioned above. I guess that's the only way huh? Perhaps I am out of luck then since I must redraw the whole screen when my character is moving on a scrolling map.

  8. #8
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    Sounds like you should just move to a graphics API.

  9. #9
    Registered User
    Join Date
    Mar 2004
    Posts
    220
    Unless your maps are extremely variant, there will be some drawing that you don't have to repeat. For instance if you have your flooring as one texture, you might only have to re-draw one to two rows worth of flooring to replace it with trees or something.

    That's one method that you can use to deal with the problem. Of course checking the continuity of your maps at any given world position is quite a difficult formula to come up with, but if you're that dedicated it is possible.
    OS: Windows XP Pro CE
    IDE: VS .NET 2002
    Preferred Language: C++.

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I have an idea. Dump all the archaic stuff and stop using a mode that was not designed to do what you want to and hence works against you in all cases. Learn a graphics API.

  11. #11
    Registered User
    Join Date
    Mar 2004
    Posts
    220
    Oh, I have a suggestion! Don't move your map where you don't need to! Meaning, scroll through your world when you hit the end of the section, not when you've just moved a pixel or so. Also, since you can control which cells you draw to, redrawing in this method is extremely simple, fast, and alot better (your flicker problem will look more like a transition than a glitch ).
    OS: Windows XP Pro CE
    IDE: VS .NET 2002
    Preferred Language: C++.

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Redraw the map every frame.

    Code:
    WORD CellX=(WORD)(-ScrollX/CellSize);
    WORD CellY=(WORD)(-ScrollY/CellSize);
    
    WORD offset=CellY*MapWidth+CellX;
    WORD MoveDownOneRow=MapWidth;
    
    WORD MapX=CellX;
    WORD MapY=CellY;
    
    char *Glyph=0;
    
    for (int y=Top;y<Bottom;y++)
    {
      for (int x=Left;x<Right;x++)
      {
         WORD value=MapData[offset];
         switch (value)
         {
            case 0:
              Glyph=" ";break;
            case 1:
              Glyph="X";break;
            case 2:
              Glyph="*";break;
          }
         printf("%s",Glyph);
         offset++;
         MapX++;
         if (MapX>MapWidth) break;
      }
      offset+=MoveDownOneRow;
      MapX=CellX;
      MapY++;
      if (MapY>MapHeight) break;
    }

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    I've had problems with the same thing so long and I've been using puttext() for it. Of course bubba's idea in his last message depends on pc's power but it's still much slower than puttext() for I have tried it.

    Puttext() is for console and draws an 1D array, like char view[80 * 24 * 2], on screen pretty effectively. Because every pixel on screen takes 2 bytes of memory, for example view[0] holds glyph and view[1] color of one coordinate of map. In this case, view can save 80x24 sized screen and draw it with
    puttext(1, 1, 80, 24, view). But note that puttext draws the view from left to right and top to bottom, like text is normally written (if not japan style ).

    So, if u'd like to fill screen with yellow 'T' marks, for a simple version u could do:

    Code:
    struct Pixel {
       char mark;
       char color;
    
       Pixel() {
          mark = 'T';
          color = YELLOW // (or 14) 
       }
    }
    
    void main() {
    
    Pixel map[24][80] // actual map
    char view[24 * 80 * 2] // screen buffer
    int vidx = 0;
    
    for (int i = 0; i < 24; ++i)
       for (int j = 0; j < 80; ++j) {
          view[vidx] = map[i][j].mark;
          view[vidx + 1] = map[i][j].color;
          vidx += 2;
       }
    
    puttext(1, 1, 80, 24, view);
    
    }
    Now, I'd do this kind of thing every time I want to refresh the map But in my game, I use a map drawing function that centers the view on given coordinates.

    Maybe this is not what u wanted but at least u have another idea

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Of course bubba's idea in his last message depends on pc's power but it's still much slower than puttext() for I have tried it.
    ?? Please explain. I could write puttext myself in assembler but I left that part out. Trying to stay simple here. I doubt in text mode that anything will run slow.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    24
    Ah I read it too fast I think, it wasn't what I thought at first. Writing screen with printf() So, nothing then.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Testing some code, lots of errors...
    By Sparrowhawk in forum C Programming
    Replies: 48
    Last Post: 12-15-2008, 04:09 AM
  2. Conversion From C++ To C
    By dicon in forum C++ Programming
    Replies: 2
    Last Post: 06-10-2007, 02:54 PM
  3. Need some help/advise for Public/Private classes
    By nirali35 in forum C++ Programming
    Replies: 8
    Last Post: 09-23-2006, 12:34 PM
  4. Please HELP!!
    By traz in forum C++ Programming
    Replies: 4
    Last Post: 04-14-2003, 09:20 PM
  5. double buffering for allegro
    By Leeman_s in forum C++ Programming
    Replies: 6
    Last Post: 09-12-2002, 02:45 PM