3

I write a simple game with using MonoGame library. As far as I know MonoGame (unlike XNA) doesn't automatically support changing orientation of the phone and it is necessary to use RenderTarget2D and then draw it with a proper orientation. For this purpose I need to detect current orientation of the phone.

In order to get OrientationChanged event, I have to allow GamePage.xaml to use different orientations:

SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"

The problem is that in this case my GamePage starts changing orientations automatically and in landscape position sprites are stretched horizontally. It seems that in the landscape position phone thinks that it has the same number of pixels along horizontal side as in the portrait orientation (480 pixels).

enter image description here enter image description here

This effect happens without any manual rotation. The code of drawing is:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(t, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 1);
    spriteBatch.End();

    base.Draw(gameTime);
}

One of the solutions is to forbid different orientations in GamePage.xaml:

SupportedOrientations="Portrait" Orientation="Portrait"

but in this case I can't get the OrientationChanged event nowhere (GamePage.OrientationChanged or Game.Window.OrientationChanged). I put following code in the constructor of Game class, but it didn't help

graphics.SupportedOrientations = DisplayOrientation.Portrait |
                                 DisplayOrientation.PortraitDown |
                                 DisplayOrientation.LandscapeLeft |
                                 DisplayOrientation.LandscapeRight;

graphics.ApplyChanges();
this.Window.OrientationChanged += OrientationChanged;

Please advise me how to get OrientationChanged event and at the same time don't allow GamePage to change its coordinate axes in landscape mode.

Kara
  • 6,115
  • 16
  • 50
  • 57
Eugene
  • 143
  • 10

1 Answers1

2

Thank you for a number of replies :)

The solution that I was invented is to fix page orientation:

SupportedOrientations="Portrait" Orientation="Portrait"

And to use accelerometer in order to get actual position of the phone:

public class Game1 : Game
{
    Accelerometer accelSensor;
    PageOrientation currentOrientation = PageOrientation.None;
    PageOrientation desiredOrientation = PageOrientation.None;
    ...

    public Game1()
    {
        accelSensor = new Accelerometer();
        accelSensor.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs> AccelerometerReadingChanged);
        ...

    private void AccelerometerReadingChanged(object sender, AccelerometerReadingEventArgs e)
    {
        double angle = Math.Atan2(-e.X, e.Y) * 180.0 / Math.PI;
        double delta = 15;

        if (angle > -45 + delta && angle < 45 - delta) desiredOrientation = PageOrientation.PortraitDown;
        if (angle > 45 + delta && angle < 135 - delta) desiredOrientation = PageOrientation.LandscapeLeft;
        if (angle > -135 + delta && angle < -45 - delta) desiredOrientation = PageOrientation.LandscapeRight;
        if ((angle >= -180 && angle < -135 - delta) || (angle > 135 + delta && angle <= 180)) desiredOrientation = PageOrientation.PortraitUp;
    }

    protected override void Update(GameTime gameTime)
    {
        if (desiredOrientation != currentOrientation) SetOrientation(desiredOrientation);
        ...

If you know a better way please tell me...

Eugene
  • 143
  • 10