MonoGame — Tips & Tricks для Windows phone 8

Статья освещает не очевидные решения многих проблем возникающих при работе с MonoGame на Windows phone 8.

 

При использование SoundEffect на WP8 возникает ошибка TypeInitializationException

В инсталлятор забыли положить файл SharpDX.WP8.winmd, поэтому придется компилировать библиотеку самим. Рекомендую собирать из https://github.com/crnjan/MonoGame в ней уже исправлено множество багов, которые есть в основной ветке.

 

Падение приложения в WP8 при переключения на другое и обратно(Resume)

Исправлено в https://github.com/crnjan/MonoGame

 

Определение разрешения экрана устройства на WP8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public enum Resolutions { WVGA, WXGA, HD720p };
 
    public static class ResolutionHelper
    {
        private static bool IsWvga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 100;
            }
        }
 
        private static bool IsWxga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 160;
            }
        }
 
        private static bool Is720p
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 150;
            }
        }
 
        public static Resolutions CurrentResolution
        {
            get
            {
                if (IsWvga) return Resolutions.WVGA;
                else if (IsWxga) return Resolutions.WXGA;
                else if (Is720p) return Resolutions.HD720p;
                else throw new InvalidOperationException("Unknown resolution");
            }
        }
    }
public enum Resolutions { WVGA, WXGA, HD720p };

    public static class ResolutionHelper
    {
        private static bool IsWvga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 100;
            }
        }

        private static bool IsWxga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 160;
            }
        }

        private static bool Is720p
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 150;
            }
        }

        public static Resolutions CurrentResolution
        {
            get
            {
                if (IsWvga) return Resolutions.WVGA;
                else if (IsWxga) return Resolutions.WXGA;
                else if (Is720p) return Resolutions.HD720p;
                else throw new InvalidOperationException("Unknown resolution");
            }
        }
    }

 

TouchPanel возвращает все Gesture(жесты) c X и Y равными Infinity

На данный момент при первом прохождение Update нужно использовать хак:

1
2
3
4
// Temp hack to fix gestures
                typeof(Microsoft.Xna.Framework.Input.Touch.TouchPanel)
                    .GetField("_touchScale", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                    .SetValue(null, Vector2.One);
// Temp hack to fix gestures
                typeof(Microsoft.Xna.Framework.Input.Touch.TouchPanel)
                    .GetField("_touchScale", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                    .SetValue(null, Vector2.One);

 

Поддержка Landscape и переворотов экрана на WP8

Какие-либо перевороты изначально не поддерживаются, поэтому рисуем на текстуре и поворачиваем ее как нам надо.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private RenderTarget2D _wp8RenderTarget;
public static float RenderRoatation;
public Vector2 RenderOffset;
 
//нужно подписаться у странице на OrientationChanged, и не у нее установить поддержку нужных орентаций
public void ChangeOrientation(OrientationChangedEventArgs e)
{
    //реализация только для Landscape
    if (e.Orientation == PageOrientation.LandscapeLeft)
    {
        RenderOffset = new Vector2(_wp8RenderTarget.Bounds.Height, 0);
        RenderRoatation = MathHelper.PiOver2;
    }
 
    if (e.Orientation == PageOrientation.LandscapeRight)
    {
        RenderOffset = new Vector2(0, _wp8RenderTarget.Bounds.Width);
        RenderRoatation = -MathHelper.PiOver2;
    }
}
 
protected override void Initialize()
{
///...
 
_wp8RenderTarget = new RenderTarget2D(GraphicsDevice, Camera.ViewPortWidth, Camera.ViewPortHeight);
 
RenderOffset = new Vector2(_wp8RenderTarget.Bounds.Height, 0);
RenderRoatation = MathHelper.PiOver2;
 
///...
}
 
protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.SetRenderTarget(_wp8RenderTarget);
 
    base.Draw(gameTime);
    GraphicsDevice.SetRenderTarget(null);
 
    var spriteBatch = new SpriteBatch(GraphicsDevice);
 
    spriteBatch.Begin();
    spriteBatch.Draw(_wp8RenderTarget, RenderOffset, null, Color.White, RenderRoatation, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f);
    spriteBatch.End();
}
private RenderTarget2D _wp8RenderTarget;
public static float RenderRoatation;
public Vector2 RenderOffset;

//нужно подписаться у странице на OrientationChanged, и не у нее установить поддержку нужных орентаций
public void ChangeOrientation(OrientationChangedEventArgs e)
{
	//реализация только для Landscape
    if (e.Orientation == PageOrientation.LandscapeLeft)
    {
        RenderOffset = new Vector2(_wp8RenderTarget.Bounds.Height, 0);
        RenderRoatation = MathHelper.PiOver2;
    }

    if (e.Orientation == PageOrientation.LandscapeRight)
    {
        RenderOffset = new Vector2(0, _wp8RenderTarget.Bounds.Width);
        RenderRoatation = -MathHelper.PiOver2;
    }
}

protected override void Initialize()
{
///...

_wp8RenderTarget = new RenderTarget2D(GraphicsDevice, Camera.ViewPortWidth, Camera.ViewPortHeight);

RenderOffset = new Vector2(_wp8RenderTarget.Bounds.Height, 0);
RenderRoatation = MathHelper.PiOver2;

///...
}

protected override void Draw(GameTime gameTime)
{
	GraphicsDevice.SetRenderTarget(_wp8RenderTarget);

	base.Draw(gameTime);
	GraphicsDevice.SetRenderTarget(null);

	var spriteBatch = new SpriteBatch(GraphicsDevice);

	spriteBatch.Begin();
	spriteBatch.Draw(_wp8RenderTarget, RenderOffset, null, Color.White, RenderRoatation, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f);
	spriteBatch.End();
}

 

Переворот жестов и касаний на WP8

Они также находиться всегда в портретном режиме. Поэтому при их считывание нужно выполнять переворот координат, также как и текстуру для экрана.