XNA 4.0 Behavior-driven Development, Chapter 6

0 views
Skip to first unread message

David Wallace

unread,
Dec 22, 2011, 4:50:09 AM12/22/11
to bost...@googlegroups.com
Chapter 6: RNA input synthesis

These last two methods use input to create vectors.

    public class KeyVectorTest : TestBase
    {
        List<Keys> keys = new List<Keys>();
        InputService input;

        public override bool Test(BehaviorArgs args)
        {
            var forekey = (input.IsDown(keys[0]) ? 1 : 0);
            var backkey = (input.IsDown(keys[1]) ? 1 : 0);
            var leftkey = (input.IsDown(keys[2]) ? 1 : 0);
            var rightkey = (input.IsDown(keys[3]) ? 1 : 0);
            args.Position = new Vector3(forekey - backkey, rightkey - leftkey, 0);
            return args.Position.Length() > 0;
        }

Left and right here are relative to the direction the character is pointing.

        public KeyVectorTest(InputService gi, Keys[] data)
        {
            input = gi;
            keys = data.ToList();
        }

        public static TestBase Build(ContentService service, string source)
        {
            var ginput = service.Serve<InputService>();
            if (ginput == null) return null;
            var sources = source.Split(',');
            if (sources.Length < 4) return null;
            Keys key;
            Keys[] keys = new Keys[4];
            for (int i = 0; i < 4; i++)
            {
                if (!Enum.TryParse<Keys>(sources[i], out key))
                    throw new InvalidCastException("Invalid key " + sources[i]);
                keys[i] = key;
            }
            return new KeyVectorTest(ginput, keys);
        }
    }

The idea here is to allow four keys to represent directions and build a vector from them.  The script could implement this as KeyVector(W,A,S,D), for example.

The gamepad is not so simple, however.

    public class PadVectorTest : TestBase
    {
        string type;
        InputService input;

        public override bool Test(BehaviorArgs args)
        {
            args.Position = new Vector3(input.Vector(type), 0);
            return args.Position.Length() > 0;
        }

        public PadVectorTest(InputService gi, string data)
        {
            input = gi;
            type = data;
        }

        public static TestBase Build(ContentService service, string source)
        {
            var ginput = service.Serve<InputService>();
            if (ginput == null) return null;
            return new PadVectorTest(ginput, source);
        }
    }

The test seems straightforward, but I had to add a method to the InputService behind the scenes to support it.

        public Vector2 Vector(string target)
        {
            if (!pad[me].IsConnected) return Vector2.Zero;
            switch (target)
            {
                case "Dpad":
                    Vector2 dir = Vector2.Zero;
                    if (pad[me].DPad.Left == ButtonState.Pressed)
                dir -= Vector2.UnitX;
                    if (pad[me].DPad.Right == ButtonState.Pressed)
                dir += Vector2.UnitX;
                    if (pad[me].DPad.Up == ButtonState.Pressed)
                dir -= Vector2.UnitY;
                    if (pad[me].DPad.Down == ButtonState.Pressed)
                dir += Vector2.UnitY;
                    if (dir.Length() > 1) dir.Normalize();
                    return dir;
                case "LeftThumb":
                    return pad[me].ThumbSticks.Left;
                case "RightThumb":
                    return pad[me].ThumbSticks.Right;
                case "Trigger":
                    return new Vector2(
                        pad[me].Triggers.Left,
                        pad[me].Triggers.Right);
                default:
                    return Vector2.Zero;
            }
        }

Note that BehaviorArgs.Position contains the resulting vector, passing it in turn to the action that supports it.

Reply all
Reply to author
Forward
0 new messages