Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members   Examples  

IsoTileSet.cpp

Go to the documentation of this file.
00001 
00013 #include <string.h>
00015 #include <malloc.h>
00016 
00017 #include "IsoTileSet.h"
00018 
00020 
00021 IsoTileSet::IsoTileSet() {
00022     tileCount = 0;
00023     tileList = NULL;
00024     tilesetSurface = NULL;
00025     filename = NULL;
00026 }
00027 
00028 IsoTileSet::~IsoTileSet() {
00029     unloadTileset();
00030 }
00031 
00033 
00034 
00035 
00037 
00039 bool IsoTileSet::loadTileset(char* name) {
00040     //Clean up if necessary:
00041     if(!unloadTileset()) {
00042         //Could not clean-up...
00043         return false;
00044     }
00045 
00046     //Store the name of the file:
00047     filename = strdup(name);
00048 
00049     //Load the tileset from a file:
00050     ImageCanvas ts;
00051     if(!ts.loadImage(filename)) {
00052         return false;
00053     }
00054     
00055     //Make the tileset surface a surface equivalent to the canvas:
00056     tilesetSurface = SDL_CreateRGBSurface(((SDL_Surface*)ts)->flags,
00057         ((SDL_Surface*)ts)->w,
00058         ((SDL_Surface*)ts)->h,
00059         ((SDL_Surface*)ts)->format->BitsPerPixel,
00060         ((SDL_Surface*)ts)->format->Rmask,
00061         ((SDL_Surface*)ts)->format->Gmask,
00062         ((SDL_Surface*)ts)->format->Bmask,
00063         ((SDL_Surface*)ts)->format->Amask);
00064     //Blit image from canvas onto the surface:
00065     SDL_BlitSurface(ts, NULL, tilesetSurface, NULL);
00066 
00067     //Copy the dimensions of the image:
00068     int width = tilesetSurface->w;
00069     int height = tilesetSurface->h;
00070 
00071     //Temporary vars for tile bounds:
00072     int* hTileBound = NULL;
00073     int hTileBoundCount = 0;
00074     int* vTileBound = NULL;
00075     int vTileBoundCount = 0;
00076     int xCount = 0;
00077     int yCount = 0;
00078 
00079     //Before grabbing pixels from the surface, lock it:
00080     SDL_LockSurface(tilesetSurface);
00081 
00082     //Temporary colour control vars:
00083     Uint32 transparentColor = getPixel(tilesetSurface, width - 1, 0);
00084     //Uint32 boundColor = getPixel(tilesetSurface, width - 1, 1);
00085     Uint32 anchorColor = getPixel(tilesetSurface, width - 1, 2);
00086     Uint32 insideColor = getPixel(tilesetSurface, width - 1, 3);
00087     Uint32 insideAnchorColor = getPixel(tilesetSurface, width - 1, 4);
00088     Uint32 testColor = 0;
00089 
00090     //Count the number of tile delimiters in a row by scanning the top row of pixels:
00091     vTileBoundCount = 0;
00092     for(xCount=0; xCount<width; xCount++) {
00093         //Fetch current pixel:
00094         testColor = getPixel(tilesetSurface, xCount, 0);
00095 
00096         //If it is of transparent colour, we got a vertical bound:
00097         if(testColor == transparentColor) {
00098             vTileBoundCount ++;
00099         }
00100     }
00101 
00102     //Now that we have the number of vertical tile bounds, allocate an array of them:
00103     vTileBound = new int[vTileBoundCount];
00104 
00105     //Do the same loop as above again, now to find the coordinates of the vertical tile bounds
00106     vTileBoundCount = 0;
00107     for(xCount=0; xCount<width; xCount++) {
00108         //Fetch current pixel:
00109         testColor = getPixel(tilesetSurface, xCount, 0);
00110 
00111         //If it is of transparent colour, we got a vertical bound:
00112         if(testColor == transparentColor) {
00113             //Add the x coordinate to the list:
00114             vTileBound[vTileBoundCount] = xCount;
00115 
00116             //Increment the list subscript:
00117             vTileBoundCount ++;
00118         }
00119     }
00120 
00121     //Count the number of tile delimiters in a column by scanning the first column of pixels:
00122     hTileBoundCount = 0;
00123     for(yCount=0; yCount<height; yCount++) {
00124         //Fetch current pixel:
00125         testColor = getPixel(tilesetSurface, 0, yCount);
00126 
00127         //If it is of transparent colour, we got a horizontal bound:
00128         if(testColor == transparentColor) {
00129             hTileBoundCount ++;
00130         }
00131     }
00132 
00133     //Allocate the array of horizontal bound coordinates:
00134     hTileBound = new int[hTileBoundCount];
00135 
00136     //Find the coordinates of the horizontal tile bounds:
00137     hTileBoundCount = 0;
00138     for(yCount=0; yCount<height; yCount++) {
00139         //Fetch current pixel:
00140         testColor = getPixel(tilesetSurface, 0, yCount);
00141 
00142         //If it is of transparent colour, we got a horizontal bound:
00143         if(testColor == transparentColor) {
00144             hTileBound[hTileBoundCount] = yCount;
00145 
00146             hTileBoundCount ++;
00147         }
00148     }
00149 
00150     //Compute the number of rows, columns, and tiles altogether:
00151     int numrows = hTileBoundCount - 1;
00152     int numcols = vTileBoundCount - 1;
00153     tileCount = numrows * numcols;
00154 
00155     //Temporary variables for the tile scan:
00156     int currentTile = 0;
00157     bool found = false;
00158 
00159     //Allocate the list of tiles:
00160     tileList = new TILEINFO[tileCount];
00161 
00162     //Scan the tiles in:
00163     for(int rowcount=0; rowcount<numrows; rowcount++) {
00164         for(int colcount=0; colcount<numcols; colcount++) {
00165             //Find the number of the current tile:
00166             currentTile = colcount + rowcount * numcols;
00167 
00168             //Reset the found flag:
00169             found = false;
00170 
00171             //Scan the top row of pixels:
00172             yCount = hTileBound[rowcount];
00173 
00174             //Find the x coordinate of the anchor:
00175             for(xCount=vTileBound[colcount]+1; (!found)&&(xCount<vTileBound[colcount+1]-1); xCount++) {
00176                 //Grab the current pixel:
00177                 testColor = getPixel(tilesetSurface, xCount, yCount);
00178 
00179                 //Check if this pixel is an anchor:
00180                 if((testColor == anchorColor) || (testColor == insideAnchorColor)) {
00181                     found = true;
00182                     tileList[currentTile].ptAnchor.x = xCount;
00183                 }
00184             } //End of find anchor loop
00185 
00186             //Find the first tile pixel (x coordinate):
00187             found = false;
00188             for(xCount=vTileBound[colcount] + 1;
00189                 (!found) && (xCount < vTileBound[colcount+1] - 1);
00190                 xCount++) {
00191                 //Grab the current pixel:
00192                 testColor = getPixel(tilesetSurface, xCount, yCount);
00193 
00194                 if((testColor == insideColor) || (testColor == insideAnchorColor)) {
00195                     found = true;
00196                     tileList[currentTile].rcSrc.left = xCount;
00197                 }
00198             } //End of find inside pixel loop
00199 
00200             //If couldn't find the inside pixel, use default:
00201             if(!found) {
00202                 tileList[currentTile].rcSrc.left = vTileBound[colcount] + 1;
00203             }
00204 
00205             //Find the x coordinate of the last tile pixel:
00206             found = false;
00207             for(xCount=vTileBound[colcount+1] - 1;
00208                 (!found) && (xCount >= vTileBound[colcount] + 1);
00209                 xCount--) {
00210                 //Grab the current pixel:
00211                 testColor = getPixel(tilesetSurface, xCount, yCount);
00212 
00213                 if((testColor == insideColor) || (testColor == insideAnchorColor)) {
00214                     found = true;
00215                     tileList[currentTile].rcSrc.right = xCount + 1;
00216                 }
00217             } //End of find inside pixel loop
00218 
00219             //If couldn't find the inside pixel, use default:
00220             if(!found) {
00221                 tileList[currentTile].rcSrc.right = vTileBound[colcount + 1];
00222             }
00223 
00224             //Now, scan the left column of pixels:
00225             xCount = vTileBound[colcount];
00226 
00227             //Find the anchor:
00228             found = false;
00229             for(yCount=hTileBound[rowcount] + 1;
00230                 (!found) && (yCount < hTileBound[rowcount+1] - 1);
00231                 yCount++) {
00232                 //Grab the current pixel:
00233                 testColor = getPixel(tilesetSurface, xCount, yCount);
00234 
00235                 //Check pixel for the appropriate color:
00236                 if((testColor == anchorColor) || (testColor == insideAnchorColor)) {
00237                     found  = true;
00238                     tileList[currentTile].ptAnchor.y = yCount;
00239                 }
00240             }
00241 
00242             //Find the first inside pixel:
00243             found = false;
00244             for(yCount=hTileBound[rowcount] + 1;
00245                 (!found) && (yCount < hTileBound[rowcount+1] - 1);
00246                 yCount++) {
00247                 //Grab the current pixel:
00248                 testColor = getPixel(tilesetSurface, xCount, yCount);
00249 
00250                 //Check pixel for the appropriate color:
00251                 if((testColor == insideColor) || (testColor == insideAnchorColor)) {
00252                     found  = true;
00253                     tileList[currentTile].rcSrc.top = yCount;
00254                 }
00255             }
00256 
00257             //If could not find, use the default setting:
00258             if(!found) {
00259                 tileList[currentTile].rcSrc.top = hTileBound[rowcount] + 1;
00260             }
00261 
00262             //Find the last inside pixel:
00263             found = false;
00264             for(yCount=hTileBound[rowcount+1] - 1;
00265                 (!found) && (yCount >= hTileBound[rowcount] + 1);
00266                 yCount--) {
00267                 //Grab the current pixel:
00268                 testColor = getPixel(tilesetSurface, xCount, yCount);
00269 
00270                 //Check pixel for the appropriate color:
00271                 if((testColor == insideColor) || (testColor == insideAnchorColor)) {
00272                     found  = true;
00273                     tileList[currentTile].rcSrc.bottom = yCount+1;
00274                 }
00275             }
00276 
00277             //If could not find, use the default setting:
00278             if(!found) {
00279                 tileList[currentTile].rcSrc.bottom = hTileBound[rowcount+1];
00280             }
00281 
00282             //Calculate the destination extents:
00283             CopyRect(&tileList[currentTile].rcDstExtent, &tileList[currentTile].rcSrc);
00284             OffsetRect(&tileList[currentTile].rcDstExtent, -tileList[currentTile].ptAnchor.x, -tileList[currentTile].ptAnchor.y);
00285         }
00286     }
00287 
00288     //Done grabbing pixels. Unlock surface:
00289     SDL_UnlockSurface(tilesetSurface);
00290 
00291     //Set the transparent color keying:
00292     SDL_SetColorKey(tilesetSurface, SDL_SRCCOLORKEY, transparentColor);
00293 
00294     return true;
00295 }
00296 
00298 bool IsoTileSet::reloadTileset() {
00299     //Load the tileset from a file:
00300     ImageCanvas ts;
00301     if(!ts.loadImage(filename)) {
00302         return false;
00303     }
00304     
00305     //Make the tileset surface a surface equivalent to the canvas:
00306     tilesetSurface = SDL_CreateRGBSurface(((SDL_Surface*)ts)->flags,
00307         ((SDL_Surface*)ts)->w,
00308         ((SDL_Surface*)ts)->h,
00309         ((SDL_Surface*)ts)->format->BitsPerPixel,
00310         ((SDL_Surface*)ts)->format->Rmask,
00311         ((SDL_Surface*)ts)->format->Gmask,
00312         ((SDL_Surface*)ts)->format->Bmask,
00313         ((SDL_Surface*)ts)->format->Amask);
00314     //Blit image from canvas onto the surface:
00315     SDL_BlitSurface(ts, NULL, tilesetSurface, NULL);
00316 
00317     return true;
00318 }
00319 
00321 bool IsoTileSet::unloadTileset() {
00322 
00323     //Clean up the tile list
00324     if(tileList) {
00325         delete [] tileList;
00326         tileList = NULL;
00327         tileCount = 0;
00328     }
00329 
00330     //Free up the tileset surface:
00331     SDL_FreeSurface(tilesetSurface);
00332 
00333     //Free up memory name:
00334     if(filename) {
00335         free(filename);
00336         filename = NULL;
00337     }
00338 
00339     return true;
00340 }
00341 
00343 
00344 
00345 
00347 
00349 Uint32 IsoTileSet::getTileCount() {
00350     return tileCount;
00351 }
00352 
00354 TILEINFO* IsoTileSet::getTileList() {
00355     return tileList;
00356 }
00357 
00359 SDL_Surface* IsoTileSet::getSurface() {
00360     return tilesetSurface;
00361 }
00362 
00365 char* IsoTileSet::getFileName() {
00366     return filename;
00367 }
00368 
00370 
00372 void IsoTileSet::putTile(SDL_Surface* destinationSurface, int xCoord, int yCoord, int tileNumber) {
00373     //Offset the desired tile's extent:
00374     OffsetRect(&tileList[tileNumber].rcDstExtent, xCoord, yCoord);
00375     //Blit the tile:
00376     SDL_BlitSurface(tilesetSurface, GetSDLRect(&tileList[tileNumber].rcSrc), destinationSurface, GetSDLRect(&tileList[tileNumber].rcDstExtent));
00377     //Put the extent back as it was:
00378     OffsetRect(&tileList[tileNumber].rcDstExtent, -xCoord, -yCoord);
00379 }

Generated on Mon May 26 22:13:18 2003 for SDL Isometric Engine by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002