The array
Okay, so first you're obviously going to need an array. What is the array going to be of? An array of tiles, which you create yourself...
Code: Select all
class Tile
{
private:
int x, y, w, h, fx;
bool solid;
public:
Tile();
void Setup( int tx, int ty, int tw, int th, int tfx, bool tsolid );
void Draw( BITMAP *buffer, BITMAP *tileset, int xOff, int yOff );
};
I have variables storing X, Y, W, H, and "FX", where FX is the X-coordinate on the filmstrip. My filmstrip is only one tile high, one long strip, so I only need the x coordinate.
>> I would probably change the x, y, w, h to an SDL_Rect or Rectangle object now.
Drawing the map
My array is 1D because it's easier to make it dynamic that way, I was lazy ;P But 2d or 3d is probably more "intuitive". It doesn't matter much, as their coordinates are stored inside of the Tile instance anyway.
To draw the map, you just call a function that calls each Tile's draw function.
Code: Select all
void Tile::Draw( BITMAP *buffer, BITMAP *tileset, int xOff, int yOff )
{
if ( fx != 0 && fx != 1 )
{
masked_blit( tileset, buffer, fx, 0, x-xOff, y-yOff, w, h );
}
if ( fx == 1 )
{
line( buffer, x-xOff, y-yOff, x-xOff+w, y-yOff+h, makecol( 255, 0, 0 ) );
line( buffer, x-xOff, y-yOff+h, x-xOff+w, y-yOff, makecol( 255, 0, 0 ) );
}
}
On my filmstrip, the first tile was empty, so the first if-statement is to tell it to draw if it is NOT the blank tile (just extra work). I think fx = 1 denotes a collision tile, which would be for a special layer. Not sure why I did it this way, code is old. :P
Checking what the mouse clicks
So that would draw the map, how about clicking a tile to change it?
Under my "if ( mouse_b & 1)" code (for left-click):
Choosing a tile from the tileset
Code: Select all
if ( mouse_y < 32 ) //choosing tile
{
cursor.SetFx( (( mouse_x + tileScroll ) / 32 ) * 32 );
}
My tileset was displayed on the top of the screen, between y=0 and y=32, so it's saying if the mouse's y coordinate is above that region, they're clicking on the tileset to choose a tile.
Scrolling the map
Code: Select all
else if ( mouse_y < 60 && mouse_x < 138)
{
HandleButton( &cursor, &level[levelIndex], &winTile, &tileScroll, imgTileset->w, mapSave, mapLoad, &system, MAX_X, MAX_Y );
}
This is just the little scrolling buttons I had in my map editor, not important. Adjusts the scrolling of the tileset.
Clicking a button on the bottom menu
Code: Select all
else if ( mouse_y >= winSub.Y1() ) //on bottom menu
{
cursor.SetClick( true );
}
This would just be hitting a button on the bottom menu.
Clicking on the map to change a tile
Code: Select all
else //on level
{
level[levelIndex].CheckClick( &cursor, 1, MAX_X, MAX_Y );
}
This would be clicking in the map region, setting a tile to whatever the brush currently is (more later).
What are behind those functions?
Selecting a tile off the tileset
Code: Select all
cursor.SetFx( (( mouse_x + tileScroll ) / 32 ) * 32 );
This is just a basic Set function for the Brush object
cursor. It is setting the brush by telling it what x coordinate on the filmstrip to draw from.
This might look a little confusing, but it's the mouse position on the tileset, offset by how much the tileset is scrolled. I don't know why I divided and multiplied by 32. Old code. ;P
Drawing onto the map
Code: Select all
level[levelIndex].CheckClick( &cursor, 1, MAX_X, MAX_Y );
The Level item has a function to check which tile the mouse's x and y coordinate correspond to.
Code: Select all
void Level::CheckClick( Brush *mouse, int click, int MAX_X, int MAX_Y )
{
//See if a tile was clicked
int mx = ( mouse_x + xOff ) / 32;
int my = ( mouse_y + yOff ) / 32;
int tLayer = mouse->Layer();
int tBrush = mouse->Fx();
mx and my are the "index ID" of the tile, instead of storing the pixel location.
TILE mx = 3 is at (3*32) or fx = 96.
The current layer is stored in the brush (essentially just an integer), and the current brush pixel-x coordinate on the filmstrip.
If the mouse is right-clicking, then it erases the current tile instead of drawing something.
Code: Select all
if ( mx < MAX_X && my < MAX_Y )
{
tile[ tLayer ][ mx ][ my ].FX ( tBrush );
}
If the tile the mouse is clicking is within the array of tiles, then set that tile's FX coordinate to the brush FX coordinate given.
Code: Select all
if ( mouse->Size() == 3 )
{
if ( mx-1 < MAX_X && my < MAX_Y )
tile[ tLayer ][ mx-1 ][ my ].FX ( tBrush );
if ( mx+1 < MAX_X && my < MAX_Y )
tile[ tLayer ][ mx+1 ][ my ].FX ( tBrush );
if ( mx < MAX_X && my-1 < MAX_Y )
tile[ tLayer ][ mx ][ my-1 ].FX ( tBrush );
if ( mx < MAX_X && my+1 < MAX_Y )
tile[ tLayer ][ mx ][ my+1 ].FX ( tBrush );
if ( mx-1 < MAX_X && my-1 < MAX_Y )
tile[ tLayer ][ mx-1 ][ my-1 ].FX ( tBrush );
if ( mx-1 < MAX_X && my+1 < MAX_Y )
tile[ tLayer ][ mx-1 ][ my+1 ].FX ( tBrush );
if ( mx+1 < MAX_X && my-1 < MAX_Y )
tile[ tLayer ][ mx+1 ][ my-1 ].FX ( tBrush );
if ( mx+1 < MAX_X && my+1 < MAX_Y )
tile[ tLayer ][ mx+1 ][ my+1 ].FX ( tBrush );
}
}
This is an extension of the drawing, if the brush is of size 3 instead of 1, it sets the eight surrounding tiles to the same brush.
Let me know if this helps.