ou ever notice how all the young people on Murder, She Wrote
I'm serious. Every episode, Jessica Fletcher would be visiting a friend somewhere, somebody would get murdered, and there would be five or six suspects. The older people were usually played by character actors who've been around forever. But the younger people were all played by canonically-attractive unknowns. Episode after episode, week after week, there was an endless stream of blandly good-looking men and women. If they didn't have different colored hair, I couldn't tell them apart.
Weird, huh? I asked a friend in showbiz why this was so, and he said it was because Los Angeles has a vast pool of attractive young people all trying to get into television or films. The market's saturated, so they're cheap -- if you don't care too much about acting ability.
On the other hand, try looking around at people's faces the next time you go to the mall, or to work. The variation in human appearance is enormous. Try to ignore the hair (whose appearance is at least as much a matter of personal choice as it is of genetics) and concentrate on facial features: eyes, noses, lips, chins, cheekbones. Look at skin colors and textures. Hollywood does a very poor job of duplicating the diversity of the real world on TV.
Of course, we're not in any position to throw stones. In the video game industry, we've been turning out characters that look alike for years. And not just somewhat alike -- exactly alike. Completely identical. Game after game, level after level, we sell an endless stream of canonically mean-looking bad guys.
The reason for that is hardware limitations, of course. You've only got so much room in memory for sprites. You have to strike a balance between diversity of characters and number of animation frames per sprite. As a result, all Level 5 Bog Monsters look and act identically. We're so used to it that we never question it -- it's part of the landscape of computer gaming. But imagine a person completely new to computer games encountering this for the first time: "Why is that guy back? I killed him five seconds ago!" "No, it's a different guy." "Then why does he look exactly like the guy I just killed?"
Well, I say it's time to put a stop to it. There's no longer any excuse for it. We now have the capacity to make every single character in a computer game a unique individual. They can not only look differently, they can behave differently as well. How? With physical anthropology.
Physical anthropology is the study of human physical variation. Unlike medicine, which seeks to learn about things that we all have in common (so that we can develop treatments that work for everybody), physical anthropology is the study of how we differ from one another, both today and in the past.
There's a subdiscipline of physical anthropology called forensic anthropology, which appeared prominently in the book (and movie) Gorky Park.
The hero, a policeman, has three bodies he can't identify. The faces and fingers have been removed. He takes the heads to a forensic anthropologist, who, knowing the average tissue thickness at different points on the skull, is able to build up faces on each of the heads with clay. Ta-da! From the shape of the underlying skull, the face is revealed.
There's actually a lot of debate about the validity this technique in anthropological circles. For one thing, you don't know that a given person's skin was
of "average" thickness. For another, there are aspects of our appearance that aren't governed by the underlying bone: the shape of the ears, for example. The technique is useful to get an impression of what the "average" Neanderthal looked like, but it doesn't really matter if we get it wrong. It's another thing to claim it's accurate beyond a reasonable doubt in a murder trial.
We don't have to live up to courtroom standards, thank goodness. But I think we should start to apply the principles of physical anthropology in our games. Now that we've got polygon people to work with, we can create variation in each individual, by adjusting the positions of the vertices that define a character's skin surface. I'm not actually suggesting that you try to build up a face from the skull, like a forensic anthropologist. Rather, I'm suggesting that you try to define a set of adjustments to your "standard" polygon model which will enable you to create individual people. For each vertex, you can establish a formula that governs how much its position varies from the "average" or starting case. You can't treat each vertex independently, however; you will have to group them into meaningful categories and adjust them collectively. For example, if a person has a wide skull, he must necessarily have a wide jaw to go with it. You will need to examine your model to create a hierarchy of vertices, so that the positions of the major ones influence the positions of the minor ones. Motion capture data uses a similar concept for the skeleton: the position of the hand is dependent on the position of the forearm, which is dependent on the position of the upper arm. Likewise, unless you're creating a race of monsters (and I'm sure many of you are), you'll want to preserve the bilateral symmetry of the human form: most people's left arm is the same length as their right, and so on.
At this point some of you programmers may have switched off, thinking I'm talking to the artists. I'm not. I'm talking to the programmers. I don't think you should do this ahead of time, in a pre-rendering production step. If you do that, you're just back to the old situation of having a number of characters whose appearance is fixed. I think you should do it on the fly, as the game is being played
when the character is "born" in your game. One pleasant consequence of this is improved replayability -- the characters don't look the same every time you play the game.
However, be warned: if you create individuals whose physical variation is more than cosmetic -- if you start modifying their heights, for example -- then you run into some tricky issues, because of the interlocking relationships between appearance and motion. Suppose you decide you want a character who is taller than the average, and you make appropriate modifications to the model's leg length. As a result, your motion-capture data is going to require some on-the-fly modification also. Since your motion-capture data is (presumably) designed to work with your "average" person, you are going to need to adjust it for each individual to account for all the ways that that individual diverges from the norm. In this case, the model's stride is going to get longer. But once the model's stride is longer, you will need to modify the character's speed and acceleration accordingly as well -- otherwise you'll get the well-known "skating" phenomenon, where a character's leg movements don't correspond to her motion across the floor. Getting this right with fixed characters, with testing and tuning, is hard enough. Getting it right algorithmically for all possible cases is going to be very tricky indeed -- but I have faith in you; nobody becomes a game programmer who doesn't already think he or she is a stone genius, right?
These adjustments can apply to behavioral characteristics as well as cosmetic ones. Recently I was playing a game with a large number of characters of different races. The designers had, rather interestingly, given each character his or her own name, so they were uniquely identifiable. However, all the characters of a given race and experience level had identical abilities. In other words, although each Level 5 Bog Monster had its own name, they all were exactly the same strength. Why should that be? It would add interest and variety to the game for them all to be slightly different, although clustering about a common average. To set the strength of each Level 5 Bog Monster, the program could have taken a starting value (the average strength of all Level 5 Bog Monsters) and added a random number, positive or negative, to it to create a unique individual.
If you do change a character's appearance, you should change his behavior as well. Since we're used to an endless stream of identical bad guys, experienced gamers will expect bad guys that look different to have different skill levels.
Now your ordinary random number generator, if it's a decent one, is going to return values which are uniformly distributed. If you use it to create the variations from the "average" individual, then the probability of ending up with an "extreme" individual is the same as the probability of ending up with a "normal-looking" one. Unless you're working on a game involving post-nuclear mutants, you probably don't want this. Instead, you want small deviations from the norm to be common, and large deviations to be rare. In other words, you want the distribution of your random numbers to be governed by the famous "bell-shaped," "normal," or "Gaussian" curve (they're all names for the same thing).
So how do you generate random numbers with a bell-shaped distribution instead of a uniform distribution? There are several ways to do it, as with most software solutions:
The first way will be familiar to those of you who have played Dungeons and Dragons. In D& D, to get the starting attributes of your character, you throw three six-sided dice and add them together. When you add uniformly-distributed values together, the probability distribution of the resulting sums is, in fact, a Gaussian curve. The more values you add together (the more dice you throw), the more accurately the distribution resembles the "standard" bell-shaped curve. (In D& D, you actually throw four dice and ignore the lowest one. This shifts the average result to a slightly higher value, but doesn't affect the shape of the curve.) If your random number generator is fast, you should probably add about ten uniformly-distributed random numbers together to get each Gaussianly-distributed random number. Remember that you'll have to normalize the result afterwards: if you add ten uniformly distributed random numbers between 0 and 1, you'll end up with Gaussianly-distributed random numbers between 0 and 10, with a mean value of 5.
Another way to do it is with a simple lookup table. Create a table of, say, 100 integers, then fill it with numbers in a Gaussian distribution: 10 zeros, 9 ones, 9 negative ones, 8 twos, 8 negative twos, 7 threes, 7 negative threes, and so on down to 1 nine and 1 negative nine. Whenever you need a Gaussianly-distributed random number between -9 and 9, choose one of the table values at random and use it. (This example isn't literally bell-shaped; it's shaped like a triangle, but it may be close enough for your application. You can use a larger table for a more precise approximation. Microsoft Excel has a function which generates Gaussianly-distributed random numbers if you need to know what to put in the table). This method means you only have to call the random number generator once.
Finally, there's one more method which I include for the sake of completeness, although I don't recommend it. You can compute the equation:
BELLRAND = SQRT(-2 * LN(RAND())) * COS(2 * PI * RAND())
BELLRAND will be a Gaussianly-distributed floating point value. The mean value will be zero and the standard deviation will be 1. It assumes that RAND() is a function which returns a uniformly-distributed random floating-point value between 0 and 1. However, it's very slow. Any formula that calls the square root, natural log, and cosine functions probably has no business being in a computer game. And one other warning about this equation: unlike the additive or lookup methods above, this method has no upper or lower bound.
In extremely rare cases, it will return an extremely large negative or positive number. You may need to set artificial limits on the result it returns.
In my previous article I argued against encouraging human diversity in on-line environments, because I don't think on-line environments are ready for it. Here I AM arguing for diversity in our artificial characters -- because, with the advent of polygon people, I think we ARE ready for it. We're on the threshold of a whole new generation of visually fascinating computer games. If anyone has already done this, or is contemplating doing it, please let me know!