SDL 2.0 how to generate texture on top of everything?

Hi,
I'm doing this Frogger type of game and I want to display a texture on certain coordinates when player approaches the "win" position.
This is what I have:
https://pasteboard.co/INBWcUB.png
In red circles is space where the player (in my example - hamburger) texture should be rendered after achieving this position.


Function which checks if player is on "win" position:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void checkIfWon(SDL_Rect *frogRect, int *lives, bool *play)
{
	if (frogRect->y == 50 + (SCREEN_HEIGHT % 100))
	{
		if ((frogRect->x > 29 && frogRect->x < 61)   || (frogRect->x > 169 && frogRect->x < 201) || 
			(frogRect->x > 309 && frogRect->x < 341) || (frogRect->x > 449 && frogRect->x < 481) ||
			(frogRect->x > 589 && frogRect->x < 621))
		{
			printf("WON!\n");
			*lives = *lives + 1;
			renderWonPosition(frogRect->x, frogRect->y); //function below
			gameOver(frogRect, lives, play);
		}
		else
		{
			printf("LOST!\n");
			gameOver(frogRect, lives, play);
		}
	}
}


Function which should somehow render this texture on top of everything:
1
2
3
4
5
6
void renderWonPosition(int x, int y)
{
	SDL_Rect wonPosition = { x, y, 50, 50 };
	SDL_RenderCopy(gRenderer, frog, NULL, &wonPosition);
	SDL_RenderPresent(gRenderer);
}


This does nothing.
And this is what I have in main():
1
2
3
4
5
6
7
	checkIfWon(&otherRect[0], &lives, &play);
	SDL_SetRenderDrawColor(gRenderer, 2, 100, 64, 1);
	SDL_RenderClear(gRenderer);
	SDL_RenderCopy(gRenderer, plansza, NULL, &otherRect[2]);
	renderMovingObjects(enemiesRect, alliesRect);
	SDL_RenderCopy(gRenderer, frog, NULL, &otherRect[0]);
	SDL_RenderPresent(gRenderer);

To be more clear: the texture should stay until the game ends on its won position.
No idea what should I do in which order. Appreciate any help.
Last edited on
The graphics device consists of two buffers: the back buffer, which is the target of your draw commands, and the front buffer, which is what's currently being displayed on the screen.
What SDL_RenderPresent() does is swap the two buffers, so that what you've drawn so far is sent to the screen and the front buffer becomes available for reuse. Therefore, each call to SDL_RenderPresent() is the same as a frame. What you've done in the code you've posted is
1. Draw a texture to the back buffer.
2. Swap the buffers.
3. Clear the back buffer (SDL_RenderClear())
4. Some more draw commands.
5. Swap the buffers again.
Step #2 means that what you did in step #1 will never be seen (unless you're using v-sync, in which case it will be visible every other frame).

What you need to do is move the SDL_RenderCopy() call so it's after the SDL_RenderClear() call and before the SDL_RenderPresent() call. Furthermore, since you've said the texture should appear on top of everything, you should draw it just before calling SDL_RenderPresent(), after you've drawn everything that's supposed to be behind it.

EDIT: Oh, I forgot: of course, there never needs to be more than one call to SDL_RenderPresent() in your game loop, unless you know exactly what you're doing.
Last edited on
Hello @helios, thank you for your reply.
I didn't know that SDL_RenderPresent() should be called once, thanks for that!
I tried to change some of the code to achieve what I want in more reasonable way, so I used viewports.

This is renderWonPosition function again, but modified:
1
2
3
4
5
6
7
8
9
void renderWonPosition(int x, int y)
{
	SDL_Rect wonPosition = { x, y, 50, 50 };
	SDL_RenderSetViewport(gRenderer, &wonPosition);
	SDL_RenderCopy(gRenderer, frog, NULL, NULL);
	SDL_Rect undoView = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
	SDL_RenderSetViewport(gRenderer, &undoView);

}


When I call this function from main() before SDL_RenderPresent() it works as it should, and I am grateful for that, but as I said - to use this function more reasonably, I need to call it from another function with specific parameters, as followed below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void checkIfWon(SDL_Rect* frogRect, int* lives, bool* play)
{
	static int places = 0;
	static bool pos1 = false, pos2 = false, pos3 = false, pos4 = false, pos5 = false;
	if (frogRect->y == 50 + (SCREEN_HEIGHT % 100))
	{
		if (frogRect->x > 29 && frogRect->x < 61)
		{	
			checkIfPositionWon(&pos1, &places, lives);
			renderWonPosition(frogRect->x, frogRect->y);
			gameOver(frogRect, lives, play);
		}
		else if (frogRect->x > 169 && frogRect->x < 201)
		{
                 .....
                 } // same inside for another 4 else if's 


So... when I call function renderWonPosition() inside checkIfWon() function, nothing happens and I do not understand why.
In main, checkIfWon() is just before SDL_RenderPresent().

Is there a simple explanation for this?
Thanks a lot.
Let's start from the basics. Is renderWonPosition() ever actually called? Did you set a breakpoint or tried to print a value to console from the function?
I've got renderWonPosition() declared at the top of the project, then inside main is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (checkEnemyCollision(otherRect[0], enemiesRect)) {
	gameOver(&otherRect[0], &lives, &play);
	if(play == false) quit = true;
	}

if (checkAllyCollision(&otherRect[0], alliesRect)) {
gameOver(&otherRect[0], &lives, &play);
if (play == false) quit = true;
	}

		if (play)
		{
		SDL_SetRenderDrawColor(gRenderer, 2, 100, 64, 1);
		SDL_RenderClear(gRenderer);
		SDL_RenderCopy(gRenderer, plansza, NULL, &otherRect[2]);
		renderMovingObjects(enemiesRect, alliesRect);
		SDL_RenderCopy(gRenderer, frog, NULL, &otherRect[0]);
		//renderWonPosition(50, 74); //this called like that works perfectly
        	checkIfWon(&otherRect[0], &lives, &play); //inside this function is again renderWonPosition()
		SDL_RenderPresent(gRenderer);
		}


I tried debugging renderWonPosition() inside checkIfWon() function and passed parameters were ok - coordinates of the player were sent correctly, so I really cannot see where the problem is... Or I don't know what am I missing?
Topic archived. No new replies allowed.