Mapping Tutorial | Tileset Tutorial |
This is the Tileset Tutorial for NWMap versions 1.2 and higher. Tilesets
changed dramatically at v 1.2;
you can still access the old
tileset tutorial for versions < 1.2.
More pragmatically, a tileset is a collection of bitmap images, and two support text files for each bitmap (a tooltip file and a groups definition file). A single tileset may contain up to 5 available layers, each represented by a separate bitmap image, and each requiring its own tooltips and group definition files(*). The layers are drawn sequentially on top of each other, starting with the base layer and working up.
(*: the base layer does not use a groups definition file)
Transparent layering circumvents this problem by separating the "bases" (the grass, dirt, cobblestones, etc.) from the "features" (roads, fences, buildings, etc.), and placing them in separate layers which can be stacked in any possible combination. A key part of this is that the "features" layers contain some transparent pixels, which allow whatever is in the base layer to show through.
Unfortunately, there is no such thing as a transparent pixel in a standard bitmap. However, we can designate a color to represent transparency, and in the NWMap code, do some fancy masking to simulate transparency when the designated color is encountered. We need to pick a color that no one will want to use normally, so that accidental transparency doesn't occur. We have designated pure magenta as the transparent color (RGB = {255, 0, 255}), the theory being that it is such an ugly color that no one will ever miss it :)
Note that only Pure Magenta (RGB=255,0,255) is transparent! Colors that are very nearly magenta (i.e., RGB=254,0,255) will not be transparent, and will show up as bright pink in your maps. I'm making this point because you have to be careful when creating the tileset images. Many image processing routines (such as blur) make subtle changes to the pixel values. I suggest you draw the map using a neutral color like black for transparent regions, and then as a final step, select regions that should be transparent and use your paint program's "bucket" tool to fill them with Pure Magenta.
Every tileset must contain at least one layer, the base layer. The generic outdoor base layer bitmap is shown above. The base layer is a bit schizophrenic; it actually contains two layers in one bitmap! The first column is designated as the "true" bottom layer. The 10 tiles in this column will not be drawn transparently (because they are at the bottom of the stack, and there's nothing below them to show through), so don't put any magenta pixels in these tiles. The rest of the base layer is the "base transitions" layer. These tiles get drawn transparently directly above layer 0. The idea is that these tiles are "base transition tiles"; they allow you to smoothly transition from one base to another.
The base layer is also special because it is the only layer with a predefined tile grouping structure (therefore, you don't need a groups file for the base layer). The 4 leftmost tiles in each row define a separate Box Mode group, and they must be oriented as shown in the above image. See the Section on defining groups for more information.
The Default Tile: The tile in the top left corner is the default base layer for new maps.
A generic test upper layer is shown above. You may have up to 4 upper layers on top of the base/transition layer. However, I will be suprised if anyone needs to use more than one or two of these. One thing to consider when adding additional layers is that transparent drawing is pretty slow (the bitmap must be copied from video memory to system memory, and each pixel's color must be examined), so the program will perform more slowly with each layer added. I have used a couple of tricks to minimize the problem, but it is still noticeable.
The BlankTile: The tile in the top left corner of each upper layer should be left blank. The program does not even attempt to draw this tile if it is encountered in the map. This is one of my time-saving tricks. By pre-defining such a BlankTile, I can initialize new maps to be entirely composed of BlankTiles, which makes drawing the map very fast. Even as the map is filled in, most of the locations will remain BlankTiles, so there is still a significant performance boost.
Other than the BlankTile, you can lay out your tiles however you wish. There has been talk about defining a standard layout, but this is no longer necessary thanks to the groups definition file. However, the users will appreciate some kind of logical layout, and a logical layout (organizing groups along rows or columns) will also make it easier to construct the groups file.
Identifying tiles: Tiles are identified by a number between 0 and 99. Tile 0 is the BlankTile in the upper left corner. Tile numbers then increase from left to right, and then top to bottom (just as if you were "reading" the tileset). So, in the generic Tileset, the tree is Tile 9, the straight road segment is Tile 10, and the bridge is Tile 35. The leftmost tiles are all even multiples of 10, so an easy way to find the number is to count down by 10's, and then count to the right by ones, until you reach the tile.
Specifying rotation: In addition to identifying the Tile's position in the Tileset, you also have to specify the Tile's rotation as drawn. There are 4 possible orientations (numbered 0,1,2,3). The rotation number specifies the number of 90-degree, clockwise rotations required to bring the tile to the default orientation. More on what the "default" means below.
The groups definition file: At last! We're ready to get to defining groups. The groups definition file must have the same filename as its corresponding bitmap, except instead of a "BMP" extension, it should end in "GRP". So, if your bitmap is "CITY.BMP", the group file would be "CITY.GRP". Each group is defined by a single line in the group file. At this point, I will show the group file for the default layer shown above. You may want to display the bitmap in a separate window, so you can follow along.
B:46 0 26 3 36 3 16 0 : Draw Buildings : bldg.bmp S:10 0 11 0 12 0 13 0 : 20 14 1 30 35 1 -1 -1 0 -1 -1 0 : -1 -1 0 -1 -1 0 -1 -1 0 -1 -1 0 : Paint Roads : road.bmp S:20 0 21 0 22 0 23 0 : 10 14 0 30 34 1 -1 -1 0 -1 -1 0 : -1 -1 0 -1 -1 0 -1 -1 0 -1 -1 0 : Paint Walls : wall.bmp S:30 0 31 0 32 2 40 0 : 10 35 0 20 34 0 -1 -1 0 -1 -1 0 : 122 33 0 -1 -1 0 -1 -1 0 -1 -1 0 : Paint Rivers : river.bmp
Each line consists of a number of fields separated by colons. The first field is a single character, and must be a "B" or an "S" (if this is not the case, the line should be ignored by NWMap). "B" indicates the line defines a Box Mode, and "S" indicates a Snake Mode. You can define up to eight of each type of mode.
Since Box Modes are the simplest, I'll start with them. The second field in a Box Mode line contains 4 pairs of numbers, indicating the Tile number and its rotation for the group's interior tile, corner tile, edge tile, and "obtuse corner" tile. So, in the example, the "Draw Buildings" interior tile is Tile 46 (solid white in the bitmap); the corner is Tile 26; the edge is Tile 36 and the obtuse corner is Tile 16. The default rotations for each Tile are given in the following Table (along with the values from the generic group file):
Box Position | Default orientation | example rot. value |
---|---|---|
Interior | Doesn't matter | 0 |
Corner | Transparent along Top and Left | 3 |
Edge | Transparent along Top | 3 |
Obtuse Corner | Open Corner at Top Left | 0 |
Convince yourself that if you rotate each tile clockwise by the number indicated, it will be in the default orientation. That's all NWMap needs to be able to draw the Box Mode! It will automatically place and rotate the interior, edge and corner tiles. The two remaining fields simply specify the String to display when the Box Mode is active, and the 16x16 bitmap to place on the button that activates the Mode.
One more note about Box Mode: The "obtuse angle" tile is not used in box mode. I am planning to implement a mode sort of like Box Mode, but one that can draw more complex shapes...something like "Blob Mode" :) Anyway, this new mode will use the same tile groups as Box Mode, just implement them in a slightly different way (more like Snake Mode).
Let's move on to Snake Mode now. The second field in Snake Mode is similar to Box Mode: it consists of 4 pairs of numbers identifying the Tiles and rotations for the parts required by Snake Mode: straight segment, corner segment, "T" segment, and "Cross" segment. So, for roads, we have defined straight (Tile 10), corner (Tile 11), "T" (Tile 12), and "Cross" (Tile 13) segments. Note that the rotation values are all zero! I was smart enough to draw these Tiles in their default orientations. If you do the same, you can just fill in zeroes here and not worry about confusing rotation values. Just for completeness, here is the Default rotation table for Snake Modes:
Snake Segment | Default orientation | example rot. value |
---|---|---|
Straight | Horizontal | 0 |
Corner | Bottom and Right connects | 0 |
"T" | Left, Right and Bottom connects | 0 |
"Cross" | Doesn't matter | 0 |
Intersections: The next field contains 4 triplets of numbers, each defining an "intersection". Intersections place special tiles down when the Snaking object hits a specified Tile. For example, when drawing a road, if you cross a river, it should place a bridge. The first number in the triplet is the number of the Tile that will trigger the intersection. The second number is the Tile that should replace the trigger Tile, and the third number is the replacement tile's rotation, relative to the trigger tile.
Let's examine the first intersection definition for the "Paint Roads" Snake Mode. The defining triplet of numbers is:
20 14 1
So, the Trigger tile is Tile 20...that's the "straight Wall" Tile. OK, so we're painting a road, and we hit a Wall, what should it do? The replacement tile is Tile 14...that's the "Gate" tile! The rotation is 1, because you'd have to rotate the Gate Tile once to make it line up with the Wall that was there previously. Make sense? See if you can decipher the other intersections.
Note that you can only define up to 4 intersections. If you don't need all 4, use the "-1 -1 0" triplet to indicate an unused slot.
Anchors: Let's say you are painting a river, and you come to a lake. The Mode should be smart enough to know that it should replace the "Lake Shore" tile with a "River Mouth" tile. This is what "anchors" are for: defining an "End Tile" for the Snaking object that should be placed when it sees that it is on an anchor trigger tile. This works similarly to the intersection: the triplet consists of a trigger, a replacement, and a relative rotation. The first Anchor definition for "Paint Rivers" is:
122 33 0
Uh oh. Tile numbers are supposed to be between 0 and 99, so how can I identify the trigger tile with "122"?! Here's the clever bit: You can specify a tile from another layer to be the trigger tile! You specify the layer by adding 100*(layer_number) to the trigger tile's ID. Note that layer_number ignores the fact that the base layer is actually two layers, just count the bitmaps. OK, so Tile 122 means Tile 22 from the first bitmap. It so happens that the first bitmap is the generic outdoor base layer, so tile 122 refers to the straight lake shore tile. The replacement Tile is 33. Since this is between 0 and 99, it is in the current Layer (technically, you can also refer to it as tile 233, since this is the second layer). Anyway, Tile 33 is the "River Mouth" Tile. The rotation is 0 because Tiles 122 and 33 have the same orientation. Again, you can define up to 4 anchor triplets, and use "-1 -1 0" to fill in unused triplets.
The last two fields are the same as for Box Modes: The Mode description string, and a filename for a 16x16 bitmap image for the Mode button.
Like the Groups file, the Tooltips file has the same filename as the bitmap image, except it uses the extension "TIP" instead of "BMP". So, for a bitmap layer named "CITY.BMP", the tooltip file would be "CITY.TIP". The file is a list of 100 strings, one string per line. Each line is the tooltip for a tile in the bitmap. The tooltips are ordered in the same way that the Tiles are numbered (starting in the upper left, moving across rows left to right, and then moving down by rows, just as if you were "reading" the tileset). If a Tile is unused, it should still have a tooltip, like "no Tile" or "nothing" or "unused" or whatever).
File |
Add Tileset...
. The dialog is pictured below:
Enter the bitmap filenames for your layers in the 5 text entry fields near the top, starting with the base layer. Leave unused layers blank. You can also use the Browse button next to each field to select the file in a File Selection Dialog. You don't have to specify the tooltip or group files, they will be resolved from the bitmap filenames. (Note that the TIP and GRP files must be in the same directory as the BMP files). Enter a short name for the Tileset in the field at the top. Hit OK. From now on, you will be able to start a map using your tileset from the File menu, or from the "New Map" toolbar button! There's no need to define your tileset every time you start NWMap, it will remember all custom tilesets.
If you need to remove your tileset, you'll have to open the file "NWMAP.INI" with Notepad, and remove the lines that define your tileset.
Now that you're tileset is available, give it a test drive! Try out all the Group Modes, explore all the intersections and anchors. If anything is not working properly, open up the GRP file and try to fix it. Also, feel free to email/IM me if you can't resolve a problem.
I hope you enjoyed making your tileset! If you have any suggestions for improving the program, this tutorial, or any other documentation, please email nwmap@hotmail.com.