Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to render some elements in my game. First, I render the textures (the textures of the textboxes themselves etc). Then I render the primitives (borders around controls etc). Then I render the text.

However, by doing so, this gives a weird result in my user-interface when showing tooltips (by hovering over a textfield), as seen in the screenshot below.

Screenshot

Due to the order of drawing, borders around the window are drawn after textures, which (for the tooltip that appears when my mouse is over the textfield) makes it look weird.

share|improve this question
add comment

3 Answers 3

up vote 6 down vote accepted

If these are each separate DrawableGameComponents, you should set the DrawOrder property of each component so that they draw in the correct order.

To make it more manageable as you add more components, the DrawOrder should be an enum:

/* DisplayLayer.cs */
public enum DisplayLayer
{
    Background, //back-layer
    Particles,
    Player,
    MenuBack,
    MenuFront //front-layer
}

public class MyComponent : DrawableGameComponent
{
    public MyComponent(Game game) : base(game)
    {
        this.DrawOrder = (int)DisplayLayer.Background;
    }

    /* etc. */
}

If this is all being drawn within a single DrawableGameComponent, then you should take @Andrew's advice and simply draw them in the correct order. If for some reason you can't do that, you can still have the clarity of enums when using layerDepth by simply normalizing the value of the enum to be between 0 and 1:

/* DisplayLayer.cs */
public enum DisplayLayer
{
    MenuFront, //front-layer
    MenuBack,
    Player,
    Particles,
    Background, //back-layer
    MAX_LAYER   //Do not use this as a layer
}

public void Draw()
{
    spriteBatch.Begin(SpriteSortMode.BackToFront);
    foreach(Thingy thingy in thingys)
        spriteBatch.Draw(/* blah blah */, (float)thingy.DisplayLayer/(float)DisplayLayer.MAX_LAYER);
    spriteBatch.End();
}

(The ordering of the enum is reversed because layerDepth uses lower numbers for the front-layer rather than the back-layer)

share|improve this answer
add comment

http://msdn.microsoft.com/en-us/library/ff433989.aspx

public void Draw (
         Texture2D texture,
         Vector2 position,
         Nullable<Rectangle> sourceRectangle,
         Color color,
         float rotation,
         Vector2 origin,
         Vector2 scale,
         SpriteEffects effects,
         float layerDepth
)


layerDepth The depth of a layer. By default, 0 represents the front layer and 1 represents a back layer. Use SpriteSortMode if you want sprites to be sorted during drawing.
For example you have: Form, and in the form labels, buttons
So for children elements you can add to layerDepth some value
For example: Form A have children: Form B and some buttons, Form B have only button
Form A - 1.0
Buttons in form A - 1.5
Form B in Form A - 1.5
Buttons in form B - 2

For Dialogs - you can store some bigger value

share|improve this answer
4  
A few caveats for this method: the valid range of layerDepth (I'm reasonably sure) is 0 to 1, so you'd have to stay inside that range. Additionally all drawing will need to be done within the one sprite batch (between Begin and End). Finally: it is worth pointing out that this method provides no performance benefit over simply drawing things in the correct order in the first place. –  Andrew Russell Jun 9 '11 at 12:19
add comment

I'm going to give the simple and fairly obvious answer, and that is just draw everything in the correct order in the first place.

To mock-up an example of what I mean:

// Assuming you have sorted windowList by Z-order, using one of the many
// existing sorting mechanisms provided by the framework such as List<T>.Sort().
foreach(var window in windowList)
    window.Draw();

// in your Window class:
public void Draw()
{
    this.DrawBackground();
    this.DrawBorders();
    this.DrawText();
}

Is there a particular, compelling reason why you are not already drawing your windows in this way?

share|improve this answer
    
I would guess that, as he states in his question, it is because he is doing both SpriteBatch and primitive calls, and hence he wants to batch them together, which is not really a bad idea. I seem to recall that even so, the SpriteBatch will batch all calls anyway so I'm pretty sure tour option would be the same perf wise. It also makes more sense. –  Jonathan Connell Jun 9 '11 at 13:17
    
@3nixios I would guess his reason is for performance too - but I'd then immediately suggest that it's premature optimisation. Is his GUI really performing so badly? And is consolidating batches really the correct choice of optimisation? Also SpriteBatch cannot batch past a texture change - so my method is potentially slower than his method if his implementation is properly optimised. –  Andrew Russell Jun 9 '11 at 15:48
    
And his method is viable - by the way. But it's difficult to implement correctly - including forming it into a good answer. So it's probably not worth the effort for the small performance gain - and therefore it would be the wrong answer to give. (The short version is: use the Z-buffer.) –  Andrew Russell Jun 9 '11 at 15:51
    
I totally agree :) –  Jonathan Connell Jun 9 '11 at 15:56
    
I don't follow why the above approach prevents you from batching all your SpriteBatch operations together. Just modify the draw methods to accept the SpriteBatch as a parameter. Then, in the base-most "Draw" method, first call SpriteBatch.Begin() -- then call "Draw" on the Windows (passing in SpriteBatch, which they will use and pass into each child) -- then after the loop, in the base-most "Draw" method, call SpriteBatch.End(). . . (My $0.02: I bet he's not using objects and the whole thing is probably a big procedural mess in his main Game class.) –  BrainSlugs83 Apr 28 at 3:08
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.