Как сделать независимым разрешение 2D-игры?

10

Я работаю над простой 2D игрой. Я закончил версию для мобильного телефона.

Однако мой босс хочет, чтобы игра работала на его RT. Я делаю «преобразование», но мои кнопки находятся в неправильных местах, потому что я жестко запрограммировал размер экрана, например так:

 texture = game.Content.Load<Texture2D>("StartScreen");
 mainFrame = new Rectangle(0, 0, game.GraphicsDevice.Viewport.Width, game.GraphicsDevice.Viewport.Height);

 // button definitions
 startbrect = new Rectangle(300, 258, 88, 88);
 startbtext = game.Content.Load<Texture2D>("bplay");

В этом примере mainframeэто хорошо, но startbrectэто не так, потому что я определил размер в соответствии с экраном Windows Phone. Как справиться с адаптивным дизайном, когда экраны всех телефонов под управлением Windows 8 отличаются? Есть ли формула или макрос для расчета каждый раз хорошего размера?

Gabson
источник
Вы можете проверить, какой процент используемых в Windows Phone размеров экрана используются кнопками, а затем использовать этот процент для расчета правильного размера экрана для любого другого разрешения. Но я уверен, что есть более элегантные способы, чем этот.
Кристиан
Я ищу более элегантный способ, но сейчас попробую с процентами.
Габсон
2
Вы должны быть в состоянии сделать это, манипулируя камерой.
ashes999
Мое решение состояло в том, чтобы иметь дело с процентом, не находил лучше.
Габсон

Ответы:

17

Я использую эталонный размер экрана и масштабирую все в соответствии с ним, сохраняя соотношение всех одинаковых.

private static float CalcRatio(Vector2 Sizes)
{
    return Sizes.y/Sizes.x;
}

public static Vector2 CalculateNewPos(Vector2 RefPos, Vector2 RefScreenSize, 
                                      Vector2 CurrentScreenSize)
{       
    return new Vector2((RefPos.x/RefScreenSize.x) * CurrentScreenSize.x, 
                       (RefPos.y/RefScreenSize.y) * CurrentScreenSize.y);
}

public static Vector2 CalculateNewSize(Vector2 RefSize, Vector2 RefScreenSize,
                                       Vector2 CurrentScreenSize)
{       
    float origRatio = CalcRatio(RefSize);
    float perW = RefSize.x * 100f / RefScreenSize.x;    
    float newW = perW / 100f * CurrentScreenSize.x;
    float newH = newW * origRatio;
    return new Vector2(newW, newH);
}

Чтобы игра выглядела хорошо на разрешениях с соотношениями, существенно отличающимися от ваших эталонных разрешений, определите «игровую зону», которая вписывается в любой вид экрана, и поместите все критически важные для игрового процесса визуальные эффекты. Заполните все вне этого фоном. Обычно моя эталонная воспроизводимая область равна размеру самого эталонного экрана.

В портретной ориентации я вычисляю (новую) воспроизводимую область таким образом, чтобы экран заполнялся вертикально, а занимаемое им пространство по горизонтали было таким же большим, как требуется для сохранения соотношения. В альбомной ориентации я заполняю экран горизонтально и сохраняю соотношение при установке размера по вертикали.

Для получения дополнительной информации см. Http://en.wikipedia.org/wiki/Safe_area_(television), поскольку это похожая, если не идентичная концепция.


источник
0

Я думаю, что самый простой и естественный подход к разрешению независимых макетов - это относительная (процентная) схема. Таким образом, с самого начала не работайте с реальным разрешением, а только по возможности в едином квадрате [0,1] x [0,1].

Это означает, что для данной screen_sizeи данной object_sizeи данной относительной позиции (px, py)(например (0,5, 0,5) для центра экрана) верхний левый угол объекта рассчитывается по формуле:

x = px * screen_size.width - 0.5 * object_size.width
y = py * screen_size.height - 0.5 * object_size.height

Идея должна быть ясной. Готовая абстракция будет

x = cx1 * screen_size.width + cx2 * object_size.width + cx3
y = cy1 * screen_size.height + cy2 * object_size.height + cy3

и каждая позиция определяется тогда (cxi, cyi). Таким образом можно размещать объекты в углах с границами или без них и т. Д.

Пожалуйста, убедитесь, что размеры отдельных элементов (кнопки, метки, ...) тоже масштабируются.

Trilarion
источник
-2

Специально для MonoGame у меня есть независимое от платформы решение этой проблемы, которое называется IRR (Independent Resolution Renderer). У него очень простое использование:

  1. Создать IRR в методе Initialize ()

    _irr = новый ResolutionRenderer (это, VirtualResolutionWidth, VirtualResolutionHeight, _gfx.PreferredBackBufferWidth, _gfx.PreferredBackBufferHeight);

  2. Вызывать _irr.Draw () каждый цикл в вызове Draw ()
  3. Поставка _irr.GetTransformationMatrix () в любом SpriteBatch.Begin () вызов, который необходимо использовать IRR.

Описание здесь: http://panthernet.ru/forum/index.php?/topic/17-monogamexna-examples-v14/?p=44

Код здесь: https://github.com/panthernet/Monogame-Examples

Александр Смирнов
источник