Developer experiences from the trenches
Fri 20 February 2009 by Michael Labbe
The secret sauce is ketchup. Really good ketchup.
What makes a game great? These days, it needs to do a lot of things very well, or the user will be annoyed. But, we don’t choose our entertainment such that we avoid annoyance. Some of the greatest games of all time have had very annoying experiences associated with them. As core gamers, we overcome annoyances in order to access our preferred form of entertainment. (Ever tried to get a modem game of Doom working back in the 90s?)
The Quake games are great games. Id and Carmack have been well praised for the renderers and tech that underpin these classics. As outdated as the assumptions underlying the Quake technology may be in 2009, the games feel much more responsive and enjoyable to play than, well, a handful of the top titles from this console generation.
The secret sauce to making a game great is making the game respond well to its users. It’s obvious and simple. And, like the ketchup on you dining room table, the ingredients are right out there for you to inspect. Where, you ask? Some of the greatest movement and control code in the history of games has been GPL’d and released by Id in their three Quake releases.
For all of the praise Id gets for their tech, their movement code is a scant few hundred lines, overlooked by most. In response to mouse and keyboard input, it glides the user through the level seamlessly, giving the user the expected return for every input. That’s the secret sauce.
Behind making a responsive game lies a handful of techniques and principles. There are too many for one blog entry, but I’ll address some of the technical considerations here, moving on to design in a future post.
60 frames per second just makes your game feel more responsive. If you are making a current gen console game, it is technically achievable, though it requires team wide discipline. In response for that discipline, the user receives a viscerally responsive feedback loop.
On high quality displays, the difference between 30 fps and 60 fps : is very perceptible.
There is a sense of quality and production values associated with a : game that has a high framerate.
I understand that there are many development scenarios where 60 is not plausible. Maybe your platform doesn’t refresh well (I had this experience while developing a Flash 9 arcade game). Maybe your publisher won’t allow you to commit to a game design and art direction that lets you target sixty.
If that’s the case, you need to vsync lock at 30 without wavering. If Gears of War can look that good and hit a steady 30, why can’t you?
And, if you’re making a PC game, just wait a year or two and your game will fly on a $500 machine. Just don’t do the dumb thing and lock your renderer at 30 so it can’t take advantage of it, eh?
Use velocity-based movement unless you have strong animation talent. If your character moves through the world by calculating the model space displacement of its animations, your animation team is in charge of character movement and your programming team is not.
If you’re doing an involved interaction system with doors to open, cover to hide behind and detailed reload animations, you need to iteratively work with your animation team to ensure the animations are interruptible, blend very quickly and can be updated quickly to help your team.
Alternatively, a velocity-based movement scheme allows you to assign acceleration impulses to an entity. On each tick, you extrapolate the current position using the velocity, executing collision and response. This is a procedural approach to character movement and it can feel very organic. With this approach, your animations do not change the rate of your player’s movement.
I’m not going to say locomotion based movement is bad. It can look better than velocity based movement. You just need to seat your animator and your programmer next to each other. Remain analytical and vigilant and you will come out on top.
As a bottom line, you need to make sure the player gets the movement response he wants and expects from all input at any time.
This is a technique that isn’t immediately obvious, but is difficult to argue against once you’ve considered the ramifications.
In a given tick, you can have up to two samples for a single button press whether it’s a keyboard button, an Xbox gamepad button or a mouse button. Test for button down and button up states — cut your output velocity by half if you get both.
There are two cases where this is useful:
First, consider that the user wants to move forward lightly. If a key is tested for down and not up state, you multiply the velocity by 1.0. However, if a key was tapped down and up in a tick, you multiply the velocity by 0.5. You can use this to allow half-height jumps in response to a light tap, for example.
The second point is more important. When a user’s framerate dips to, say, 20 fps, he is likely to overshoot his goal by walking off a ledge or firing for too long. By cutting his velocity in half, you assist in reeling in the negative effects of the framerate dip. Your user would thank you for doing this, but he’ll never know you did it. He’ll just inexplicably like your game better than the competition’s.
Different mice and gamepads send analog updates at different speeds. How do you make sure you have a stick or mouse movement update ready for processing when it’s time to queue up a new frame? Ya can’t.
Even if your first person shooter is vertically synced and running at 120 FPS on a beautiful 24 inch widescreen CRT, you can pan a crappy Radioshack serial mouse around your scene and watch the camera chunk at 20 updates per second. The rest of your in-game animations may seem smooth, but you won’t notice because the panning is rate is as crappy as your mouse.
A common approach to dealing with this problem is interpolating the mouse from the last known input and the one before it. This means you are always a percentage of the way between 2 known mouse samples.
If you are running at 60 fps, this is acceptable for 99.5% of the population. Even if you’re 20 years old and hyperperceptive, you’re not going to be able to determine that you are a quarter of a mouse delta away from the truth.
If you’re running at 25 fps, a mouse or gamepad starts to feel laggy. 25 fps is a new frame every 42 milliseconds and you are partially between the mouse delta received 42 milliseconds ago and the one received 84 milliseconds ago. That sucks, and perceptibly so.
Unfortunately, unless your framerate is a steady 60 fps, you do not want to filter your inputs. If you are making a PC game, make input filtering an advanced user choice. And, please, think about it - it does not make sense to automatically disable filtering on a framerate threshold or the user will perceive a small mouse leap when you toggle the filtering.
Oh, and if you’re a gamer, buy mice that refresh quickly. This is basically resolved by buying a quality, modern gamer mouse. In the old days, we had to seek out specific mice and run custom programs to bump up the refresh rate. Good riddance.
When developing a game, there are lots of temptations to halve the processor demand for a calculation by performing it every other frame.
“It’s taking our AI 5 milliseconds to assess all of the threats in the world. Let’s run that on even frames only!” This is a naive but common suggestion heard in game programming.
Unfortunately, if your AI runs its threat test on every other frame, your framerate fluxuates by 5 milliseconds. Do that enough and the game will have a difficult to describe hitchy feel.
Some modern game perf tools and profilers work on a per-frame basis and this is an excellent way to have your code evade performance analysis tests.
Find another way.