5
\$\begingroup\$

While working on a Monogame project on Linux (Arch to be exact), I found that I could not change the screen height away from the default 800 px, while I could easily, perfectly change the width to whatever I want. Has anyone ever had this issue, and is there a fix for it? I am going to try the solution that @Jon explained in this post, but I doubt it will work since this seems to be a Linux-only problem. I have installed the latest version of OpenTK and built the latest build of Monogame as of a few days ago, and have looked through the source for the Monogame OpenTKGameWindow and GraphicsDevice classes, as well as the GraphicsDeviceManager. I don't see the issue in any of those, but I might be missing something.

\$\endgroup\$
  • \$\begingroup\$ I don't know if you've seen this - github.com/mono/MonoGame/issues/628 \$\endgroup\$ – SpartanDonut Dec 19 '14 at 22:03
  • \$\begingroup\$ I kept reading and now see you've made posts on it. :) \$\endgroup\$ – SpartanDonut Dec 19 '14 at 22:05
  • \$\begingroup\$ Yeah, I saw. I also posted my own issue, but no one there could figure out why it was happening. I have a suspicion that the problem is in OpenTK somewhere. \$\endgroup\$ – Pip Dec 19 '14 at 22:55
4
\$\begingroup\$

It seems that my bug report on Github has been responded to. If this is being read before the next official version is released, this fix will most likely contained in the development branch of the repository on Github. All that you have to do is pull down the repo and dependencies from Github and then build Monogame using Protobuild (this requires Mono to be installed to compile the framework). After that, you can link the generated library files to your Monogame project and then it should work fine.

Links to Github:

Issue: https://github.com/mono/MonoGame/issues/3254

Pull Request w/ fix: https://github.com/mono/MonoGame/pull/3315

\$\endgroup\$
2
\$\begingroup\$

I thinks this is the same bug I found when experimenting with MonoGame to decide if I will use C#/MonoGame rather than C++/Various Libraries.

I suggest the following work around: try to change the resolution more than once. The property AllowUserResizing must be set to true before doing the change of resolution. And you must call ApplyChanges(). All of this came from the bug report.

I made a ResolutionChanger class that automates all that. The class has an update() method that should be called each frame. This update method will check the current resolution to see if it is the same as the last requested resolution, if it is not the same, the change is assumed as failed and the class will continue trying to change the resolution until it see that the current resolution is the same as the requested resolution.

Note that I had some success with this approach but I observed that some times the game starts with the default resolution, switch to full screen and back to windowed fixs it but I don't remember now if that worked 100% of the time.

I don't know if this will work for you, but you can try.

How to use (in your main game class extending Game):

In the constructor create a ResolutionChanger instance:

public MyGame ()
{
    graphics = new GraphicsDeviceManager (this);
    Content.RootDirectory = "Content";              
    this.IsFixedTimeStep = true;
    screen = new VirtualScreen(graphics, Window, 1366, 768);
    resolution = new ResolutionChanger(graphics, Window);
    //(...) More code
}

In the Initialize() method:

protected override void Initialize ()
{
    resolution.DesiredWidth = 1280;
    resolution.DesiredHeight = 720;

    base.Initialize ();
}

In the Update() method:

protected override void Update (GameTime gameTime)
{
    //(...) your code

    // Switch fullscreen with Enter key. Change it if you do not like it
    if (Keyboard.GetState().IsKeyDown(Keys.LeftAlt) && Keyboard.GetState().IsKeyDown(Keys.Enter))
    {
        resolution.FullScreen = !resolution.FullScreen;
    }

    // This will change the back buffer bounds and game window bounds if required
    resolution.Update(false);

    //(...) your code

    base.Update (gameTime);
}

Here is the code for the ResolutionChanger class:

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MonoGameTest
{
    public class ResolutionChanger
    {
        private int mDesiredWidth;
        private int mDesiredHeight;
        private bool mFullScreen;
        private Rectangle mLastWindowedBounds;
        private GraphicsDeviceManager mGraphics;
        private GameWindow mWindow;

        public ResolutionChanger (GraphicsDeviceManager graphics, GameWindow window)
        {
            mLastWindowedBounds = window.ClientBounds;
            mDesiredHeight = 640;
            mDesiredWidth = 480;
            mGraphics = graphics;
            mWindow = window;
        }

        public void Update (bool force)
        {
            if (mGraphics.GraphicsDevice.PresentationParameters.BackBufferWidth != mDesiredWidth ||
                mGraphics.GraphicsDevice.PresentationParameters.BackBufferHeight != mDesiredHeight ||
                force)
            {
                bool setUserResizing = mWindow.AllowUserResizing;

                if (!mGraphics.IsFullScreen && !setUserResizing)
                {
                    mWindow.AllowUserResizing = true;
                }

                mLastWindowedBounds = mWindow.ClientBounds;
                mGraphics.PreferredBackBufferWidth = mDesiredWidth;
                mGraphics.PreferredBackBufferHeight = mDesiredHeight;
                mGraphics.ApplyChanges();

                if (!mGraphics.IsFullScreen && !setUserResizing)
                {
                    mWindow.AllowUserResizing = false;
                }

                Console.WriteLine("ResolutionChanger: a change in resolution took place");
            }

            if (mFullScreen != mGraphics.IsFullScreen)
            {
                mGraphics.IsFullScreen = mFullScreen;

                if (!mGraphics.IsFullScreen)
                {
                    mDesiredWidth = mLastWindowedBounds.Width;
                    mDesiredHeight = mLastWindowedBounds.Height;
                    Update(false);

                    //var form = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle(mWindow.Handle);
                    //form.Location = new System.Drawing.Point(mLastWindowedBounds.X, mLastWindowedBounds.Y);
                }

                Console.WriteLine("ResolutionChanger: Full Screen state changed");
            }
        }

        public int DesiredWidth
        {
            get {
                return mDesiredWidth;
            }

            set {
                mDesiredWidth = value;
            }
        }

        public int DesiredHeight
        {
            get {
                return mDesiredHeight;
            }

            set {
                mDesiredHeight = value;
            }
        }

        public bool FullScreen
        {
            get {
                return mFullScreen;
            }

            set {
                mFullScreen = value;
                if (mFullScreen)
                {
                    mDesiredWidth = mGraphics.GraphicsDevice.DisplayMode.Width;
                    mDesiredHeight = mGraphics.GraphicsDevice.DisplayMode.Height;
                }
            }
        }

    }
}
\$\endgroup\$
  • \$\begingroup\$ I'l try to implement this, then get back to you. I'm pretty sure that I tried something similar to this though. \$\endgroup\$ – Pip Dec 25 '14 at 16:27

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.