SDL2 Fade Text Animation

Hello everybody!
I got a huge problem with changing textes and the fade animation with them.
//---------------------------------------------------------------------------------------------------
Changing texts


3 times right key pressed
next 3 times left key pressed
then single times

I wanted to do, when GameScreen is SplashScreen and keypressed = right then GameScreen is TitleScreen
then if GameScreen is TitleScreen and keypressed again = right then GameScreen is return to splashScreen
and the same with the left key.
//----------------------------------------------------------------------------------------------------
Fade animation
I dont know exactly how to do this but I tried to make something like that : https://github.com/shout12341312312/FadeAnima/tree/master/SDL2%20platformer%20Coding%20Made%20easy

When key pressed it smoothly changing from text to text.

Greetings and thanks for any help

My advice is that you create a kind of state machine for your game states (splashscreen, titlescreen, gamescreen etc). Your state machine will then be able to switch between each of those states whenever you want to.

If you want a smooth transition between your states, I would personally make it so that the screen fades to black whenever a state change should occur.
The complete state change sequence would then be as follows:

  1. The screen fades to black by using a black quad (SDL_Rect) that fills the whole window
  2. When the screen is completely black (the quad’s alpha is 255, i.e full opaque), change CurrentState/CurrentScreen to the new state/screen
  3. Fade away the black quad
  4. When the quad is 100% invisible (the quad’s alpha is 0, i.e transparent), the state change sequence is finished.

This whole sequence can (if you like) occur whenever a key on the keyboard is pressed.

I can see in your code that you’re creating (with ‘new’) your new state and destroying (with ‘delete’) your old state whenever you switch to a new state. Don’t to that. Create all your states (splashscreen, titlescreen etc) at program start, switch between them when you want to and then delete them all when the program shuts down.

Why not to delete the old screen?

And what if I would do on splashscreen an image, then texts on it are
fading? Or maybe render black rect under the image and then I’ll be
working. Sorry for my English btw.

The reason why I think you shouldn’t ‘new’ and ‘delete’ the states at every state change is because I think it’s unnecessary and wasteful memory allocations/deallocations. If you create the states at program start and destroy them at program shutdown, you’ll only have 1 new and 1 delete for each of the states, instead of allocating/deallocating at each state change.

For your next question: I guess you can do the same state change sequence as I show above but instead of fading the full screen quad in/out, you fade the fexture containing the text in/out instead. So the new state change sequence would then be:

Example state change from Splashscreen to Titlescreen:

  1. Fade out the splashscreen texture (containing either an image, a text or both)
  2. When the splashscreen texture is completely transparent, change the current state into the new state
  3. Fade in the titlescreen texture (containing either an image, a text or both)
  4. When the titlescreen texture is completely opaque, the state change sequence is finished

So, if I’ll do :

void ScreenManager::AddScreen(GameScreen *screen, SDL_Renderer *renderer)
{
currentScreen->UnloadContent();
//delete currentScreen;
currentScreen = screen;
currentScreen->LoadContent(renderer);

}

that would be ok?

and delete currentScreen in deconstructor or void UnloadContent

And how can I do that when key is pressed the thing is doing only once. I
tried to do something like bool active = false

if(key)
{
if(!active)
{
active = true; and do…
}
}

in both classes, still not working. While key is pressing the thing is
happening 22 times. I said cout<<“KEY”<<endl; and count it.

No, that won’t be enough, I’m afraid.

This is how I would design your ScreenManager:

Note that I rearranged the code a bit, used another naming convention and also changed the name of the AddScreen function to SetState, since all it does at the moment is changing the state (screen).

ScreenManager.h
#ifndef _SCREEN_MANAGER_H_
#define _SCREEN_MANAGER_H_

#include "GameScreen.h"
#include "SplashScreen.h"
#include "TitleScreen.h"
#include "FadeAnimation.h"
#include "Texture.h"

#define ScreenWidth	(1280)
#define ScreenHeight	(720)

class ScreenManager
{
public:

	~ScreenManager(void);
	static ScreenManager &GetInstance(void);

	void Initialize(SDL_Renderer* pRenderer);
	void Deinitialize(void);

	void Update(SDL_Renderer* pRenderer, SDL_Event& rEvent);
	void Draw (SDL_Renderer* pRenderer);

	void SetState(GameScreen* pNewScreen);

	//////////////////////////////////////////////////////////////////////////

	Texture GetSplashText (void) const {return m_SplashText;}
	Texture GetTitleText  (void) const {return m_TitleText;}

	GameScreen* GetSplashScreen (void) const {return m_SplashScreen;}
	GameScreen* GetTitleScreen  (void) const {return m_TitleScreen;}

	Uint8 GetAlpha(void) const {return m_Fade.getAlpha();}

private:

	ScreenManager(void);
	ScreenManager(ScreenManager const&);
	void operator = (ScreenManager const&);

	void Transition(SDL_Renderer* pRenderer);

	//////////////////////////////////////////////////////////////////////////

	// The states in the game/application
	GameScreen* m_pSplashScreen;
	GameScreen* m_pTitleScreen;
//	GameScreen* m_pMainMenuScreen;	<-- example state
//	GameScreen* m_pGameplayScreen;	<-- example state

	GameScreen* m_pCurrentScreen;

	bool m_Transition;

	Texture m_SplashText;
	Texture m_TitleText;

	FadeAnimation m_Fade;
};

#endif // _SCREEN_MANAGER_H_

And:

ScreenManager.cpp
#include "ScreenManager.h"

ScreenManager::ScreenManager(void)
: m_pSplashScreen(nullptr)
, m_pTitleScreen(nullptr)
, m_pCurrentScreen(nullptr)
, m_Transition(false)
{
// ^ It is always a good practice to initialize every pointer/variable to nullptr / 0 / false etc
}

ScreenManager::~ScreenManager(void)
{

}

ScreenManager &ScreenManager::GetInstance(void)
{
	static ScreenManager instance;

	return instance;
}

void ScreenManager::Initialize(SDL_Renderer* pRenderer)
{
	m_pSplashScreen	= new GameScreen;
	m_pTitleScreen	= new GameScreen;

	if(m_pSplashScreen) m_pSplashScreen->LoadContent(pRenderer);
	if(m_pTitleScreen)  m_pTitleScreen->LoadContent(pRenderer);

	// Which state to start at, at program start
	m_pCurrentScreen = m_pSplashScreen;

	m_Fade.LoadContent(pRenderer);
}

void ScreenManager::Deinitialize(void)
{
	if(m_pTitleScreen)  m_pTitleScreen->UnloadContent();  delete m_pTitleScreen;  m_pTitleScreen  = nullptr;
	if(m_pSplashScreen) m_pSplashScreen->UnloadContent(); delete m_pSplashScreen; m_pSplashScreen = nullptr;
}

void ScreenManager::Update(SDL_Renderer* pRenderer, SDL_Event& rEvent)
{
	if(m_pCurrentScreen)
		m_pCurrentScreen->Update(pRenderer, rEvent);	
}

void ScreenManager::Draw(SDL_Renderer* pRenderer)
{
	if(m_pCurrentScreen)
		m_pCurrentScreen->Draw(pRenderer);
}

void ScreenManager::SetState(GameScreen* pNewScreen)
{
	// Set the new state
	m_pCurrentScreen = pNewScreen;
}

void ScreenManager::Transition(SDL_Renderer* pRenderer)
{

}

It is now very easy to add a new state into the game/application and to change (for example) into the TitleScreen state, you can now write:
ScreenManager::GetInstance().SetState(ScreenManager::GetInstance().GetTitleScreen());

And then to change into a (hypothetical) GameplayScreen, you can write:
ScreenManager::GetInstance().SetState(ScreenManager::GetInstance().GetGameplayScreen());

Im sorry. I think I don’t exactly understand

Tell me what part of the code you don’t understand and I will try to explain.

How should getstate () looks like?

You shouldn’t have any such function. Check the code I’ve pasted into my latest post and check how it works.

I made a mistake. I meant SetState, but I’ll check it again. Yeah. I was reading it on gmail and I didn’t event realise that there’s a code.

This code should be good for a image as well, right? There’s something wrong with it, I think. I did everything like you said and it’s not working. The images are not showing. Im wondering… What if I would have 1000 images? Isn’t it better to load for example only 5 if they’re needed and if not unload, instead of 1000 and only cover them?

Hard to tell what’s wrong. You’ll have to debug your code and check the states of your textures and such.

Regarding the 1000 images. It all depends on the number of textures that will be used, I guess. On today’s computers it shouldn’t really matter though that a high amount of textures are being loaded during runtime, but some profiling will need to be made of course.
If your game/application is using too much memory later on, you can always switch back to doing new/delete at state change.

Or maybe it’s something wrong with me…

ScreenManager.h : https://pastebin.com/42QVJy3D
ScreenManager.cpp + splashScreen.cpp : https://pastebin.com/BzyX8xp5

Those error messages are warnings and can be ignored at this point.

Don’t know what the problem is with the code. You’ll have to check in which order everything is executed. For example, you shouldn’t have to execute that LoadContent function twice, so either it’s something wrong with the order in which the functions is executed, or there’s something else going on.
The debugger is the best tool in this case.

shames me to admit. First time using debugger though.