Here's some code from by tile-based RTS, One to draw the map, and one to draw the minimap. FWIW, I keep by map in a one-dimensional array, and determine the X/Y via Y*Height + X index.
My mini-map has a square around where the current camera is on the main map as well.
#define INDEX(xMapX, xMapY) ((xMapY)*mu32MapHeight+(xMapX))
...
/******************************************************************************
*
* Draw() - Draw the map that's in view
*
******************************************************************************/
BOOL WarTurnsMap::Draw(U32 &u32CameraX, U32 &u32CameraY)
{
U32 u32FullWidth, u32FullHeight;
U32 u32MapStartX, u32MapStartY;
U32 u32MapEndX, u32MapEndY;
S32 s32DrawStartX, s32DrawStartY;
S32 s32CurrentX, s32CurrentY;
U32 x, y;
/* store off the camera */
mu32CameraX = u32CameraX;
mu32CameraY = u32CameraY;
/* figure out where we need to start drawing */
u32FullWidth = mu32MapWidth*mu32TileWidth;
u32FullHeight = mu32MapHeight*mu32TileHeight;
if (u32CameraX + MAP_SCREEN_WIDTH > u32FullWidth)
{
/* move camera back */
u32CameraX = u32FullWidth - MAP_SCREEN_WIDTH;
}
if (u32CameraY + MAP_SCREEN_HEIGHT > u32FullHeight)
{
/* move camera back */
u32CameraY = u32FullHeight - MAP_SCREEN_HEIGHT;
}
u32MapStartX = u32CameraX / mu32TileWidth;
u32MapStartY = u32CameraY / mu32TileHeight;
u32MapEndX = u32MapStartX + MAP_SCREEN_WIDTH/mu32TileWidth + 2;
u32MapEndY = u32MapStartY + MAP_SCREEN_HEIGHT/mu32TileHeight + 2;
s32DrawStartX = u32CameraX % mu32TileWidth;
s32DrawStartY = u32CameraY % mu32TileHeight;
s32CurrentX = -s32DrawStartX;
s32CurrentY = -s32DrawStartY;
for (y = u32MapStartY; y < u32MapEndY; y++)
{
for (x = u32MapStartX; x < u32MapEndX; x++)
{
if ((s32CurrentX < MAP_SCREEN_WIDTH) &&
(s32CurrentY < MAP_SCREEN_HEIGHT))
{
U32 u32Width = mu32TileWidth;
U32 u32Height = mu32TileHeight;
if (s32CurrentX + mu32TileWidth >= MAP_SCREEN_WIDTH)
{
u32Width = MAP_SCREEN_WIDTH - s32CurrentX;
}
if (s32CurrentY + mu32TileWidth >= MAP_SCREEN_HEIGHT)
{
u32Height = MAP_SCREEN_HEIGHT - s32CurrentY;
}
/* draw the Map Unit at this location */
mpMapUnits[INDEX(x, y)]->Draw(s32CurrentX, s32CurrentY,
u32Width, u32Height);
/* Draw Lines around map, above and below */
if (s32CurrentY + mu32TileHeight <= MAP_SCREEN_HEIGHT)
{
PutImageFX2(pu8HorizBar, s32CurrentX,
s32CurrentY + mu32TileHeight-1,
u32Width, u32Height);
}
if (s32CurrentX + mu32TileWidth <= MAP_SCREEN_WIDTH)
{
PutImageFX2(pu8VertBar, s32CurrentX + mu32TileWidth-1,
s32CurrentY,
u32Width, u32Height);
}
}
s32CurrentX += mu32TileWidth;
}
s32CurrentX = -s32DrawStartX;
s32CurrentY += mu32TileHeight;
}
}
/******************************************************************************
*
* MiniMapDraw() - Draw the mini-map
*
******************************************************************************/
void WarTurnsMap::MiniMapDraw(S32 s32X, S32 s32Y, U32 &u32Width, U32 &u32Height)
{
float fXpixels, fYpixels;
U32 u32Xpixels, u32Ypixels;
WarTurnsUnit *pUnit;
/* check if there's less pixels than width */
if (u32Width < mu32MapWidth)
{
printf("FooBar on Map Width!\n");
}
if (u32Height < mu32MapHeight)
{
printf("FooBar on Map Height!\n");
}
/* compute the ratio between num tiles and width */
u32Xpixels = u32Width/mu32MapWidth;
u32Ypixels = u32Height/mu32MapHeight;
/* adjust the width/Height */
u32Width = u32Xpixels*mu32MapWidth;
u32Height = u32Ypixels*mu32MapHeight;
/* save off the minimap size */
mu32MiniWidth = u32Width;
mu32MiniHeight = u32Height;
/* draw outline */
RectFillFX(s32X-2, s32Y-2, u32Width+4, u32Height+4,
0xff, 0xff, 0xff, 255, NULL);
int x, y;
U8 u8r, u8g, u8b;
#if 0
/* draw all green 1st */
RectFillFX(s32X, s32Y, u32Width, u32Height,
0, 155, 0, 255, NULL);
#else
/* draw all black 1st */
RectFillFX(s32X, s32Y, u32Width, u32Height,
1, 1, 1, 255, NULL);
#endif
/* now draw the minimap */
for (y = 0; y < mu32MapHeight; y++)
{
for (x = 0; x < mu32MapWidth; x++)
{
/* check we've revealed this space */
if (mpMapUnits[INDEX(x, y)]->ViewableGet() == FALSE)
{
continue;
}
/* check there's a Unit on this map tile */
pUnit = mpMapUnits[INDEX(x, y)]->UnitGet(0);
/* check there's a building on this spot */
if (mpMapUnits[INDEX(x, y)]->BuildingGet() != NULL)
{
/* draw gray for our building, black for enemy building */
if (mpMapUnits[INDEX(x, y)]->BuildingGet()->OwnerGet() == MyOwnerIdGet())
{
u8r = 160;
u8g = 82;
u8b = 45;
}
else
{
u8r = 1;
u8g = 1;
u8b = 1;
}
}
else if (pUnit)
{
/* Do Later */
if (pUnit->OwnerGet() == MyOwnerIdGet())
{
/* Put a white dot here */
u8r = 255;
u8g = 255;
u8b = 255;
}
else
{
/* put red dot if visible */
//if (Visible)
{
u8r = 255;
u8g = 0;
u8b = 0;
}
}
}
else
{
switch(mpMapUnits[INDEX(x, y)]->TileGet()->eTileType)
{
case TILE_GRASS:
//continue;
u8r = 0;
u8g = 155;
u8b = 0;
break;
case TILE_RESOURCE:
u8r = 148;
u8g = 0;
u8b = 211;
break;
case TILE_ROCK:
u8r = 205;
u8g = 201;
u8b = 201;
break;
case TILE_WATER:
u8r = 0;
u8g = 0;
u8b = 255;
break;
case TILE_SAND:
u8r = 155;
u8g = 155;
u8b = 0;
break;
case TILE_NONE:
u8r = 1;
u8g = 1;
u8b = 1;
break;
}
}
RectFillFX(s32X+(x*u32Xpixels), s32Y+(y*u32Ypixels),
u32Xpixels, u32Ypixels,
u8r, u8g, u8b, 255, NULL);
}
}
/* Finally, draw square around where the camera is */
{
U32 u32StartX, u32EndX;
U32 u32StartY, u32EndY;
U32 u32Temp;
/* calculate where to start for X */
u32Temp = (mu32CameraX*10000)/(mu32MapWidth*mu32TileWidth);
u32StartX = s32X + (u32Temp*mu32MiniWidth)/10000;
u32EndX = u32StartX + (mu32MiniWidth*MAP_SCREEN_WIDTH)/
(mu32MapWidth*mu32TileHeight);
u32Temp = (mu32CameraY*100)/(mu32MapHeight*mu32TileHeight);
u32StartY = s32Y + (u32Temp*mu32MiniHeight)/100;
u32EndY = u32StartY + (mu32MiniHeight*MAP_SCREEN_HEIGHT)/
(mu32MapHeight*mu32TileHeight);
RectFillFX(u32StartX, u32StartY, u32EndX - u32StartX, 1,
MINI_MAP_COLOR, NULL);
RectFillFX(u32StartX, u32StartY, 1, u32EndY - u32StartY,
MINI_MAP_COLOR, NULL);
RectFillFX(u32StartX, u32EndY, u32EndX - u32StartX, 1,
MINI_MAP_COLOR, NULL);
RectFillFX(u32EndX, u32StartY, 1, u32EndY - u32StartY,
MINI_MAP_COLOR, NULL);
}
}