roguelike地图的随机生成算法
如果要想自己设计一个roguelike游戏,那么需要你有一个随机地图生成,我在indienova上看到一篇文章,描述了一个roguelike算法,然后自己用unity实现了一个下。
原文有这个算法的各种讲解,还有动态的演示图,不理解算法原理的可以去看一下。
根据这个算法的代码:
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 ();
}
}
运行效果图:
最开始随机出来的地图,后面是逐步处理的效果:
![]()
![]()
![]()
![]()
![]()









浙公网安备 33010602011771号