Question

I am working with XNA 3.0 and attempting to make a sprite class, but am unsure how to approach it. Do I perform the animation within the sprite class? I also keep receiving an error with my code

Game1.cs

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();
        Sprite.Draw(spriteBatch);
        base.Draw(gameTime);
    }

Sprite.cs

private static Texture2D rings;

    Point rings_frameSize = new Point(75, 75);
    Point rings_currentFrame = new Point(0, 0);
    Point rings_sheetSize = new Point(6, 8);

    int ms_elapsedRings = 0;

    public static void setup_sprites(ContentManager Content)
    {
        rings = Content.Load<Texture2D>("Images/threerings");
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(rings,
                         new Vector2(0,0),
                         new Rectangle(rings_currentFrame.X * rings_frameSize.X, //X component of where to begin
                                       rings_currentFrame.Y * rings_frameSize.Y, //Y component of where to begin
                                       rings_frameSize.X,  //cell width
                                       rings_frameSize.Y), //cell height
                         Color.White,
                         0,
                         Vector2.Zero,
                         1,
                         SpriteEffects.None,
                         0);
    }

which returns

Error 1 An object reference is required for the non-static field, method, or property 'WindowsGame1.Sprite.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch)' C:\Users\XXXXXX\Documents\Visual Studio 2008\Projects\WindowsGame1\WindowsGame1\Game1.cs 107 13 WindowsGame1

Was it helpful?

Solution

First, your second error: "An object reference is required for the non-static field, method, or property".

In object-oriented programming, programs have the benefit of structure, through concepts like classes, and inheritance, as opposed to historical imperative programming, in which "programs" consisted of a series of basic instructions, one after the other. In object-oriented programming, an class represents some abstract entity. Such entities could be an animal, a car, a TV. In such cases, it makes sense that you can write a class Car and "create" many "instances" of Car objects, one of which might be called Honda, another BMW, and another Rolls-Royce. But sometimes, it doesn't make sense to create instances of a class. What if your class wasn't a car - what if it was "Math". It's perfectly valid to have a "Math" class - in fact, the .NET framework has a Math class. But in such a case, it wouldn't make sense to have "instances" of Math. Math is math. It's a study - and there's only one of it.

So, non-static methods are accessed like so:

Car honda = new Car();
honda.Drive();

It doesn't make sense to say Car.Drive(), because which car are you referring to? Car, as a class, is only a general blueprint - you want to call new Car() to make some concrete objects out of that class blueprint.

Static methods are accessed, on the other hand, like so:

Math.Add();

It doesn't make sense to say Math myMath = new Math();, that's why Math is its own static class.

Now, you've made your method setup_sprites() static. You may be thinking that this setup method should be static because, no matter how many thousands of sprites are created, each created sprite will be accessing the same texture during setup. If you want to make your sprite class this way, that's fine - but you've got to make your entire sprite class static then, because static methods and variables cannot access non-static methods and variables.

Generally, Sprite classes are not made static though. You can read more on static vs non-static here: http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx.

Now, your first question. How you integrate animation into your code is entirely up to you. It looks like you're embedding the animation code within your Draw() method. This isn't wrong, but there may be better solutions.

Object-oriented programming has a few principles to keep complexity elegantly simple, and one of them is the Single Responsibility Principle, which, in simple terms, recommends that a programmer give one class just one responsibility. Your Sprite class should simply load its resources, draw itself, and unload its resources. That's all a sprite should do.

But what about animation? Here's where object-oriented programming comes in - split up that responsibility; you don't have to stick everything into the Sprite class. You have two choices: you can either extend your Sprite functionality in the form of an AnimatedSprite class which inherits from the Sprite class, or you can extend your Sprite functionality in the form of an Animatable interface. The design question here is: extension by class or interface?

You can read more about the debate here: http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface

What I really enjoyed from that article was the following definition: abstract classes define core functions, while interfaces describe peripheral attributes.

Your sprite can not only animate, but also move. Those sound more like attributes rather than core functionality. It has the ability to animate. It has the ability to move. Some people think of interfaces as having a "has-a" relationship, whereas classes are thought of as having a "is-a" relationship. Your class isn't essentially an animation - it is first and foremost a sprite. It then has the ability to animate.

So I think you should go extend your Sprite class by adding an Animatable interface. You actually want to call it IAnimatable, to preserve naming standards.

So you might end up with something like this (pseudocode):

public class Sprite : IAnimatable
{
    private Texture2D rings;

    public void LoadContent(ContentManager Content)
    {
        // Call this method from Game.LoadContent()
        rings = Content.Load<Texture2D>("Images/threerings");
    }

public void Draw(SpriteBatch spriteBatch)
    {
        if (IsAnimating)
        {
            // Incorporate IAnimatable variables here to draw your animation
        }
    }

}

public interface IAnimatable
{
    public bool IsAnimating {get; set;}
    public int CurrentFrameIndex {get; set;}
    public Point FrameSize {get; set;}
}

And in the future, you may even have:

public interface IMovable
{
    public bool IsMoving {get; set;}
    public Point CurrentLocation {get; set;}
    public Point DestinationLocation {get; set;}
}

and integrate all this into:

public class NpcSprite : Sprite, IMovable, IAnimatable
{
}

It's true that, even using interfaces, you still end up writing the interface code in your Sprite class, but at least you've established an explicit contract between sprites, animatable sprites, and movable sprites. It will be much easier to edit and extend later on.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top