webik150

ProceduralAsteroid - Finished

Oct 31st, 2015
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.04 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.IO;
  4.  
  5. public class ProceduralAsteroid : MonoBehaviour {
  6.  
  7.     [Header("Reference texture")]
  8.     public Texture2D referenceTexture;
  9.    
  10.     public float coloringSize = 6;                //Size of the Perlin noise map. Basically, a smaller number means you can see more of the map.
  11.    
  12.     public int wearLevel = 2;                     //How much should we torture the asteroid? Each level has a chance to destroy a "naked" pixel (coloured pixel that's next to transparent pixel).
  13.                                                   //Performance heavy, because each level iterates through all the pixels of the referenceTexture.
  14.     [Range(0f,1f)]
  15.     public float wearChance = 0.5f;               //What is the chance of pixel getting destroyed? 0f-1f. If (Random.value > wearChance), destroy pixel.
  16.    
  17.     [Header("Very Deep Ocean")]                   //Asteroid's layers
  18.     public Color veryDeepOceanColor;
  19.     [Header("Deep Ocean")]
  20.     public float deepOcean;
  21.     public Color deepOceanColor;
  22.     [Header("Ocean")]
  23.     public float ocean;
  24.     public Color oceanColor;
  25.     [Header("Shallow Water")]
  26.     public float shallowWater;
  27.     public Color shallowWaterColor;
  28.     [Header("Beach")]
  29.     public float beach;
  30.     public Color beachColor;
  31.     [Header("Forest")]
  32.     public float forest;
  33.     public Color forestColor;
  34.     [Header("Mountain")]
  35.     public float mountain;
  36.     public Color mountainColor;
  37.     [Header("Mountain Top")]
  38.     public float mountainHigh;
  39.     public Color mountainHighColor;
  40.  
  41.     // Use this for initialization
  42.     void Start () {
  43.    
  44.     }
  45.    
  46.     // Update is called once per frame
  47.     void Update () {
  48.         if (Input.GetKeyDown (KeyCode.G)) {
  49.             Generate (Random.Range (-12525352, -354245), Random.Range (3, 32));
  50.         }
  51.     }
  52.  
  53.     public ProceduralAsteroid Generate (float seed, float size)        //This horrible thing creates asteroids.
  54.     {
  55.         //Material mat = Instantiate<Material> (GetComponent<SpriteRenderer> ().material);    //Uncomment this if you're using custom shaders.
  56.         Color[] finalColors = referenceTexture.GetPixels ();           //First, we need to get the pixels.
  57.         int y = 0;                                                     //Now, we create Height and Width counters (Because GetPixels() returns one dimensional array. Don't ask me why.).
  58.         int xCounter = 0;
  59.         for (int i = 0; i < wearLevel; i++) {                          //For each wearLevel we assigned in the variables
  60.             xCounter = 0;                                              //Reset the counters
  61.             y = 0;
  62.             for (int x = 0; x < finalColors.Length; x++) {             //Iterate through all the pixels
  63.                 if (xCounter == referenceTexture.width) {              //Reset width counter if equal to texture width
  64.                     xCounter = 0;
  65.                 }
  66.                 if (x > 0) {                                           //YOU DON'T LIKE BUGS! THIS KILLS BUGS!
  67.                     if (x % (referenceTexture.width - 1) == 0) {
  68.                         if (y == referenceTexture.width - 1) {
  69.                             break;
  70.                         }
  71.                        
  72.                     }
  73.                     y += 1;                                             //Please note: the y+=1 is in weird place, because it generates the nice random texture. It would normally be two lines up, but that makes the texture smooth.
  74.                 }
  75.                
  76.                 if (finalColors [x] == Color.black) {                                   //Each black pixel,
  77.                     if ((finalColors [x + 1].a == 0) || (finalColors [x - 1].a == 0)) { //that has at least one neighbor missing
  78.                         if (Random.value > wearChance) {                                //has a chance
  79.                             finalColors [x] = new Color (0, 0, 0, 0);                   //of getting removed.
  80.                         }                                                               //Wow, that seems so racist....
  81.                     }
  82.                     if ((finalColors [x - referenceTexture.width].a == 0) || (finalColors [x + referenceTexture.width].a == 0)) {  //The same as above, but checks for up and down.
  83.                         if (Random.value > wearChance) {
  84.                             finalColors [x] = new Color (0, 0, 0, 0);
  85.                         }
  86.                     }
  87.                 }
  88.                 xCounter++;
  89.                
  90.             }
  91.         }
  92.        
  93.         xCounter = 0;                                   //Now, we basically do the same thing, but we assign colours instead of removing pixels.
  94.         y = 0;
  95.         for (int x = 0; x < finalColors.Length; x++) {
  96.             if (xCounter == referenceTexture.width) {
  97.                 xCounter = 0;
  98.             }
  99.             if (x > 0) {
  100.                 if (x % (referenceTexture.width - 1) == 0) {
  101.                     if (y == referenceTexture.width - 1) {
  102.                         break;
  103.                     }
  104.                    
  105.                 }
  106.                 y += 1;
  107.             }
  108.            
  109.             if (finalColors [x] == Color.black) {                                   //Each black pixel
  110.                 finalColors [x] = GetColorByCoordinate (xCounter, y, size, seed);   //Gets the proper colour.
  111.                                                                                     //Wow... again...
  112.                
  113.             }
  114.             xCounter++;
  115.            
  116.         }
  117.         Texture2D finalTexture2D = Instantiate<Texture2D> (referenceTexture);   //Now, we just make a copy of the referenceTexture,
  118.         finalTexture2D.SetPixels (finalColors);                                 //and apply the new colors to it.
  119.         finalTexture2D.filterMode = FilterMode.Point;                           //This kinda makes the texture pixel-perfect.
  120.         finalTexture2D.Apply ();                                                //NEVER FORGET TO APPLY CHANGES!!!!!!!!!
  121.         GetComponent<SpriteRenderer> ().sprite = Sprite.Create (finalTexture2D, new Rect (0, 0, finalTexture2D.width, finalTexture2D.height), new Vector2 (0.5f, 0.5f), GetComponent<SpriteRenderer>().sprite.pixelsPerUnit);  //Now just create a new sprite, with our texture.
  122.         //GetComponent<SpriteRenderer> ().material = mat;     //Uncomment this if you're using custom shaders.
  123.         //GetComponent<SpriteRenderer> ().material.SetTexture ("_MainTex", finalTexture2D);     //Uncomment this if you're using custom shaders.
  124.         return this;   //Enjoy!
  125.     }
  126.  
  127.     Color GetColorByCoordinate (float x, float y, float size, float seed)     //This code generates the colors. It's really simple, Mathf.PerlinNoise(x,y) returns float (0-1) according to the "height" of x and y.
  128.     {
  129.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < deepOcean) {  //We take the height, and check for the apropriate layer. That's all.
  130.             return veryDeepOceanColor;                                               //The (seed+x) could be switched for some more complex calculation, but you can do that when assigning the seed. "/size" makes everything the right size.
  131.         }
  132.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= deepOcean && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < ocean) {
  133.             return deepOceanColor;
  134.         }
  135.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= ocean && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < shallowWater) {
  136.             return oceanColor;
  137.         }
  138.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= shallowWater && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < beach) {
  139.             return shallowWaterColor;
  140.         }
  141.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= beach && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < forest) {
  142.             return beachColor;
  143.         }
  144.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= forest && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < mountain) {
  145.             return forestColor;
  146.         }
  147.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= mountain && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < mountainHigh) {
  148.             return mountainColor;
  149.         }
  150.         if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= mountainHigh) {
  151.             return mountainHighColor;
  152.         }
  153.         return Color.magenta; //The error color. If you did something wrong, you'll see magenta.
  154.     }
  155. }
Advertisement
Add Comment
Please, Sign In to add comment