1
\$\begingroup\$

I have the main game (Game1.cs) draw the sprites like so:

        //Clear everything
        GraphicsDevice.Clear(Color.CornflowerBlue);

        //Begin drawing
        _spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

        //Draw enemies
        for (int i = 0; i < ControlObj.EnemyList.Count; i++)
        {
            ControlObj.EnemyList[i].DrawObject(_spriteBatch);
        }

        //Draw powerups
        for (int i = 0; i < ControlObj.PowerupList.Count; i++)
        {
            ControlObj.PowerupList[i].DrawObject(_spriteBatch);
        }

        //Draw other stuff
        for (int i = 0; i < ControlObj.OtherStuffToDraw.Count; i++)
        {
            ControlObj.OtherStuffToDraw[i].DrawObject(_spriteBatch);
        }

        //Draw the player
        ControlObj.PlayerObj.DrawObject(_spriteBatch);

        //Finish drawing
        _spriteBatch.End();

DrawObjects method:

        public virtual void DrawObject(SpriteBatch sb)
    {
        int imgIndex = (int)Math.Floor(ImageIndex);

        //Draw the object!
        sb.Draw(Sprite[imgIndex],   //Sprite (Texture2D)
                Center,             //Location of object (Vector2)
                null,               //Source rectangle (USELESS)
                ColorBlend,         //Color blend (Color)
                Rotation,           //Rotation angle (in radians)
                CenterOffset,       //Offset (Vector2)
                ImageScale,         //Image scale (Vector2)
                SpriteEffects.None, //Flip sprite? (USELESS)
                Depth);             //Depth of the object
    }

The issue: Some objects draw other objects by overriding the DrawObject method like so:

        public override void DrawObject(SpriteBatch sb)
    {
        base.DrawObject(sb);

        for (int i = 0; i < OtherStuffList.Count; i++)
        {
            OtherStuffList[i].DrawObject(sb);
        }
    }

For some reason, objects drawn by other objects do not obey their depth property. How could I fix this?

\$\endgroup\$
4
  • \$\begingroup\$ Is it only the "OtherStuffList" objects that are having an issue? Everything else renders at the depth expected? \$\endgroup\$
    – Djentleman
    Jan 21, 2013 at 11:24
  • \$\begingroup\$ Everything that is not drawn by another object renders on the correct layer. \$\endgroup\$
    – Andrew Sun
    Jan 21, 2013 at 11:44
  • \$\begingroup\$ This looks correct to me, How are you instantiating the new OtherStuffList objects depth? \$\endgroup\$ Jan 21, 2013 at 13:14
  • \$\begingroup\$ I use an enum and a dictionary. Upon starting the game I loop through the enum and store depth values (e.g. 0, 0.1, 0.2, etc) in the dictionary. Then when objects are created I just set their depth values using the values in the dictionary. \$\endgroup\$
    – Andrew Sun
    Jan 22, 2013 at 1:14

3 Answers 3

2
\$\begingroup\$

To develop on what our fellow Xavier said, do not use that SpriteSortMode in your case. As it is right now, it doesn't matter the order objects are put to be drawn, they will be sorted by their layer value later, before being put on screen.

Use SpriteSortMode.Deferred (_spriteBatch.Begin(SpriteSortMode.Deferred /*!!*/, BlendState.AlphaBlend);) and this will most probably work. This one disables ordering, making it so that textures are drawn in the order they are called.

You can check out some more info on SpriteSortMode here, if you'd like.

\$\endgroup\$
2
  • \$\begingroup\$ I believe that Andrew is intentionally using BackToFront. As he implies in his question, objects have a depth property assigned so they aren't meant to be drawing in the order they appear in the Draw call. They're meant to be drawing based on the Depth property. \$\endgroup\$
    – Djentleman
    Jan 21, 2013 at 22:40
  • 1
    \$\begingroup\$ Yeah, if there's really no other way, I would probably just let Game1 draw everything. What I really want to know is why having objects draw other objects is messing up the depth order. \$\endgroup\$
    – Andrew Sun
    Jan 22, 2013 at 1:10
0
\$\begingroup\$

To implement the concept of layers you could call Begin, draw the layer's content and call End on the spritebatch (note that more Begin/End calls means loosing performance!).

Make sure that there aren't any sprites trying to be drawn on the same depth value, as the draw order is not defined for 2 sprites with the same depth value (causing random flickering).

Since you're using some kind of object hierarchy to draw your game I'd recommend you to avoid using depth values and use the hierarchic model through all the game (cocos2d handles it this way).

This way you can have a screen object that draws all the screen, and the order of it's children will decide who draws first. This idea, used recursively, decides all the relative depths for your sprites.

\$\endgroup\$
0
\$\begingroup\$

Oops, I found the source of the issue... Turns out that having objects draw other objects works fine. The issue was that I initialized values to zero in objects' constructors like so:

    public GameObject(Game1 game) : base(game)
    {
        game.Components.Add(this); //ISSUE HERE
        //...
        Depth = 0;
    }

And I set their values per-object in Initialize():

        //Set the drawing depth
        Depth = _myGame.UtilitiesObj.GetDepth(Utilities.DrawingDepths.Missile);

The issue was that calling Game1.Components.Add() also called Initialize() immediately. So the values would be set to their correct values, and then "initialized" back to 0. I thought that Initialize() was always called AFTER the constructor, hence the bug.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .