Screen Transitions in MonoGame.Extended

This week I worked on simplifying the screen management system in MonoGame.Extended 2.0.

Screen Transitions

The screen management system in version 1 was kinda complicated and a lot of people found it difficult to use. So this time around I decided to keep it super simple.

Basic Screens

Starting with the base screen class, it’ll feel familiar because the methods match the Game class and behave as you’d expect.

    public abstract class Screen : IDisposable
    {
        public ScreenManager ScreenManager { get; internal set; }

        public virtual void Dispose() { }
        public virtual void Initialize() { }
        public virtual void LoadContent() { }
        public virtual void UnloadContent() { }
        public abstract void Update(GameTime gameTime);
        public abstract void Draw(GameTime gameTime);
    }

Game Screens

A common pattern when creating new screens is to pass in an instance of your Game class to the constructor. Some people like this approach and some people don’t. So now there’s a new optional GameScreen base class that provides easy access to the useful helpers like a Content manager, the GraphicsDevice and game Services.

    public abstract class GameScreen : Screen
    {
        protected GameScreen(Game game)
        {
            Game = game;
        }

        public Game Game { get; }
        public ContentManager Content => Game.Content;
        public GraphicsDevice GraphicsDevice => Game.GraphicsDevice;
        public GameServiceContainer Services => Game.Services;
    }

Transitions

Switching between screens has been simplified to one LoadScreen method and an optional Transition overload on the ScreenManager. The pattern is to create a new instance of the screen you’re switching to each time and an instance of the desired transition if you want one.

var screen = new PongGameScreen(Game);
var transition = new FadeTransition(GraphicsDevice, Color.Black, 0.5f);
ScreenManager.LoadScreen(screen, transition);

We’re going to ship with a handful of transitions out of the box and the ability to create your own transitions by derving from the Transition class.

For example, a simple FadeTransition can be created by using a SpriteBatch to draw a box over the screen during the transition fading it in and out by changing the opacity.

public class FadeTransition : Transition
{
    private readonly GraphicsDevice _graphicsDevice;
    private readonly SpriteBatch _spriteBatch;

    public FadeTransition(GraphicsDevice graphicsDevice, Color color, float duration = 1.0f)
        : base(duration)
    {
        Color = color;

        _graphicsDevice = graphicsDevice;
        _spriteBatch = new SpriteBatch(graphicsDevice);
    }

    public override void Dispose()
    {
        _spriteBatch.Dispose();
    }

    public Color Color { get; }

    public override void Draw(GameTime gameTime)
    {
        _spriteBatch.Begin(samplerState: SamplerState.PointClamp);
        _spriteBatch.FillRectangle(_graphicsDevice.Viewport.Bounds, Color * Value);
        _spriteBatch.End();
    }
}

Happy coding!