2010-11-30 12 views
0

Ich arbeite derzeit an einem XNA-Spiel-Prototyp. Ich versuche eine isometrische Ansicht der Spielwelt zu erreichen (oder ist es othographisch? Ich bin mir nicht sicher, welcher der richtige Ausdruck für diese Projektion ist - siehe Bilder). Die Welt sollte eine Kachel-basierte Welt aus kubischen Kacheln (z. B. ähnlich der Minecraft-Welt), und ich versuche, es in 2D mit Sprites zu rendern.XNA isometrische Fliesen Rendering Problem

Also habe ich ein Sprite-Blatt mit der Oberseite des Würfels, der Vorderseite und der Seite (Sichtseite). Ich zeichne die Kacheln mit 3 separaten Aufrufen von drawSprite, eine für die Spitze, eine für die Seite, eine für die Vorderseite, mit einem Quellrechteck das Gesicht, das ich zeichnen möchte und ein Zielrechteck, um die Position auf dem Bildschirm entsprechend einzustellen zu einer Formel, um von 3D-Weltkoordinaten in isometrische (orthographische?) zu konvertieren.

(Probe Sprite: Sprite)

Das funktioniert gut, solange ich die Gesichter ziehen, aber wenn ich versuche, jeden Block feine Kanten zu zeichnen (nach einer Kachel Gittern) kann ich sehen, dass ich ein zufälliges Rendering-Muster, bei dem einige Linien vom Gesicht selbst überschrieben werden und andere nicht.

Bitte beachten Sie, dass für meine Weltrepräsentation X links nach rechts ist, Y ist innerhalb des Bildschirms nach außen Bildschirm und Z ist von oben nach unten.

In diesem Beispiel arbeite ich nur mit oberen Flächenkanten. Hier ist, was ich (Bild) bekommen:

alt text

Ich verstehe nicht, warum einige der Linien dargestellt sind und manche nicht. Die Rendering-Code, den ich verwenden ist (man beachte in diesem Beispiel habe ich nur die obersten Schichten zeichnen in jeder Dimension):

/// <summary> 
/// Draws the world 
/// </summary> 
/// <param name="spriteBatch"></param> 
public void draw(SpriteBatch spriteBatch) 
{ 
    Texture2D tex = null; 

    // DRAW TILES 
    for (int z = numBlocks - 1; z >= 0; z--) 
    { 
     for (int y = 0; y < numBlocks; y++) 
     { 
      for (int x = numBlocks - 1; x >=0 ; x--) 
      { 

       myTextures.TryGetValue(myBlockManager.getBlockAt(x, y, z), out tex); 
       if (tex != null) 
       { 
        // TOP FACE 
        if (z == 0) 
        { 
         drawTop(spriteBatch, x, y, z, tex); 
         drawTop(spriteBatch, x, y, z, outlineTexture); 
        } 

        // FRONT FACE 
        if(y == numBlocks -1) 
         drawFront(spriteBatch, x, y, z, tex); 

        // SIDE FACE 
        if(x == 0) 
         drawSide(spriteBatch, x, y, z, tex); 

       } 
      } 
     } 
    } 
} 


private void drawTop(SpriteBatch spriteBatch, int x, int y, int z, Texture2D tex) 
     { 
      int pX = OffsetX + (int)(x * TEXTURE_TOP_X_OFFRIGHT + y * TEXTURE_SIDE_X); 
      int pY = OffsetY + (int)(y * TEXTURE_TOP_Y + z * TEXTURE_FRONT_Y); 
      topDestRect.X = pX; 
      topDestRect.Y = pY; 
      spriteBatch.Draw(tex, topDestRect, TEXTURE_TOP_RECT, Color.White); 
     } 

Ich habe versucht, einen anderen Ansatz, eine zweite 3-Ebenen verschachtelt for-Schleife nach dem Erstellen der erste, also behalte ich die oberste Gesichtszeichnung in der ersten Schleife und die Kantenhervorhebung in der zweiten Schleife (ich weiß, das ist ineffizient, sollte ich wahrscheinlich auch vermeiden, einen Methodenaufruf für jede Kachel zu haben, um es zu zeichnen, aber ich bin versuche nur, es für jetzt zu arbeiten).

Die Ergebnisse sind irgendwie besser, aber es fehlt noch nicht wie erwartet, Top-Reihen arbeiten, siehe Bild:

alt text

Jede Idee, warum habe ich dieses Problem? In der ersten Annäherung könnte es eine Art von Z-Kämpfen sein, aber ich zeichne Sprites in einer genauen Reihenfolge, also sollten sie nicht überschreiben, was schon da ist?

Vielen Dank allen

+0

Machst du irgendeine Skalierung? –

Antwort

1

Whoa, Entschuldigung Jungs, ich bin ein Idiot :) Ich startete den Stapel mit SpriteBatch.begin (SpriteSortMode.BackToFront), aber ich habe keinen Z-Wert in der Zeichnung verwendet. Ich hätte SpriteSortMode.Deferred verwenden sollen! Es funktioniert jetzt gut. Danke allen!

0

Versuchen Sie, die Größen Ihrer Quell- und Zielrechtecke mit 1 oder 2 Pixel zwicken. Ich habe den Verdacht, dass dies etwas mit der Art und Weise zu tun hat, wie diese Rechtecke als eine Art "Umrisse" des zu rendernden Bereichs und als eine Art von Einzelproblem behandelt werden. Das ist kein Expertenrat, nur die Intuition eines Kollegen.

0

Sieht aus wie ein Sub-Pixel-Genauigkeit oder Skalierungsproblem. Versuchen Sie auch sicherzustellen, dass Ihre Textur/Kachelbreite/-höhe eine Potenz von 2 (32, 64, 128 usw.) ist, da dies den Effekt ebenfalls weniger schlecht machen könnte. Es ist wirklich schwer zu sagen, nur von diesen Bildern.

Ich weiß nicht, wie/wenn Sie alles skalieren, aber Sie sollten versuchen, Rundungen möglichst zu vermeiden (besonders innerhalb Ihrer drawTop() Methode).Jedes Mal, wenn Sie einige Positions-/Koordinatenchancen gut sind, können Sie die Fehler-/Zufallsoffsets erhöhen. Versuchen Sie, doppelte (oder besser: float) Koordinaten anstelle von Integer zu verwenden.

+0

Momentan benutze ich 1: 1, wenn ich es ändere, laufe ich in einigen Artefakten mit bestimmten Skalen (d. H. Die Blöcke "vermissen" ein Pixel in einer gegebenen Zeile), aber ansonsten ist es in Ordnung. Es scheint auch, dass der Ursprung des Rechtecks ​​nur auf einen int Wert gesetzt werden kann? – Marco83

+0

Niemals verwendet (hauptsächlich auf normales DirectX und OpenGL konzentriert), aber wenn es Bildschirmkoordinaten/Pixel verwendet, sind Ganzzahlen in Ordnung. Runden Sie einfach nicht ab, während Sie diese berechnen (bevor Sie sie weitergeben). – Mario