Saturday, May 28, 2016

c# - Texture2D.SetPixel method behaving weirdly in game province creation


I have been trying to implement a province system in Unity. I am trying to read the provinces from an image file, store their coordinates in a province, and use those coordinates to generate a texture and a 2D sprite for the province to be displayed on the screen at its appropriate world coordinates. Games like Risk, and many strategy games that rely on world maps to function use this approach. So far, I have the following code to parse the image from the province.png file I have created.


public class ProvinceReader()
{
public static void Read()
{

Texture2D provinces = MapImageCache.province_tex;
for(int x = 0; x < provinces.width; x++)
{
for(int y = 0; y < provinces.height; y++)
{
Color32 color = provinces.GetPixel(x,y);
ProvinceData province = null;
if(MapInstance.ColorCodedData.TryGetValue(color, out province))
{
province.AddPoint(x, y);

//TODO: Check if the neighboring pixels are of different colors. If so,
//add the pixel to the 'province border' pixels. The, get the province at
//the checked pixel position and store the x,y coordinate in a dictionary
//IDictionary>.
}
else
{
//MapInstance.Instance.ColorCodedData.Add(color, new ProvinceData());
}
}

}
foreach (ProvinceData prov in MapInstance.Instance.ColorCodedData.Values)
{
GameObject newProv = new GameObject();
newProv.AddComponent().SetData(prov);
newProv.AddComponent().sprite = prov.GenerateSprite();
}
}
}


public class ProvinceData
{
private List points = new List();
private List xPoints = new List();
private List yPoints = new List();
private Sprite image;

public Sprite GenerateSprite()
{
int minX = xPoints[0], minY = yPoints[0];

int maxX = xPoints[0], maxY = yPoints[0];
for(int i = 0; i < xPoints.Count; i++)
{
int xval = xPoints[i], yval = yPoints[i];
if(xval < minX) minX = xval;
else if(xval > maxX) maxX = xval;

if(yval < minY) minY = yval;
else if(yval > maxY) maxY = yval;
}

int width = (maxX - minX) + 1, height = (maxY - minY) + 1;
Texture2D m_tex = new Texture2D(width, height);

for(int i = 0; i < xPoints.Count; i++)
{
int xval = xPoints[i] - minX, yval = yPoints[i] - minY;
m_tex.SetPixel(xval, yval, new Color32(0, 123, 20, 255)); //I want to display the province on screen in green
}
m_tex.Apply();
this.image = Sprite.Create(m_tex, new Rect(0, 0, width, height), Vector2.zero, 1f);

return image;
}
public void AddPoint(int x, int y)
{
xPoints.Add(x);
yPoints.Add(y);
points.Add(new Vector2((float)x, (float)y));
//Also save whether it is a border point.
}
}


I have a black (0,0,0) province in the center of the texture in my png file:


enter image description here


And I am trying to read it. I loaded it into my MapInstance.Instance.ColorCodedData and ensured the data is valid. I loaded the png into a Texture2D and ensured the image was set up properly.


I am getting the following on my screen when I start the game:


enter image description here


I did some experimenting, and used Debug.Log to record a list of points. The largest point in the province that matches the province color is (x,y) => (643, 290). The smallest is (x,y) => (627, 281). I recorded the final value of "width" and "height", in the ProvinceReader.Read() method using Debug.Log(); The value was 1 when I explicitly subtracted the minimum of each value from the maximum of each value. So, I should have gotten (width, height) => (16, 9), but when I record these values I get 1. Which is weird.


I then changed the width and height values arbitrarily to 200,200 to see what happens, and I just get a 200x200 version of the above sprite.



Why is the sprite doing this? How can I solve it? If you need any more information, please let me know and I will include it.




Answer



public Sprite GenerateSprite()
{
int minX = xPoints[0], minY = yPoints[0];
int maxX = xPoints[0], maxY = yPoints[0];

for(int i = 0; i < xPoints.Count; i++)
{
int xval = xPoints[i], yval = yPoints[i];


if(xval < minX) minX = xval;
if(xval > maxX) maxX = xval;
if(yval < minY) minY = yval;
if(yval > maxY) maxY = yval;
}
int width = (maxX - minX) + 1, height = (maxY - minY) + 1;
Texture2D m_tex = new Texture2D(width, height);

for(int i = 0; i < xPoints.Count; i++)
{

//This is the modified code.
int worldX = xPoints[i];
int worldY = yPoints[i];
int xval = maxX - worldX;
int yval = maxY - worldY;

m_tex.SetPixel32(xval, yval, new Color32(0, 123, 20, 255)); //I want to display the province on screen in green
}
m_tex.Apply();
this.image = Sprite.Create(m_tex, new Rect(0, 0, width, height), Vector2.zero, 1f);

return image;
}

This code fixes the error. For whatever reason, the else when I was setting my max and min values was screwing things up. I was also forgetting to convert the x and y values into the coordinates of the new texture.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...