|
On the fourth Monday of each month, we explore the code underneath The Broken Hourglass, the game environment called "WeiNGINE." This month, we look at the basics of creating a sprite--an in-game graphical representation of a character, monster, or special animated scenery object. If it walks, talks, swings a weapon or just gently moves across the screen in The Broken Hourglass, chances are that it's a sprite. Because WeiNGINE uses 2D graphics techniques, most animated objects, from heroes to water fountains, are represented by sprites. Conceptually, sprite animation works much like a flip-book. Instead of pages, the engine flips through small PNG images. To make a character walk across the screen from right to left, that character's sprite has 12 frames which represent a complete, looping walk cycle. In theory, these images could all be drawn by hand. In practice, this would be impractical. Animating a single humanoid hero requires roughly 4,600 frames. Add in the full roster of available equipment for a hero sprite, and the total leaps to nearly 30,000 frames! As a result, the frames are generated not with traditional 2D drawing techniques but through 3D animation software. Models are created, rigged, and animated in a 3D rendering package and then the results are saved as sequences of PNG frames, specially labeled so that the sprite files used in the engine can find the right images at the right time.
This will not be a complete tutorial on the step-by-step mechanics of the rendering process, although we will share important details about camera angle and related information at a later date. Instead, this article serves as an introduction to important concepts both on the artistic as well as on the implementation side of sprites. Defining a sprite is done much like defining almost any other resource in the game--with a special XML file in the sprite namespace. A sprite file describes one or more actions that a creature in the game may take. The most basic action (and the one which ultimately almost every action will default to, if undefined) is called "Standing" or "Standing1".  A mesh of an in-game sprite
A simplified example is below. We will explain each attribute in turn.
<sprite> <variant_3 name="mhhero1" base="mhhero1" image="mhhero1-DIRECTION-FRAME" recoloration="generic-6" equipanim="mh-equip" action="Standing1 21 30" action="Standing2 31 40" action="Standing3 41 54" fps="8" w="155" h="155" cx="77" cy="107" /> </sprite>
This code represents part of the definition of the "mhhero1" sprite: Male Human Hero #1. He can't do much--all he can do is stand around in three different poses or mini-animations. Each field is described below.- <sprite> & </sprite>: These tags wrap around the sprite resource and are necessary for the XML parser to understand the data.
- <variant_3>: This entire sprite is described as a single "variant_3" asset. There are three different methods which can be used to describe a sprite to the engine. variant_3 is the most comprehensive and flexible and therefore is the most commonly used.
- name & base: These attributes are used internally by the engine to designate and keep track of the sprite. They should be unique from sprite to sprite. Usually "name" and "base" will be the same for a given sprite.
- image: This field provides the format for the individual PNG frames associated with this sprite. DIRECTION and FRAME are special replacement keywords. DIRECTION will be replaced internally by the code for the direction the creature is facing, taken from the numeric keypad (7 is northwest, 6 is east, etc.) FRAME will be replaced by the number of the frame to load. By default WeiNGINE looks for four-digit frame numbers, but this setting can be overridden at the individual sprite level.
- recoloration: Recoloration is an advanced topic which we will only gloss over here. Some sprites can be customized by recoloring some or all of their regions. "generic-6" indicates that this sprite can be recolored in 6 different regions--typically the maximum, and on a humanoid sprite representing hair, skin, and four different clothing or accessory colors. Some sprites cannot be recolored at all, while others, like some types of equipment, offer just two or three different recoloration zones.
- equipanim: In order for a sprite to display equipment (helmets, swords, armor, etc.) the engine must know how to associate different items with the correct equipment sprite to layer atop the base sprite. If a sprite has an equipanim defined (another advanced topic we will only gloss over in this introduction) then implicitly it is a "body" sprite and when a creature using that sprite equips an item, the engine will look at the equipanim file to locate a matching sprite for that item and layer it on the body. Multiple sprites may share the same equipanim-for instance, all four Male Hero bodies share the same equipment sprites, as they look different but are animated the same.
- action: The frames associated with each type of sprite action are listed in an "action" attribute. This sprite has three Standing sequences, so it can do three different things while standing around idle (not attacking anyone, not walking, not casting any spells, not dying, etc.) The two digits represent the low and high frame number, respectively, the engine should seek while playing those sequences. So the Standing1 sequence plays frames 0021 through frame 0030. Note that Standing3 uses more frames than the other sequences. This is legal. The total number of frames in each action sequence can be different per sprite and between sprites.
- fps: The frames-per-second to play the specified actions at. So in this example, Standing1 will be played over a period of 1.2 seconds. Note that FPS may, and often will be, different for different actions. Attacking and dying sequences tend to use more frames, and play more per second, than standing-around or walking-around sequences.
- w & h: These values tell the engine how wide and high each frame should be rendered on-screen. Most sprites are displayed at the same proportions they were rendered at--the mhhero1 PNGs are in fact all images measuring 155x155. If we put different values in here, however, the engine would automatically scale the images to the specified size. Typically this is only used to make sprites smaller, or occasionally slightly larger, to avoid unpleasant pixellation and stretching effects.
- cx & cy : These values tell the engine where to place the "center dot" of the sprite--typically, for humanoids, this is the space between the feet. This value determines the center of the sprite for purposes of determining its solidity--the space it occupies on the map which other creatures cannot intrude upon. It also determines where the "foot circle" is drawn--with this CX/CY as the center.
A list of valid action sequences ("appearance modes") follows. Not all sprites will use all of these sequences.
- Standing1 through Standing3. Standing1 is the ultimate default for all appearance modes--if a sprite isn't defined to take a certain action, it will simply appear to be standing around.
- Walking
- Attacking1 through Attacking3. By convention, these animation sequences are used for one-handed weapons or bare fist, with shield if applicable. The engine sequences through the three different Attacking sequences (if available) for variety.
- Kick. This is a special "unarmed attack sequence" which is played, along with Attacking1 through Attacking3, when the creature is attacking without a weapon (or with something like brass knuckles.) It is optional, but helps add variety for fighters who prefer bare-knuckle engagements.
- Attacking4 through Attacking6. By convention, these animation sequences are used for two-handed weapons.
- Ranged1 through Ranged3. By convention, these animations sequences are used for bow-type weapons, or for the first ranged weapon in a creature's arsenal.
- Ranged4 through Ranged6. By convention, these animation sequences are used for crossbow-type weapons, or for the second ranged weapon (if applicable) in a creature's arsenal.
- Casting1 through Casting3. Used for spellcasting animations.
- Falling. This animation is played as a creature dies (or is "knocked down.") It is played in reverse when a creature is revived.
- Dead. Typically this is set to be the last frame of Falling. (action="Dead 120 120", etc.) It could also be an arbitrary frame or animation, however.
Other sprite trivia:  A 3D representation of a model with equipment layers present Sprites may have eight unique facings, representing compass points. With extremely little overhead, the engine can "flip" a sprite frame across either its X or Y axis, which for animated sprites such as creatures and characters means that certain facings can be reused without having to store an extra frame on disk and in memory. Either the 7-4-1 or the 9-6-3 directions may be mirrored, or none at all--the decision can be made at the individual sprite level (different sprites may use different mirroring schemes, or use unique frames for all 8 directions.)
All creatures have sprites, but not everything which uses a sprite is a creature. Area animations (a running fountain, a glowing crystal ball, etc) use sprites. Typically an area animation will only employ "Standing" actions. Visual effects (a spike trap shooting out of the floor, a spell impact graphic, etc.) also use sprites, but depending on the nature of the effect, may employ more than just a single Standing animation.
Typically sprites will use PNG frames. JPEG frames could be used as well, although this is rare.
Sprites may be layered on top of one another. This is most typically done when a character or creature equips some item or has some quality which needs to be reflected with additional graphics. Equip a sword in the female elven heroine's hand, and the female elven sword is overlaid atop the female elven heroine body. Different "layers" of equipment have different priorities, so that, for instance, shields are applied after armor. This layering priority is handled automatically.
|