TouchPanel in MonoGame reset after orientation change on Win 8.1 - c#

I'm creating a Universal (Win 8.1 + Win Phone 8.1) app using C# / Monogame (VS 2013). I'm using MonoGame v3.4.
In my game1.cs initialization code, I set:
TouchPanel.DisplayWidth = _drawState.ScreenBounds.Width;
TouchPanel.DisplayHeight = _drawState.ScreenBounds.Height;
So that touch input is consistent to my game screen size (_drawState.ScreenBounds is a Rectangle containing the dimensions of my virtual screen size).
My game is set to support only portraint orientations: I have picked only the portrait and portrait-flipped orientations in the Package.appxmanifest files for both target (Win and WinPhone), and I have set this in the game1.cs Init method:
graphics.SupportedOrientations = DisplayOrientation.Portrait |
DisplayOrientation.PortraitDown
Testing the game on the Win 8.1 Simulator and on a real Win 8.1 tablet, I found out that after an orientation change (btw, the Simulator rotates and crops the game field, whereas the real device, as expected, keeps the portrait aspect), the TouchPanel has wrong dimensions - it resets to the actual screen dimensions, and so all my touches are off.
This only happens on the Win8.1 target - the Win Phone targets works as intended.
Any ideas?
EDIT:
Since I couldn't find what was going on, I just decided to subscribe to the size changed event and set the TouchPanel.DisplayWidth and TouchPanel.DisplayHeight variables:
this.Window.AllowUserResizing = true;
this.Window.ClientSizeChanged += Window_ClientSizeChanged;
The Window_ClientSizeChanged method is called on the Simulator, but not on the real device.
I tried with:
_window = Windows.UI.Core.CoreWindow.GetForCurrentThread();
_window.SizeChanged += _window_SizeChanged;
Same thing - called on the simulator, not on the device.

Not being able to find a solution to this problem, I just decided to handle the touch input differently; instead of setting the TouchPanel.DisplayWidth & Height, I decided to convert the touch (and mouse) position to the virtual screen coordinates using a simple function:
ScreenYScale = GraphicsDevice.PresentationParameters.BackBufferHeight / 1920.0f;
public Vector2 TranslateCoords(Vector2 coords)
{
return new Vector2(coords.X / ScreenYScale, coords.Y / ScreenYScale);
}

Related

Problem with Fullscreen Resolution in Mono Game

a couple days ago I started game developing in MonoGame with Visual Studio 2017 and porting my code which i wrote in WinForms to MonoGame. Now I have a problem with the fullscreen mode. I searched the internet and the only thing I found out is that it depends on the resolution the monitor has.
In the default window mode of the application the screen looks like follows:
Now when I switch to fullscreen mode - this happens:
Now my problems are:
One can not see it on the picture because I used the print button and pasted in to paint but the image is largely strechted.
The right part of the screen is cut off
the sprites are moved to the top.
I'm using
graphics.ToggleFullScreen();
Is there a way to keep the original status like it is in window mode? Maybe to put flexible bars for a 4:3 mode and keep the sprite positions? My positions are fixed. So use something like
spriteBatch.Draw(Params.CUR_SPRITE_P1, new Rectangle(Convert.ToInt32(POSITION_P1.X), Convert.ToInt32(POSITION_P1.Y), 750, 476), Color.White); for the player position and the screen (to implement scrolling).
Or maybe adjust everything in full screen mode bu keep the positions of the sprites on different screen resolutions...
Thank you a lot!
Ok after searching and searching I finally found an answer:
var scaleX = (float)ActualWidth / VirtualWidth;
var scaleY = (float)ActualHeight / VirtualHeight;
var matrix = Matrix.CreateScale(scaleX, scaleY, 1.0f);
spriteBatch.Begin(transformMatrix: matrix);
This has to be put in the Draw()-Method.
My virtual screensize was 800x480. I tested it with my Monitor size 1920x1080 and this did the job.

C# Setting cursor position - different results with WinForms and WPF

I have a strange problem. I am trying to set the cursor position with WPF. So far so good. The problem is the following:
On my computer screen (1920x1080, 100% windows scaling) everything works fine, but on my surface laptop (3000x2000, 200% windows scaling) I have run into some problems. Because of the scaling factor the "new resolution" is 1500x1000 (because of the 200% every pixel is "twice as big").
When I set the cursor to 750, 500 with WinForms the cursor appears in the exact middle of the screen but when I set the cursor position to the same point with WPF the cursor appears in the upper left section.
So apparently WinForms uses the resolution 1500x1000 and WPF uses the resolution 3000x2000 when setting the cursor position...
Why are they using different resolutions here? This doesn't make sense to me. Because when I am reading the ScreenWidth and Height with
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width // and Height, WinForms
and
System.Windows.SystemParameters.PrimaryScreenWidth // and Heigth, WPF
both are showing 1500x1000.
Can anyone help me? Maybe it is just a WPF/WinForms difference?
Code to set cursor:
Cursor.Position = p; // with imported System.Windows.Forms;
// or (tryed both)
[DllImport("User32.dll")]
private static extern bool SetCursorPos(int X, int Y);
SetCursorPos(p.X, p.Y);
First post so please don't kill me!
I am not an expert in this topic, but maybe:
WPF uses vector graphics to render things, and has a native support for scaling. If you change font size in Windows to 200%, every WPF application will be 2x bigger.
But in WinForms, if you didn't write your application correctly, scaling can ruin your UI.
To avoid this, if you run WinForms app (in Windows 10) it will just use 100% font size and it will stretch rendered image to 200% size. So you can see for example blurry text. If image is stretched - screen coordinates must be stretched too.
But that's just my guess, I'm not an expert at this.

Position to center screen in triple monitor setup with extended view

I have three monitors/screens of different sizes/resolutions setup as an extended view, all wired to the same NVIDIA graphic card. And from left to right:
Screen#0: 2400*1080
Screen#1: 1920x1080
Screen#2: 1920*1080
My application has three separate Windows, where I respectively position each Window to the corresponding monitor/screen with the following code
window00.Left = System.Windows.Forms.Screen.AllScreens[0].WorkingArea.Left;
window01.Left = System.Windows.Forms.Screen.AllScreens[1].WorkingArea.Left;
window02.Left = System.Windows.Forms.Screen.AllScreens[2].WorkingArea.Left;
window00.WindowState = System.Windows.WindowState.Maximized;
window01.WindowState = System.Windows.WindowState.Maximized;
window02.WindowState = System.Windows.WindowState.Maximized;
I only get the 3rd windows (window02) position to the right most screen properly (Screen#02), but both the 1st and 2nd windows (window00 & window01) stack and maximized to the first screen (Screen#00), leaving the middle Screen#01 empty displaying the background desktop environment, regardless if I set WindowsState.Maximized or Normal.
Even if I workaround the problem through offsetting window01 position by the width of Screen#00 to get all three windows position properly to their corresponding screens, if I maximize Windows.State, window01 still jumps back to Screen#00.
Why is this happening and why does the window not position or maximized to its WorkingArea it assigned to? Could it be due to WPF application using Forms properties?

XNA game starts drawing off screen on laptop

I currently have my XNA PC game running in a borderless windowed mode which has worked well until recently on my new laptop. It seems to start drawing a few hundred pixels off the screen to the top left. This leaves a gap at the bottom of the screen and on the right where you can see the desktop below the game. All the mouse coords are accurate to where you should have to mouse over and click on things even though it's just not drawing in the right place.
My older laptop it drew correctly but this new one I just got it seems to be off somehow. I am using David Amador's Resolution class to set up a virtual resolution via:
graphics = new GraphicsDeviceManager(this);
Resolution.Init(ref graphics);
control = Control.FromHandle(this.Window.Handle);
Resolution.SetVirtualResolution(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height);
Resolution.SetResolution(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width, GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height, false);
I set fullscreen to false and then once I create the game screen I do the following to set it to borderless:
Form gameForm = (Form)Form.FromHandle(curGame.Window.Handle);
gameForm.FormBorderStyle = FormBorderStyle.None;
I tried doing "gameForm.Location = new System.Drawing.Point(0, 0);" to try and force set it to start drawing at (0,0) but with my current set up that doesn't seem to do anything because I can set it to (150, 150) and it won't start drawing there. Here is a screenshot from my laptop that shows how it's moved the window and cut off the left and top side exposing the desktop:
Does anyone have any idea why it could be happening now on my new laptop when it hasn't happened on my desktop or old laptop ever before?

Windows 8 app XNA on two monitors with different resolutions

I'm using Monogame to write an XNA game for Windows 8 app store. I'm also using a laptop hooked up to an external monitor. Naturally the resolution on my external monitor is much higher than my laptop's screen. When I drag the app from one screen to another the resolution on the view port changes.
In my constructor I'm using
_graphics = new GraphicsDeviceManager(this);
_graphics.PreferredBackBufferHeight = 768;
_graphics.PreferredBackBufferWidth = 1366;
To set my viewport resolution. This makes the app to work fine when the application runs on either monitors, however dragging the app from one monitor to another changes the resolution on the GraphicsDeviceManager. Is there anyway to prevent this change?
So I figured it out
First I wrote a method that checks to see if the port resolution on the graphic device has changed
private bool hasResolutionChanegd()
{
if ((GraphicsDevice.Viewport.Width != ScreenManager.Instance.ScreenWidth) || (GraphicsDevice.Viewport.Height != ScreenManager.Instance.ScreenHeight))
{
return true;
}
else
{
return false;
}
}
I call this method on every update
if (hasResolutionChanegd())
{
Debug.WriteLine("Resolution Change new width= " + GraphicsDevice.Viewport.Width +" new height="+ GraphicsDevice.Viewport.Height);
_graphics.PreferredBackBufferHeight = 768;
_graphics.PreferredBackBufferWidth = 1366;
_graphics.ApplyChanges();
}
This way every time the resolution changes on the Graphic Device Manager (when the user drags the app from one screen environment to another), the preferred resolution is enforced.
I get the same thing as the original poster, but with XNA, not MonoGame. When I drag the window between the two monitors, the resolution changes, but the ClientSizeChanged event is not (of course) triggered. The suggestion above to use the SizeChanged event is helpful but only for Windows8 the documentation says.
I appear to have fixed it by handling the Window.ScreenDeviceNameChanged event - I hooked it up to the same handler as the ClientSizeChanged.
I would have put this in as a comment to the original post, but I don't have enough "reputation" points for the system to let me.

Categories

Resources