SDL2 tilemap - 太慢了

时间:2013-09-03 11:57:27

标签: c sdl sdl-2

我正在使用SDL2编写一个在每一帧都显示一个tilemap的游戏,但性能太慢了。我写了一个小程序来隔离问题。考虑“temp.bmp”是16x16图像。

#include <stdio.h>

#include "SDL2/SDL.h"
#include "SDL2/SDL_timer.h"
#include "SDL2/SDL_image.h"

int main()
{
    SDL_Window* win;
    SDL_Renderer* ren;
    int x, y;

    SDL_Init(SDL_INIT_VIDEO);
    SDL_CreateWindowAndRenderer(800, 600, 0, &win, &ren);
    SDL_Surface* sf = IMG_Load("temp.bmp");
    SDL_Texture* tx = SDL_CreateTextureFromSurface(ren, sf);

    for(;;) {
        Uint32 t = SDL_GetTicks();
        for(x=0; x<800; x+=16) {
            for(y=0; y<600; y+=16) {
                SDL_Rect src = { 0, 0, 16, 16 };
                SDL_Rect dst = { x, y, 16, 16 };
                SDL_RenderCopy(ren, tx, &src, &dst);
            }
        }
        SDL_RenderPresent(ren);
        printf("%ld ms\n", SDL_GetTicks() - t);
    }
}

运行程序,我发现渲染帧需要大约16ms。这正好是60 FPS(1000/60),这为游戏逻辑留下了空间。另外,我在一台非常快的计算机上运行它。

我很确定我使用了错误的策略,但我不确定什么是正确的策略。也许创建一个大的纹理并且不那么频繁地更新它可能是要走的路,但我找不到任何关于如何将一个纹理复制到另一个纹理的文档。

那么,我怎样才能提高tilemap的性能呢?

4 个答案:

答案 0 :(得分:1)

this页面上,它提到SDL_RENDERER_PRESENTVSYNC标志表示您已同步刷新率。 试试这个

    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

答案 1 :(得分:1)

在我的vsync系统上,SDL_RenderPresent()之前有足够的额外时间(~15ms):

#include <stdio.h>
#include <stdlib.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>

int main( int argc, char** argv )
{
    SDL_Window* win;
    SDL_Renderer* ren;
    int x, y;

    SDL_Init( SDL_INIT_VIDEO );

    win = SDL_CreateWindow
        ( 
        "Window", 
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
        800, 600, 
        0 
        );

    ren = SDL_CreateRenderer
        ( 
        win, 
        -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
        );

    for(;;) 
    {
        Uint32 t = SDL_GetTicks();
        for(x=0; x<800; x+=16) 
        {
            for(y=0; y<600; y+=16) 
            {
                SDL_Rect dst = { x, y, 16, 16 };
                SDL_SetRenderDrawColor( ren, rand()%255, rand()%255, rand()%255, 255 );
                SDL_RenderFillRect( ren, &dst );
            }
        }

        // adjust this up/down to figure out how much extra time you have
        // stop when you start seeing frame times exceeding ~16ms
        SDL_Delay( 15 );

        SDL_RenderPresent(ren);
        printf("%ld ms\n", SDL_GetTicks() - t);
    }
}

答案 2 :(得分:0)

您可以先使用SDL_SetRenderTarget渲染为大纹理。那个纹理比每帧只绘制一次。

即。类似的东西:

Uint32 fmt;
SDL_QueryTexture(tx, &fmt, NULL, NULL, NULL);
SDL_Texture* tm = SDL_CreateTexture(ren, fmt, SDL_TEXTUREACCESS_TARGET, 800, 600);
SDL_SetRenderTarget(ren, tm);
// Your draw loop here
SDL_SetRenderTarget(ren, NULL);
// Real draw loop only needs to RenderCopy tm

答案 3 :(得分:0)

它是由图形驱动程序强制的垂直同步(opengl后端)。它由用户控制,并且应用程序本身无法更改。