Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.IO;
- public class ProceduralAsteroid : MonoBehaviour {
- [Header("Reference texture")]
- public Texture2D referenceTexture;
- public float coloringSize = 6; //Size of the Perlin noise map. Basically, a smaller number means you can see more of the map.
- 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).
- //Performance heavy, because each level iterates through all the pixels of the referenceTexture.
- [Range(0f,1f)]
- public float wearChance = 0.5f; //What is the chance of pixel getting destroyed? 0f-1f. If (Random.value > wearChance), destroy pixel.
- [Header("Very Deep Ocean")] //Asteroid's layers
- public Color veryDeepOceanColor;
- [Header("Deep Ocean")]
- public float deepOcean;
- public Color deepOceanColor;
- [Header("Ocean")]
- public float ocean;
- public Color oceanColor;
- [Header("Shallow Water")]
- public float shallowWater;
- public Color shallowWaterColor;
- [Header("Beach")]
- public float beach;
- public Color beachColor;
- [Header("Forest")]
- public float forest;
- public Color forestColor;
- [Header("Mountain")]
- public float mountain;
- public Color mountainColor;
- [Header("Mountain Top")]
- public float mountainHigh;
- public Color mountainHighColor;
- // Use this for initialization
- void Start () {
- }
- // Update is called once per frame
- void Update () {
- if (Input.GetKeyDown (KeyCode.G)) {
- Generate (Random.Range (-12525352, -354245), Random.Range (3, 32));
- }
- }
- public ProceduralAsteroid Generate (float seed, float size) //This horrible thing creates asteroids.
- {
- //Material mat = Instantiate<Material> (GetComponent<SpriteRenderer> ().material); //Uncomment this if you're using custom shaders.
- Color[] finalColors = referenceTexture.GetPixels (); //First, we need to get the pixels.
- int y = 0; //Now, we create Height and Width counters (Because GetPixels() returns one dimensional array. Don't ask me why.).
- int xCounter = 0;
- for (int i = 0; i < wearLevel; i++) { //For each wearLevel we assigned in the variables
- xCounter = 0; //Reset the counters
- y = 0;
- for (int x = 0; x < finalColors.Length; x++) { //Iterate through all the pixels
- if (xCounter == referenceTexture.width) { //Reset width counter if equal to texture width
- xCounter = 0;
- }
- if (x > 0) { //YOU DON'T LIKE BUGS! THIS KILLS BUGS!
- if (x % (referenceTexture.width - 1) == 0) {
- if (y == referenceTexture.width - 1) {
- break;
- }
- }
- 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.
- }
- if (finalColors [x] == Color.black) { //Each black pixel,
- if ((finalColors [x + 1].a == 0) || (finalColors [x - 1].a == 0)) { //that has at least one neighbor missing
- if (Random.value > wearChance) { //has a chance
- finalColors [x] = new Color (0, 0, 0, 0); //of getting removed.
- } //Wow, that seems so racist....
- }
- if ((finalColors [x - referenceTexture.width].a == 0) || (finalColors [x + referenceTexture.width].a == 0)) { //The same as above, but checks for up and down.
- if (Random.value > wearChance) {
- finalColors [x] = new Color (0, 0, 0, 0);
- }
- }
- }
- xCounter++;
- }
- }
- xCounter = 0; //Now, we basically do the same thing, but we assign colours instead of removing pixels.
- y = 0;
- for (int x = 0; x < finalColors.Length; x++) {
- if (xCounter == referenceTexture.width) {
- xCounter = 0;
- }
- if (x > 0) {
- if (x % (referenceTexture.width - 1) == 0) {
- if (y == referenceTexture.width - 1) {
- break;
- }
- }
- y += 1;
- }
- if (finalColors [x] == Color.black) { //Each black pixel
- finalColors [x] = GetColorByCoordinate (xCounter, y, size, seed); //Gets the proper colour.
- //Wow... again...
- }
- xCounter++;
- }
- Texture2D finalTexture2D = Instantiate<Texture2D> (referenceTexture); //Now, we just make a copy of the referenceTexture,
- finalTexture2D.SetPixels (finalColors); //and apply the new colors to it.
- finalTexture2D.filterMode = FilterMode.Point; //This kinda makes the texture pixel-perfect.
- finalTexture2D.Apply (); //NEVER FORGET TO APPLY CHANGES!!!!!!!!!
- 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.
- //GetComponent<SpriteRenderer> ().material = mat; //Uncomment this if you're using custom shaders.
- //GetComponent<SpriteRenderer> ().material.SetTexture ("_MainTex", finalTexture2D); //Uncomment this if you're using custom shaders.
- return this; //Enjoy!
- }
- 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.
- {
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < deepOcean) { //We take the height, and check for the apropriate layer. That's all.
- 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.
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= deepOcean && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < ocean) {
- return deepOceanColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= ocean && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < shallowWater) {
- return oceanColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= shallowWater && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < beach) {
- return shallowWaterColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= beach && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < forest) {
- return beachColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= forest && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < mountain) {
- return forestColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= mountain && Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) < mountainHigh) {
- return mountainColor;
- }
- if (Mathf.PerlinNoise ((seed + x) / size, (seed + y) / size) >= mountainHigh) {
- return mountainHighColor;
- }
- return Color.magenta; //The error color. If you did something wrong, you'll see magenta.
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment