Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] How to change pixels on a big map  (Read 2453 times)

0 Members and 1 Guest are viewing this topic.

Boute

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
[SOLVED] How to change pixels on a big map
« on: April 14, 2017, 12:26:35 pm »
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) :



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
« Last Edit: April 15, 2017, 02:43:46 pm by Boute »

UroboroStudio

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: How to change pixels on a big map
« Reply #1 on: April 14, 2017, 02:36:35 pm »
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()

Boute

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: How to change pixels on a big map
« Reply #2 on: April 14, 2017, 03:58:23 pm »
Thank you Uroboro for your answer.

I already thought to do this way at the begining of my project. It is really easier in the use. But i gave up for some reason :
  • It's a hard work to do each texture and put each sprite correctly
  • What can I do of countries that I don't want to implement ? I have a restricted time to do the game and I don't want to put all the countries of the world

However, after a reflexion, I think I'll go this way. I will get the texture of each country with the Photoshop's magical wand tool and it will be much easier to use it in the code than what I started to do (I started to do a vertex-array (triangle strip) for each country to do an approximate shape and then detect if the mouse is over this shape by detecting if the mouse is over one of the triangles of the triangle strip ...) It'll be faster to take the texture with the Wand than writing the coordinates of each vertex of the country's shape. So thank you for your help ! =)

I still hope someone can find an other solution using the map texture, it could save me a lot of time.

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: How to change pixels on a big map
« Reply #3 on: April 14, 2017, 06:00:47 pm »
If time is an issue you could continue using your large texture as the background, but instead of modifying the texture to apply a color, you could overlay a colored sprite of the country at that position. You can then just skip creating the sprites for the countries you don't want to implement.

Boute

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: How to change pixels on a big map
« Reply #4 on: April 14, 2017, 06:33:59 pm »
Yes you're right but if I overlay with a sprite of country, it won't take so many extra time to assign a texture to a country with this sprite. It's almost what I am doing : I am making a texture for many countries and then I'll put them over the big map so I'll keep the little countries I've not made. Actually I just started and doing a texture for each country is not so long and it will probably simplify my code.

Anyway thank you for your answer ; )

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: How to change pixels on a big map
« Reply #5 on: April 14, 2017, 06:36:58 pm »
first think comes to my mind is using polygon shape for each country. did you consider it?

Boute

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: How to change pixels on a big map
« Reply #6 on: April 14, 2017, 06:47:15 pm »
I think it looks too complicated to construct a polygon shape for each country wich fits exactly like the country's shape on the map. I started to do an approximative polygon of vertex array for mouse-detection for few countries and it took a lot of time to put each vertex at the correct position. So i don't imagine with an almost perfect polygon to draw a country.