I am currently working on a RTS game with a minimap. Since drawing this minimap is eating around 20% of my CPU time. I thought of reducing the amount of draw calls. So instead of using a rectangleShape for every map tile I might try using a vertex array of quads instead. And only draw the vertex array going from 62500 (for a 250*250 tiles map) draw calls per miniMap layer update to one!
So I came up with the following code:
static const sf::Color colors[] =
{
{0, 0, 0},
{152, 205, 115},
{200, 160, 80},
{200, 160, 80},
{200, 160, 80},
{200, 160, 80},
{200, 160, 80},
{69, 164, 208},
{69, 164, 208},
{69, 164, 208},
{69, 164, 208},
{69, 164, 208}
};
sf::VertexArray miniMapPoints(sf::Quads, MAP_HEIGHT*MAP_WIDTH);
minimapTexture.clear(sf::Color(0, 0, 0, 0));
for (int j = 0; j < MAP_HEIGHT; j++)
{
for (int i = 0; i < MAP_WIDTH; i++)
{
sf::Vertex* currentMiniMapQuad = &miniMapPoints[(i * MAP_HEIGHT) + j];
currentMiniMapQuad[0].color = colors[currentGame.currentMap[i][j]];
currentMiniMapQuad[1].color = colors[currentGame.currentMap[i][j]];
currentMiniMapQuad[2].color = colors[currentGame.currentMap[i][j]];
currentMiniMapQuad[3].color = colors[currentGame.currentMap[i][j]];
//cords miniMapSpace(cords location)
//{
// int wX = mapOffsetX * 20 + (location.x - location.y) * (20 / 2);
// int wY = mapOffsetY * 10 + (location.x + location.y) * (10 / 2);
// return { wX, wY };
//}
//Each quad should be 20px wide and 10px high. We define them clockwise from the top left (x + 0 and y + 0)
currentMiniMapQuad[0].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x), static_cast<float>(miniMapSpace({ i, j }).y)); //0,0
currentMiniMapQuad[1].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x) + 20.f, static_cast<float>(miniMapSpace({ i, j }).y)); //1,0
currentMiniMapQuad[2].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x) + 20.f, static_cast<float>(miniMapSpace({ i, j }).y) + 10.f); //1,1
currentMiniMapQuad[3].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x), static_cast<float>(miniMapSpace({ i, j }).y)+10.f); //0,1
//miniMapPixel.setFillColor(colors[currentGame.currentMap[i][j]]);
//miniMapPixel.setPosition(static_cast<float>(miniMapSpace({ i, j }).x), static_cast<float>(miniMapSpace({ i, j }).y));
//minimapTexture.draw(miniMapPixel);
}
}
minimapTexture.draw(miniMapPoints);
minimapTexture.display();
I left the old working code for drawing the miniMapPixels in there for reference. And also added the commented out function miniMapSpace() to make clear what is happening.
I attached the result of the miniMap draw and the expected result.
currentMiniMapQuad[0].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x), static_cast<float>(miniMapSpace({ i, j }).y) + 10.f); //0,1
currentMiniMapQuad[1].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x), static_cast<float>(miniMapSpace({ i, j }).y)); //0,0
currentMiniMapQuad[2].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x) + 20.f, static_cast<float>(miniMapSpace({ i, j }).y)); //1,0
currentMiniMapQuad[3].position = sf::Vector2f(static_cast<float>(miniMapSpace({ i, j }).x) + 20.f, static_cast<float>(miniMapSpace({ i, j }).y) + 10.f); //1,1
I tried different orders of the currentQuad corner coordinates. Like starting on the bottom left. While this somewhat fixed the colors the map drawn is not correct. Eg water tiles are drawn where grass tiles need to go. And there is distortion the lower Y goes and the higher X goes. So last attachment.
I think the error lies in the order of assigning the four corners of the quad. But I cant figure out the right order.
And doing this:
currentMiniMapQuad->color = colors[currentGame.currentMap[i][j]];
Also does not get the correct result.