While I have been fully enjoying my Zune HD experience I decided I should give apps a try after seeing the announcement about XNA Studio 3.1 and the XNA Extensions for the Zune HD.  I have explored XNA a little prior to this but did not really dig into it.  With my Zune HD in hand I decided it was time to take it for a spin.

Getting Started – What you need:

  • Zune HD (16 or 32gb, I rock with the 32) + Cable
  • Visual Studio 2008 / Visual C# + XNA Studio 3.1
  • Zune HD Extensions
  • Zune Software must be closed while running XNA Studio and debugging on your Zune hardware

Should you try to run software on your Zune without the extensions you will get an error message to the effect of “The XNA Framework runtime required by this game project is not available on ‘{YOUR ZUNE NAME HERE}’”.  If you see this message, make sure you have the extensions installed and that your project targets XNA 3.1.  This post on the XNA Creators Club forums helped me get started.

For some other background reading check out “Nazeeh’s Little Corner of the Web”, particularly his posts Anatomy of a Game Part 1 and “Hello World!” in XNA.

Exploring Microsoft.Xna.Framework.Input

As with all things framework, namespaces help us find things.  The default XNA Project for the Zune does not give you too many pointers on where to find your input devices so I hopped over to object browser and found some interesting classes:

inputTouch

The documentation on the classes is pretty skim so I took a stab at some code and hacked this out:

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            //Get the touches from the TouchPanel
            TouchCollection touches = TouchPanel.GetState();
            if (TouchPanel.GetCapabilities().HasPressure)
            {
                foreach (TouchLocation item in touches)
                {
                    squareManVector = item.Position;
                    touchPressure = item.Pressure;
                }
            }
            base.Update(gameTime);
        }

There is a TouchCollectionEnumerator, however, I was looking for the simplest thing that could possibly work and this does the job.  What I did was created a TouchCollection variable “touches” and call “GetState” on the TouchPanel class.  That provides a TouchCollection which we can enumerate through to update the position and pressure.  I’m not entirely sure the check for HasPressure is needed, but I was exploring the API and thought I would see what that provided. 

A couple of variables in here may leave you wondering, so I will explain them real quick.  squareManVector is a Vector2 which sets the position of my square man sprite: Square Man who is aptly named squareManTexture.  Yes I know, he is nothing fancy!  In my first attempts just to learn I was looking for the basics, so I stuck him at a vector of 0,0.  But, after discovering the touch API I decided to see if I could move him around. 

Also note that for the Zune HD the “BackButton” is the button on the center of the device near the bottom.  Based on the code above it becomes the de-facto exit button.

In the Draw method I have the following code:

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

            spriteBatch.Begin();
            string currentVector = string.Format("{0}.{1} : {2}",                squareManVector.X.ToString(),                squareManVector.Y.ToString(),                touchPressure.ToString());
            spriteBatch.DrawString(font, currentVector, new Vector2(50, 50), Color.Black);
            spriteBatch.Draw(squareManTexture, squareManVector, Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

What is the end result you ask?  When the game loads, squareMan is hanging out at the top left of the screen:

Razor-30-1

If you touch the screen he obediently moves:

Razor-30-2

But we can do more than touch…so let’s drag him around:

Razor-30-3

Note that while dragging the pressure sensitivity begins to display.  Freaking sweet!  I don’t think I have been this giddy about programming since I first started.  Look forward to more articles on XNA programming as I dive into it with the Zune HD.  I might even have to hook up my 360 with XNA Studio to give that a whirl!

Update 9/19/2009 @ 11:47PM CST

Because I’m still tinkering with it, here is how you can use an IEnumerator with the TouchPanel which is probably the more proper way to use it:

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

            IEnumerator<TouchLocation> touches = TouchPanel.GetState().GetEnumerator();
            while (touches.MoveNext())
            {
                squareManVector = touches.Current.Position;
                touchPressure = touches.Current.Pressure;
            }

            base.Update(gameTime);
        }

Enjoy!!