This article was published as:

"Automating Game Tile Creation"
 PC Techniques, Vol. 5, No. 1
 Apr/May 1994, page 65

What appears here is the original manuscript, as submitted to Jeff
Duntemann. Any changes in the published version are due to Jeff's
expert editing. There is a code file that goes with this, see QFRIP.ZIP.


                       Designing a Tile Ripper
                     copyright 1994 Diana Gruber

Game programming is not all glamour and code, a lot of it is quite tedious.
One of the most tedious jobs is preprocessing artwork so that it will fit
into a game. Sprites, after they are drawn, must be measured and cataloged
and indexed and stored, so they can later be allocated and read and
displayed. Likewise, background tiles must be arranged in a file and
indexed so they can be rebuilt into the marvelous large scrolling worlds
necessary for action/arcade games.

A game programmer will find his development time greatly reduced if as many
of these tasks as possible are automated. Sprite editors trim and measure
and store sprites. Level editors build levels out of blocks of tiles. But
where do the tiles come from originally? Your artist creates a picture and
sends it to you in a PCX file, and you must break it down into the minimal
number of tiles required to create the background. Doing this by hand would
require painstakingly cutting out 16x16 areas and visually comparing them
to other areas on the screen, then storing and indexing them -- a nearly
impossible task! Small changes to the artwork would require the work be
started over again from the beginning. Even if you don't make any mistakes,
a job like this will take you all day. There has to be a better way.

The answer, of course, is to write a tile ripper. A tile ripper will take
raw artwork and reduce it to its elemental tiles. The basic concept is
quite simple. The artwork is displayed on one video page. The ripper starts
at the upper left corner, picking up a 16x16 bitmap, and storing it in RAM
and on another video page. Then it picks up a second bitmap and compares it
to the first copy in RAM. If it finds a match, it throws out the second
tile, and indexes the level map with the first tile. If there is no match,
the new tile is stored on the hidden page, and the tile library is
increased by one. Subsequent tiles must be compared to the first tile, the
second tile, and any other tiles which are found to be unique. Eventually,
the tile page contains only unique tiles, and the picture is stored as an
array of indices into the tile library.

As the tile ripper progresses, it "blacks out" the duplicate tiles, leaving
only the unique tiles visible. There's no good reason for doing this,
except it makes the rip more fun to watch.

After the ripper has reduced the picture to its elemental tiles, it writes
out the level to a binary file, and also creates a pcx file containing the
tiles. Finally, the ripper checks its work by reconstructing the original
picture from the tiles, and displaying it on the visual page.

The tile ripper will read and process more than one input file. The total
number of input files will vary according to the complexity and amount of
duplication in the artwork. The Quickfire background has a lot of blue sky,
and all the completely blue tiles are identical. I ripped approximately
five pcx files of background art to create the Quickfire sky.

A tile ripper should not be confused with a level editor. The purpose of a
level editor is to build game levels by moving around blocks of tiles,
adding and deleting rows and columns, changing the tile attributes, etc. I
will release some level editor source code in a future article. The tile
ripper creates the raw levels that are used as input to the level editor.
Once you have the ripper data, you can use the level editor to create
create several levels out of one tile set. In the case of Quickfire, I
created a vast expanse of blue sky, and placed the clouds on it in such a
way as to give the impression of a large, non-repeating background.

Our tile ripper will generate no more than 240 unique tiles. This number
was chosen for several reasons. It is the number of 16x16 tiles that will
fit on one 320x200 screen. Having no more than one screen of tiles makes
them easy to manage. You can view the tiles with a paint program or level
editor, and you can store them all on one page in video memory. Perhaps
most important, if you have fewer than 256 tiles you can define your level
as an unsigned char array. If you have more than 256 tiles, you must use
integers in your level array, which will double its size. Since level
arrays are allowed to become quite large, this is a non-trivial
consideration. It could be the difference between storing your level array
in near memory or far memory, for example, which is the difference between
using the medium and large memory model. Changing memory models is more
than a size consideration, it also causes a potential degradation in speed.
A larger level array will also mean you have less room in RAM for sprites
and music, and you may have to do more disk accesses.

Of course, like all game design decisions, one must always consider the
trade-offs. If you have compelling reasons to allow more than 240 tiles in
your tile library, then by all means modify the tile ripper to accomodate
them. You can store the extra tiles on page 2 or page 3, which are not
being used by the tile ripper. Fitting them into your game is a another
matter, but it can certainly be done.

A tile ripper is a useful utility that will save a game developer time and
aggravation. The dedicated game developer will have a personalized
collection of such utilities and will be adept at using them. Any time
you find yourself doing a repetitious task, try to find a way to get the
computer to do it for you. A few hours spent developing a utility can shave
weeks off the game development cycle.



                               - Figure 1 -


 +------------------------------------+
 |                                    |
 | +-----------------------------+    |
 | |                             |    |
 | |                             |    |
 | |                             \/   \/
 | |  +------------------+     +-----------------+    +--------------+
 | |  |oooo|             |     |oooo|xxxx|       |    |oooo|         |
 | +--|  0 |             |     |  0 | 1  |       | +->|  0 |         |
 |    |----+             |     |----+----+       | |  |----+         |
 |    |oooo|             |     |  |   |          | |  |oooo|         |
 |    |  1 |             |     |  |   +------------+->|  0 |         |
 |    |----+             |     |  +----------------+  |----+         |
 |    |xxxx|             |     |                 | |  |xxxx|         |
 +----|  2 |  original   |     |                 | +->|  1 |         |
      |----+  picture    |     |                 | |  |----+         |
      |xxxx|             |     |     tiles       | |  |xxxx|         |
      |  3 |             |     |                 | +->|  1 |         |
      |----+             |     |                 |    |----+         |
      |                  |     |                 |    | reconstructed|
      |                  |     |                 |    |  picture     |
      +------------------+     +-----------------+    +--------------+
    
          visual page               hidden page         visual page
          before rip                                     after rip


                               Figure 1

In this example, tiles 0 and 1 are duplicates, so 1 is discarded. Tiles
2 and 3 are also duplicates, so 3 is also discarded. Tiles 0 and 2 are
the only unique tiles, and they are renumbered to 0 and 1 and stored on
the tile page. The picture is reconstructed by displaying multiple copies
of the two unique tiles.

