On Microsoft.Xna.Framework.GamerServices.Guide.IsVisible

Sam Hart

There's something I've heard a lot over the years. It's a common complaint that Win32 developers express when they first come to an Open Source development environment (such as Linux with its myriad of Free Software/Open Source development tools). This common complaint is that the development documentation is somehow lacking compared to the Win32 development documentation. Generally, they point to MSDN as the gold standard and bemoan Linux's lack of something similar. This complaint is even one of the motivating factors for the LSB project (which, I used to be a part of).



Whenever I have heard this complaint in the past, it has always made me laugh. I've laughed because the development documentation for Linux and its Free Software/Open Source ilk tends to be very good... you just have to know where to look for it. You have to be comfortable reading man pages, browsing info documents, snooping through /usr/doc, etcetera, etcetera. True, it's not all available in one web site, but more often than not it's more convenient to get at in the end (much of it can be accessed quickly from the command line).



Well, after an ordeal I've had today trying to solve a simple, and common, problem with my XNA-based video game using MSDN, I will laugh even harder when I encounter Win32-weenies with this complaint in the future...





XNA's Lovely Guide Class

1) Your game display will be dimmed and the guide will overlay on top.

Your game display will be dimmed and the guide will overlay on top.

2) Your game will lose all user input connections as those will be taken over by the guide.



MSDN's Not-So Helpful Advice





// Pause if the Guide is up, or if the user has paused

if ((paused == false) && (Guide.IsVisible == false))

{

base.Update(gameTime);



....

}









if(!Guide.IsVisible)

{

base.Update(gameTime);

....

}





Guide Is Part Of Gamer Services





if(!Guide.IsVisible)

{

base.Update(gameTime);

....

}





The Real Solution





// Somewhere up where we define properties or fields

public GamerServicesComponent GamerServices;



....



// Then down in our Update(..) method

if (Guide.IsVisible)

{

GamerServices.Update(gameTime);

}

else

{

base.Update(gameTime);

}





Notes



(1) : Okay, technically you can control it somewhat. You can cause various guide features (such as a keyboard entry dialog) to pop-up. However, once the guide has been enabled, you cannot control when it will be turned back off from within your code.

(1) : Okay, technically you control it somewhat. You can cause various guide features (such as a keyboard entry dialog) to pop-up. However, once the guide has been enabled, you cannot control when it will be turned back off from within your code.

(2) : "Tick" is just some discrete quanta of execution time. It's actually a pretty complicated concept that I'm hand-waving over.





Without going intomuch detail, XNA is a C#-based framework that allows you to quickly create video games (and related technologies) for the various Microsoft platforms including Windows, the Xbox 360, and the Zune. On some of these platforms you have an interface which is called the "Guide" that operates outside of your game and provides the user access to system-wide information. You cannotcontrol this guide inside of your application(1). If the user presses the guide button on their controller, for example, the guidepop-up and intercept all user inputs. This is a design feature which primarily makes sense on the Xbox 360 where the guide provides access to the Dashboard What this means to your code is:The end result is when the guide pops up, your code needs to stop what it's doing and wait until the guide goes away. If you are in a gameplay loop, your game needs to pause (so your player doesn't die, for example). If you are in the middle of a complicated animation or cut-scene, perhaps your animation or cut-scene should be paused until the game gets focus again.XNA provides a way to determine whether the guide is active or not in the Gamer Services class Guide . Specifically, the member Guide.IsVisible tells you whether or not the guide is visible (active). This means you can simply poll Guide.IsVisible every Update(..) to verify that the guide isn't active before performing your gameplay loop logic. Sounds simple enough, right?When the guide is active, the game probably should be paused somehow. So coupling Guide.IsVisible with other pause-code seems logical.In fact, this is exactly what is suggested in the MSDN article How To: Pause a Game . In this article, they suggest using the following segment of code inside your Update(..) to handle both user pause requests as well as guide events:If you run their sample code, itto work. You are able to pause/unpause the game manually, exit the game successfully, etcetera and so on. However, if you actually watch the Guide.IsVisible property you notice something is wrong.When the game starts up, Guide.IsVisible is false- as it should be. When you press the guide button on your controller and activate the guide, Guide.IsVisible becomes true- as it should be. However, closing the guide on screen, and thus returning control back to your game, does not reset Guide.IsVisible back to false. Instead, Guide.IsVisibletrue for the rest of the application's run.Furthermore, if you google around for using Guide.IsVisible to pause your XNA game when the guide activates, you will findvariants on this theme:However,of these variantsthe original MSDN article are. This isthe way to use Guide.IsVisible. Let me tell you why.As I mentioned above, the Guide class is a part of something called Gamer Services. More specifically, it is managed by the GamerServicesComponent . Persons intimately familiar with the way XNA works will likely already see the problem, but for those who don't, allow me to explain a bit of the XNA internals.A typical XNA application consists of multiple entities called "components". These components allow you to divide up the work that must be done every tick(2) by your application. You can think of these components as the building blocks for your application.Each component must have an Update(..) method which is called every tick. This Update(..) contains component-specific logic. If the component's Update(..) iscalled, then its per-tick logic will not run (obviously).Well, note that Gamer Services is a component. This means if it isrun, it wont update the various members it manages, which includes Guide.IsVisible.Now look back at the code:Once Guide.IsVisible is set to true because the guide has been activated, we never call base.Update(..) again. This means that Gamer Services' Update(..) is never called again! This means that, no matter what happens with the guide, Guide.IsVisibleThe end result is that you need to ensure that your Gamer Services get updated each tick even when the guide is active. I'm certain there's plenty of ways to do this, but the way I chose was to first define a local instance of GamerServicesComponent, and then to ensure that local instance's Update(..) is called.Long story short, MSDN is misleading and wrong, and their example code for using Guide.IsVisible will lead you astray.I will be submitting a bug report on this, and hopefully it will be fixed (so, if you're reading this at some point in the future when the example code has been corrected, you know who to thank).