I posted the following on the Card Kingdom development blog.
Since the beginning of the Card Kingdom, we’ve been using XBox controllers as the main sources of input for the game. The controllers afford us preexisting control schemes, analog movement, and support for multiple players at once. What it does not support is a way to interact with HTML in a standard, keyboard and mouse way. To support this, I’ve been working on a UI Paneling System, written in jQuery, that does not rely on a keyboard or mouse for interaction, while still providing a robust framework on which a user interface can be built.
The system is structured as the following:
- The UI Container is the root for all panels. It handles what panel is being shown, when to transition to the next one, and dispatches input events down to the active panel.
- A UI Panel is a single frame of the UI. It contains all the UI elements that should be displayed when shown. Custom show and hide animations can be set for the panel as well.
- A UI Element Group is the root for all UI elements. It handles which element is active, dispatching input events to the active element, and can cycle through the elements using defined buttons. Wrapping around to the beginning or end of the list of elements is also supported.
- A UI Element is a general container for actual UI controls and supports custom events for being selected and deselected.
- A UI Slider is a control that acts much like a slider bar. It supports a minimum, maximum, and step values. The current value of the slider can be increased or decreased depending on defined controls.
- A UI Toggle is a control that acts much like a check box. It supports being checked and unchecked with a defined button. This control can also be used as a button by disregarding whether or not it’s checked in the toggle event handler.
- A UI Select is a control that acts much like a select list. It supports custom data that can be cycled through and selected with defined buttons. Wrapping of element selection is also supported.
Some other features of the system include:
- Support for custom input handling at each container level (panel, element group, element, slider, toggle, select) that can be different than the normal process.
- Stack-based panel transitions for “forward” and “backward” panel transitions
- Custom enter and exit animations for both forward and backward panel transitions, as well as a hooks for when the transitions are complete.
- UI Slider, Toggle, and Select have no predefined rendering methods, making each fully and easily customizable.
The entire purpose of this system was to eliminate the need for a keyboard and mouse. In order to test this properly, I made a virtual XBox controller to simulate button presses that the system reads and responds to. The virtual controller and real controller, when hooked up to the engine, use the same function to send input events into the system, leading to a seamless transition from testing in the browser to playing in-engine.
Here is an example of the first pass of the main menu for the game:
For the main menu, when an element is active it slides over to the left, when inactive it slides back. This uses the UI Element’s onSelected
and onDeselected
hooks to animate the element. UI Toggles are used as buttons so when an element is selected, it transitions to a new panel. On the credits panel pressing any face button will return to the main menu, even though there are no controls on that panel. This is done with a custom input handler on the panel itself. The code for that looks like this:
$('#credits-screen').uiPanel({ onButtonPress: function (button) { switch (button) { case Buttons.BUTTON_A: case Buttons.BUTTON_B: case Buttons.BUTTON_X: case Buttons.BUTTON_Y: case Buttons.BUTTON_BACK: case Buttons.BUTTON_START: this .data('container') .trigger('uiBack'); break; } } });
Overall, this was a very strange task to think about and work on: a user interface inside of a user interface. It seemed daunting at first to completely bypass the keyboard and mouse in HTML, but it works, and it works well. I am really quite happy with the results.