Keyboard shortcuts info in debug builds – IMGUI style

Original Author: Hubert Rutkowski

I want to share a little discovery, a trick easing the creation and development of games. First a short motivational and historical introduction.

Case study

I don’t know if you have it too, but when I’m creating a game, I often add to it a lot of keyboard shortcuts – even a few dozens. Player avatar, enemies, map, camera, physics, rules etc. Shortcuts use normal letters, digits, F keys, special keys (tab, home, backspace), and their combinations with ctrl, shift, alt. Sometimes it’s hard to figure out what is available and what does what.

Especially I had problem with that in Ninja Cat, where shortcut availability depended on compilation mode (CONFIG:: variables, you can treat them like #defines) – debug+editor had all of them, debug without editor had a part of that, editor without debug had yet another part etc. It was very useful, because sometimes having too much shortcuts and special keys was bad – ie. during testing, when pressing some keys would change gameplay.

But I didn’t want to have it as binary – either all, or none. Sometimes the ability to intervene meant beaing able to catch a bug on the hot spot (perhaps Heisenbug?), and do something about it. So it was nice having it at such a granular level (debug/release, editor, deploy, profile). The disadvantage was that often I forgot what the actual shortctus were, what could I do at this moment. I was pressing shortcuts and they didn’t work, or I was forgeting about some magic functionality, hidden in not so visible code places.

Solution

Ok, now I’ll explain how to fix this situation. The easiest is to just display a list of all shortcuts, upon pressing some key like F1 or H(elp). But nobody would be able to create such list and maintain it over time. Also, looking at huge list of shortcuts when you have available only let’s say, a third of them, is not that really helpful. The solution? Do it in a automated way.

I’ve discovered something similiar to Immediate Mode GUI (

Simple and obvious. Now let’s add something:

if (CONFIG::debug)
 
  {
 
      if (Game.info_keyboard_shortcuts_show)
 
      {
 
          Game.info_keyboard_shortcuts_list += "SHIFT+D = kill all enemiesn";
 
      }
 
  
 
      if (FlxG.keys.SHIFT && FlxG.keys.justPressed("D"))
 
      ...
 
      // code from above
 
  }
 
  
 
  // in singleton Game:
 
  public static var info_keyboard_shortcuts_show : Boolean = false;
 
  public static var info_keyboard_shortcuts_list : String;
 
  
 
  

Because the code is in if corresponding to compilation mode, its body will be executed only in that one specific mode. In this way, only the available shortcuts will be added to string and displayed.

Implementing the rest is trivial:

// once a frame call this function which checks whether you want to see the shortcuts list.
 
  // In such a case, display the list, collected in a simple string over the course of a frame
 
  
 
  static public function ShowKeyboardShortcuts():void
 
  {
 
      info_keyboard_shortcuts_show = FlxG.keys.pressed("H");
 
  
 
      if (info_keyboard_shortcuts_show)
 
      {
 
           var shortcuts_list : FlxText = new FlxText(200, 10, 350, info_keyboard_shortcuts_list);
 
           shortcuts_list.shadow = 0x000001;
 
           shortcuts_list.draw();
 
  
 
           info_keyboard_shortcuts_list = "";
 
      }
 
  }

That’s how it looks in practice:

key short info imgui

The text is displayed after holding H. So far I’ve added only few shortcuts.

Additions

1. The compilation modes can be combined, as well as mixed with runtime modes, ie.

if (CONFIG::debug && CONFIG::profile &&
 
      Game.is_profiling_state && Camera.is_some_other_state)
 
  {
 
        // some very specific shortcut
 
  }
 
  

2. My friend where I posted first about this technique; warning: polish language), how to make it even faster and less verbose. This:

if (CONFIG::debug)
 
  {
 
      if (Game.info_keyboard_shortcuts_show)
 
      {
 
          Game.info_keyboard_shortcuts_list += "SHIFT+D = kill all enemiesn";
 
      }
 
  
 
      if (FlxG.keys.SHIFT && FlxG.keys.justPressed("D"))
 
      ...
 
  }

should be quite easy to reduce to:

IF_DEBUG_KEY( SHIFT+'D', "kill all enemies" )
 
  {
 
     ... code ...
 
  }

Where IF_DEBUG_KEY does everything inside: testing compilation mode, checking whether to display shortcut info, testing whether such key combination is pressed, removing code in release build.

Summary

Little work, simple and flexible code, works everywhere (language agnostic), fixes specific problem. Maintainibility is high, because code handling the shortcuts is just next to the code displaying shortcut info. I recommend to use it to your bag of tricks / current game :)