スプライトのグループの回転の原点を調整するにはどうすればよいですか?


7

現在、スプライトをグループ化して、描画に回転変換を適用しています。

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

ここで、原点は私のスプライトグループの中心点です。この変換をグループ内の各スプライトに適用します。

私の問題は、原点を調整すると、スプライトグループ全体が画面上で再配置されることです。

変換で使用される回転のポイントを、スプライトグループの位置とどのように区別できますか?この変換行列を作成するより良い方法はありますか?

編集

次に、Draw()関数の関連部分を示します。

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);
    }
}

これはすべて正常に機能しますが、問題は、回転が設定され、原点が変更されると、スプライトグループの位置が画面上でオフセットされることです。

私は、位置を変えずに原点を調整する方法を見つけようとしています。

編集2 現在のところ、これが機能していないため、回避策を探しています。XNAでスプライトのグループを回転させるより良い方法を誰かが知っていますか?画面上のスプライトグループの位置に影響を与えずに回転ポイント(原点)を変更できる方法が必要です。

編集3 スプライトの位置で画面座標を(0,0)にリセットできれば、基本的に移動せずに原点を再配置できると思います。基本的に、現在の位置/回転を設定して、最初から始める方法が必要です。私のスプライトを新しい画面の原点にすることが可能かどうか誰かが知っていますか?

回転せずに原点を移動:

回転なし

回転による原点の移動(上方向への移動方法に注意してください):

回転あり


:質問のように聞こえるが、私は最近尋ねgamedev.stackexchange.com/questions/19297/...
notlesh

私の問題は、回転があり、原点が変更されると、スプライトグループ全体が画面上でシフトすることです。これをどのように適切に処理しますか?
jgallant

spitebatch.drawを呼び出すコードの領域を確認できますか?
ClassicThunder

スプライトグループの位置が画面上でシフトすると言うと、原点が同じ画面位置に留まりますか?視覚的なマーカーでポイントの原点を表示できるかどうかを確認し、スクリーンショットを比較します。
ChrisC、2011年

回転が0の場合、位置は移動しません。問題は、回転の原点が変更されると、スプライトのグループが別の場所で回転されるため、回転行列がスプライトのグループの位置をシフトしてしまうことです。これは理にかなっていますが、私はこの動作を完全に回避したいと思います。
jgallant

回答:


6

私はこれを私の世界のエディターに実装しました。スプライトをグループ化して回転させたり、任意の原点(私の場合はグループの中心でもあります)を中心にグループとしてスケーリングしたりできます。私はこのようなものを使用します:

// 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;
    }
}

グループ全体を回転させたい場合は、このメソッドを呼び出すだけです。このメソッドは、スプライトごとに新しい位置と回転を計算し、グループとして変化しているように見せます。

最も重要なのは、描画関数に特別な行列を渡さないことです。各スプライトには、グループ内にあるかどうかに関係なく、独自の位置、回転、原点があります。

つまり、グループの起源は概念的なものであり、その値を変更するだけではスプライトに影響を与えません。この値は、グループの回転時にピボットの位置を指定するためにのみ使用され、描画時には使用されません。

要するに、SpriteBatch.Beginに渡す必要がある唯一のマトリックスはViewマトリックスだけで、他には何もありません。各スプライトは、個々のプロパティに従って描画する必要があります。グループとして回転させる場合は、描画コードではなく、それらのプロパティを操作してください。


0

変更してみてください

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);

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);

2番目の引数は、原点を配置する場所です。原点をデフォルトの0,0から変更する場合は、それを補正する必要があります。


ここのOriginプロパティは、スプライトグループではなく、テクスチャの原点です。
jgallant

0

ちょっと待って、すべてのスプライトを一度に回転させたいと思います。次に、原点をtexture.widthとtexture.height ...に変更し、変更しないでください。スプライトの実際の回転を変更するだけです。スプライト..そして、すべてのスプライトの回転を単一のfloat変数として設定します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.