Game Development Community

Making ImageMap mode = "key" work

by Jason Cahill · in Torque Game Builder · 07/23/2005 (7:13 pm) · 3 replies

This turned out to be a little nonobvious so I thought I'd share how this works with everyone so that they don't have to figure this out from scratch (or with Melv's help, as it was in my case).

fxImageMapDatablock2D supports three modes: full, cell, and key. Key is used specifically for a collection of images that are of different sizes or a collection of images with a single-pixel color key between your images, regardless of size. The later case means that you can use mode = "key" for sprite sheets that have sprites all of the same sizes too (like cell), but specifically want to have a single-pixel wide color border between the sprites. Because this color key is made transparent by T2D during loading, this has the advantage of eliminating the texture bleeding that occurs when sprite sheets are tiled without the border.

The sprite packing format is very important to get right. If you get this wrong, T2D will either not "acquire" any images, or will acquire the wrong number of them. The rules for creating proper mode="key" images are as follows:

1. You must use an image that has widths and heights that are powers of two (e.g., 128x128, 256x64, etc)
2. The color of the pixel in the top-left corner of the image is your "color key" (e.g., magenta 0xFF00FF)
3. You must use an image format that doesn't degrade, since your color key must always be exact (e.g., BMP, PNG, GIF)
4. For simplicity, the top row of the image should consist of your "color key" (e.g., magenta)
5. The first sprite tile of each row must begin at x = 0 (i.e., you should not have your color key at x=0, unless you are trying to start a new row of sprite tiles)
6. Between each sprite tile within a row, you should have a one pixel wide border in your color key
7. If you have left over space between your last sprite tile in a row and the width of your image, you should color it with your color key
8. You should separate "rows" of sprite tiles with your color key
9. Because sprite tiles can be different sizes, it is up to you to reset the size of the sprite every time you change the image frame

Now, because this is probably as clear as mud for some of you, here are some sample pictures:
mysite.verizon.net/jasoncahill/CourierNewFont.png
mysite.verizon.net/jasoncahill/NineTiles.png
The first image is the Windows "Courier New" font rendered into a sprite sheet using PhotoShop. Courier is a fixed-width font, but you can imagine using this technique for proportional fonts, like "Arial".

The second image shows nine completely differently sized tiles. Here's the datablock definition for using both in your code:

datablock fxImageMapDatablock2D(CourierFont)
{
   mode = key;
   textureName = "~/client/images/CourierNewFont.png";
};
 
datablock fxImageMapDatablock2D(NineTiles)
{
   mode = key;
   textureName = "~/client/images/NineTiles.png";
};

Then, to use these, simply create a sprite and map the image:
$char = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
$char.setSize("1.9 2.9");
$char.setImageMap(CourierNewFont, 0);
$char.setPosition("0 0");
 
$tile = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
$char.setSize("1.7 3.6");
$char.setImageMap(NineTiles, 0);
$char.setPosition("10 0");

#1
07/23/2005 (7:20 pm)
Excellent post. I was just about to have to use this feature. Needless to say I'm not glad that you had to go through the headache of figuring it out, but I AM glad that you shared it :)
#2
07/24/2005 (2:44 am)
Thanks for the write-up Jason, very helpful.

EDIT: One minor modification is that you don't have to have only a single-pixel horizontal/vertical between the frames themselves as T2D should search for the next frame in either direction. Each frame should really start on the same pixel-row though as you've shown.

- Melv.
#3
06/17/2006 (10:17 pm)
You dont even want to know how much time this saved me.... Thanks so much for sharing this, converting my images to POT and shifting them to start left saved me from redoing some time consuming art. I had a starting border on the left blowing me up.. weeeeee