Jump to content

  • Log In with Google      Sign In   
  • Create Account


Help with menu selection in XNA


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 12:42 PM

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


Sponsor:

#2 Dave Hunt   Crossbones+   -  Reputation: 2419

Like
1Likes
Like

Posted 03 April 2013 - 01:45 PM

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.



#3 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 04:44 PM

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


#4 ch1mera   Members   -  Reputation: 176

Like
1Likes
Like

Posted 03 April 2013 - 04:57 PM

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)) 
{
//...
}
 


#5 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 05:04 PM

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


#6 ch1mera   Members   -  Reputation: 176

Like
2Likes
Like

Posted 03 April 2013 - 06:08 PM

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!


Edited by ch1mera, 03 April 2013 - 06:17 PM.


#7 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 06:13 PM

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


#8 ch1mera   Members   -  Reputation: 176

Like
1Likes
Like

Posted 03 April 2013 - 06:18 PM

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.



#9 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 06:24 PM

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


#10 ch1mera   Members   -  Reputation: 176

Like
1Likes
Like

Posted 03 April 2013 - 06:30 PM

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. 



#11 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 06:44 PM

We can PM if you like.

 

I sent you a PM. I changed the code to this:

        //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 == true)
            {
                playButton.active = false;
                creditsButton.active = true;
            }

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

            previousKeyboardState = currentKeyboardState;

 

It still scrolls through the credits right down to the exit. I am pretty sure it is how and where I am calling the current and previous keyboard states


Cpl Alt, Travis A

USMC


#12 moneal2001   Members   -  Reputation: 606

Like
2Likes
Like

Posted 03 April 2013 - 08:17 PM

you are asking if the down key is down both times back to back, before assigning currentKeyboardState to previousKeyboardState.  so yes it will jump all the way down to the exit button because you are asking about the same keyboardstate both times.  so both will be activated during the same Update.  you should set up the menu items in an array or list have an indexer that moves up or down one with each press.  also move your keyboardstate declerations out of the method.   like this.

int menuIndex = 0;  // place this in your menu fields
menuItem[] menuItems; //place this in your menu fields
KeyboardState currentKeyboardState; //place this in your menu fields
KeybardState previousKeyboardState; //place this in your menu fields

private void MainMenuSelection()
        {            
            currentKeyboardState = Keyboard.GetState();
            
            menuItems[index].IsActive = true;

            // If player presses down arrow go down in menu
            if (currentKeyboardState.IsKeyDown(Keys.Down) && previousKeyboardState.IsKeyUp(Keys.Down))
            {
                   //deactivate current menuItem
                   menuItems[menuIndex].IsActive = false;
 
                   //go down in the menu
                   menuIndex++;
                   
                   // keep index within the your menu items
                   if(menuIndex <= menuItems.Count)
                        index = 0;

                   //activate new menuItem
                   menuItems[index].IsActive = true;

            }

            // If player presses Up Go Up in menu
            if (currentKeyboardState.IsKeyDown(Keys.Up) && previousKeyboardState.IsKeyUp(Keys.Up))
            {
               //deactivate current menuItem
               menuItems[menuIndex].IsActive = false;

              //go up in the menu
              menuIndex--;

              // goes to last menuItem if already at top of menu
              if(menuIndex > 0)
                 index = menuItems.Count -1;

              //activate new menuItem
              menuItems[index].IsActive = true;
            }

            previousKeyboardState = currentKeyboardState;

Edited by moneal2001, 03 April 2013 - 08:20 PM.


#13 Manhattanisgr8   Members   -  Reputation: 486

Like
0Likes
Like

Posted 03 April 2013 - 09:15 PM

you should set up the menu items in an array

 

Would this work even though I have the two different textures for each button in a List?

 

My Button Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace TronPongClone
{
    class Buttons
    {
        // Button texture at Idle
        public List<Texture2D> texture;

        // Button height
        public int height;

        // Button width
        public int width;

        // Button position
        public Vector2 poition;

        // Button state
        public bool active;

        public Buttons()
        {
            texture = new List<Texture2D>();
            height = 100;
            width = 300;
            poition = Vector2.Zero;
            this.active = true;
        }

        public void Update(SpriteBatch spriteBatch)
        {
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            if (active == true)
            {
                spriteBatch.Draw(texture.ElementAt(1), poition, Color.White);
            }
            if (active == false)
            {
                spriteBatch.Draw(texture.ElementAt(0), poition, Color.White);
            }
        }
    }
}


Cpl Alt, Travis A

USMC


#14 moneal2001   Members   -  Reputation: 606

Like
1Likes
Like

Posted 03 April 2013 - 09:37 PM

Yea that should work.  i would create a list since you can add and remove from lists at will(adding or removing any number of buttons you need as you go).  and put something together kinda like my example and it should work just fine.  the button class you have looks set up pretty well.  

 

there are some great examples of how to do a menu system out there for xna.  a good one is at xnagpa, in his rpg tutorial(the one i think i modeled the example after if i remember right).  he also has a lot of menu control items.  and as someone mentioned earlier in the thread at the app hub resources the Game State Management Tutorial has a good menu and input handling system in it.


Edited by moneal2001, 03 April 2013 - 09:39 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS