In my current project I have a class which loads a map file and then it should load all associated tilesets (no transparent tiles - I used to work with magenta as a colorkey) and precreate a surface for each static layer of the map so I only have to display one bigger image per frame rather then iterating over all of my tiles. For each tileset I have a loop which loads them successfully like this
IDirect3DSurface9 *pTilesetSurface = nullptr;
// Create surface
HRESULT hResult = Engine::GetInstance()->GraphicsDevice->CreateOffscreenPlainSurface(
pTileset->GetImage()->GetWidth(),
pTileset->GetImage()->GetHeight(),
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&pTilesetSurface,
nullptr);
if(!SUCCEEDED(hResult))
return FALSE;
// Load tileset
std::wstring strTilesetSource(
pTileset->GetImage()->GetSource().begin(),
pTileset->GetImage()->GetSource().end());
strTilesetSource = strPathToMap + strTilesetSource;
hResult = ::D3DXLoadSurfaceFromFile(
pTilesetSurface,
nullptr,
nullptr,
strTilesetSource.c_str(),
nullptr,
D3DX_FILTER_LINEAR,
D3DCOLOR_ARGB(255, 255, 0, 255),
nullptr);
if(!SUCCEEDED(hResult))
return FALSE;
this->m_vTilesets.push_back(pTilesetSurface);
After this loop I am iterating over every layer of the map and trying to build a surface for each layer with the associated tiles like this.
IDirect3DSurface9 *pLayerSurface = nullptr;
HRESULT hResult = Engine::GetInstance()->GraphicsDevice->CreateOffscreenPlainSurface(
pLayer->GetWidth() * 16,
pLayer->GetHeight() * 16,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&pLayerSurface,
nullptr);
if(!SUCCEEDED(hResult))
return FALSE;
Engine::GetInstance()->GraphicsDevice->ColorFill(
pLayerSurface,
nullptr,
D3DCOLOR_ARGB(0, 0, 0, 0));
for(int x = 0; x < pLayer->GetWidth(); ++x) {
for(int y = 0; y < pLayer->GetHeight(); ++y) {
const Tmx::MapTile tile = pLayer->GetTile(x, y);
if(tile.tilesetId != -1) {
int dwTilesetWidth =
this->m_pTmxFile->GetTileset(tile.tilesetId)->GetImage()->GetWidth() / 16;
std::div_t tileCoords = std::div(tile.id, dwTilesetWidth);
RECT srcRect = { tileCoords.rem * 16, tileCoords.quot * 16,
tileCoords.rem * 16 + 16, tileCoords.quot * 16 + 16 };
RECT destRect = { x * 16, y * 16, x * 16 + 16, y * 16 + 16 };
Engine::GetInstance()->GraphicsDevice->StretchRect(
this->m_vTilesets[tile.tilesetId],
&srcRect,
pLayerSurface,
&destRect,
D3DTEXF_NONE);
}
}
}
A call to D3DXSaveSurfaceToFile for debugging purposes creates transparent png files which can be layered correctly in Photoshop etc. but when I render these surfaces with this loop
for(auto iter = this->m_vLayers.begin(); iter != this->m_vLayers.end(); ++iter) {
Engine::GetInstance()->GraphicsDevice->StretchRect(
*iter,
nullptr,
Engine::GetInstance()->Backbuffer,
nullptr,
D3DTEXF_NONE);
}
then I have some wrong output which you can see here:
.
All the blacks areas should be transparent such that one can see the layer below. Has anyone an idea what I might be doing wrong?
PS: I have read about the IDirect3DTexture9 and ID3DXSprite interfaces which could be helpful, but I haven't used them yet as I did not find any information on how to rebuild a map with tiles like I did here with usual surfaces. If anyone has suggestions about this, I would be glad to here them!