2012-03-11 117 views
1

所以,我一直在试图创建一个'Map'类来处理我的瓷砖地图在窗口上的绘制,但我有一个问题将所有的瓷砖绘制到屏幕上。用sfml绘制一个瓷砖地图

这是我的问题:可以说我有10 * 10瓦的地图,其中5层总计为10 * 10 * 5 = 500瓦(当然实时会有更多可能是瓦的10倍)这会更糟糕)...它存储在一个3D数组[层] [行] [COL]或字符,每个字符表示我的精灵表上的索引 所以我创建了一个'SpriteSheet'类来处理我的精灵表,并从索引中获取每个精灵:spriteSheet-> GetSubSprite(idx)。所以最后我有一些像Draw(spriteSheet-> GetSubSprite((int)mapArray [i] [j] [k]))应该为每个精灵调用,每个游戏循环,所以可以说我的游戏运行在60 FPS和我有500个瓷砖画:游戏的目标是每秒画500 * 60 = 30,000(!)瓷砖...

所以你可以看到我在这里有一个问题的高招......?任何人都知道如何充分在速度方面提供这个? (当然,对我目前的结构进行任何改进都会非常幸运)。

所以,以防万一我的SpriteSheet.cpp和我的Map.cpp文件,我知道我有很多设计错误,但请专注于我的问题,设计远没有完成。


#include "Map.h" 

sz::Map::Map(std::string path, std::string name, std::string image) : Tmx::Map() { 
    ParseFile(path); 

    if (HasError()) { 
     printf("error code: %d\n", GetErrorCode()); 
     printf("error text: %s\n", GetErrorText().c_str()); 

     system("PAUSE"); 
    } 
    else { 
     mapArray = new unsigned char**[GetNumLayers()]; 
     for(int i = 0; i < GetNumLayers(); i++) { 
      mapArray[i] = new unsigned char*[GetLayer(i)->GetHeight()]; 
      for(int j=0; j<GetLayer(i)->GetHeight(); j++) { 
       mapArray[i][j] = new unsigned char[GetLayer(i)->GetWidth()]; 
       // [layer][row][col] 
      } 
     } 
     //load the array 
     for (int i = 0; i < GetNumLayers(); ++i) { 

      // Get a layer. 
      const Tmx::Layer *layer = GetLayer(i); 

      for (int y = 0; y < layer->GetHeight(); ++y) { 
       for (int x = 0; x < layer->GetWidth(); ++x) { 
        // Get a tile global id. 
        mapArray[i][x][y] = (char)layer->GetTileGid(x, y); 
        //printf("%3d", mapArray[i][x][y]); 
        /* need to fix later on 
        /**************************** 
        // Find a tileset for that id. 
        const Tmx::Tileset *tileset = FindTileset(layer->GetTileGid(x, y)); 
        if (layer->IsTileFlippedHorizontally(x, y)){ 
         printf("h"); 
        }else{ 
         printf(" "); 
        } 
        if (layer->IsTileFlippedVertically(x, y)){ 
         printf("v"); 
        }else{ 
         printf(" "); 
        } 
        if (layer->IsTileFlippedDiagonally(x, y)){ 
         printf("d "); 
        } else { 
         printf(" "); 
        } 
        ****************************/ 
       } 
       //printf("\n"); 
      } 
      //printf("\n\n"); 
     } 
    } 
    tiles = new sz::SpriteSheet(name, image, 33, 33); 
} 

void sz::Map::Draw(sf::RenderWindow *rw) { 
    // dont know what to do T_T 
} 

#include "SpriteSheet.h" 

sz::SpriteSheet::SpriteSheet(std::string name, std::string path, int tileW, int tileH) : sz::GameObject(name, path) { 
    this->tileH = tileH; 
    this->tileW = tileW; 
    numOfTiles = ((this->GetImage()->GetHeight())/tileH) * ((this->GetImage()->GetWidth())/tileW); 
} 

int sz::SpriteSheet::GetTileWidth() { return tileW; } 
int sz::SpriteSheet::GetTileHeight() { return tileH; } 
int sz::SpriteSheet::GetNumOfTiles() { return numOfTiles; } 

sf::Sprite sz::SpriteSheet::GetSubSprite(int idx) { 
    if(idx < 1 || idx > numOfTiles) { 
     std::cout << "Incorrect index!" << std::endl; 
     // need return value 
    } 

    int row=0, col=0, tilesEachRow = (GetImage()->GetWidth()/tileW); 

    while(idx > tilesEachRow) { 
     idx -= tilesEachRow; 
     col++; 
    } 
    row = idx-1; 

    sz::GameObject *sub = new sz::GameObject(name, path); 
    /*std::cout << "tileW: " << tileW << std::endl; 
    std::cout << "tileH: " << tileH << std::endl; 
    std::cout << "row: " << row << std::endl; 
    std::cout << "col: " << col << std::endl; 
    std::cout << "tiles per row: " << tilesEachRow << std::endl; 
    std::cout << "(" << row*tileW << ", " << col*tileH << ", " << (row+1)*tileW << ", " << (col+1)*tileH << ")" << std::endl;*/ 
    sub->SetSubRect(sf::IntRect(row*tileW, col*tileH, (row+1)*tileW, (col+1)*tileH)); 
    return *sub; 
} 

回答

3

你真正遇到任何速度问题?虽然每秒钟30,000个瓦片可能听起来很多,但在用更现代化的个人电脑进行计算方面,这可能不是什么大问题。我已经说过,如果输出单个tile有一定的开销(例如,2个tile需要比1 tile更长的时间才能输出),我肯定会想到一种方法来优化你所拥有的功能。瓷砖组合)。我不知道SFML方面有多少知识,但我认为有某种表面/画布系统已经到位。你可以做的是写一个方法,一次将静态瓷砖绘制到表面。然后在游戏的每一帧输出一次这个表面。这意味着不需要以瓦片的方式在瓦片中的每一帧重复输出瓦片。您只需输出组合的所有静态图块的单个图像。

我想你甚至可以动态地使用这个系统。如果瓷砖需要更改,只需使用更新的瓷砖数据覆盖该表面的相关部分。换句话说,您将所有静态的东西放在一边,只针对需要更新的区域。

1

我同意亚历克斯Z与现代/主流硬件渲染5个屏幕价值瓷砖不应该太慢。然而,唯一可以确定的方法是测试它。

此外,您需要认识到,即使您的地图有1000x1000的贴图,您每帧只能渲染10x10块的贴图,因为其余的贴图都在屏幕之外。

如果你想让你的当前结构更加优化,你应该将每个精灵存储在你的精灵表中作为一个数组中的独立精灵。这样,每次需要访问单个磁贴时,都不需要调用SetSubRect。