Hi,
I’m working on a game project. The game is a Quizz where a name of a country appear on the screen and you have to click on the right country on a map.
I’m having trouble with a module of my game : I want that when your mouse is passing over a country, it changes its color, and when the country is found, its color is green etc.
Here is a pic to demonstrate what i’ve achieved (the mouse is over the France) :
(http://www.pictures-cloud.fr/uploads/477515e6fd7c8ae78d8dc91e4cbc42c5/thumb-geoquizz_forum.-3e12b88aa61e66ab904f3c991ea02e57.jpg) (http://www.pictures-cloud.fr/large-477515e6fd7c8ae78d8dc91e4cbc42c5/geoquizz_forum.-3e12b88aa61e66ab904f3c991ea02e57.jpg.html)
Here is how my program works :
• Each country has a pixel array in the Country class :
std::vector<sf::Vector2u> PixelsArray
It is charged at the start of the game using a Boundary-Fill-like algorithm.
The pixel array countains the position of each pixel of the country.
• When the mouse is over a country, a fonction in the Map class is called.
Here is how it works :
void Map::fill(std::vector <sf::Vector2u>& pixelsArray, sf::Color newColor)
{
//Exit the function if we fill with the color of the boundaries
if (newColor == borderColor)
return;
for (int i = 0; i < pixelsArray.size(); i++)
imageMap.setPixel(pixelsArray[i].x, pixelsArray[i].y, newColor);
texture.loadFromImage(imageMap);
map.setTexture(texture);
}
I use an image of the map to transform the pixels and then i am updating the texture of map’s sprite with this image.
The problem is that my map is 3958 * 2596 and it takes about a second to update the texture. So each time i move my mouse over a country, when it wants to update the color to the selected color, my game freeze for one second. I noticed that it doesn’t come from the pixel Array loop but more from the part :
texture.loadFromImage(imageMap);
map.setTexture(texture);
I've tried to reduce the Map's texture to what the player is able to see (the view) so it is by exemple 1700*1050 when the player is on the Europe continent, but it's too slow too.
I've thinked about update texture with :
void sf::Texture::update ( const Uint8 * pixels,
unsigned int width,
unsigned int height,
unsigned int x,
unsigned int y
)
but it would be very difficult to set an IntRect for each country etc.
Actually what could be perfect, is to use something like
void sf::Texture::update ( const Uint8 * pixels )
with the position of each pixels (wich I already have). In other words, updating the texture with only the pixels of a country (with my country's sf::Vector2u pixel array)
Thank you for your attention, I hope you will understand : P
You might consider getting rid of that big texture (map) and use sf::Sprite for each country.
It will be more fast, and much more less expensive for your computer.
The idea is to create one texture for each country, load them at the start in a std::vector<sf::Sprite> and asign each sprite his position on the "map". Use window.clear(dark blue) for the background, and Sprite.setColor(light blue) for the country.
sf::Sprite country;
country.setColor(sf::Color::Blue);
country.SetPosition(pos);
vCountry.pushback(country);
Now, you need a method to know when the mouse is over any country. You can use Sprite.getGlobalBounds().contains(Mouse Position) to check it. But it's not a precise method because the FloatRect of a Sprite is a square shape and can overlay with any other country nearby.
So I will say to check if the mouse position is inside the bounds of a contry Sprite and IF so, then perform a pixel perfect check to be sure the mouse IS inside the country.
for (int i = 0; i < vCountry.size(); ++i)
{
if (vCountry[i].getGlobalBounds().contains(mouse) && pixel_perfect(vCountry[i], mouse)
{
vCountry[i].setColor(Grey);
}
}
For drawing, you only have to iterate through the vector of sprites and draw them.
window.clear(Dark Blue);
for (int i = 0; i < vCountry.size(); ++i) window.draw(vCountry[i])
window.display()