Question

I have gone through the other questions concerning this and cant seem to get the answer i'm looking for. My current game runs at 60 fps taking 9.5 ms/frame in debug mode(3.8 ms/frame in release mode). And this is with player, enemies, and the map all blitted onto the screen which doesn't seem to cause a drop in fps at all, but when I blit my 1024x768 BG image it drops to 27-30 FPS and now renders each frame at 33 ms/frame. heres the game loop---

while(!quit)
{
    if(SDL_PollEvent(&event))
    {
        quit = Sys->isQuitGame(event);
    }

    fps->timerReset();
    blit_surface(bg,Sys->screen,0,0);//HERE'S THE PROBLEM!
    mapItem.RedrawingItems(Sys->screen, Sys->map);
    movement = input->Keyboard(key, Sys->screen, player);
    enemies.moveAllEnemies(Sys->map, player );
    player->move(movement, Sys->map);
    player->DrawPlayer(Sys->screen);
    enemies.draw(Sys->screen);

    SDL_Flip(Sys->screen);
    SDL_FillRect(Sys->screen, NULL, SDL_MapRGB( Sys->screen->format, 0xFF, 0xFF, 0xFF ));

    renderTime = calculatingFps->get_ticks();
    frame++;
    if(calculatingFps->get_ticks() > 1000) 
    {
        renderTime -= totalDelay;
        totalDelay = 0;
        stringstream Afps;
        Afps <<"fps: " <<frame/ (calculatingFps->get_ticks() / 1000.f)<<
                " ---- RenderTimePerFrame: "<<(float)renderTime / (float)frame<<"/ms";
        SDL_WM_SetCaption( Afps.str().c_str(), NULL);
        Game::FPS = frame/ (calculatingFps->get_ticks() / 1000.f);
        calculatingFps->timerReset();
        frame = 0;
        renderTime = 0;
    }
    if(frameRenderedTooFast(fps))
    {
        totalDelay += (remainingTime(fps));
        SDL_Delay(remainingTime(fps));
    }
}

So that one blit of that img manages to low the fps by half, I must be missing something? By the way I dont think it is SDL_DisplayFormat, I have that code already, heres the snippit of code that deals with img loading ---

SDL_Surface* altSDL::load_image(std::string filename)  
{
    SDL_Surface* loadedImage = NULL;

    SDL_Surface* optimizedImage = NULL;

    loadedImage = IMG_Load( filename.c_str() );

    if( loadedImage != NULL )
    {
        optimizedImage = SDL_DisplayFormat( loadedImage );        
        SDL_FreeSurface( loadedImage );
    }
    else
    {
        Failure* fail;
        fail = Failure::getInstance();
        fail->failLog(filename);
    }

    if( optimizedImage != NULL )
    {
        Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0xFF, 0, 0xFF );
        SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
    }

    return optimizedImage;
}

I want to blit it once or only every once in awhile but there is character movement on every frame, so waiting for movement then re-blit is useless. Do I have to use setVideoMode on a separate surface for the background or something?. Can anyone help me?

Was it helpful?

Solution

The problem might be in SDL_SetColorKey. When you set the colorkey you give the flags of optimized image to SDL_MapRGB. Instead give SDL_MapRGB the flags of the display surface ( Sys->screen apparently ). ( Setting color key might slow the blitting process despite the flags.)

    Uint32 colorkey = SDL_MapRGB( video_surface->format, 0xFF, 0, 0xFF );
    SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );

Looks like the first draw on the screen is the background surface so i don't see why would you even need to set the SDL_SetColorKey. Just remove it. On the same note, the call SDL_FillRect(Sys->screen,NULL,SDL_MapRGB(Sys->screen->format, 0xFF, 0xFF, 0xFF )) is also superfluous if the background surface covers the whole screen.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top