質問

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