|
| 1 | +--- |
| 2 | +title: Rotating a Group of Sprites |
| 3 | +description: Demonstrates how to rotate a group of sprites around a single point. |
| 4 | +requireMSLicense: true |
| 5 | +--- |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +Sometimes either an individual character is made up of many sprites/textures, or you simply want to arrange a group of sprites in a grid and have them move as one. The process is simple enough and simply an extension of what is covered in [HowTo Rotate a Sprite](HowTo_Rotate_Sprite.md). |
| 10 | + |
| 11 | +## Drawing a Rotated Group of Sprites |
| 12 | + |
| 13 | +1. Follow the steps of [Drawing a Sprite](HowTo_Draw_A_Sprite.md). |
| 14 | + |
| 15 | +2. Create one array of [Vector2](xref:Microsoft.Xna.Framework.Vector2) variables that represent the un-rotated positions of the sprites and another to hold the rotated values. |
| 16 | + |
| 17 | + ```csharp |
| 18 | + private Vector2[] myVectors; |
| 19 | + private Vector2[] drawVectors; |
| 20 | + protected override void Initialize() |
| 21 | + { |
| 22 | + myVectors = new Vector2[9]; |
| 23 | + drawVectors = new Vector2[9]; |
| 24 | + |
| 25 | + base.Initialize(); |
| 26 | + } |
| 27 | + ``` |
| 28 | + |
| 29 | +3. After loading the sprite, calculate the positions of the un-rotated group of sprites based on the sprite's size. |
| 30 | + |
| 31 | + ```csharp |
| 32 | + private Texture2D spriteTexture; |
| 33 | + private Vector2 spriteOrigin; |
| 34 | + private Vector2 spritePosition; |
| 35 | + protected override void LoadContent() |
| 36 | + { |
| 37 | + // Create a new SpriteBatch, which can be used to draw textures. |
| 38 | + _spriteBatch = new SpriteBatch(GraphicsDevice); |
| 39 | + |
| 40 | + spriteTexture = Content.Load<Texture2D>("Character"); |
| 41 | + viewport = _graphics.GraphicsDevice.Viewport; |
| 42 | + spriteOrigin.X = spriteTexture.Width / 2; |
| 43 | + spriteOrigin.Y = spriteTexture.Height / 2; |
| 44 | + spritePosition.X = viewport.Width / 2; |
| 45 | + spritePosition.Y = viewport.Height / 2; |
| 46 | + |
| 47 | + // Populate the `myVectors` array with a grid of Vector2 positions for the character to draw. These will then be rotated around the center of the screen. |
| 48 | + int i = 0; |
| 49 | + while (i < 9) |
| 50 | + { |
| 51 | + for (int x = 0; x < 3; x++) |
| 52 | + { |
| 53 | + for (int y = 0; y < 3; y++) |
| 54 | + { |
| 55 | + myVectors[i] = new Vector2(x * 200, y * 200); // Assign positions |
| 56 | + i++; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + ``` |
| 62 | + |
| 63 | +4. In your [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_) method, copy the un-rotated vectors and determine the screen position around which all the sprites will rotate. |
| 64 | + |
| 65 | + ```csharp |
| 66 | + private float rotationAngle = 0f; |
| 67 | + private Matrix rotationMatrix = Matrix.Identity; |
| 68 | + protected override void Update(GameTime gameTime) |
| 69 | + { |
| 70 | + if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) |
| 71 | + Exit(); |
| 72 | + |
| 73 | + // The time since Update was called last. |
| 74 | + float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; |
| 75 | + |
| 76 | + // TODO: Add your game logic here. |
| 77 | + rotationAngle += elapsed; |
| 78 | + float circle = MathHelper.Pi * 2; |
| 79 | + rotationAngle %= circle; |
| 80 | + |
| 81 | + // Copy and rotate the sprite positions. |
| 82 | + drawVectors = (Vector2[])myVectors.Clone(); |
| 83 | + |
| 84 | + RotatePoints(ref spritePosition, rotationAngle, ref drawVectors); |
| 85 | + |
| 86 | + base.Update(gameTime); |
| 87 | + } |
| 88 | + ``` |
| 89 | + |
| 90 | + Transform each vector using a rotation matrix created for the rotation angle. |
| 91 | + |
| 92 | +5. To rotate around the origin, transform each vector relative to the origin by subtracting the origin vector. |
| 93 | + |
| 94 | +6. Add the origin vector to the transformed vector to create the final rotated vector. |
| 95 | + |
| 96 | + ```csharp |
| 97 | + private static void RotatePoints(ref Vector2 origin, float radians, ref Vector2[] Vectors) |
| 98 | + { |
| 99 | + Matrix myRotationMatrix = Matrix.CreateRotationZ(radians); |
| 100 | + |
| 101 | + for (int i = 0; i < 9; i++) |
| 102 | + { |
| 103 | + // Rotate relative to origin. |
| 104 | + Vector2 rotatedVector = |
| 105 | + Vector2.Transform(Vectors[i] - origin, myRotationMatrix); |
| 106 | + |
| 107 | + // Add origin to get final location. |
| 108 | + Vectors[i] = rotatedVector + origin; |
| 109 | + } |
| 110 | + } |
| 111 | + ``` |
| 112 | + |
| 113 | +7. Draw each sprite using the rotated vectors as screen locations. |
| 114 | + |
| 115 | + ```csharp |
| 116 | + protected override void Draw(GameTime gameTime) |
| 117 | + { |
| 118 | + GraphicsDevice.Clear(Color.CornflowerBlue); |
| 119 | + |
| 120 | + // TODO: Add your drawing code here |
| 121 | + _spriteBatch.Begin(); |
| 122 | + for (int i = 0; i < drawVectors.Length; i++) |
| 123 | + { |
| 124 | + _spriteBatch.Draw(spriteTexture, drawVectors[i], null, |
| 125 | + Color.White, rotationAngle, spriteOrigin, 1.0f, |
| 126 | + SpriteEffects.None, 0f); |
| 127 | + } |
| 128 | + _spriteBatch.End(); |
| 129 | + |
| 130 | + base.Draw(gameTime); |
| 131 | + } |
| 132 | + ``` |
| 133 | + |
| 134 | +8. When all the sprites have been drawn, call [SpriteBatch.End](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_End). |
| 135 | + |
| 136 | + This results in the Grid of characters that are drawn being rotated `Together` around a position in the center of the screen, instead of each sprite rotating individually. |
| 137 | + |
| 138 | +## See Also |
| 139 | + |
| 140 | +- [Drawing a Sprite](HowTo_Draw_A_Sprite.md) |
| 141 | + |
| 142 | +### Concepts |
| 143 | + |
| 144 | +- [What Is a Sprite?](../../whatis/graphics/WhatIs_Sprite.md) |
| 145 | + |
| 146 | +### Reference |
| 147 | + |
| 148 | +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) |
| 149 | +- [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) |
| 150 | +- [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) |
0 commit comments