Article: Fading between 2 images
by Conkerjo
![]()
This article describes how to fade between 2 images using SpriteBatch
Fading between 2 images is a very simple task using XNA, I’ve seen a lot of different ways of doing this so here’s my take on the problem.
We need to fade from one image which is currently displaying on screen to another image we have stored in memory.
Here are 3 states of 2 images fading between each other.
The Start
The Fade
The Result
To keep it simple we use functionality within the XNA framework so we don’t have to write our own. This can be done using the SpriteBatch AlphaBlend which just happens to be the default option when calling Begin on a SpriteBatch.
Simply call Begin, draw the image currently on screen at a reduced alpha, then draw the image you want to transition to over the top with a alpha set to the other extreme.
I created a class which takes care of the drawing and alpha transitioning. Once we create an instance of the CustomImage class we must call Update, passing it the elapsed time since the last frame and also call the Draw method to draw the transition.
If there is no transition the CustomImage will simply draw the Image set at full opacity.
We define the amount of time to take in a transition in the constructor of the CustomImage or it can be changed via the TransitionTime property.
To start a transition just pass a Texture2D to the TransitionTo method. This will begin the process of fading between the two images and will completely switch over to the new image once complete.
Here is the full class implementation.
public class CustomImage
{
private float timer;
public CustomImage(Texture2D initialImage, Vector2 position, Vector2 origin, float transitionTime)
{
this.Image = initialImage;
this.TransitionTime = transitionTime;
this.Color = Color.White;
this.Rotation = 0;
this.Position = position;
this.Origin = origin;
}
public float TransitionTime { get; set; }
public Texture2D Image { get; private set; }
public Texture2D ToImage { get; private set; }
public Vector2 Origin { get; set; }
public Vector2 Position { get; set; }
public Color Color { get; set; }
public float Rotation { get; set; }
public void TransitionTo(Texture2D image)
{
if (this.ToImage != null)
{
return;
}
this.ToImage = image;
this.timer = 0;
}
public void Draw(SpriteBatch batch)
{
if (this.ToImage == null)
{
batch.Draw( this.Image, this.Position, null, this.Color, this.Rotation, this.Origin, 1f, SpriteEffects.None, 0);
}
else
{
int alpha = (int)((this.timer / this.TransitionTime) * 255);
this.DrawImage(batch, this.Image, 255 - alpha);
this.DrawImage(batch, this.ToImage, alpha);
}
}
public void Update(float elapsed)
{
// We must be transitioning
if (this.ToImage != null)
{
this.timer += elapsed;
if (this.timer >= this.TransitionTime)
{
this.Image = this.ToImage;
this.ToImage = null;
}
}
}
private void DrawImage(SpriteBatch batch, Texture2D texture, int alpha)
{
batch.Draw( texture, this.Position, null, new Color(this.Color, (byte)alpha), this.Rotation, this.Origin, 1f, SpriteEffects.None, 0);
}
}
To use this class we pass a Texture2D, a position, an origin and a length of time we want a transition to take.
Calling Draw will draw the image set until you pass a Texture2D to the TransitionTo method.
Here’s is the full Game code to show how I used this class in the sample which you can download at the end of the page.
public class Game1 : Microsoft.Xna.Framework.Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
private SpriteFont font;
private CustomImage image1;
private CustomImage image2;
private float storedTimer = 2;
private KeyboardState currentKeyboardState, lastKeyboardState;
private Vector2 imageSize = new Vector2(400, 300);
public Game1()
{
this.graphics = new GraphicsDeviceManager(this);
this.Content.RootDirectory = "Content";
}
private Vector2 ScreenSize
{
get
{
return new Vector2(this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height);
}
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
this.spriteBatch = new SpriteBatch(GraphicsDevice);
this.font = this.Content.Load<spritefont>("Fonts/Arial");
Vector2 position = new Vector2((this.ScreenSize.X / 4), this.ScreenSize.Y / 2);
this.image1 = new CustomImage(
this.Content.Load<texture2d>("Textures/Image1"),
position,
this.imageSize / 2,
this.storedTimer);
position.X += this.ScreenSize.X / 2;
this.image2 = new CustomImage(
this.Content.Load<texture2d>("Textures/Image2"),
position,
this.imageSize / 2,
this.storedTimer);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
this.lastKeyboardState = this.currentKeyboardState;
this.currentKeyboardState = Keyboard.GetState();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
this.HandleInput();
this.image1.Update(elapsed);
this.image2.Update(elapsed);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
this.GraphicsDevice.Clear(Color.Black);
StringBuilder instructions = new StringBuilder();
instructions.Append("Space : Transition");
instructions.Append(Environment.NewLine);
instructions.Append("PgUp / PgDwn : Increase / Decrease Timer");
instructions.Append(Environment.NewLine);
instructions.Append(string.Format("Transition Time : {0}", this.storedTimer));
this.spriteBatch.Begin();
this.spriteBatch.DrawString(this.font, instructions, new Vector2(25), Color.White);
this.image1.Draw(this.spriteBatch);
this.image2.Draw(this.spriteBatch);
this.spriteBatch.End();
base.Draw(gameTime);
}
private void HandleInput()
{
if (this.IsNewKeyPress(Keys.Space))
{
this.image1.TransitionTo(this.image2.Image);
this.image2.TransitionTo(this.image1.Image);
}
if (this.IsNewKeyPress(Keys.PageDown))
{
this.storedTimer -= 0.25f;
this.image1.TransitionTime =
this.image2.TransitionTime = this.storedTimer;
}
if (this.IsNewKeyPress(Keys.PageUp))
{
this.storedTimer += 0.25f;
this.image1.TransitionTime =
this.image2.TransitionTime = this.storedTimer;
}
}
private bool IsNewKeyPress(Keys keys)
{
return this.currentKeyboardState.IsKeyUp(keys) && this.lastKeyboardState.IsKeyDown(keys);
}
private void DrawImage(Texture2D image, Vector2 position)
{
this.spriteBatch.Draw(image, position, null, Color.White, 0, this.imageSize / 2, 1, SpriteEffects.None, 0);
}
}
You can download the sample project with complete working sample here
Conkerjo - www.conkerjo.com - www.twitter.com/conkerjo