XNA UK User Group

A helping hand for bedroom coders throughout the land.
in

MVi

Articles and thoughts on working with the Microsoft XNA Framework and game development in general.
  • IntelliShade

    Hi all,

    I came across a link to IntelliShade the other day, an extension to Visual Studio which seems to be rather hard to find now that the official website has gone down along with ziggyware. IntelliShade offers syntax highlighting and some basic intellisense to editing HLSL (.fx) files. Rather than having to rely on a plain text editor, IntelliShade will highlight data types, semantics and other tokens that it recognises and has a rudimentary list of suggestions as well, it also makes use of outlining functionality, allowing you to take advantage of the ability to hide functions and structs at the click of a button, which helps editing large effect files greatly.

    I've mirrored this download onto my personal webspace now, you can download the installer here

    You can find alternate mirrors here and here

    You might also be interested in checking out NShader, which supports HLSL, GLSL and CG, although it's HLSL support lacks more than syntax highlighting at this time.

    As far as I'm aware neither IntelliShade nor NShader work with Express versions of Visual Studio. If you're on express then you should be able to create a usertype.dat file containing HLSL keywords which will give you more basic syntax highlighting. For some example keyword lists, check out this topic.

  • XNA 4.0 Official

    XNA 4.0 was officially announced today at GDC 2010, earlier this week support was announced by Windows Phone 7 Series phones for XNA developed products and to support this new platform XNA 4.0 has been announced. So besides support for Microsoft's new mobile OS, what does XNA 4 change?

    Firstly, there is now support for Visual Studio 2010. Next there have been audio improvements with support for dynamic audio output and microphone input. Further to this there have been a number of graphics changes and optimisations, with the addition of new effect classes (like BasicEffect) to support skinned animations, environment mapping, dual textures and alpha testing. 

    More details at Michael Klucher's blog and Sgt. Conker's blog

  • Static Classes and their use for Resource Storage

    Static classes are extremely useful in software development and here I will cover how they can be used for keeping track of important game resources.

    Firstly, for those of you unfamilliar with static classes, what is a static class?

    Static classes are a type of class that can not be instantiated and can only contain static members. A static class will only store one instance of fields and methods. The Math and MathHelper classes are examples of static classes, you do not (and indeed cannot) instantiate these classes, but make use of their static methods and static properties which return the value in a static field. 

    So how is this useful?

    Static classes are extremely useful for helper classes, my engine is full of static classes for localisation, utilities such as math extension helper classes, crypto random generators and physics. However this is generally mainly for the static functions contained within them (which in fact aren't restricted just to static classes), now in regard to game resources, we typically store one object of the graphics device, spritebatch, contentmanager, game etc... but it can be very useful gaining access to the graphics device easily by storing it in a public static class. This enables you to simply use Resources.GraphicsDevice rather than having to pass down the graphics device from parameter to parameter.

    An example:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;

    namespace MyNamespace
    {
        public static class Resources
        {
            public static GraphicsDevice GraphicsDevice;
            public static SpriteBatch SpriteBatch;
            public static ContentManager Content;       
            public static GameTime GameTime;
            public static Game Game;

            public static void Cleanup()
            {
                GraphicsDevice = null;

                if (SpriteBatch != null)
                    SpriteBatch.Dispose();
                SpriteBatch = null;

                if (Content != null)
                    Content.Dispose();
                Content = null;

                GameTime = null;
                Game = null;           
            }
        }
    }
     

  • Avatars - Step Two - Persistent Avatar Descriptions

    Since it's not always convenient to be using random avatars or a signed in gamers avatar (especially as the signed in gamer's avatar isn't allowed a life of its own), you may want to create an avatar in the editor and use that in the game as a NPC friend, enemy or boss. Additionally, you may want to keep randomising avatars till you find one you like, and keep that to use. This tutorial will show you exactly how to accomplish this.

    The AvatarDescription Class

    The AvatarDescription class stores a byte array containing 1021 entries. This array stores all the unique characteristics of an avatar, such as skin colour, weight, clothes, facial features, hair etc. The last 19 bytes of this array, appears to be a checksum, preventing you from creating your own avatars (unless of course you know how the checksum is generated.) The guys on the XNA forums are looking into determining what in the array does what. If there's an element you need, I recommend using the avatar editor on the NXE dashboard, then seeing what's changed, as per the advice of AtraX. 

    The Parser Script [Located Here]

    This script simply runs through the supplied text, parsing it using a regular expression and outputting the second column in one of four formats. As a byte array, for hardcoding, then as newline delimited, comma separated values or XML for easy storage external to the binary, so that you can store many preset avatars and load them in from a file(s).

    Step One: Run the avatar code from Tutorial One or indeed any avatar code which makes use of the AvatarDescription class. 

    Step Two: As soon as this code is running on your screen, hit the break all button, or use the Ctrl-Shift-Break shortcut.


    Step Three: Bring up the locals window, the locals window shows you all the local variables at play which you can inspect and examine the values of. Here we are very much interested in what is stored in the avatarDescription.description. If the locals window is not already up hit Ctrl-Alt-V,L.

    Step Four: Now under game->avatarDescription->description (or equivalent), highlight all entries in the description from [0] down to [1020], right click and hit copy.


    Step Five: Next, load up the parser script on my site, paste into the box, and using the byte array format, and hit submit:

    Step Six: This will now parse the data, and put it in a format that can be used easily in our code. Highlight and copy the results, including the { and } at each end.

    Step Seven: Now back in the Visual Studio hit the stop button or press Shift-F5. Now find and replace the avatarDescription initialisation code, instead of generating a random avatar (or using a signed in gamer's avatar) we now want to use the avatar data we've obtained from the IDE, using the following line (pasting in the clipboard):

     

    avatarDescription = new AvatarDescription(new byte[] YOURBYTEARRAYHERE );

    e.g. 

     

    avatarDescription = new AvatarDescription(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, ...... 58, 45, 243, 60 } );

    Step Eight: The avatarDescription now is a preset avatar rather than an avatar generated on each execution of the game.

    In summary, we've grabbed the desription out of the IDE, processed it and put it back into the code to ensure a permanent avatar appearance.

    Complete source (Game1.cs)

    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    namespace AvatarStepOne
    {
    public class Game1 : Microsoft.Xna.Framework.Game
    {
    GraphicsDeviceManager graphics;

    AvatarDescription avatarDescription;
    AvatarRenderer avatarRenderer;
    AvatarAnimation avatarCelebrateAnimation;

    public Game1()
    {
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    Components.Add(new GamerServicesComponent(this));
    }

    protected override void LoadContent()
    {
    avatarDescription = new AvatarDescription(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 16, 0, 0, 3, 26, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 8, 0, 0, 3, 37, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 32, 0, 0, 3, 59, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 0, 128, 0, 2, 250, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 2, 142, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 2, 110, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 215, 185, 113, 255, 55, 33, 22, 255, 235, 125, 128, 255, 114, 127, 53, 255, 55, 33, 22, 255, 197, 73, 109, 255, 55, 33, 22, 255, 101, 68, 40, 255, 101, 68, 40, 0, 0, 0, 2, 0, 0, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 31, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 96, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 144, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 60, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 60, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 144, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 96, 0, 1, 193, 200, 241, 9, 161, 156, 178, 224, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 31, 0, 3, 193, 200, 241, 9, 161, 156, 178, 224, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 145, 254, 13, 246, 78, 178, 157, 244, 219, 52, 73, 35, 119, 60, 219, 58, 45, 243, 60 });
    avatarRenderer = new AvatarRenderer(avatarDescription);
    avatarCelebrateAnimation = new AvatarAnimation(AvatarAnimationPreset.Celebrate);
    }

    protected override void Update(GameTime gameTime)
    {
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
    this.Exit();

    if (avatarRenderer.IsLoaded)
    {
    avatarCelebrateAnimation.Update(gameTime.ElapsedGameTime, true);
    }

    base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.CornflowerBlue);

    avatarRenderer.View = Matrix.CreateLookAt(new Vector3(0, 1, -3), new Vector3(0, 1, 0), new Vector3(0, 1, 0));
    avatarRenderer.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f);
    avatarRenderer.Draw(avatarCelebrateAnimation.BoneTransforms, avatarCelebrateAnimation.Expression);

    base.Draw(gameTime);
    }
    }
    }
  • Avatars - Step One Extended - Signed In Gamers

    Carrying on from the first article, I thought I'd just extend it to include support for a signed in gamer's credentials. While the only new avatar element here is the capability to draw a user's avatar instead of a generated one (which I'd already given the code for in the introduction), it also shows off getting the gamerpicture, tag, gamerscore etc, and some basic use of event handlers.

    Step One: Set up storage for a sprite batch for drawing 2D elements, a sprite font so that we can draw text to the screen, a boolean value to tell us whether the player is signed in, copies of the signed in player's Gamer and GamerProfile objects, a texture for a pretty background to render along with a texture to store the player's gamer picutre. In the declarations add:

            SpriteBatch spriteBatch;
    SpriteFont arial;
    bool gamerSignedIn = false;
    GamerProfile profile;
    Gamer gamer;
    Texture2D gamerPicture;
    Texture2D background;

    Step Two: Set the screen resolution to 720p, this means that we can rely on co-ordinates always being at the sample place. In the game constructor add:

                graphics.PreferredBackBufferWidth = 1280;
    graphics.PreferredBackBufferHeight = 720;

    Step Three: Add two event handlers to handle the user signing in and out. It is useful to note that for the first few frames of the game the player may not be signed in, so calling their profile without checking that they're signed in will result in an exception. Also we want to take care of the player signing out during our game also. Again in the game constructor add:

                SignedInGamer.SignedIn += new EventHandler<SignedInEventArgs>(SignedInGamer_SignedIn);
    SignedInGamer.SignedOut += new System.EventHandler<SignedOutEventArgs>(SignedInGamer_SignedOut);

    Step Four: Since we are using the signed in player's avatar rather than a random one, we can remove the lines initiallising the avatarDescription and subsequent avatarRenderer with a random avatar. In the LoadContent function remove:

                avatarDescription = AvatarDescription.CreateRandom(); //Generate a random avatar, by randomising the description byte array with acceptable values           
    avatarRenderer = new AvatarRenderer(avatarDescription); //Create a renderer for the avatar we have just randomly created

    Step Five: Create the sprite batch and load the background texture and default font spritefont. In the LoadContent function add:

                spriteBatch = new SpriteBatch(GraphicsDevice);
    background = Content.Load<Texture2D>("background");
    arial = Content.Load<SpriteFont>("Arial");

    Step Six: In the update function modify the if statement to update only if the gamer is signed in in addition to the renderer being loaded. Modify the if statement to be:

                if (gamerSignedIn && avatarRenderer.IsLoaded)

    Step Seven: In the draw function, after the call to clear the graphics device, but before the view matrix set, we will be wanting to draw the background, so add:

                spriteBatch.Begin();
    spriteBatch.Draw(background, new Vector2(0), Color.White);
    spriteBatch.End();

    Step Eight: Now we want to ensure the avatar is only renderred when the player is signed in. So enclose the view matrix set, projection matrix set and draw call in curly brackets which are preceeded with the following line:

                if (gamerSignedIn)

    Step Nine: It would be nicer to have the avatar at the side of the screen, so modify the view matrix set to:

                    avatarRenderer.View = Matrix.CreateLookAt(new Vector3(1, 1, -3), new Vector3(1, 1, 0), new Vector3(0, 1, 0)); //Set the view matrix supplying a sensible eye position, target and up direction

    Step Ten: Now we need to draw the signed in gamer's picture and credentials. We make use of the Gamer object for the gamertag, the Texture2D set in the sign in event handler for the gamer picture and the GamerProfile object for the rest of the credentials. Again using the sprite batch, after the avatar draw call but before the if statement closing curly bracket add:

                    spriteBatch.Begin();
    spriteBatch.Draw(gamerPicture, new Rectangle(115, 81, 100, 100), Color.White);
    spriteBatch.DrawString(arial, gamer.Gamertag, new Vector2(240, 80), Color.Black);
    spriteBatch.DrawString(arial, profile.Motto, new Vector2(240, 120), new Color(10, 10, 10));
    spriteBatch.DrawString(arial, "Zone: " + profile.GamerZone, new Vector2(100, 230), Color.Black);
    spriteBatch.DrawString(arial, "Region: " + profile.Region, new Vector2(100, 260), Color.Black);
    spriteBatch.DrawString(arial, "Rep: " + profile.Reputation, new Vector2(100, 290), Color.Black);
    spriteBatch.DrawString(arial, "Titles played: " + profile.TitlesPlayed, new Vector2(100, 320), Color.Black);
    spriteBatch.DrawString(arial, "Achievements: " + profile.TotalAchievements, new Vector2(100, 350), Color.Black);
    spriteBatch.DrawString(arial, "Score: " + profile.GamerScore, new Vector2(100, 380), Color.Black);
    spriteBatch.End();

    Step Eleven: Now we need to add the event handling functions which are set up and referenced in the game constructor. The sign in event handler copies the gamer object, profile object and gamer picture. The avatar description is set to that of the gamer's avatar, and a new renderer is created from this description. The gamer signed in flag is also set to true. The signout event handler however just sets this flag to false. After the draw function add:

            void SignedInGamer_SignedIn(object sender, SignedInEventArgs e)
    {
    gamer = e.Gamer;
    profile = e.Gamer.GetProfile();
    gamerPicture = profile.GamerPicture;

    avatarDescription = e.Gamer.Avatar;
    avatarRenderer = new AvatarRenderer(avatarDescription); //Create a renderer for the avatar we have just randomly created

    gamerSignedIn = true;
    }
    void SignedInGamer_SignedOut(object sender, SignedOutEventArgs e)
    {
    gamerSignedIn = false;
    }

    Step Twelve: Add a new sprite font named "Arial", in the spritefont xml description set the fontname tag to "Arial" and the font size to 24. Also download the background file from here and include it in the Content folder of the solution. (Make sure it's included in the project)

    Step Thirteen: Deploy and run on your Xbox 360


    So what have we achieved here? We've added some basic event handlers to handle signing in and out or profiles, and we've taken this signed in player's avatar and other details and rendered them to the screen. It is worth noting however that there are a couple of areas where this will fall down. Notably that if the motto or gamertag is long then it'll go off the yellow block. Additionally if multiple gamers are signing in and out then, the last player to sign in will have their avatar rendered, while if any signed in player signs out then the system assumes no players are signed in. However in the interests of keeping this tutorial simple, I've not gone over these elements.

    Complete source (Game1.cs)

    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    namespace AvatarStepOne
    {
    public class Game1 : Microsoft.Xna.Framework.Game
    {
    GraphicsDeviceManager graphics;

    AvatarDescription avatarDescription;
    AvatarRenderer avatarRenderer;
    AvatarAnimation avatarCelebrateAnimation;

    SpriteBatch spriteBatch;
    SpriteFont arial;
    bool gamerSignedIn = false;
    GamerProfile profile;
    Gamer gamer;
    Texture2D gamerPicture;
    Texture2D background;

    public Game1()
    {
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    Components.Add(new GamerServicesComponent(this));
    graphics.PreferredBackBufferWidth = 1280;
    graphics.PreferredBackBufferHeight = 720;
    SignedInGamer.SignedIn += new EventHandler<SignedInEventArgs>(SignedInGamer_SignedIn);
    SignedInGamer.SignedOut += new System.EventHandler<SignedOutEventArgs>(SignedInGamer_SignedOut);
    }

    protected override void LoadContent()
    {
    avatarCelebrateAnimation = new AvatarAnimation(AvatarAnimationPreset.Celebrate);
    spriteBatch = new SpriteBatch(GraphicsDevice);
    background = Content.Load<Texture2D>("background");
    arial = Content.Load<SpriteFont>("Arial");
    }

    protected override void Update(GameTime gameTime)
    {
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
    this.Exit();

    if (gamerSignedIn && avatarRenderer.IsLoaded)
    {
    avatarCelebrateAnimation.Update(gameTime.ElapsedGameTime, true);
    }

    base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(background, new Vector2(0), Color.White);
    spriteBatch.End();

    if (gamerSignedIn)
    {
    avatarRenderer.View = Matrix.CreateLookAt(new Vector3(1, 1, -3), new Vector3(1, 1, 0), new Vector3(0, 1, 0)); //Set the view matrix supplying a sensible eye position, target and up direction
    avatarRenderer.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f);
    avatarRenderer.Draw(avatarCelebrateAnimation.BoneTransforms, avatarCelebrateAnimation.Expression);

    spriteBatch.Begin();
    spriteBatch.Draw(gamerPicture, new Rectangle(115, 81, 100, 100), Color.White);
    spriteBatch.DrawString(arial, gamer.Gamertag, new Vector2(240, 80), Color.Black);
    spriteBatch.DrawString(arial, profile.Motto, new Vector2(240, 120), new Color(10, 10, 10));
    spriteBatch.DrawString(arial, "Zone: " + profile.GamerZone, new Vector2(100, 230), Color.Black);
    spriteBatch.DrawString(arial, "Region: " + profile.Region, new Vector2(100, 260), Color.Black);
    spriteBatch.DrawString(arial, "Rep: " + profile.Reputation, new Vector2(100, 290), Color.Black);
    spriteBatch.DrawString(arial, "Titles played: " + profile.TitlesPlayed, new Vector2(100, 320), Color.Black);
    spriteBatch.DrawString(arial, "Achievements: " + profile.TotalAchievements, new Vector2(100, 350), Color.Black);
    spriteBatch.DrawString(arial, "Score: " + profile.GamerScore, new Vector2(100, 380), Color.Black);
    spriteBatch.End();
    }

    base.Draw(gameTime);
    }
    void SignedInGamer_SignedIn(object sender, SignedInEventArgs e)
    {
    gamer = e.Gamer;
    profile = e.Gamer.GetProfile();
    gamerPicture = profile.GamerPicture;

    avatarDescription = e.Gamer.Avatar;
    avatarRenderer = new AvatarRenderer(avatarDescription); //Create a renderer for the avatar we have just randomly created

    gamerSignedIn = true;
    }
    void SignedInGamer_SignedOut(object sender, SignedOutEventArgs e)
    {
    gamerSignedIn = false;
    }
    }
    }
  • Avatars - Step One - Getting Started

    Following my introduction to the series of articles I'm writing on the use of avatars in XNA games, (which I'd advise you to read before this article) it would only make sense to start with the basics of implementing avatars in an XNA 3.1 game. The following shows an implementation of how to get avatars into XNA:

    Step 1: Start a new XNA 3.1 project, and select the Xbox 360 3.1 template.


    Step 2: In the variable declarations add:

    AvatarDescription avatarDescription; //Stores the data relating to an avatar's appearance in a byte array, and allows generation of a random avatar
    AvatarRenderer avatarRenderer; //Allows an easy method to render avatars
    AvatarAnimation avatarCelebrateAnimation; //Stores the animation keyframe bone matrices so that the bones of the avatar can be modified

    Step 3: In the Game1 class constructor add:

    Components.Add(new GamerServicesComponent(this)); //Avatars require the GamerServices component so we need to attach it

    Step 4: In the LoadContent function add:

    avatarDescription = AvatarDescription.CreateRandom(); //Generate a random avatar, by randomising the description byte array with acceptable values 
    avatarRenderer = new AvatarRenderer(avatarDescription); //Create a renderer for the avatar we have just randomly created
    avatarCelebrateAnimation = new AvatarAnimation(AvatarAnimationPreset.Celebrate); // Load the celebrate animation 

    Step 5: In the Update function add:

    if (avatarRenderer.IsLoaded) //If the avatar has been loaded, update the animation
    {
    avatarCelebrateAnimation.Update(gameTime.ElapsedGameTime, true);
    }

    Step 6: In the Draw function add:

    avatarRenderer.View = Matrix.CreateLookAt(new Vector3(0, 1, -3), new Vector3(0, 1, 0), new Vector3(0, 1, 0)); //Set the view matrix supplying a sensible eye position, target and up direction
    avatarRenderer.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f); //Again a sensible projection matrix
    avatarRenderer.Draw(avatarCelebrateAnimation.BoneTransforms, avatarCelebrateAnimation.Expression); //Now draw the avatar, passing to it the animations bones and expression texture

    Step 7: Deploy and run on your Xbox 360

    So how does all that work? Basically what happens is we store data relating to the appearance of the avatar, the avatar's animation and a system to render it. Every update call we move through the animation a little, and then in every draw call we render out the avatar according to its appearance description and current animation bone world matrices.

    Complete source (Game1.cs)

    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    namespace AvatarStepOne
    {
    public class Game1 : Microsoft.Xna.Framework.Game
    {
    GraphicsDeviceManager graphics;

    AvatarDescription avatarDescription;
    AvatarRenderer avatarRenderer;
    AvatarAnimation avatarCelebrateAnimation;

    public Game1()
    {
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    Components.Add(new GamerServicesComponent(this));
    }

    protected override void LoadContent()
    {
    avatarDescription = AvatarDescription.CreateRandom();
    avatarRenderer = new AvatarRenderer(avatarDescription);
    avatarCelebrateAnimation = new AvatarAnimation(AvatarAnimationPreset.Celebrate);
    }

    protected override void Update(GameTime gameTime)
    {
    // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
    this.Exit();

    if (avatarRenderer.IsLoaded)
    {
    avatarCelebrateAnimation.Update(gameTime.ElapsedGameTime, true);
    }

    base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.CornflowerBlue);

    avatarRenderer.View = Matrix.CreateLookAt(new Vector3(0, 1, -3), new Vector3(0, 1, 0), new Vector3(0, 1, 0));
    avatarRenderer.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f);
    avatarRenderer.Draw(avatarCelebrateAnimation.BoneTransforms, avatarCelebrateAnimation.Expression);

    base.Draw(gameTime);
    }
    }
    }
  • Avatars - Introduction

    It's been a while since I wrote here, however below is the first in a series of articles I will be writing on the use of avatars with XNA.

    With the addition of Avatars to Xbox 360 last year in November, it was only a matter of time until games started supporting them. With the recent development of XNA 3.1, support has now been added to include avatars in your own games.

    The Dos and Do Nots

    Avatars form part of the Xbox experience, and as such there are limitations on what you can do with them. Because they represent a link to Microsoft and Xbox, it could be perceived as damaging to their reputation to allow you to go round making "murder simulators" or recreating "hot coffee" and releasing it. Indeed, as avatars are officially supported by Microsoft it could be interpreted as Microsoft supporting murder games. But that's just getting into the grounds of downright silly.

    To help you with creating games which don't go against the rules, an article has been provided on the Creators Club website detailing what can't be done. To briefly summarise, it states that the player's avatar cannot have a mind of its own, excessive violence is not allowed, anti social behaviour is also a no-no along with replacing/obscuring avatar features and modifying avatar proportions beyond a uniform scalar. I've heard several people misinterpret the list however, believing that you can only use avatars which belong to the player. The list however states that only player characters are not allowed to be autonomous and only player avatars are not allowed to talk. Presumably it's fine to build games with many avatar NPCs, as long as the player's avatar isn't one of them. (I guess that the chance of a randomised NPC avatar being the same as the players custom one is just grey enough to be allowable.) I would also assume its fine to have non-player avatars as key characters in specific roles and cutscenes. It's just the player's avatar which will not be allowed to talk or interact in cutscenes (remind you of GTA III?)

    As a guideline, Microsoft have stated that only games which are suitable for age 10+ and age ratings below may feature avatars. Meaning any game which would require a rating higher than 10 years of age is not suitable for inclusion of avatars. It might be an idea to have a look at games in the E10+ category, though its quite limited theres still a lot of room, and if you tone down some of the elements of a game which might not be suitable, I'm sure you could get it working.

    Creators Club Samples

    Three samples have been provided, I suggest if you haven't checked them out already that you download them and take a look at the way they work.

    Avatar Animation Blending Sample - shows how to blend one animation into the next, tweening and morphing bones so that you don't get judders and obvious bone repositions when the animation switches.
    Avatar Multiple Animations Sample - shows how to combine several animations at the same time on different parts of the body, this sample for example has the body using the celebrate animation while one of the hands is carrying out the wave animation.
    Object Placement On Avatar Sample - shows how to calculate the position of particular bones, and then have a mesh "stuck" to that part of the body. The sample has the avatar with a baseball bat stuck on their hand. Anyone fancy making a baseball game?

    How do avatars work?

    Avatars are based on skeletal animation for the movement of the body, and rely on changing textures for the facial animations. Each avatar contains all the data relating to its unique state, such as the skin colour, clothes, facial features and other details. It is worth noting that you can only use avatars on Xbox 360 builds, they will not work on PC or Zune, meaning that you need to use XNA Game Studio Connect on the 360 to use them.

    XNA has added a number of classes for animation support, as listed below (class descriptions stolen from creators site):

    AvatarAnimation - Provides methods and properties for animating an avatar using standard animations (for example, celebrate).
    AvatarDescription - Provides access to the methods and properties of the description data for an avatar.
    AvatarExpression - Contains the various components of the avatar's face, such as the left and right eyebrows.
    AvatarRenderer - Provides properties and methods for rendering a standard avatar.

    AvatarAnimationPreset - Defines standard animations for avatars.
    AvatarBone - Defines a list of the useful bones of the avatar model.
    AvatarEyebrow - Defines the standard animation textures for an avatar's eyebrows.
    AvatarEye - Defines the standard animation textures for an avatar's eyes.
    AvatarMouth - Defines the standard animation textures for an avatar's mouth.

    There have have also been two additions to the SignedInGamer class allowing you to use the signed in players' avatars and to detect whether they have been changed.

    SignedInGamer.AvatarChanged - Occurs when a gamer's avatar changes.
    SignedInGamer.Avatar - Description data for the avatar that represents the gamer.

    Custom Animations

    While I haven't found any mention about if custom animations are allowed in XNA (please let me know if you find any material saying it is), it would be logical to assume that it's allowed, especially based on the structure of the avatar support in XNA 3.1. Since the animations that come supported are very limited, it would be very good to add some more, running/walking/jumping/driving etc. The guys at CoderNet.es have made some excellent work on this front, creating custom animations in 3ds max, then getting these animations working in XNA. You can check out a video tutorial which also demonstrates the finished in game animation at Youtube. You can also download the source code, along with two Max files. One containing the base biped (unanimated and in a classic T), the other contains the animation he creates in that video (arms spread like wings, going from side to side.) Using this, you should be able to create your own animations, and get them working!

    Useful snippet

    Finally, although this is just the introduction article to the series there's still a snippet of code which you may be interested in if you don't know about it.

    The samples currently just generate random avatars and draw them, while this is a nice feature it comes second to being able to use your own avatars. To set the avatar description to an actual player's avatar use "avatarDescription = Gamer.SignedInGamers[PlayerIndex.One].Avatar;"

  • Rotated rectangle to rectangle collision

    While recently working on a 3D crazy taxi like game, I had to program the collision checking code between a vehicle and other vehicles or buildings. Since the project didn't have the car moving in the vertical axis, collision is essentially 2D. Unfortunately I couldn't find any support for rotated rectangle collision in XNA, only collision between two parallel rectangles, so needed to code this collision detection from scratch.

    There are two criteria for a collision between two rectangles:

    * A rectangle line intersects the other rectangles line
    * The entire rectangle is contained in the other rectangle (a rectangle point is contained in the other rectangle)

    Because the collision detection rate was so high, and time was slim I decided not to bother with the latter as most objects were of comparable size any way. As such collision between the two rectangles can be done by testing each line in the rectangle against each line in the other rectangle. Similarly, this could be applied to any shape (uniform or otherwise).

    For checking the line to line collision detection I coded a dedicated function. The function essentially worked like this:

    First of all we represent each line as two points, stored as a Vector2. For line A we have A1 and A2, for line B we have B1 and B2.



    Next we translate all points so that A1 is at 0,0.



    Finally we then rotate all points so that A2 is on the X axis. (and as such line A goes along the X axis from the origin to a certain point at (whatever, 0)



    Now that we have the lines in this state it is simple to work out whether line B intersects line A, firstly B1 and B2 must be on opposite sides of the x axis, and the point where line B crosses the X axis must be between A1 and A2.

    Now all that's necessary is to iterate through each line and test its collision against each line from the other rectangle using this line-to-line collision method.

    As usual comments and criticisms are appreciated. I can post a proof of concept project with the code if someone wants it
  • The Dictionary class and its use in preventing memory duplication

    Warning: This article is partially obsolete. See footnote 1

    I'm currently writing a 2d platformer game, a project that I intend to last only a few days. I've implemented a map loading system which makes use of XML  to store the platform information and textures. When parsing the XML document and adding objects to a list of platform I ran into a minor problem, my platform class stores a Texture2D for the platform texture, and the existing system of passing a Content.Load<Texture2D> to the platform class constructor as a parameter would result in massive memory duplication of the texture, with game worlds that could consist of hundreds of the same textured platform, the game would be loading and storing the same texture hundreds of times. To get round this I made use of the dictionary class, the approach is explained below:

    Declaration 

    Dictionary<string, Texture2D> textureDictionary = new Dictionary<string, Texture2D>(); 

    The dictonary class has two parts to it, the key and the value. Here I am using the texture name as the unique identifier, and the Texture2D class to store the texture.

    Checking whether the texture already exists and adding an entry if it doesn't

    if (!textureDictionary.ContainsKey(textureName))
    {
                            textureDictionary.Add(textureName,Content.Load<Texture2D>(textureName));
    }

    First off we check to see if the texture has already been added, if it hasn't we add a new entry to the dictionary entry supplying the texture name as a key, and loading the texture in as a Texture2D from the Content folder (here we are assuming that all your textures are loaded into the projects content folder, an alternate loading system would be required if they aren't.)

    Using the stored texture

    platforms.Add(new Platform(platformRectangle,textureDictionary[textureName]));

    Finally we reference the textureDictionary entry, by supplying the texture name as the key we can get the value of the dictionary entry (in this case the texture), much in the same way passing an index to an array works.


    Footnote 1: It has unfortunately been pointed out to me that the Content loader already stops memory duplication as it will only load content once. On testing this I've noticed that there is no noticeable difference in load time between loading a 1 megabyte texture once or ten thousand times. I will rewrite this article at some point to show how dictionary classes can be used for something actually useful, however I hope the existing display of their workings will be useful to any of you who haven't encountered them yet.

  • Bullet Collision

    Bullet collision can often be a problem, while a small projectile moving at high velocity will cause a lot of damage in the real world in can be hard to simulate the collision properly using collision methods which would treat the projectile as an ordinary object. As such object to object collision (for example sphere to sphere) collision requires either a very low projectile velocity or a very high framerate (or in XNA's multithreaded case updaterate). Because a realistic simulation of the projectile will have it travelling a large distance between position updates, it is necessary to treat the entire range of positions between the last update position and current update position as potential collision sites. As such line to object collision is highly useful, as you can test a line between the last update position and current bullet position with your impactable targets.

    For this example I'm going to explain line to sphere collision, much of collision detection involves working out distances (for instance 3d sphere to sphere collision is essentially a one dimensional distance measurement, just rotated into a 3d plane.) In this example we need four pieces of data: the bullet's last update position, it's current position, the target collision sphere centre and its radius.

    Ideally we want the bullet to be travelling along an axis, this is so we can disregard unneccessary dimensions. To do this, you'll need to use trigonometry to find the angles the bullet is travelling at to the axis (in this case the z axis) once this has been done you'll end up essentially with the data which the two diagrams below provide.



    The y-x diagram does not include the z axis, and therefore does not factor in two bullet positions, rather the common path of the bullet and what the bullet could potentially or have potentially hit. The y-z diagram however factors in the bullet distance travelled to see whether it intersects with the sphere (or circle) from a side perspective.

    Wrapping it up:

    • Find the bullet's last position, it's current position, and the object you're interested in's collision sphere position/radius.
    • Resolve the 3d co-ordinates so that the bullet is travelling along an axis to make detection much simpler.
    • Check the view from behind the bullet to see if a line of infinite length would intersect the sphere.
    • Check the view from the side to see if the actual line would intersect a sphere while ignoring the x axis.
    • If both the two conditions are true then a collision occured.
  • Object Visibility: Adventures in Efficiency

    It's been a few weeks since my last post here, during that time I've been attempting to improve the efficiency of the code which seems to not be as cheap on the CPU as I was expecting due to the heavy CPU use in reading the frame buffer as a Texture2D then cycling through the pixels to find a red pixel. More recently I've tried reimplementing the code by using an HLSL shader, my hope was to somehow make the shader do the work of the object visibility detection, and to flag up the top left pixel as red in the event of any pixel in the scene being red. That way only one pixel check needs occur rather than buffer width*height number of checks. Unfortunately I've yet to be able to implement a shader which can accomplish this, and it's possible that HLSL shaders simply can't operate in a fashion which could emulate such functionality. The method I finally resorted to was use of an occlusion query, if you're not familliar with occlusion queries, they basically operate by determing the number of pixels changed by a drawing event. As such if an object is visible on screen, the occlusion query would return a positive number, otherwise the query would return 0. This has it's drawbacks unfortunately, it doesn't appear to run as fast as I believe a shader approach could (certainly not in all potential cases anyway) and the query return runs on the GPU, and as such is independent of the CPU's set of instructions. This means that the query return could be at any time, rather than at a set time as it would if running also on the CPU, as such the output can not be relied upon to be returned before the frame has finished drawing. (Thanks to MJP from GameDev and Leaf for advising the use of occlusion queries.)

    I'll post the new version of the object visibility code soon.

    In other projects, the polygon ping pong project is currently on hold (on my end) until the other programmer finishes the networking code. I should also be posting up an XML Mapping System for XNA soon, which I've developed for the Imagine Cup entry I'm involved in. The basic elements such as loading the objects, then applying translations, rotations, scaling and collision detection has been implemented, I'm now adding more advanced features to the system and should be posting the code in a week.

  • CPU Cheap Object Visibility Detection

    http://www.youtube.com/v/bIKZdOWbRa4 <p><a href="http://www.youtube.com/v/bIKZdOWbRa4">http://www.youtube.com/v/bIKZdOWbRa4</a></p>

    Detecting whether an object is visible or not can be very CPU intensive when you start using raytracing, but with CPU speeds and polygon renderring ever at a premium it can be advanteous to look to other means. This example uses an industry trick which is as old as the hills, to check whether a single pixel of the target object is visible. Ok, so how does it work:

    The program works by performing two renders, while there is an ordinary render which displays the end image, there is a second render which is used for visibility checks.

    For this render everything is turned off, whether it's your HUD, special effects, bloom, some pretty shader effect, bump mapping, textures or lighting. Next everything is renderred in the same colour -copy  white, except for the target object which is renderred in red. The program then creates a temporary copy of the backbuffer as a texture, creates an array of pixels from this texture and cycles through them. If it finds a red pixel, then the program knows that the object is visible.

    The advantage of this system, not just the saving on CPU time, is the expandability. We're only dealing with one colour (representation of an object) here, and 24 bit colour systems support 16777216 colours, so you can essentially peform this check on as many objects as you can render simultaneously. Furthermore, you can set the renderred size of this pass to be quite small compared to your main renderring which might be 1080p for instance, which speeds up renderring even further. The advantage of a smaller relative object detection pass is that theres no point renderring a high polycount model for the sake of a pixel which may not be visible on a smaller resolution. Indeed, by counting red pixels and using a threshold you could turn off renderring of objects which have less than 5 pixels on screen (although this could be a slippery slope, and is certainly not recommended ordinarily.) Also, it's rarely important to run the visibility check every frame, so you could reduce the iterations to say once every 5 renderred frames, to reduce the dent on the CPU further.

    Please note, the above improvements require modifications to the supplied code, some of which require fundamental recodes, and are shown only for illustrative purposes. Although I may implement many of these features and release further code sometime soon.


    Source Download

    Comments as always are very welcome.

  • New Blog

     

    The logical thing for me to do here would be for me to introduce both myself and the blog, not being one to shy away from the logical course of action I suppose that's exactly what I should do ;-). My name is Barnaby Smith, I'm a bedroom coder and have been programming for 11 years now since the days of QuickBasic on Windows 3.11. I am able to use C++, C#, VB6, Java, PHP/MySQL, XHTML and a range of other languages. More recently I've made the logical (there's that word again) step of starting a games programming degree at University of Huddersfield. Last year the university decided to start using XNA, which I picked up easily having previously built 3d games in DirectX 8.0/VB. I am currently working on two projects in XNA, one is a ping pong game, with a twist, for the Xbox Live Community Games, the other project is an entry for this year's Imagine Cup. During my time on this blog, while talking about many other aspects of XNA, I will be starting by covering the development of the ping pong game, followed by the Imagine Cup entry.

    Polygon Ping Pong

    The mechanics of this game are very straightforward, the game consists of a polygon (n-sided shape) which starts with 8 sides. Each side represents a player and has its respective colour and bat, the objective is like ordinary ping pong games: to hit the ball with the intention of making an opponent unable to hit the ball back, while ensuring as few balls go past your line as possible. Each player will be given a set number of lives, once these lives are exhausted the player loses, and the polygon loses a side - their side. Once the 6th player loses, the game goes from a triangle to an ordinary ping pong game (4 sides, 2 for players and 2 for walls) to form a Finale mode. The game is intended to be highly configurable, and will support both human and and AI players, with support for 4 people on one Xbox, or up to 8 online. Development started yesterday on the 13th. The end of Day 1 and Day 2 videos are available to watch below. Comments are welcome.

    http://www.youtube.com/v/SWfaoBuuga4 <p><a href="http://www.youtube.com/v/SWfaoBuuga4">http://www.youtube.com/v/SWfaoBuuga4</a></p>

    http://www.youtube.com/v/EC3OkooYgcc <p><a href="http://www.youtube.com/v/EC3OkooYgcc">http://www.youtube.com/v/EC3OkooYgcc</a></p>