Fake isometrische Grafiken in einem 2D-Weltraumspiel

15

Zuallererst weiß ich genau, was mein Zeichenproblem ist, und ich habe verschiedene Ideen, wie ich es lösen kann. Ich bin hier, um herauszufinden, wie man den Rahmen so einstellt, dass die isometrische "Illusion" erhalten bleibt.

Ich schreibe ein 2D-Spiel aus der Vogelperspektive, das im Weltraum stattfindet. Ich versuche, isometrische Grafiken in einer Welt zu verwenden, in der Up Nord ist, kein Drehen der Spielwelt wie in traditionellen isometrischen Spielen (denken Sie daran, das Spiel findet im Weltraum statt, kein Gelände). Hier ist ein Beispiel-Sprite, das ich verwenden möchte : http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png 64-mal um die eigene vertikale Achse gedreht, mit einem Betrachtungswinkel von 35 Grad (aka, iso). Das Bild wurde erzeugt, so dass dies kann geändert werden.

Aus Gründen der Klarheit habe ich festgelegt, dass Nord (Oben) 0 Grad und Ost (Rechts) 90 Grad beträgt.

Mein Problem ist, dass mein Sprite nicht immer so aussieht, als würde es dort ausgerichtet sein, wo das Spiel denkt, dass es auf einen Unterschied in den verwendeten 3D-Ebenen zurückzuführen ist. Ich bin nicht sicher, ob ich die Terminologie richtig verwende, aber mein Raumschiff wurde in einer Ebene gedreht, und die Ansichtsebene erwartet, dass die Dinge in ihrer eigenen Ebene gedreht werden. Hier ist eine Darstellung des Problems:

http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png Links habe ich Seitenansichten, rechts habe ich Ansichten von oben nach unten. Oben habe ich die Raumschiff- / Sprite-Ansicht der Welt. Unten sehe ich, wie das Sprite aussieht, wenn es auf dem Bildschirm angezeigt wird.

Oben rechts ist eine vereinfachte Version davon zu sehen, wie mein Raumschiff gedreht wurde (gleichmäßige Gradtrennungen zwischen den einzelnen Frames). In der rechten unteren Ecke ist der Winkel, die Sprite aussehen wie es mit Blick auf, wenn ein bestimmte Winkel auf dem Bildschirm gezeichnet wird. Das Problem tritt am deutlichsten bei etwa 45 Grad auf. Hier ist ein Bild, das mit einer "Bildschirmebenen" -Linie überlagert ist, die in die Richtung zeigt, in die das Schiff ausgerichtet sein soll: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png Die rote Linie sollte immer genau in die gleiche Richtung zeigen wie das Schiff, aber wie Sie sehen können, verursacht das Projektionsproblem ein Problem. Ich hoffe, ich beschreibe das Problem gut genug.

BEARBEITEN: Die rote Linie wird in der Bildschirmebene gedreht, während das Raumschiff in der "Schiffsebene" gedreht wird, daher der große Unterschied zwischen dem Schiffswinkel und dem Bildschirmwinkel, wenn es gezeichnet wird. ENDE BEARBEITEN

Es sieht ziemlich seltsam aus, wenn dieses Schiff einen Laserstrahl auf ein seitlich entferntes Ziel schießt, wenn es geradeaus schießen soll.

Also ... die Lösungen, die ich gefunden habe, sind:

  1. Hören Sie auf, eine isometrische Ansicht zu fälschen, gehen Sie groß oder gehen Sie nach Hause. Drehe meine Welt schon. (PS: das wird mein Problem beheben, oder?)
  2. Ändere mein Sprite Sheet (irgendwie) so, dass es Frames enthält, die den "Bildschirmwinkel" darstellen, unter dem das Modell angezeigt wird. Wenn ich also nach einem 45-Grad-Bild frage, sieht es tatsächlich so aus, als würde es 45 Grad auf dem Bildschirm anzeigen.
  3. Ändern Sie mein Sprite-Rendering-System, um (irgendwie) einen anderen Frame aus dem Sprite-Sheet zu ziehen, da Sie wissen, dass das Ziehen des "normalen" Frames lustig aussehen wird. Anstatt also den 45-Grad-Rahmen zu greifen, greift er den ... 33-Grad-Rahmen (nur raten), damit er für den Benutzer korrekt aussieht .
  4. Benutze einfach 3D! Es ist so viel einfacher, Mann

Zum einen: Welche Lösung würden Sie empfehlen? Ich neige zu 2, obwohl ich weiß, dass es falsch ist. Denken Sie daran, dass ich vollen Zugriff auf das Sprite-Generierungs-Tool habe. Methode 3 wäre meine zweite Wahl. Bei beiden Methoden muss ich lediglich einige Berechnungen auf die Winkel anwenden, um das gewünschte Ergebnis zu erzielen. Übrigens habe ich als Scherz # 4 hinzugefügt, ich möchte nicht zu 3D wechseln.

Zu zweit: Wie würde ich mit den Methoden 2 oder 3 den Ein- oder Ausgabewinkel anpassen? Ich kann mit 3D-Projektionen und 3D-Matrizen (geschweige denn 2D-Matrizen) nicht allzu gut umgehen, und mit welcher anderen Mathematik auch immer kann ich das gewünschte Ergebnis erzielen.

Hier laut denken: Wenn ich einen Einheitsvektor nehme, der in die Richtung zeigt, in die das Schiff schauen soll (auf der Bildschirmebene), dann projiziere diesen auf die Schiffsebene und finde dann heraus, wie der Winkel zwischen dieser projizierten Linie und der Ebene ist Norden ist, sollte ich den Winkel der Schiffsgrafik haben, die ich anzeigen möchte. Richtig? (Lösung für # 3?) Mann ... das kann ich nicht herausfinden.

BEARBEITEN:

Ich weiß, dass das Problem mit statischen Bildern nur schwer zu visualisieren ist. Daher habe ich meinen Sprite Library Visual Tester befolgt, um das Problem anzuzeigen: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zip Für diese Anwendung ist XNA 4.0 erforderlich Drehe einfach das Sprite und ziehe eine Linie von seinem Mittelpunkt nach außen in dem Winkel, in dem das Spiel glaubt, dass das Schiff ausgerichtet sein sollte.

EDIT 8. September

Fortsetzung von meinem Abschnitt "Lautes Denken": Anstatt eine Projektion zu verwenden (weil es schwierig aussieht), denke ich, ich könnte einen nach Norden gerichteten Einheitsvektor (0x, 1y, 0z) verwenden, um ihn in den Winkel zu drehen Das Sprite ist tatsächlich ausgerichtet. Drehen Sie es dann erneut von der "Ansichtsebene" nach außen in die "Spriteebene" um die X-Achse. Dann ... Abflachen? Der Vektor wird (im Wesentlichen) zurück auf die Betrachtungsebene projiziert, indem nur X und Y verwendet werden (Z wird ignoriert). Mit diesem neuen abgeflachten Vektor könnte ich dann seinen Winkel bestimmen und damit ... etwas tun. Ich werde später mehr darüber nachdenken.

EDIT 8. September (2)

Ich habe versucht meine Idee von oben mit einigem Erfolg zu verfolgen, yay! Um eine rote Linie zu erhalten, die aussieht, als würde sie direkt aus meinem Raumschiff kommen (nur zu Testzwecken), habe ich Folgendes getan:

Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);

float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));

Wo rotationist der Bildschirmwinkel und adjustedRotationjetzt sieht dieser Bildschirmwinkel auf der Sprite-Ebene aus. Ich weiß nicht, warum ich Y anstelle von X drehen musste, aber es hat wahrscheinlich etwas mit 3D zu tun, von dem ich nichts weiß.

Nun habe ich also eine zusätzliche Information, aber wie verwende ich diese, um einen passenderen Rahmen auszuwählen? Vielleicht sollte ich versuchen, es andersherum zu machen, anstatt mich von der Ansichtsebene in die Sprite-Ebene zu drehen und dann nach hinten zu projizieren. Hier ist mein Sprite mit einer angepassten roten Linie, aber ich möchte wirklich das Modell und nicht die Linie anpassen: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png

EDIT 9. September

HORAY! Es ist repariert! Ich werde beschreiben, was ich getan habe, um es zu beheben:

Ich folgte dem Rat von eBusiness und "quetschte" mich nach dem Weltkoordinatensystem (oder dehnte mich aus ...?). Dies ist im Wesentlichen Lösung Nr. 1, obwohl ich den Eindruck hatte, dass ich mein Weltkoordinatensystem in Bezug auf das Bildschirmkoordinatensystem drehen müsste. Nicht wahr! Oben ist immer noch + y und rechts ist immer noch + x. Ich habe meine WorldToScreen- und ScreenToWorld-Methoden so geändert, dass sie korrekt zwischen den Welt- und Bildschirmkoordinaten konvertieren. Diese Methoden sind möglicherweise nicht optimal, aber hier sind die einzigen zwei Methoden in meiner Codebasis, die geändert werden mussten.

public Vector2 ScreenToWorld(float x, float y)
{
    float deltaX = x - (size.Width / 2f);
    float deltaY = y - (size.Height / 2f);

    deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
    deltaY = deltaY * scaleFactor;

    return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}

public Vector2 WorldToScreen(float x, float y)
{
    float deltaX = x - focusWorldPoint.X;
    float deltaY = y - focusWorldPoint.Y;

    deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
    deltaY = deltaY / scaleFactor;

    return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}

Das war's! Das Ändern dieser beiden Methoden wirkte sich auf alles andere aus: was ich sah, wo die Objekte gezeichnet wurden, wo ich klickte, alles. Mein Raumschiff schaut jetzt direkt auf das Ziel, auf das es schießt, und alles passt zusammen. Ich werde mit der orthografischen Projektion experimentieren, um zu sehen, ob dadurch alles „realer“ erscheint.

John McDonald
quelle
Herzliche Glückwünsche. Vergiss nicht, mich zu stupsen, wenn du etwas Spielbares hast. Ich würde gerne sehen, wohin das führt.
aaaaaaaaaaa 10.09.11
@eBusiness Wie versprochen: cell.stat-life.com/images/stories/AsteroidOutpost/… und cell.stat-life.com/images/stories/AsteroidOutpost/AOOhNoes.png Sehen Sie, wie das Schiff aussieht, als würde es auf diesen Turm blicken ? : D Danke!
John McDonald
@eBusiness, A video youtube.com/watch?v=Q8pR9KDBsCo Es gibt auch einen Link zum Herunterladen, da Sie gefragt haben.
John McDonald

Antworten:

4

Wenn Sie die isometrische Perspektive gewählt haben, müssen Sie den Maßstab zwischen der X- und der Y-Achse korrigieren. Wenn ein bestimmter Abstand auf der Y-Achse des Bildschirms auf 1 projiziert wird, wird derselbe Abstand auf der X-Achse des Bildschirms auf sqrt (3) projiziert. Wenn Sie also Dinge flach auf den Bildschirm zeichnen, würden Sie Folgendes tun:

draw(object.image, object.x*sqrt(3), object.y)

Nicht beantwortete Notizen:

  • Warum würdest du dich mit Sprite Sheets und anderen Dingen anlegen? Wenn Sie möchten, können Sie einen 3D-Renderer für die Isometrie verwenden.
  • Warum verwenden Sie keine Sprite-Blätter mit Anti-Aliasing-Effekten?
  • Isometrisch im Weltraum, ich glaube nicht, dass ich jemals ein Spiel gesehen habe, das so funktioniert. Ich bin mir nicht sicher, wie gut es funktioniert, da es keinen klar isometrischen Grund für die visuelle Bezugnahme gibt.
aaaaaaaaaaa
quelle
1
Ich denke ... Das könnte alles reparieren. Es ist eine einfache Lösung, und ich kann das Blatt in Ruhe lassen. Ich werde das so schnell wie möglich ausprobieren und dich wissen lassen, wie es geht. So beantworten Sie Ihre Notizen: 1) Ich verwende 2D, weil ich damit vertraut bin und meine Blätter aus 3D-Modellen generiere. 2) Die Kanten sollten scharf sein, aber innerhalb der harten Kanten könnte ich den Alpha-Kanal als Anti-Alias ​​verwenden, das wird kommen. 3) Ich habe nicht vor, die dritte Dimension (viel) zu simulieren, ich möchte hauptsächlich 2D-Grafiken, die nicht von oben nach unten sind und es Ihnen ermöglichen, die Seiten der Dinge zu sehen.
John McDonald
5

Wie wird das gedrehte Sprite generiert? Sind diese Screenshots eines rotierenden 3D-Modells? Der Blickwinkel könnte aufgrund der Kameraperspektive des 3D-Modellierungswerkzeugs deaktiviert sein. Die isometrische Perspektive ist keine genaue Darstellung des 3D-Raums. Sachen weit weg von der "Kamera" werden nicht kleiner.

Wenn Sie nur eine schnelle Lösung wünschen. Lösung 2 ist möglicherweise schwer zu finden. Lösung 3 scheint einfach zu sein, tauschen Sie einfach die Rahmen, die nicht zum Winkel passen, mit denen aus, die besser zum Winkel passen.

Die Laser sind manchmal immer noch ausgeschaltet. Da Sie keine gleichmäßige Drehung ausführen, sondern für bestimmte Gradbereiche unterschiedliche Frames anzeigen.

BEARBEITEN:

Ihr Problem ist, dass die generierten Screenshots keine isometrische Perspektive sind, sondern eine normale 3D-Kameraansicht.

Bildbeschreibung hier eingeben

Die isometrische Ansicht simuliert den 3D-Raum, ist jedoch keine genaue Darstellung. Mit zunehmendem Abstand zur Kamera wird es kleiner. Für die isometrische Perspektive ist dies nicht der Fall, da dies hässliche Skalierungsartefakte im Sprite verursachen würde.

Ihre Weltraumschiff-Screenshots werden mit 3D-Kameraperspektive erstellt. Deshalb ist das Laserschießen ausgeschaltet. Vergleichen Sie die rote Linie in der "isometrischen" und der "Perspektive".

Ihr Sprite-Generator sollte Matrix.CreateOrthographic () anstelle von Matrix.CreatePerspective () für die Projektionsmatrix verwenden.

Stephen
quelle
Das Sprite wird mit einem 3D-zu-2D-Tool generiert, das ich entwickle. Das Problem könnte also in diesem Tool liegen. Das Tool lädt einfach ein 3D-Modell. Um dann Spaceship64.png (oben) zu erhalten, dreht es das Modell um (360/64) = 5,625 Grad, speichert es als Rahmen und dreht es dann erneut um denselben Betrag, bis alles vorhanden ist 64 Bilder. Der Code zum Rendern des Modells lautet hier: code.google.com/p/sprite-maker/source/browse/trunk/XNAWindow/… Das Drehen erfolgt in einer anderen Klasse. Ich dachte auch, dass Lösung 2 und 3 das Gegenteil voneinander sind, nicht wahr?
John McDonald
Bearbeitet meine Antwort. Siehe oben.
Stephen
Ich denke, ich muss möglicherweise beides tun: Mache, dass mein Sprite-Generator eine orthografische Projektion verwendet UND ändere mein Weltkoordinatensystem wie das, was @eBusiness sagt. Ich habe gestern Abend die orthografische Projektion ausprobiert, und es hat sicherlich das Aussehen meines Schiffes verändert, aber es allein hat das Winkelproblem, das ich habe, nicht behoben.
John McDonald
Hab gerade deine Bearbeitung gesehen. Das korrigierte Sprite scheint nicht in der Mitte der roten Linie zu liegen. Vielleicht reicht es aus, das Schiff ein oder zwei Pixel höher als den Startpunkt der roten Linie zu zeichnen. Ändert sich der sichtbare Fehler, während sich das Schiff von Ihrem Weltursprung entfernt? Dann kann das Problem möglicherweise durch Skalieren der X-Achse behoben werden.
Stephen
1

Ich denke, was Sie hier haben, ist einfach, wie isometrisch aussieht. Sie haben recht damit, dass es visuell einen größeren Unterschied zwischen 0 und 10 Grad gibt als zwischen 90 und 100 Grad. . . Das liegt aber daran, dass die Isometrie eine Achse intrinsisch komprimiert. Wenn Sie diesen Blick nicht wollen, wollen Sie nicht isometrisch.

Das heißt, ich denke, die visuellen Probleme, die Sie haben, sind darauf zurückzuführen, dass Sie keinen visuellen Bezugspunkt haben. Ihr Gehirn geht davon aus, dass Sie es von oben nach unten betrachten - hey, es ist Platz, warum nicht? Fügen Sie zu Testzwecken einige schwebende holographische Referenzpunkte hinzu. Zum Beispiel ein 45-Grad-Winkelgitter oder eine Reihe von Entfernungskreisen um Ihr Raumschiff. Stellen Sie sicher, dass sie angemessen verzerrt sind, als befänden sie sich auf derselben isometrischen Ebene, auf der Ihr Raumschiff gerendert wurde. Ich würde wetten, dass Ihr Gehirn die Perspektive herausfindet und sie plötzlich richtig aussieht.

Finden Sie heraus, wie Sie dies Ihren Benutzern vermitteln können. . . Das ist eine ganz andere Sache.

ZorbaTHut
quelle
Muss ich nicht auch die Weltachse drehen, um die Illusion mit dieser Methode zu vervollständigen (Methode 1 in der Frage)?
John McDonald
Soweit ich das beurteilen kann, wird das Schiff bereits korrekt gerendert - die Seitenansichten zeigen es in dem Winkel, in dem es sein sollte, damit die Isometrie "korrekt" aussieht. Ich glaube, ich bin mir nicht sicher, was Sie mit "Weltachse drehen" meinen.
ZorbaTHut
Mit "Weltachse drehen" meine ich, dass die Welt in Bezug auf die Kamera um 45 Grad gedreht wird, damit "Norden" in einer Diagonale nach rechts oben oder links oben auf dem Bildschirm angezeigt wird, anstatt dass "Norden" gerade nach oben zeigt nach oben auf dem Bildschirm.
John McDonald
Das könnte helfen, aber im Weltall sollte es sowieso keinen großen Unterschied machen. Es sollte einfach keine Rolle spielen, es sei denn, Sie haben ein Raster über der Welt.
ZorbaTHut