سؤال

Situation: I currently am trying to render a few things (images and some text) using SDL_image and SDL in C++. However I am coming across some problems which look to be like buffering issues however with my attempts to fix this, Ive been stuck for hours with no avail.

Problem: When rendering, the screen gives a Single-buffering like effect where the image in its previous position is still being displayed on screen like it would in the last buffer. I suspect the problem lies somewhere within my draw function (main loop function)

problem

Here is my main.cpp:

#include "SDL.h" 
#include "SDL_image.h"
#include "Player.h"
#include "Values.h"
#include <string>
#include <sstream>
#include "SDL_ttf.h"
#include "Timer.h"


//The surfaces that will be used
SDL_Surface *message = NULL;
SDL_Surface *background = NULL;
SDL_Surface *text = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *startStop = NULL;
SDL_Surface *pauseMessage = NULL;
SDL_Surface *seconds = NULL;
//The font thats going to be used
TTF_Font *font = NULL;
//The colour of the font
SDL_Color textColor = {255,255,255};

Player ** player;

Timer myTimer;

bool quit = false;
Uint32 start = 0;
bool running = true;

int fame = 0;
bool cap = true;
//Timer fps;

SDL_Event event;

void clean_up()
{
    //Free the surfaces
    //SDL_FreeSurface( message );
    player[0]->clean();
    SDL_FreeSurface( background );
    SDL_FreeSurface( seconds );
    SDL_FreeSurface(startStop);
    SDL_FreeSurface(pauseMessage);
    TTF_CloseFont(font);
    TTF_Quit();
    //Quit SDL
    SDL_Quit();
}

SDL_Surface *load_image( std::string filename )
{
    //Temporary storage for the image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image
    loadedImage = SDL_LoadBMP( filename.c_str() );

    //If nothing went wrong in loading the image
    if( loadedImage != NULL )
    {
        //Create an optimized image
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old image
        SDL_FreeSurface( loadedImage );
    }

    //Return the optimized image
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
    //Make a temporary rectangle to hold the offsets
    SDL_Rect offset;

    //Give the offsets to the rectangle
    offset.x = x;
    offset.y = y;

    //Blit the surface
    SDL_BlitSurface( source, NULL, destination, &offset );
}

bool loadFiles()
{
    player[0]->load_files();
    background = load_image( "Floor1.bmp" );

    //Open the font
    font = TTF_OpenFont("lazy.ttf",28);

    //If there was a problem in loadin the font 
    if(font == NULL)
    {
        return false;
    }
    return true;
}

bool init()
{
    //Initialize all SDL subsystems
    SDL_Init( SDL_INIT_EVERYTHING );

    //Set up the screen
    //screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 0,
      SDL_HWSURFACE | SDL_DOUBLEBUF );
    //Initialize SDL_tff
    if(TTF_Init() == -1)
    {
        return false;
    }

    //Set the window caption
    SDL_WM_SetCaption( "10 seconds", NULL );    

    player = new Player*[1];
    player[0] = new Player(screen);
    loadFiles();



    return true;
};

void mainloop()
{
    startStop = TTF_RenderText_Solid(font, "Press S to start or stop the timer", textColor);
    pauseMessage = TTF_RenderText_Solid(font, "Press P to pause or unpause the timer", textColor);

    myTimer.start();
    while (quit == false)
    {
        //While there's events to handle 
        while( SDL_PollEvent( &event ) ) 
        { 
            //Handle events for the dot 
            player[0]->handleInput(event); 

            if (event.type == SDL_KEYDOWN)
            {
                //if s was pressed
                if(event.key.keysym.sym == SDLK_s)
                {
                    //if the timer is running
                    if(myTimer.isStarted() == true)
                    {
                        //Stop the timer
                        myTimer.stop();                     
                    }
                    else
                    {
                        //Start the timer
                        myTimer.start();
                    }
                }
                if (event.key.keysym.sym == SDLK_p)
                {
                    //If the timer is paused
                    if (myTimer.isPaused() == true)
                    {
                        //Unpause the timer
                        myTimer.unpause();
                    }
                    else
                    {
                        //Pause the timer
                        myTimer.pause();
                    }
                }
            }
                //If the user has Xed out the window 
            else if( event.type == SDL_QUIT ) 
            { 
                //Quit the program 
                quit = true; 
            }

        }

        //Apply all images to screen
        apply_surface( 0, 0, background, screen );
        apply_surface( ( SCREEN_WIDTH - startStop->w ) / 2, 200, startStop, screen );
            apply_surface( ( SCREEN_WIDTH - pauseMessage->w ) / 2, 250, pauseMessage, screen );
        //The timers time as a string
            std::stringstream time;
            //convert the timers time to a string
            time << "Timer: " << myTimer.getTicks() / 1000.f;
            seconds = TTF_RenderText_Solid( font, time.str().c_str(), textColor );
            //Render the time surface
            apply_surface( ( SCREEN_WIDTH - seconds->w ) / 2, 0, seconds, screen );
            /Free the time surface 

        //PlayerHandling
        player[0]->move();
        player[0]->setCamera();
        player[0]->draw();
            SDL_FreeSurface( seconds );

        SDL_Flip(screen);
    }
}



int main( int argc, char* args[] )
{

    init();
    mainloop();
    clean_up();   

    return 0;
}
هل كانت مفيدة؟

المحلول

It seems, judging by the graphical effect and the fact that your background is all black, your code fails in loading the background. You can test it by just filling background with a color.

background = SDL_CreateRGBSurface( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 );
SDL_FillRect( background, NULL, SDL_MapRGBA( background->format, 125, 125, 0, 255) );

Since SDL does not break or warn you if you try using a SDL_Surface* that points to NULL, I also suggest adding an error message to your load_image :

SDL_Surface *load_image( std::string filename )
{
    //Temporary storage for the image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image
    loadedImage = SDL_LoadBMP( filename.c_str() );

    //If nothing went wrong in loading the image
    if( loadedImage != NULL )
    {
        //Create an optimized image
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old image
        SDL_FreeSurface( loadedImage );
    } else 
    {
        std::cout << "ERROR : Failed to load image : " << filename << std::endl;
    }

    //Return the optimized image
    return optimizedImage;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top