Unity_Dungeonize 随机生成迷宫

时间:2022-09-08 19:22:00

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

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

  Unity_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);
}
}
}
}

这样就能生成基本的随机模型
Unity_Dungeonize 随机生成迷宫
2d ver
Unity_Dungeonize 随机生成迷宫
3d ver
也可以根据需求进行修改

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

  1. canvas——随机生成迷宫

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

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

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

  3. UWP开发:自动生成迷宫&amp&semi;自动寻路算法(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&ast;自己主动寻路算法

    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. window&period;frameElement的使用

    window.frameElement的使用: 返回嵌入当前window对象的元素(比如 <iframe> 或者 <object>),如果当前window对象已经是顶层窗口,则 ...

  2. php计算中英文混搭字符串长度

    preg_match_all('/./us', $content, $match); count($match[0])://中英文按相同字符数计算

  3. css style与class之间的区别

    问题描述:    网页点击[导出]按钮后,将页面table内容另存成excel文件,却发现无法保存表格样式 分析过程: 1.table表格用class,而不是style.导出时并没有导出class定义 ...

  4. C&num;之异步

    C#之异步 异步是相对于同步而言.跟多线程不能同一而论.异步简单而言好比一个人两双手可以同时做两件以上不同的事情.多线程好比多个人做不同或相同的事情. 异步跟多线程有什么关系? 异步可以分为CPU异步 ...

  5. 前端开发,走浏览器缓存真的很烦,拒绝浏览器走缓存从meta标签做起!

    <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv ...

  6. C&plus;&plus;构造函数和析构函数的调用顺序

    1.构造函数的调用顺序 基类构造函数.对象成员构造函数.派生类本身的构造函数 2.析构函数的调用顺序 派生类本身的析构函数.对象成员析构函数.基类析构函数(与构造顺序正好相反) 3.特例 局部对象,在 ...

  7. C&num;反编译笔记

    碰到下面这种 public class DstBoneName : Enum { public int value__; ; } 还原为 public enum DstBoneName { cf_J_ ...

  8. Python sendmail

    #coding:utf- #强制使用utf-8编码格式 import smtplib #加载smtplib模块 from email.mime.text import MIMEText from em ...

  9. &lbrack;django&rsqb;django models最佳实战

    models class People(models.Model): name = models.CharField(max_length=30) age = models.CharField(max ...

  10. transiton&comma;transform&comma;animation&comma;border-image

    animation,transition,transform三者联系与区别: https://www.jianshu.com/p/0e0e1903b80d transform: 使用小技巧: tran ...