本文对随机生成迷宫的实现思路进行记录,其作用在于为游戏过程提供随机性以及节省开发周期,下面是Dungeonize的结构

  随机迷宫的生成主要包括几个阶段

  

1.生成房间体结构,为墙体,自定义房间,自定义物体生成平台

     for (var i = ; i < room_count; i++) {
Room room = new Room ();
if (rooms.Count == ) {
//初始房间生成玩家和任务事件监听
room.x = (int)Mathf.Floor (map_size / 2f);
room.y = (int)Mathf.Floor (map_size / 2f); //Random.Range(10,20);
room.w = Random.Range (min_size, max_size);
if (room.w % == ) room.w += ;
room.h = Random.Range (min_size, max_size);
if (room.h % == ) room.h += ;
room.branch = ;
lastRoom = room;
} else {
int branch = ;
if (collision_count == ) {
branch = Random.Range (, ); //complexity
}
room.branch = branch; lastRoom = rooms [rooms.Count - ];
int lri = ; while (lastRoom.dead_end) {
lastRoom = rooms [rooms.Count - lri++];
} if (direction == "set") {
string newRandomDirection = directions[Random.Range(, directions.Count)];
direction = newRandomDirection;
while (direction == oldDirection)
{
newRandomDirection = directions[Random.Range(, directions.Count)];
direction = newRandomDirection;
} }
this.roomMarginTemp = Random.RandomRange(, this.roomMargin - );
//邻接方位生成房间
if (direction == "y") {
room.x = lastRoom.x + lastRoom.w + Random.Range (, ) + this.roomMarginTemp;
room.y = lastRoom.y;
} else if (direction == "-y") {
room.x = lastRoom.x - lastRoom.w - Random.Range (, ) - this.roomMarginTemp;
room.y = lastRoom.y;
} else if (direction == "x") {
room.y = lastRoom.y + lastRoom.h + Random.Range (, ) + this.roomMarginTemp;
room.x = lastRoom.x;
} else if (direction == "-x") {
room.y = lastRoom.y - lastRoom.h - Random.Range (, ) - this.roomMarginTemp;
room.x = lastRoom.x;
} room.w = Random.Range (min_size, max_size);
if (room.w % == ) room.w += ; room.h = Random.Range (min_size, max_size);
if (room.h % == ) room.h += ; room.connectedTo = lastRoom;
}

  在随机产生生成房间体后,生成墙体形成一个完整的房间结构,为之后prefab提供空间

//wall 
for (int x = ; x < map_size_x -; x++) {
for (int y = ; y < map_size_y -; y++) {
if (map [x, y].type == ) {
if (map [x + , y].type == || map [x + , y].type == ) { //west
map [x, y].type = ;
map [x, y].room = map [x + , y].room;
}
if (x > ) {
if (map [x - , y].type == || map [x - , y].type == ) { //east
map [x, y].type = ;
map [x, y].room = map [x - , y].room; }
} if (map [x, y + ].type == || map [x, y + ].type == ) { //south
map [x, y].type = ;
map [x, y].room = map [x, y + ].room; } if (y > ) {
if (map [x, y - ].type == || map [x, y - ].type == ) { //north
map [x, y].type = ;
map [x, y].room = map [x, y - ].room; }
}
}
}
}

通过list存储方位参数

//tile types for ease
public static List<int> roomsandfloors = new List<int> { , };
public static List<int> corners = new List<int> {,,,};
public static List<int> walls = new List<int> {,,,};  //wall direction
private static List<string> directions = new List<string> {"x","y","-y","-x"}; //,"-y"};

根据lis存储过道结构

     //corners
for (int x = ; x < map_size_x -; x++) {
for (int y = ; y < map_size_y -; y++) {
if (walls.Contains (map [x, y + ].type) && walls.Contains (map [x + , y].type) && roomsandfloors.Contains (map [x + , y + ].type)) { //north
map [x, y].type = ;
map [x, y].room = map [x + , y + ].room;
}
if (y > ) {
if (walls.Contains (map [x + , y].type) && walls.Contains (map [x, y - ].type) && roomsandfloors.Contains (map [x + , y - ].type)) { //north
map [x, y].type = ;
map [x, y].room = map [x + , y - ].room; }
}
if (x > ) {
if (walls.Contains (map [x - , y].type) && walls.Contains (map [x, y + ].type) && roomsandfloors.Contains (map [x - , y + ].type)) { //north
map [x, y].type = ;
map [x, y].room = map [x - , y + ].room; }
}
if (x > && y > ) {
if (walls.Contains (map [x - , y].type) && walls.Contains (map [x, y - ].type) && roomsandfloors.Contains (map [x - , y - ].type)) { //north
map [x, y].type = ;
map [x, y].room = map [x - , y - ].room; }
}
/* door corners --- a bit problematic in this version */
if (map [x, y].type == ) {
if (map [x + , y].type == ) {
map [x, y + ].type = ;
map [x, y - ].type = ;
} else if (Dungeon.map [x - , y].type == ) {
map [x, y + ].type = ;
map [x, y - ].type = ;
}
} }
}

这样一个房间体的完整结构已经创建完毕,之后对迷宫结构生成地下城结构

        for (var y = ; y < Dungeon.map_size_y; y++) {
for (var x = ; x < Dungeon.map_size_x; x++) {
int tile = Dungeon.map [x, y].type;
int orientation = Dungeon.map[x, y].orientation;
GameObject created_tile;
Vector3 tile_location;
if (!makeIt3d) {
tile_location = new Vector3 (x * tileScaling, y * tileScaling, );
} else {
tile_location = new Vector3 (x * tileScaling, , y * tileScaling);
} created_tile = null;
if (tile == ) {
GameObject floorPrefabToUse = floorPrefab;
Room room = Dungeon.map[x,y].room;
if(room != null){
foreach(CustomRoom customroom in customRooms){
if(customroom.roomId == room.room_id){
floorPrefabToUse = customroom.floorPrefab;
break;
}
}
} created_tile = GameObject.Instantiate (floorPrefabToUse, tile_location, Quaternion.identity) as GameObject;
} if ( Dungeon.walls.Contains(tile)) {
GameObject wallPrefabToUse = wallPrefab;
Room room = Dungeon.map[x,y].room;
if(room != null){
foreach(CustomRoom customroom in customRooms){
if(customroom.roomId == room.room_id){
wallPrefabToUse = customroom.wallPrefab;
break;
}
}
} created_tile = GameObject.Instantiate (wallPrefabToUse, tile_location, Quaternion.identity) as GameObject;
if(!makeIt3d){
created_tile.transform.Rotate(Vector3.forward * (- * (tile -)));
}
else{
created_tile.transform.Rotate(Vector3.up * (- * (tile -)));
}
} if (tile == ) {
if (corridorFloorPrefab)
{
created_tile = GameObject.Instantiate(corridorFloorPrefab, tile_location, Quaternion.identity) as GameObject;
}
else
{
created_tile = GameObject.Instantiate(floorPrefab, tile_location, Quaternion.identity) as GameObject;
} if (orientation == && makeIt3d)
{
created_tile.transform.Rotate(Vector3.up * (-));
} } if (Dungeon.corners.Contains(tile)) {
GameObject cornerPrefabToUse = cornerPrefab;
Room room = Dungeon.map[x,y].room;
if(room != null){
foreach(CustomRoom customroom in customRooms){
if(customroom.roomId == room.room_id){
cornerPrefabToUse = customroom.cornerPrefab;
break;
}
}
} if(cornerPrefabToUse){ //there was a bug in this line. A good man helped for fix.
created_tile = GameObject.Instantiate (cornerPrefabToUse, tile_location, Quaternion.identity) as GameObject;
if(cornerRotation){
if(!makeIt3d){
created_tile.transform.Rotate(Vector3.forward * (- * (tile -)));
}
else{
created_tile.transform.Rotate(Vector3.up * (- * (tile -)));
}
}
}
else{
created_tile = GameObject.Instantiate (wallPrefab, tile_location, Quaternion.identity) as GameObject;
}
} if (created_tile) {
created_tile.transform.parent = transform;
}
}
}

  迷宫生成后,需要对房间内容进行添加,随机的物品以及房间为玩家提供游玩条件,特定的内容包含战斗条件或者任务条件

//Spawn Objects;
List<SpawnList> spawnedObjectLocations = new List<SpawnList> (); //OTHERS
for (int x = ; x < Dungeon.map_size_x; x++) {
for (int y = ; y < Dungeon.map_size_y; y++) {
if (Dungeon.map [x, y].type == &&
((Dungeon.startRoom != Dungeon.map [x, y].room && Dungeon.goalRoom != Dungeon.map [x, y].room) || maximumRoomCount <= )) {
var location = new SpawnList (); location.x = x;
location.y = y;
if (Dungeon.walls.Contains(Dungeon.map[x + , y].type)) {
location.byWall = true;
location.wallLocation = "S";
}
else if (Dungeon.walls.Contains(Dungeon.map[x - , y].type))
{
location.byWall = true;
location.wallLocation = "N";
}
else if (Dungeon.walls.Contains(Dungeon.map[x, y + ].type)) {
location.byWall = true;
location.wallLocation = "W";
}
else if (Dungeon.walls.Contains(Dungeon.map [x, y - ].type)) {
location.byWall = true;
location.wallLocation = "E";
} if (Dungeon.map [x + , y].type == || Dungeon.map [x - , y].type == || Dungeon.map [x, y + ].type == || Dungeon.map [x, y - ].type == ) {
location.byCorridor = true;
}
if (Dungeon.map [x + , y + ].type == || Dungeon.map [x - , y - ].type == || Dungeon.map [x - , y + ].type == || Dungeon.map [x + , y - ].type == ) {
location.byCorridor = true;
}
location.room = Dungeon.map[x,y].room; int roomCenterX = (int)Mathf.Floor(location.room.w / ) + location.room.x;
int roomCenterY = (int)Mathf.Floor(location.room.h / ) + location.room.y; if(x == roomCenterX + && y == roomCenterY + )
{
location.inTheMiddle = true;
}
spawnedObjectLocations.Add (location);
}
else if (Dungeon.map [x, y].type == ) {
var location = new SpawnList ();
location.x = x;
location.y = y; if (Dungeon.map [x + , y].type == ) {
location.byCorridor = true;
location.asDoor = ;
location.room = Dungeon.map[x + ,y].room; spawnedObjectLocations.Add (location);
}
else if(Dungeon.map [x - , y].type == ){
location.byCorridor = true;
location.asDoor = ;
location.room = Dungeon.map[x - ,y].room; spawnedObjectLocations.Add (location);
}
else if (Dungeon.map [x, y + ].type == ){
location.byCorridor = true;
location.asDoor = ;
location.room = Dungeon.map[x,y + ].room; spawnedObjectLocations.Add (location);
}
else if (Dungeon.map [x, y - ].type == ){
location.byCorridor = true;
location.asDoor = ;
location.room = Dungeon.map[x,y - ].room; spawnedObjectLocations.Add (location);
}
}
}
}

这样就能生成基本的随机模型

2d ver

3d ver
也可以根据需求进行修改

Unity_Dungeonize 随机生成迷宫的更多相关文章

  1. canvas——随机生成迷宫

    先上图. 效果 代码 随机生成迷宫要求任意两点都能够找到相同的路径,也就是说,迷宫是一个连通图.随机生成迷宫可以使用普里姆算法.广度优先算法.深度优先算法等实现.这里将使用普里姆算法通过生成最小数的方 ...

  2. 【Javascript + Vue】实现随机生成迷宫图片

    前言 成品预览:https://codesandbox.io/s/maze-vite-15-i7oik?file=/src/maze.js 不久前写了一篇文章介绍了如何解迷宫:https://www. ...

  3. UWP开发:自动生成迷宫&自动寻路算法(3)

    + , + ];//0<=x<=12 0<=y<=24 private static Random Rd = new Random(); 首先声明mazeMap存储数据,声明了 ...

  4. php生成迷宫和迷宫寻址算法实例

    较之前的终于有所改善.生成迷宫的算法和寻址算法其实是一样.只是一个用了遍历一个用了递归.参考了网上的Mike Gold的算法. <?php //zairwolf z@cot8.com heade ...

  5. PHP树生成迷宫及A*自己主动寻路算法

    PHP树生成迷宫及A*自己主动寻路算法 迷宫算法是採用树的深度遍历原理.这样生成的迷宫相当的细,并且死胡同数量相对较少! 随意两点之间都存在唯一的一条通路. 至于A*寻路算法是最大众化的一全自己主动寻 ...

  6. Prim算法生成迷宫

    初始化地图 function initMaze(r,c){ let row = new Array(2 * r + 1) for(let i = 0; i < row.length; i++){ ...

  7. 随机生成长度为len的密码,且包括大写、小写英文字母和数字

    一道华三面试题,随机生成长度为len的密码,且包括大写.小写英文字母和数字,主要Random类的使用,random.nextInt(len)表示生成[0,len)整数.具体实现见下面代码,已经很详细了 ...

  8. Java随机生成18位身份证号

    package com.ihome.data; import java.text.SimpleDateFormat; import java.util.Calendar; import java.ut ...

  9. js 随机生成姓名、手机号、身份证号、银行卡号

    开发测试的时候,经常需要填写姓名.手机号.身份证号.银行卡号,既要符合格式要求.又不能重复.大家会到网上搜各种生成器.能不能自己写一个简单的生成器呢.下面是随机生成姓名.手机号.身份证号.银行卡号的j ...

随机推荐

  1. [C++] WinAES的问题

    WinAES是个不错的windows CAPI封装. 如果C++程序需要和java的程序进行aes加解密通讯,那么WinAES的代码是有问题的. java的aes代码缺省不会设置IV而且采用ECB模式 ...

  2. spring json 返回中文乱码

    如前台显示的json数据中的中文为???,则可尝试以下方法. 方法一(推荐):在@RequestMapping中添加  produces={"text/html;charset=UTF-8; ...

  3. python进阶之面向对象初识

    面向对象 不同于面向过程的编程思想,面向对象是一种将程序抽象为一个个对象的编程思想,能更好的处理现实世界到的一些复杂问题. 通过下面的例子来初步了解面向对象的编程方式. class Person: # ...

  4. 用生活例子来形象了解TCP-IP协议

    TCP/IP模型四层协议 与 邮件? 1.应用层——与用户直接打交道 类似 要寄的物件 2.传输层——处理和增加源数据并传输到IP层 类似 快递单信息 3.IP层——分配地址和传送数据 类似 分拣站分 ...

  5. MVC,MVP,MVVM基本原理

    MVC,MVP,MVVM基本原理 模式与框架,其诞生就是为了解决日益复杂的事务处理 当同一问题不断出现,人们就会总结细分出相应的问题解决办法 当需求变得庞大的时候,就会出现细分,在细分的过程中就会出现 ...

  6. 一排盒子,jq鼠标移入的盒子动画移出停止动画,css动画

    css .category > div.active { animation: servicetobig 0.5s ease 1 forwards; } @keyframes serviceto ...

  7. 2018-8-14-resharper-自定义代码片

    title author date CreateTime categories resharper 自定义代码片 lindexi 2018-08-14 17:34:51 +0800 2018-2-13 ...

  8. javascript拷贝

    function copy(obj){ //浅拷贝 var result = {}; for(var attr in obj){ result[attr] = obj[attr]; } return ...

  9. Java方法参数:

    一个方法不能修改一个基本数据类型的参数 一个方法可以改变一个对象参数的状态 一个方法不能实现让对象参数引用一个新的对象 案例1: 一个方法不能修改一个基本数据类型的参数 String a = &quo ...

  10. 什么是神经网络 (Neural Network)

    反向传播: 可以看作是再一次将传过来的信号传回去, 看看这个负责传递信号神经元对于”讨糖”的动作到底有没有贡献, 让它好好反思与改正, 争取下次做出更好的贡献. 生物神经网络和人工神经网络的差别: 人 ...