Case Study: Character Animation

       A video game company wanted to make the animation of the characters in its games more realistic. After viewing a sample of their games, I suggested that they could concentrate on the motions of the characters' arms.

       Each video game consists of a series of pictures, or frames, with each frame depicting one instant in the action. About 30 frames are generated and displayed per second, so that all of the computation to generate each frame must be completed within about 30 milliseconds.

       Frames are generated back to front. That is, the things furthest from the player's viewpoint are placed first, and successively closer objects are placed on top of the prior images. So a frame might be made up by placing the sky, then distant hills, then individual trees on the hills, then a castle, a road leading to the castle, horses on the road, and finally knights on the horses, starting with the horse and knight furthest from the viewer.

       All of the games follow nearly the same plot line. The good guys must battle and defeat the evil knights, the invading motorcycle gang, the aliens in the space station, etc. The action is mostly pairs of characters fighting one on one.

       The video game portrays characters in motion by first displaying the body with the legs in one of four positions, standing, crouching, walking left leg forward, and walking right leg forward. The crouching position is used either to escape a blow, or to prepare to leap. These four images are stored, and can be displayed in either left or right profile, for a total of 8 positions. For some characters there is also a front and/or back view, which enables the character to switch between left and right profiles through an intermediate position. These are views, however, are static.

       For each type of character there is one mode of attack, which is shown as a sequence of 3 arm/weapon images. For boxing characters, using a fist, brass knuckles or spiked glove, the arm is shown cocked, half-extended, or fully extended, as a sequence of 3 stored images. For vertical weapons, such as swords, maces or warhammers, the arm and weapon are shown as a sequence of 3 positions, straight up, halfway down, and horizontal. The same image is used for all 3 positions, rotated by 45 degrees each time, so the elbow and wrist always maintain the same angles. For horizontal weapons, such as a whip, bola or saber, the arm is shown pointing straight at the viewer, rotated halfway, and pointing straight at the opponent. These weapons get 3 separate images to show their motions, but the arm is rigid; it always has the same angles at the elbow and wrist. Thrusting weapons, such as a spear or trident, combine the same 3 positions of the boxing arm with the weapon moving along a straight horizontal line.

       The image of the rear arm, the arm away from the player, is either kept static, or moved opposite to the forward arm, so that both arms form an approximate straight line. In some cases one or two regions of the clothing on the arm get colored so that different characters of the same type will have different colored garb, albeit always of the same cut and fit.

       The net effect was jerky unrealistic battles, made even less lifelike because characters of different types all had arms of the same shape, with the same angle at the elbow. The images of each character are scaled according to the distance from the player's viewpoint. The arms and weapons get scaled twice, first for the size of the character, and then again for the distance from the viewer.

       My suggestion was to divide the arms into three sections. The upper section would contain the shoulder joint and upper arm. The middle section would contain the elbow joint and forearm. The lower section would contain the wrist, hand and weapon. The upper and middle sections could be the same for all characters, but with the length and width scaled according to the size and type of the character.

       The animation of the arm would be done from the shoulder down. First the upper section is rotated a fixed amount around an imaginary pivot point at the center of the shoulder. This establishes the pivot point for the middle section of the arm. That moves through a specified arc to establish the pivot point for the lower section.

       The Pascal Macro Compiler could be used to generate a separate procedure for each class of characters. This generated procedure has built-in the lengths of each arm segment and the character's arm speed, and takes the character's location on the screen as a parameter. This lets it calculate the angle of each arm segment after each step of the arm motion. It is too time-consuming to rotate each arm image between frames, so the routine picks one of the stored images closest to the desired angle. The angle of the stored image, not the calculated angle, determines the pivot point for the next arm segment. Otherwise the arm segments would not align correctly.

       The generated procedure could then paint each portion of the image with the colors of the clothing that the specific character is wearing, and impose the colored images onto the frame in the correct order.

       Using the Pascal Macro Compiler this way, it would be easy to add new characters. It is simply a matter of setting the lengths of the arm segments and the angles moved between frames. This approach would also make it easy to add new motions to the characters, such as bending the knees, bending at the waist, and turning the head.

       The old way of producing these character procedures was to take an existing procedure, and then to modify it with the characteristics of each new class of characters. This works fine until some change is needed for a large number of characters. For example, suppose a new type of motion is required, such as saluting, or pulling a knife from a sheath, or treating the characters' arms as 3 separate segments. With the old method of programming characters, that would mean rewriting all of the character procedures. The great advantage of generating the character procedures using the Pascal Macro Compiler is that this new feature needs to be coded only once. Then all of the character procedures would be generated again, and the change is propagated to all of them automatically.

© Copyright 2005 Frank Rubin