Як зробити роздільну здатність 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. Як я можу впоратися з гнучким дизайном, коли всі екрани телефонів Windows 8 різні? Чи є формула або макрос для кожного розрахунку хорошого розміру?


Ви можете перевірити, який відсоток екрана телефону Windows використовує ваші кнопки, а потім використати цей відсоток для обчислення правильного розміру екрана для кожної іншої роздільної здатності. Але я впевнений, що є більш елегантні способи, ніж цей.
Крістіан

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

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] х [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). Цим можна розміщувати предмети в кутах з або без кордонів тощо.

Будь ласка, переконайтеся, що розмір одиничних елементів (кнопки, мітки, ...) також масштабується.


-2

Спеціально для MonoGame У мене є незалежне від платформи рішення цієї проблеми під назвою IRR (Незалежний резолюторний рендер). Це дуже просте використання:

  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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.