本文对随机生成迷宫的实现思路进行记录,其作用在于为游戏过程提供随机性以及节省开发周期,下面是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. Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory

    遇到问题 在服务器上运行 nexus 出现Native memory allocation (mmap) failed to map 838860800 bytes for committing re ...

  2. Scrap简介

    原文:https://blog.csdn.net/ssw_1990/article/details/51254227 提到Python与网络爬虫,可能会想到urllib,urllib2,Beautif ...

  3. 【u236】火炬

    Time Limit: 1 second Memory Limit: 128 MB 2008北京奥运会,你想成为四川汶川的一名火炬手,结果层层选拔,终于到了最后一关,这一关是一道很难的题:任意给定一个 ...

  4. redux.js的基本使用

    1.先是安装reduxJx, cnpm i --save rudux 2.创建一个store的js文件 3.使用import来引用 redux import { createStore } from ...

  5. 2018-2-13-win10-uwp-异步进度条

    title author date CreateTime categories win10 uwp 异步进度条 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17 ...

  6. Linux 内核 标准 PCI 配置寄存器

    一些 PCI 配置寄存器是要求的, 一些是可选的. 每个 PCI 设备必须包含有意 义的值在被要求的寄存器中, 而可选寄存器的内容依赖外设的实际功能. 可选的字段不被 使用, 除非被要求的字段的内容指 ...

  7. Python11_文件的读写

    1.打开和关闭文件(文件对象的方法open,close) file object = open(file_name [, access_mode][, buffering]) 各个参数的细节如下: f ...

  8. SSL/TLS 配置

    Quick Start 下列说明将使用变量名 $CATALINA_BASE 来表示多数相对路径所基于的基本目录.如果没有为 Tomcat 多个实例设置 CATALINA_BASE 目录,则 $CATA ...

  9. 006.MFC_对话框_复选框_单选钮

    对话框和控件复选框单选框分组框示例:三原色画图 一.建立名为Demo2的MFC工程,按照下图添加控件 并修改2个Group Box Caption属性分别为颜色.外观 修改3个Check Box Ca ...

  10. Memcahced 缓存过期时间问题

    转载:https://help.aliyun.com/knowledge_detail/38654.html 关于设置缓存数据的过期时间,可以参考以下Memcached官方说明: An expirat ...