LiteralliJeff 发表于 2023-2-18 08:52

用Unity实现元气骑士地图的自动生成

哈喽大家好,我是yumir~
上次提到unity提供了脚本绘制Tilemap的API,今天就是报告成果的日子啦!(快给我点赞)
这次Tilemap游戏物体的设置是沿用上一篇文章的,如果要做出这种立体效果的话需要到上一篇文章去看哦,这里就不重复了。


传送门:
1、瓦片地图

在脚本中绘制Tilemap只需要调用SetTile()方法,用法如下:
tilemap.SetTile(坐标,瓦片);也就是说想要实现自动生成地图只需要设置好这些坐标点让unity在对应位置放上对应的瓦片就可以了。
那么怎么得到这些坐标点呢?我的做法是先将地图绘制到二维数组中,用不同的数字表示不同的瓦片。
众所周知元气骑士是roguelike游戏,而roguelike游戏的特色就是“随机”。
为了让系统自动绘制出一张随机的地图(保存到二维数组中)我的制作思路是这样的:

[*]首先随机出房间方位;
[*]再在房间方位随机房间;
最终实现效果如下:


2、生成房间布局

这个方法是观(mo)摩(yu)了元气骑士的地图之后总结出来的,稍微有丢丢不一样但是问题不大~
首先要知道几个要点:

[*]房间布局图的格局是5*5的;
[*]房间和房间之间一定有路;
[*]起点在中心,终点在末端;
(从以上三点可以想到用一个树结构可以解决需求,元气骑士看起来是用的图结构)
我在excel里面划拉了一个5*5的表格来表示我们的地图,中间的小房子就是我们每次进入新地图的起点。


接下来我们要开房间咯~在起点周围有四个可选的房间可以开(红色),随机选中其中一个作为第一个房间(绿色)。


可以看到新的房间周围又有三个可选,在三个可选中又随机选中1~3个房间(浅绿色)。


在选出的房间里面随机选择一个房间,重复上一步操作,重复两次(你想重复几次都可以啦反正我重复两次)在选出的房间里面随机选择一个房间作为终点(蓝色), 房间布局就随机出来啦~


实现代码如下:
    /// 统计可选房间
    public void AddRange(int roomVector)
    {
      int[] vec = new int;
      vec = roomVector / 5 == 0 ? -1 : roomVector - 5;
      vec = roomVector / 5 == 4 ? -1 : roomVector + 5;
      vec = roomVector % 5 == 0 ? -1 : roomVector - 1;
      vec = roomVector % 5 == 4 ? -1 : roomVector + 1;
      range.Clear();
      for (int i = 0; i < vec.Length; i++)
       {
            if (vec != -1 && map / 5, vec % 5] == 0)
            {
                range.Add(vec);
            }
      }
   }
    /// 生成新的房间方位
    /// <param name="roomCount">房间数量</param>
    /// <param name="roomType">房间类型</param>
    public void AddRoom(int roomCount, RoomType roomType)
    {
      ++num;
      while (roomCount > 0)
      {
            int b = Random.Range(0, range.Count);
            //加为子节点,修改map值为1
            map / 5, range % 5] = num;
            ranRoom.AddNextRoom(new Room(range, roomType));
            range.Remove(range);
            --roomCount;
         }
      ranRoom = ranRoom.nextRooms;
    }
3、生成完整地图

上文的房间布局是用一个5*5的二位数组存储起来的,而完整的地图则需要一个足够大的二维数组,这个足够大是多大呢,就是你最大的房间有多大,再预留一点空间作为走廊的大小,再乘以五就是大地图的边长了。
虽然是个随机房间的游戏,但是房间的格局可不是可以随便长的,布局信息可以通过excel设计之后转为二维数组数据,我比较懒就直接在脚本里面码出来了(代码在文末网盘),这样一来就可以随机房间的样式了。
道理都懂了,怎么动笔呢?这里就要用到之前提到的树结构了,我声明了一个类,在生成房间布局的时候对每个房间新建一个对应的对象,这个对象又记住了自己的子房间,形成一颗树,比如上面的房间布局生成推演可以生成出一颗这样的树。


这样的好处一方面是在绘制房间之间的通道的时候直接从父节点向子节点计算路径(其实就是画直线)就可以了,一方面在绘制房间的时候不需要遍历整个房间格局二维数组,直接从“起点”往下找每个节点就可以了。
    /// 在大地图中绘制房间
    /// <param name="room">起点</param>
    private void AddRoomForMap(Room room)
   {
      SetRoomInArray(room);
      if (room.nextRooms.Count != 0)
      {
            foreach (Room item in room.nextRooms)
            {
                AddRoomForMap(item);
            }
      }
    }
    /// 在大地图中绘制路径
    /// <param name="room">起点</param>
    private void AddPathForMap(Room room)
    {
      foreach (Room item in room.nextRooms)
       {
            SetPathInArray(room, item);
       }
      foreach (Room item in room.nextRooms)
      {
            if (item.nextRooms.Count != 0)
            {
                AddPathForMap(item);
            }
       }
    }
起点和终点的房间样式是固定的,其他房间则是随机一个“其他房间样式”,通过简单的数学计算得到房间在完整地图上的坐标之后将房间样式二维数组赋值到完整地图的对应位置,再在房间之间画上路径,一个完整地图二维数组就生成好了。
最后遍历完整地图二维数组,根据数组中的数据在Tilemap上绘制瓦片就可以生成最终效果了,再换几套贴图~每次都有新感觉~
链接:https://pan.baidu.com/s/1dSxD-h7dmm0jSxH0G4jVjw
提取码:ow9w

~~~分割线~~~
欢迎加入游戏开发群欢乐搅基:610475807
对游戏开发感兴趣的童鞋可戳这里进一步了解:http://www.levelpp.com/

Arzie100 发表于 2023-2-18 08:57

很容易理解的方法~~ 元气骑士房间少,办法挺多的

kyuskoj 发表于 2023-2-18 09:03

标题打错了

fwalker 发表于 2023-2-18 09:11

生成房间那个看懂了,绘制地图有点迷迷糊糊的[尴尬]
页: [1]
查看完整版本: 用Unity实现元气骑士地图的自动生成