Clg
Clg

Reputation: 23

Blitting a surface onto another surface (SDL2, C++, VS2015)

I'm working on a small game for school. I tiled an image on screen, but every time my character moves I have to re-tile it (the tiles are behind the character, because it's a grid and the character moves in the cells). I tried to tile everything onto a different surface, and then have that surface blit onto my screen surface to avoid having to retile it every single time and save on process time. It didn't really work, it's like the surface that I tile on forgets what was tiled onto it. It doesn't error it, it just doesn't display the tiled surface on my window surface.

Here's my code (the relevant part at least)

void postaviTiles() {

SDL_BlitSurface(cell, NULL, polje, &offsetcell); //cell

for (int i = 0; i < 89; i++) {
    SDL_Delay(5);
    if (offsetcell.x < 450) {
        offsetcell.x += 50;
        SDL_BlitSurface(cell, NULL, polje, &offsetcell);
    }

    else {
        offsetcell.x = 9;
        offsetcell.y += 50;
        SDL_BlitSurface(cell, NULL, polje, &offsetcell);
    }
    SDL_UpdateWindowSurface(okno);
}

poljezrisano = true;
}

//--------------------------------------------------------------//

void tileCells() {

if (poljezrisano == false) {
    postaviTiles();}

SDL_BlitSurface(polje, NULL, oknoSurface, NULL); //cell
SDL_UpdateWindowSurface(okno);
}

//--------------------------------------------------------------//

Worth mentioning is that tiling it every single time works fine, but I want to tile it once, have that on a surface and then just blit that surface onto my screen surface.

P.S.: Sorry about most of the variables and function names not being in English

Upvotes: 1

Views: 4877

Answers (2)

Jurgen Hissen
Jurgen Hissen

Reputation: 43

Not sure if the code is complete as posted, but it seems you are not initializing offsetcell. That fits the symptom of having nothing show up. Explicit definition of offsetcell might be better than the incremental method you've provided. For example:

for( offsetcell.x = 0; offsetcell.x < 450; offsetcell.x += 50) {
    for( offsetcell.y = 0; offsetcell.y < 450; offsetcell.y += 50) {
        ...
    }
}

Upvotes: 1

user2501659
user2501659

Reputation:

The SDL_BlitSurface takes in a source surface, a clip of that source surface, then the destination surface and a position where you want to display (blit) your source.

The last parameter thats passed to SDL_BlitSurface ignores the width and height, it just takes in the x an y.

Here is a quote from the documentation:

The width and height in srcrect determine the size of the copied rectangle. Only the position is used in the dstrect (the width and height are ignored).

And the prototype for the function:

int SDL_BlitSurface(SDL_Surface*    src,
                const SDL_Rect* srcrect,
                SDL_Surface*    dst,
                SDL_Rect*       dstrect)

That's one thing to keep in mind, not sure if that applies to your case, since your variable names aren't English.

But essentially with this line:

SDL_BlitSurface(cell, NULL, polje, &offsetcell);

You are telling SDL that you want all of cell placed inside polje at the position offsetcell.x and offsetcell.y with the width of cell.w and the height of cell.h.

If you wanted to place cell inside polje using the width and height of offsetcell then you would have to use another blit function, namely SDL_BlitScaled

Here is how I would blit tiles inside a grid (map).

SDL_Surface* grid; // assuming this is the new grid surface that holds the blited tiles
SDL_Surface* tile; // assuming this is a single tile of width 50, height 50
SDL_Surface* windowSurface;
SDL_Window* window;

int TileWidth = 50;
int TileHeight = 50;
int NumTiles = 90;
int TileColumns = 450 / TileWidth; // = 9, so we have a grid of 9X10

bool isFillGridTiles = false;

void FillGridTiles()
{
    for (int i = 0;i < NumTiles; i++)
    {
        auto y = i / TileColumns; // divide to get the y position and...
        auto x = i % TileColumns; // the remainder is the x position inside the grid

        SDL_Rect srcClip;
        srcClip.x = 0;
        srcClip.y = 0;
        srcClip.w = TileWidth;
        srcClip.h = TileHeight;

        SDL_Rect dstClip;
        dstClip.x = x * TileWidth;
        dstClip.y = y * TileHeight;
        dstClip.w = TileWidth;
        dstClip.h = TileHeight;

        SDL_BlitSurface(tile, &srcClip, grid, &dstClip); //since we have the same width and height, we can use SDL_BlitSurface instead of SDL_BlitScaled

    }

    isFillGridTiles = true;
}

void BlitOnScreen()
{
    if(!isFillGridTiles)
    {
        FillGridTiles();
    }

    SDL_BlitSurface(grid, NULL, windowSurface, NULL);
    SDL_UpdateWindowSurface(window);
}

Upvotes: 1

Related Questions