Help with menu selection in XNA

Started by
12 comments, last by moneal2001 11 years ago

I am making a main menu game state and have come across a problem. I have two textures for each button in order to indicate which button is currently selected. The problem I have is when the player presses the down key from the first button, it doesn't stop at the middle button, but goes all the way down to the third button. How can I have it pause at the middle button, before going down to the bottom button?


        //Menu selections
        private void MainMenuSelection()
        {
            // If player presses down arrow, highlight credits
            if (Keyboard.GetState(p1.pNumber).IsKeyDown(Keys.Down))
            {
                playButton.active = false;
                creditsButton.active = true;
            }
            // If player presses down again, highlight credits
            if (Keyboard.GetState(p1.pNumber).IsKeyDown(Keys.Down))
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

Cpl Alt, Travis A

USMC

Advertisement

The problem is that that code executes 60 times a second, so there is a very good chance that it will execute multiple times before the user lets go of a key. You need to track the input state from both the current frame and the previous frame. That way you can detect and act on a key press the first frame in which it is pressed and ignore it until its state changes again.

Have a look at the Game State Management sample in the XNA Education Catalog. There is an InputState class that handles that aspect for you.

edited the code to have a previous and current keyboard state, still haveing the same problems


        //Menu selections
        private void MainMenuSelection()
        {

            KeyboardState currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            // If player presses down arrow, select credits
            if (currentKeyboardState.IsKeyDown(Keys.Down) && !previousKeyboardState.IsKeyDown(Keys.Down))
            {
                playButton.active = false;
                creditsButton.active = true;
            }

            // If player presses down again, highlight exit
            if (currentKeyboardState.IsKeyDown(Keys.Down) && ! previousKeyboardState.IsKeyDown(Keys.Down))
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

            previousKeyboardState = currentKeyboardState;
        }

Cpl Alt, Travis A

USMC

So whats going on here is you're saying if the current keyboard down key is pressed and the previous keyboard down key is not pressed. Well at the moment, your second statement will always return true until the key is initially pressed, I believe that what you want to do is use the "IsKeyUp" method on the currentKeyboardState.

Like So:


if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down)) 
{
//...
}
 

I believe that what you want to do is use the "IsKeyUp" method on the currentKeyboardState.

Just tried it with the same result

Cpl Alt, Travis A

USMC

Do you mind sharing the updated code? I don't know why this solution wouldn't work off the top of my head.

EDIT:

Actually now that i take a step away from the PC, i realized what the problem is. You're performing both conditions at the same time. So your second condition would be something along these lines:


if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down) && creditsButton.active = true)
 

since you don't want the exit button to be the "next in line" to be highlighted until the button above that is already selected.

Hope that works!

Do you mind sharing the updated code? I don't know why this solution wouldn't work off the top of my head.


        //Menu selections
        private void MainMenuSelection()
        {

            KeyboardState currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            // If player presses down arrow, select credits
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down))
            {
                playButton.active = false;
                creditsButton.active = true;
            }

            // If player presses down again, highlight exit
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down))
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

            previousKeyboardState = currentKeyboardState;

I am putting this method at the bottom of Game1 and calling it in the Update() of Game1.

Cpl Alt, Travis A

USMC

Do you mind sharing the updated code? I don't know why this solution wouldn't work off the top of my head.


        //Menu selections
        private void MainMenuSelection()
        {

            KeyboardState currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            // If player presses down arrow, select credits
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down))
            {
                playButton.active = false;
                creditsButton.active = true;
            }

            // If player presses down again, highlight exit
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down))
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

            previousKeyboardState = currentKeyboardState;

I am putting this method at the bottom of Game1 and calling it in the Update() of Game1.

I believe the edit to my previous post should solve the problem.

I believe the edit to my previous post should solve the problem.

Changed the code to what you suggested with no luck. Now it doesn't highlight anything but the play button which is set to active by default.


        //Menu selections
        private void MainMenuSelection()
        {

            KeyboardState currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            // If player presses down arrow, select credits
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down) && creditsButton.active == true)
            {
                playButton.active = false;
                creditsButton.active = true;
            }

            // If player presses down again, highlight exit
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down) && exitButton.active == true)
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

            previousKeyboardState = currentKeyboardState;

Would it be easier for you if I PMed you the entire Game1.cs code?

Cpl Alt, Travis A

USMC

I believe the edit to my previous post should solve the problem.

Changed the code to what you suggested with no luck. Now it doesn't highlight anything but the play button which is set to active by default.


        //Menu selections
        private void MainMenuSelection()
        {

            KeyboardState currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            // If player presses down arrow, select credits
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down) && creditsButton.active == true)
            {
                playButton.active = false;
                creditsButton.active = true;
            }

            // If player presses down again, highlight exit
            if (currentKeyboardState.IsKeyUp(Keys.Down) && previousKeyboardState.IsKeyDown(Keys.Down) && exitButton.active == true)
            {
                creditsButton.active = false;
                exitButton.active = true;
            }

            previousKeyboardState = currentKeyboardState;

Would it be easier for you if I PMed you the entire Game1.cs code?

We can PM if you like.

I think this solution should work, the problem is that its done in the wrong order, if that makes sense. In the first condition you're stating that it will only run if creditsButton.active == true, but the value of creditsButton.active isn't set to true until you're inside the statement. What you want the first condition to have is playButton.active == true instead, as it seems that this value is default set to true just as the play button (as you said) is default set to to active.

and likewise in the second condition, instead of exitButton.active == true, you want creditsButton.active == true.

This topic is closed to new replies.

Advertisement