When you’re making a game, you may want to code special functionality that only exists for you when you’re building your game. This could opening up a leel editor, reloading the game on a key press, or rendering hitboxes. You don’t want your players to see these things, so how would you only render it for you while you’re making your game?

Enter debug mode!

When you launch the dragonruby executable, it runs in debug mode, meaning things like the console are available and args.outputs.debug is output. When you release your game, it runs in production mode.

So let’s break down how to use debug mode to improve the development experience.

Check the current environment

You can check if the game is running in production mode by calling $gtk.production. It returns a boolean value. It’ll be false in development mode. Here’s an example of how you could use it to make pressing the r key resets the game state:

def tick(args)
  if !$gtk.production && args.inputs.keyboard.key_down.r
    $gtk.reset
  end
end

Pretty nifty!

Debug Helper

If you’re relying upon that check a lot, introduce a #debug? method:

def tick(args)
  if debug? && args.inputs.keyboard.key_down.r
    $gtk.reset
  end
end

def debug?
  !$gtk.production
end

args.outputs.debug

DragonRuby GTK has a really nifty feature for outputting labels, sprites, etc. only in debug mode. Here are some ideas of how to use that.

Render Debug Properties

Want to track properties of a given data structure?

args.outputs.debug << [args.state.player.x, args.state.player.y, "health: #{args.state.player.health}"].label

That’ll render the player’s health right below their current position for you when developing but not for your players. Maybe you find it’s a neat feature and you want to include it! That’s cool too.

Render Collision Details

Let’s say you have some collision detection in your game and you want to see what sprite your entity is colliding with. In your collision check, render a rectangle around the collided entity:

collided_bottom = args.state.level.tiles.find { |t| t.y < @y && t.intersect_rect?(self) }
if collided_bottom
  rect = collided_bottom.rect
  args.outputs.debug << [rect.x, rect.y, rect.w, rect.h, 255, 20, 20].border
  @y = collided_bottom.top
end

Outro

By making use of our custom #debug? method and args.outputs.debug, you can really make your life easier when building and testing your game. Boom!

Additional Ideas

  • Add toggleable hitbox rectangle rendering for sprites to visually see how everything’s working
  • Easily switch between scenes in your game with different number keys
  • Ask testers what debug tools they could use to make it easier for them to efficiently test