0
\$\begingroup\$

I have a function in which I'm looping y and x over my array of sprites. That's a lot of loops, and it is very slow; I'd like to improve the performance.

I would like to only have to build the surface once, calling a buildMap method at the start, and referencing the resulting surface each time I need to blit it without having to loop to find the correct sprite and position.


int aff_map(t_exe *exe)
{
    int         sprite_idx;
    int         y, x;
    SDL_Rect    srcrect, dstrect;

    dstrect.y = 0;
    srcrect.y = 0;
    srcrect.w = TILE;
    srcrect.h = TILE;

    for (y = 0; y < HEIGHT; y++)
    {
        dstrect.x = MARGE_X;

        for (x = 0; x < WIDTH; x++)
        {
            for (sprite_idx= 0; sprite_idx< NB_TILES; sprite_idx++)
            {
                if (exe->map[y][x] == g_assoc_map[sprite_idx].key)
                      srcrect.x = g_assoc_map[sprite_idx].idx * TILE;
                if (SDL_BlitSurface(exe->sprite, &srcrect, exe->screen, &dstrect)
                        < 0)
                    return (err_sdl(SDL_GetError()));
            }

            dstrect.x += TILE;
        }

      dstrect.y += TILE;
    }

  return (EXIT_SUCCESS);
}

Is it possible to build an SDL_Surface before blitting it?

\$\endgroup\$
0
\$\begingroup\$

So from what I could gather what you want to do is to pre-render your level into one surface, so that each frame you can just blit that one surface that you need to.

This is quite straight-forward. You can use SDL_CreateRGBSurface to create a surface of your required size. You can do this in your main() or some other appropriate place that gets only called once.

Now, you just need to change the call SDL_BlitSurface(exe->sprite, &srcrect, exe->screen, &dstrect) to SDL_BlitSurface(exe->sprite, &srcrect, yourPrecreatedSurface, &dstrect). The difference between the two calls is that the former version blits directly to the screen, while the latter uses the surface you created previously.

Now, in your game loop you are probably calling your function aff_map. Instead of doing that, you can now call aff_map before the game enters the main loop, and in the main loop you can just do SDL_BlitSurface(yourPrecreatedSurface, NULL, exe->screen, NULL);

As a side-disclaimer, you might want to take a look at SDL2 and it's accelerated hardware rendering support. You might get a performance boost, and moving on to the newer SDL stuff might really be a good idea. The alternative there is to use textures and render targets instead of surfaces.

\$\endgroup\$
  • 1
    \$\begingroup\$ Wow thank you so much, that's so fast I can't play it now ! Actually I didn't get SDL_BlitSurface's goal which is to copy a surface from another one. I saw it more like the only way to display something on the screen. Should have read its man more carefully. Anyway, thanks ! \$\endgroup\$ – Theo Pnv Dec 12 '16 at 22:40
0
\$\begingroup\$

Your code is a little vague (I suggest using more descriptive names for variables) but I think the issue is that you are trying to render everything every time.

Rather than drawing all of it, only draw what you can see. Calculate the offset tile (if the camera is centered, camera position - half screen) and draw only the number of tiles needed to fill the screen (screen size / tile size).

You can also organize your sprites into a more spacial friendly representation like a grid - every 4x4 square of tiles for example has its own list of sprites. As sprites move, update which square they are in.
Then, only draw sprites in the grids which are visible.

\$\endgroup\$
  • \$\begingroup\$ I renamed a few variables to simplify the question. To put a context on it, this is the function blitting the map in Pacman. So everything is always seen, there's no camera move. That's why I have to blit all of my tiles... I named my images "sprites" because it's a single image representing the different walls of the maze, and I use a sprite_idx to blit the correct wall. But the sprites are always the same, they're static through all the game. Is there any way to "add one by one" the tiles to a SDL_Surface, and THEN to blit it ? \$\endgroup\$ – Theo Pnv Dec 11 '16 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.