Nachdem ich meinem Spiel Geschwindigkeit hinzugefügt habe, habe ich das Gefühl, dass meine Texturen zucken. Ich dachte, es wären nur meine Augen, bis ich es schließlich in einem Screenshot festhielt:
Der linke ist das, was in meinem Spiel gerendert wird. Das rechte ist das ursprüngliche Sprite, das eingefügt wurde. (Dies ist ein Screenshot aus Photoshop, 6-fach vergrößert.)
Beachten Sie, dass die Kanten Aliasing sind - es sieht fast wie Subpixel-Rendering aus. Wenn ich meine Sprites (die Position und Geschwindigkeit als Ints haben) nicht gezwungen hätte, mit ganzzahligen Werten zu zeichnen, würde ich schwören, dass MonoGame mit Gleitkommawerten zeichnet. Aber es ist nicht so.
Was könnte die Ursache dafür sein, dass diese Dinge verschwommen erscheinen? Es passiert nicht ohne angewendete Geschwindigkeit.
Um genau zu sein, meine SpriteComponent
Klasse hat ein Vector2 Position
Feld. Wenn ich anrufe Draw
, benutze ich im Wesentlichen new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))
für die Position.
Ich hatte vorher einen Fehler, bei dem sogar stationäre Objekte zitterten - das lag daran, dass ich den geraden Position
Vektor verwendete und die Werte nicht auf rundete ints
. Wenn ich Floor
/ Ceiling
anstelle von rund verwende, sinkt / schwebt das Sprite (ein Pixel Unterschied in beide Richtungen), zeichnet aber immer noch verschwommen.
Antworten:
Nun, das ist peinlich.
Es stellt sich heraus, dass ich nicht mit ganzzahligen Positionen, sondern mit Gleitkommazahlen gezeichnet habe. Archy zeigte mir mit seinem Kommentar den richtigen Weg
@ashes999 did you debug this call and checked this.X, this.Y and this.origin?
Sobald ich eine Trace-Anweisung hinzufügte, bemerkte ich, dass nichts zurückverfolgt wurde. Es stellt sich heraus, dass meine
SpriteComponent
Klasse korrekt ganzzahlige Werte verwendet hat, aber meineSpriteSheetComponent
noch verwendeten Gleitkommawerte aus dem RohwertVector2 Position
.Obwohl ich nicht versucht habe, Texturen zu filtern und zu klemmen, war ich misstrauisch, dass dies nicht die richtige Änderung war, da ich ein 2D-Bild mit der gleichen Breite und Höhe wie das Quellbild gezeichnet habe (keine Skalierung).
quelle
XNA verwendet DirectX9, das die Mitte des Pixels als Position verwendet. Dies macht sich bei Verwendung der Vector2-basierten Überladungen der Draw-Klasse bemerkbar. Ich glaube, dass das Subtrahieren (.5, .5) Ihr Problem beheben sollte.
Mehr Infos hier.
quelle
int, int
den Argumenten übergebe. Außerdem sieht es ganz gut aus, wenn ich keine Objekte in Bewegung habe.SpriteComponent
hat eineVector2
Position, die sich je nach Geschwindigkeit als Float erhöht; Wenn ich zeichne, erstelle ich eine neueVector2
mit ganzzahligen (gerundeten) Versionen meinesposition
X und Y. Dies ist nicht das Problem, da stationäre Objekte ohne Geschwindigkeit in Ordnung erscheinen.p += v
während hinzuUpdate
und rendere mitnew Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y)))
.Das Rendern weiß nichts über Ihre Geschwindigkeit, daher ist entweder die Position, Größe oder irgendetwas anderes, das Sie an SpriteBatch weitergeben. Draw ist anders oder der Fehler war vorhanden, bevor Sie die Geschwindigkeit hinzugefügt haben. Wie nennt man SpriteBatch.Draw genau?
Haben Sie diesen Aufruf debuggt und this.X, this.Y und this.origin überprüft? Was ist this.origin eingestellt? Grundsätzlich ist das Renderergebnis mit der Geschwindigkeit nicht unterschiedlich, wenn dieser Draw-Aufruf identisch ist.
quelle
Das Problem ist wahrscheinlich, dass die Texturfilterung aktiviert ist. Wenn Sie sich nicht sicher sind, was dies bedeutet, stellen Sie sich eine Situation vor, in der Sie ein Bild mit einer Breite von 2 Pixel haben: Das erste Pixel ist schwarz, das zweite Pixel ist weiß. Wenn Sie diese Textur vergrößern und die Texturfilterung aktivieren, werden Sie feststellen, dass sie unscharf wird und der Bereich zwischen dem schwarzen und dem weißen Pixel eine graue Farbverlaufsfarbe verwendet.
Ein klassisches Beispiel für Spiele mit und ohne Filterung ist Super Mario 64, das gefiltert wurde, Doom jedoch nicht.
Wenn Sie keine Geschwindigkeit verwenden, ist Ihr Sprite wahrscheinlich so positioniert, dass sich die Mitte der Textur an dem Abtastpunkt befindet, an dem XNA (oder die zugrunde liegende API) die Farbe erfasst. Wenn Sie sich mit einer Gleitgeschwindigkeit bewegen, ändert sich die Position Ihres Sprite, sodass der Abtastpunkt möglicherweise nicht direkt mit der Mitte eines Pixels ausgerichtet ist. Das Endergebnis ist also, dass eine Farbe vorliegt, die ein Durchschnitt der nächsten Pixel ist verwendet, um zu rendern.
Sie können überprüfen, ob die Filterung aktiviert ist, indem Sie Ihr Sprite einfach auf dem Bildschirm sehr groß machen. Wenn es verschwommen ist, dann ist das das Problem.
Wenn Sie beim Rendern eine pixelgenaue Genauigkeit benötigen, möchten Sie einen Gleitkommawert für die Position irgendwo speichern, aber ganzzahlige Werte für die Position des Objekts verwenden, das Sie rendern ... oder Sie können natürlich einfach die Filterung deaktivieren wenn dein Spiel es nicht braucht.
Sie können auch lesen wollen dies .
quelle
Draw
. Ich bin mir also nicht sicher, wie das der Fall sein könnte - aber ich werde versuchen, in großem Maßstab zu rendern und zu prüfen, ob das Deaktivieren der Texturfilterung hilfreich ist.Versuchen Sie, Ihren SamplerState im SpriteBatch.Begin-Aufruf auf SamplerState.PointClamp zu setzen.
quelle