0
votes

I have just recently begun playing around with XNA and couldn’t find anything on the web regarding this question. Is there a way to tell if SpriteBatch.Begin (and conversely End) has been called on a particular SpriteBatch object?

At the moment, I am using only one essentially global SpriteBatch object for the system, mainly because that seems to be the preferred method from the articles I have been reading. I’m assuming that creating a SpriteBatch instance for each object would cause too much overhead. Anyways, I am having problems with keeping SpriteBatch.Begin/End synchronized. In particular when drawing objects can contain other drawing objects. If I could test whether Begin/End has been called then my problems go away. I suppose I could try something like subclassing the SpriteBatch class but it seems to me like this operation is so basic that there has to be a built in way to tell. I just haven’t been able to figure out how.

Thanks for any insight you can provide!

2
If you can't find it, subclassing the SpriteBatch to add an "has begun" flag seems like the way to go. Here's hoping.Kawa
I'm still trying to understand if each object should call Begin/End or if it should be at a higher level. My intuition tells me that each object calling Begin/End is more flexible. In that case I would probably put a wrapper around the global SpriteBatch object. Otherwise, I guess I don't need to know if Begin/End was called. With the higher level approach, I suspect (but don't have enough XNA experience to know yet) that it is going to limit some options with what I can do when drawing the individual objects.Dunk

2 Answers

1
votes

If you take a look at this link i think it will answer your question, sorry if the link is a different version than what you're using:

http://www.ziggyware.com/forum/viewthread.php?forum_id=12&thread_id=12996

It's kind of up to the developer to figure out if the code they are writing will be within the begin and end. You want to make sure you are "holding" everything you need draw until you do call that "begin" and then draw after that.

Additionally you might want to take a look at some articles on "game loops" and how they operate it will help you get a good understanding of how to code in such a way that you shouldn't have this problem.

Hope this helps! :-)

For instance make an interface, which you can inherit from that has a Draw() method. Then back in the game loop, make sure you cycle through all objects to be drawn (which inherit from that interface) and call their draw method within the begin end lines. The code inside each object can have the drawing specifics, but you KNOW that will be called when its suppose to. Maybe that will clarify a little.

1
votes

I’m assuming that creating a SpriteBatch instance for each object would cause too much overhead.

As the name imply, the SpriteBatch is used to organize a batch of sprites and draw them in a particular way in a buffer. When you call SpriteBatch.End(), the sprites added in the SpriteBatch are sorted (or not) and written in a buffer (ex: the screen) using a particular blend mode and other options specified before SpriteBatch.End().

When you call SpriteBatch.Begin(), you have to call SpriteBatch.End() before calling SpriteBatch.Begin() again (using the same SpriteBatch object).

So this code is wrong :

class Main
{
    private Ship ship;
    private SpriteBatch spriteBatch;

    //logic to create the ship/spriteBatch

    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        ship.Draw(spriteBatch);
        spriteBatch.End();
    }
}

class Ship
{
    private Texture2D image;

    //logic to create the image

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        spriteBatch.Draw(image, Vector2.Zero, Color.White);
        spriteBatch.End();
    }
}

because spriteBatch.Begin is called twice. The right way to do it :

class Main
{
    private Ship ship;
    private SpriteBatch spriteBatch;

    //logic to create the ship/spriteBatch

    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        ship.Draw(spriteBatch);
        spriteBatch.End();
    }
}

class Ship
{
    private Texture2D image;

    //logic to create the image

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(image, Vector2.Zero, Color.White);
    }
}