Skip to content

Instantly share code, notes, and snippets.

@Bocom
Created July 19, 2012 15:45
Show Gist options
  • Save Bocom/3144806 to your computer and use it in GitHub Desktop.
Save Bocom/3144806 to your computer and use it in GitHub Desktop.
A message queue for XNA
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace WanderfulEngine
{
public struct Message
{
/// <summary>
/// The message text.
/// </summary>
public string Text;
/// <summary>
/// The length of the text.
/// Does not factor in transition time.
/// </summary>
public TimeSpan Length;
/// <summary>
/// Whether to skip the initial transition.
/// </summary>
public bool ShowInstantly;
/// <summary>
/// The fade in time.
/// </summary>
public TimeSpan InTime;
/// <summary>
/// The fade out time.
/// </summary>
public TimeSpan OutTime;
/// <summary>
/// The font to use for the message.
/// </summary>
public SpriteFont Font;
public Message(string message)
{
Text = message;
Length = TimeSpan.FromSeconds(3);
ShowInstantly = false;
InTime = TimeSpan.FromMilliseconds(250);
OutTime = TimeSpan.FromMilliseconds(250);
Font = Fonts.MessageFont;
}
}
public class MessageQueue : DrawableGameComponent
{
enum MessageState
{
Hidden,
TransitionIn,
Showing,
TransitionOut,
Done
}
private Queue<Message> messages;
private Nullable<Message> currentMessage;
private float timer;
private MessageState state;
private float transitionPosition;
private SpriteBatch spriteBatch;
public MessageQueue(Game game)
: base(game)
{
messages = new Queue<Message>();
}
public override void Initialize()
{
base.Initialize();
this.spriteBatch = new SpriteBatch(GraphicsDevice);
}
/// <summary>
/// Push a message into the queue.
/// </summary>
/// <param name="message">The Message object to push.</param>
public void Push(Message message)
{
messages.Enqueue(message);
}
/// <summary>
/// Updates the message queue and
/// </summary>
/// <param name="gameTime"></param>
public override void Update(GameTime gameTime)
{
// If there is no message to display, just skip updating.
if (!currentMessage.HasValue && messages.Count == 0)
return;
// If we don't have a message right now, pull the next message.
if (!currentMessage.HasValue && messages.Count > 0)
{
timer = 0;
state = MessageState.Hidden;
currentMessage = messages.Dequeue();
}
timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (state == MessageState.Hidden)
{
if (timer >= 0)
SwitchState();
}
else if (state == MessageState.TransitionIn)
{
transitionPosition += (float)(gameTime.ElapsedGameTime.Milliseconds /
currentMessage.Value.InTime.TotalMilliseconds);
if (timer >= currentMessage.Value.InTime.TotalSeconds)
SwitchState();
}
else if (state == MessageState.Showing)
{
if (timer >= currentMessage.Value.Length.TotalSeconds)
SwitchState();
}
else if (state == MessageState.TransitionOut)
{
transitionPosition -= (float)(gameTime.ElapsedGameTime.Milliseconds /
currentMessage.Value.OutTime.TotalMilliseconds);
if (timer >= currentMessage.Value.OutTime.TotalSeconds)
{
SwitchState();
currentMessage = null;
}
}
}
/// <summary>
/// Draws the current message
/// </summary>
/// <param name="gameTime">The elapsed time</param>
public override void Draw(GameTime gameTime)
{
if (!currentMessage.HasValue)
return;
spriteBatch.Begin();
Color color = Color.White;
if (state == MessageState.TransitionIn ||
state == MessageState.TransitionOut)
color *= transitionPosition;
if (state != MessageState.Done &&
state != MessageState.Hidden)
spriteBatch.DrawString(currentMessage.Value.Font,
currentMessage.Value.Text,
Vector2.Zero,
color);
spriteBatch.End();
}
/// <summary>
/// Switches the state of the queue.
/// </summary>
private void SwitchState()
{
if (state == MessageState.Hidden)
{
if (currentMessage.Value.ShowInstantly)
{
state = MessageState.Showing;
transitionPosition = 1;
}
else
state = MessageState.TransitionIn;
}
else if (state == MessageState.TransitionIn)
state = MessageState.Showing;
else if (state == MessageState.Showing)
state = MessageState.TransitionOut;
else if (state == MessageState.TransitionOut)
state = MessageState.Done;
transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
timer = 0;
}
}
}
namespace Example
{
public class MessageQueueExample : Game
{
private MessageQueue msgQueue;
public MessageQueueExample()
{
msgQueue = new MessageQueue(this);
Components.Add(msgQueue);
}
public void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.M))
{
Message m = new Message("Hi!");
Message m2 = new Message("Hello!")
{
ShowInstantly = true,
Length = TimeSpan.FromSeconds(1)
};
msgQueue.Push(m);
msgQueue.Push(m2);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment