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 found debugging games especially hard for some obvious reasons. It's hard to monitor some internal values in dynamic, conditional breakpoints helps somehow, but only to detect some specific conditions. You don't get information that lead you there. Sometimes you just want to monitor some value, sometimes value are hard to interpret in their internal form (say a current path calculated by AI).

So I'm thinking about implementing kind of debug layer which will draw this information above gameplay in real time. The question is how to do it in most convenient and reusable way.

I'm currently thinking to make interface say IDebugInfo, implement it in all entities which I want to monitor, and add then to debug layer (it's a DrawableGameComponent) via GameServices. The debug layer will draw them. It can be turned on or off in realtime by removing/adding debug layer.

Does this sound good? I'm almost sure this was done many times already, is there some proved patterns?

Update. So, I implemented it this way:

// iface
public interface IDebugDrawable
{
    void DrawDebug(GameTime gameTime, SpriteBatch spriteBatch);
}

// service
public class StateManager
{
    public StateManager()
    {
        this.DebugDrawables = new List<IDebugDrawable>();
    }

    public List<IDebugDrawable> DebugDrawables { get; private set; }
}

// debug screen draw
public override void Draw(GameTime gameTime)
{
    SpriteBatch sb = this.ScreenManager.SharedSpriteBatch;
    StateManager sm = this.ScreenManager.Game.GetService<StateManager>();

    sb.Begin();

    foreach (IDebugDrawable debugDrawable in sm.DebugDrawables)
    {
        debugDrawable.DrawDebug(gameTime, sb);
    }

    sb.End();
}

// implementation in game entity
public void DrawDebug(GameTime gameTime, SpriteBatch spriteBatch)
{
    spriteBatch.DrawString(
        DebugScreen.DebugFont,
        this.Cell.ToString(),
        this.Position,
        Color.White);
}

this looks like:

Debug screen output example

share|improve this question
    
I would suggest to write some sort of DebugRenderer with methods like DrawBoundingBox, that would not draw boundingbox but store command to draw it later. Then you could call debug renderer from methods like Update without need for special interface... –  Kikaimaru May 3 '12 at 8:47
    
@Kikaimaru I don't quite understand your concept, could you please post it as a full answer with sample code? –  Petr Abdulin May 3 '12 at 14:03
add comment

2 Answers

up vote 1 down vote accepted

You can collect draws from all your methods and then draw them all at once. (Because in debug draws you don't really care about ordering)

This you will call anywhere in your code (like in update method) - you an make DebugRenderer singleton

  DebugRenderer.Commands.Enqueue((sb)=> sb.DrawString(DebugScreen.DebugFont,
            this.Cell.ToString(),
            this.Position,
            Color.White);

This is a component that will do the drawing

    public class DebugRenderer : DrawableGameComponent
    {
       // Action of this queue can take DebugRenderer as parameter then you will have access to spritebatch and graphics device 

       public Queue<Action<SpriteBatch> Commands;

       public void Draw(GameTime gameTime)
       {
            spriteBatch.Begin(); // we only have commands to spritebatch so you call begin
            while (Commands.Length > 0)
            {
                 var command = Commands.Dequeu();
                 command(this.spriteBatch);
            }
            spriteBatch.End();
       }
    }

It's not really a good design but for debugging it's great.

share|improve this answer
    
Oh, now I understand. I don't see any significant advantages to my situation for now, but I will keep that one as an alternative. Thanks! –  Petr Abdulin May 3 '12 at 15:18
    
@PetrAbdulin Abdulin You may want to display an arrow to direction you will move when holding key down (in some class where you set your movement vector when key is down) you could implement that interface and add check if that key is down again, but with this system you could just add that code directly under that if (iskeydown) condition, and it will be rendered next frame –  Kikaimaru May 3 '12 at 19:35
    
Oh, I get it finally now! Thanks for explanation! I suppose this and mine approaches can be combined if necessary. The minus with this approach is that debug code is scattered throughout the code. –  Petr Abdulin May 4 '12 at 2:02
    
Yes, but you can add [Conditional("DEBUG")] so it will not be compiled into your realese, and/or pass seconadry argument, telling what kind of debug functionality it is (like Enque(new Command("movement", (sb) => sb.Draw()) and then you can have filter on debugrenderer that will draw just commands with "movement" name –  Kikaimaru May 4 '12 at 4:35
    
Still it pollutes the real game code. I guess it's just a matter of personal taste :) –  Petr Abdulin May 4 '12 at 4:41
add comment

you could just do a key binding (that is not normally used in your game) that modifies the game state, and then in some section of your screen print out specific information about what is going on. Keep in mind that I have not worked with the debug layer, but I have done this with output.

remember that somethings are easier to see what is going on numerically (seeing that valueX is changing/not changing in this way), and other are easier to debug visually (it looks like that model is interpenetrating the wall)

the biggest thing is figuring out is what information is really needed for you to know that everything is working or not.

When I have done this in the past (was designing debug for keyboard) I mapped AI states/positions to one button, another button showing bounding volumes, another button outputting positions, and bounding data, and a final button that displayed every collision that was not purely Y (at one point I had things falling through the world, and had to just revers the bool check, but that a different story)

share|improve this answer
add 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.