Delay in keyboard input
I'm so close! I am using the XNA Game State management example here and am trying to change the way I handle input so that I can hold a key / create an input buffer.
In GameplayScreen.cs, I declared a double name elapsedTime and set it to 0.
In the HandleInput method, I changed the Key.Right button to:
if (keyboardState.IsKeyDown(Keys.Left))
movement.X -= 50;
if (keyboardState.IsKeyDown(Keys.Right))
{
elapsedTime -= gameTime.ElapsedGameTime.TotalMilliseconds;
if (elapsedTime <= 0)
{
movement.X += 50;
elapsedTime = 10;
}
}
else
{
elapsedTime = 0;
}
Pseudocode:
If the right arrow key is not pressed, time will elapse from time to 0. If pressed, the elapsed time is equal to the minimum millisecond since the last frame. If the difference is then 0 or less, move object 50 and then set the elapsed time to 10 (delay).
If the key is held down, then after the event the value should never be set to 0. Instead, after the elapsed time after a successful check, the decimal time value expires, the elapsed time should be lower and lower as it is subtracted by TotalMilliseconds. When it reaches 0, it will check the validation again and move the object again.
The problem is that it moves the object once for each click, but doesn't work if you hold it down. Can anyone offer any advice / example / bit of knowledge on this? Thanks in advance, it was driving me crazy. In theory, I thought it would work for sure.
EXPLANATIONS
Think about the grid when you think about how I want the block to move. Instead of just moving around the screen, it moves widthwise (honeycomb jumps) to the next position. If I hold down the key, it runs across the screen. I want to slow down this whole process so that holding down a key creates a delay of X milliseconds between jumping / moving across it in width.
EDIT: Turns off gameTime.ElapsedGameTime.TotalMilliseconds returns 0 ... all the time. I have no idea why.
SOLVED: detected gameTime.ElapsedGameTime.TotalMilliseconds returned 0 ... moved it to a different location.
a source to share
Found gameTime.ElapsedGameTime.TotalMilliseconds was returning 0 ... used GameTime parameter in Update method to set a public double variable named GameT. Then GameT was used in the HandleInput method and returned valid times. Not the most legal way to do this, but it works for now.
a source to share
So the question is, what kind of behavior do you want your organization to have?
- If you want it to move once when you press the button (as if navigating through a menu), you want to store the KeyboardState in a class-level variable so that each update can be checked against the current state. You only move if the button was not saved in its previous state, but is now being held down. This ensures that you only ever activate the action once.
- If you want it to move regularly and smoothly (for example, scrolling to the right when you press the right arrow), then scale your displacement variable (currently hardcoded to 50) by a specific amount (which you can tweak). So something like
movement.X += 50 * .05;
. You can tweak it up and down until the movement it makes each frame matches the speed you want to move.
a source to share
If you are using a fixed game time, you don't need to linger at all. You can store a variable that keeps track of "frames" and updates based on this:
int elapsedFrames = 10; //<- Set up somewhere higher than the function call
if (keyboardState.IsKeyDown(Keys.Right))
{
elapsedFrames++;
if (elapsedFrames >= 10)
{
movement.X += 50;
elapsedTime = 0;
}
}
else
{
elapsedTime = 10;
}
This way you don't have to deal with gameTime.
a source to share