I am Guillermo García Subirana, student of the Bachelor’s Degree in Video Games by UPC at CITM. This content is generated for the second year’s subject Project 2, under supervision of lecturer Ricard Pillosu.

Intro to the problem

An input combo system can vary greatly from one video game to another. That’s why we have not established a fixed system to follow when we’re developing a system for our video game.

In this guide we will investigate about the input combos system that some video games have developed, we will discuss the different techniques that can be applied and, finally, we will make step by step our input system combo.

My intention is to make the system as flexible and complete as possible, which can be adapted to any project with a few simple changes. All the development exposed on this page has been done from scratch with techniques developed from the research done before this guide.

Different approaches by different games

First let’s analyze some games that use a input combo system significantly different between them. In this way we can distinguish some key parts of the system more easily.

Street Fighter

Street Fighter Example

Street Fighter - Ryu vs Ken

In Street Fighter, the user is able to perform a variety of combos already defined. Some keys of their input combo system are:

Heavy Rain

Heavy Rain Example

Heavy Rain example

In Heavy Rain they usually use a very interesting input combo system:

Description in detail

In all the titles that use an input combo system, they use a vector/list or tree (difference explained in detail below) to store the last inputs introduced by the user.

Input Storage

If we use a vector or list to store the inputs generated by the user, we will have to require a list of combos already defined to compare in each iteration of the application if there is a match between the “volatile” inputs that have been entered and the combo already defined.

The images below shows a combo list already predefined (the one above) that will be compared with the volatile vector (the bottom one) to know if the combo has been successfully completed at some time.

Vector_List_Example

Volatile vector doesn’t match with the predefined combo

Vector_List_Example

Introced new input in the volatile vector

Vector_List_Example

There is a match between volatile chain and the predefined combo

Vector_List_Example

The volatile combo is cleaned

On the other hand we can use a tree to store both the last inputs entered by the user and the combo itself. In this way, every time an input is received we will have to check if we can continue the path towards the end of the combo. In case of not being able to continue with the given input, the combo will fail and will have to start from the beginning. Also keep in mind that the combos system will only be aware of the input that follows.

Tree_Example

The tree is build around the combo/s predefined and wait for only the required input

Tree_Example

The tree has obtained a new event and stores it temporarily (green mark)

Tree_Example

If the tree gets an incorrect input (red mark), the previously stored events are deleted

Tree_Example

If the end of the tree is reached, the combo will be made and the temporary events will be cleaned

Circular Buffer

As we already know the memory is not unlimited and, therefore, storage is usually carried out using a circular buffer system that keeps the most recent inputs in memory. In this way, every time a new input is introduced (and therefore the oldest one is deleted) it is checked from the first found event to the last one created and then look for a match between the chain of inputs and one of our combos. It should be noted that conditions can be added to eliminate events such as in a fighting game: the time between events.

In the images below, the time buffer is shown graphically. The blue line marks the time (milliseconds) that must happen for the last input to be deleted. For another band the red mark indicates the time limit that has the following input to be considered as a combo with the previous ones.

Buffer_Example

The volatile chain with three inputs

Buffer_Example

The condition of time has caused input “A” to be eliminated. While another input “B” has entered

Resolution of the combo

In case of finding a match, we will eliminate or not the list of our last events and the appropriate movement or action can be carried out by means of a finite state machine.

Our approach step by step

Since in a fight / beat em ‘up genre the input combo system becomes more complex due to the time factor between events, we are going to create a combo system similar to the one that a videogame of this genre would use, although it will be ready to adapt to any other combo system in an easy way. We are going to use vectors and lists to store predefined combos and to organize the volatile chain of events.

Cick here to download the last release

Example final

At the end of the steps we will have a result like this

First let’s locate, all the magic of this system will occur in the folder InputComboSystem. In this folder we’ll find three classes:

Click here to download the project

TODO 1

Objective

Solution

If you have built the InputEvents properly, try to generate some InputEvent with the keyboard or gamepad (Controls in the readme). If everything works correctly, they will be displayed at the bottom of the screen.

Example1

TODO 2

Objective

We must eliminate the inputs of the volatile chain after a certain time.

Solution

Now the inputs that you generate should be deleted after 2000 milliseconds (GENERIC_TIME_LIMIT) and now the inputevents will save the time that has occurred since they were born until another input has been entered. We just made the whole circular buffer!

Example2

TODO 3

Objective

So far so good! It’s time to add some combos to the system. In this case there will be two: Shoryuken and Tatsumaki.

Solution

The help label will indicate if you have correctly entered the combo in the list of combos.

Example3

TODO 4

Objective

We arrived at the most complicated part, but if you have arrived here, you will surely achieve it!

If all the answers are yes, the combo has been performed correctly. Obviously you have to control the denials!

Solution

If the comparison has been made correctly, the combo movement will be executed.

Example4

But wait a second, something is wrong…

TODO 5

Objective

We didn’t clean the volatile input chain, that was it!

Solution

Now the function that compares the list of combos and the volatile chain does not make the player receive multi-calls, it only calls it once and then the temporary chain is eliminated.

Example5

Optional Homework

Performance

I have captured the time by iteration of the input combo system module using Brofiler. Specifically, the Preupdate and the Postupdate of the iteration.

preupdate final

preupdate final

Ways to improve

References

Devs - talks about trees - www.gamedev.net

Devs - handle tons of inputs - www.reddit.com

Commercial indie - What do we do when the combo is completed? - www.reddit.com

Use of queue storage for inputs - shivansite.wordpress.com

Handle input events - www.stackoverflow.com

Devs - talking about ghosting and rollover - www.reddit.com

License


MIT License

Copyright (c) 2018

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.