<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Page Flipping Problem - Flicker</title>
		<link>http://www.allegro.cc/forums/view/590316</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Sat, 03 Mar 2007 13:42:34 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[Hi! I'm using a combination of page flipping and double buffering. I'm trying to use pageflip for background scrolling and Double buffering for drawing all the sprites, bullets, etc. However, my screen seems to flicker so much. I don't know what I'm doing wrong... Here are my classes, I hope you could help me. Thanks!<br />
<br />
<br />
I have a class which is in-charge of overall drawing/rendering.<br />
<br />
[code]<br />
#include &quot;globals.h&quot;<br />
<br />
GameManager::GameManager()<br />
{<br />
}<br />
<br />
GameManager::~GameManager()<br />
{<br />
}<br />
<br />
void GameManager::blitBuffer()<br />
{<br />
    acquire_screen();<br />
    <br />
    blit(buffer, screen, 0, 0, 0, 0, GAME_WIDTH, GAME_HEIGHT);<br />
    <br />
    release_screen();<br />
    <br />
    clear_bitmap(buffer);<br />
} <br />
<br />
void GameManager::blitVideoBuffer()<br />
{<br />
    //acquire_screen();<br />
    acquire_bitmap(videoBuffer);<br />
    <br />
    blit(videoBuffer, screen, 0, 0, 0, 0, GAME_WIDTH, GAME_HEIGHT);<br />
    <br />
    release_bitmap(videoBuffer);<br />
    <br />
    show_video_bitmap(videoBuffer);<br />
    <br />
    //release_screen();<br />
    <br />
    //clear_bitmap(videoBuffer);<br />
}<br />
<br />
BITMAP* GameManager::buffer;<br />
BITMAP* GameManager::videoBuffer;<br />
<br />
const short int GameManager::GAME_WIDTH = 640;<br />
const short int GameManager::GAME_HEIGHT = 480;<br />
const short int GameManager::COLOR_DEPTH = 16;<br />
<br />
int GameManager::game_score;<br />
<br />
[/code]<br />
<br />
<br />
Now, I have a GameBackground class in which I try to scroll the parallax background.<br />
<br />
[code]<br />
#include &quot;globals.h&quot;<br />
<br />
<br />
GameBackground::GameBackground(BITMAP* bitmap, BackgroundScrollType scrollType, int scrollSpeed, int x, int y)<br />
{<br />
    this-&gt;bitmap = bitmap;<br />
    this-&gt;scrollType = scrollType;<br />
    this-&gt;scrollSpeed = scrollSpeed;<br />
    this-&gt;x = x;<br />
    this-&gt;y = y;<br />
    <br />
    //tmpBuffer = create_bitmap(SCREEN_W, SCREEN_H);<br />
    tmpBuffer = create_video_bitmap(SCREEN_W, SCREEN_H);<br />
}    <br />
<br />
GameBackground::~GameBackground()<br />
{<br />
    destroy_bitmap(tmpBuffer);<br />
}<br />
<br />
void GameBackground::update()<br />
{<br />
    scrollBackground();<br />
}<br />
<br />
void GameBackground::scrollBackground()<br />
{<br />
    switch(scrollType)<br />
    {<br />
        case HORIZONTAL_LEFT:<br />
            scrollLeft();<br />
            break;<br />
        default:<br />
            break;<br />
    }    <br />
}<br />
<br />
void GameBackground::draw()<br />
{<br />
    //draw_sprite(GameManager::buffer, tmpBuffer, 0, 0);<br />
    draw_sprite(GameManager::videoBuffer, tmpBuffer, 0, 0);<br />
}    <br />
<br />
void GameBackground::setScrollSpeed(int speed)<br />
{<br />
    scrollSpeed = speed;<br />
}    <br />
<br />
void GameBackground::scrollLeft()<br />
{<br />
    x -= scrollSpeed;<br />
    <br />
    int bw = bitmap-&gt;w;<br />
    int bh = bitmap-&gt;h;<br />
    <br />
    int xOffSet = (SCREEN_W + bw);<br />
    <br />
    if ( x &gt; bw || x &lt; -(bw) )<br />
    { <br />
        x = 0;<br />
    }    <br />
    <br />
    int newX = 0;<br />
    <br />
    for (int i = -(bw); i &lt; (xOffSet); i += bw)<br />
    {<br />
        newX = (x + i);<br />
        <br />
        for (int j = 0; j &lt; SCREEN_H; j += bh)<br />
        {<br />
            //draw tile<br />
            //Optimization: draw only parts that are visible to the screen            <br />
            if ( ( newX + bw) &gt; 0 )<br />
            {<br />
                draw_sprite(tmpBuffer, bitmap, newX, j);    <br />
            }<br />
            else<br />
            {<br />
                break;<br />
            }    <br />
                    <br />
        }    <br />
    }<br />
}                 <br />
<br />
[/code]<br />
<br />
<br />
And the update and draw methods for GameBackground class are called in this class which functions as the main entry point of my game...<br />
<br />
[code]<br />
#include &quot;globals.h&quot;<br />
<br />
PlayState::PlayState()<br />
{<br />
    currentLevel = 1;<br />
<br />
    GameManager::game_score = 0;<br />
<br />
    //create buffer image (double bufferring)<br />
    GameManager::buffer = create_bitmap(SCREEN_W, SCREEN_H);<br />
    //create video image (page flipping)<br />
    GameManager::videoBuffer = create_video_bitmap(SCREEN_W, SCREEN_H);<br />
    <br />
    //load sprites<br />
    BitmapManager::addBitmap(SHIP_SPRITE, &quot;graphics/fs.bmp&quot;);<br />
    BitmapManager::addBitmap(VULCAN_SPRITE, &quot;graphics/vulcan.bmp&quot;);<br />
    BitmapManager::addBitmap(ASTEROID_SPRITE_FLYING, &quot;graphics/asteroid_flying.bmp&quot;);    <br />
    BitmapManager::addBitmap(ASTEROID_SPRITE_HIT, &quot;graphics/asteroid_hit.bmp&quot;); <br />
    BitmapManager::addBitmap(ASTEROID_SPRITE_DYING, &quot;graphics/asteroid_destroyed.bmp&quot;);<br />
    BitmapManager::addBitmap(BULLET_HEAD_SPRITE_FLYING, &quot;graphics/bullet_head_flying.bmp&quot;);<br />
    BitmapManager::addBitmap(BULLET_HEAD_SPRITE_HIT, &quot;graphics/bullet_head_hit.bmp&quot;);<br />
    BitmapManager::addBitmap(SPRITE_EXPLOSION, &quot;graphics/explosion.bmp&quot;);<br />
    BitmapManager::addBitmap(SWIRL_SPRITE_FLYING, &quot;graphics/swirl_flying.bmp&quot;);    <br />
    BitmapManager::addBitmap(SWIRL_SPRITE_HIT, &quot;graphics/swirl_hit.bmp&quot;); <br />
    BitmapManager::addBitmap(SWIRL_SPRITE_DYING, &quot;graphics/swirl_destroyed.bmp&quot;);<br />
    BitmapManager::addBitmap(POWER_UP, &quot;graphics/power_up.bmp&quot;);<br />
    <br />
    //load SFX<br />
    SoundManager::addSample(METEOR_DESTROYED_SFX, &quot;sfx/meteordestroyed.wav&quot;);<br />
    SoundManager::addSample(VULCAN_GUN_FIRE_SFX, &quot;sfx/vulcan.wav&quot;);<br />
    SoundManager::addSample(POWER_UP_SFX, &quot;sfx/power_up.wav&quot;);<br />
    <br />
    //ship = new Ship(BitmapManager::SHIP_SPRITE, 50, 50, 50, 32, 1);<br />
    //Ship(int x, int y, int w, int h, int speed, int recoveryRate, int recoveryTime, Status stat, int lfe);<br />
    ship = new Ship(50, 50, 50, 45, 3, MAX_RECOVERY_RATE, MAX_RECOVERY_TIME, ALIVE, MAX_PLAYER_LIFE);<br />
    <br />
    //add a weapon for the ship<br />
    ship-&gt;addWeapon(VULCAN_GUN, WeaponFactory::getWeapon(VULCAN_GUN) );<br />
    ship-&gt;setCurrentWeapon(VULCAN_GUN);<br />
    ship-&gt;move(0, (SCREEN_H / 2) );<br />
}    <br />
<br />
PlayState::~PlayState()<br />
{<br />
    BitmapManager::removeAll();<br />
    <br />
    destroy_bitmap(GameManager::buffer);<br />
    <br />
    delete ship;<br />
}<br />
<br />
PlayState* PlayState::getInstance()<br />
{<br />
    if (instance == NULL)<br />
    {<br />
        instance = new PlayState();<br />
    }<br />
    <br />
    return instance;    <br />
}    <br />
<br />
void PlayState::init()<br />
{<br />
}<br />
<br />
void PlayState::pause()<br />
{<br />
}<br />
<br />
void PlayState::run()<br />
{<br />
    GameStateManager::pushState( GameOverState::getInstance() );     <br />
        GameStateManager::getCurrentState()-&gt;run();//--execute run method<br />
        GameStateManager::popState(); //--pop the element on top<br />
                  <br />
    loadLevel(currentLevel);<br />
    <br />
    //begin main game loop<br />
    while ( !key[KEY_ESC] )<br />
    {   <br />
        <br />
        while (GameTimer::game_ticker &gt; 0)<br />
        {<br />
            //move left<br />
            if ( key[KEY_A] )<br />
            {<br />
                ship-&gt;move( ship-&gt;x - ship-&gt;getSpeed(), ship-&gt;y );<br />
                if ( ship-&gt;x &lt;= 0 )<br />
                {<br />
                    ship-&gt;move( ship-&gt;x + ship-&gt;getSpeed(), ship-&gt;y ); <br />
                }<br />
            }    <br />
            //move down<br />
            if ( key[KEY_S] )<br />
            {<br />
                ship-&gt;move( ship-&gt;x, ship-&gt;y + ship-&gt;getSpeed() );<br />
            <br />
                if ( (ship-&gt;y + ship-&gt;height) &gt;= SCREEN_H )<br />
                {<br />
                    ship-&gt;move( ship-&gt;x, ship-&gt;y - ship-&gt;getSpeed() );<br />
                }<br />
            }    <br />
            //move right<br />
            if ( key[KEY_D] )<br />
            {<br />
                ship-&gt;move( ship-&gt;x + ship-&gt;getSpeed(), ship-&gt;y );<br />
                <br />
                if ( (ship-&gt;x + ship-&gt;width) &gt;= SCREEN_W )<br />
                {<br />
                     ship-&gt;move( ship-&gt;x - ship-&gt;getSpeed(), ship-&gt;y );<br />
                }<br />
            }    <br />
            //move up<br />
            if ( key[KEY_W] )<br />
            {<br />
                ship-&gt;move( ship-&gt;x, ship-&gt;y - ship-&gt;getSpeed() );<br />
                <br />
                if ( ship-&gt;y &lt;= 20 )<br />
                {<br />
                    ship-&gt;move( ship-&gt;x, ship-&gt;y + ship-&gt;getSpeed() );     <br />
                }<br />
            }<br />
            //fire weapon<br />
            if ( key[KEY_K] )<br />
            {<br />
                ship-&gt;fireWeapon();<br />
            }<br />
            //change weapon<br />
            if ( key[KEY_TAB] )<br />
            {<br />
                 //ship-&gt;fireWeapon();<br />
            }<br />
            //fire special<br />
            if ( key[KEY_L] )<br />
            {<br />
            }<br />
            <br />
            //exit to menu<br />
            if ( key[KEY_ESC] )<br />
            {<br />
                break;<br />
            }    <br />
            <br />
            //scroll the background<br />
            bg-&gt;update();<br />
            bg-&gt;draw();  <br />
                        <br />
            //animate the ship<br />
            ship-&gt;update();<br />
            <br />
  <br />
            //move all powerups<br />
            for (std::vector&lt;PowerUp*&gt;::iterator it = PowerUp::powerUpPool.begin(); it != PowerUp::powerUpPool.end(); ++it)<br />
            {<br />
                PowerUp* pUp = (*it);<br />
                <br />
                if ( pUp-&gt;isActive() )<br />
                {<br />
                    pUp-&gt;update();<br />
                    pUp-&gt;draw();<br />
                    <br />
                    if ( ship-&gt;collides(pUp) )<br />
                    {<br />
                        pUp-&gt;makeInactive();<br />
                        ship-&gt;upgradeWeapon();<br />
                        play_sample( SoundManager::getSample(POWER_UP_SFX), 255, 0, 2000, 0);<br />
                    }<br />
                }    <br />
                    <br />
                pUp = NULL;<br />
            }    <br />
         <br />
            //move all enemies<br />
            for(std::vector&lt;Enemy*&gt;::iterator it = EnemyFactory::enemyPool.begin(); it != EnemyFactory::enemyPool.end(); ++it)<br />
            {<br />
                Enemy* e = *it;<br />
                <br />
                //enemy is alive or dying<br />
                if ( !( e-&gt;isDead() ) || e-&gt;isDying() )<br />
                {<br />
                    e-&gt;update();<br />
                    e-&gt;draw();<br />
                    <br />
                    //enemy is alive, ship is not recovering and ship hits enemy<br />
                    if ( !( e-&gt;isDead() ) &amp;&amp; !( ship-&gt;isRecovering() ) &amp;&amp; ship-&gt;collides(e) )<br />
                    {<br />
                        ship-&gt;takeDamage(10); //TODO: change to enemy attack power<br />
                        e-&gt;takeDamage(1);<br />
                    }                     <br />
                }<br />
            }            <br />
                  <br />
            //move all projectiles<br />
            for (std::vector&lt;Projectile*&gt;::iterator it = ProjectileFactory::projectilePool.begin(); it != ProjectileFactory::projectilePool.end(); ++it)<br />
            {                   <br />
                                 <br />
                if ( (*it)-&gt;isVisible() == true &amp;&amp; (*it)-&gt;isActive() )<br />
                {<br />
                    Projectile* p = *it;<br />
                    p-&gt;update(); //(*it)-&gt;update();<br />
                    p-&gt;draw(); //(*it)-&gt;draw();<br />
                    <br />
                    <br />
                    if ( p-&gt;isHostile() &amp;&amp; !( ship-&gt;isRecovering() ) )<br />
                    {<br />
                       /* check if ship collides projectile instead of<br />
                          projectile collides ship because ship provides<br />
                          a more precise collision that a player would not<br />
                          get annoyed with<br />
                       */<br />
                       if ( ship-&gt;collides(p) )<br />
                       {<br />
                         ship-&gt;takeDamage(10); //change this to projectile power<br />
                         p-&gt;makeInactive();<br />
                       }<br />
                    }                    <br />
                    <br />
                    //check for collision on bullet and enemies<br />
                    for(std::vector&lt;Enemy*&gt;::iterator eit = EnemyFactory::enemyPool.begin(); eit != EnemyFactory::enemyPool.end(); ++eit)<br />
                    {                              <br />
                        Enemy* e = *eit; <br />
                        <br />
                        //projectile hits an enemy<br />
                        if ( p-&gt;collides(e) &amp;&amp; p-&gt;isActive() &amp;&amp; !( p-&gt;isHostile() ) &amp;&amp; !( e-&gt;isDead() ) &amp;&amp; !( e-&gt;isDying() ) )<br />
                        {<br />
                             e-&gt;takeDamage(1); //TODO: change 1 to weapon power<br />
                             p-&gt;makeInactive();<br />
<br />
                             //player killed the enemy                             <br />
                             if ( !( e-&gt;isAlive() ) )<br />
                             {<br />
                                 GameManager::game_score += 10;                                  <br />
                             }<br />
                             <br />
                             //exit the inner loop<br />
                             break;<br />
                        }<br />
                    }                    <br />
                    <br />
                }<br />
                else<br />
                { <br />
                    Projectile* p = *it;<br />
                    it = ProjectileFactory::projectilePool.erase(it);<br />
                    // we must decrement, because it will be incremented when the loop starts over again<br />
                    --it;<br />
                    delete p;<br />
                }  <br />
            }    <br />
                     <br />
            <br />
            //control game speed<br />
            GameTimer::game_ticker--;                                   <br />
            <br />
            ship-&gt;draw();<br />
        <br />
            textout_ex(GameManager::buffer, font, &quot;Life: &quot;, 10, 10, makecol(0, 0, 255), -1);<br />
            //drawLifeBar(int x, int y, int length, height, BITMAP* bitmap); <br />
            drawLifeBar(50, 0, ship-&gt;getLife() , 20, GameManager::buffer);<br />
            <br />
            textprintf_centre_ex(GameManager::buffer, font, SCREEN_W/2, 10, makecol(255, 255, 255), makecol(0, 0, 0), &quot;Current Weapon: %s&quot;, ship-&gt;getCurrentWeapon()-&gt;getWeaponName() );                      <br />
            textprintf_centre_ex(GameManager::buffer, font, (SCREEN_W - (SCREEN_W/8) ), 10, makecol(255, 255, 255), makecol(0, 0, 0), &quot;Score: %d&quot;, GameManager::game_score);                      <br />
            <br />
            textprintf_centre_ex(GameManager::buffer, font, SCREEN_W/2, 176, makecol(255, 255, 255), makecol(0, 0, 0), &quot;num=%d&quot;, GameTimer::game_ticker);<br />
        <br />
            //blit buffer<br />
            GameManager::blitVideoBuffer(); <br />
            GameManager::blitBuffer();                      <br />
        }    <br />
                          <br />
    }<br />
    <br />
    unloadLevel(currentLevel);    <br />
}<br />
<br />
void PlayState::update()<br />
{<br />
}<br />
<br />
void PlayState::clean()<br />
{<br />
}                        <br />
<br />
void PlayState::loadLevel(int level)<br />
{     <br />
    PACKFILE* levelMap;<br />
    <br />
    switch(level)<br />
    {<br />
        case 1:                          <br />
            levelMap = pack_fopen(&quot;levels/level_01.lvl&quot;, &quot;r&quot;);            <br />
<br />
            createLevel(levelMap);<br />
<br />
            bg = new GameBackground(BitmapManager::addBitmap(SPACE_BACKGROUND, &quot;graphics/bg.bmp&quot;), HORIZONTAL_LEFT, 1, SCREEN_W, SCREEN_H);<br />
<br />
            break;<br />
        default:<br />
            break;        <br />
    }<br />
    <br />
    if (levelMap)<br />
    {<br />
        pack_fclose(levelMap);<br />
    }                <br />
}<br />
<br />
void PlayState::createLevel(PACKFILE* packFile)<br />
{<br />
    std::string line;<br />
    char buf[255];<br />
    <br />
    int currX = 0;<br />
    int currY = 0;<br />
    int xIncrement = (SCREEN_W / 20);<br />
    int yIncrement = (SCREEN_H / 20);     <br />
     <br />
    if (!packFile)<br />
    {<br />
        allegro_message(&quot;COULD NOT CREATE LEVEL!: %s&quot;, allegro_error);<br />
    }    <br />
            <br />
    while ( pack_feof(packFile) == 0 )<br />
    {<br />
        //read a line from the file (levelMap)<br />
        line = pack_fgets(buf, sizeof(buf), packFile);<br />
                <br />
        //loop through each character in the line<br />
        for (int i = 0; i &lt; line.length(); i++)<br />
        {                           <br />
            //only an empty space<br />
            if ( line.at(i) == ' ')<br />
            {<br />
                currX += xIncrement;    <br />
            }<br />
            else if( line.at(i) == 'P' )<br />
            {                <br />
                PowerUp* pUp = new PowerUp(currX, currY, 32, 32, 2, true);<br />
                <br />
                PowerUp::powerUpPool.push_back(pUp);<br />
            <br />
                pUp = NULL;<br />
            <br />
                currX += xIncrement;<br />
            }    <br />
            else //create an enemy object<br />
            {<br />
                Enemy* e = EnemyFactory::getEnemy( line.at(i) );<br />
                //set initial position of the enemy<br />
                e-&gt;move(currX, currY);<br />
                EnemyFactory::enemyPool.push_back(e);<br />
                        <br />
                e = NULL;<br />
                        <br />
                currX += xIncrement;<br />
            }        <br />
        }<br />
        <br />
        currX = 0;<br />
        currY += yIncrement;    <br />
    }              <br />
}<br />
<br />
void PlayState::unloadLevel(int level)<br />
{<br />
    switch(level)<br />
    {<br />
        case 1:<br />
            std::vector&lt;Enemy*&gt;().swap(EnemyFactory::enemyPool);<br />
            std::vector&lt;Projectile*&gt;().swap(ProjectileFactory::projectilePool);<br />
            std::vector&lt;PowerUp*&gt;().swap(PowerUp::powerUpPool);<br />
            delete bg;<br />
            break;<br />
        default:<br />
            break;<br />
    }    <br />
}<br />
<br />
void PlayState::drawLifeBar(int x, int y, int length, int height, BITMAP* bitmap)<br />
{<br />
    //rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);<br />
    if (length &lt;= 0)<br />
    {<br />
        length = 0;<br />
    }<br />
    <br />
    rectfill(bitmap, x, y, (x + length), height, 255);<br />
}    <br />
<br />
PlayState* PlayState::instance;<br />
int PlayState::currentLevel;<br />
Ship* PlayState::ship;<br />
<br />
[/code]<br />
<br />
<br />
I'm trying to use page flipping to gain extra performance since my game runs pretty slow on PIII machines and below. I just want to try it out and see if it makes any difference. Thanks!]]>
		</description>
		<author>no-reply@allegro.cc (armond)</author>
		<pubDate>Wed, 28 Feb 2007 17:13:43 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
void GameManager::blitVideoBuffer()<br />{<br />    //acquire_screen();<br />    acquire_bitmap(videoBuffer);<br />    <br />    blit(videoBuffer, screen, 0, 0, 0, 0, GAME_WIDTH, GAME_HEIGHT);<br />    <br />    release_bitmap(videoBuffer);<br />    <br />    show_video_bitmap(videoBuffer);<br />    <br />    //release_screen();<br />    <br />    //clear_bitmap(videoBuffer);<br />}
</p></div></div><p>
This is not proper page flipping. You blit the bitmap AND flip. This is not right.<br />There are, basically, two double buffering approaches you can implement here - blitting the back buffer, or flipping.<br />If you go the blitting route, you would first create a bitmap as the back buffer; each frame, you render the scene to the back buffer, and then use blit() to copy the pixels to the screen.<br />In page flipping, you don&#39;t touch &quot;screen&quot; at all. Instead, you create TWO memory bitmaps, A and B. Set A as the front buffer by calling show_video_bitmap() on it, and render your scene to B. When you&#39;re done, swap the buffers: call show_video_bitmap() on B, which will be displayed instantly, and render the next frame to A (which will be invisible). The idea behind this is not to copy pixel data, but to change the video memory location from which the hardware&#39;s DAC reads pixels.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Wed, 28 Feb 2007 18:36:42 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Does create_video_bitmap(); give you a memory bitmap and not a video bitmap?</p><p>And by rendering, you mean calling draw_sprite() and probably drawing on the BITMAP returned by create_video_bitmap? Thanks!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (armond)</author>
		<pubDate>Wed, 28 Feb 2007 18:53:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Does create_video_bitmap(); give you a memory bitmap and not a video bitmap?
</p></div></div><p>
Please read TFM.<br />create_bitmap() -&gt; memory bitmap<br />create_video_bitmap() -&gt; video bitmap (hence the &#39;video&#39; in the function name).</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
And by rendering, you mean calling draw_sprite() and probably drawing on the BITMAP returned by create_video_bitmap? Thanks!
</p></div></div><p>

Rendering your scene. I don&#39;t know what else to call it. Draw all the sprites and lines and whatnot, basically everything you want to display, to the back buffer, not to the screen. Most likely, this will involve draw_sprite(), but it doesn&#39;t have to. <br />That&#39;s what frame buffering is all about: Since you cannot draw all objects at once, the user would normally be able to watch you drawing the scene: First, the background would appear, then the tile map, then some characters, and finally, some overlay like score, level, text, health bars etc. You don&#39;t want this, because it looks ugly. So you draw to an invisible buffer instead, and when you&#39;re done drawing everything, you make the contents of the buffer visible in one go - either by copying the pixel data with a call to blit(), or by changing the location the video hardware reads from (show_video_bitmap()).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Wed, 28 Feb 2007 19:09:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Thank you, I&#39;ve been reading TFM for several hours now. I just wanted to be sure and that&#39;s why I asked. Now, I tried changing from video bitmap to memory bitmap as you said. However, it doesn&#39;t show anything on the screen. When I use video bitmaps, the background overlaps all other sprites. But I&#39;m sure I&#39;m rendering and drawing the background first. You can see my trial-and-error stuff through comments here in my code. I also made a variable called frameCounter so I&#39;d be changing the buffer on which to draw on in its every increment. Thanks!</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="p">#include "globals.h"</span></td></tr><tr><td class="number">2</td><td>&#160;</td></tr><tr><td class="number">3</td><td>&#160;</td></tr><tr><td class="number">4</td><td>GameBackground::GameBackground<span class="k2">(</span><a href="http://www.allegro.cc/manual/BITMAP" target="_blank"><span class="a">BITMAP</span></a><span class="k3">*</span> bitmap, BackgroundScrollType scrollType, <span class="k1">int</span> scrollSpeed, <span class="k1">int</span> x, <span class="k1">int</span> y<span class="k2">)</span></td></tr><tr><td class="number">5</td><td><span class="k2">{</span></td></tr><tr><td class="number">6</td><td>    this-&gt;bitmap <span class="k3">=</span> bitmap<span class="k2">;</span></td></tr><tr><td class="number">7</td><td>    this-&gt;scrollType <span class="k3">=</span> scrollType<span class="k2">;</span></td></tr><tr><td class="number">8</td><td>    this-&gt;scrollSpeed <span class="k3">=</span> scrollSpeed<span class="k2">;</span></td></tr><tr><td class="number">9</td><td>    this-&gt;x <span class="k3">=</span> x<span class="k2">;</span></td></tr><tr><td class="number">10</td><td>    this-&gt;y <span class="k3">=</span> y<span class="k2">;</span></td></tr><tr><td class="number">11</td><td>    </td></tr><tr><td class="number">12</td><td>    frameCounter <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td>    </td></tr><tr><td class="number">14</td><td>    <span class="c">//tmpBuffer = create_bitmap(SCREEN_W, SCREEN_H);</span></td></tr><tr><td class="number">15</td><td>    <span class="c">//bufferA = create_video_bitmap(SCREEN_W, SCREEN_H);</span></td></tr><tr><td class="number">16</td><td>    <span class="c">//bufferB = create_video_bitmap(SCREEN_W, SCREEN_H);</span></td></tr><tr><td class="number">17</td><td>    bufferA <span class="k3">=</span> <a href="http://www.allegro.cc/manual/create_bitmap" target="_blank"><span class="a">create_bitmap</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/SCREEN_W" target="_blank"><span class="a">SCREEN_W</span></a>, <a href="http://www.allegro.cc/manual/SCREEN_H" target="_blank"><span class="a">SCREEN_H</span></a><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>    bufferB <span class="k3">=</span> <a href="http://www.allegro.cc/manual/create_bitmap" target="_blank"><span class="a">create_bitmap</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/SCREEN_W" target="_blank"><span class="a">SCREEN_W</span></a>, <a href="http://www.allegro.cc/manual/SCREEN_H" target="_blank"><span class="a">SCREEN_H</span></a><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td><span class="k2">}</span>    </td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>GameBackground::~GameBackground<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">22</td><td><span class="k2">{</span></td></tr><tr><td class="number">23</td><td>    <a href="http://www.allegro.cc/manual/destroy_bitmap" target="_blank"><span class="a">destroy_bitmap</span></a><span class="k2">(</span>bufferA<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">24</td><td>    <a href="http://www.allegro.cc/manual/destroy_bitmap" target="_blank"><span class="a">destroy_bitmap</span></a><span class="k2">(</span>bufferB<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">25</td><td><span class="k2">}</span></td></tr><tr><td class="number">26</td><td>&#160;</td></tr><tr><td class="number">27</td><td><span class="k1">void</span> GameBackground::update<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">28</td><td><span class="k2">{</span></td></tr><tr><td class="number">29</td><td>    scrollBackground<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">30</td><td><span class="k2">}</span></td></tr><tr><td class="number">31</td><td>&#160;</td></tr><tr><td class="number">32</td><td><span class="k1">void</span> GameBackground::scrollBackground<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">33</td><td><span class="k2">{</span></td></tr><tr><td class="number">34</td><td>    <span class="k1">switch</span><span class="k2">(</span>scrollType<span class="k2">)</span></td></tr><tr><td class="number">35</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">36</td><td>        <span class="k1">case</span> HORIZONTAL_LEFT:</td></tr><tr><td class="number">37</td><td>            scrollLeft<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">38</td><td>            <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">39</td><td>        default:</td></tr><tr><td class="number">40</td><td>            <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">41</td><td>    <span class="k2">}</span>    </td></tr><tr><td class="number">42</td><td><span class="k2">}</span></td></tr><tr><td class="number">43</td><td>&#160;</td></tr><tr><td class="number">44</td><td><span class="k1">void</span> GameBackground::draw<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">45</td><td><span class="k2">{</span></td></tr><tr><td class="number">46</td><td>    <span class="c">//draw_sprite(GameManager::buffer, tmpBuffer, 0, 0);</span></td></tr><tr><td class="number">47</td><td>    <span class="c">//draw_sprite(GameManager::videoBuffer, tmpBuffer, 0, 0);</span></td></tr><tr><td class="number">48</td><td>    <span class="k1">if</span> <span class="k2">(</span>frameCounter % <span class="n">2</span> <span class="k3">=</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">49</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">50</td><td>        <a href="http://www.allegro.cc/manual/show_video_bitmap" target="_blank"><span class="a">show_video_bitmap</span></a><span class="k2">(</span>bufferA<span class="k2">)</span><span class="k2">;</span>          </td></tr><tr><td class="number">51</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">52</td><td>    <span class="k1">else</span></td></tr><tr><td class="number">53</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">54</td><td>        <a href="http://www.allegro.cc/manual/show_video_bitmap" target="_blank"><span class="a">show_video_bitmap</span></a><span class="k2">(</span>bufferB<span class="k2">)</span><span class="k2">;</span>        </td></tr><tr><td class="number">55</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">56</td><td>    frameCounter<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">57</td><td><span class="k2">}</span>    </td></tr><tr><td class="number">58</td><td>&#160;</td></tr><tr><td class="number">59</td><td><span class="k1">void</span> GameBackground::setScrollSpeed<span class="k2">(</span><span class="k1">int</span> speed<span class="k2">)</span></td></tr><tr><td class="number">60</td><td><span class="k2">{</span></td></tr><tr><td class="number">61</td><td>    scrollSpeed <span class="k3">=</span> speed<span class="k2">;</span></td></tr><tr><td class="number">62</td><td><span class="k2">}</span>    </td></tr><tr><td class="number">63</td><td>&#160;</td></tr><tr><td class="number">64</td><td><span class="k1">void</span> GameBackground::scrollLeft<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">65</td><td><span class="k2">{</span></td></tr><tr><td class="number">66</td><td>    x <span class="k3">-</span><span class="k3">=</span> scrollSpeed<span class="k2">;</span></td></tr><tr><td class="number">67</td><td>    </td></tr><tr><td class="number">68</td><td>    <span class="k1">int</span> bw <span class="k3">=</span> bitmap-&gt;w<span class="k2">;</span></td></tr><tr><td class="number">69</td><td>    <span class="k1">int</span> bh <span class="k3">=</span> bitmap-&gt;h<span class="k2">;</span></td></tr><tr><td class="number">70</td><td>    </td></tr><tr><td class="number">71</td><td>    <span class="k1">int</span> xOffSet <span class="k3">=</span> <span class="k2">(</span><a href="http://www.allegro.cc/manual/SCREEN_W" target="_blank"><span class="a">SCREEN_W</span></a> <span class="k3">+</span> bw<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">72</td><td>    </td></tr><tr><td class="number">73</td><td>    <span class="k1">if</span> <span class="k2">(</span> x <span class="k3">&gt;</span> bw <span class="k3">|</span><span class="k3">|</span> x <span class="k3">&lt;</span> <span class="k3">-</span><span class="k2">(</span>bw<span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">74</td><td>    <span class="k2">{</span> </td></tr><tr><td class="number">75</td><td>        x <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">76</td><td>    <span class="k2">}</span>    </td></tr><tr><td class="number">77</td><td>    </td></tr><tr><td class="number">78</td><td>    <span class="k1">int</span> newX <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">79</td><td>    </td></tr><tr><td class="number">80</td><td>    <span class="k1">for</span> <span class="k2">(</span><span class="k1">int</span> i <span class="k3">=</span> <span class="k3">-</span><span class="k2">(</span>bw<span class="k2">)</span><span class="k2">;</span> i <span class="k3">&lt;</span> <span class="k2">(</span>xOffSet<span class="k2">)</span><span class="k2">;</span> i <span class="k3">+</span><span class="k3">=</span> bw<span class="k2">)</span></td></tr><tr><td class="number">81</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">82</td><td>        newX <span class="k3">=</span> <span class="k2">(</span>x <span class="k3">+</span> i<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">83</td><td>        </td></tr><tr><td class="number">84</td><td>        <span class="k1">for</span> <span class="k2">(</span><span class="k1">int</span> j <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> j <span class="k3">&lt;</span> <a href="http://www.allegro.cc/manual/SCREEN_H" target="_blank"><span class="a">SCREEN_H</span></a><span class="k2">;</span> j <span class="k3">+</span><span class="k3">=</span> bh<span class="k2">)</span></td></tr><tr><td class="number">85</td><td>        <span class="k2">{</span></td></tr><tr><td class="number">86</td><td>            <span class="c">//draw tile</span></td></tr><tr><td class="number">87</td><td>            <span class="c">//Optimization: draw only parts that are visible to the screen            </span></td></tr><tr><td class="number">88</td><td>            <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span> newX <span class="k3">+</span> bw<span class="k2">)</span> <span class="k3">&gt;</span> <span class="n">0</span> <span class="k2">)</span></td></tr><tr><td class="number">89</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">90</td><td>                <span class="k1">if</span> <span class="k2">(</span>frameCounter % <span class="n">2</span> <span class="k3">=</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">91</td><td>                <span class="k2">{</span></td></tr><tr><td class="number">92</td><td>                    <a href="http://www.allegro.cc/manual/draw_sprite" target="_blank"><span class="a">draw_sprite</span></a><span class="k2">(</span>bufferB, bitmap, newX, j<span class="k2">)</span><span class="k2">;</span>      </td></tr><tr><td class="number">93</td><td>                <span class="k2">}</span></td></tr><tr><td class="number">94</td><td>                <span class="k1">else</span></td></tr><tr><td class="number">95</td><td>                <span class="k2">{</span></td></tr><tr><td class="number">96</td><td>                    <a href="http://www.allegro.cc/manual/draw_sprite" target="_blank"><span class="a">draw_sprite</span></a><span class="k2">(</span>bufferA, bitmap, newX, j<span class="k2">)</span><span class="k2">;</span>    </td></tr><tr><td class="number">97</td><td>                <span class="k2">}</span>    </td></tr><tr><td class="number">98</td><td>            <span class="k2">}</span></td></tr><tr><td class="number">99</td><td>            <span class="k1">else</span></td></tr><tr><td class="number">100</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">101</td><td>                <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">102</td><td>            <span class="k2">}</span>    </td></tr><tr><td class="number">103</td><td>                    </td></tr><tr><td class="number">104</td><td>        <span class="k2">}</span>    </td></tr><tr><td class="number">105</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">106</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>


And BTW, I also have a double buffer after the update and draw routines for this class&#39;s object is called. But the pageflip is called first.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (armond)</author>
		<pubDate>Wed, 28 Feb 2007 19:41:48 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I didn&#39;t bother to read through your source, so sorry if this isn&#39;t helping. Anyway, there&#39;s a gereat article on page flipping in the wiki: <a href="http://wiki.allegro.cc/Page_flipping">http://wiki.allegro.cc/Page_flipping</a>. I suggest you read through that and see if it helps at all.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Wed, 28 Feb 2007 20:19:04 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p><b>Tobias:</b> I think you had initially confused Armond because you said to use show_video_bitmap() on <i>memory</i> bitmaps:</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Instead, you create TWO memory bitmaps, A and B. Set A as the front buffer by calling show_video_bitmap() on it...
</p></div></div><p>


<b>Armond:</b> The two simplest ways to render to the screen are Double Buffering and Page Flipping.</p><p>Double Buffering allows you to take certain liberties you can&#39;t with Page Flipping, such as not syncing to the monitor refresh rate and being able to render to the buffer at any point in time. Page Flipping has the advantage of taking less CPU time and being smoother.</p><p>To Double Buffer, all you need to do is have a regular bitmap to draw on as your buffer, and then you blit that to the screen at the end of your game loop. You don&#39;t need to ever call the acquire or release commands using this approach. You can also add the vsync() command to just before the blit to potentially improve the smoothness of the display. (However, poor timer logic or a slow computer may degrade performance when using vsync().)</p><p>To Page Flip, you need to make three BITMAP pointers. Two will be video bitmaps made with create_video_bitmap(), the third will be a reference pointer which swaps between the other two video pages every frame. You must group all of your drawing to the reference bitmap into one chunk that lies between acquire and release commands for the reference bitmap. Once you render everything and release the reference bitmap, call show_video_bitmap() on the reference pointer, then switch the reference pointer to the alternate video bitmap. (Thus the video bitmap you draw to &quot;flips&quot; every frame.)</p><p>Two things to note when you do Page Flipping:</p><p>1. By default, show_video_bitmap() will automatically vsync. You can disable this behaviour, but then the resulting display quality really isn&#39;t much better than Double Buffering.</p><p>2. The very first video bitmap you make with create_video_bitmap() will almost certainly use the same video memory as the screen. (Not really a problem, it just means if you&#39;re going to put more stuff in video memory than the video pages you should probably define the video pages first.</p><p>Hope that helps. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" /></p><p>I personally recommend double buffering because bad things can happen if you do too much stuff between an acquire/release pair. (And because page flipping + Allegro != working properly on my particular computer.)</p><p>--- Kris Asick (Gemini)<br />--- <a href="http://www.pixelships.com">http://www.pixelships.com</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Wed, 28 Feb 2007 20:46:07 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;d do away with the acquire/releases altogether. They&#39;re not actually needed, and mainly just increase the risk of you <span class="cuss"><span>fuck</span></span>ing up somewhere further down the line.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (gnolam)</author>
		<pubDate>Wed, 28 Feb 2007 20:52:55 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I&#39;d do away with the acquire/releases altogether. They&#39;re not actually needed, and mainly just increase the risk of you <span class="cuss"><span>fuck</span></span>ing up somewhere further down the line.
</p></div></div><p>

True for Double Buffering, not true for Page Flipping, since in Page Flipping you render everything directly to video memory. (Thus if you removed the acquire and release commands there, video memory would have to be locked and unlocked for every single call to draw something to video memory. This is why you can remove them with double buffering, since you generally only need to make one render to video memory (the screen) per frame that way.)</p><p>Unless of course you <i>combine</i> double buffering with page flipping, but then you&#39;re just wasting CPU time and eliminating the speed boost page flipping provides.</p><p>--- Kris Asick (Gemini)<br />--- <a href="http://www.pixelships.com">http://www.pixelships.com</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Wed, 28 Feb 2007 21:00:05 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
True for Double Buffering, not true for Page Flipping, since in Page Flipping you render everything directly to video memory.
</p></div></div><p>Nope, gnolam&#39;s right. You <i>never</i> need the acquire/release calls.</p><div class="quote_container"><div class="title">TFM said:</div><div class="quote"><p>
<b>You never need to call the function explicitly</b> as it is low level, and <b>will only give you a speed up if you know what you are doing. Using it wrongly may cause slowdown,</b> or even lock up your program.
</p></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Wed, 28 Feb 2007 21:07:57 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Nope, gnolam&#39;s right. You never need the acquire/release calls.
</p></div></div><p>

Permit me to explain what exactly those commands are doing.</p><p>DirectX, in all its glory, is made in such a way that in order to successfully write to video memory that memory <i>must</i> first be locked so that Windows doesn&#39;t mess with it while a write is happening. This memory lock takes a good amount of CPU time to engage, and while it&#39;s active, making any kind of system call can do bad things.</p><p>Allegro controls the state of this lock with its acquire and release commands. Because video memory must be locked in order to draw to it, Allegro will automatically lock and unlock video memory when you draw to it if you haven&#39;t locked it already.</p><p>So long as you only make one video memory draw per frame, using acquire and release doesn&#39;t save you any time.</p><p>But, when doing proper page flipping, ALL rendering is happening direct to video memory, which means if you don&#39;t enclose all those functions within an acquire/release pair, video memory will be locked and unlocked for every single call to stuff like putpixel, blit, draw_sprite, etc... which will <i>eat</i> CPU time.</p><p>If you&#39;re rendering everything to a buffer, blitting that to video memory and then doing a page flip, that&#39;s essentially combining double buffering with page flipping, which doesn&#39;t give you the speed benefits page flipping is supposed to provide.</p><p>--- Kris Asick (Gemini)<br />--- <a href="http://www.pixelships.com">http://www.pixelships.com</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Thu, 01 Mar 2007 06:07:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
This memory lock takes a good amount of CPU time to engage
</p></div></div><p>Really? So what is &quot;a good amount&quot;, I mean, I&#39;ve never used the acquire/release calls anywhere and I&#39;ve never ran into any problems. How much speed can you actually gain by adding those calls?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Thu, 01 Mar 2007 17:14:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Tobias: I think you had initially confused Armond because you said to use show_video_bitmap() on memory bitmaps:
</p></div></div><p>
You are, of course, right. That is utter nonsense I wrote there.</p><p>Armond:<br />I haven&#39;t really read all of your code there, but on first glance, it looks as if you were allocating the frame buffers inside the background class, which doesn&#39;t look right to me. The background is just one of many objects that draw something onto the back buffer; it has no business with the underlying mechanics of the frame buffering system.<br />IMO, you should split your code up into the following overall modules (no matter what the genre):<br />- A framebuffer module that handles setting up, flipping, and shutting down the frame buffering system. You can either make two classes with the same interface for memory-blitting and page flipping, or one class that can do both. Either way, the public interface should look something like this:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">class</span> cFramebuffer <span class="k2">{</span>
<span class="c">// protected / private members left out.</span>
  public:
    cFramebuffer<span class="k2">(</span><span class="k1">int</span> buffer_method <span class="k3">=</span> MEMORY_BLIT<span class="k2">)</span><span class="k2">;</span> 
<span class="c">// The parameter is only needed if you put all buffer methods into the same class.</span>
<span class="c">// Otherwise, each buffering method would have its own constructor.</span>
<span class="c">// If you have a dedicated class for each buffering method, the member funcs below</span>
<span class="c">// need to be virtual.</span>
    ~cFramebuffer<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
    <span class="k1">void</span> flip<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// takes the appropriate action depending on the buffer method used.</span>
    <a href="http://www.allegro.cc/manual/BITMAP" target="_blank"><span class="a">BITMAP</span></a><span class="k3">*</span> get_backbuffer<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
    <span class="k1">const</span> <span class="k1">char</span><span class="k3">*</span> get_buffer_mode_desc<span class="k2">(</span><span class="k2">)</span> <span class="k1">const</span><span class="k2">;</span> <span class="c">// optional, and useful mainly for debugging purposes;</span>
<span class="k2">}</span><span class="k2">;</span>
</pre></div></div><p>
Of course, this doesn&#39;t have to be a class; were you using plain C, you&#39;d just provide the plain functions in the header and use static variables in the .c file. In C++, though, a class is a much better choice.<br />If you want to go all fancy, make the framebuffer class a singleton, but I suggest you don&#39;t do that for now. The key here is ENCAPSULATION: make sure that nothing except the frame buffer module itself ever touches the internal buffers directly - only through the get_backbuf() method. This gives you more control over who draws what and where to.<br />- A game module that manages your objects, scene, backgrounds, timing, etc. - pretty much everything that is in-game. For drawing, it first calls the global framebuffer&#39;s get_backbuffer() method, draws everything to the bitmap it provides (typically calling its sub-modules&#39; draw() methods), and finally calls framebuffer-&gt;flip(). The game module should - at least for more complex games - be split up into more modules, e.g. one for the background, one for characters, one for timing, etc. A typical drawing routine might look like this:
</p><div class="source-code snippet"><div class="inner"><pre>cGame::draw<span class="k2">(</span><span class="k2">)</span> <span class="k2">{</span>
  <span class="c">// note that this method does not know which frame buffering method is being used.</span>
  <a href="http://www.allegro.cc/manual/BITMAP" target="_blank"><span class="a">BITMAP</span></a><span class="k3">*</span> backbuf <span class="k3">=</span> framebuffer-&gt;get_backbuffer<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// get a valid back buffer from the framebuffer module</span>
  <a href="http://www.delorie.com/djgpp/doc/libc/libc_48.html" target="_blank">assert</a><span class="k2">(</span>backbuf<span class="k2">)</span><span class="k2">;</span> <span class="c">// make sure we really have a back buffer!</span>
  <span class="c">// OK, now draw our scene back-to-front:</span>
  background-&gt;draw<span class="k2">(</span>backbuf, scroll_x, scroll_y<span class="k2">)</span><span class="k2">;</span>
  <span class="k1">for</span> <span class="k2">(</span><span class="k1">int</span> i <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> i <span class="k3">&lt;</span> num_actors<span class="k2">;</span> <span class="k3">+</span><span class="k3">+</span>i<span class="k2">)</span>
    actor<span class="k3">&lt;</span>i&gt;-&gt;draw<span class="k2">(</span>backbuf, scroll_x, scroll_y<span class="k2">)</span><span class="k2">;</span>
  <span class="c">// if you want to display overlay like scores, health bars, etc., here's the place</span>
  framebuffer-&gt;flip<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Tell the framebuffer module we're done with this frame.</span>
<span class="k2">}</span>
</pre></div></div><p>
- A &quot;main&quot; module that sets up allegro, creates a global frame buffer object, spawns the game module, and finally cleans up by destroying the game and frame buffer objects and exiting allegro.</p><p>The nice thing about this approach is that once you have one frame buffering system ready to go, the interface can be reused, so if you later want to add another option, you only need to change the frame buffer module, and add a few lines to the main module, while all the other modules can remain unchanged.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Thu, 01 Mar 2007 18:20:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Really? So what is &quot;a good amount&quot;, I mean, I&#39;ve never used the acquire/release calls anywhere and I&#39;ve never ran into any problems.
</p></div></div><p>
&quot;A good amount&quot; can be anywhere from near instantanious to several tens to hundreds of milliseconds, or more. Since it involves a mutex lock, if something else is holding that lock, your program will pause until the lock becomes free. There could be other factors involved too.. I&#39;m not very familiar with the Windows code.</p><p>But as mentioned, as long as you draw to the screen/video bitmaps, the screen must be acquired no matter what. And if all you do is blit a memory buffer to the screen, there&#39;s nothing to gain since Allegro will acquire for you.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kitty Cat)</author>
		<pubDate>Thu, 01 Mar 2007 18:36:59 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
But as mentioned, as long as you draw to the screen/video bitmaps, the screen must be acquired no matter what. And if all you do is blit a memory buffer to the screen, there&#39;s nothing to gain since Allegro will acquire for you.
</p></div></div><p>Yeah, I know. I&#39;d just like to know what kind of speed differences we&#39;re talking about.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Thu, 01 Mar 2007 19:26:40 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>For blitting a memory buffer to screen: zero.<br />For drawing directly to video memory: depends. Hugely.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Thu, 01 Mar 2007 19:30:10 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
For drawing directly to video memory: depends.
</p></div></div><p>On what. Amount of stuff getting drawn, obviously, but how about hardware? Anything else? If I don&#39;t see a big difference on my system, could there still be a big difference on another system?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Thu, 01 Mar 2007 19:38:36 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p><b>Kauhiz:</b> It is dependent on a number of factors, but the speed difference can be insane if you do enough writes.</p><p>For instance, if you draw 200 objects directly to the screen on one update, but fail to call the acquire and release commands first, those 200 objects will each call those commands themselves. Thus instead of one locking operation you suddenly have 200.</p><p>And again, this is only if you do <i>all</i> of your drawing directly to video memory. If you draw everything to a memory buffer then blit that to video memory, the lock is only engaged once because regular bitmaps don&#39;t need to be locked to be written to.</p><p>Here&#39;s a quick example you can test:</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="c">// Example 1 - No Locking</span></td></tr><tr><td class="number">2</td><td>v <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">3</td><td><span class="k1">do</span> <span class="k2">{</span></td></tr><tr><td class="number">4</td><td>  v<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">5</td><td>  <span class="k1">for</span> <span class="k2">(</span>z <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> z <span class="k3">&lt;</span> <span class="n">640</span><span class="k2">;</span> z<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span> <span class="k1">for</span> <span class="k2">(</span>zz <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> zz <span class="k3">&lt;</span> <span class="n">480</span><span class="k2">;</span> zz<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span></td></tr><tr><td class="number">6</td><td>    <a href="http://www.allegro.cc/manual/putpixel" target="_blank"><span class="a">putpixel</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>,z,zz,<a href="http://www.allegro.cc/manual/makecol" target="_blank"><span class="a">makecol</span></a><span class="k2">(</span>z<span class="k3">+</span>v,zz-v,<span class="k2">(</span>z<span class="k3">+</span>zz<span class="k2">)</span><span class="k3">*</span>v<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">7</td><td><span class="k2">}</span> <span class="k1">while</span> <span class="k2">(</span><span class="k3">!</span><a href="http://www.allegro.cc/manual/keypressed" target="_blank"><span class="a">keypressed</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">8</td><td>&#160;</td></tr><tr><td class="number">9</td><td><span class="c">// Example 2 - With Locking</span></td></tr><tr><td class="number">10</td><td>v <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">11</td><td><span class="k1">do</span> <span class="k2">{</span></td></tr><tr><td class="number">12</td><td>  v<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td>  <a href="http://www.allegro.cc/manual/acquire_screen" target="_blank"><span class="a">acquire_screen</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">14</td><td>    <span class="k1">for</span> <span class="k2">(</span>z <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> z <span class="k3">&lt;</span> <span class="n">640</span><span class="k2">;</span> z<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span> <span class="k1">for</span> <span class="k2">(</span>zz <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> zz <span class="k3">&lt;</span> <span class="n">480</span><span class="k2">;</span> zz<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span></td></tr><tr><td class="number">15</td><td>      <a href="http://www.allegro.cc/manual/putpixel" target="_blank"><span class="a">putpixel</span></a><span class="k2">(</span><a href="http://www.allegro.cc/manual/screen" target="_blank"><span class="a">screen</span></a>,z,zz,<a href="http://www.allegro.cc/manual/makecol" target="_blank"><span class="a">makecol</span></a><span class="k2">(</span>z<span class="k3">+</span>v,zz-v,<span class="k2">(</span>z<span class="k3">+</span>zz<span class="k2">)</span><span class="k3">*</span>v<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">16</td><td>  <a href="http://www.allegro.cc/manual/release_screen" target="_blank"><span class="a">release_screen</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td><span class="k2">}</span> <span class="k1">while</span> <span class="k2">(</span><span class="k3">!</span><a href="http://www.allegro.cc/manual/keypressed" target="_blank"><span class="a">keypressed</span></a><span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr></tbody></table></div></div><p>

You&#39;re going to find that Example 2 runs <i>much</i> faster than Example 1.</p><p>Note however that not all operating systems require locking. For instance, these two examples will likely run the same speed if you run them in DOS.</p><p>--- Kris Asick (Gemini)<br />--- <a href="http://www.pixelships.com">http://www.pixelships.com</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Thu, 01 Mar 2007 21:37:52 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
If you draw everything to a memory buffer then blit that to video memory, the lock is only engaged once because regular bitmaps don&#39;t need to be locked to be written to.
</p></div></div><p>Why does everyone keep saying this? <img src="http://www.allegro.cc/forums/smileys/tongue.gif" alt=":P" /> I&#39;M NOT RETARDED! <img src="http://www.allegro.cc/forums/smileys/rolleyes.gif" alt="::)" /> Besides, I knew that much before the thread anyway.</p><p>Sorry, Kris, but you really didn&#39;t help that much. Well, apart from the operating system thing.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Thu, 01 Mar 2007 23:28:47 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p><b>Kauhiz:</b> We&#39;re helping you perfectly fine, you just don&#39;t like our answers. You want to know exactly what factors go into the delay of locking a video bitmap. The trouble is, <i>everything</i> is a factor. The speed of the computer, the speed of the video card, the speed of your RAM, the speed of the video RAM, the state of your CPU registers... no matter what computer you are on the lock can take anywhere from an insignificant amount of CPU time to a rather large amount of CPU time to engage. There&#39;s absolutely no way to calculate or control it so there&#39;s no sense trying to.</p><p>All you need to understand is that locking and unlocking a video bitmap multiple times in one frame is slower than locking and unlocking once per frame. By how much? There&#39;s no way to know until you do it.</p><p>--- Kris Asick (Gemini)<br />--- <a href="http://www.pixelships.com">http://www.pixelships.com</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kris Asick)</author>
		<pubDate>Thu, 01 Mar 2007 23:43:09 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
We&#39;re helping you perfectly fine, you just don&#39;t like our answers.
</p></div></div><p>Nope, you&#39;re not answering my question. I don&#39;t really need help, since I don&#39;t use allegro for graphics anymore, I&#39;m just curious.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The speed of the computer, the speed of the video card, the speed of your RAM, the speed of the video RAM, the state of your CPU registers...
</p></div></div><p>That&#39;s the answer I was looking for, thanks.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Kauhiz)</author>
		<pubDate>Fri, 02 Mar 2007 01:05:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The speed of the computer, the speed of the video card, the speed of your RAM, the speed of the video RAM, the state of your CPU registers...
</p></div></div><p>
...the graphics mode you&#39;re in, directx version, other active processes...
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Tobias Dammers)</author>
		<pubDate>Fri, 02 Mar 2007 01:31:11 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Thank you people. I think you&#39;ve done everything you can to help this poor fella. It&#39;s up to me now to incorporate your ideas with my code. If I succeed, I&#39;ll get back at you and post the working code. Thanks!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (armond)</author>
		<pubDate>Sat, 03 Mar 2007 13:42:34 +0000</pubDate>
	</item>
</rss>
