1
\$\begingroup\$

Sorry for the non-descriptive title.

So I've been trying to implement fullscreen mode into my xna-game, and I've hit a couple of roadblocks.

My basic code setup for this functionality is the following:

This code is ran while the game starts (in the LoadContent() method to be precise) and works just fine:

// Membervariables that are declared elsewhere
screen = new Point(1200, 800);
isFullScreen = false;

graphics.PreferredBackBufferWidth = screen.X;
graphics.PreferredBackBufferHeight = screen.Y;
graphics.ApplyChanges();

So far so good. Now this is my ToggleFullScreen() method in the same class (also just to be clear, this is the class that inherits from Microsoft.Xna.Framework.Game):

protected void ToggleFullScreen()
{
    // toggle our boolean
    isFullScreen = !isFullScreen;

    if (isFullScreen)
    {
        float nw, nh;
        nw = (float)GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width / (float)screen.X;
        nh = (float)GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height / (float)screen.Y;

        if (nw > nh)
        {
            graphics.PreferredBackBufferWidth = (int)((float)(screen.X) * nh);
            graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
        }
        else
        {
            graphics.PreferredBackBufferHeight = (int)((float)(screen.Y) * nw);
            graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
        }
    }
    else
    {
        graphics.PreferredBackBufferWidth = screen.X;
        graphics.PreferredBackBufferHeight = screen.Y;
    }

    graphics.IsFullScreen = isFullScreen;
    graphics.ApplyChanges();
}

Right, so in the ToggleFullScreen() method I calculate the new size of the window by taking our windowed-mode size (saved in the point 'screen'), and then multiplying it with the smalles factor that will make our window touch the edges of the screen (the drawable area that is, not the window borders). Then I toggle GraphicsDevice.IsFullScreen (using GraphicsDevice.ToggleFullScreen() doesn't seem to make any difference).

Now this is where the trouble happens. First of all, somehow the resolution goes awry. As you can see, the resolution I picked for screen is a 3:2 resolution. My monitor is 1920x1080. So logically, our new resolution would be 1620x1080 (since in my code, nw > nh, so we use the height of the screen and 1200 * (1080/800) for the width). Quickly using Console.WriteLine shows that these are indeed the values of PreferredBackBufferWidth/Height.

Except when I'm in fullscreen mode, I can clearly see that the ratio gets warped. Somehow the game gets stretched a bit horizontally, which is kinda strange considering I haven't implemented any method of dealing with fullscreen yet, graphicswise. I.e. I haven't yet implemented a method that scales all my graphics to fit the new resolution.

So when I run my game in fullscreen mode, everything is drawn in the topleft corner of the screen (with some stuff overflowing outside of the regular 1200x800 area, into our newly acquired space), but still, everything gets stretched a bit horizontally. This becomes especially apparent when I render this test image on the screen. It's square, it has a diagonal line, but when I draw it, it becomes sliiightly rectangular and the line gets a bit blurred over parts of its length, indicating that it is being stretched.

Thing is, I'd take a screenshot and measure it out precisely, except printscreen doesn't work anymore. When I'm in fullscreen mode, and press the prt scr button, the result is a 1680x1050 (!= 1620x1080) texture completely colored in a light shade of grey ((240,240,240) to be precise. I searched through all of my code and I have no clue where it comes from).

This confuses me greatly - first of all, where does this resolution come from? Considering the final product gets stretched horizontally a bit, I think it's fair to assume that somehow XNA stretches my 1200x800 game to a 1680:1050-ratio instead of maintaining the desired 3:2-ratio, as well as setting the size of the screen to 1680x1050 instead of 1620x1080, which, again, is rather strange considering I haven't implemented any method to make my graphics match with the screen size, yet.

This makes me think the problem is somehow with the GraphicsDevice.IsFullScreen stuff. Yet when I browse around a bit on MSDN or other places around the web, I can not find any information about how this function affects the ratio of the backbuffer.

So I guess my question is, am I overlooking something? Am I misunderstanding how XNA's fullscreen/GraphicsDevice/BackBuffer functionality works? Am I overthinking this, is there another easy way to handle fullscreen mode while preserving ratio?

Sorry for the wall of text, and thanks in advance!

\$\endgroup\$
  • \$\begingroup\$ If graphics are 2D, do not set PreferredBackBufferWidth/Height when changing to/from full screen. Decide the fixed screen size most convenient to your game graphic assets or target platform, render them to a RenderTarget2D then use SpriteBatch.begin() passing a properly configured scaling matrix (not hard to calculate) to get a "fill preserving aspect ratio" effect, with letter box when the screen aspect ratio is not the same as your game chosen one. You need to implement something like this: david-amador.com/2010/03/… \$\endgroup\$ – Hatoru Hansou Dec 24 '13 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.