I see strange behavior in XNA when using MediaPlayer

In XNA, I use MediaPlayer to play my music. I found that when playing a release build (run as an executable, not from Visual Studio) the game window sometimes flickers and looks like it is trying to minimize and then return. Sometimes the game icon on the taskbar will show a little to the side and go back to where it is. I'm using Windows 7. This was easy to reproduce by starting the game, making the explorer window the active window, leaving it for a second or two, and then clicking on the game. The game window takes about 6-10 seconds, but then it happens about every 4-8 seconds after that.

I was looking for what exactly was causing this and this is the following code called through the main game update.

if (!IsActive && MediaPlayer.State != MediaState.Paused)
{
    MediaPlayer.Pause();
}
if (IsActive && MediaPlayer.State == MediaState.Paused)
{
    MediaPlayer.Resume();
}

      

Basically, I pause the music when the game is not active, and pause when the game is active again. It's a mess for some reason. I tried to just mute the music instead of pausing, but I get the same effect. I made a new PC game XNA 4.0, but even with the above code (and the basic .Update) in the main function, the update is still happening, so this is definitely the code causing the problem. Does anyone know what's going on here, or another way to pause the music when the game is inactive?

+3


source to share


2 answers


I was able to reproduce a similar issue (for me the Game window actually freezes and becomes unresponsive) in a new game project using the code you provided above.

I was also able to find posts from others who are experiencing similar issues (dating from two years ago like this one -> http://forums.create.msdn.com/forums/t/45296.aspx ). This appears to be a framework bug.

I'm not really sure what might happen. My guess is that there is some kind of funky with the MediaPlayer check that can steal the window focus and then return to the game, which returns focus so that within a few milliseconds, the game is lost and focused, so that the music pauses and pauses again at 60 once a second. On weaker machines such as mine, this causes the window to become invulnerable. It's all guessing, since I don't know for sure, but it makes sense.

I was able to work around the issue, but by simply disabling the MediaPlayer health check from the equation. If you have your own boolean flag that you add to the game (something like "isPlaying") and then query that boolean instead of checking the state of the MediaPlayer, the problem is fixed and you get the desired functionality.



The code will look something like this.

bool isMusicPlaying = false;
protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    Song song = Content.Load<Song>("SampleSong");
    MediaPlayer.Play(song);
    isMusicPlaying = true;
}

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    if (!IsActive && isMusicPlaying == true)
    {
        MediaPlayer.Pause();
        isMusicPlaying = false;
    }
    else if (IsActive && isMusicPlaying == false)
    {
        MediaPlayer.Resume();
        isMusicPlaying = true;
    }

    base.Update(gameTime);
}

      

With the above code, you should still get the original functionality you were looking for, while getting rid of the unwanted behavior that happens using the built-in state of the MediaPlayer.

+1


source


Why not pause music playback when you really want to pause music playback and resume playback at events that pause the game? Then you remove the need for the bool variable and check it every time. I did it on my logic of the PauseScreen class.



+1


source







All Articles