Tuesday, 1 November 2011

Two Months, One Code Sample and Half an Update


Wow! Just Wow. 2 months since my last post is very bad on my part. Especially as I've been making progress (abeit slowly) on at least one of my projects.
From my last post I was hoping to do an initial post on each of my projects, and then have weekly or bi-monthly updates on the progress of those projects. However, they're all still quite rough looking and not much to say. However, we'll see. I might change my mind. But even though the posts have been thin, I've been making progress on at least one of my projects and have ended up creating a lot of, what I think are, useful components. Because of this, I thought I would start sharing them with my fellow readers. So if you're not a developer you may want to avoid any post from now on that has the tag "codesample". I must also warn that all code samples will be for XNA (determined by the "XNA" tag) for the foreseeable future, but this of course could change. But anyway...on with the code.

SpriteText - A text container with a twist

In order to describe and show some of my more useful components, I need to really start with some of my more basic components. This one is basically a container for all information that relates to drawing text to the screen. This
container contains public methods for each of the required parameters in the SpriteBatch.DrawString method. This is as follows:

/// <summary>
/// The font to draw the text in
/// </summary>
public SpriteFont Font { get; set; }

/// <summary>
/// The text to draw
/// </summary>
public string Text 
{
 get
 {
  return _text;
 }
 set
 {
  _text = value;
  this.Size = new Vector2(Font.MeasureString(value).X * this.Scale.X,
  Font.MeasureString(value).Y * this.Scale.Y);
  this.SetOrigin(_currentOrigin);
 }
}

/// <summary>
/// The position to draw the text at
/// </summary>
public Vector2 Position { get; set; }

/// </summary>
/// The size of the text
/// </summary>
public Vector2 Size
{
 get 
 {
  return _size;
 }
 private set
 {
  _size = value;
  _size = Vector2.Transform(_size, Matrix.CreateRotationZ(_rotation));
 }
}

/// <summary>
/// The colour to draw the text in
/// </summary>
/// <remarks>
/// Default is white
/// </remarks>
public Color Colour { get; set; }

/// <summary>
/// The rotation to draw the text
/// </summary>
public float Rotation 
{
 get
 {
  return _rotation;
 }
 set
 {
  _rotation = value;
  this.Size = new Vector2(Font.MeasureString(_text).X * _scale.X,
  Font.MeasureString(_text).Y * _scale.Y);
 }
}

/// <summary>
/// The origin of the text
/// </summary>
/// <remarks>
/// Default is the centre of the text
/// </remarks>
public Vector2 Origin { get; protected set; }

/// <summary>
/// The scale at which to draw the text in
/// </summary>
public Vector2 Scale
{
 get
 {
  return _scale;
 }
 set
 {
  _scale = value;
  _size = new Vector2(Font.MeasureString(_text).X * _scale.X,
  Font.MeasureString(_text).Y * _scale.Y);
 }
}

/// <summary>
/// The effect to apply to the text
/// </summary>
/// <remarks>
/// Default is none
/// </remarks>
public SpriteEffects Effect { get; set; }

/// <summary>
/// The depth at which the text is drawn
/// </summary>
/// <remarks>
/// By default this is 0
/// </remarks>
public float LayerDepth { get; set; }

I feel this is all very self explainatory. Most of the properties are automatic. The ones that aren't have corresponding protected variables. Scale and Rotation both change the Size property value when changed as these effect the overall size of the text object. Text sets a text property but then calls a method called SetOrigin passing in a private variable call _currentOrigin. "What's this doing?" I hear you ask. Well let me explain.

The twist that SpriteText does is it auto adjusts the origin value that is used when drawing the text so that it will always appear in the same location when the text is changed. Take the following example; You want to use the sprite text object to display a score on the right hand side of the screen. Now you can do this two ways; you can have origin set to Vector2.Zero and calculate the position taking into account the length of the text, or you can set the position to the far right and adjust the origin to the length of the text.


This is fine if your text doesn't change, but as soon as the length of the text changes, you need to change the value of either the origin or the position. As I'm a programmer, I'm lazy and want this done automagically. So incomes UpdateOrigin and _currentOrigin. _currentOriginis set in the constructor of SpriteText (along with other defaults for the other properties) and is a custom enum called Alignment (the code of which can be found below)

/// <summary>
/// Constructor
/// </summary>
/// <param name="spriteBatch">The sprite batch to draw the text to</param>
/// <param name="font">The font to draw the text in</param>
/// <param name="text">The text to draw</param>
public SpriteText(SpriteBatch spriteBatch, SpriteFont font, string text)
{
 this.Font = font;
 _currentOrigin = Alignment.Centre;
 this._spriteBatch = spriteBatch;
 this.Colour = Color.White;
 this.Scale = Vector2.One;
 this.Effect = SpriteEffects.None;
 this.Text = text;
 this.LayerDepth = 0;
}

/// <summary>
/// Represents the different alignments an object could be placed in
/// </summary>
public enum Alignment
{
 None,
 TopLeft,
 Top,
 TopRight,
 Right,
 BottomRight,
 Bottom,
 BottomLeft,
 Left,
 Centre
}

SetOrigin (which is a public method that can be called to change the origin "on the fly") takes an Alignment parameter and updates the origin/position values for the SpriteText object so it will always appear in the correct position on the screen. The code of which is below

/// <summary>
/// Set the origin of text
/// </summary>
/// <param name="origin">The origin alignment</param>
public void SetOrigin(Alignment origin)
{
 _currentOrigin = origin;

 switch (origin)
 {
  case Alignment.Left:
   this.Origin = new Vector2(0.0f,
   this.Font.MeasureString(this.Text).Y / 2);
   break;
  case Alignment.TopLeft:
   this.Origin = new Vector2(0.0f,
   0.0f);
   break;
  case Alignment.Top:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X / 2,
   0.0f);
   break;
  case Alignment.TopRight:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X,
   0.0f);
   break;
  case Alignment.Right:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X,
   this.Font.MeasureString(this.Text).Y / 2);
   break;
  case Alignment.BottomRight:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X,
   this.Font.MeasureString(this.Text).Y);
   break;
  case Alignment.Bottom:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X / 2,
   this.Font.MeasureString(this.Text).Y);
   break;
  case Alignment.BottomLeft:
   this.Origin = new Vector2(0.0f,
   this.Font.MeasureString(this.Text).Y);
   break;
  case Alignment.Centre:
   this.Origin = new Vector2(this.Font.MeasureString(this.Text).X / 2,
   this.Font.MeasureString(this.Text).Y / 2);
   break;
  default:
  throw new ArgumentException("Alignment not supported");
 }
}

Then there is the standard draw method which just calls the SpriteBatch.DrawString method passing in the corresponding methods. As you can see it doesn't do anything special but I find it useful when wanting to draw text on the screen in XNA. The full code sample is available to download.

Monday, 29 August 2011

Congestion of Updates - Initial Tractor Update


After I wrote my last post, I thought that perhaps you lovely readers may want to actually read what I'm up to. As I've got a host of projects under way on the Windows Phone 7 and Xbox 360 platforms, I thought it would be a good idea to do a post on each of my projects, what I hope to accomplish and how far along (or not) they may be.

The first project of mine I hope to disclose is a project that is quite far along, and one I hope to release very soon. The idea behind the app (as you may have guessed by the above picture) is based around congestion/ traffic incidents. The desire to create the app came to me when I was stuck in a traffic jam with my girlfriend, with a journey that usually took forty-five minutes took two and half hours! While we were in the traffic jam, my girlfriend was keeping an eye on traffic updates via some source.

This made me think. Are there any good traffic related apps on the marketplace? While there are a few, none of them jumped out at me, and more importantly while they provided me with information, the information wasn't necessarily related to me. So I decided to work on my own app. Below are a few shots of work in progress.






The key features I have implemented at the moment:
  • Traffic information from a host of different sources (Currently I have information from one source, but hope to find more)
  • Traffic information provided to me based on a given route (this seems to be working most of the time - at least filtering by road)
  • Traffic information being clickable to send me to the original source (who are clearly credited as they deserve)
  • Route directional information so the user doesn't have to bounce back between my app and bing maps (if they so desire to use it)
  • The ability to save, delete and pin routes to my start screen
So there is a sneak look. I hope to polish and add a few more features and then release it. At the moment, this looks like it will be my first published app. Hopefully this app will be something that will provide a handy tool for all you users.

    Thursday, 25 August 2011

    Who Are You and Why Am I Here?


    Its been over a month since I created this blog and have yet to write anything on it, which is kind of ironic as I set it up to try and motivate me to accomplish things.

    So here we go, an introductory blog post for all you first time readers. My name is David Kendall (if you hadn't of guessed by the big banner at the top of the page) and I'm a software developer. As a day job, I work for a company that specialises in developing software for the financial sector. It's an interesting job, that brings with it new and exciting challenges. But this is not what this blog will be for.

    No, No. This blog will be for all the little projects I will develop in my spare time for a variety of different platforms. Yeah that's right, I program for my day job and then I program some more in my spare time. I must be mad right?

    I have already got a few projects on my plate, some big some small and there will be probably be more I'll add along the way of developing these ones (yeah that's how I roll). I will get into the specifics of these projects in my next blog post.

    So what will you, the reader, get from the blog. Well, you will get an insight into the development of these projects. You will possibly get some code samples for things that I've developed that I think are useful (but probably wont be) and you may get some screenshots and video footage. Finally, it will probably include other topics that I think you may want to read.

    Hope you find all of this talk interesting. Now hopefully I can follow through with what I've said and should have another more interesting post for you in a few days.