Блиттинг фона SDL замедляет игру

Я рассмотрел другие вопросы, касающиеся этого, и, похоже, не могу получить ответ, который ищу. Моя текущая игра работает со скоростью 60 кадров в секунду, занимая 9,5 мс/кадр в режиме отладки (3,8 мс/кадр в режиме выпуска). И это с игроком, врагами и картой, выведенными на экран, что, кажется, вообще не вызывает падения частоты кадров, но когда я сокращаю свое изображение BG 1024x768, оно падает до 27-30 кадров в секунду и теперь рендерит каждый кадр. при 33 мс/кадр. Вот игровой цикл ---

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));
    }
}

Так что один блит этого img может снизить fps вдвое, я должен что-то упустить? Кстати, я не думаю, что это SDL_DisplayFormat, у меня уже есть этот код, вот фрагмент кода, который имеет дело с загрузкой img ---

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;
}

Я хочу блитить его один раз или только время от времени, но в каждом кадре есть движение персонажа, поэтому ждать движения, а затем повторно блитить бесполезно. Должен ли я использовать setVideoMode на отдельной поверхности для фона или что-то в этом роде? Может кто-нибудь помочь мне?


person DeathB4Allegiance    schedule 26.06.2013    source источник
comment
Colorkey сделал свое дело? Я любопытный.   -  person    schedule 27.06.2013
comment
да, это было. Извините, я оставил комментарий в ответном ответе, поблагодарив его, но не упомянул об этом здесь. В принципе, зачем добавлять прозрачность к фону, который покрывает весь экран, это просто ОГРОМНАЯ трата ресурсов процессора.   -  person DeathB4Allegiance    schedule 29.07.2015


Ответы (1)


Проблема может быть в SDL_SetColorKey. Когда вы устанавливаете цветовой ключ, вы устанавливаете флаги оптимизированного изображения на SDL_MapRGB. Вместо этого дайте SDL_MapRGB флаги поверхности дисплея (очевидно, Sys->screen). (Установка цветового ключа может замедлить процесс копирования, несмотря на установленные флаги.)

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

Похоже, что первый рисунок на экране — это фоновая поверхность, поэтому я не понимаю, зачем вам вообще нужно устанавливать SDL_SetColorKey. Просто удалите его. В то же время вызов SDL_FillRect(Sys->screen,NULL,SDL_MapRGB(Sys->screen->format, 0xFF, 0xFF, 0xFF )) также является лишним, если фоновая поверхность занимает весь экран.

person Community    schedule 26.06.2013
comment
О боже спасибо!!! Я занимаюсь этим уже 3 дня! Вы пишете обертку, чтобы сэкономить время, чтобы вам не пришлось делать это долго и иногда забывать, что не все должно проходить через нее. Я знал, что что-то упускаю! еще раз спасибо! - person DeathB4Allegiance; 27.06.2013