随机Tiled Map的生成

来源:互联网 发布:用电脑看小说的软件 编辑:程序博客网 时间:2024/05/22 12:49
背景
Tiled Map是一种利用地块儿元素拼接,构成2D或伪3D地图的技术。随机地图生成技术,则可以不依赖人力,通过程序产生大量的各不相同的游戏地图。当我们把这两种技术结合起来,就可以在游戏中提供大量的、运行期产生的tiled map类型地图,大大增加这类游戏的耐玩程度。下面的图片来自知名的游戏系列<<风来的西林>>,这一系列的游戏就以随机地图著称。玩家每次进入游戏,都会挑战与上次不同的关卡。本文将介绍一种产生随机tiled map的方法。

 


简介
我们要产生的地图采用著名的“Tiled”编辑器的TMX格式,风格上则是isometric投影的即时战略游戏,如下图:
 

随机地图生成的过程可以简单归结为以下步骤,现在我们可以暂且不理解每一步的用意,后面会有设计思路的说明。
  1. 根据地图模板的尺寸产生对应的“可行走/障碍物”点阵(下文也会使用w点阵的叫法)。
  2. 定义2个地形类型(terrain type)过渡的队列(下文也会使用t队列的叫法),分别对应可行走区域和障碍物区域。
  3. 针对“可行走/障碍物”点阵的每个点进行噪声扰动,并根据噪声值和上述2个地形类型过渡队列,获得地形类型点阵。
  4. 制作一个TMX格式的地图文件模板,其中包含了tileset和terrain types的定义。
  5. 根据地形类型点阵,配合TMX地图文件模板的tileset中定义的tile和每个tile的4个角的terrain types,产生tiled map。
  6. 输出TMX格式的地图文件。

我们从解决方案的设计思路上来说明一下上述的各个步骤。

首先需要考虑通过什么样的手段来产生随机的地图效果。对于我们希望得到的这种地图,最基本的,我们需要有一个可行走区域的轮廓,即哪些区域是可行走的,哪些区域是障碍物,如果我们能够产生随机的可行走区域,那么问题就解决了很大一部分。这项工作对应上述步骤的第1步:根据地图模板的尺寸产生对应的“可行走/障碍物”点阵

对于一副地图,只定义哪些区域可以行走哪些区域不能行走是远远不够的,因为这些信息相当于一个摆满黑白两色棋子的围棋盘,非常单调。我们需要让这两种区域都呈现一定的变化,从而丰富地图效果。这部分的工作对应上述步骤的第3步:针对“可行走/障碍物”点阵的每个点进行噪声扰动,并根据噪声值和上述2个地形类型过渡队列,获得地形类型点阵。这项工作也需要上述第2步:定义2个地形类型(terrain type)过渡的队列,分别对应可行走区域和障碍物区域。我们将每个点的噪声值分别映射到这2个地形过渡队列包含的地形类型,就能获得地图的地形类型点阵,换而言之,我们定义了地图点阵每一点处的地形类型。

现在我们已经获得了随机的地形分布情况,下一步则是把它可视化呈现出来。我们需要美术资源来提供一些基本的地图图块(tiles),以及每个图块对应的地形属性(4个角的地形类型),这对应上述的第4步:制作一个TMX格式的地图文件模板,其中包括了使用的tileset和terrain types的定义

有了地形类型点阵、地图图块及其地形属性,我们就可以通过简单的映射,产生对应的tiled map,如第5步所述:根据地形类型点阵,配合TMX地图文件模板的tileset中定义的tile和每个tile的4个角的terrain types,产生tiled map

最后我们仍然采用TMX格式输出地图,第6步:输出TMX格式的地图文件

下面我们将详细介绍每一个步骤。

产生“可行走/障碍物”点阵(w点阵)
有很多成熟的方法来产生这种点阵,实际上这是一个经典的随机地图生成问题。本文采用的方法属于Cellular Automata技术,参考了如下算法:
http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels
这里需要注意的是,由于点阵的每个点对应tiled map每个tile的某个角,所以如果tiled map的尺寸是m x n,那么点阵的尺寸应该是(m + 1) x  (n + 1)。

Perlin Noise
获得w点阵以后,我们需要通过噪声获得对应每个点的地形类型。这里我们使用Perlin噪声,请参考:https://en.wikipedia.org/wiki/Perlin_noise

地形类型点阵
当获得w点阵,以及对应每个点的噪声值后,我们就可以通过地形类型过渡队列(t队列)获得每个点的地形类型。
举例来说,假设对于特定的A点,w点阵中标明其为可行走点,其噪声值为-0.25。假设我们有两个t队列,一个是可行走队列,称为ta,为5、6、7、8、8,另一个为不可行走(障碍物)队列称为tb,为10,10,10,11,11,12。我们显然应该选择ta。由于ta含有5种地形类型,我们需要把[-1,+1]区间等分为5份,看-0.25落在哪个子区间里。[-0.25 - (-1)] / (2 / 5) = 1.875,所以落在第2个子区间里,故这一点的terrain type应该为6。

定义地形类型(Terrain Type)的过渡队列(t队列)
经过噪声扰动的地形点阵呈现一定的概率分布,即每个点对应一个介于-1到+1的浮点数,其出现机会符合一定概率分布。我们需要把噪声值映射到terrain type上去。举例来说,我们如果提供一个这样的地形类型过渡队列:1、2、3、4、4,那么我们相当于把一定概率分布的噪声值的取值范围[-1, +1]等分为5个区间,当某个点的噪声值落在某个区段里,我们就用对应的terrain type来标记这个点。如下图所示,假设某一点的浮点数噪声值落在最后一个区间[+0.6, +1],因为对应的terrain type是4,我们就认为该点的terrain type为4。由此可见,t队列的安排决定了各种地形类型的出现概率,对应地形类型在概率分布图上占据的面积越大,出现的概率越高,所以指定t队列的时候要考虑这一点。
还要注意的是可行走区域和障碍物区域采用各自的地形类型过渡队列,所以我们需要2个t队列。

最后,t队列不仅仅反映terrain type的出现概率,还要反映地形的某种变化趋势。例如,上述的1、2、3、4、4队列可能暗示1、2、3、4地形类型的海拔依次逐渐升高。

制作一个TMX格式的地图文件模板
一个人工制作好的TMX文件就能作为一个地图文件模板。但是为了适用于随机地形生成,我们需要做一些要求:
  • 我们需要定义好所有希望出现在随机地形中的terrain type。
  • 我们需要定义好tile set中的每个tile的terrain type属性,即指定每一个tile的4个角处的terrain type。
  • 我们需要有足够多的tile,来体现各种terrain type的过渡效果。

产生Tiled Map
对于m x n的tiled map,当我们获得(m + 1) x  (n + 1)的地形类型点阵后,对应的tiled map就能够比较容易地获得了。由于我们此时已经有了对应的TMX地图模板,其中的tileset定义了每一种tile 4个角上的地形类型,我们只要将地形类型点阵每4个点围成的区域映射成具有相同地形类型组合的tile,就能获得整幅tiled map。最后,我们仍然用TMX格式输出产生的tiled map。这里我们需要说明的是,我们之所以能够通过1个tile的4个角上的地形类型来确定对应的tile,是因为“Tiled”编辑器就是用这种方式来实现地形的。“Tiled”编辑器的源码请参考:https://github.com/bjorn/tiled/tree/master/src/tiled

随机地图展示


API使用方法
API的使用非常简单,请参考下面的代码例子:

using System;
using System.IO;
using System.Xml.Linq;
using MapGen4Tiled;

class MainClass
{
    public static void Main (string[] args)
    {
        XDocument template = XDocument.Load("map_01.tmx");

        RandomTMXGenerator gen = RandomTMXGeneratorFactory.Create(RandomTMXGeneratorType.Default,
            template,
            new int[]{1, 1, 1, 1, 1, 8, 9, 9},
            new int[]{6, 6, 6, 0, 0, 0, 2, 2, 2});
        
        XDocument output = gen.Generate();

        output.Save("output.tmx");
    }
}


(完)







0 1
原创粉丝点击