0
votes

recently I started to use XNA with MonoMac. I have problem with classes. I want to create a class with textures and position information inside. Also I would like to make draw function.

My idea was to pass spriteBatch and Content arround so I could load textures and draw them afterwards. However Content object i pass into this object doesnt load any textures, when I tried Content outside the class, it loaded textures fine, so textures must be there.

    public class TPlayer {
        public Texture2D[] textures;
        public ContentManager Content;
        public SpriteBatch spriteBatch;
        public int currentFrame;
        public Rectangle position;
        public TPlayer(ContentManager ccontent, SpriteBatch cspritebatch){
            this.Content = ccontent;
            this.spriteBatch = cspritebatch;
            this.Content.RootDirectory = "Content";
            this.currentFrame = 0;
            this.position = new Rectangle(250,20,100,150);
            this.LoadContent();
        }

        protected void LoadContent(){
            this.textures[0] = this.Content.Load<Texture2D>("Textures/ToughStanding");
            this.textures[1] = this.Content.Load<Texture2D>("Textures/ToughWalking1");
            this.textures[2] = this.Content.Load<Texture2D>("Textures/ToughWalking2");
        }

        public void Draw(){
            spriteBatch.Begin (SpriteSortMode.Deferred, BlendState.AlphaBlend);
            this.spriteBatch.Draw (textures[0], this.position, Color.White);
            this.spriteBatch.End ();
        }

This is how i create instance:

Player = new TPlayer(this.Content,this.spriteBatch);

Maybe Im trying to use wrong model.. Maybe I shouldnt want to use spritebatch and Content inside of class, but than can i make spritebatch and content global ?

Thank you for your help

1
What is the value of Content.RootDirectory before it enters your TPlayer constructor? inside the constructor you're setting the value, are you sure you need to do that?Andy
Also as a tip (unrelated to your issue) I'm guessing you've got a loop that draws the players, call spritebatch.begin and end either side of that loop rather than in each draw method, you'll speed things up quite a bit.Andy
no i think i do not need to do that. It was set to "Content" before. I was just trying to guess where can be problem so i tried that too. Thank you for the spritebatch advice... I will call Begin and End only once from now.Dr Vary-cute
I solved problem by passing only texture to the object and than passing spritebatch to the draw function as it is done here: create.msdn.com/en-US/education/tutorial/2dgame/… sorry for your troubleDr Vary-cute

1 Answers

2
votes

Since you have solved your own problem (nice work!) I'll use this space to suggest a slightly less resource intensive method of drawing your sprite frames which will also solve the problem you had, instead of using a separate texture for each frame of animation you can combine them in to one single texture. Swapping textures is actually a relatively slow operation.

so instead of 3 textures for Standing, Walking1, Walking2 and using the current frame property to switch between them you can create one large texture to hold all 3, this can be done in paint or any drawing package by simply creating a blank image the size of all 3 frames and copy/paste them in to place (taking note of the start/end positions of each one)

enter image description here

You can create a rectangle array to hold the positions of each sprite in the sheet.

spriteSheetRegions = new Rectangle[]
{
    new Rectangle (0,0, 50,50),     // standing.
    new Rectangle (50,0, 100, 50),  // tough walking 1
    new Rectangle (100,0, 150, 50), // tough walking 2
};

Then to animate the sprite you simply keep track of which rectangle is the current frame.

I've attached a quick game class below that shows how the whole operation would work along with a sprite and player class, the sprite class can become the base for all sprites not just the players.

#region Using Directives.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#endregion

namespace sprites
{
    public class Sprite
    {
        // Texture instances.
        public Texture2D spriteSheet;
        protected Rectangle[] spriteSheetRegions;
        protected Rectangle currentSpriteSheetRegion;

        // player instances.
        public Rectangle location;

        // call this to change the image that's drawn for the sprite.
        public void SetSpriteSheetIndex(int index)
        {
            currentSpriteSheetRegion = spriteSheetRegions[index];
        }
    }

    public class TPlayer : Sprite
    {
        public TPlayer()
        {
            // Since your sprite sheets for the player are fixed we can set them up here.
            spriteSheetRegions = new Rectangle[]
            {
                new Rectangle (0,0, 50,50),     // standing.
                new Rectangle (50,0, 100, 50),  // tough walking 1
                new Rectangle (100,0, 150, 50), // tough walking 2
            };
            currentSpriteSheetRegion = spriteSheetRegions[0];
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(spriteSheet, location, currentSpriteSheetRegion, Color.White);
        }
    }

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        List<TPlayer> players;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // Create the players and add 3 of them.
            players = new List<TPlayer>();
            players.Add(new TPlayer() { location = new Rectangle(10, 10, 100, 100) });
            players.Add(new TPlayer() { location = new Rectangle(110, 10, 100, 100) });
            players.Add(new TPlayer() { location = new Rectangle(220, 10, 100, 100) });

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Load up the players content.
            Texture2D playerSpriteSheet = Content.Load<Texture2D>("PlayerSpriteSheet");

            // each player gets a reference to the same texture so there is no duplication.
            for (int i = 0; i < players.Count; i++)
                players[i].spriteSheet = playerSpriteSheet;
        }

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

            // draw the players.
            spriteBatch.Begin();
            for (int i = 0; i < players.Count; i++)
                players[i].Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

When you want to change the current frame for the player, you call the SetSpriteSheetIndex.

If you wanted to set player zero's picture to the tough walking 1 frame you would call.

players[0].SetSpriteSheetIndex(1);