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随机地下城 | 二、设置门和优化最终房间的选择相关推荐

  1. Unity 2D案例学习——制作Roguelike随机地下城

    01简介 该学习案例来自b站up主M_Studio的系列视频制作Roguelike随机地下城,此篇博客为案例学习笔记 Notice 1.该项目不包含包括敌人在内的一些游戏元素,仅为具有基础功能的dem ...

  2. 【unity实战】随机地下城生成1——随机生成地下城初稿(含源码)

    先看看实现的最终效果 #用到的素材 https://download.csdn.net/download/qq_36303853/87712757 导入素材 导入房间图片素材,配置图片信息信息 点击s ...

  3. mysql高级篇(二)mysql索引优化分析

    mysql高级篇笔记 mysql高级篇(一)mysql的安装配置.架构介绍及SQL语句的复习. mysql高级篇(二)mysql索引优化分析. mysql高级篇(三)查询截取分析(慢查询日志).主从复 ...

  4. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...

  5. 深度学习(31)随机梯度下降九: Himmelblau函数优化实战

    深度学习(31)随机梯度下降九: Himmelblau函数优化实战 1. Himmelblau函数 2. 函数优化实战 1. Himmelblau函数 Himmelblau函数是用来测试后话算法的常用 ...

  6. tableView 获取网络图片,并且设置为圆角(优化,fps)

    代码地址如下: http://www.demodashi.com/demo/11088.html 一.准备工作 例子比较精简,没有什么特殊要求,具备Xocde8.0左右版本的就好 二.程序实现 1.相 ...

  7. 前端页面中根据链接随机生成二维码

    前端页面中根据链接随机生成二维码 1.需要安装qrcodejs2 npm install qrcodejs2 -save 2.在所需要的页面中引入 import QRCode from 'qrcode ...

  8. [Unity]Roguelike随机地图生成(一)

    初步随机地图生成 基础房间生成 房间门的判断 基础房间生成 首先需要确定每次房间生成都是在上一个房间的哪个方向上生成,为此需要声明一个枚举值来记录上下左右四个方向 创建脚本RoomGenerator, ...

  9. 做SEO优化第十一步:如何设置外部链接优化

    网站外链是SEO过程中非常重要的一个环节~往往很多站长忽视或者不知道怎么着手网站外链建设,接下来常州SEO姜东将对外链建设进行讲解.让大家更系统的了解外链建设. 一.外链的基本知识 1.1.外链是什么 ...

  10. SQL Server提高事务复制效率优化(二)快照初始化优化

    SQL Server提高事务复制效率优化(二)快照初始化优化 测试数据表量1500w+,使用初始化默认的快照代理参数,复制的三个过程包括快照初始化,订阅初始化和数据修改复制,主要对快照代理.分发代理. ...

最新文章

  1. Google 全球员工围攻 Google!
  2. 题解 guP2421 【[NOI2002]荒岛野人】
  3. Angular 内容投影出现 No provider for TemplateRef found 错误的单步调试
  4. Elastic Stack简介
  5. LeetCode算法入门- Valid Parentheses -day11
  6. Master of Typing 3 for mac (打字大师3)支持m1
  7. 计算机选修论文,【计算机专业论文】论计算机专业选修课的实践(共2142字)
  8. 用RANSAC算法实现干扰严重的直线拟合(续)求点线距离
  9. Go语言(golang)的错误(error)处理的推荐方案
  10. 如何从初级程序员变成高级程序员?
  11. Android JetPack Room
  12. Java面试题总结之数据结构、算法和计算机基础(刘小牛和丝音的爱情故事1)...
  13. Ubuntu 18 安装DNS解析服务器
  14. 计算机网络协议(三)——UDP、TCP、Socket
  15. 美国L1签证和B1,E2签证的区别
  16. LCD1602液晶显示屏学习笔记
  17. GTD时间管理:高效管理你的时间,GTD软件一款就够
  18. python输出时怎么保留两位小数_python输出怎么保留两位小数-Python教程
  19. wangEditor上传图片事件抛出处理+解决Form-Making中无法粘贴
  20. C语言的字符数组(字符串)的定义与初始化

热门文章

  1. javacv视频处理二:视频合并背景音乐
  2. mysql my.cnf位置_我如何找到MySQL my.cnf位置
  3. ubuntu安装vbox虚拟机
  4. Python安全之使用Python进行MD5解密
  5. vlc搭建流媒体转发服务器
  6. snapchat为什么_什么是Snapchat?
  7. Centos 安装SVN
  8. 注册一个北京公司可以申请办理京牌吗,好申请吗?
  9. 网络信息安全-U盘病毒编写
  10. cortex m3 寄存器