tatman blue

I have several Microsoft.Xna.Framework.DrawableGameComponent derived objects that I use, one for each game state (the components are called MenuView, GameView).

In MenuViews update method I check for back button pressed and exit the program.

In GameView, I want the back button to take me back to the MenuView. So in the GameView update code, I check for it and if thats true set my state back GameStateMenuView. But the program exits anyways.

This because the MainView also sees the back button as pressed.

Is there a way to clear the button states or how do I handle this

Thnx
Matt


Re: XNA Framework Problem with Buttons.Back

Jim Perry

You only change states when the button is released. You can set a flag in the GameView when the button is pressed and when the button is released, then go back to the MenuView.




Re: XNA Framework Problem with Buttons.Back

tatman blue

that sorta makes sense but not totally.

On button pressed I should hide one view and show the other. And on release change the state. Is that what you are saying.




Re: XNA Framework Problem with Buttons.Back

Glenn Wilson

Have a look at the keyboard example in the Documentation, you could set the Controller to have an old and a new state. Then each update get the new state check to make sure that the button was released and also the old state says that it was pressed. then at the end of the input update functions transfer the new state to the old state.






Re: XNA Framework Problem with Buttons.Back

slugonamission

Basically, it's something like this you want.

First, if the button is pressed, then set a var to true, then, on each call of the update method, if it was pressed, check it still is.

This is probably the wrong syntax, but it's something I have just quickly thrown together

protected bool WasPressed = false;

protected override void Update()
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
WasPressed = true;
}
else if(WasPressed)
{
WasPressed = false;
//It's been pressed and released, so go back now
}
}




Re: XNA Framework Problem with Buttons.Back

Jon Watte

Those are all hack solutions that work around the problem only in this special case.

In general, I would recommend treating input as a stream, with a defined sequence of input consumers. The input consumers that consume the input should clear out the input being consumed, so that underlying "listening" nodes don't actually get to see the data.

Thus, inside the game update function (before calling base, which calls the components), read the gamepad, and put the state into a queue or holder of some sort. Each component that wants to listen to input then gets to look at this in turn, and if they use the input data, they remove it from the queue, leaving nothing there for the later components.

The "queue" could be as simple as a GamePadState global that gets set to NULL when a component uses it, or could be something more elaborate. You might not even want to read input inside Update(), but instead manage the queue explicitly, and push data into each queue listener in order. The input code would then look like:

interface InputListener {
bool Listen(GamePadState state);
}
List<InputListener> gInputUsers = new List<InputListener>;

// in Game.Update()
GamePadState gps = GamePad.GetState(PlayerIndex.One);
int n = gInputUsers.Length;
for (int i = n-1; i >= 0; --i) {
if (gInputUsersIdea.Listen(gps)) {
break;
}
}

// in component:
Activate() {
if (!active_) gInputUsers.Add(this);
}

bool Listen(GamePadState gps) {
if (gps.Buttons.Back) {
gInputUsers.Remove(this);
// do whatever
return true;
}
return false;
}

You can also do much of the same thing using an Event, but the Event does not provide well-defined removal/adding semantics inside the Listen callback like the above code, and also needs a "used" flag in the event args, as you can't break out of event delivery in the middle.