zoukankan      html  css  js  c++  java
  • roguelike地图的随机生成算法

    如果要想自己设计一个roguelike游戏,那么需要你有一个随机地图生成,我在indienova上看到一篇文章,描述了一个roguelike算法,然后自己用unity实现了一个下。

    原文地址:随机生成 Tile Based 地图之——洞穴

    原文有这个算法的各种讲解,还有动态的演示图,不理解算法原理的可以去看一下。

    根据这个算法的代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public enum Tile
    {
        Floor,//地板
        Wall//墙
    }
    
    public class createMap : MonoBehaviour {
    
        public int row = 30;
        public int col = 30;
        private Tile[,] mapArray;
        public GameObject wall, floor,player;
        private GameObject map;
        private Transform maps;
        private int forTimes=0;//SmoothMapArray循环次数
        // Use this for initialization
        void Start () {
            mapArray = new Tile[row,col];
            maps = GameObject.FindGameObjectWithTag ("map").transform;
            map = new GameObject ();
            map.transform.SetParent (maps);
            //CreateMap ();
    
            GenerateMap ();
        }
        
        // Update is called once per frame
        void Update () {
            if (Input.GetKeyDown (KeyCode.Q)) {
                Destroy (map);
                GenerateMap ();
            }
            if (Input.GetKeyDown (KeyCode.W)) {
                InitMap ();
            }
            //下一步
            if (Input.GetKeyDown (KeyCode.E)) {
                CreateMap ();
            }
        }
        private void InitMapArray(){
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    //采用<50%生成墙
                    mapArray[i,j] = Random.Range(0,100)<40?Tile.Wall:Tile.Floor;
                    //边界置为墙
                    if (i == 0 || j == 0 || i == row - 1 || j == col - 1) {
                        mapArray [i, j] = Tile.Wall;
                    }
                }
            }
        }
    
        private Tile[,] SmoothMapArray0(){
            Tile[,] newMapArray = new Tile[row,col];
            int wallCount1 = 0,wallCount2 = 0;
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    wallCount1 = CheckNeighborWalls (mapArray, i, j, 1);
                    wallCount2 = CheckNeighborWalls (mapArray, i, j, 2);
                    if (mapArray [i, j] == Tile.Wall) {
                        newMapArray [i, j] = (wallCount1 >= 4) ? Tile.Wall : Tile.Floor;
                    } else {
                        newMapArray [i, j] = (wallCount1 >= 5 || wallCount2<=2) ? Tile.Wall : Tile.Floor;
                    }
                    if (i == 0 || i == row - 1 || j == 0 || j == col - 1) {
                        newMapArray [i, j] = Tile.Wall;
                    }
                }
            }
            return newMapArray;
        }
    
        //4-5规则 
        //当前墙:周围超过4个保持为墙
        //当前地板:周围超过5个墙变为墙
        //循环4-5次
        private Tile[,] SmoothMapArray1(){
            Tile[,] newMapArray = new Tile[row,col];
            int wallCount = 0;
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    wallCount = CheckNeighborWalls (mapArray, i, j, 1);
                    if (mapArray [i, j] == Tile.Wall) {
                        newMapArray [i, j] = (wallCount >= 4) ? Tile.Wall : Tile.Floor;
                    } else {
                        newMapArray [i, j] = (wallCount >= 5) ? Tile.Wall : Tile.Floor;
                    }
                    if (i == 0 || i == row - 1 || j == 0 || j == col - 1) {
                        newMapArray [i, j] = Tile.Wall;
                    }
                }
            }
            return newMapArray;
        }
    
        //判断周围墙的数量
        private int CheckNeighborWalls(Tile[,] mapArray, int i,int j,int t){
            int count = 0;
            for (int k = i - t; k <= i + t; k++) {
                for (int l = j - t; l <= j + t; l++) {
                    if (k >= 0 && k < row && l >= 0 && l < col) {
                        if (mapArray[k,l] == Tile.Wall) {
                            count++;
                        }
                    }
                }
            }
            //去除本身是否为墙
            if (mapArray[i,j] == Tile.Wall) {
                count--;
            }
            return count;
        }
    
        private void InstanceMap (){
            bool setPlayer = true;
            map = new GameObject ();
            map.transform.SetParent (maps);
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    if (mapArray [i, j] == Tile.Floor) {
                        GameObject go = Instantiate (floor, new Vector3 (i, j, 1), Quaternion.identity) as GameObject;
                        go.transform.SetParent (map.transform);
                        //设置层级
                        go.layer = LayerMask.NameToLayer ("floor");
    
                        if (setPlayer) {
                            //设置角色
                            GameObject g_player = Instantiate (player, new Vector3 (i, j, 1), Quaternion.identity) as GameObject;
                            g_player.transform.SetParent (map.transform);
                            setPlayer = false;
                        }
                    } else if (mapArray [i, j] == Tile.Wall) {
                        GameObject go = Instantiate (wall, new Vector3 (i, j, 1), Quaternion.identity) as GameObject;
                        go.transform.SetParent (map.transform);
                        go.layer = LayerMask.NameToLayer ("wall");
                    }
                }
            }
        }
    
    
        private void InitMap (){
            forTimes = 0;
            Destroy (map);
            map = new GameObject ();
            map.transform.SetParent (maps);
            InitMapArray ();
            InstanceMap ();
        }
    
        private void CreateMap (){
            Destroy (map);
            map = new GameObject ();
            map.transform.SetParent (maps);
            if (forTimes < 7) {
                if (forTimes < 4) {
                    mapArray = SmoothMapArray0 ();
                } else {
                    mapArray = SmoothMapArray1 ();
                }
                forTimes++;
            }
            InstanceMap ();
        }
    
        private void GenerateMap (){
            forTimes = 0;
            map = new GameObject ();
            map.transform.SetParent (maps);
            InitMapArray ();
            while (forTimes < 7) {
                if (forTimes < 4) {
                    mapArray = SmoothMapArray0 ();
                } else {
                    mapArray = SmoothMapArray1 ();
                }
                forTimes++;
            }
            InstanceMap ();
        }
    
    }
    运行效果图:
    最开始随机出来的地图,后面是逐步处理的效果:
    
    
    
    
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/sufferingStriver/p/8834299.html
Copyright © 2011-2022 走看看