Code Sample: 2D Sprite Rotation in D3D.

wyrd

Senior Contributor
Joined
Aug 23, 2002
Messages
1,405
Location
California
I had to do a lot of hunting and playing around to get this rotation method working properly, so I'm assuming there are others who have yet to figure it out (I don't know about you people, but I'm mathematically challenged, plus the D3D Sprite class isn't exactly documented either).

Basically what I did was created an extension to the sprite class called SpriteEx (maybe I should of called it SpriteX for eXtreme, ooooo!). Using the SpriteEx class is identical to what you'd do with the normal Sprite class, except it also provides a rotation method (plus one more for normal sprites so you don't have to keep tossing in a Vector3 for the center rotation).

However, there is one problem with the SpriteEx class; If you draw one sprite using rotation, you must draw ALL of yoru sprites using rotation. I'm not exactly sure what's going on (as I said, no documentation on the Sprite class), but no doubt someone out there will be able to tell us and tweak the code. Anyway, to draw a non-rotated sprite with a rotated one, use the angle 0.0F (0 degrees).

As for how the rotation is done, I'm hoping the code will speak for itself. I think once you see the math calculations that are involved, it will become quite obvious (especially if you've done regular D3D before).

A sample of how to use the the class + the class itself follows;

Code:
// Quick example.
// texture = D3D texture - your image loaded as a texture.
// src = Source (texture) area to draw.
// pos = Position on the screen in Vector3 format (use 0 for Z-axis).
// angle = Angle in radians to rotate.
// color = System.Drawing.Color to overlay over the sprite (similar to the Photoshop effect).

sprite.Begin(SpriteFlags.AlphaBlend);

sprite.Draw(texture, src, pos, angle, color);

// .. continue to draw more rotated sprites.

sprite.End();

Code:
using System;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Drawing;

namespace Phoenix.Graphics
{
	/// <summary>
	/// Summary description for GameObject.
	/// </summary>
	public class SpriteEx
		: Sprite
	{
    	#region Member Variables

        private readonly Vector3 _zv = new Vector3(0, 0, 0);

        #endregion

    	#region Constructor

    	/// <summary>
        /// Creates a sprite extension.
    	/// </summary>
        /// <param name="device">Device to use.</param>
		public SpriteEx(Device device) : base(device) { }

        #endregion

		#region SpriteEx Methods

        /// <summary>
        /// Adds a sprite to the list of batched sprites.
        /// </summary>
        /// <param name="texture">Texture to draw.</param>
        /// <param name="src">Source area of texture to draw.</param>
        /// <param name="pos">Screen coordinates to draw at.</param>
        /// <param name="color">Overlay color - use white for none.</param>
        public void Draw(Texture texture, Rectangle src, Vector3 pos, Color color)
        {
        	this.Draw(texture, src, _zv, pos, color);
        }

        /// <summary>
        /// Adds a sprite to the list of batched sprites for rotation.
        /// NOTE: If you use this rotation method, all other sprites must also use this
        /// 	rotation method. For sprites that don't need rotation, use 0.0F as the angle.
        /// </summary>
        /// <param name="texture">Texture to draw.</param>
        /// <param name="src">Source area of texture to draw.</param>
        /// <param name="pos">Screen coordinates to draw at.</param>
        /// <param name="angle">Rotation angle (in radians).</param>
        /// <param name="color">Overlay color - use white for none.</param>
        public void Draw(Texture texture, Rectangle src, Vector3 pos, float angle, Color color)
        {
        	// Calculate source center (this is where the sprite is rotated around).
            Vector3 center = new Vector3(src.Width / 2, src.Height / 2, 0);

        	// Rotate and move texture around center.
            Matrix pm = Matrix.Translation(pos.X + center.X, pos.Y + center.Y, pos.Z);
            this.Transform = Matrix.RotationZ(angle) * pm;

            // Add to batched list.
            this.Draw(texture, src, center, _zv, color);
        }

        #endregion
	}
}
 
Back
Top