Stellen Sie sich ein Spiel mit einer Standardauflösung von 800 x 600 vor. Objekte mit Kollisionsmasken werden in eine Spielwelt der Größe 800x600 gelegt. Die Kollisionsmasken können erkennen, wann die Maus mit ihnen kollidiert.
Nehmen wir nun an, wir skalieren das Spiel auf 1024 x 768 (nehmen wir an, wir skalieren die Grafik, indem wir einfach alles auf eine Ebene rendern und dann die gesamte Ebene auf einmal skalieren). Wir haben zwei Möglichkeiten, um die Kollisionen mit der Maus in dieser neuen Auflösung richtig funktionieren zu lassen:
A.) Skalieren Sie die Welt auf 1024x768 und skalieren Sie die Kollisionsmaske jedes Objekts entsprechend.
B.) "Map" die Mausposition auf die Originalwelt (800x600).
Mit "Karte" meine ich, skaliere einfach die Mausposition auf die ursprüngliche 800x600-Welt. Wenn die Mausposition auf dem Bildschirm beispielsweise (1024, 768) ist, ist die Mausposition in der Welt (800, 600).
Offensichtlich erfordert Option B einen Weg weniger Berechnung und ist wahrscheinlich weniger anfällig für geometrische Fehler, aber es fühlt sich auch Art „hackish“ zu mir, wie es unvorhergesehenen Folgen mit dieser Methode geht die Hölle sein wird , zu beheben später.
Mit welcher Methode soll ich gehen: A, B oder etwas anderes?
quelle
Antworten:
In der Regel (auch für 2D-Spiele) gibt es ein separates Koordinatensystem für das Spiel, das von der Auflösung unabhängig ist. Dies wird normalerweise als Weltraum bezeichnet. Auf diese Weise können Sie auf eine beliebige Auflösung skalieren.
Der einfachste Weg, dies zu erreichen, ist die Verwendung einer 2D-Kamera. Hierbei handelt es sich im Wesentlichen um eine Matrix, die den Übergang vom Weltraum (Ihre willkürlichen Einheiten) zum Bildschirmraum (die Pixel auf dem Bildschirm) definiert. Dies macht den Umgang mit der Mathematik trivial.
Werfen Sie einen Blick auf den folgenden Abschnitt in XNA 2d Camera Scrolling - warum sollten Sie die Matrixtransformation verwenden?
Es macht es wirklich einfach, zwischen Koordinatensystemdefinitionen zu konvertieren
Verwenden Sie einfach Vector2.Transform, um vom Bildschirm in den Weltraum zu gelangen. Dies wird häufig verwendet, um die Position der Maus in der Welt für die Objektauswahl zu ermitteln.
Um von der Welt in den Bildschirmraum zu gelangen, machen Sie einfach das Gegenteil.
Es gibt keine Nachteile bei der Verwendung einer Matrix, außer dass ein wenig Lernen erforderlich ist.
quelle
Eine weitere Option wäre: Bewegen Sie bei jedem eingegebenen Mausbewegungsereignis den Mauszeiger im Spiel um die Anzahl der Spielpixel, die der Anzahl der Pixel im Mausereignis entspricht. Dies ist natürlich bei 3D-Spielen der Fall, bei denen der echte Mauszeiger in der Mitte fixiert und die Zielrichtung um einen Betrag gedreht wird, der der eingegebenen Mausbewegung entspricht. Sie können dies jedoch auf die gleiche Weise tun, indem Sie ein Sprite bewegen, das den Mauszeiger im Spiel darstellt.
Sie müssen natürlich alle Mausbewegungsereignisse ignorieren, die durch das Verziehen der Maus in die Mitte verursacht werden. Wenn Ihr Spiel überhaupt eine Verzögerung bei der Eingabe aufweist, ist die Unempfindlichkeit des Cursors der störendste und auffälligste Aspekt.
Welche Lösung Sie verwenden, hängt zum Teil davon ab, wie wichtig die Mausposition für das Gameplay ist. Wenn dies ein RTS ist und der Spieler einfach auf Einheiten klickt, können Sie wahrscheinlich einfach entscheiden, welches von Ihren A oder B einfacher ist. Wenn es sich um einen Top-Down-Shooter handelt und die Maus die Bewegungen des Charakters direkt steuert, werden Sie wahrscheinlich eine detailliertere Lösung wünschen, die die Variabilität der Bewegungen des Charakters nicht nur aufgrund der Auflösung, sondern auch aufgrund von Dingen wie der Mausbewegung einschränkt Geschwindigkeit. Wenn die Maus stattdessen die Ausrichtung steuert, möchten Sie eine andere Lösung usw.
quelle
Die Antwort von ClassicThunder ist richtig, aber ich möchte ein Beispiel für ein alternatives / einfacheres Mittel zum Erreichen des gewünschten Effekts geben. Dies ist eine einfachere Lösung für Rapid Prototyping, wenn Sie keinen Zugriff auf eine voll funktionsfähige Bibliothek haben oder wenn Sie keinen Zugriff auf eine GPU haben (z. B. in eingebetteten Systemen).
Um dieses Mapping durchzuführen, können Sie die folgende Funktion verwenden (vorausgesetzt, sie wird in der statischen Klasse definiert
Helper
):(Sie haben keine Sprache angegeben, aber ich sehe, dass Sie etwas über C # wissen. Mein Beispiel ist also in C #.)
Sie können diese Funktion dann wie folgt verwenden:
Wo
camera.Bounds
ist ein Rechteck, das den Bereich der Welt darstellt, den die Kamera sehen kann (dh den Bereich, der auf den Bildschirm projiziert wird).Wenn Sie eine
Vector
oderPoint
-Klasse haben, können Sie diesen Vorgang weiter vereinfachen, indem Sie ein 2D-Äquivalent der Kartenfunktion erstellen.Was Ihren Mapping-Code zu einem einfachen Einzeiler machen würde:
quelle
Option (C): Ändern Sie die Bildschirmauflösung zurück auf 800x600.
Auch wenn Sie dies nicht tun, betrachten Sie es als Gedankenexperiment. In diesem Fall liegt es in der Verantwortung des Bildschirms, die Größe der Grafiken an die physische Größe anzupassen, und dann in der Verantwortung des Betriebssystems, Zeigerereignisse mit einer Auflösung von 800 x 600 zu erhalten.
Ich denke, es hängt alles davon ab, ob es sich bei Ihren Grafiken um Bitmaps oder Vektoren handelt. Wenn es sich um Bitmaps handelt und Sie in einem 800 x 600-Puffer rendern, ist es viel einfacher, die Maus dem Bildschirmbereich neu zuzuordnen und die tatsächliche Bildschirmauflösung zu ignorieren. Der große Nachteil dabei ist jedoch, dass die Hochskalierung hässlich aussehen kann, insbesondere wenn Sie blockige 8-Bit-Grafiken verwenden.
quelle