Sign in to follow this  
FlameTheLoner

XNA 4.0 'Keyboard Input' Help

Recommended Posts

FlameTheLoner    108
I'm learning XNA from a book called Introduction to [i]Programming Through Game Development Using Microsoft XNA Game Studio[/i] by Rob Miles. I am currently learning how to display from the keyboard.

So basically, I'm trying to get my input from the Keyboard to show up as formatted text. Nothing special, just a display of text.

This is my current code.

[code]
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Reading_Text_Input
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

//Game World
SpriteFont font;
string messageString = "";
Keys[] oldKeys = new Keys[0];


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

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here

base.Initialize();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

// Adding font
font = Content.Load<SpriteFont>("SpriteFont1");
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

KeyboardState keyState = Keyboard.GetState();

// Exit on Esc
if (keyState.IsKeyDown(Keys.Escape))
{
this.Exit();
}

//Get pressed keys and display them
Keys[] pressedKeys;
pressedKeys = keyState.GetPressedKeys();

// work through each key presently pressed
for (int i = 0; i < pressedKeys.Length; i++)
{
//set a flag to indicate we have not found the key
bool foundIt = false;


//work through each key previously pressed
for (int j = 0; j < oldKeys.Length; j++)
{
if (pressedKeys[i] == oldKeys[j])
{
//we found the key in previously pressed keys
foundIt = true;
//no need to look further
break;



}



}

if (foundIt == false)
{
//if we get here we didnt find the key in old keys, so
// add the key to the end of the message string
messageString = messageString + pressedKeys[i].ToString();
}
}

//remember currently pressed keys for next time
oldKeys = pressedKeys;



base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

Vector2 messageVector = new Vector2(50, 100);

spriteBatch.Begin();
spriteBatch.DrawString(font, messageString, messageVector, Color.White);
spriteBatch.End();

base.Draw(gameTime);
}
}
}

[/code]

Now, when I run debug and press ' A12RS ' on my keyboard, I get the following output :
[img]http://i55.tinypic.com/15n7ml4.jpg[/img]

You can see that the numbers '1' '2' are displayed as D1 and D2.

Now I found out some code which can fix this, which is the following :

[code]string keyString = ""; //empty string
switch (pressedKeys[i])
{
//digits
case Keys.D0:
keyString = "0";
break;

case Keys.D1:
keyString = "1";
break;

// other keys
}[/code]

Now the problem is, I don't know where to put this code. And the book doesn't specify where. I tried putting it in Update in many places, but I get errors.

Could someone observe the code and tell me where to put the code in so that it displays 'A12RS'?

Share this post


Link to post
Share on other sites
Litz    122
When you add the string of a key to your message, check if it's a digit. If it is, add whatever you want to add instead. If not, add the actual string.

You just need to edit this piece of code:

[code]messageString = messageString + pressedKeys[i].ToString();
[/code]

Share this post


Link to post
Share on other sites
marrshal    108
Change the end of Update to:


[code]
if (foundIt == false)
{
//if we get here we didnt find the key in old keys, so
// add the key to the end of the message string
string keyString = ""; //empty string
switch (pressedKeys[i])
{
//digits
case Keys.D0:
keyString = "0";
break;

case Keys.D1:
keyString = "1";
break;

// other keys

default:
keyString = pressedKeys[i].ToString();
break;
}
messageString = messageString + keyString;
}[/code]

Share this post


Link to post
Share on other sites
FlameTheLoner    108
[quote name='Marrshal' timestamp='1311104552' post='4837576']
Change the end of Update to:


[code]
if (foundIt == false)
{
//if we get here we didnt find the key in old keys, so
// add the key to the end of the message string
string keyString = ""; //empty string
switch (pressedKeys[i])
{
//digits
case Keys.D0:
keyString = "0";
break;

case Keys.D1:
keyString = "1";
break;

// other keys

default:
keyString = pressedKeys[i].ToString();
break;
}
messageString = messageString + keyString;
}[/code]
[/quote]

OMG Thank You!
Worked perfectly!

Share this post


Link to post
Share on other sites
FlameTheLoner    108
By the way, this piece of code is a bit confusing for me :

[code]//Get pressed keys and display them
Keys[] pressedKeys;
pressedKeys = keyState.GetPressedKeys();

// work through each key presently pressed
for (int i = 0; i < pressedKeys.Length; i++)
{
//set a flag to indicate we have not found the key
bool foundIt = false;


//work through each key previously pressed
for (int j = 0; j < oldKeys.Length; j++)
{
if (pressedKeys[i] == oldKeys[j])
{
//we found the key in previously pressed keys
foundIt = true;
//no need to look further
break;



}
[/code]

Could someone explain what exactly is going on here?

From what I got, it is comparing my currently pressed keys with my previously pressed keys. But after that its kinda meh (the nested for loops confuse me). Could someone break it down and explain it to me? :D

Share this post


Link to post
Share on other sites
marrshal    108
[quote name='FlameTheLoner' timestamp='1311144144' post='4837821']
By the way, this piece of code is a bit confusing for me :

[code] //Get pressed keys and display them
Keys[] pressedKeys;
pressedKeys = keyState.GetPressedKeys();

// work through each key presently pressed
for (int i = 0; i < pressedKeys.Length; i++)
{
//set a flag to indicate we have not found the key
bool foundIt = false;


//work through each key previously pressed
for (int j = 0; j < oldKeys.Length; j++)
{
if (pressedKeys[i] == oldKeys[j])
{
//we found the key in previously pressed keys
foundIt = true;
//no need to look further
break;



}
[/code]

Could someone explain what exactly is going on here?

From what I got, it is comparing my currently pressed keys with my previously pressed keys. But after that its kinda meh (the nested for loops confuse me). Could someone break it down and explain it to me? :D
[/quote]


Well, when you are wondering what a piece of code was doing - delet it and see the difference.
When you deletit you'll see if you hold a key it would be drawn many times. This code avoids that.

It is very bad formated so it is hard understand it. Look that:[font="CourierNew, monospace"] [/font]
[code]
//Get pressed keys and display them
Keys[] pressedKeys;
pressedKeys = keyState.GetPressedKeys();


// work through each key presently pressed
for (int i = 0; i < pressedKeys.Length; i++)
{
//set a flag to indicate we have not found the key
bool foundIt = false;


//work through each key previously pressed
for (int j = 0; j < oldKeys.Length; j++)
{
if (pressedKeys[i] == oldKeys[j])
{
//we found the key in previously pressed keys
foundIt = true;
//no need to look further
break;
}
}

//...
}[/code]


oldKeys are the keys pressed (at the same time) in the last call of Update
pressedKeys are the currently pressed keys.
First loop "visits" each currently pressed key. The second loop compare the current key from the first loop. When (if) it is found the search stops (that do the break statement if the second loop) and that key is not drawn. Analogeus, if it is not found the key is drawn.

[i]Note[/i]: When you release all keys pressedKeys is empty and because of that you can draw single letter several times.

Hope I was helpful :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this