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

文章首发见博客:https://mwhls.top/4848.html。
无图/格式错误/后续更新请见首发页。
更多更新请到mwhls.top查看
欢迎留言提问或批评建议,私信不回。

汇总:Unity 记录

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

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

Unity记录5.3-地图-随机生成连续地形块_第1张图片

实现代码-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;
        }
    }

你可能感兴趣的:(Unity,unity,游戏引擎)