Tutorial

This tutorial currently covers version 0.2a of XTiles.

This tutorial is meant to show you how to get started with XTiles. After you setup your environment, using XTiles in your program is really simple and straightforward, as you'll see in the following sections. If the documentation which comes bundled with XTiles isn't enough, then read on...

I have only tested the current version of the library with Microsoft Visual C++ 2010 on Windows 7, and this tutorial assumes that you are also developing in this same environment. You don't need to have the Professional edition of MSVC, it works perfectly fine in the Express edition. Also, remember that XTiles is built on top of SDL, so you need to have it installed somewhere in your computer.

How to setup XTiles with MSVC in 15 steps

1. Go to File > New > Project > Empty Project;
2. Setup the project name, path, and everything;
3. Create a new source file in your project, such as Test.cpp;
4. Click with the left button on the name of the project in the Solution Explorer, then click on "Properties" on the popup menu;
5. Go to Configuration Properties > Debugging;
6. In "Environment", enter the following (replace C:\SDL\lib with the path where you have the files SDL.lib and SDLmain.lib, and replace C:\XTiles with the path where you have XTiles.lib): PATH=C:\SDL\lib;C:\XTiles;
7. Go to C/C++ > General;
8. In "Additional Include Directories" add the directory where you have the SDL headers and the directory where you have the XTiles headers.
9. Go to Linker > General;
10. In "Additional Library Directories" add the directory where you have the SDL library files (SDL.lib and SDLmain.lib) and the directory where you have the XTiles library file (XTiles.lib);
11. Go to Linker > Input;
12. In "Additional Dependencies" add SDL.lib, SDLmain.lib and XTiles.lib;
13. Go to Linker > System;
14. In "Subsystem" select the option named "Windows (/SUBSYSTEM:WINDOWS)";
15. Click OK and you're done (with the compiler setup).

Testing your environment

Now, let's test your environment to see if you can compile a program that uses SDL and XTiles. In the source file that you created in the previous section, type the following program to test if at least SDL is OK:


#include "SDL.h"
#include "Xtiles.h"

int main( int argc, char* argv[] )
{
    SDL_Init( SDL_INIT_VIDEO );
    SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );

    SDL_Event evt;
    bool running = true;

    while ( running )
    {
        SDL_PollEvent( &evt );

        switch ( evt.type )
            case SDL_KEYDOWN:
                if ( evt.key.keysym.sym == SDLK_ESCAPE )
                    running = false;
    }

    SDL_Quit();
    return 0;
}


Now, save this file and press F5 (or go to Debug > Start Debugging). If everything is OK you will see a blank window appear. Then press ESC to quit. This means that SDL is working.

Hello World

Now to check whether XTiles is also OK, add the following lines after "bool running = true" and before "while ( running )":


    XTiles::generateTileset();
    XTiles::generatePalette();
    XTiles::drawString( screen, 0, 0, 1, 2, 4, 4, "Hello World!" );
    SDL_Flip( screen );


Notice how every XTiles function is safely wrapped inside the namespace XTiles. If you just hate this "XTiles::" thing, just add "using namespace XTiles;" before the functions so that you can get rid of the namespace prefix. Now save the file again and press F5 to debug. You should see the following:




Now let me explain what you just did to make that happen:

The function generateTileset() creates a default tileset which has 512 tiles. The default tileset contains 256 ASCII characters in the first half (from 0x00 to 0xFF), which are based on a certain version of the IBM-PC character set, and 256 blank tiles in the second half (from 0x100 to 0x1FF). If you don't call this function, you can't write unless you first create the tiles containning those characters or any other characters you like (you'll learn how to do this in the next tutorial). In the following image you can see the first half of the default tileset generated by XTiles (the other half is blank):




The function generatePalette() creates a default color palette, which has 256 colors. The default XTiles palette looks very much like the Atari 5200 palette, except that the indexes are all screwed up. In fact, this is the palette generated by default (click to enlarge):




Now why do we need to generate a default tileset and palette? Because most XTiles functions which draw tiles require that you indicate the index of a tile and the index of colors from the palette.

In the example above, the function that actually writes to the screen is drawString(). This function draws a string of tiles at a given location on the given SDL surface, with the given colors and at the given size. The parameters are passed in the following order: drawString( the SDL surface, X coordinate, Y coordinate, foreground color index, background color index, horizontal stretch of tiles, vertical stretch of tiles, string to write ).

The SDL_Flip() function belongs to SDL and it's used to update the screen. You always have to call this function after drawing tiles with XTiles, so that's why we call it after using drawString(), otherwise the "Hello World!" wouldn't have appeared.

Well, now that you can draw a colorful string, try changing the parameters, such as the X and Y coordinates, the color indexes, the size of the tiles, etc. and see what happens. When you are ready, let's go for the next tutorial.

Customizing the palette

It's very easy to change the colors in the palette to whatever you like. For that purpose, there is the setColor() function. Its parameters must be in the following order: setColor( palette index, RGB color in the 0xRRGGBB format ). Any color can be defined by a so-called "hex triplet", which is just a hexadecimal value representing red, green and blue color intensities. So, for example, if you want to set the color at index 0xFF to bright yellow, the following line is enough: setColor( 0xFF, 0xFFFF00 ).

Customizing the tileset

The default tileset containning all of the 256 ASCII characters may be enough for roguelike games or text-based games. But what if you'd like to change those characters? Or what if you'd like to use the default ASCII characters and also create new characters in the second half of the tileset? Well, as you'll see now this is extremely easy and simple to do.

Add the following code to your source file, in the same place where you had added the "Hello World!" example code in the previous section:


    XTiles::setTile
    (
        0x100,
        "00111010",
        "00101010",
        "00111010",
        "00010010",
        "11111111",
        "00010010",
        "00101000",
        "01000100"
    );

    XTiles::drawTile( screen, 0x100, 0x84, 0x00, 10, 6, 4, 4 );
    SDL_Flip(screen);


What's happening there? The setTile() function is used to customize any tile in the tileset. As parameters you need to provide the index of the tile you want to customize (from 0x000 to 0x1FF), followed by eight "binary strings" each containning exactly eight characters, no more, no less. Now, what I call "binary strings" are strings of characters containning only '0's and '1's. Each character '0' or '1' represents a pixel of the tile. A pixel '0' is drawn using the background color, and a pixel '1' is drawn using the foreground color. These colors are only determined when you draw the tile with drawTile(). The order of the parameters for setTile() are as follows (each "line" refers to a line in the tile): setTile( tile index, line 1, line 2, line 3, line 4, line 5, line 6, line 7, line 8 ).

Anyway, this is what you should see after compiling the example code above:




That small figure is the tile at index 0x100 that you've just customized through setTile() and the binary strings. The drawTile() function is used to draw any tile from the tileset, using any two colors from the palette for the background and foreground. The tile can be drawn at any location and size, and it can be aligned to the grid (as it does by default). The parameters to this function are in the following order: drawTile( the SDL surface, the tile index, foreground color index, background color index, X coordinate, Y coordinate, horizontal stretch, vertical stretch, align to grid ). The last parameter, "align to grid" is optional and true by default. If you set it to false, then the X and Y coordinates will not be relative to its total size but to the size of each of its pixels.

You can also customize the tileset by assigning a Tile structure to a tile index, by using an overloaded version of setTile(). A Tile structure is a built-in type in XTiles, it contains 64 integer values representing the pixel data of a tile. You could replace the previous example with the following code and achieve exactly the same result:


    XTiles::Tile myTile =
    {
        0,0,1,1,1,0,1,0,
        0,0,1,0,1,0,1,0,
        0,0,1,1,1,0,1,0,
        0,0,0,1,0,0,1,0,
        1,1,1,1,1,1,1,1,
        0,0,0,1,0,0,1,0,
        0,0,1,0,1,0,0,0,
        0,1,0,0,0,1,0,0
    };

    XTiles::setTile( 0x100, myTile );


This version of setTile() requires the index of the tile you are customizing followed by a reference to a Tile structure. It is mostly useful when you want to create multi-color tiles instead of two-color tiles, as you'll learn in the next tutorial.

Creating and drawing multi-colored tiles

XTiles goes beyond drawing tiles with just two colors. You can actually draw tiles containning up to 64 different colors (since every tile has only 64 pixels). The colors in multi-colored tiles can be either indexed or direct. You can determine which color mode to use when you draw a multi-colored tile through the drawTileMC() function.

The drawTileMC() function works almost like drawTile(), except it interprets the tile data differently, and it expects different parameters. The order of parameters is as follows: drawTileMC( color mode, the SDL surface, tile index, X coordinate, Y coordinate, horizontal stretch, vertical stretch ).

There are two color modes, and you can pass an XTiles enumeration as a parameter to the drawTileMC() function: MULTICOLOR_INDEXED for indexed color mode and MULTICOLOR_DIRECT for direct color mode. Depending on which mode you choose, the function will interpret the tile data differently, as follows:

In indexed color mode, each pixel value in the tile refers to an index in the color palette. In direct color mode, each pixel value in the tile is an absolute color value in the format 0xRRGGBB.

The steps to draw a multi-colored tile as as follows: create an instance of the Tile structure and initialize it with pixel values. If you intend to use the indexed color mode, then the pixel values must be between 0x00 and 0xFF, referring to color indexes in the color palette. Otherwise, if you intend to use the direct color mode, then you don't need to care about the color palette, because every pixel value is just a hex triplet in the format 0xRRGGBB.

To illustrate the creation and drawing of multi-colored tiles, type the following code in your source file:


    XTiles::Tile myTile =
    {
        0x000000,0x000000,0xFFFF00,0xFFFF00,0xFFFF00,0x000000,0x00FFFF,0x000000,
        0x000000,0x000000,0xFFFF00,0xFFFF00,0xFFFF00,0x000000,0x00FFFF,0x000000,
        0x000000,0x000000,0xFFFF00,0xFFFF00,0xFFFF00,0x000000,0x00FFFF,0x000000,
        0x000000,0x000000,0x000000,0x00FF00,0x000000,0x000000,0x00FFFF,0x000000,
        0xFFFF00,0x00FF00,0x00FF00,0x00FF00,0x00FF00,0x00FF00,0xFFFF00,0x000000,
        0x000000,0x000000,0x000000,0x0000FF,0x000000,0x000000,0xFF0000,0x000000,
        0x000000,0x000000,0x0000FF,0x000000,0x0000FF,0x000000,0x000000,0x000000,
        0x000000,0x0000FF,0x000000,0x000000,0x000000,0x0000FF,0x000000,0x000000
    };

    XTiles::setTile( 0x100, myTile );
    XTiles::drawTileMC( XTiles::MULTICOLOR_DIRECT, screen, 0x100, 10, 6, 4, 4 );
    SDL_Flip(screen);


The code above when compiled and run will generate a multi-colored tile of a little man with a sword, his head and hands yellow, his shirt green, his pants blue and his sword cyan and red. The setTile() function you already know, it doesn't change here. The drawTileMC() is passed the direct color mode because every pixel value is just an RGB hex triplet. Then we call SDL_Flip() to update the screen as usual. You should see the following:




If instead of using custom colors you just want to use indexed colors from the palette, you'd have to change the pixel values to be equal to the color indexes in the palette corresponding to the color you want each pixel to be, and also change the color mode to indexed mode in the drawTileMC() function call. Try playing around with these functions and see what happens.

Saving and loading the tileset and palette

As a convenience, XTiles provides four simple functions which can be used to save and load the entire tileset and palette to and from binary files. When saving, if the files already exist, they will be overwritten, otherwise they will first be created. When loading, if the files do not exist, the behavior is undefined.

The saveTileset() function requires only a string containning the path of a disk file, to which it will simply "dump" the entire Tileset structure at once. Likewise, the savePalette() function requires only a string containning the path of a disk file, to which it will simply "dump" the entire Palette structure at once.

The loadTileset() function requires only a string containning the path of a disk file, from which it will read an entire Tileset structure. Likewise, the loadPalette() function requires only a string containning the path of a disk file, from which it will read an entire Palette structure. These functions assume that the files it is loading have been saved through the corresponding saveTileset() and savePalette() functions. If you try to load a file which is in another format, or if the file is somehow damaged, the behavior is undefined.

Other functions

Now I'm going to show you some other XTiles functions.

You can fill an entire SDL surface with copies of the same tile. Just use the fill() function. It needs the following parameters: fill( the SDL surface, the tile index, foreground color of the tile, background color of the tile, horizontal stretch of the tile, vertical stretch of the tile ).

You can clear the entire SDL surface to some color from the palette, by using the clear() function, passing as parameters the SDL surface followed by a color index.

You can reset (clear) the entire tileset and palette through the clearTileset() and clearPalette() functions, respectively. Clearing the tileset updates every tile with blank data. Clearing the palette changes every color to black.

If for whatever reason you need to know what color is at any index of the palette, you can use the function color( palette index ) to retrieve the RGB value. Likewise, if you need to know what tile is at any index of the tileset, use the function tile( tileset index ) to retrieve the Tile structure.

And that's all folks!