Search code examples
c#xna

How to load sprite from another class and change it on input XNA


I am just learning XNA and i have some basic questions.

  1. Let's say I have class Car and want to load/draw sprites. How should I do it? Xna created methods for that but they are in Game class.

  2. After I deal with loading my sprite using custom class my class to have 3 states and depending on state. I want it to draw different sprite. I would like to have them all loaded in array of Texture2d.


Solution

  • As you said, these methods are in the Game class and unless you change radically how things work, you'll have to get used to that fact.

    However, as soon as you inherit from DrawableGameComponent (which all your game objects should do if you want them to draw/update), you'll see that all your objects need to have that Game class passed to them in the constructor anyway because of their base class. You can then use it from there to load your textures :

    public class Car : DrawableGameComponent
    {
        private Texture2D texture;
    
        public Car(Game game) : base(game)
        {
            texture = game.Content.Load<Texture2D>("mytexture");
        }
    }
    

    Or hold a reference to it and load them later. This also means somewhere in your Game1.cs you have something like

    Car car = new Car(this);
    

    or, if you're loading it from an other file, that file need to know your Game class in order to create your car.

    To draw the sprites, simply use the

    public override void Draw(GameTime gameTime)
    

    method of DrawableGameComponent.


    If you want to make it less painful, you could still create a static class that holds your Game class (and possibly your SpriteBatch, as it will be quite useful) :

    public static class GameHolder
    {
        public static Game Game { get; set; }
    }
    

    So your game components can be created like this :

    public class Car : DrawableGameComponent
    {
        private Texture2D texture;
    
        public Car() : base(GameHolder.Game)
        {
            texture = GameHolder.Game.Content.Load<Texture2D>("mytexture");
        }
    }
    

    And don't forget to feed the Game value from your Game1 class :

    public class Game1 : Game
    {
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            GameHolder.Game = this;
        }
    }
    

    To handle states, you can indeed load them all in an array and print one of them. To remove the logic from the Draw method, you can also use an other Texture2D that will hold the current sprite you want to render.

    public class Car : DrawableGameComponent
    {
        private List<Texture2D> states;
        private Texture2D currentState;
        private SpriteBatch spriteBatch;
    
        public Car(Game game, SpriteBatch sb) : base(GameHolder.Game)
        {
            states.Add(game.Content.Load<Texture2D>("state1"));
            states.Add(game.Content.Load<Texture2D>("state2"));
            states.Add(game.Content.Load<Texture2D>("state3"));
            currentState = states[0];
            spriteBatch = sb;
        }
        public override void Update(GameTime gameTime)
        {
            if (someCondition)
            {
                currentState = states[0];
            }
            else if (someOtherCondition)
            {
                currentState = states[1];
            }
            else if (moreConditions)
            {
                currentState = states[2];
            }
    
            base.Update(gameTime);
        }
    
        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Draw(currentState, new Vector2(0,0), Color.White);
    
            base.Draw(gameTime);
        }
    }
    

    As you can see, the Draw method don't really care you have multiple states to handle.


    If you need a detailed tutorial, the Platformer Starter Kit is really awesome.