4
\$\begingroup\$

Last night I showed my game to my friends and they said it was a bit jumpy.

The example he gave was in the pokemon games when a battle starts music plays, the screen flashes then pixels out then the pokemon slide on from the side and the battle menu appears.

In my game you are walking along and the all of a sudden you are staring at the battle menu, I do see his point.

I am using a switch statement for my game loop, 1 is a fields and 2 is battle, in battle I run an if statement, if battle active do battle else display results screen/wait for user input.

I thought about making a state for the transition but them I would need a stater for field -> battle, battle -> field, town -> field and the list goes on an on seeming like lots of repeated code to me but I cant think of a way to pause the state while i play an animation like pokemon

With that sort or architecture how would transition between screens smoothly like my mate suggests?

C++ and directX

Edit: the problem I have is that once the state is changed the update routeen for that state is not called so all the sprites disappear as they are textures and only the background remains so I cannot just play a animation then change state or it will look even worse.

\$\endgroup\$
4
  • \$\begingroup\$ If you have one state where you draw something, and one state where you draw another, you have to fade to a color between them, generally black. Old Scene -> Black -> New Scene. If you want a nice fade between the two scenes you can maybe render the previous scene into a RenderTarget, and fade that texture into the new scene. \$\endgroup\$ Jun 10, 2011 at 15:28
  • \$\begingroup\$ @3nixios as I understand it direct x surfaces are blited to a buffer surface which is shown on screen where as a directx texture is drawn directly on the screen, i may be wrong but in my experience the player,npc and items disappear (texturex) and the background remains as it is copied from the back buffer and drawn outside the switch. this means i cannot maintain the current screen in order to do a fade \$\endgroup\$
    – Skeith
    Jun 10, 2011 at 15:42
  • \$\begingroup\$ Can you not use a RenderTarget that is maintained between the two scenes? \$\endgroup\$ Jun 10, 2011 at 15:49
  • \$\begingroup\$ @3nixion what do you mean render trigger I am unfamiliar with that term? \$\endgroup\$
    – Skeith
    Jun 10, 2011 at 15:50

5 Answers 5

5
\$\begingroup\$

I built a generic transition system for a 2d engine for iPhone. I'm going to try to explain it. This is only an approach, the implementation has more things that are not relevant.

Suppose that your engine is hierarchical, if it is not, there are a lot of of reasons why a game engine must be hierarchical. We can have two interfaces IState and ITransition inheriting from the SceneNode class. Like this:

enter image description here

Well, SceneNode can be updateable, this means that the parent calls the children method "update" and enabled, that receive or not input events ( so you can disable the user events when the transition is executing ).

Every state has a name, and every transition has the old and new state between the transition exists.

Ok. Now we can have two managers, Transition and StateManager, the purpose of these managers is to have a registry of all Transitions and States and offer features. These managers can be singleton to be accessible from everywhere.

enter image description here

With addTransition we attach a custom transition to a pair of menus, the order is important. When we call changeState, the manager is responsible of test if a transition has been added and execute it if exist.

With this simple architecture, we are to program a transition between the MainMenu to Battle.

The current scene graph is:

enter image description here

My transition implementation:

TransitionMenuToBattle : public ITransition
{
    public:
        void enter()
        {
            getOldState()->setActive( false );
            getRoot()->addChild( this );

            addChild( blackSprite );
        }

        void update( float delta )
        {
            // make fade of blackSprite
            // ...

            if ( blackSprite->getAlpha() == OPAQUE )
            {
                getRoot()->addChild( getNewState() );
                getNewState()->setActive( false );
            }

            if ( blackSprite->getAlpha() == INVISIBLE )
                exit();
        }

        void exit()
        {
            getRoot()->removeChild( this );
            getNewState()->setActive( true );
        }
};

When enter method finishes, the scene graph is:

enter image description here

When exit method is called in update:

enter image description here

when exit method finishes:

enter image description here

when the game begins we need to add the transition:

TransitionFactory::get()->addTransition( "StateMainMenu", "StateBattle", new TransitionMenuToBattle( ) );

Then, for example in a button callback from MainMenu, we can put the call TransitionFactory::get()->changeMenu( "StateMainMenu", "StateBattle" ); or wrap this method into:

IState::changeMenu( std::string newMenu )
{
    TransitionFactory::get()->changeMenu( getStateMenu(), newMenu );
}

You can complicate the transition much as you want. The transition has access to the two states and it can do things like overlap elements of two. The transition can receive the things that needs in his constructor. If TransitionManager detects that there is no transition added between two states can have a default behavior.

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

You could just make a single "transition" state, with which state you're going to and from indicated as a couple of variables in the object.

\$\endgroup\$
4
  • \$\begingroup\$ except that would require all the code from every possible state so it can maintain the screen while it changes. \$\endgroup\$
    – Skeith
    Jun 10, 2011 at 15:16
  • \$\begingroup\$ @Skeith: Alternatively, you could just ask the originating state what to do when transitioning to the target state. Depending on how complex your requirements are, you could just get a 2D array of animations and index into it to find what to do. \$\endgroup\$
    – DeadMG
    Jun 10, 2011 at 15:17
  • \$\begingroup\$ I don't see how passing every variable in my program to the transition state it at all a good idea? could you please explain you answer more. \$\endgroup\$
    – Skeith
    Jun 10, 2011 at 15:21
  • \$\begingroup\$ Sorry, I'm off to bed, but expect an update from me in the morning \$\endgroup\$
    – DeadMG
    Jun 10, 2011 at 21:13
0
\$\begingroup\$

If you're not willing to change your architecture from a switch statement to using the state design pattern (which is fine, as you know your code best) then it's gonna be pretty ugly.

Assuming you're using an architecture with a fairly standard Update loop, perhaps you could have a flag checking whether a transition is required and on the next Update check for the flag being set right at the beginning of your update loop and if it's on, then play a transition and wait until the transition has completed before turning the flag off.

Quick, dirty pseudocode would be:

bool bStateChangeRequested;

while( bUpdate )
{
    if( bStateChangeRequested )
    {
        PlayTransition();
        WaitForTransitionToComplete();
    }

    DoStateStuff();
}

Hope that helps, although I'd highly recommend the state design pattern for solving this. It'll make everything so much cleaner and better organised, so a definite thing to think about in future iterations.

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

In your switch statement call to a transition routine. For a ridiculously oversimplified pseudo answer:

void changeState ( int destinationState, int *currentState ) {
    // check that destination state is valid
    // check that current state can transition to destination state
    doTransition ( *currentState, destinationState);
    *currentState = destinationState
}

[Edit] To call this using a switch statement that already exists you would do something like this:

switch (destinationState): {
1: {changeState ( 1, &currentState); break; } // switch from some state to fields
2: {changeState ( 2, &currentState); break; } // switch from some state to battle
}

Then you do still need to write doTransition() that would actually do that transition animation. doTransition would do your fade in/fade out/whatever you wanted it to do.

\$\endgroup\$
2
  • \$\begingroup\$ you your self state this does not fit into my architecture so its not really an answer to the question that was asked. \$\endgroup\$
    – Skeith
    Jun 10, 2011 at 15:18
  • \$\begingroup\$ @Skeith I don't believe I did, you can call this from your switch statement fairly straightforwardly, I'll edit my answer to show how. \$\endgroup\$
    – Stephen
    Jun 10, 2011 at 19:35
0
\$\begingroup\$

I use the SFML library to do all my graphics and windows and stuff, but one way of doing it is with a few variables:

#include <SFML/Graphics.hpp>

bool FaderHappens = false;
bool FaderTrue = false;
bool gameStarted = false;
bool gameStartedSub1 = false;
float FaderVar = 0;
int main() {
  while (window.isOpen())
  {
    sf::RenderWindow window(sf::VideoMode(840, 680), "Your Program Name",sf::Style::Default);

    window.setFramerateLimit(65);
    sf::RectangleShape Fader(sf::Vector2f(850, 550));
    while (window.pollEvent(event))
    {
      if (event.type == sf::Event::Closed)
        window.close();
    }
    window.clear();

    if (YOUR_EVENT) {
      FaderHappens = true;
      FaderTrue = true;
    }
    if (FaderTrue == true && FaderHappens == true) {
      if (gameStartedSub1 == false) {
        FaderVar = FaderVar + 63.75;
      }
    }
    if (FaderVar == 255 && FaderHappens == true && FaderTrue == true) {
      if (gameStarted == false && gameStartedSub1 == false) {
        gameStartedSub1 = true;
      }
      FaderTrue = false;
    }
    if (FaderTrue == false && FaderHappens == true) {
      FaderVar = FaderVar - 63.75;
    }
    if (FaderVar == 0 && FaderTrue == false && FaderHappens == true) {
      FaderHappens = false;
    }
    Fader.setFillColor(sf::Color(0, 0, 0, FaderVar));
    window.draw(Fader);
    window.display();
  }
}

This should give you a basic understanding of the logic that goes into making a fading animation. The 63.75s can be changed to make the animation slower or faster, though note that the number you put in must be the number 255 divided by any whole number (otherwise it would loop forever). I am sorry if something is mixed up, as I took this from my own project and was trying not to show irrelevant code. I believe it to be clean of any mistakes though.

\$\endgroup\$
1
  • \$\begingroup\$ Hey, just letting you know that I removed the suggestion to use SFML instead; the OP's project seems to have been well under way in Directx, 6 years ago, so there is not point in suggesting to use another library. The fact that the example is in SFML is fine though, because that's what you know and it could be useful as is to other users, regardless of their library of choice. \$\endgroup\$
    – Vaillancourt
    Jun 22, 2017 at 16:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .