Unity记录5.3-地图-随机生成连续地形块

汇总:Unity 记录

摘要:随机选择若干地形块,并与周围地形连续。

随机生成连续地形块-2023/9/1

  • 在上篇的8个地形块基础上,加了1个实心,1个空气,1个错误,下面的示例图包括除错误外的10个地形。
  • 默认十个正常地形都能生成,然后根据上下左右区块的可选相邻区块,进行随机。

Unity_018_RandomBlock.gif

实现代码-2023/08/31-2023/9/1

  • 在随机可选地形时,通过对四个可用地形列表取交集来实现。
  • 如果最后为空,那说明生成错误,例如下方是空气,左边却是实心块。
    • 如果只有一个连续生成区域,那错误不会出现,但是两个连续生成区域靠近时可能出现。
struct _DirectionsInfo{
    public string[] direction;
    public int ID;
    public int[] up;
    public int[] down;
    public int[] left;
    public int[] right;
    public float[] up_prob;
    public float[] down_prob;
    public float[] left_prob;
    public float[] right_prob;
}

    /*  ---------- surface direction ----------
     *  ┌---┬---┬---┐
     *  │ 7 │ 8 │ 9 │ I label these directions with numbers 
     *  ├---┼---┼---┤     corresponding to the number pad positions for the block's solid area.
     *  │ 4 │ 5 │ 6 │ For example, 
     *  ├---┼---┼---┤     1 in left-down, only left-down tiles are solid, i.e. from left to down
     *  │ 1 │ 2 │ 3 │     4 in left, the tiles in left are solid, i.e. from up-left to down-right
     *  └---┴---┴---┘     7,9 are opposite which denotes the empty area
     *  0. [empty, ]           : no tile in this block
     *  1. [left, down]        : from left to down
     *  2. [horizontal, ]      : from left to right
     *  3. [right, down]       : from right to down
     *  4. [vertical, left]    : from up-left to down-right
     *  5. [full, ]            : all tiles are soild
     *  6. [vertical, right]   : from up-right to down-left
     *  7. [left, up]          : from left to up
     *  8. [horizontal, ]      : 8. == 2.
     *  9. [right, up]         : from right to up
     *  
     *  ---------- Additional directions ----------
     *  -1.[error, ]           : relation error
     * 
     *  ---------- direction relation ----------
     * If direction of this block is 'x', which block can connect it?
     *  ┌---┬---┬---┐       ┌---┬---┬---┐       ┌---┬---┬---┐
     *  │   │3 6│   │       │   │   │   │       │   │1 4│   │
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │239│ 7 │459│       │   │ 2 │   │       │567│ 9 │127│
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │   │ 5 │   │       │   │   │   │       │   │ 5 │   │
     *  └---┴---┴---┘       └---┴---┴---┘       └---┴---┴---┘
     * 
     *  ┌---┬---┬---┐       ┌---┬---┬---┐       ┌---┬---┬---┐
     *  │   │1 4│   │       │   │279│   │       │   │3 6│   │
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │567│ 4 │036│       │6 7│ 5*│4 9│       │014│ 6 │459│
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │   │4 9│   │       │   │   │   │       │   │6 7│   │
     *  └---┴---┴---┘       └---┴---┴---┘       └---┴---┴---┘
     * 
     *  ┌---┬---┬---┐       ┌---┬---┬---┐       ┌---┬---┬---┐
     *  │   │ 0 │   │       │   │ 0 │   │       │   │ 0 │   │
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │239│ 1 │036│       │239│ 2 │127│       │014│ 3 │127│
     *  ├---┼---┼---┤       ├---┼---┼---┤       ├---┼---┼---┤
     *  │   │4 9│   │       │   │ 5 │   │       │   │6 7│   │
     *  └---┴---┴---┘       └---┴---┴---┘       └---┴---┴---┘
     * 
     *  ┌---┬---┬---┐
     *  │   │   │   │   x*: around with x
     *  ├---┼---┼---┤
     *  │1 4│ 0*│3 6│
     *  ├---┼---┼---┤
     *  │   │123│   │
     *  └---┴---┴---┘
     * 
     *  
     */
class _DirectionsConfig{
    _DirectionsInfo[] directions_info = new _DirectionsInfo[] { 
        new _DirectionsInfo{ ID = 0, direction = new string[] {"empty", ""},
            up = new int[]{0},              up_prob = new float[]{1},
            down = new int[]{0, 1, 2, 3},   down_prob = new float[]{1, 1, 1, 1},
            left = new int[]{0, 1, 4},      left_prob = new float[]{1, 1, 1},
            right = new int[]{0, 3, 6},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 1, direction = new string[] {"left", "down"},
            up = new int[]{0},              up_prob = new float[]{1},
            down = new int[]{4, 9},         down_prob = new float[]{1, 1},
            left = new int[]{2, 3, 9},      left_prob = new float[]{1, 1, 1},
            right = new int[]{0, 3, 6},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 2, direction = new string[] {"horizontal", ""}, 
            up = new int[]{0},              up_prob = new float[]{1},
            down = new int[]{5},            down_prob = new float[]{1},
            left = new int[]{2, 3, 9},      left_prob = new float[]{1, 1, 1},
            right = new int[]{1, 2, 7},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 3, direction = new string[] {"right", "down"},
            up = new int[]{0},              up_prob = new float[]{1},
            down = new int[]{6, 7},         down_prob = new float[]{1, 1},
            left = new int[]{0, 1, 4},      left_prob = new float[]{1, 1, 1},
            right = new int[]{1, 2, 7},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 4, direction = new string[] {"vertical", "left"},
            up = new int[]{1, 4},           up_prob = new float[]{1, 1},
            down = new int[]{4, 9},         down_prob = new float[]{1, 1},
            left = new int[]{5, 6, 7},      left_prob = new float[]{1, 1, 1},
            right = new int[]{0, 3, 6},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 5, direction = new string[] {"full", ""},
            up = new int[]{2, 5, 7, 9},     up_prob = new float[]{1, 1, 1, 1},
            down = new int[]{5},            down_prob = new float[]{1},
            left = new int[]{5, 6, 7},      left_prob = new float[]{1, 1, 1},
            right = new int[]{4, 5, 9},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 6, direction = new string[] {"vertical", "right"},
            up = new int[]{3, 6},           up_prob = new float[]{1, 1},
            down = new int[]{6, 7},         down_prob = new float[]{1, 1},
            left = new int[]{0, 1, 4},      left_prob = new float[]{1, 1, 1},
            right = new int[]{4, 5, 9},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 7, direction = new string[] {"left", "up"},
            up = new int[]{3, 6},           up_prob = new float[]{1, 1},
            down = new int[]{5},            down_prob = new float[]{1},
            left = new int[]{2, 3, 9},      left_prob = new float[]{1, 1, 1},
            right = new int[]{4, 5, 9},     right_prob = new float[]{1, 1, 1} 
        },
        new _DirectionsInfo{ ID = 2, direction = new string[] {"horizontal", ""}, 
            up = new int[]{0},              up_prob = new float[]{1},
            down = new int[]{5},            down_prob = new float[]{1},
            left = new int[]{2, 3, 9},      left_prob = new float[]{1, 1, 1},
            right = new int[]{1, 2, 7},     right_prob = new float[]{1, 1, 1} 
        }, // ID8 == ID2
        new _DirectionsInfo{ ID = 9, direction = new string[] {"right", "up"},
            up = new int[]{1, 4},           up_prob = new float[]{1, 1},
            down = new int[]{5},            down_prob = new float[]{1},
            left = new int[]{5, 6, 7},      left_prob = new float[]{1, 1, 1},
            right = new int[]{1, 2, 7},     right_prob = new float[]{1, 1, 1} 
        }
    };

    public string[] select_direction(_BlockAround block_around) {
        int[] available_directions = _get_available_direction(block_around);
        if (available_directions.Length == 0)
            return new string[] {"error", ""};
        float[] directions_prob = new float[available_directions.Length];
        for(int i = 0; i < available_directions.Length; i++){
            directions_prob[i] = 1f;
        }
        int direction_index = _random_by_prob(directions_prob);
        int direction_ID = available_directions[direction_index];
        string [] direction = directions_info[direction_ID].direction;
        return direction;
    }

    int _random_by_prob(float[] probs){
        float sum = probs.Sum();
        float target = Random.Range(0f, sum);
        for(int i = 0; i < probs.Length; i++){
            target -= probs[i];
            if(target <= 0){
                return i;
            }
        }
        return probs.Length - 1;
    }

    int[] _get_available_direction(_BlockAround block_around){
        // int[] around_directions = _get_around_directions(block_around);
        int[] availables = new int[directions_info.Length];
        for(int i = 0; i < directions_info.Length; i++){
            availables[i] = directions_info[i].ID;
        }

        if(block_around.up.isExist){
            int direction_ID = _mapping_direction_to_index(block_around.up.direction);
            int[] avail = directions_info[direction_ID].down;
            availables = availables.Intersect(avail).ToArray();
        }
        if(block_around.down.isExist){
            int direction_ID = _mapping_direction_to_index(block_around.down.direction);
            int[] avail = directions_info[direction_ID].up;
            availables = availables.Intersect(avail).ToArray();
        }
        if(block_around.left.isExist){
            int direction_ID = _mapping_direction_to_index(block_around.left.direction);
            int[] avail = directions_info[direction_ID].right;
            availables = availables.Intersect(avail).ToArray();
        }
        if(block_around.right.isExist){
            int direction_ID = _mapping_direction_to_index(block_around.right.direction);
            int[] avail = directions_info[direction_ID].left;
            availables = availables.Intersect(avail).ToArray();
        }
        return availables;
    }

    int _mapping_direction_to_index(string[] direction){
        for(int i = 0; i < directions_info.GetLength(0); i++)
            if(direction[0] == directions_info[i].direction[0] && direction[1] == directions_info[i].direction[1])
                return i;
        return -1;
    }
}

版权声明:
作者:MWHLS
链接:https://panwj.top/4848.html
来源:无镣之涯
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录