3
\$\begingroup\$

I'm trying to create a fade logic with Monogame for my screen transitions. I've read tutorials online but I'd like to work with Premultiplied Alpha for the fading. I've seen people add 1x1 pixels black images to their content, scale it to the screen's width/height (depending on aspect ratio) and drawing it with the alpha value first decreasing, and then increasing (fade in, fade out). So I would like someone to give me an example code to work with, preferably, 2 methods: FadeIn() and FadeOut in something like a Transition class. I should be able to call these at the begging and at the end of my screen classes. Keep in mind that I'm using the following enum code for screen state management:

public enum gameStates
{
    splashScreen,
    engineScreen,
    titleScreen,
    optionsScreen,
    playScreen,
    gameOverScreen,
    creditsScreen,
}
private static gameStates currentGameState = gameStates.splashScreen;
public static gameStates CurrentGameState
{
    get { return currentGameState; }
    set { currentGameState = value; }
}
// And then switch(currentGameState) in Update() and Draw()

So maybe FadeIn() and FadeOut() should take an enum value as a parameter? So that when they are called, the value is passed and inside them the currentGameState is accessed through the property in Game1 and is changed. Would this be the correct approach? Thanks!

\$\endgroup\$
5
\$\begingroup\$

The problem with dealing with gamestates in an enum and a big switch statement and dealing with transitions is that you want also keep track of what the previous state was. This becomes more complex is some states may be triggered at various points during gameplay (options screen, inventory screens, other special states). So to deal with transitions more easily I've structured my states a bit differently. It comes with other benefits as well, so might be worth considering.

I have implemented the gamestates as classes to isolate their own logic. I then made a gamestate manager to deal with the active gamestate. The gamestates are then handled as a stack. The main gameloop calls the update/draw functions of the top of the stack. Don't worry, I'll get to the transitions soon :-)

public interface IGameState
{
    void Update(GameTime gametime);
    void Draw(GraphicsDevice gd, SpriteBatch sb);
    void WakeUp();
    void Sleep();
    //some other things as initialize, reset, cleanup or dispose you may need for your game.
}

The WakeUp and Sleep functions contain logic that is required when something becomes active or goes to sleep again. For example my "option menu" gamestate can be pushed at any moment and just get pushed to the top of the stack. The gamestate manager looks a bit like this:

    private Stack<IGameState> GameStack = new Stack<IGameState>();

    public void Pop()
    {
        if (GameStack.Count > 0)
            GameStack.Pop();

        if (GameStack.Count > 0)
            GameStack.Peek().WakeUp();

    }

    public void Push(IGameState state)
    {
        if (GameStack.Count > 0)
            GameStack.Peek().Sleep();

        GameStack.Push(state);
    }

    public void Update(GameTime gametime)
    {
        if (GameStack.Count > 0)
            GameStack.Peek().Update(gametime);
    }

    public void Draw(GraphicsDevice gd, SpriteBatch sb)
    {
        if (GameStack.Count > 0)
            GameStack.Peek().Draw(gd,sb);
    }

It makes the main gameloop as easy as this:

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        GamestateManager.Update(gameTime);
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GamestateManager.Draw(GraphicsDevice, spriteBatch);
        base.Draw(gameTime);
    }

So now to the topic of transitions: You could do a couple of things using this mechanism.

For example, implement a fadeout effect that is triggered before a state 'pops' itself from the stack (do a fade, once it is complete, pop itself from the stack and push the next state onto the stack). On the wakeup of a state trigger a fadein effect. This would result in a fade-to-black type of fade.

Another option is on a 'sleep' draw the scene to a RenderTarget and use that in your transition action triggered by the 'wakeup' of a new gamestate. Use the static graphic in your transition animation. You may expand your IGameState with a Texture2D GenerateTransitionSnapshot() or something. With this you could create a crossfade or any more complex fades where the old state 'freezes' and a new scene is shown.

Another thing you could do, is call the 'update' and 'draw' function of a previous gamestate each frame (for example if you want keep things animating or something) render those to a Rendertarget and deal with the transition in your gamestate manager. This makes the gamestate manager contain a bit more logic. You wakeup and sleep functions could control wether player input is accepted or not. This would result in a fade where the old state keeps animating. Performance wise your game should be able to draw both scenes.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the detailed answer, I've been looking for something like this screen manager class to use the advantages of object-oriented programming with C#! Sadly I only found the enum tutorials online, anyways this screen class should have all I need to add my transition logic. \$\endgroup\$ – PowerUser Sep 19 '15 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.