Jak uniezależnić rozdzielczość gry 2D?

10

Pracuję nad prostą grą 2D. Skończyłem wersję telefonu komórkowego.

Jednak mój szef chce, aby gra działała na jego RT. Robię „konwersję”, ale moje przyciski znajdują się w niewłaściwych miejscach, ponieważ na stałe zakodowałem rozmiar ekranu:

 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");

W tym przykładzie mainframejest w porządku, ale startbrectnie jest, ponieważ zdefiniowałem rozmiar, aby pasował do ekranu telefonu z systemem Windows. Jak poradzić sobie z responsywnym projektowaniem, gdy ekrany wszystkich telefonów z systemem Windows 8 są inne? Czy istnieje formuła lub makro do obliczenia za każdym razem, gdy rozmiar jest dobry?

Gabson
źródło
Możesz sprawdzić, jaki procent rozmiaru ekranu używanego w Windows Phone jest używany przez twoje przyciski, a następnie użyć tego procentu do obliczenia prawidłowego rozmiaru ekranu dla każdej innej rozdzielczości. Ale jestem pewien, że są bardziej eleganckie sposoby niż to.
Christian
Szukam bardziej eleganckiego sposobu, ale na razie spróbuję z procentem.
Gabson,
2
Powinieneś być w stanie to zrobić, manipulując kamerą.
ashes999
Moje rozwiązanie polegało na tym, aby odsetek nie znalazł się lepiej.
Gabson

Odpowiedzi:

17

Używam referencyjnego rozmiaru ekranu i skaluję wszystko zgodnie z nim, zachowując proporcje wszystkiego bez zmian.

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);
}

Aby upewnić się, że gra dobrze prezentuje się w rozdzielczościach znacznie różniących się od rozdzielczości odniesienia, zdefiniuj „obszar grywalny”, który pasuje do każdego rodzaju ekranu, i umieść tam wszystkie krytyczne elementy wizualne rozgrywki. Wypełnij wszystko poza nim tłem. Zazwyczaj mój referencyjny obszar gry jest tak duży, jak sam rozmiar ekranu referencyjnego.

W orientacji pionowej obliczam (nowy) obszar grywalny, aby ekran był wypełniony w pionie, a przestrzeń, którą zajmuje w poziomie, jest tak duża, jak to konieczne, aby utrzymać ten współczynnik. W orientacjach poziomych wypełniam ekran poziomo i zachowuję proporcje przy ustawianiu rozmiaru pionowego.

Więcej informacji można znaleźć na stronie http://en.wikipedia.org/wiki/Safe_area_(television), ponieważ jest to podobna, jeśli nie identyczna koncepcja.


źródło
0

Myślę, że najłatwiejszym i najbardziej naturalnym podejściem do układów niezależnych od rozdzielczości jest schemat względny (procentowy). Tak więc od samego początku nie pracuj z rzeczywistą rozdzielczością, ale tylko w miarę możliwości w jednolitym kwadracie [0,1] x [0,1].

Oznacza to, że dla danej screen_sizei danej object_sizei danej pozycji względnej (px, py)(na przykład (0,5, 0,5) dla środka ekranu), lewy górny róg obiektu jest obliczany przez:

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

Pomysł powinien być jasny. Gotowa byłaby abstrakcja

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

i każda pozycja jest następnie definiowana przez (cxi, cyi). W ten sposób można umieszczać obiekty w rogach z lub bez granic itp.

Upewnij się, że rozmiar pojedynczych elementów (przyciski, etykiety, ...) są również skalowane.

Trilarion
źródło
-2

Specjalnie dla MonoGame mam niezależne od platformy rozwiązanie tego problemu o nazwie IRR (Independent Resolution Renderer). Ma bardzo proste użycie:

  1. Utwórz IRR w metodzie Initialize ()

    _irr = new ResolutionRenderer (this, VirtualResolutionWidth, VirtualResolutionHeight, _gfx.PreferredBackBufferWidth, _gfx.PreferredBackBufferHeight);

  2. Wywołaj _irr.Draw () każdy cykl w wywołaniu Draw ()
  3. Zasilanie _irr.GetTransformationMatrix () w każdym SpriteBatch.Begin () zadzwonić chcesz użyć IRR.

Opis jest tutaj: http://panthernet.ru/forum/index.php?/topic/17-monogamexna-examples-v14/?p=44

Kod jest tutaj: https://github.com/panthernet/Monogame-Examples

Aleksander Smirnow
źródło