7
\$\begingroup\$

I am currently grouping sprites together, then applying a rotation transformation on draw:

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

Where the origin is the Centermost point of my group of sprites. I apply this transformation to each sprite in the group.

My problem is that when I adjust the point of origin, my entire sprite group will re-position itself on screen.

How could I differentiate the point of rotation used in the transformation, from the position of the sprite group? Is there a better way of creating this transformation matrix?

EDIT

Here is the relevant part of the Draw() function:

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

This all works fine, again, the problem is that when a rotation is set and the point of origin is changed, the sprite group's position is offset on screen.

I am trying to figure out a way to adjust the point of origin without causing a shift in position.

EDIT 2 At this point, I'm looking for workarounds as this is not working. Does anyone know of a better way to rotate a group of sprites in XNA? I need a method that will allow me to modify the point of rotation (origin) without affecting the position of the sprite group on screen.

EDIT 3 I think if I was able to reset the screen coordinates to (0,0) at my sprite position, it would essentially allow me to re-position the origin without movement. I essentially need a way to set the current position/rotation, then start from scratch. Does anyone know if it is possible to make my sprite the new screen origin?

MOVING ORIGIN WITHOUT A ROTATION:

Without Rotation

MOVING ORIGIN WITH A ROTATION (notice how it shifted upwards):

With Rotation

\$\endgroup\$
8
  • \$\begingroup\$ Sounds like a question I asked recently: gamedev.stackexchange.com/questions/19297/… \$\endgroup\$
    – notlesh
    Nov 29, 2011 at 18:50
  • \$\begingroup\$ My problem is that when there is a rotation and the origin is modified, the entire sprite group shifts on the screen. How do you handle this gracefully? \$\endgroup\$
    – jgallant
    Nov 29, 2011 at 19:20
  • \$\begingroup\$ Can we see the area of you code that calls spitebatch.draw? \$\endgroup\$ Nov 30, 2011 at 3:35
  • \$\begingroup\$ When you say that the sprite group's position shifts on the screen, does this make the origin stay in the same screen position? See if you can display the point origin with some visual marker and compare screenshots. \$\endgroup\$
    – ChrisC
    Nov 30, 2011 at 15:49
  • \$\begingroup\$ If the rotation is 0 -- the position does not shift. The problem is that when the origin of rotation is changed, the rotation matrix ends up shifting the position of the group of sprites because it is rotated at a different location. This makes sense, but I want to avoid this behavior completely. \$\endgroup\$
    – jgallant
    Nov 30, 2011 at 16:56

3 Answers 3

6
\$\begingroup\$

I've got this implemented on my world editor. I can group sprites together and rotate them or scale them as a group around an arbitrary origin (which in my case is also the center of the group). I use something like this:

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

I simply call this method when I want to rotate my group as a whole, and the method calculates a new position and rotation for each sprite in order to give the illusion that they are changing as a group.

Most importantly, I don't pass any special matrix to my drawing function. Each sprite still has its own individual position, rotation and origin which are independent from them being in a group or not.

This means that the group's origin is conceptual, and simply changing that value won't mess up with your sprites. The value is only used when rotating the group in order to specify where the pivot should be, but not when drawing.

In sum, the only matrix you should be passing to SpriteBatch.Begin is your View matrix, nothing else. Each sprite should be drawn according to its individual properties, and if you'd like to rotate them as a group, play around those properties, not around the drawing code.

\$\endgroup\$
0
\$\begingroup\$

Try changing

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

to

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

The second argument is where the point of origin should be located so if you change the point of origin from the default 0,0 you have to compensate for that.

\$\endgroup\$
1
  • \$\begingroup\$ The Origin property here, is the origin for the Texture, not the Sprite group. \$\endgroup\$
    – jgallant
    Nov 30, 2011 at 11:51
0
\$\begingroup\$

Wait, you want to rotate all sprites at once.. then change the origin to texture.width and texture.height... and dont change it.. just change the actual rotation of the sprite.. and do this for all of the sprites.. and set the rotation of all sprites as a single float variable.. trust me it works!!

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .