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

Author Topic: Detecting shaded areas of a texture  (Read 3132 times)

0 Members and 1 Guest are viewing this topic.

starkhorn

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • Email
Detecting shaded areas of a texture
« on: May 07, 2015, 04:38:32 am »
First I'm still newish to sfml. I have been tinkering with it on/off for a while now and I've been using only really basic items. i.e. loading texture, drawing sprites, changing colour of sprites. I've also setup a nice wee GUI using the tgui libs.

Anyway, I have a basic game working now but I want to start doing more advance stuff with the sprites. The game at it's core has a real-life map of Europe, split into individual regions. Each png are all of the same size, say 1218 X 730. The background is transparent and each image has each a shaded area for that region, drawn in the proper position. i.e. Italy is drawn where italy should be, etc, etc

The reason I did it this way was because it allows me to set the sprite position as 0,0 and the regions of europe all line up perfectly. When I tried having each region image as a small image, it was a nightmare to try to align up each region correctly.

Anyway, what I want to do now is to have army sprites on the map, but they should only go on the land areas of the region map. So I need a way to detect whether a sprite's position is within a shaded area and indeed which region it is located. As the region areas are all irregular, then defining via hard-coded values would seem to be quite a difficult and likely involve overlap.

Also I cannot simply check the bounding box i.e. something like below, as I assume the bounding box will the same for all regions i.e. 1218 * 730. Right?

if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
    // transform the mouse position from window coordinates to world coordinates
    sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));

    // retrieve the bounding box of the sprite
    sf::FloatRect bounds = sprite.getGlobalBounds();

    // hit test
    if (bounds.contains(mouse))
    {
        // mouse is on sprite!
    }
}
 

So I am wondering if there is any dynamic way to go about checking whether a mouse or another sprite is located on a shaded part of a texture? Is this possible with SFML and if so how (at a high-level - not looking for someone to write the code) ?
« Last Edit: May 07, 2015, 06:34:45 am by starkhorn »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11033
    • View Profile
    • development blog
    • Email
AW: Detecting shaded areas of a texture
« Reply #1 on: May 07, 2015, 09:56:22 am »
Probably the easiest way would be to keep a copy of the sf::Image when loading the texture and then do a pixel perfect checking.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Detecting shaded areas of a texture
« Reply #2 on: May 07, 2015, 10:42:12 am »
Yes, I would also store a separate data structure that allows you to quickly sample a region. sf::Image is an option, but less memory-wasting would be std::vector<Country> with Country being an enum or integer representing the country. When loading the images, you fill in this data structure accordingly.

There's another thread with a similar problem, it might help you.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Detecting shaded areas of a texture
« Reply #3 on: May 07, 2015, 08:59:45 pm »
I've solved it in the way, that I'm using a  background map (Image) (painted in paint.net because of better compression that doesn't remove color information, thats very important to have clean and precise colors) of 1000x1000 slices, where every province has a unique rgb combination. Then I put the province sprites on it, so the background map is not visible anymore. (you don't even need to draw it for being able to read the color information). The provinces are all white for better colorification during runtime. But you can give them any fancy texturing you want as long as it is a neutral color and not too dark, if you later want to see a deep owner color. Those provinces should be placed exactly over the corresponding colors in the background image.

As for the positioning problem of the province shapes you could write some sprite movement code and print the real-time coordinates, so you finally know where to place it. The province sprites only represent the ownership color (are not clickable, but you can later simulate an effect as if a province was clicked, for example to darken its color slightly) and the background image is for getting the pixel color at the clicked position. Of course you have to store all necessary information in a container like a vector/vector of pairs/tuples or array.

As for the army sprites you create another vector and with pushing back the army units you store the current cursor position during creation or the position where the unit is to be created. If you want the unit being able moving only to neighbouring provinces and prevent them from going into water provinces you should create a 2d province array and store for example bools, where 1 means accessible and 0 not accessible. (or you could store some kind of distances, where higher number means that it needs more movement points and 0 means non accessible and so on) You will have to fill in that information manually. First dimension means current province and second dimension means intended province. Units are selected by checking after click if cursor is in sprite and then choosing the topmost one, if you have a stack of several units.
Every province should have an index, that would correspond to the index of the array, so you could check with help of the stored unit sprite position and the intended position, if a move is possible or not. If move is successful, than do the move and store the new position+ new current province of the unit etc....

As for checking how many or which units are in a specific province you could simply go through the vector and formulate some multi level conditions like "unit is in province x"...."unit is of type texture1" and then count the number of those units and so on....You could even remove certain units of specific type, belonging to given country, in province x, but for that you have to store the relevant unit information you need during creation and whenever something is changed.
« Last Edit: May 07, 2015, 09:42:52 pm by Bogdan »

starkhorn

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • Email
Re: AW: Detecting shaded areas of a texture
« Reply #4 on: May 08, 2015, 03:00:46 am »
Probably the easiest way would be to keep a copy of the sf::Image when loading the texture and then do a pixel perfect checking.

Thank you for the suggestion. I honestly had never heard of "pixel perfect checking" before so thank you. After some google and forum searches has helped explain that to me. :) I did find this example which I found really useful.

https://github.com/SFML/SFML/wiki/Source:-Simple-Collision-Detection

Obviously I need to play with it more etc but thanks for pointing me in the right direction.

starkhorn

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • Email
Re: Detecting shaded areas of a texture
« Reply #5 on: May 08, 2015, 03:07:04 am »
Yes, I would also store a separate data structure that allows you to quickly sample a region. sf::Image is an option, but less memory-wasting would be std::vector<Country> with Country being an enum or integer representing the country. When loading the images, you fill in this data structure accordingly.

There's another thread with a similar problem, it might help you.

Ok thank you. So when you say "When loading the images, you fill in this data structure accordingly." Can I clarify if I understand correctly.

Are you saying.

- Load in images.
- During load-in phase, use pixel perfect matching to determine the pixels that are land of a region.
- If there is a hit with the pixel perfect match, then add to a vector, the co-ordinates (I guess with a sf::Vector2f) of each 'land' pixel of a region.
- Then during game-play, I can check the mouse (or army icon) position to see if it matches one of these pixels?

starkhorn

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • Email
Re: Detecting shaded areas of a texture
« Reply #6 on: May 08, 2015, 03:08:26 am »
Hi Bogdan,

Thank you so much for the long reply. I realized that the "other thread" posted by Nexus is one done by yourself. I'll need to get my head around both your post and thread but I just wanted to say thanks for the post. Some good ideas for me to mull over/test out.

 

anything