Roguelike随机地下城 | 二、设置门和优化最终房间的选择
Roguelike随机地下城
设置门&优化最终房间的选择
一、设置门&优化最终房间的选择
首先我们先添加四个方向的门。
点击Prefab,然后我们建立一个方形暂时代替我们的门。
右键|creat|2D|Sprites|Square。
然后拖入我们的Prefab中复制三个,放置到如图的位置。
接下来建立一个Room脚本挂载到Prefab上。
首先我们先声明这四个GameObject。
public GameObject doorLeft,doorRight,doorUp,doorDown;
回到Unity对齐进行赋值。
这里将会用到Sorting Layer,他表示我们的显示层,为了我们的门可以显示出来,我们这里建立一个Room层,同时把Ground和Player层建立。
接下来我们将判断这个房间上下左右是否有门,我们要生成四个布尔值。
public bool roomLeft,roomRight, roomUp, roomDown;
然后我们在之后需要考虑它们是否显示出来,所以我们在Start方法中定义一下显示的方法。
void Start(){doorLeft.SetActive(roomLeft);doorRight.SetActive(roomRight);doorUp.SetActive(roomUp);doorDown.SetActive(roomDown);}
我们会判断当前的房间上下左右是否有房间,有房间就显示门,没有就不显示。
接下来我们判断上下左右是否有房间。
为了获得每一个房间上面的变量,将我们一开始设置的rooms的List的类型改成Room,下面的地方并做适当的更改。
public List<Room> rooms = new List<Room>();void Start(){for (int i = 0; i < rooNumber; i++){rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity).GetComponent<Room>());//改变point位置ChangePointPos();}rooms[0].GetComponent<SpriteRenderer>().color = startColor;endRoom = rooms[0].gameObject;foreach (var room in rooms){if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude){endRoom = room.gameObject;}}endRoom.GetComponent<SpriteRenderer>().color = endColor;}
接下来我们要设置一个方法,来判断上下左右是否有房间,并对Room进行赋值。
方法中需要加入两个参数,一个用于识别Room,一个用于获得房间的位置。
public void SetupRoom(Room newRoom,Vector3 roomPosition){newRoom.roomUp = Physics2D.OverlapCircle(roomPosition + new Vector3(0, yOffset, 0), 0.2f, roomLayer);newRoom.roomDown = Physics2D.OverlapCircle(roomPosition + new Vector3(0, -yOffset, 0), 0.2f, roomLayer);newRoom.roomLeft = Physics2D.OverlapCircle(roomPosition + new Vector3(-xOffset, 0, 0), 0.2f, roomLayer);newRoom.roomRight = Physics2D.OverlapCircle(roomPosition + new Vector3(xOffset, 0, 0), 0.2f, roomLayer);}
调用这个方法,可以先将之前找到最后一个房间的方法注释掉。
void Start(){for (int i = 0; i < rooNumber; i++){rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity).GetComponent<Room>());//改变point位置ChangePointPos();}rooms[0].GetComponent<SpriteRenderer>().color = startColor;endRoom = rooms[0].gameObject;foreach (var room in rooms){//if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude)//{//endRoom = room.gameObject;//}SetupRoom(room,room.transform.position);}endRoom.GetComponent<SpriteRenderer>().color = endColor;}
这样我们的门就设置好了。
二、优化最终房间的选择
我们要选择离我们出生点最远的那个房间,所以接下来我添加一个Text方便显示,每一个房间到我出生点房间的网格的步数。
首先为我们的Prefab建立一个画布Canvas在建立一个Text,把文字改为0。
设置好之后,我们要在脚本中获得这个Text,并且更改他的数值。
这里我们在Room脚本中新建一个方法。
public void UpdateRoom(){}
我们的步数怎么计算呢?
可以通过我们当前房间的坐标,x、y值除以我们的x、y的偏移量就可以得到步数!
我们要获得这个数值,所以一开始先定义一个变量。
因为我们的坐标可能是负数,所以我们要用到数学方法中的绝对值。
这里我为了方便直接除以了固定的值。
public int stepToStart;public void UpdateRoom(){stepToStart = (int)(Mathf.Abs(transform.position.x / 18) + Mathf.Abs(transform.position.y / 9));}
然后我们定义一个变量来获得我们的文本。
然后让这个文本显示我们的stepToStart。
public Text text;public void UpdateRoom(){stepToStart = (int)(Mathf.Abs(transform.position.x / 18) + Mathf.Abs(transform.position.y / 9));text.text = stepToStart.ToString();}
然后我们这个方法要在RoomGenerator脚本中的SetupRoom方法中调用。
public void SetupRoom(Room newRoom,Vector3 roomPosition){newRoom.roomUp = Physics2D.OverlapCircle(roomPosition + new Vector3(0, yOffset, 0), 0.2f, roomLayer);newRoom.roomDown = Physics2D.OverlapCircle(roomPosition + new Vector3(0, -yOffset, 0), 0.2f, roomLayer);newRoom.roomLeft = Physics2D.OverlapCircle(roomPosition + new Vector3(-xOffset, 0, 0), 0.2f, roomLayer);newRoom.roomRight = Physics2D.OverlapCircle(roomPosition + new Vector3(xOffset, 0, 0), 0.2f, roomLayer);newRoom.UpdateRoom();}
接下来我们怎么设置我们的最终房间?
我们的思路是找到步数最大的和次大的房间,找到只有一个门的房间,随机选择一个当作最终房间,如果没有只有一个门的房间,那么我们就随机选择一个步数最大的房间当作最终房间。
接下来要设计三个列表,一个用来存放步数最大的房间,一个存放步数次大的房间,一个存放两种房间只有一个门的房间。
首先回到Room脚本,首先我们先找到一个房间有几个门。
我们先定义一个变量,用来记录门的数量。
然后我们有四个布尔值,每有一个布尔值为true,我们的数量就加1。
public int doorNumber;public void UpdateRoom(){stepToStart = (int)(Mathf.Abs(transform.position.x / 18) + Mathf.Abs(transform.position.y / 9));text.text = stepToStart.ToString();if (roomUp)doorNumber++;if (roomDown)doorNumber++;if (roomLeft)doorNumber++;if (roomRight)doorNumber++;}
接下来回到RoomGenerator脚本中定义三个数值。
List<GameObject> farRooms = new List<GameObject>();List<GameObject> lessFarRooms = new List<GameObject>();List<GameObject> oneWayRooms = new List<GameObject>();
然后我们再定义一个变量,用来表示步数最大的那个数字。
public int maxStep;
新定义一个方法,用来找到最终的房间。
首先我们用一个for循环,找到所有房间里面步数最大的房间,把他加入farRooms数组中,把次大的房间放入lessFarRooms数组中。
//获得最大数值for (int i = 0; i < rooms.Count; i++){if (rooms[i].stepToStart > maxStep)maxStep = rooms[i].stepToStart;}//获得最大数值房间和次大数值房间foreach (var room in rooms){if (room.stepToStart == maxStep)farRooms.Add(room.gameObject);if(room.stepToStart == maxStep-1)lessFarRooms.Add(room.gameObject);}
接下来判断数组中有没有只有一个门的房间。
for (int i = 0; i < farRooms.Count; i++){if (farRooms[i].GetComponent<Room>().doorNumber == 1)oneWayRooms.Add(farRooms[i]);}for (int i = 0; i < lessFarRooms.Count; i++){if (lessFarRooms[i].GetComponent<Room>().doorNumber == 1)oneWayRooms.Add(lessFarRooms[i]);}
接下来如果两个oneWayRooms数组中有数值,就随机在这个数组中随机取一个数值,作为对应的最终房间,如果数值为0,则在farRooms数值中随机取一个数值,作为对应的最终房间。
if (oneWayRooms.Count != 0){endRoom = oneWayRooms[Random.Range(0, oneWayRooms.Count)];}else{endRoom = farRooms[Random.Range(0, farRooms.Count)];}
最后在上面调用就可以了。
void Start(){for (int i = 0; i < rooNumber; i++){rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity).GetComponent<Room>());//改变point位置ChangePointPos();}rooms[0].GetComponent<SpriteRenderer>().color = startColor;endRoom = rooms[0].gameObject;foreach (var room in rooms){//if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude)//{// endRoom = room.gameObject;//}SetupRoom(room,room.transform.position);}FindEndRoom();endRoom.GetComponent<SpriteRenderer>().color = endColor;}
最后运行一下,效果如下。
源码
现阶段我们的完整代码如下:
RoomGenerator脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class RoomGenerator : MonoBehaviour
{public enum Direction {up,down,left,right };public Direction direction;[Header("房间信息")]public GameObject roomPrefab;public int rooNumber;public Color startColor,endColor;private GameObject endRoom;[Header("位置控制")]public Transform generatorPoint;public float xOffset;public float yOffset;public LayerMask roomLayer;public int maxStep;public List<Room> rooms = new List<Room>();List<GameObject> farRooms = new List<GameObject>();List<GameObject> lessFarRooms = new List<GameObject>();List<GameObject> oneWayRooms = new List<GameObject>();// Start is called before the first frame updatevoid Start(){for (int i = 0; i < rooNumber; i++){rooms.Add(Instantiate(roomPrefab, generatorPoint.position, Quaternion.identity).GetComponent<Room>());//改变point位置ChangePointPos();}rooms[0].GetComponent<SpriteRenderer>().color = startColor;endRoom = rooms[0].gameObject;foreach (var room in rooms){//if (room.transform.position.sqrMagnitude > endRoom.transform.position.sqrMagnitude)//{// endRoom = room.gameObject;//}SetupRoom(room,room.transform.position);}FindEndRoom();endRoom.GetComponent<SpriteRenderer>().color = endColor;}// Update is called once per framevoid Update(){if (Input.anyKeyDown){SceneManager.LoadScene(SceneManager.GetActiveScene().name);}}public void ChangePointPos(){do{direction = (Direction)Random.Range(0, 4);switch (direction){case Direction.up:generatorPoint.position += new Vector3(0, yOffset, 0);break;case Direction.down:generatorPoint.position += new Vector3(0, -yOffset, 0);break;case Direction.left:generatorPoint.position += new Vector3(-xOffset, 0, 0);break;case Direction.right:generatorPoint.position += new Vector3(xOffset, 0, 0);break;}}while (Physics2D.OverlapCircle(generatorPoint.position,0.2f,roomLayer));}public void SetupRoom(Room newRoom,Vector3 roomPosition){newRoom.roomUp = Physics2D.OverlapCircle(roomPosition + new Vector3(0, yOffset, 0), 0.2f, roomLayer);newRoom.roomDown = Physics2D.OverlapCircle(roomPosition + new Vector3(0, -yOffset, 0), 0.2f, roomLayer);newRoom.roomLeft = Physics2D.OverlapCircle(roomPosition + new Vector3(-xOffset, 0, 0), 0.2f, roomLayer);newRoom.roomRight = Physics2D.OverlapCircle(roomPosition + new Vector3(xOffset, 0, 0), 0.2f, roomLayer);newRoom.UpdateRoom();}public void FindEndRoom(){//获得最大数值for (int i = 0; i < rooms.Count; i++){if (rooms[i].stepToStart > maxStep)maxStep = rooms[i].stepToStart;}//获得最大数值房间和次大数值房间foreach (var room in rooms){if (room.stepToStart == maxStep)farRooms.Add(room.gameObject);if(room.stepToStart == maxStep-1)lessFarRooms.Add(room.gameObject);}for (int i = 0; i < farRooms.Count; i++){if (farRooms[i].GetComponent<Room>().doorNumber == 1)oneWayRooms.Add(farRooms[i]);}for (int i = 0; i < lessFarRooms.Count; i++){if (lessFarRooms[i].GetComponent<Room>().doorNumber == 1)oneWayRooms.Add(lessFarRooms[i]);}if (oneWayRooms.Count != 0){endRoom = oneWayRooms[Random.Range(0, oneWayRooms.Count)];}else{endRoom = farRooms[Random.Range(0, farRooms.Count)];}}
}
Room脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Room : MonoBehaviour
{public GameObject doorLeft,doorRight,doorUp,doorDown;public bool roomLeft,roomRight, roomUp, roomDown;public Text text;public int stepToStart;public int doorNumber;// Start is called before the first frame updatevoid Start(){doorLeft.SetActive(roomLeft);doorRight.SetActive(roomRight);doorUp.SetActive(roomUp);doorDown.SetActive(roomDown);}// Update is called once per framepublic void UpdateRoom(){stepToStart = (int)(Mathf.Abs(transform.position.x / 18) + Mathf.Abs(transform.position.y / 9));text.text = stepToStart.ToString();if (roomUp)doorNumber++;if (roomDown)doorNumber++;if (roomLeft)doorNumber++;if (roomRight)doorNumber++;}
}
Roguelike随机地下城 | 二、设置门和优化最终房间的选择相关推荐
- Unity 2D案例学习——制作Roguelike随机地下城
01简介 该学习案例来自b站up主M_Studio的系列视频制作Roguelike随机地下城,此篇博客为案例学习笔记 Notice 1.该项目不包含包括敌人在内的一些游戏元素,仅为具有基础功能的dem ...
- 【unity实战】随机地下城生成1——随机生成地下城初稿(含源码)
先看看实现的最终效果 #用到的素材 https://download.csdn.net/download/qq_36303853/87712757 导入素材 导入房间图片素材,配置图片信息信息 点击s ...
- mysql高级篇(二)mysql索引优化分析
mysql高级篇笔记 mysql高级篇(一)mysql的安装配置.架构介绍及SQL语句的复习. mysql高级篇(二)mysql索引优化分析. mysql高级篇(三)查询截取分析(慢查询日志).主从复 ...
- (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例
Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...
- 深度学习(31)随机梯度下降九: Himmelblau函数优化实战
深度学习(31)随机梯度下降九: Himmelblau函数优化实战 1. Himmelblau函数 2. 函数优化实战 1. Himmelblau函数 Himmelblau函数是用来测试后话算法的常用 ...
- tableView 获取网络图片,并且设置为圆角(优化,fps)
代码地址如下: http://www.demodashi.com/demo/11088.html 一.准备工作 例子比较精简,没有什么特殊要求,具备Xocde8.0左右版本的就好 二.程序实现 1.相 ...
- 前端页面中根据链接随机生成二维码
前端页面中根据链接随机生成二维码 1.需要安装qrcodejs2 npm install qrcodejs2 -save 2.在所需要的页面中引入 import QRCode from 'qrcode ...
- [Unity]Roguelike随机地图生成(一)
初步随机地图生成 基础房间生成 房间门的判断 基础房间生成 首先需要确定每次房间生成都是在上一个房间的哪个方向上生成,为此需要声明一个枚举值来记录上下左右四个方向 创建脚本RoomGenerator, ...
- 做SEO优化第十一步:如何设置外部链接优化
网站外链是SEO过程中非常重要的一个环节~往往很多站长忽视或者不知道怎么着手网站外链建设,接下来常州SEO姜东将对外链建设进行讲解.让大家更系统的了解外链建设. 一.外链的基本知识 1.1.外链是什么 ...
- SQL Server提高事务复制效率优化(二)快照初始化优化
SQL Server提高事务复制效率优化(二)快照初始化优化 测试数据表量1500w+,使用初始化默认的快照代理参数,复制的三个过程包括快照初始化,订阅初始化和数据修改复制,主要对快照代理.分发代理. ...
最新文章
- Google 全球员工围攻 Google!
- 题解 guP2421 【[NOI2002]荒岛野人】
- Angular 内容投影出现 No provider for TemplateRef found 错误的单步调试
- Elastic Stack简介
- LeetCode算法入门- Valid Parentheses -day11
- Master of Typing 3 for mac (打字大师3)支持m1
- 计算机选修论文,【计算机专业论文】论计算机专业选修课的实践(共2142字)
- 用RANSAC算法实现干扰严重的直线拟合(续)求点线距离
- Go语言(golang)的错误(error)处理的推荐方案
- 如何从初级程序员变成高级程序员?
- Android JetPack Room
- Java面试题总结之数据结构、算法和计算机基础(刘小牛和丝音的爱情故事1)...
- Ubuntu 18 安装DNS解析服务器
- 计算机网络协议(三)——UDP、TCP、Socket
- 美国L1签证和B1,E2签证的区别
- LCD1602液晶显示屏学习笔记
- GTD时间管理:高效管理你的时间,GTD软件一款就够
- python输出时怎么保留两位小数_python输出怎么保留两位小数-Python教程
- wangEditor上传图片事件抛出处理+解决Form-Making中无法粘贴
- C语言的字符数组(字符串)的定义与初始化