Following are some notes on integrating various input devices into Retrobooster. I hope this is useful to other game designers and programmers. First of all, the original plan was to let players use keyboard, keyboard plus mouse, and game controllers. I’m happy to report that testers prefer each of these in roughly equal measure, so they are all worth retaining for the final game.
Retrobooster has some fast-paced action and requires high-precision flying, which I described in my Thrust Ship Flight Dynamics post. To give players as much accuracy as possible, I have tried to decouple the controls as much as possible (i.e. make it so thrusting doesn’t interfere with rotating).
There isn’t much to say about keyboard control. Every desktop computer has one, and games in the cave-flyer genre make good use of them. Each key is physically separate, so controls are never coupled.
Keyboards are limited by a lack of analog controls and sometimes by rollover. The lack of analog controls has caused some testers problems with aiming at first, but I implemented a touch of rotational acceleration which greatly reduces the problem. This means that your ship will not rotate at full speed at first, so a quick tap on a rotation key will cause a relatively small change of direction. Rollover refers to the number of keys a computer can detect simultaneously. Most keyboards have 4-key rollover, which is usually enough for Retrobooster when you are in control. Once out of control, players often mash more keys, leaving one or more key presses undetected.
Mouse control is surprisingly pleasant. I was originally worried that it would be too difficult to control Retrobooster with a mouse. I was dead wrong, and now it is my favorite input device.
I tried a few different methods of control using the mouse, plus many variations on each of them:
- Rotate by moving the mouse side-to-side. Thrust using the mouse buttons.
- Rotate by moving the mouse side-to-side. Thrust by moving the mouse up and down.
- Natural mapping–the ship moves in the direction the player moves the mouse.
After much testing, Method 1 was the clear winner. It gives the most precise control because it is the simplest and does the best job of decoupling controls. Controlling thrust by moving the mouse required too much fuzzy logic to determine if the player was trying to thrust, stop, or reverse direction. It also had coupling problems with rotation. I tried hard to get natural mapping to work as well, but it was a complete mess every way I tried it. The fundamental problem with Methods 2 and 3 is that mouse movements can indicate a direction but cannot indicate a magnitude without sustained movement. You always have to use fuzzy logic to guess the magnitude, making for very imprecise controls.
My original implementation of Method 1 was also flawed. I tried to limit the angular velocity of the ship to prevent it from rotating unrealistically fast and to add fairness to multiplayer games with multiple input devices. This feature confused testers and made them feel unfairly handicapped, so I threw it out. The lesson learned is to make every device perform at its best; having a limit on controllability that feels contrived is way too frustrating.
Gamepads seem to work better for Retrobooster than joysticks because gamepads have small thumbsticks instead of big sticks that you move with your whole hand. Joysticks give the greatest precision but lend themselves better to games with a slower pace, such as flight simulators.
Like mouse control, I tried to couple thrust and rotation on the same stick. This works much better with a game controller than with a mouse because a stick can indicate both a direction and a magnitude–nothing needs to be inferred. However, testers still usually prefer to have rotation alone controlled by a stick. They prefer to have thrust controlled by buttons. This doesn’t allow for variable thrust, but it does decouple thrust and rotation so players make fewer mistakes when flying. Decoupling wins again. I need to do more testing, but so few people prefer coupling thrust and rotation on a single stick that Retrobooster will probably only have one set of defaults for game controllers.
I have not tried natural mapping with game controllers yet, but that would be a good experiment. This will still require fuzzy logic, but less than the mouse required.
Xbox 360 Controller
From what I have read, the Xbox 360 Controller has become the de-facto standard controller for PC games. Hence, Retrobooster should support them.
Unfortunately, Microsoft has made some really wonky design choices when it comes to the Xbox 360 Controller. Nominally, both its triggers behave as one axis in Windows. If you pull one completely, it indicates a value of -32767 for the axis. The other, 32767. Both or neither, 0. In Linux, each trigger behaves as a separate axis with a rest value of -32767 and a maximum value of 32767. I have never before seen a game controller software axis that has a rest value of anything other than 0 or one that has been mapped to multiple hardware axes. Needless to say, this makes writing robust, cross-platform code for using this controller difficult to impossible. Apparently, the official solution for Windows is to use Microsoft’s XInput API for the Xbox 360 Controller while using the standard DirectInput API for all other game controllers.
The best complete solution will require more study and planning. Retrobooster uses SDL for input device support, and, to my knowledge, SDL does not currently support XInput.
My only other gripe with the Xbox 360 Controller is its low-quality thumbsticks. They sometimes output rest values worse than 10% of their maximum, so they require very high software deadbands and drastically limit a player’s precision. With an MSRP of US$39.95, Microsoft should shell out for some decent hardware.
People keep asking if there will be a phone and tablet version of Retrobooster. I do not currently have plans to make one, but anything is possible if the Windows and Linux versions sell well enough.
I believe one of the most challenging aspects of porting Retrobooster to touch screen devices would be the touch screen itself. Retrobooster is a skill-based game that requires precision control, and touch screens are quite imprecise compared to the input devices already discussed. Maybe I will get to try this someday.