示例#1
0
    /**
     * If there is any true bits in a 3x3 grid make the centre bit false
     * @param  {BinaryImage} ref BinaryImage   b [description]
     * @return {BinaryImage}     The erosion image
     */
    private BinaryImage erosion(BinaryImage b)
    {
        int[,] dirs = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };
        BinaryImage t = new BinaryImage(b.x, b.y, true);

        int w = b.x; // width
        int h = b.y; // height

        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                // t.Set(x + y*w, true);
                for (int z = 0; z < dirs.GetLength(0); z++)
                {
                    int i = x + dirs[z, 0], j = y + dirs[z, 1];
                    if (i < w && i >= 0 && j < h && j >= 0)
                    {
                        if (!b.Get(i + j * w))
                        {
                            t.Set(x + y * w, false);
                        }
                    }
                    else
                    {
                        t.Set(x + y * w, false);
                    }
                }
            }
        }
        return(t);
    }
示例#2
0
    private List <Vector2> getPath(ref BinaryImage b, int startPos)
    {
        List <Vector2> path = new List <Vector2>();

        // Add start point to path
        path.Add(new Vector2(startPos % b.x, startPos / b.x));

        int  pos = 0, prevPos = startPos, currPos = startPos;
        bool open = true;

        if (!nextPos(ref b, ref pos, prevPos))
        {
            // No other points found from the starting point means this is a single pixel island so we can remove it
            b.Set(currPos, false);
            return(null);
        }

        // While there is a next pos
        while (open)
        {
            if (nextPos(ref b, ref pos, ref currPos, ref prevPos))
            {
                // b.Set(pos, false);
                if (currPos == startPos)
                {
                    open = false;                      // We found a closed path
                }
                path.Add(new Vector2(currPos % b.x, currPos / b.x));
                b.Set(currPos, false);
            }
            else
            {
                // If no next position, backtrack till we find a closed path
                var index = backTrack(ref b, ref path, path.Count - 1);

                if (index != -1)
                {
                    // find next new point!
                    path.RemoveRange(index + 1, path.Count - 1 - index);

                    pos     = (int)path[index].x + (int)path[index].y * b.x;
                    prevPos = (int)path[index - 1].x + (int)path[index - 1].y * b.x;
                    currPos = pos;
                }
                else
                {
                    open = false;  // If we cannot, close the path (this is the worst case and will give us a buggy collider)
                }
            }
        }

        return(path);
    }
示例#3
0
    IEnumerator GenerateTerrain()
    {
        float t = Time.time;

        yield return(new WaitForEndOfFrame());

        SimplexNoiseGenerator sng = new SimplexNoiseGenerator(seed);
        BinaryImage           bi  = new BinaryImage(tex.width, tex.height, false);

        for (int x = 0; x < tex.width; x++)
        {
            float height = sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 200, 1.75f, 2f, 0.9f);
            height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 2, 25, 0.05f, 2f, 0.9f);
            height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 25, 0.1f, 2f, 0.9f);
            for (int y = 0; y < tex.height; y++)
            {
                if (y < height * tex.height + 500)
                {
                    bi.Set(x, y, true);
                }
                else
                {
                    break;
                }
            }
        }
        binaryImage = bi;
        binaryImage = tidyBinaryImage(binaryImage);
        updateCollider();
        Debug.Log((Time.time - t) * 1000f);
    }
示例#4
0
    void floodFill(ref BinaryImage b, ref List <int> i, int pos)
    {
        int w = b.x;

        if (b.Get(pos))
        {
            i.Add(pos);
            b.Set(pos, false);
        }
        else
        {
            return;
        }

        if ((pos % w) + 1 < w)
        {
            floodFill(ref b, ref i, pos + 1);                                                   // Right
        }
        if ((pos % w) - 1 >= 0)
        {
            floodFill(ref b, ref i, pos - 1);                                           // Left
        }
        if (pos + w < b.Length)
        {
            floodFill(ref b, ref i, pos + w);                                   // Top
        }
        if (pos - w >= 0)
        {
            floodFill(ref b, ref i, pos - w);                                                   // Bottom
        }
    }
示例#5
0
    /**
     * Remove a part of the texture
     * @param  {Vector2} point         World point
     * @param  {int}     radius        Radius of destroyed area
     */
    public void ApplyDamage(Vector2 point, int radius)
    {
        // edit binaryImage
        int w = binaryImage.x, h = binaryImage.y;

        // get relative position of the circle
        Vector2 rPos = new Vector2(point.x - transform.position.x, point.y - transform.position.y);

        // get rotation matrix
        float theta = transform.rotation.eulerAngles.z * Mathf.PI / 180f;
        float sin   = Mathf.Sin(theta);
        float cos   = Mathf.Cos(theta);

        // apply rotation to the circle centre
        Vector2 c = new Vector2(rPos.x * cos + rPos.y * sin, -rPos.x * sin + rPos.y * cos);

        c.x = (xBounds + (c.x / transform.localScale.x)) / (xBounds * 2) * w;
        c.y = (yBounds + (c.y / transform.localScale.y)) / (yBounds * 2) * h;

        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                float dx   = x - c.x;
                float dy   = y - c.y;
                float dist = Mathf.Sqrt(dx * dx + dy * dy);
                if (dist <= radius)
                {
                    binaryImage.Set(x + y * w, false);
                }
            }
        }

        updateCollider();
    }
示例#6
0
    /**
     * Generates a BitArray from a Texture2D
     * @param  {Texture2D} t []
     * @return {BitArray} [description]
     */
    private BinaryImage BinaryImageFromTex(ref Texture2D t)
    {
        BinaryImage b = new BinaryImage(t.width, t.height);

        Color[] data = t.GetPixels();

        for (int x = 0; x < b.Length; x++)
        {
            b.Set(x, data[x].a > 0);
        }

        return(b);
    }
示例#7
0
    /**
     * Subtracts one binaryImage from another
     * @param  {BinaryImage}  b1            [description]
     * @param  {BinaryImage}  b2            [description]
     * @return {BinaryImage}             [description]
     */
    private BinaryImage subtraction(BinaryImage b1, BinaryImage b2)
    {
        BinaryImage t = new BinaryImage(b1.x, b1.y);

        int w = b1.x; // width
        int h = b1.y; // height

        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                t.Set(x + y * w, (b1.Get(x + y * w) != b2.Get(x + y * w)));
            }
        }
        return(t);
    }
示例#8
0
    /**
     * Remove a part of the texture
     * @param  {Vector2} point         World point
     * @param  {int}     radius        Radius of destroyed area
     */
    public void ApplyDamage(Vector2 point, int radius)
    {
        // edit binaryImage
        int w = binaryImage.x, h = binaryImage.y;

        // get relative position of the circle
        Vector2 rPos = new Vector2(point.x - transform.position.x, point.y - transform.position.y);

        // get rotation matrix
        float theta = transform.rotation.eulerAngles.z * Mathf.PI / 180f;
        float sin   = Mathf.Sin(theta);
        float cos   = Mathf.Cos(theta);

        // apply rotation to the circle centre
        Vector2 c = new Vector2(rPos.x * cos + rPos.y * sin, -rPos.x * sin + rPos.y * cos);

        c.x = (xBounds + (c.x / transform.localScale.x)) / (xBounds * 2) * w;
        c.y = (yBounds + (c.y / transform.localScale.y)) / (yBounds * 2) * h;
        int loops = 0;

        for (int x = 0; x < w; x++)
        {
            for (int y = 0; y < h; y++)
            {
                float dx   = x - c.x;
                float dy   = y - c.y;
                float dist = Mathf.Sqrt(dx * dx + dy * dy);
                if (dist <= radius)
                {
                    binaryImage.Set(x + y * w, false);
                    loops++;
                }
            }
        }
        Debug.Log("Finished destruction");
        tex = ApplyBinaryImage2Texture(ref tex, ref binaryImage);
        gameObject.GetComponent <SpriteRenderer>().sprite = Sprite.Create(tex, gameObject.GetComponent <SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
        Debug.Log("Finished collider");
    }
    /**
     * Subtracts one binaryImage from another
     * @param  {BinaryImage}  b1            [description]
     * @param  {BinaryImage}  b2            [description]
     * @return {BinaryImage}             [description]
     */
    private BinaryImage subtraction(BinaryImage b1, BinaryImage b2)
    {
        BinaryImage t = new BinaryImage(b1.x, b1.y);

        int w = b1.x; // width
        int h = b1.y; // height

        for(int x=0; x<w; x++){
            for(int y=0; y<h; y++){
                t.Set(x+y*w, (b1.Get(x+y*w)!=b2.Get(x+y*w)) );
            }
        }
        return t;
    }
    void split(BinaryImage b)
    {
        int startPos;

        // TODO: copy the binaryImage instead of setting it
        BinaryImage t = new BinaryImage(b.x, b.y);
        for(int x=0; x<b.Length; x++) t.Set(x, b.Get(x));

        List<List<int> > islands = new List<List<int> >();

        // Find islands
        while(findStartPos(ref t, out startPos)) {
            List<int> island = new List<int>();

            floodFill(ref t, ref island, startPos);

            islands.Add(island);
        }

        // If there is only 1 island we wont split anything
        if(islands.Count <= 1) return;

        // Get bounding boxes for each island
        for(int i=0; i<islands.Count; i++) {
            int x1, y1, x2, y2;
            x1 = x2 = islands[i][0]%b.x;
            y1 = y2 = Mathf.FloorToInt((float)islands[i][0]/b.x);

            // Find the smallest and biggest points
            for(int j=0; j<islands[i].Count; j++) {
                int x = islands[i][j]%b.x, y = Mathf.FloorToInt((float)islands[i][j]/b.x);
                if(x < x1) x1 = x;
                else if(x > x2) x2 = x;
                if(y < y1) y1 = y;
                else if(y > y2) y2 = y;
            }

            int w = x2-x1, h = y2-y1; // bounds
            int cx = (x2+x1)/2, cy = (y2+y1)/2; // new center for island

            // Create new gameobject
            GameObject go = new GameObject("DestructibleSpritePiece");
            go.AddComponent<SpriteRenderer>();
            go.AddComponent<Rigidbody2D>();
            go.AddComponent<DestructibleSprite>();
            go.GetComponent<DestructibleSprite>().doSplit = true;

            // Copy part of the original texture to our new texture
            Color32[] d = tex.GetPixels32();
            Color32[] e = new Color32[w*h];
            for(int x=0, y=0; x<d.Length; x++) {
                if(x%tex.width>=x1 && x%tex.width<x2 && Mathf.FloorToInt((float)x/tex.width)<y2 && Mathf.FloorToInt((float)x/tex.width)>=y1) {
                    e[y] = d[x];
                    y++;
                }
            }

            // Apply to our new texture
            Texture2D texture = new Texture2D(w,h);
            texture.SetPixels32(e);
            texture.Apply();

            // Add the spriteRenderer and apply the texture and inherit parent options
            SpriteRenderer s = go.GetComponent<SpriteRenderer>();
            s.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
            s.color = gameObject.GetComponent<SpriteRenderer>().color;
            s.sortingOrder = gameObject.GetComponent<SpriteRenderer>().sortingOrder;

            // Set the position to the new center
            go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset)/pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset)/pixelsToUnits - yBounds, transform.position.z);
            // Put it in the same layer as the parent
            go.layer = gameObject.layer;

        }
        // We can destroy the orignal object
        Destroy(gameObject);
    }
    private List<Vector2> getPath(ref BinaryImage b, int startPos)
    {
        List<Vector2> path = new List<Vector2>();

        // Add start point to path
        path.Add(new Vector2(startPos%b.x, startPos/b.x));

        int pos = 0, prevPos = startPos, currPos = startPos;
        bool open = true;

        if(!nextPos(ref b, ref pos, prevPos)) {
            // No other points found from the starting point means this is a single pixel island so we can remove it
            b.Set(currPos, false);
            return null;
        }

        // While there is a next pos
        while(open) {
            if(nextPos(ref b, ref pos, ref currPos, ref prevPos)) {
                // b.Set(pos, false);
                if(currPos == startPos) open = false; // We found a closed path
                path.Add(new Vector2(currPos%b.x, currPos/b.x));
                b.Set(currPos, false);
            } else {
                // If no next position, backtrack till we find a closed path
                var index = backTrack(ref b, ref path, path.Count-1);

                if(index!=-1) {
                    // find next new point!
                    path.RemoveRange(index+1, path.Count-1-index);

                    pos = (int)path[index].x + (int)path[index].y*b.x;
                    prevPos = (int)path[index-1].x + (int)path[index-1].y*b.x;
                    currPos = pos;

                } else open = false; // If we cannot, close the path (this is the worst case and will give us a buggy collider)
            }
        }

        return path;
    }
    void floodFill(ref BinaryImage b, ref List<int> i, int pos)
    {
        int w = b.x;

        if(b.Get(pos)) {
            i.Add(pos);
            b.Set(pos, false);
        }	else return;

        if((pos%w)+1 < w) floodFill(ref b, ref i, pos+1);				// Right
        if((pos%w)-1 >= 0) floodFill(ref b, ref i, pos-1);			// Left
        if(pos+w < b.Length) floodFill(ref b, ref i, pos+w);		// Top
        if(pos-w >= 0) floodFill(ref b, ref i, pos-w);					// Bottom
    }
    /**
     * If there is any true bits in a 3x3 grid make the centre bit false
     * @param  {BinaryImage} ref BinaryImage   b [description]
     * @return {BinaryImage}     The erosion image
     */
    private BinaryImage erosion(BinaryImage b)
    {
        int[,] dirs = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
        BinaryImage t = new BinaryImage(b.x, b.y, true);

        int w = b.x; // width
        int h = b.y;	// height

        for(int x=0; x<w; x++) {
            for(int y=0; y<h; y++) {
                // t.Set(x + y*w, true);
                for(int z=0; z<dirs.GetLength(0); z++) {
                    int i = x+dirs[z,0], j = y+dirs[z,1];
                    if(i<w && i>=0 && j<h && j>=0) {
                        if(!b.Get(i + j*w)) t.Set(x + y*w, false);
                    }
                    else t.Set(x + y*w, false);
                }
            }
        }
        return t;
    }
    /**
     * Generates a BitArray from a Texture2D
     * @param  {Texture2D} t []
     * @return {BitArray} [description]
     */
    private BinaryImage BinaryImageFromTex(ref Texture2D t)
    {
        BinaryImage b = new BinaryImage(t.width, t.height);

        Color[] data = t.GetPixels();

        for(int x=0; x<b.Length; x++) b.Set(x, data[x].a > 0 );

        return b;
    }
示例#15
0
    void split(BinaryImage b)
    {
        int startPos;

        // TODO: copy the binaryImage instead of setting it
        BinaryImage t = new BinaryImage(b.x, b.y);

        for (int x = 0; x < b.Length; x++)
        {
            t.Set(x, b.Get(x));
        }

        List <List <int> > islands = new List <List <int> >();

        // Find islands
        while (findStartPos(ref t, out startPos))
        {
            List <int> island = new List <int>();

            floodFill(ref t, ref island, startPos);

            islands.Add(island);
        }

        // If there is only 1 island we wont split anything
        if (islands.Count <= 1)
        {
            return;
        }

        // Get bounding boxes for each island
        for (int i = 0; i < islands.Count; i++)
        {
            int x1, y1, x2, y2;
            x1 = x2 = islands[i][0] % b.x;
            y1 = y2 = Mathf.FloorToInt((float)islands[i][0] / b.x);

            // Find the smallest and biggest points
            for (int j = 0; j < islands[i].Count; j++)
            {
                int x = islands[i][j] % b.x, y = Mathf.FloorToInt((float)islands[i][j] / b.x);
                if (x < x1)
                {
                    x1 = x;
                }
                else if (x > x2)
                {
                    x2 = x;
                }
                if (y < y1)
                {
                    y1 = y;
                }
                else if (y > y2)
                {
                    y2 = y;
                }
            }

            int w = x2 - x1, h = y2 - y1;               // bounds
            int cx = (x2 + x1) / 2, cy = (y2 + y1) / 2; // new center for island

            // Create new gameobject
            GameObject go = new GameObject("DestructibleSpritePiece");
            go.AddComponent <SpriteRenderer>();
            go.AddComponent <Rigidbody2D>();
            go.AddComponent <DestructibleSprite>();
            go.GetComponent <DestructibleSprite>().doSplit = true;

            // Copy part of the original texture to our new texture
            Color32[] d = tex.GetPixels32();
            Color32[] e = new Color32[w * h];
            for (int x = 0, y = 0; x < d.Length; x++)
            {
                if (x % tex.width >= x1 && x % tex.width < x2 && Mathf.FloorToInt((float)x / tex.width) < y2 && Mathf.FloorToInt((float)x / tex.width) >= y1)
                {
                    e[y] = d[x];
                    y++;
                }
            }

            // Apply to our new texture
            Texture2D texture = new Texture2D(w, h);
            texture.SetPixels32(e);
            texture.Apply();

            // Add the spriteRenderer and apply the texture and inherit parent options
            SpriteRenderer s = go.GetComponent <SpriteRenderer>();
            s.sprite       = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
            s.color        = gameObject.GetComponent <SpriteRenderer>().color;
            s.sortingOrder = gameObject.GetComponent <SpriteRenderer>().sortingOrder;

            // Set the position to the new center
            go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset) / pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset) / pixelsToUnits - yBounds, transform.position.z);
            // Put it in the same layer as the parent
            go.layer = gameObject.layer;
        }
        // We can destroy the orignal object
        Destroy(gameObject);
    }