I created a prototype UI menu system in C++, using a little bit of SFML to provide sprite and text objects. It was lovely making something like this in C++!
The UI of a game is often not the first thing that is thought about when we think about games, people think of the graphics or the action, etc. However, the UI is the first thing that the player sees and interacts with, and the last thing that they interact with before exiting the game. It is therefore an absolutely crucial system.
However the useability and the intuitiveness of the menu to players is paramount. Furthermore UI systems need to scale well as they evolve: as new menus and components are added often links between menus can become broken. It is also important to try and to keep track of how many connections are needed between different menus: we don’t want to frustrate the player with an overcomplicated system.
Graphs
Crucially, my goal of designing this system was to implement it with graphs in mind. In his book Michael Dickheiser describes how a graph can be a very useful data structure for designing UI and menu systems. On consoles where we don’t have access to a mouse, we need to push up, down, left, right through the different buttons. Having the components connected together as nodes on a graph makes this relatively easy! Furthermore, we then have the ability to apply graph search algorithms, such as breadth-first-search or depth-first-search (I use the former here) to test for missing connections: a very useful test that can be run regularly to provide confidence that as the menu system evolves it remains functional.
Having the menu system implemented as a graph provides other advantages: it can provide a report on how many edges exist between menus as a metric for how complicated the system is to the user. I in this video provide a “return to root menu” button that returns to the top menu, via iterating through the graph structure.
As you can see in the video I have provided a simple “interpolation-based” animation system too, that provides fade-in fade-out transitions between the background images, the buttons and the menus, provide scaling animations (with a non-linear interpolation) to some of the buttons, and the different animations can be combined (to provide scaling and fading, e.g., to the ‘blinking’ buttons.
I provide examples of buttons that open up menus, close menus, sliders, tick boxes, and provide different animating buttons (scaling up and down, and the “blinking” aura around the buttons).
Code examples
As this was a prototype, I haven’t provided serialisation or deserialisation of objects through XML or Json, etc. Instead I have used a design pattern known as a fluent builder to construct the UI objects (you simply return *this to create a reference to the object). This was useful as in my system each element can have six connections, up, down, left, right, and forward and backwards (for opening up menus or returning back to other menus).
I provide interface segregation to allow bundling up the objects for rendering, updating etc, but providing more granularity than having one large interface for everything with potentially unused virtual functions:
This is the function that does the graph search test, testing that all components are connected:
You can see a similar example to this search in action in the video, where I provide the “return to root” functionality.