Roy Triesscheijn’s Weblog

My programming world

CodeSnippet: Quad renderer

Posted by Roy Triesscheijn on 7th May 2011

This quad renderer was already part of my conversion of Catalin Zima’s Deferred Rendering for XNA tutorial, but because I plan to use it in a tutorial I’m going to write later today here is a handy snippet for drawing a quad with texture coordinates in XNA. (You could use the SpriteBatch class for this, but as you all know the SB class tends to mess up your render state if you do not define all states correctly).

Anyway here’s the class:

    public class QuadRenderer
    {
        public QuadRenderer(GraphicsDevice device)
        {
            this.device = device;
            vertices = new VertexPositionTexture[]
            {
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(1,1)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(0,1)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(0,0)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(1,0))
            };

            indexBuffer = new short[] { 0, 1, 2, 2, 3, 0 };
        }

        public void Draw(Vector2 v1, Vector2 v2)
        {
            vertices[0].Position.X = v2.X;
            vertices[0].Position.Y = v1.Y;

            vertices[1].Position.X = v1.X;
            vertices[1].Position.Y = v1.Y;

            vertices[2].Position.X = v1.X;
            vertices[2].Position.Y = v2.Y;

            vertices[3].Position.X = v2.X;
            vertices[3].Position.Y = v2.Y;

            device.DrawUserIndexedPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, 4, indexBuffer, 0, 2);
        }

        public void DrawFullScreenQuad()
        {
            Draw(Vector2.One * -1, Vector2.One);
        }

        #region FieldsAndProperties
        private VertexPositionTexture[] vertices = null;
        private short[] indexBuffer = null;
        private GraphicsDevice device;
        #endregion
    }

Tags: , ,
Posted in Blog, XNA | 1 Comment »

Traversal algorithms using generics, generic constraints (where), and Action delegates

Posted by Roy Triesscheijn on 10th February 2011

As many of you I enjoy solving a very complex problem, however sometimes it’s finding new ways todo simple things that really excites me! This happened again today, I was working on a simple Depth-First-Search traversal algorithm when it suddenly doomed to me that I was duplicating a lot of code because I had to do DFS multiple times, with the only difference the action to take at each node.

Pondering about this for a few minutes and I thought about using a delegate as a sort of method pointer to tell the DFS algorithm what action to take for each node. I wrote a quick delegate and named it Action, but then I remembered that C# has the built in Action delegate.

With these techniques in mind I quickly wrote the following code:

public void DFS<T>(T node, Action<T> action) where T : IHasChildren<T>
{
    Stack<T> stack = new Stack<T>();
    action(node);
    stack.PushMany<T>(node.Children);
    while (stack.Count > 0)
    {
        T n = stack.Pop();
        action(n);
        stack.PushMany<T>(n.Children);
    }
}

public interface IHasChildren<T>
{
    List<T> Children;
}

This way you can use DFS on any type of node as long as it implements IHasChildren, and you can use any Action too, saves a lot of duplicate code !

Edit:

Stack.PushMany is my own extension method that allows a list to be put on a stack (just a simple for each).

Tags: , , , , ,
Posted in Blog, General Coding | 7 Comments »

Codesnippet: handy input manager

Posted by Roy Triesscheijn on 5th November 2010

Today I was working on a small prototype, however I got carried away a bit with the input management. In the end I spend nearly an hour working on “the mother of all InputManagers”. To spare you from this, I’ve decided to put the snippet online.

Features:
-Registers input from keyboard or gamepad.
-Left, Right, Up, Down mapped to gamepad Dpad and gamepad left thumbstick at the same time.
-Settable deadzones for the gamepad thumbsticks
-Provides, button up, button down and button pressed methods.

The code: (be sure to see the test code as well, at the bottom of this post)

public class InputManager
    {
        public InputManager(InputType type, PlayerIndex player)
        {
            this.inputType = type;
            this.playerIndex = player;

            //Fill dictionaries, TODO: bring this out into an xml file
            inputToKeys = new Dictionary<Inputs, Keys>(10);
            inputToKeys.Add(Inputs.A, Keys.A);
            inputToKeys.Add(Inputs.B, Keys.S);
            inputToKeys.Add(Inputs.Back, Keys.Escape);
            inputToKeys.Add(Inputs.Down, Keys.Down);
            inputToKeys.Add(Inputs.Left, Keys.Left);
            inputToKeys.Add(Inputs.Right, Keys.Right);
            inputToKeys.Add(Inputs.Start, Keys.Space);
            inputToKeys.Add(Inputs.Up, Keys.Up);
            inputToKeys.Add(Inputs.X, Keys.Z);
            inputToKeys.Add(Inputs.Y, Keys.X);

            inputToButtons = new Dictionary<Inputs, Buttons>(10);
            inputToButtons.Add(Inputs.A, Buttons.A);
            inputToButtons.Add(Inputs.B, Buttons.B);
            inputToButtons.Add(Inputs.Back, Buttons.Back);
            inputToButtons.Add(Inputs.Down, Buttons.DPadDown);
            inputToButtons.Add(Inputs.Left, Buttons.DPadLeft);
            inputToButtons.Add(Inputs.Right, Buttons.DPadRight);
            inputToButtons.Add(Inputs.Start, Buttons.Start);
            inputToButtons.Add(Inputs.Up, Buttons.DPadUp);
            inputToButtons.Add(Inputs.X, Buttons.X);
            inputToButtons.Add(Inputs.Y, Buttons.Y);
            //note that left, right, down and up are also mapped
            //to the left thumbstick
        }

        public bool IsInputPressed(Inputs input)
        {
            if (inputType == InputType.Keyboard)
            {
                return (curState.IsKeyDown(inputToKeys[input])
                    && !prevState.IsKeyDown(inputToKeys[input]));
            }
            else //inputType == InputType.Controller
            {
                //Check both left thumbstick dpad and buttons
                return (StickDirectionDown(curPadState, input)
                    && !StickDirectionDown(prevPadState, input))

                    || (curPadState.IsButtonDown(inputToButtons[input])
                    && !prevPadState.IsButtonDown(inputToButtons[input]));
            }
        }

        public bool IsInputDown(Inputs input)
        {
            if (inputType == InputType.Keyboard)
            {
                return curState.IsKeyDown(inputToKeys[input]);
            }
            else //inputType == InputType.Controller
            {
                return (StickDirectionDown(curPadState, input)

                || curPadState.IsButtonDown(inputToButtons[input]));
            }
        }

        public bool IsInputUp(Inputs input)
        {
            if (inputType == InputType.Keyboard)
            {
                return prevState.IsKeyUp(inputToKeys[input]);
            }
            else //inputType == InputType.Controller
            {
                return (!StickDirectionDown(curPadState, input)

                    && prevPadState.IsButtonUp(inputToButtons[input]));
            }
        }

        public bool StickDirectionDown(GamePadState gamePadState, Inputs input)
        {
            if (input == Inputs.Left)
            {
                return (gamePadState.ThumbSticks.Left.X < -thumbStickDeadzone);
            }
            else if (input == Inputs.Right)
            {
                return (gamePadState.ThumbSticks.Left.X > thumbStickDeadzone);
            }
            else if (input == Inputs.Up)
            {
                return (gamePadState.ThumbSticks.Left.Y > thumbStickDeadzone);
            }
            else if (input == Inputs.Down)
            {
                return (gamePadState.ThumbSticks.Left.Y < -thumbStickDeadzone);
            }

            return false;
        }

        public bool InputIsDirection(Inputs input)
        {
            return (input == Inputs.Left || input == Inputs.Right ||
                input == Inputs.Up || input == Inputs.Down);
        }

        public void Update()
        {
            if (inputType == InputType.Keyboard)
            {
                prevState = curState;
                curState = Keyboard.GetState();
            }
            else if (inputType == InputType.Controller)
            {
                prevPadState = curPadState;
                curPadState = GamePad.GetState(playerIndex);
            }

        }        

        #region FieldsAndProperties
        public float thumbStickDeadzone = 0.5f;

        private Dictionary<Inputs, Keys> inputToKeys;
        private Dictionary<Inputs, Buttons> inputToButtons;

        private KeyboardState curState, prevState;
        private GamePadState curPadState, prevPadState;
        private InputType inputType;
        private PlayerIndex playerIndex;
        #endregion
    }

    public enum Inputs
    {
        A, B, X, Y, Left, Right, Up, Down, Start, Back
    }

    public enum InputType
    {
        Keyboard, Controller
    }

Testcode:


InputManager input = new InputManager(InputType.Keyboard, PlayerIndex.One);
public void Update(GameTime gameTime){
            input.Update();

            foreach (object value in Enum.GetValues(typeof(Inputs)))
            {
                if (((Inputs)value) == Inputs.Left)
                {

                }
                bool pressed = input.IsInputPressed((Inputs)value);
                bool down = input.IsInputDown((Inputs)value);
                bool notUp = !input.IsInputUp((Inputs)value);

                if (pressed || down)
                {
                    string message = "Input{3} was: Pressed({0}), Down({1}), NotUp({2})";
                    message = String.Format(message, pressed, down, notUp, Enum.GetName(typeof(Inputs), value));
                    Console.Out.WriteLine(message);
                }
            }
}

Tags: , , , , , ,
Posted in Blog, General Coding, General Gamedesign, XNA | 4 Comments »

XNA: Accessing ContentManager and GraphicsDevice anywhere anytime, the GameServiceContainer

Posted by Roy Triesscheijn on 25th August 2010

A quick code snippet that I produced today and wanted to share.

Often you find yourself looking for a good path/way to give a certain component access to the ContentManager. Usually you will just plug it in the construct. However sometimes the object creating the new object doesn’t have access to this component as well. Things start to become a bit more complicated then, of course you can add it to both constructors, but things often start to clutter.

Objects like the ContentManager and the GraphicsDevice are often needed on the craziest of places in a game’s code. They can easily be shared as they are usually in a valid state throughout the runtime of your program and usually you don’t need more than one. For these kind of objects it would be easy to create a static class so that anyone can access them.

A common technique is to create a static List in which you can throw anything in. But this doesn’t enforce that there is only instance of a given type in the container (why add two GraphicsDevices?) and makes it hard to get the right component from.

Luckily XNA has the GameServiceContainer class which allows you to store elements like this:

container = GameServicesContainer();
container.AddService(typeof(GraphicsDevice), device);

There’s also GetService and RemoveService. However this casting can make a lot of lines way longer than they need to be. Also we need to make the container static and protected access to it, so let’s create a nice little class like this:

public static class GameServices
    {
        private static GameServiceContainer container;
        public static GameServiceContainer Instance {
            get
            {
                if (container == null)
                {
                    container = new GameServiceContainer();
                }
                return container;
            }
        }

        public static T GetService<T>()
        {
            return (T)Instance.GetService(typeof(T));
        }

        public static void AddService<T>(T service)
        {
            Instance.AddService(typeof(T), service);
        }

        public static void RemoveService<T>()
        {
            Instance.RemoveService(typeof(T));
        }
    }

In the Initialize method of Gam1.cs put this:

protected override void Initialize()
        {
            base.Initialize();
            GameServices.AddService<GraphicsDevice>(GraphicsDevice);
            GameServices.AddService<ContentManager>(Content);
        }

Remember that GameServices is static so you can read, add and remove from anywhere in your code like this:

GameServices.AddService<GraphicsDevice>(device);
myDevice = GameServices.GetService<GraphicsDevice>();
GameServices.RemoveService<GraphicsDevice>()

Quite a nifty way of doing this, if I may say that myself (A). However do note (as NullSoldi did on Efnet #xna) that this will increase coupling between your components as some class will start to depend on the non standard class we’ve just created while this otherwise wasn’t needed. However I personally think that the benefits greatly outweigh the small penalty on coupling.

Have fun with this snippet, let me know if you’re using it or found it useful for your own GameServices-like class.

Tags: , , , ,
Posted in Blog, General Coding, General Gamedesign, XNA | 5 Comments »