Wie passe ich den Rotationsursprung für eine Gruppe von Sprites an?


7

Ich gruppiere derzeit Sprites und wende dann beim Zeichnen eine Rotationstransformation an:

private void UpdateMatrix(ref Vector2 origin, float radians)
{
     Vector3 matrixorigin = new Vector3(origin, 0);
     _rotationMatrix = Matrix.CreateTranslation(-matrixorigin) * Matrix.CreateRotationZ(radians) *  Matrix.CreateTranslation(matrixorigin);
}

Wo der Ursprung der zentralste Punkt meiner Gruppe von Sprites ist. Ich wende diese Transformation auf jedes Sprite in der Gruppe an.

Mein Problem ist, dass sich meine gesamte Sprite-Gruppe beim Anpassen des Ursprungspunkts auf dem Bildschirm neu positioniert.

Wie kann ich den in der Transformation verwendeten Drehpunkt von der Position der Sprite-Gruppe unterscheiden? Gibt es eine bessere Möglichkeit, diese Transformationsmatrix zu erstellen?

BEARBEITEN

Hier ist der relevante Teil der Draw () -Funktion:

Matrix allTransforms = _rotationMatrix * camera.GetTransformation();

spriteBatch.Begin(SpriteSortMode.BackToFront, null, null, null, null, null, allTransforms);

for (int i = 0; i < _map.AllParts.Count; i++)
{
    for (int j = 0; j < _map.AllParts[0].Count; j++)
    {            
       spriteBatch.Draw(_map.AllParts[i][j].Texture, _map.AllParts[i][j].Position, null, Color.White, 0, _map.AllParts[i][j].Origin, 1.0f, SpriteEffects.None, 0f);
    }
}

Dies alles funktioniert wieder einwandfrei. Das Problem besteht wiederum darin, dass die Position der Sprite-Gruppe auf dem Bildschirm versetzt wird, wenn eine Drehung festgelegt und der Ursprungspunkt geändert wird.

Ich versuche einen Weg zu finden, um den Ursprungspunkt anzupassen, ohne eine Positionsverschiebung zu verursachen.

BEARBEITEN 2 An dieser Stelle suche ich nach Problemumgehungen, da dies nicht funktioniert. Kennt jemand einen besseren Weg, um eine Gruppe von Sprites in XNA zu drehen? Ich benötige eine Methode, mit der ich den Drehpunkt (Ursprung) ändern kann, ohne die Position der Sprite-Gruppe auf dem Bildschirm zu beeinflussen.

BEARBEITEN 3 Ich denke, wenn ich die Bildschirmkoordinaten an meiner Sprite-Position auf (0,0) zurücksetzen könnte, würde es mir im Wesentlichen ermöglichen, den Ursprung ohne Bewegung neu zu positionieren. Ich brauche im Wesentlichen eine Möglichkeit, die aktuelle Position / Drehung einzustellen und dann von vorne zu beginnen. Weiß jemand, ob es möglich ist, mein Sprite zum neuen Bildschirmursprung zu machen?

URSPRUNG OHNE DREHUNG BEWEGEN:

Ohne Drehung

URSPRUNG MIT DREHUNG BEWEGEN (beachten Sie, wie er sich nach oben verschoben hat):

Mit Rotation


Klingt wie eine Frage , fragte ich vor kurzem: gamedev.stackexchange.com/questions/19297/...
notlesh

Mein Problem ist, dass bei einer Drehung und einer Änderung des Ursprungs die gesamte Sprite-Gruppe auf dem Bildschirm verschoben wird. Wie gehst du anmutig damit um?
Jgallant

Können wir den Bereich Ihres Codes sehen, der trotzbatch.draw aufruft?
ClassicThunder

Wenn Sie sagen, dass sich die Position der Sprite-Gruppe auf dem Bildschirm verschiebt, bleibt der Ursprung dann auf derselben Bildschirmposition? Überprüfen Sie, ob Sie den Punktursprung mit einer visuellen Markierung anzeigen und Screenshots vergleichen können.
ChrisC

Wenn die Drehung 0 ist, verschiebt sich die Position nicht. Das Problem ist, dass die Rotationsmatrix beim Ändern des Rotationsursprungs die Position der Gruppe von Sprites verschiebt, da sie an einer anderen Stelle gedreht wird. Das macht Sinn, aber ich möchte dieses Verhalten vollständig vermeiden.
Jgallant

Antworten:


6

Ich habe dies in meinem World Editor implementiert. Ich kann Sprites gruppieren und drehen oder sie als Gruppe um einen beliebigen Ursprung skalieren (der in meinem Fall auch das Zentrum der Gruppe ist). Ich benutze so etwas:

// Origin should be supplied in World-Space
void RotateGroup(IEnumerable<Sprite> sprites, Vector2 origin, float angle)
{
    Matrix transform =  Matrix.CreateTranslation(-origin.X, -origin.Y, 0f) *
                        Matrix.CreateRotationZ(angle) *
                        Matrix.CreateTranslation(origin.X, origin.Y, 0f);

    foreach(Sprite sprite in sprites)
    {
        sprite.Position = Vector2.Transform(sprite.Position, transform);
        sprite.Rotation += angle;
    }
}

Ich rufe diese Methode einfach auf, wenn ich meine Gruppe als Ganzes drehen möchte, und die Methode berechnet für jedes Sprite eine neue Position und Drehung, um die Illusion zu vermitteln, dass sie sich als Gruppe ändern.

Am wichtigsten ist, dass ich meiner Zeichenfunktion keine spezielle Matrix übergebe. Jedes Sprite hat immer noch seine eigene Position, Rotation und Herkunft, die unabhängig davon sind, ob sie zu einer Gruppe gehören oder nicht.

Dies bedeutet, dass der Ursprung der Gruppe konzeptionell ist und das einfache Ändern dieses Werts Ihre Sprites nicht durcheinander bringt. Der Wert wird nur beim Drehen der Gruppe verwendet, um anzugeben, wo sich der Drehpunkt befinden soll, nicht jedoch beim Zeichnen.

Insgesamt ist die einzige Matrix, die Sie an SpriteBatch.Begin übergeben sollten, Ihre View-Matrix, sonst nichts. Jedes Sprite sollte gemäß seinen individuellen Eigenschaften gezeichnet werden. Wenn Sie sie als Gruppe drehen möchten, spielen Sie mit diesen Eigenschaften und nicht mit dem Zeichencode.


0

Versuchen Sie es zu ändern

spriteBatch.Draw(_map.AllParts[i][j].Texture, _map.AllParts[i][j].Position, null, Color.White, 0, _map.AllParts[i][j].Origin, 1.0f, SpriteEffects.None, 0f);

zu

spriteBatch.Draw(_map.AllParts[i][j].Texture, _map.AllParts[i][j].Position + _map.AllParts[i][j].Origin, null, Color.White, 0, _map.AllParts[i][j].Origin, 1.0f, SpriteEffects.None, 0f);

Das zweite Argument ist, wo sich der Ursprungspunkt befinden sollte. Wenn Sie also den Ursprungspunkt von der Standardeinstellung 0,0 ändern, müssen Sie dies kompensieren.


Die Origin-Eigenschaft hier ist der Ursprung für die Textur, nicht für die Sprite-Gruppe.
Jgallant

0

Warten Sie, Sie möchten alle Sprites gleichzeitig drehen. Ändern Sie dann den Ursprung in Textur.Breite und Textur.Höhe. Und ändern Sie ihn nicht. Ändern Sie einfach die tatsächliche Drehung des Sprites. Und tun Sie dies für alle Sprites .. und stellen Sie die Rotation aller Sprites als einzelne Float-Variable ein .. Vertrauen Sie mir, es funktioniert !!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.