Rotating Sprites
Xna4.png

Introduction

In previous tutorials, we've seen how to draw sprites. Now we will look at the next step in drawing sprites. In this tutorial, we will see how to rotate sprites. It turns out, once you know the basic way of drawing sprites, drawing sprites that are rotated is actually quite easy.

Preparing the Content

As usual, our first step is to get the content that we want. For this tutorial, we just need one simple image. You can get one of your own, or you can use the one that I will use in this tutorial. It can be found at http://rbwhitaker.wikidot.com/local--files/rotating-sprites-resources/arrow.png. This image is just a simple picture of an arrow, shown below:

arrow.png

Download the file (or get one of your own) and add it to the content of your project like we have done before. Then add the following two lines of code as instance variables at the top of your class:

private Texture2D arrow;
private float angle = 0;

The first variable will store our texture for drawing, and the second will store the current angle of rotation in radians.

Now let's make sure that both of these two variables are set up like we need them to be. Let's add the following line of code in the LoadContent() method to load our sprite into the arrow variable:

arrow = Content.Load<Texture2D>("arrow"); // use the name of your texture here, if you are using your own

Also, we want to update our angle variable so that our angle changes. This way we can see our sprite rotate. So let's go to the Update() method and add the line below:

angle += 0.01f;

This line will change the angle that we are rotating our sprite by, a little bit more each time. Of course, in a real game, we would probably do something fancier with this, like have it based on user input or something. But this will be good enough for what we're doing in this tutorial.

Drawing Rotated Sprites

Alright, the only thing we have left to do now is to actually draw our sprite. We will use a method that is very similar to what we used before. We will use the SpriteBatch.Begin(), then use SpriteBatch.Draw(), and then call SpriteBatch.End() to finish it, just like before. But we will use a different version of the SpriteBatch.Draw() method that is slightly more complicated, but also powerful enough to do sprite rotation. Let's go down to the Draw() method of our game and add the following code:

spriteBatch.Begin();
 
Vector2 location = new Vector2(400, 240);
Rectangle sourceRectangle = new Rectangle(0, 0, arrow.Width, arrow.Height);
Vector2 origin = new Vector2(0, 0);
 
spriteBatch.Draw(arrow, location, sourceRectangle, Color.White, angle, origin, 1.0f, SpriteEffects.None, 1);
 
spriteBatch.End();

You can see that we've used the Begin() and End() methods, just like before. But you'll notice that our Draw() method is quite a bit more complicated. And to make it easier to understand, I've added a few other lines of code. So let's go through them one at a time and see what they do. The first line creates a variable to store the location of where we want to draw our sprite. This is the same as in our earlier tutorial.

The second line stores what is called the source rectangle. This is a rectangle (consisting of the x and y-coordinates of the top left corner, and its width and height) that indicates what part of the texture we want to draw. So, for instance, we could just use a part of the texture if we wanted. But this line says we want the top corner to be at (0, 0) and be the full width and height of the texture. So basically, this line is saying we want a rectangle that covers the entire texture.

The third line is the location in the texture of the origin of our rotation. We will actually come back and look at this in more detail in the next section.

Finally, we get to the command to actually draw the rotated sprite:

spriteBatch.Draw(arrow, location, sourceRectangle, Color.White, angle, origin, 1.0f, SpriteEffects.None, 1);

The first parameter is the texture we want to draw. The second parameter is the location we want to draw at. For this, we are going to use our location variable that we created a couple of lines before. The third parameter is the source rectangle, which we already created. The fourth parameter is the tint color. We are going to have no tint, which is done by using the color white. Next is the rotation angle, which will be our angle variable. The sixth parameter is the origin, which we also already defined, and we'll come back to in a minute. The seventh parameter is the scale factor. A scale factor of 1.0 will keep the scale the same as the original. The eighth parameter says what type of SpriteEffect to use. We don't want a sprite effect, so we'll use SpriteEffect.None, but the other choices are SpriteEffect.FlipHorizonally and SpriteEffect.FlipVertically. Finally, we need to say what the depth of our sprite is. We're just going to use 1.0 for now.

Now we can run our program and see our arrow rotating around, as shown in the screenshot below:

screenshot-1.png

Using a Center Point for Rotation

When you run the program, you may notice that the rotation probably doesn't look quite like you want it. That is because it is rotating wrong! The problem we are having is that the sprite is not rotating around the location we want. I've said twice before that we would come back to the origin variable we defined in our Draw() method. Now's the time.

The origin variable indicates what point we want to rotate around. We've set it up to rotate around (0, 0), which is the top left corner. Instead, if we look at the image, we can see that we really want to rotate around the bottom in the middle. So to fix our problem, all we need to do is adjust our origin so that it is located at the desired point. Change the line in the Draw() method that says:

Vector2 origin = new Vector2(0, 0);

to say:

Vector2 origin = new Vector2(arrow.Width / 2, arrow.Height);

Try running your program again, and you will see that it rotates as we want it to now.

What's Next?

Rotating sprites is very simple. We just need to use a more sophisticated SpriteBatch.Draw() method. If you haven't gone through the Texture Atlas tutorial, that might be a nice place to go next. Otherwise, you might find it useful to look at how to combine 2D and 3D stuff, which can be a little tricky. You will find tutorials for both of these here.


Troubleshooting.png Having problems with this tutorial? Try the troubleshooting page!