Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Menu's 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 Litarded   Members   -  Reputation: 105

Like
0Likes
Like

Posted 20 June 2011 - 10:17 PM

I am a total noob in XNA. I mean, I know some stuff, but am a total noob.

I am having troubles with making a menu in XNA like Play, Credits, Exit.

I want it so you can click the Play, Credits, Exit and have the credits show, and then for play make it so that the menu "hides or disappears" and then the playing screen shows.

Thanks

Sponsor:

#2 ApochPiQ   Moderators   -  Reputation: 16412

Like
0Likes
Like

Posted 20 June 2011 - 10:49 PM

Moving to For Beginners.

#3 Haps   Members   -  Reputation: 1315

Like
0Likes
Like

Posted 20 June 2011 - 11:22 PM

There's a couple tutorials in the Education Catalog you might start with.

Game State Management Sample

Network Game State Management

#4 falcon93   Members   -  Reputation: 121

Like
1Likes
Like

Posted 21 June 2011 - 02:46 AM

This is actually pretty easy to do if you are familiar with object-orientated programming.

First of all, you want to be able to hide/show your menu (collection of buttons), and it would also be good to have a place to check button clicks. Therefore, it can be a good idea to do a MainMenu class. In your main menu class, you can do like this to get ability to show/hide your menu:

public void Update()
{
	if (visible)
	{
		button_play.Update();
		button_credits.Update();
		button_quit.Update();
	}
}

public void Draw()
{
	if (visible)
	{
		button_play.Draw();
		button_credits.Draw();
		button_quit.Draw();
	}
}


If you want to show you menu, simply set the the bool visible to true, and if you want to hide it, change it to false.
Ex:
main_menu.visible = true;

When you want to check button click, put this code in your main_menu class:
public void Update()
{
	Point x = new Point(Mouse.GetState().X, Mouse.GetState().Y);

	if (visible)
	{
		button_play.Update();    			
		button_credits.Update();
	button_quit.Update();

		if (Mouse.GetState().LeftButton == ButtonState.Pressed)
		{
			if (button_play.rectangle.Contains(x))
			{
				// What happens when the button was clicked?
			}

			if (button_credits.rectangle.Contains(x))
			{
				// What happens when the button was clicked?
			}

			if (button_quit.rectangle.Contains(x))
			{
		// What happens when the button was clicked?
			}
		}

	}
}


Hope that helps. Maybe I missunderstood what you searched help for, if so just shout Posted Image

#5 XainFaith   Members   -  Reputation: 102

Like
1Likes
Like

Posted 21 June 2011 - 01:53 PM

Falcon93 is quite correct on many points so i am just going to add something more. A menu is basically a collection of States or at least where sub options of the menu are incurred. What this means is that it really is just a branching section in the code that breaks the game down and runs along a path selected.

Simply put you could even do it with a switch statement if you really wanted to do but there are better ways. One of the best ways to do it is with a Game State management system each part of your game could be referred to as a state eg ( Menu, Options, Game Play, HighScore )

Each on of these states are separate from each other in one form of way or another and can have there own code to deal with just there state. Writing a Game State Manager is not really to hard but depending on the features you want it to have it can become more difficult. But it basically breaks down like this.

Game State Manager

Screen " Represents a game state"

The Game State Manager runs one screen at a time calling methods from the Screen class such as Update and Draw.
You inherit the screen class to make the Game State for example you can have a MenuScreen and in that all the code to the menu could go.

There are a lot of examples on how to do this across the web if you really want to make a game and worries less about the underlying stuff i suggest taking a look at the XNA Game Engine
called Flat Red Ball http://FlatRedBall.com you can find me there from time to time and it comes with the above mentioned Game State Management.

Regards XainFaith

#6 Litarded   Members   -  Reputation: 105

Like
0Likes
Like

Posted 22 June 2011 - 09:53 AM

Thanks. Helped out a lot.

#7 SkoobyD00   Members   -  Reputation: 108

Like
1Likes
Like

Posted 22 June 2011 - 11:04 AM

I want to jump in and comment based on my experience. The snippet of code regarding checking if the mouse is currently pressed and then processing the clicks will likely cause a problem (may not, I'm not sure if XNA is super magical, as I've never worked with it). The issue comes from the fact that the user may click (press and then release) the mouse entirely between times which this condition is checked, which could result in a click being completely ignored. The way I've solved this in the past is by having a 'mouse' class which responds to any sort of mouse event, and keeps track of buttons that are currently pressed, and buttons that have been pressed AT ANY POINT since the last time the class was instructed to reset itself, resulting in two separate 'checking' functions, "isPressed(int Button)" and "hasBeenPressed(int Button)". I'm not aware if xna deals with input in this event oriented method, but I don't see why it wouldn't. In the time since I worked out this solution, I've seen it in at least a couple of places, so I'm sure it's fairly standard.

EDIT: yeah, it's probably worth downvoting some advice just because it doesn't necessarily apply to you. Thanks, whoever.

#8 XainFaith   Members   -  Reputation: 102

Like
0Likes
Like

Posted 22 June 2011 - 11:25 AM

Here is a bit to get your started off since XNA does not use a polling input system things can become tricky very fast and checking for a left mouse down is not that same as a click.

Here is my mouse class for XNA 4.0 the MouseEventData is just a struct with some basic data you can pass down ill add it too so you can see it.




    public delegate void MouseEvent(MouseEventData mouseData);



    internal class MouseInput

    {

        #region Fields



        public int X { get; private set; }

        public int Y { get; private set; }



        #endregion



        #region Events



        private MouseState LastState;



        public event MouseEvent MouseLeftDown;

        public event MouseEvent MouseLeftUp;



        public event MouseEvent MouseRightDown;

        public event MouseEvent MouseRightUp;



        public event MouseEvent MouseMove;



        #endregion



        #region Constructor



        public MouseInput()

        {

            this.LastState = Mouse.GetState();

        }



        #endregion



        #region Update Method



        public void Update()

        {

            MouseState mState = Mouse.GetState();

            this.X = mState.X;

            this.Y = mState.Y;



            MouseEventData mouseData = new MouseEventData();



            #region Mouse Move Event



            if (this.LastState.X != mState.X || this.LastState.Y != mState.Y)

            {

                mouseData.X = mState.X - LastState.X;

                mouseData.Y = mState.Y - LastState.Y;

                mouseData.Button = MouseButton.None;

                if (this.MouseMove != null)

                {

                    this.MouseMove(mouseData);

                }

            }



            #endregion



            mouseData.X = this.X;

            mouseData.Y = this.Y;



            #region Check for Left button Mouse input



            if (mState.LeftButton == ButtonState.Pressed)

            {

                if (this.LastState.LeftButton == ButtonState.Released)

                {

                    if (this.MouseLeftDown != null)

                    {

                        mouseData.Button = MouseButton.Left;

                        this.MouseLeftDown(mouseData);

                    }

                }



            }

            else

            {

                if (this.LastState.LeftButton == ButtonState.Pressed)

                {

                    if (this.MouseLeftUp != null)

                    {

                        mouseData.Button = MouseButton.Left;

                        this.MouseLeftUp(mouseData);

                    }

                }

            }



            #endregion



            #region Check for Right button Mouse input



            if (mState.RightButton == ButtonState.Pressed)

            {

                if (this.LastState.RightButton == ButtonState.Released)

                {

                    if (this.MouseRightDown != null)

                    {

                        mouseData.Button = MouseButton.Right;

                        this.MouseRightDown(mouseData);

                    }

                }



            }

            else

            {

                if (this.LastState.RightButton == ButtonState.Pressed)

                {

                    if (this.MouseRightUp != null)

                    {

                        mouseData.Button = MouseButton.Right;

                        this.MouseRightUp(mouseData);

                    }

                }

            }



            #endregion



            this.LastState = mState;

        }



        #endregion

    }



and now for the MouseEventData






    public struct MouseEventData

    {

        public MouseButton Button;



        public int X;

        public int Y;

    }





in your case just check for a mouse left up event and then see what button your in, since the mouse left up only fires after the left mouse has been pressed and release you will get much more accurate input.
hope this helps to at least show you how to poll xna input.

#9 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 22 June 2011 - 01:33 PM

I want to jump in and comment based on my experience. The snippet of code regarding checking if the mouse is currently pressed and then processing the clicks will likely cause a problem (may not, I'm not sure if XNA is super magical, as I've never worked with it). The issue comes from the fact that the user may click (press and then release) the mouse entirely between times which this condition is checked, which could result in a click being completely ignored. The way I've solved this in the past is by having a 'mouse' class which responds to any sort of mouse event, and keeps track of buttons that are currently pressed, and buttons that have been pressed AT ANY POINT since the last time the class was instructed to reset itself, resulting in two separate 'checking' functions, "isPressed(int Button)" and "hasBeenPressed(int Button)". I'm not aware if xna deals with input in this event oriented method, but I don't see why it wouldn't. In the time since I worked out this solution, I've seen it in at least a couple of places, so I'm sure it's fairly standard.


I'm using the above code in my 2D game, and it works, without problems.



if (Mouse.GetState().LeftButton == ButtonState.Pressed)
This will check if the left mouse button is pressed. It doesn't check if the button has been clicked, it just checks if the button is pressed.



Point x = new Point(Mouse.GetState().X, Mouse.GetState().Y);
This saves the x and y location of the mouse. So everytime the gameloop loops through this part it will initialize the mouse point, x. It has to be outside the if-statement, as it requires to be updated always. This is most easy solved by creating a class for the mouse that will update it.



if (button_play.rectangle.Contains(x))
All rectangles contains a method called contains. This method checks if a point is inside the rectangle. So what we check here is if the current location of the mouse is inside the rectangle, in other words; we check if the mouse is on the button.


Lets say that both if statements was true, that means that the mouse button was pressed when the mouse was on a button, which will give us the result we want. This is a very simple and effective way check button clicks, and it's surly possible to check it in many more ways, but why make it more complicated than required? There's only two small "downsides" with this strategy, but it still works without any bugs or problems at all.

The downsides are:

1. It's possible to click the left mouse button, then move the mouse over the button, and it will still registrate it as I pressed the button. If you want to follow the default windows button system, then you can simple solve this matter with a bool.

2. It's not 100% correct to initilize the x point everytime the game loop loops throug your mouse code. What you should instead do, is to have your own mouse class, where you update (not initialize) the position. The class Mouse is already used by in the xna library, so I usually use Cursor as class name. Updating the mouse position, without initializing it everytime the game loop loops through your cursor class, is done like this:

position.x = Mouse.GetState().X;
position.y = Mouse.GetState().Y;


#10 SkoobyD00   Members   -  Reputation: 108

Like
0Likes
Like

Posted 13 July 2011 - 07:02 PM

Sure it works under ideal circumstances, but if there is a bit of lag, and someone clicks even a little bit fast, it is not unreasonable to suggest that the user might click and have nothing happen. My suggestion makes that eventuality completely impossible. But I guess these days no one cares about proper coding, just get it working asap because F*** GOOD CODE.

Seriously though, I'm not saying the above code doesn't work, I'm saying it is not entirely robust to the level of certainty that you will probably want to guarantee in a game. If I click, I expect my gun to shoot, regardless of how quickly i released the mouse. If you only test for the current state of the mouse you might miss clicks that entirely occurred between the last game loop and the current.

#11 sturmschlag   Members   -  Reputation: 100

Like
0Likes
Like

Posted 14 July 2011 - 01:02 PM

[/lurk]

He's doing programming for a menu. While your input is appreciated, and very much correct, it probably doesn't apply to his current situation.

[lurk]

#12 falcon93   Members   -  Reputation: 121

Like
0Likes
Like

Posted 14 July 2011 - 04:17 PM

Sure it works under ideal circumstances, but if there is a bit of lag, and someone clicks even a little bit fast, it is not unreasonable to suggest that the user might click and have nothing happen. My suggestion makes that eventuality completely impossible. But I guess these days no one cares about proper coding, just get it working asap because F*** GOOD CODE.

Seriously though, I'm not saying the above code doesn't work, I'm saying it is not entirely robust to the level of certainty that you will probably want to guarantee in a game. If I click, I expect my gun to shoot, regardless of how quickly i released the mouse. If you only test for the current state of the mouse you might miss clicks that entirely occurred between the last game loop and the current.


First of all, you should remember that an XNA game runs on 50 fps on default, no matter how fast your computer is. That means that you have to hold down the mouse button for 0.02 seconds or shorter to be able to "miss" a click.

The proffesional way of checking a button press is by capturing events. However, for a simple menu with 3 buttons, there's really no reason so start coding custom events. Or maybe you propose that he should spend most of the development time on mouse events, instead of actually learning other more important things? Events is also an important thing to know when you start to move more into the advanced tracks, but I bet there's more valuable things to learn first.

Also, think about your "proper" coding... Did you learn the easiest basics first, and then moved on to the "proper" way when you understood the concepts, or did you start learning the "proper" way stright ahead? I mean, he's not supposed to copy-paste code from here. He's suposed to understand the concept of the code and then use our help for creating his own solution. That's the way of learning, not by pressing a ctrl combination twice. It's like you should start biking before you could walk...

#13 SkoobyD00   Members   -  Reputation: 108

Like
0Likes
Like

Posted 14 July 2011 - 05:54 PM

First of all, you should remember that an XNA game runs on 50 fps on default, no matter how fast your computer is. That means that you have to hold down the mouse button for 0.02 seconds or shorter to be able to "miss" a click.


I've never worked with XNA. Excuse me. It has already been noted that it is just for a menu, but it is likely that his game will be using the same input handling that the menu uses, so making it robust before it causes problems is not a problem. In a perfect world everything runs smoothly at 50 or more frames per second, but, as I am sure you are keenly aware, this is not always the case. Ensuring that all input gets handled eventually is, what I would say, a very important thing to learn in programming, otherwise a naive programmer will just assume it will work properly, which isn't necessarily the case.

The proffesional way of checking a button press is by capturing events. However, for a simple menu with 3 buttons, there's really no reason so start coding custom events. Or maybe you propose that he should spend most of the development time on mouse events, instead of actually learning other more important things? Events is also an important thing to know when you start to move more into the advanced tracks, but I bet there's more valuable things to learn first.


You might not have noticed, but my post contained no mention of events, event handlers, or any such thing, though it does rely upon the existence of some way of detecting the exact moment that the mouse has been pressed in a separate thread. This is the result of my working with java, where you have no choice but to deal with it in that manner. If there is some confusion about what I meant, here is a brief clarification.

The following method of dealing with mouse input is as follows(in java, because that is what I work with):
public class MyMouse implements MouseListener {
boolean buttons[] = new boolean[8];
public MyMouse() {
  for(int i=0; i<8; i++)
    buttons[i] = false;
}
public void mousePressed(MouseEvent e) {
  buttons[e.getButton()] = true;
}
public void mouseReleased(MouseEvent e) {
  buttons[e.getButton()] = false;
}
public boolean isMousePressed(int buttonCode) {
  return buttons[buttonCode];
}
} // end class

This is how I originally started dealing with mouse input. As I went on, I noticed that in rare combinations of circumstances, you could click without the game knowing it. Everyone here is going to be like " "I use java" <--- there's your problem right there" but the fact is that any programming language on any platform is capable of lagging. I know because I have been using a computer since I was two and /everything/ can lag.

I also do not think that it is a problem to deal with these events, especially for simple input like this. I'm not saying he go and add mouse gestures or anything.

If this method of mouse input handling is absolutely nothing like anything possible in XNA, then I will submit that my method is not only unnecessary, but likely impossible. However, since I'm pretty sure that it applies, I will continue.

The modification I was recommending at the start was to take the previously mentioned mouse class and add a second set of booleans for checking not the current state of the mouse, but the state of the mouse since the last time you checked it. you would add a new boolean array, I call it "hasBeenPressed". Modify the mousePressed function to also set the appropriate slot in hasBeenPressed to true, and add a function to check the value of hasbeenpressed which also sets the checked index to false. Modifications follow:

public class MyMouse implements MouseListener {
boolean buttons[] = new boolean[8];
boolean hasBeenPressed[] = new boolean[8];
public MyMouse() {
  for(int i=0; i<8; i++)
    buttons[i] = false;
  for(int i=0; i<8; i++)
    hasBeenPressed[i] = false;
}
public void mousePressed(MouseEvent e) {
  buttons[e.getButton()] = true;
  buttons[e.getButton()] = true;
}
public void mouseReleased(MouseEvent e) {
  buttons[e.getButton()] = false;
}
public boolean isMousePressed(int buttonCode) {
  return buttons[buttonCode];
}
public boolean hasMouseBeenPressed(int buttonCode) {
  boolean out = hasBeenPressed[e.getButton()];
  hasBeenPressed[e.getButton()] = false;
  return out;
} // end class

Optionally, you can also include a separate function that will reset all of the hasBeenPressed values to false. I have found it useful in the past. The point I am trying to make here is that this solution is not complex, and ensures that, as long as the thread(s) that is handling events isn't being starved, input is seen. (Though with this method it is still possible to construct a scenario where input is not handled, but with even a little bit of planning this can be reduced to completely negligible).

Also, think about your "proper" coding... Did you learn the easiest basics first, and then moved on to the "proper" way when you understood the concepts, or did you start learning the "proper" way stright ahead? I mean, he's not supposed to copy-paste code from here. He's suposed to understand the concept of the code and then use our help for creating his own solution. That's the way of learning, not by pressing a ctrl combination twice. It's like you should start biking before you could walk...


The method described above is precisely how I do and always have handled mouse position and input. When I first started programming games in java, I created a Mouse class which is not unlike the one above (but it handles mouse position and a few other things).

I don't understand the hostility here. Even if this is too complex for a beginner to understand (Which I still maintain it isn't), should he or any other newbie lurking here ever encounter a situation where input is not consistently being processed, maybe they will remember a flash of this discussion and be set off in the right direction to fix the problem. When introducing someone to code with potential issues, it is important to point out, even if only briefly, potential problems with the code to ensure that if they end up going in a direction where the code breaks with an increasing frequency, they understand why or at least have an idea of how to go about fixing it.

#14 falcon93   Members   -  Reputation: 121

Like
1Likes
Like

Posted 15 July 2011 - 03:57 AM

Sure, I havn't said there's anything wrong with the code you use. I just think it's unnecessary advanced for creating a menu with three buttons. Also, he was not just wondering how to capture mouse clicks, he was also asking about the buttons themselves. For the buttons click action, the two most common solutions is either mine, or the more advanced one which includes events.

So no offence, lets leave both our solutions standing here, and let him choose the one that fits him best Posted Image




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