Export (0) Print
Expand All

How To: Rotate a Group of Sprites

Demonstrates how to rotate a group of sprites around a single point using a rotation Matrix. It uses two methods. It rotates the sprite positions manually during Update, and it creates a rotation matrix during Update that SpriteBatch can use during Draw.

The Complete Sample

The code in the topic shows you the technique. You can download a complete code sample for this topic, including full source code and any additional supporting files required by the sample.

Drawing a Rotated Group of Sprites

To draw a rotated group of sprites on screen

  1. Follow the steps 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);
    }
    

    Now you need to transform each vector using a rotation matrix created for the rotation angle.

  5. To rotate around the origin, transform each vector relative to the origin by subtracting the origin vector.

  6. 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;
        }
    }
    
  7. 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();
    }
    
  8. When all the sprites have been drawn, call End.

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

  1. Follow the steps 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.

  6. To rotate around a point that is not the upper-left corner of the screen, first subtract the origin of your rotation using a translation matrix.

  7. Multiply that translation matrix by the rotation matrix.

  8. 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);
    }
    
  9. 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();
    }
    
  10. When all the sprites have been drawn, call End.

Community Additions

ADD
Show:
© 2015 Microsoft