Sprite Assembler Makes Multiframe Sprites a Snap

example A common technique for generating sprite animations on the Yaroze involves the creation of a single TIM file which holds several frames concatenated together. Your program uses the GsSPRITE attributes "u" and "v" to change the in-page offset to pick out the frame it needs. For instance your 128x128 TIM might consist of a 4x4 matrix of pictures, each one representing a 32x32 pixel frame. Then if you want frame #7 you would point u and v to (64, 32). See the illustration to the right.

Typically you would render the animation in a 3-D package and save each frame as a single graphic. Then you need to crop out any excess background, leaving only the object in which you are interested. Next you must resize each frame to meet your game's requirements (32x32 in the above example). Finally you take all of these resized graphics and concatenate them together to get your final file containing the full animation. The Sprite Assembler was designed to automate the copping, resizing, and concatenation steps in that process.

The program reads any number of 8- or 4-bit BMP files, performs each step in sequence, and outputs a final TIM file (or a BMP file if you want to do further manipulations). The entire program is run via command line parameters which makes it simple to place in a batch file.

The remainder of this article details the various functions that the Sprite Assembler performs, and how the user can affect them.

Cropping

The program must first crop all of the input graphics so it's only left with the interesting part of each picture. We will be talking about "cropping rectangles" quite a bit so we first need to tell you what this means to the program. Quite simply it is the largest region in the graphic which only includes sprite information; all empty rows and columns around the border are eliminated. This is represented as a pair of coordinates which indicate the upper-left and lower-right corner of that rectangle.

example Take a look at this figure. Assuming the bitmap's original size is 64x64, the cropping rectangle would have an upper-left coordinate of (11, 16) and a lower-right coordinate of (41, 46).

But just how does the program determine what is considered background and what isn't? This is one of the pieces of information you must give Sprite Assembler. You can select one of two switches. The first tells the program to regard any black pixel as background -- that is, a pixel with its RGB components of (0, 0, 0). The other switch lets you specify a coordinate in your BMP. Whatever color is at that pixel will be considered the background.

example The figure to the left shows two sample BMP files and how they are cropped using each method. Using the first method, the first picture is cropped as we expect, but the second one is not cropped at all because it contains no black around the edges. With the second method, picking a coordinate of (0,0), they are both cropped. This is because the background color is different for both. The color at 0,0 in the first BMP is black while in the second it is red.



You can also select a threshold value which will expand the number of background colors the program sees. If a particular color is within that threshold of the background color (either black or the color at the given coordinates - see previous paragraph) it is cropped as well.

Another option you can give works with the threshold. It tells the program to convert any color within the tolerance to the background color. The table below shows how these two parameters work.

cross
cross
cross
cross
cross
cross
Original No Tol Tol=230 Tol=230 &
Convert
Tol=350
Tol=350 &
Convert

thresh Notice the difference between when you just have a tolerance and when you have both a tolerance and conversion turned on. Why would you want to convert the colors? Suppose you have the image to the right. If you use a tolerance without converting you'll have a bunch of partial circles on the edges (which might or might not be what you want). With conversion on you're left with just the colors outside the tolerance.

Okay, the program now knows how to crop any bitmap we give it. But since we're going to give it several frames of animation how do we tell it how each of these pictures are related? There are two parameters you can specify. The first tells the program to crop each picture individually without regard to the other frames; each cropping rectangle will be independent. The second makes it generate a worst-case cropping rectangle. It reads in each BMP, determines how to crop each one, and selects a single cropping rectangle which will work for all frames such that no data is lost.

The simplest switch tells Sprite Assembler to crop each graphic on its own. It will generate a separate cropping rectangle for each picture. This is useful when you know your object shouldn't move or change size during the animation. The figure at the top of this page is a good example. Each frame of the planet animation should be the same size.

worst The second switch determines a worst-case cropping rectangle and applies that to all pictures. Say we have an animation of a ball bouncing (see figure). If we were to use the previous parameter (which crops individually), we would end up with just the ball; the bouncing effect would be lost. However, by using the second method the program will figure out the minimum cropping rectangle which fits all of the individual pictures. It compares the X and Y coordinates of the the corners that bound each individual cropping rectangle. It selects the worst case coordinate. That is, the coordinate which is most to the outside of the picture. As you can see from the figure, this switch is useful when your object moves around and you want to keep the relative position the same.

Resizing

aspect Now that Sprite Assembler knows how to crop each picture, we have to tell it how large to make each frame. A few parameters let you tell the program the height and width of each frame. You can also tell it to maintain the aspect ratio of each frame if that is important. Take a look at the example. The original picture is 128x64. Suppose we want to reduce this to 48x48. This will result in in the second picture you see.

However, we can tell the program to maintain the aspect ratio of the original. There are two choices. One parameter says that the height and width you give are the maximum values you want and the program should decrease one or the other to maintain the aspect ratio. In this case, the width is the larger of the two dimensions so the it will assign a new width of 48 and compute the new height based on the aspect ratio of the original (24 since it's 2:1).

The second parameter does the opposite. It will take the height and width as minimum values and increase the appropriate dimension. So the height would be fixed at 48 and the new height would be 96 (again, to maintain the 2:1 aspect ratio).

Concatenation

Okay, now we have our individual bitmaps cropped and resized. The last step is assembling them into a single file and writing it out as a TIM (or BMP). A parameter you give tells the program how many pictures to put on each row of the final graphic. So for instance if you have 16 frames of animation and tell Sprite Assembler to put 4 frames on each row, you would end up with a picture arranged into 4 rows of 4 columns (like the one at the top of this page). The program will fill in any unused space with zeroes (CLUT entry 0).

In addition to giving you one concatenated output, Sprite Assembler can also produce all intermediate files (as BMPs). It will save the files after three steps: tolerance conversion, cropping, and resizing. You can take these file and load them in a paint program to perform some operations on them. Then you can use them as inputs to Sprite Assembler to assemble your final TIM.

There you have it!

Your TIM file is ready to be included in your game and you didn't have to do all that boring and tedious cropping/resizing yourself. If you need to change the animation slightly, no problem! Just rerender and then rerun Sprite Assembler with the same parameters and you'll be set. It's a tremendous time saver. Click on the icon below to download a zip containing the program and documentation. If you have any questions please feel free to send me mail.

dsyaroze@concentric.net