Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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: Wrong output.

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!

share|improve this question
    
Do you actualy have a ground tile? beacuse, trancparancy is otherwise black, or the same color as your clear color of your target –  Tordin Feb 5 '13 at 14:33
    
In my loop where I create all layers, I dump all surfaces to png files to be able to debug. And I get two files, one background and one foreground. You can fetch the output files here: imgur.com/a/AnEHI –  Christian Ivicevic Feb 5 '13 at 14:37
    
well, then it looks correct. lets say your first layer is the background, and the second is the trees and houses. The trancparency is still black. since you need to blend them together to get what you want. since 1 + 0 ( 0 equals the trancaprecny ), you will fill that area with your background color. –  Tordin Feb 5 '13 at 14:41
    
I am sorry, but I cannot follow what you are saying. Could you explain how to blend the two layers together? - EDIT: Are you suggesting that I should not create surfaces for each layer, but iterate throught each layer and fill only one surface? –  Christian Ivicevic Feb 5 '13 at 14:45
    
To your backbuffer, which are displaying the image. You have to 1 draw the background, then after that, just add on the other image. what you are doing now is, render the first image, and the render the second image over the first image. you need to add the second ontop of the first. ( im trying to find the correct call for that in dx9 right now. ) –  Tordin Feb 5 '13 at 14:49
show 3 more comments

2 Answers

StretchRect just does a straight copy and so doesn't support any form of alpha blending; you're going to need to find another method of doing this.

share|improve this answer
    
As mentioned in my question I have read about IDirect3DTexture9 and ID3DXSprite which could come in handy - is this something I should take a look at? And furthermore, do you know which functions I can use to create the layers from my tileset? –  Christian Ivicevic Feb 5 '13 at 14:59
    
Somebody else is going to have to give this info as working in 2d is not something I have much experience with. If it was me I'd use textures and alpha blending with regular draw calls, which is very different to your approach and would need a total rewrite, but like I said, I don't really know what 2d options are available. –  Jimmy Shelter Feb 6 '13 at 2:09
add comment
up vote 0 down vote accepted

With the hint of mh01 and some trial and error I succeeded in drawing my map. I am still loading the tilesets as IDirect3DSurface9 objects but creating IDirect3DTexture9 objects for each layer. With a call to IDirect3DTexture9::GetSurfaceLevel() I retrieve a pointer to the underlying IDirect3DSurface9 of the texture which can be used for StretchRect. However when I want to draw the layers I must not use StretchRect as it does not render but merely copy all contents. Therefore I am relying on a ID3DXSprite object which handles this for me successfully.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.