Search Unity

Procedurally generating a Sprite

Discussion in 'Scripting' started by _GingerSheep, Sep 21, 2014.

  1. _GingerSheep

    _GingerSheep

    Joined:
    Aug 17, 2014
    Posts:
    5
    Hi all!

    I'm trying to create a game with 2d procedural level generation, in a platformer style. For now, the generation is simply the top five and bottom five "tiles" are rock, and the rest is air. the rock "tiles" should also be overlayed with a grass texture, if air is above them. The rock and grass textures are also randomly generated in the script. However, whenever this is run, either no air is generated or only air is generated, and my grass seems to just chose a random line to generate on. After doing some Debbuging, I have confirmed that the "tiles" are being stored correctly as floats (1 is rock, 0 is air) in the "world" array, and therefore it must be in my texturing that I'm going wrong, however, when I try to debug it, unity crashes. I'd be eeeextreemly grateful to anyone who helps me with this!!!!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class TerrainGen : MonoBehaviour {
    6.  
    7.     public int xWorldSize = 16;
    8.     public int yWorldSize = 8;
    9.     public int textureSize = 16;
    10.  
    11.     public Color colorRock;
    12.     public Color colorGrass;
    13.  
    14.     public float grassTextureWeight = 3f;
    15.     public float colorOffset;
    16.  
    17.     private Sprite worldSprite;
    18.  
    19.     private Texture2D worldTexture;
    20.  
    21.     private Color[,] textureRock;
    22.     private Color[,] textureGrass;
    23.  
    24.     private float[,] world;
    25.  
    26.     private Rect rect;
    27.  
    28.     private SpriteRenderer spriteRenderer;
    29.  
    30.     void Start(){
    31.  
    32.         // set World texture to correct size and format
    33.         worldTexture = new Texture2D (xWorldSize, yWorldSize, TextureFormat.ARGB32, true);
    34.  
    35.         // set textures to correct sizes
    36.         textureRock = new Color[textureSize, textureSize];
    37.         textureGrass = new Color[textureSize, textureSize];
    38.  
    39.         //set world to correct size
    40.         world = new float[xWorldSize, yWorldSize];
    41.  
    42.         //randomize textures
    43.         SetTextureRock (textureRock, colorRock);
    44.         SetTextureGrass (textureGrass, colorGrass);
    45.  
    46.         //set world array TODO all the World-gen should be called here
    47.         SetWorldLayout ();
    48.  
    49.         //actually define the texture for the level, using the world array and textures
    50.         SetWorldTextureToCorrectTexture ();
    51.  
    52.         //Define the Rect for the sprite
    53.         rect.x = xWorldSize / -2;
    54.         rect.y = yWorldSize / -2;
    55.         rect.width = xWorldSize;
    56.         rect.height = yWorldSize;
    57.  
    58.  
    59.         //stop any anti - aliasing(for F sake!!!!)
    60.         worldTexture.filterMode = FilterMode.Point;
    61.  
    62.         //set the sprite to our texture
    63.         worldSprite = Sprite.Create (worldTexture, rect, new Vector2 (0, 0), textureSize);
    64.  
    65.         //link to the objects sprite renderer
    66.         spriteRenderer = GetComponent<SpriteRenderer>();
    67.  
    68.         //assign the sprite to the world
    69.         spriteRenderer.sprite = worldSprite;
    70.  
    71.  
    72.     }
    73.  
    74.     void SetTextureRock(Color[,] textureMap,Color baseColor){
    75.  
    76.  
    77.         for(int x = 0; x < textureSize; x++){
    78.             for(int y = 0; y < textureSize; y++){
    79.  
    80.                 //set a new colour to a random colour similar to base one
    81.                 Color newColor = new Color(Random.Range (baseColor.r - colorOffset,baseColor.r + colorOffset),Random.Range (baseColor.g - colorOffset,baseColor.g + colorOffset),Random.Range (baseColor.b - colorOffset,baseColor.b + colorOffset),1);
    82.  
    83.                 //assign the color to the pixel
    84.                 textureMap[x,y] = newColor;
    85.  
    86.             }
    87.         }
    88.     }
    89.  
    90.     void SetTextureGrass(Color[,] textureMap,Color baseColor){
    91.  
    92.         //generate a whole texture for grass
    93.         SetTextureRock (textureMap, baseColor);
    94.  
    95.         for(int x = 0; x < textureSize; x++){
    96.             for(int y = 0; y < textureSize; y++){
    97.  
    98.                 // get a random number
    99.                 float rand = Random.Range (0,textureSize) / grassTextureWeight;
    100.  
    101.                 // use random number to dertermine if each pixel is grass
    102.                 if(rand > y){
    103.  
    104.                     textureMap[x,y] = Color.clear;
    105.  
    106.                 }
    107.             }
    108.         }
    109.     }
    110.  
    111.     void SetWorldLayout(){
    112.  
    113.         for(int x = 0; x < xWorldSize; x++){
    114.             for(int y = 0; y < yWorldSize; y++){
    115.  
    116.                 if(y < 5 || y > yWorldSize - 5){
    117.  
    118.                     world[x,y] = 1;
    119.  
    120.                 }
    121.                 else{
    122.  
    123.                     world[x,y] = 0;
    124.  
    125.                 }
    126.  
    127.  
    128.             }
    129.         }
    130.     }
    131.  
    132.     void SetWorldTextureToCorrectTexture(){
    133.  
    134.         //go through the entire level, pixel by pixel
    135.         for(int xW = 0; xW < xWorldSize; xW++){
    136.             for(int yW = 0; yW < yWorldSize; yW++){
    137.                 for(int xT = 0; xT < textureSize; xT++){
    138.                     for(int yT = 0; yT < textureSize; yT++){
    139.                    
    140.                         if(world[xW,yW] == 1){
    141.  
    142.                             //asign xW,yW part of the world the rock texture if it is rock
    143.                             worldTexture.SetPixel (xW * textureSize + xT, yW * textureSize + yT,textureRock[xT,yT]);
    144.  
    145.                             // overlay with grass, if it has no rock on top
    146.                             if(yW != 0){
    147.                                 if(world[xW,yW - 1] == 0){
    148.  
    149.                                     if(textureGrass[xT,yT] != Color.clear){
    150.  
    151.                                         worldTexture.SetPixel (xW * textureSize + xT, yW * textureSize + yT,textureGrass[xT,yT]);
    152.  
    153.                                     }
    154.                                 }
    155.                             }
    156.                         }
    157.  
    158.                         else{
    159.  
    160.                             //asign xW,yW part of the world the air texture if it is air
    161.                             worldTexture.SetPixel (xW * textureSize + xT, yW * textureSize + yT, Color.clear);
    162.  
    163.                         }
    164.  
    165.                     }
    166.                 }
    167.             }
    168.         }
    169.  
    170.         //actually apply the changes to the texture
    171.         worldTexture.Apply();
    172.  
    173.     }
    174. }
    175.  
    Thanks in advance, _GingerSheep
     
  2. DarkArts-Studios

    DarkArts-Studios

    Joined:
    May 2, 2013
    Posts:
    389
    Where do you set the actual colour of "colorRock" and "colorGrass"?
     
  3. _GingerSheep

    _GingerSheep

    Joined:
    Aug 17, 2014
    Posts:
    5
    thanks for the reply, I set them in unity, rather then in mono develop. They are public.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,738
    Looking through your "render" code, I think your texture isn't large enough for what you're rendering into it. I think you intend to set the worldTexture equal to these dimensions:

    xWorldSize * textureSize, yWorldSize * textureSize

    That is how you are accessing them when you use .SetPixel later on.

    You would also have to tell the Sprite.Create() function you want a larger rect chopped out of the texture, with these dimensions:

    (0,0,xWorldSize * textureSize, yWorldSize * textureSize)

    Finally, I don't think you're "generating" the kind of world shape that you think you are.

    Put this code in after you make your texture and see what your 1s and 0s are.

    Code (csharp):
    1.  
    2.         for(int xW = 0; xW < xWorldSize; xW++){
    3.             string s = "";
    4.             for(int yW = 0; yW < yWorldSize; yW++){
    5.                 if (world[xW, yW] == 1) s += "1";
    6.                 else s += "0";
    7.             }
    8.             Debug.Log ( s);
    9.         }
    10.         Debug.Break();
    11.  
    Kurt
     
  5. _GingerSheep

    _GingerSheep

    Joined:
    Aug 17, 2014
    Posts:
    5
    Thanks!