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.
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:
The screen fades to black by using a black quad (SDL_Rect) that fills the whole window
When the screen is completely black (the quad’s alpha is 255, i.e full opaque), change CurrentState/CurrentScreen to the new state/screen
Fade away the black quad
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.
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:
Fade out the splashscreen texture (containing either an image, a text or both)
When the splashscreen texture is completely transparent, change the current state into the new state
Fade in the titlescreen texture (containing either an image, a text or both)
When the titlescreen texture is completely opaque, the state change sequence is finished
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).
#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());
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.
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.