Game Engine Tutorial Part IV, Section 3 – Sprite Effects
Right now our Sprite class can only place an image at a specified location on screen. The SpriteBatch class, however, provides much more flexibility than that, so let’s take advantage of it with our Sprite class.
The effects we are interested in are as follows:
- Origin/Rotation: These two properties allow us to specify an “origin” point, around which the sprite is rotated. This is generally the center of the image, but it could be placed anywhere to achieve some interesting effects. For example, the origin of the blades of a wind mill could be placed at the blade’s edge, so that it would be rotated in a circular fashion.
- Scale: This property is fairly self explanatory, determining the change in size between the original image and the drawn image.
- SourceRectangle: The SourceRectangle determines the area of the original texture that will be sampled and drawn onto the screen. This is useful for drawing spritesheets, which place numerous sprites in the same image, to be cut out later by the graphics card. Using a sprite sheet provides a performance boost as the graphics card doesn’t have to constantly load different textures into memory.
- SpriteEffects: This property can be used to flip the image vertically, horizontally, or both. For example, a sprite representing the player controlled character can be flipped back and forth to better reflect the direction of movement.
Let’s start by adding these properties to the Sprite class:
public Vector2 Origin { get; set; }
public float Rotation { get; set; }
public Rectangle SourceRectangle { get; set; }
public float Scale { get; set; }
public SpriteEffects Effects { get; set; }
Next we’ll modify the constructor to accept a rotation value (note that this is defined in radians) and initialize these values:
public Sprite(float x, float y, float rotation, string filename)
{
this.position = new Vector2(x, y);
this.filename = filename;
Origin = Vector2.Zero;
Rotation = rotation;
SourceRectangle = new Rectangle();
Scale = 1;
Effects = SpriteEffects.None;
}
We’ll also modify the Load() function to intialize the Origin and SourceRectangle properties, as they need to know the dimensions of the sprite texture:
protected override void Load()
{
spriteTexture = Parent.Engine.Content.Load<Texture2D>(filename);
Origin = new Vector2(spriteTexture.Width / 2f,
spriteTexture.Height / 2f);
SourceRectangle = new Rectangle(0, 0, spriteTexture.Width,
spriteTexture.Height);
}
Keep in mind that these values are set when the sprite is added to a GameScreen for the first time. Thus, if the values are modified before the sprite is added to a GameScreen, the changes will be overwritten. So, you should always set the Origin and SourceRectangle properties AFTER the Sprite has been added to the GameScreen and loaded for the first time.
Finally, we can update the Draw() function to utilize these values:
public override void Draw()
{
Parent.Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
SpriteSortMode.Deferred, SaveStateMode.None);
Parent.Engine.SpriteBatch.Draw(spriteTexture, position,
SourceRectangle, Color.White, Rotation, Origin, Scale, Effects, 0);
Parent.Engine.SpriteBatch.End();
// Set back certain render states that are changed by the SpriteBatch
// that interfere with 3D rendering
resetRenderStates();
}
To demonstrate these effects, the following settings produce the output below:
protected override void LoadContent()
{
engine = new Engine(graphics);
GameScreen screen = new GameScreen();
engine.PushGameScreen(screen);
Sprite sprite = new Sprite(320, 370, MathHelper.ToRadians(45), "Content/puppy");
screen.AddComponent(sprite);
sprite.SourceRectangle = new Rectangle(50, 40, 160, 150);
sprite.Scale = 2f;
sprite.Effects = SpriteEffects.FlipHorizontally;
}

[...] Game Engine Tutorial Part IV, Section 3 – Sprite Effects [...]
Awesome tutorial! Thanks Sean.
Thanks a lot for this tuto.
By the way I have some questions:
Is there a reason to use direct accessor like this ?:
public float Rotation { get; set; }
Personnaly, I find more clean to use a private member like mRotation and use a public accessor to access it.
But I don’t know if it’s a good think when making games.
Waiting for the next tuto now ^^
There is no end difference, it is just a short cut for writing code and organizing it.