Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

How To: Rotate a Group of Sprites

This article demonstrates how to rotate a group of sprites around a single point using a rotation Matrix. It uses two methods; rotating the sprite positions manually during Update, and creating a rotation matrix during Update that SpriteBatch can use during Draw.

The Complete Sample

The code in this tutorial illustrates the technique described in the text. A complete code sample for this tutorial is available for you to download, including full source code and any additional supporting files required by the sample.

To draw a rotated group of sprites on screen

  1. Follow steps 1–4 of How To: Draw a Sprite.
  2. Create one set of Vector2 objects that represents the unrotated positions of the sprites, and one set to hold the rotated values.

    private Vector2[] myVectors;
    private Vector2[] drawVectors;
    protected override void Initialize()
    {
        myVectors = new Vector2[9];
        drawVectors = new Vector2[9];
    
        base.Initialize();
    }
    
  3. After loading the sprite, calculate the positions of the unrotated group of sprites based on the sprite's size.

    private Texture2D SpriteTexture;
    private Vector2 origin;
    private Vector2 screenpos;
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
    
        SpriteTexture = Content.Load<Texture2D>("ship");
        origin.X = SpriteTexture.Width / 2;
        origin.Y = SpriteTexture.Height / 2;
        Viewport viewport = graphics.GraphicsDevice.Viewport;
        screenpos.X = viewport.Width / 2;
        screenpos.Y = viewport.Height / 2;
    }
    
  4. In your Update method, copy the unrotated vectors and determine the screen position around which all the sprites will rotate.

    private float RotationAngle = 0f;
    private bool batchAutoRotate = false;
    private Matrix rotationMatrix = Matrix.Identity;
    protected override void Update(GameTime gameTime)
    {
        ...
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
    
        RotationAngle += elapsed;
        float circle = MathHelper.Pi * 2;
        RotationAngle = RotationAngle % circle;
    
        // Copy and rotate the sprite positions.
        drawVectors = (Vector2[])myVectors.Clone();
    
        if (!batchAutoRotate)
            RotatePoints(ref screenpos, RotationAngle, ref drawVectors);
        else
            UpdateMatrix(ref screenpos, RotationAngle);
    
        base.Update(gameTime);
    }
    
  5. Transform each vector using a rotation matrix created for the rotation angle. To rotate around the origin, transform each vector relative to the origin by subtracting the origin vector. Then add the origin vector to the transformed vector to create the final rotated vector.

    private static void RotatePoints(ref Vector2 origin, float radians, ref Vector2[] Vectors)
    {
        Matrix myRotationMatrix = Matrix.CreateRotationZ(radians);
    
        for (int i = 0; i < 9; i++)
        {
            // Rotate relative to origin.
            Vector2 rotatedVector = Vector2.Transform(Vectors[i] - origin, myRotationMatrix);
    
            // Add origin to get final location.
            Vectors[i] = rotatedVector + origin;
        }
    }
    
  6. Draw each sprite using the rotated vectors as screen locations.

    private void DrawPoints()
    {
        // Draw using manually rotated vectors
        spriteBatch.Begin();
        for (int i = 0; i < drawVectors.Length; i++)
            spriteBatch.Draw(SpriteTexture, drawVectors[i], null, Color.White, RotationAngle,
                origin, 1.0f, SpriteEffects.None, 0f);
        spriteBatch.End();
    }
    
  7. When all the sprites have been drawn, call End.

To draw a rotated group of sprites on screen using SpriteBatch transformation

  1. Follow steps 1–4 of How To: Draw a Sprite.
  2. Create one set of Vector2 objects that represents the unrotated positions of the sprites, and one set to hold the rotated values.

    private Vector2[] myVectors;
    private Vector2[] drawVectors;
    protected override void Initialize()
    {
        myVectors = new Vector2[9];
        drawVectors = new Vector2[9];
    
        base.Initialize();
    }
    
  3. After loading the sprite, calculate the positions of the unrotated group of sprites based on the sprite's size.

    private Texture2D SpriteTexture;
    private Vector2 origin;
    private Vector2 screenpos;
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
    
        SpriteTexture = Content.Load<Texture2D>("ship");
        origin.X = SpriteTexture.Width / 2;
        origin.Y = SpriteTexture.Height / 2;
        Viewport viewport = graphics.GraphicsDevice.Viewport;
        screenpos.X = viewport.Width / 2;
        screenpos.Y = viewport.Height / 2;
    }
    
  4. In your Update method, copy the unrotated vectors and determine the screen position around which all the sprites will rotate.

    private float RotationAngle = 0f;
    private bool batchAutoRotate = false;
    private Matrix rotationMatrix = Matrix.Identity;
    protected override void Update(GameTime gameTime)
    {
        ...
        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
    
        RotationAngle += elapsed;
        float circle = MathHelper.Pi * 2;
        RotationAngle = RotationAngle % circle;
    
        // Copy and rotate the sprite positions.
        drawVectors = (Vector2[])myVectors.Clone();
    
        if (!batchAutoRotate)
            RotatePoints(ref screenpos, RotationAngle, ref drawVectors);
        else
            UpdateMatrix(ref screenpos, RotationAngle);
    
        base.Update(gameTime);
    }
    
  5. Create a rotation matrix for SpriteBatch to use during Draw. To rotate around a point that is not the upper-left corner of the screen, you must first subtract the origin of your rotation using a translation matrix, then multiply that translation matrix by the rotation matrix, and multiply the result by a translation matrix adding the origin of your rotation. This is because a rotation matrix must rotate around (0,0,0).

    private void UpdateMatrix(ref Vector2 origin, float radians)
    {
        // Translate sprites to center around screen (0,0), rotate them, and
        // translate them back to their original positions
        Vector3 matrixorigin = new Vector3(origin, 0);
        rotationMatrix = Matrix.CreateTranslation(-matrixorigin) *
            Matrix.CreateRotationZ(radians) *
            Matrix.CreateTranslation(matrixorigin);
    }
    
  6. In your Draw method, call SpriteBatch.Begin, specifying your rotation matrix as the fourth parameter.

    private void DrawMatrix()
    {
        // Draw using a rotation matrix with SpriteBatch
        spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred,
            SaveStateMode.None, rotationMatrix);
        for (int j = 0; j < myVectors.Length; j++)
            spriteBatch.Draw(SpriteTexture, myVectors[j], null, Color.White, 0,
                origin, 1.0f, SpriteEffects.None, 0f);
        spriteBatch.End();
    }
    
  7. When all the sprites have been drawn, call End.

Community Additions

ADD
Show:
© 2015 Microsoft