For our tile-based engine, I load the tiles into the editor I've created and split the tiles based on the current tilesize. The tilesize must be a power of 2.
Then I go through the larger bitmap and extract the squares of tiles from it. This is done in GDI so it's hideous, but it's easier in DirectX or OpenGL since you have direct access to the surface.
Then I save the tiles into a proprietary format and load them into the texture resource manager and then load the corresponding map data into the map resource manager.
I'll post some code later after I leave work. No time right now.
EDIT:
Ok, now for some code. Work was fast eh. Actually about ten hours between first section and this section, but you'd never know it.
Ok I'm going to walk you through this conceptually first.
1. We have 1 large bitmap.
2. We want to create many smaller bitmaps from the 1 bitmap.
Immediately you will see that we need:
1. A desired cellsize for each smaller bitmap. You could use varying sizes, but that complicates the code enormously.
2. A way to extract square sections from a larger bitmap, or a larger square section.
I'll try to code this w/o using API specifics. For DirectX you would have to lock the surface of the large bitmap and the smaller bitmap and do a copy. For GDI you would need to create 2 DCs and do a whole bunch of other 'crap' to get it to work.
This is a function that will extract tiles of size cellsize from a larger image.
Code:
//Setup variables
DWORD dwSourceWidth=SourceBitmap.dwWidth;
DWORD dwSourceHeight=SourceBitmap.dwHeight;
DWORD dwSourceOffset=0;
DWORD dwStartSourceOffset=dwSourceOffset;
DWORD dwDestOffset=0;
DWORD dwDestWidth=dwCellSize;
DWORD dwDestHeight=dwCellSize;
//Vector to stick 'tiles' into
std::vector<CTile *> vImages;
int iDestColCounter=0;
int iDestRowCounter=0;
int iSourceColCounter=0;
int iSourceRowCounter=0;
do
{
//Extract 1 tile starting at dwSourceOffset
//Create tile object
CTile *tile=new CTile;
tile->Create(dwDestWidth,dwDestHeight);
//Get pointer to buffer
DWORD *pDest=tile->GetBuffer();
do
{
//Copy one DWORD from source to dest (movsd)
pDest[dwDestOffset]=pSource[dwSourceOffset];
//Increment destination offset
dwDestOffset++;
//Increment source offset
dwSourceOffset++;
//Increment destination column counter
iDestColCounter++;
//If column counter>dwCellSize
if (iDestColCounter>dwCellSize)
{
//Reset destination column counter and increment row count
iDestColCounter=0;
iDestRowCounter++;
//Move down one line in source, but move to start of line
dwSourceOffset=dwStartSourceOffset+(dwSourceWidth*iDestRowCounter);
}
} while (iRowCounter<dwDestHeight);
//Reset loop vars for next tile
dwDestOffset=0;
iDestColCounter=0;
iDestRowCounter=0;
//Save tile in vector
vImages.push_back(tile);
//Move over 1 block in source bitmap
iSourceColCounter+=dwCellSize;
dwStartSourceOffset+=dwCellSize;
//Check for end of source bitmap
if (iSourceColCounter>dwSourceWidth)
{
iSourceColCounter=0;
iSourceRowCounter+=dwCellSize;
//Move down dwCellSize*iSourceRowCounter pixels
dwStartSourceOffset=iSourceRowCounter*dwSourceWidth;
//Set starting offset to dwStartSourceOffset
dwStartOffset=dwStartSourceOffset;
}
} while (iSourceRowCounter<dwSourceHeight);
This 'should' work if I've coded everything correctly. It traverses the source bitmap and destination bitmap linearily using offsets. There are no multiplies used to figure out the current position in either of the bitmaps.
This is a small BitBlt w/o transparency in assembly.
Code:
void BitBlt(DWORD dwX,DWORD dwY,DWORD *pSource,DWORD dwSrcWidth,DWORD *pDest,DWORD dwDestWidth,DWORD dwDestHeight)
{
_asm {
mov esi,[pSource]
mov edi,[pDest]
mov eax,dwY
mov ebx,dwSrcWidth
mul ebx
//Move to dwX,dwY in source image
add esi,eax
xor eax,eax
}
START:
_asm {
mov ecx,dwDestWidth
rep movsd
//Increment row counter
inc eax
//Are we done?
cmp eax,dwDestHeight
//If above we are done
ja DONE:
//Move down one line in source bitmap
add esi,dwSrcWidth
//Move to start of line or left side of tile image by subtracting
//width of destination bitmap
sub esi,dwDestWidth
//Here edi is at the right point
//Loop
jmp START
}
DONE:
}
You may want to test this as I coded it sitting here and have not compiled it.
It looks strange because the compiler will not allow labels inside of _asm blocks and unfortunately in assembly there isn't any other way to do an a comparison (if) or break out of a loop w/o using them.
This will work provided the direction flag is correct, I prob should deliberately set it, and the coordinates given with the height and width given will not run off the edges of the source bitmap. I could adjust for this with a couple more lines of code, but chose not to.