Fighting games are rising in popularity around the globe. However, a consistent barrier to new player entry has been the difficulty of the inputs. Rather than pressing a single button for attacks and moves, fighting games often require complex frame-perfect combinations of buttons to perform combos necessary to compete at even basic levels. Many new players find that learning these combos and button strings are not worth learning, and become disenchanted with fighting games early on. This problem also extends to players at the highest level, who may have difficulty consistently inputting the most powerful and optimal combos possible.
To help solve this problem, we created a project called TKButtons. With the modified controller (Betsy) and our program, you can record your combo ahead of time, and then playback during the game. The controller contains a PIC32 microcontroller and some circuity which allows the player to play the game through a arcade stick. When the player is ready, then the player can hit the record button. The PIC32 controller then keep tracks when each button and stick input were hit and the time that they were hit. To finish the recording, the player hits one of the playback buttons. To play the recording, the player just needs to hit either the left or right playback button. The PIC32 will then play through the button/stick inputs that were just recorded. The player can also cancel the recording and the playback whenever they want. In this project, we will be mostly explaining the controller in use with the game Guilty Gear. If you are unfamiliar with the game, we recommend you to check out the appendix which have guides and instruction to all the different moves that we are explaining on this website.
Take Tiger Knee Bomber (TKB) for example, the case study for this project. In the game Guilty Gear, the player controls Axl Low to do this combo. To do massive damage however, the player needs to loop TKB three times and then break the wall. This combo can do up to 60% of the opponent HP. However, the combo loop is know to be hard to pull off, which can lead to player when they mess up to be vulnerable to the opponent attack. With this project though, the player can easily record the TKB combo beforehand, and then just hit the playback button at the right timing.
The video below shows the full project including the TKB Combo. Thanks to Professor Hunter for being the guinea pig for our demo.
High Level Design
With the release of the fighting game “Guilty Gear Strive”, traditional 2D fighting games are increasing in popularity. The main reason why fighting games are very daunting and difficult to get the hang of easily is because they require very precise inputs, often requiring inputting a series of buttons almost perfectly timed, within a few frames of each other, though this may vary between different fighting games. Guilty Gear Strive is known for being more newbie-friendly than the average fighting game, but still requires the player to be able to do very precise inputs when playing at a high level. To attempt to alleviate the player of this issue, we decided to create a way for players to record their favorite combos onto an arcade stick to ensure they would not have trouble executing the combo whenever they wanted.
From the software perspective, we split the funtionality of our project into three main threads: One for reading inputs, one for recording, and one for playing them back. This paid off, as it allowed us to quickly narrow down bugs in our design to specific threads in our code. Our circuit directly connects to the inputs of the arcade stick as well as to the port expanders, which is driven by the PIC32 on the ECE4760 small board. This is why writing to the port expander ends up “pressing” buttons on the arcade stick. Our connections ensure that the PIC32 drives the arcade stick.
We made some design choices for the hardware portion of our project that motivated our design for the software. Originally, we planned to work on this project with a classic XBOX 360 controller. After a lot of research, we concluded that using an arcade stick would be the better choice, as they are easily modifiable by the user. Making this design choice likely saved us weeks, maybe even an extra month of development time. Additionally, we decided to use multiple port expanders instead of a shift register, as although it might have made our circuit potentially easier to build, manage, and debug, it would also demand that we find or make an entirey new library for the shift register. Using a second port expander made our circuit significantly more complex, but eliminated the need to familiarize ourselves with a new interface.
The hardware of our final project is designed to enable the PIC32 to read the button inputs, spoof the button so that the button appears pressed to the PCB onboard the arcade stick, and so that all circuits leading back to the PIC32 are electrically protected. Our project is responsible for controlling 12 buttons related to gameplay, as well as reading three buttons to control recording and playback. To illustrate how all 12 of the button control circuits work, we will examine the data path of one of them.
The signals interfacing with the buttons originate from the PIC32 over a single SPI channel. The software onboard uses SPI to communicate with two port expanders which we use to communicate with all buttons on board. RB15 is SCK, RB5 is MOSI, and RA4 is MISO. The chip selects are RB9 for port expander 1 and RA0 for port expander 2. The final connected pinout is RA2, which is used to control the recording LED. The recording LED illuminates when the software is recording inputs. No other headers on the PIC32 are connected other than the necessary power, ground, and reset button.
The SPI channel is responsible for interfacing with two port expanders. Each button on the arcade stick receives two GPIO pins: one for reading the button state (input), and one for controlling if the button is electrically pressed or not (output). Since we have 12 buttons, we need 24 GPIO pins in addition to the three record/playback control buttons, bringing the total to 27 GPIO pins. The PIC32 is unable to accommodate so many GPIO pins, so external port expanders are required. Each port expander has 2 ports of 8 pins, so we decided to use two port expanders to have 32 available pins to use, of which we use 27. The reset of the port expander is tied together with that of the PIC32, and the configuration pins are all grounded as they are on the big board from class. The interrupt pins are not connected since the software uses polling to check the buttons. Each pair of GPIO pins, for example Y0 and Y1, are responsible for controlling a single button. Even numbers (0, 2, 4, 6) are inputs, and odd numbers (1, 3, 5, 7) are outputs. Using this GPIO scheme we were able to mitigate confusion during the wiring process.
Figure 4 shows the circuitry for the joystick’s GPIO. This circuit is duplicated twice: once for the XYAB GPIO, and one for the LT LB RT RB GPIO. Thus, we have 12 button control circuits total. Each button is represented by an SPST switch. When the button is pressed, both the GPIO input from the port expander and the input from the PCB read low. Otherwise, the circuit is connected to a 3.3V pullup so they read high. This matches the hardware on the arcade stick. When the button is pressed, an indicator LED also lights up to confirm that the button is registered as pressed. The second GPIO from the port expander is an output and is connected to the gate of an n-channel MOSFET. When the output is set high, the MOSFET allows current to flow through and forces the node at the drain to be electrically low. This can be read on the port expander and PCB. In addition, this turns the LED on as well. As a result the LED in each circuit is extremely useful for debugging.
On the arcade stick, each button has two inputs, one of which is pulled up. The ground of one of these inputs is connected to the PIC32 ground so that the PCB logic highs and lows can be manipulated by the PIC32. The rest are not connected for simplicity. The arcade stick inputs are connected to the corresponding node of the GPIO inputs from the port expander.
The record and playback control buttons are onboard the arcade stick on a separate PCB. The wires from the PCB header we are concerned with are the three logic wires pulled high responsible for reading each button, and a single ground wire. The logic wires are spliced so that they can be plugged into the port expanders for reading.
When all components work in tandem, the software is not only able to control the outputs of each button and read the state of each button, but also able to receive input from the user to determine whether a combo should be recorded or played back.
The software is designed to record a single combo and the timing of the inputs, as well as play the combos back with said timing. The program is split into four parts: the setup, the read button thread, the record/playback control thread, and the write button thread. The setup occurs at the top of the program file and inside the main file.