Tuesday, November 8, 2016

rotation - Understanding SpriteBatch.Draw overload XNA


I'm talking about the
public void Draw (Texture2D texture, Vector2 position, Nullable sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) method.


My Sprite has Scaling, Position and Rotation. I want it to rotate from the center, towards the mouse.


This is the method I've tried using so far:



public void RotateTo(Vector2 point)
{
var angle = AngleBetween(Position, point);
Rotation = MathHelper.ToRadians((float)angle);
}
public static double AngleBetween(Vector2 first, Vector2 second)
{
double sin = first.X * second.Y - second.X * first.Y;
double cos = first.X * second.X + first.Y * second.Y;
return Math.Atan2(sin, cos) * (180 / Math.PI);

}

But as you can imagine, this didn't work well. First of all, the origin of the sprite wasn't the center. I've tried changing the origin parameter in the Draw method to sprite.Texture.Bounds.Center.ToVector() (ToVector is an extention method) but that also didn't work. The sprite was rotating in a weird way, not focusing around the mouse, because it seemed that the sprite was rotating around a different center point, not the mouse itself.


I didn't manage to find in depth explanations about SpriteBatch.Draw, so I hoped someone here would have the knowledge and experience to help me.


Thanks for reading, and thanks in advance for the help!



Answer



Basic explaination about the method with regards to positioning, scaling and rotating:


This draws a sprite with myTexture with the topleft corner on 100,200:


sprite.Draw (myTexture, new Vector2(100,200), null, Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0);


This draws a sprite with myTexture with the center on 100,200:


sprite.Draw (myTexture, new Vector2(100,200), null, Color.White, 0, new Vector2(myTexture.Width/2,myTexture.Height/2), 1, SpriteEffects.None, 0);

This draws a sprite with myTexture with the center on 100,200, rotated 90 degrees:


sprite.Draw (myTexture, new Vector2(100,200), null, Color.White, MathHelper.PiOver2, new Vector2(myTexture.Width/2,myTexture.Height/2), 1, SpriteEffects.None, 0);

This draws a sprite with myTexture with the center on 100,200, rotated 90 degrees, scaled to half the size:


sprite.Draw (myTexture, new Vector2(100,200), null, Color.White, MathHelper.PiOver2, new Vector2(myTexture.Width/2,myTexture.Height/2), 0.5f, SpriteEffects.None, 0);

Added clarification:



The origin determines two things:




  1. The position of the sprite in relation to the position parameter in the Draw call.




  2. The center of rotation for the rotation parameter.




  3. The center of scaling.





The green dot in the image below represents the 'origin' parameter. From the examples given above the center is given in the number of pixels in relation to the top left corner of the sprite. If the grey box in the image has a size 100 x 100 pixels: the center would be 50,50 and the rightmost example (origin outside the sprite) would be 125,50.


Rotation of boxes in relation to the origin


The blue box is an indicator of where the box was without rotation or scaling. As you can see, the box is rotated 45 degrees in all three images. However, where the result ends up is different. The center of rotation is based on the origin and the box is rotated in relation to that point.


With regards to scaling; setting the scale to 0.5f would in all three images result in a box half the original size. Also where it ends up will be different due to the center of scale being relative to the origin, as shown in the image below.


Scaled sprites with different origins


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...