Creating a User-Controlled Sprite Class

Now you'll create a class that derives from your base Sprite class, adding functionality to let the user control the sprite. Add a new class to your project by right-clicking on the project in Solution Explorer and selecting Add → Class. Name the new class file UserControlledSprite.cs. Once the file is ready, mark this class as a subclass of the Sprite class:

class UserControlledSprite: Sprite

Next, you'll need to add some XNA using statements. Use the same ones as you did in the Sprite base class, plus an additional one (Microsoft.Xna.Framework.Input) that will allow you to read data from input devices:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

Next, add the constructors for the UserControlledSprite class. These will be basically the same as the constructors for the Sprite class and will just pass the parameters on to the base class:

public UserControlledSprite(Texture2D textureImage, Vector2 position,
    Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
    Vector2 speed)
    : base(textureImage, position, frameSize, collisionOffset, currentFrame,
    sheetSize, speed)
{
}


public UserControlledSprite(Texture2D textureImage, Vector2 position,
    Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
    Vector2 speed, int millisecondsPerFrame)
    : base(textureImage, position, frameSize, collisionOffset, currentFrame,
    sheetSize, speed, millisecondsPerFrame)
{
}

Then, you need to add the code for the overloaded direction property. The direction property will be used in the Update method to modify the position of the sprite (or in other words, to move the sprite in the direction indicated by this property). Direction in the case of the UserControlledSprite class will be defined as a combination of the speed member of the base class and the direction in which the player is pressing the gamepad's left thumbstick, or the arrow keys the user is pressing.

Users will also be able to control the sprite using the mouse, but mouse input will be handled a bit differently. When the mouse is being used to control the sprite, you are going to move the sprite to the position of the mouse on the screen. So, there's really no need for a direction property when dealing with mouse movement. This property, therefore, will only reflect player input from the keyboard or the Xbox 360 gamepad. To build the direction property from the data read from the thumbstick and keyboard, code the property as follows:

public override Vector2 direction
{
    get
    {
        Vector2 inputDirection = Vector2.Zero;

        if (Keyboard.GetState(  ).IsKeyDown(Keys.Left))
            inputDirection.X −= 1;
        if (Keyboard.GetState(  ).IsKeyDown(Keys.Right))
            inputDirection.X += 1;
        if (Keyboard.GetState(  ).IsKeyDown(Keys.Up))
            inputDirection.Y −= 1;
        if (Keyboard.GetState(  ).IsKeyDown(Keys.Down))
            inputDirection.Y += 1;

        GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
        if(gamepadState.ThumbSticks.Left.X != 0)
            inputDirection.X += gamepadState.ThumbSticks.Left.X;
        if(gamepadState.ThumbSticks.Left.Y != 0)
            inputDirection.Y -= gamepadState.ThumbSticks.Left.Y;

        return inputDirection * speed;
    }
}

This property will return a Vector2 value indicating the movement direction (in the X and Y planes), multiplied by the speed member of the base class. Notice that the keyboard and gamepad inputs are combined, allowing the player to control the sprite with either input device.

To deal with mouse movement, you're essentially going to detect whether the mouse has moved from frame to frame. If so, you'll assume that the user wants to control the sprite with the mouse, and move the sprite to the location of the mouse cursor. If the mouse does not move from one frame to another, the keyboard and gamepad input will affect the movement of the sprite.

To determine whether the mouse has moved from one frame to the next, add the following class-level variable to your UserControlledSprite class:

MouseState prevMouseState;

Now you can go ahead and code the Update method of your UserControlledSprite class. You'll need to override the Update method from the base class and add to that method the code that will move the sprite based on the direction property as well as mouse movement (if the mouse has been moved). In addition, you'll add some logic in that method to keep the user-controlled sprite in play if the sprite is moved off the screen. Your Update method should look like this:

public override void Update(GameTime gameTime, Rectangle clientBounds)
{
    // Move the sprite according to the direction property
    position += direction;

    // If the mouse moved, set the position of the sprite to the mouse position
    MouseState currMouseState = Mouse.GetState(  );
    if (currMouseState.X != prevMouseState.X ||
        currMouseState.Y != prevMouseState.Y)
    {
        position = new Vector2(currMouseState.X, currMouseState.Y);
    }
    prevMouseState = currMouseState;

    // If the sprite is off the screen, put it back in play
    if (position.X < 0)
        position.X = 0;
    if (position.Y < 0)
        position.Y = 0;
    if (position.X > clientBounds.Width - frameSize.X)
        position.X = clientBounds.Width - frameSize.X;
    if (position.Y > clientBounds.Height - frameSize.Y)
        position.Y = clientBounds.Height - frameSize.Y;

    base.Update(gameTime, clientBounds);
}

There you have it—your UserControlledSprite class is ready to go! You don't have to do anything with the Draw method in this class because your base class will take care of drawing the individual frames of your sprite. Nice job!

Get Learning XNA 3.0 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.