Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Approach on making 'Provinces' in game's world map.

Discussion in 'General Discussion' started by Zukas, Jan 18, 2015.

  1. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    Greetings all,

    I'm working on a 2D pixel art strategy game, and I'm looking for suggestions on how to work with world map system in programming and visual design aspect. I want players to be able to select province by mouse click, possibility for provinces to have visual effect such as glow or border color change.

    I was thinking how to possibly make this kind of system. One of the ideas were to make each province a GameObject with province component to do it's functions. Then snap sprites of those GameObjects together somehow. Though, problem with this, is that I will have to cut down my big world map sprite into many other sprites, which would be time consuming and annoying. Unless I find some sort of efficient method with Photoshop or some other editing program.

    If you have any ideas, suggestions or something to mention from your own experience, I'd love to hear it all!

    P.S. English isn't my native language and furthermore I'm new to game developing and not sure which words to use, so it might be hard to understand it. If you don't understand something out of it, please let me know and I'll try to edit it!
     
  2. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    The way I do it in my game is I have two textures, one for the display of the world map and the other is simply a black and white texture that I use as a color map.

    Each province is colored a certain way, and in game I use a Dictionary<Color32, Province> where Province is a class containing the name of the province, and all the info I need. When I move the mouse I just send a Raycast and get the texture coordinate that I hit. I then compare the Color at that pixel and get the appropriate province.
     
  3. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    Thanks for your reply ensiferum,

    That's interesting approach on it, but I don't understand how do you 'mark' region for specific province away from other provinces in single black white texture? This might be the approach I might want to use, but not quite sure yet how it exactly works.
     
  4. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    Well for example take a look at this map:


    Each country is on it's own layer, in photoshop what I do is I start with pure black and paint the province Galia in black ( new Color(0,0,0)). Then I'll increase each color channel by 10 and paint Norham (new Color(10,10,10)) and so on. I then save the black and white image in a separate image.

    So when I get a pixel from the map texture I simply query my black and white texture and get the color (10,10,10) I then know my mouse is over norham.

    You could technically have 256 different province using this approach. You could further divide it using each color chanel
    Red = Country, Green = Province, Blue = City
     
    Makaveli702, Ryiah, Kiwasi and 3 others like this.
  5. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    I believe I now completely understand how your concept works. That's really innovative and unique approach, but as much as I understand, it's not as dynamic as I want. Since I want to change provinces color to the color of it's owner.

    For example province of Nortis belonged to kingdom of Greenos and had green color, but then Reedos conquered it, and it changes it's color to red.

    Unless, I can change the black and white texture runtime inside game. I'm sure it's possible, but just too complicated for my experience.
     
  6. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    You wouldn't need to change the black and white texture, this is your lookup texture. You would need to have a shader that would overlay a color over a specific black and white color.

    Unfortunately I'm not well versed enough in shader code to tell you how to do it. Maybe someone can chime in.
     
    Makaveli702 likes this.
  7. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    Alright, thanks for your input. It's unique way and interesting way, learned a lot from it! Thanks again.
     
  8. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    I've tried to do method as you said, but I couldn't retrieve the color of pixel I pressed on. I tried RayCast.textureCoord to determinate the pixel. But seems like it doesn't work on plain textures, and seems like there's no other method, how did you do it?
     
  9. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    Make sure it's RayCastHit and not RayCast. Try to debug.Log the Vector2 that's returned by the hit and see if you get the right coordinates.

    I'll post my code here when I come back from school tonight.
     
    Makaveli702 likes this.
  10. Ostwind

    Ostwind

    Joined:
    Mar 22, 2011
    Posts:
    2,804
    Also remember to set texture to read/write enabled to be able to read the color
     
    ensiferum888 likes this.
  11. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    Yeah, it's RaycastHit, my bad I just typed it wrong, getting frustrated with all this. Thanks in advance for all the support, cant wait to see script!

    I've checked it. It's enabled.

    EDIT: Waking up in morning I fiddled with some stuff. And, it seems like it I've made it work.

    I've put my both sprites/textures bottom left corners to (0,0,0) transform. And then I use this script.
    Code (CSharp):
    1. void Update ()
    2.     {
    3.         if(Input.GetMouseButtonDown(0))
    4.         {
    5.             //We select province with Raycast
    6.             RaycastHit hit;
    7.             if (!Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit))
    8.                 return;
    9.  
    10.             Vector2 cordV2 = new Vector2 (hit.point.x,hit.point.y);
    11.             print(cordV2);
    12.  
    13.             int cordX = (int)(Mathf.FloorToInt(cordV2.x * 16));
    14.             int cordY = (int)(Mathf.FloorToInt(cordV2.y * 16));
    15.             Color32 clickedProvinceColor = colorMapTex.GetPixel(cordX,cordY);
    16.             print("Province Color: " + clickedProvinceColor + "Stats: " + cordX + " " + cordY );
    17.         }
    18.     }
    (cordX and cordY are doubled by 16 because sprite is 16 pixels per unit)

    Though, I somehow have a feeling your code will be more efficient.
     
    Last edited: Jan 20, 2015
    Richardm1985 likes this.
  12. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    Actually no my code is pretty much the same :) Sorry for the delay I got home really late yesterday and was too tired to get on the computer.

    Here is my part of the code:


    Code (CSharp):
    1.     private Country GetCountry(){
    2.         RaycastHit hit;
    3.         if (!Physics.Raycast(mapCamera.ScreenPointToRay(Input.mousePosition), out hit)){
    4.             return;  
    5.         }
    6.        
    7.         Vector2 hitPoint = hit.textureCoord;
    8.         hitPoint.x *= countryMap.width;
    9.         hitPoint.y *= countryMap.height;
    10.        
    11.         Color currentCol = countryMap.GetPixel((int)hitPoint.x, (int)hitPoint.y);
    12.         Country currentCountry;
    13.         //Here I'm getting the value from my Country Dictionary, for some reason I had only used the Color.r
    14.         //instead of the whole color.
    15.         if(currentCol.a > 0 && countryCodes.TryGetValue(currentCol.r, out currentCountry)){
    16.             return currentCountry
    17.         }
    18.         else{
    19.             return null;  
    20.         }
    21.     }
     
    Richardm1985 and Makaveli702 like this.
  13. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    No worries, I already owe you a favor :D.

    Right now I'm trying to find a way how to switch my foreach loop for finding right province to the one pressed on to something more efficient, though not sure what command of list or dictionary is best to use, not that I'm really sure how your TryGetValue works in this situation either.
     
  14. ensiferum888

    ensiferum888

    Joined:
    May 11, 2013
    Posts:
    317
    It depends, if your list isn't that big you won't see the difference.

    Accessing a Dictionary entry by it's key approaches O(1) in speed, where as iterating through a list takes O(n) where n is the number of items in your list.

    You can read more on the TryGetValue method on the official MSDN

    Basically what I do is declare a Country which is null. Then the TryGetValue method takes a key parameter (in my case the entries in the dictionary are indexed using a float which is the red chanel of the color) the out keyword for the second parameter means If you find an entry with this key, assign it's value to this parameter (in this case currentCountry),

    If successful the method will return True, therefore currentCountry now points to a valid entry in my dictionary and I can return it.

    If the method returned false I explicitly return null.
     
  15. Zukas

    Zukas

    Joined:
    Dec 17, 2013
    Posts:
    40
    Oh! So that's what out does, I was wondering how you do it since it returns a bool, everything slowly starts to fold out together!

    And those MSDN documentations are so complicated for me, probably because I never worked with Microsoft Visual Studio I suppose, one day I suppose. Thanks again! Is there any way to follow your game development?