Wie mache ich eine 2D-Spielauflösung unabhängig?

10

Ich arbeite an einem einfachen 2D-Spiel. Ich habe die Handyversion fertiggestellt.

Mein Chef möchte jedoch, dass das Spiel auf seiner RT funktioniert. Ich mache die "Konvertierung", aber meine Schaltflächen befinden sich an den falschen Stellen, da ich die Bildschirmgröße wie folgt fest codiert habe:

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

In diesem Beispiel mainframeist das in Ordnung, aber startbrectnicht, da ich die Größe so definiert habe, dass sie mit dem Bildschirm eines Windows-Telefons übereinstimmt. Wie kann ich mit Responsive Design umgehen, wenn alle Bildschirme von Windows 8-Telefonen unterschiedlich sind? Gibt es eine Formel oder ein Makro, um jedes Mal die gute Größe zu berechnen?

Gabson
quelle
Sie können überprüfen, wie viel Prozent der Windows Phone-Bildschirmgröße für Ihre Schaltflächen verwendet werden, und diesen Prozentsatz dann verwenden, um die richtige Bildschirmgröße für jede andere Auflösung zu berechnen. Aber ich bin mir sicher, dass es elegantere Möglichkeiten gibt.
Christian
Ich bin auf der Suche nach einem eleganteren Weg, aber ich werde es im Moment mit Prozentsatz versuchen.
Gabson
2
Sie sollten dazu in der Lage sein, indem Sie die Kamera manipulieren.
Asche999
Meine Lösung war, mit dem Prozentsatz umzugehen, der nicht besser war.
Gabson

Antworten:

17

Ich verwende eine Referenzbildschirmgröße und skaliere alles danach, während das Verhältnis von allem gleich bleibt.

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

Um sicherzustellen, dass das Spiel bei Auflösungen mit Verhältnissen gut aussieht, die sich erheblich von Ihren Referenzauflösungen unterscheiden, definieren Sie einen "spielbaren Bereich", der in jede Art von Bildschirm passt, und platzieren Sie alle spielkritischen Grafiken dort. Füllen Sie alles außerhalb mit Hintergrund. Normalerweise ist mein spielbarer Referenzbereich so groß wie die Größe des Referenzbildschirms.

Bei Hochformatausrichtungen berechne ich den (neuen) spielbaren Bereich so, dass der Bildschirm vertikal ausgefüllt wird und der horizontal benötigte Platz genauso groß ist, wie es erforderlich ist, um das Verhältnis beizubehalten. Bei Querformatausfüllungen fülle ich den Bildschirm horizontal und behalte das Verhältnis bei der Einstellung der vertikalen Größe bei.

Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Safe_area_(television), da es sich um ein ähnliches, wenn nicht identisches Konzept handelt.


quelle
0

Ich denke, der einfachste und natürlichste Ansatz für auflösungsunabhängige Layouts ist ein relatives (prozentuales) Schema. Arbeiten Sie also von Anfang an nicht mit der realen Auflösung, sondern nur in einem einheitlichen [0,1] x [0,1] Quadrat, wo immer dies möglich ist.

Das bedeutet, dass für eine gegebene screen_sizeund eine gegebene object_sizeund eine gegebene relative Position (px, py)(zum Beispiel (0,5, 0,5) für die Mitte des Bildschirms) die obere linke Ecke des Objekts berechnet wird durch:

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

Die Idee sollte klar sein. Eine fertige Abstraktion wäre

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

und jede Position wird dann durch definiert (cxi, cyi). Auf diese Weise könnte man Objekte in Ecken mit oder ohne Rahmen usw. platzieren.

Bitte stellen Sie sicher, dass auch die Größe der einzelnen Elemente (Schaltflächen, Beschriftungen, ...) skaliert ist.

Trilarion
quelle
-2

Spezial für MonoGame Ich habe eine plattformunabhängige Lösung für dieses Problem namens IRR (Independent Resolution Renderer). Es hat eine sehr einfache Verwendung:

  1. Erstellen Sie IRR in der Initialize () -Methode

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

  2. Call _irr.Draw () jeder Zyklus in Draw () Aufruf
  3. Versorgung _irr.GetTransformationMatrix () in jedem SpriteBatch.Begin () rufen Sie IRR verwenden.

Die Beschreibung finden Sie hier: http://panthernet.ru/forum/index.php?/topic/17-monogamexna-examples-v14/?p=44

Der Code ist hier: https://github.com/panthernet/Monogame-Examples

Alexander Smirnov
quelle