所以,我一直在尝试创建一个'Map'类来处理窗口上我的瓷砖地图的绘制,但是我有一个问题就是将所有的瓷砖都绘制到屏幕上。
这是我的问题:假设我有一张10 * 10个瓷砖的地图,其中包含5层,最多可达10 * 10 * 5 = 500个瓷砖(当然实时更多的瓷砖可能是10倍以上会更糟)...它存储在一个3d数组[layer] [row] [col]或chars中,每个char代表我的sprite表单上的索引 所以我创建了一个'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;
}
答案 0 :(得分:4)
您实际遇到任何速度问题吗? 虽然每秒30,000个磁贴可能听起来很多,但在使用更现代的PC进行计算方面,这可能不是什么大问题。
话虽如此,如果输出单个图块具有与之相关的特定开销,我绝对可以想到一种优化所需内容的方法(例如,2个图块的输出时间比1个图块的大小要长组合)。我并不自信在SFML方面知道多少,但我认为有某种表面/画布系统。您可以做的是编写一个方法,将静态切片绘制到曲面上一次。然后在游戏的每一帧输出这个表面。这意味着不需要以瓦片方式在瓦片中每帧重复输出瓦片。您只需输出所有静态图块组合的单个图像。
我估计你甚至可以动态地使用这个系统。如果需要更改切片,只需使用更新的切片数据覆盖此曲面的相关部分。换句话说,您只保留静态的所有内容,而只保留需要更新的目标区域。
答案 1 :(得分:1)
我同意Alex Z的说法,在现代/主流硬件渲染中,5块屏幕的瓷砖应该不会太慢。然而,唯一可以确定的方法是测试它。
此外,你需要意识到,即使你的地图有1000x1000个图块,你也只会每帧渲染10x10个图块,因为剩下的图块都在屏幕之外。
如果要使当前结构更加优化,则应将精灵表中的每个精灵存储为数组中的单独精灵。这样,每次需要访问单个磁贴时,您都不需要调用SetSubRect。