游戏中的过程生成——元胞自动机 Celluar Automata 生成洞穴地形
最近在学习过程生成技术,在这里写一些心得。
对于元胞自动机,我们这里只讨论输入是一副二维bool数组的情况,即大多数游戏中的情况。
一个元胞自动机,对于一个输入,给出一个同样格式的输出。输出中的每个点都是按照自动机中的规则从输入中演化而来的。大部分情况下,一个输出上的点,是根据输入中该点周围的点的状态来决定输出中的状态。
我们输入一个二维bool数组,并且规定它的演化规则为,某个点周围的true较多,就演化为true,否则演化为false。这种规则下,我们输入一个随机生成的噪点图,经过一定次数的演化,就可以获得相当自然的“洞穴”地图。
根据噪点图中噪点的数量,最终生成的洞穴被填充的面积也不同。
unity官方给出了一个用元胞自动机随机生成洞穴地形的教程 https://unity3d.com/cn/learn/tutorials/projects/procedural-cave-generation-tutorial
其中的元胞自动机生成的部分代码有一点错误,它并没有把输入的数组进行备份,直接对每个点进行遍历,因此每个点取到的之前一行的点都是新生成的点。
不过负负得正的是因此生成了看起来更像洞穴的结果。事实上如果按照它的规则,写一个周围有4个true,则下一次变为true,否则变为false的自动机的话,最终的图像会出现非常明显的锯齿抖动。如下图。

上图中的锯齿不管进行几次迭代都会一直存在
我做出的修正是当周围的格子为true时刚好有4个时,则自身保持不变。最终获得了看起来像是洞穴的效果。

类似这样的小调整可以做很多,比如边界上的点的处理等。通过不断调整可以获得各种不同效果。
贴一下代码
using UnityEngine;
using System.Collections;
namespace CS.MapGeneration {
public class CelluarAutomata {
private static int[,] offset = {
{ -1, -1 }, { -1, 0 }, { -1, 1 },
{0,-1 }, {0,1 },
{1,-1 }, {1,0 }, {1,1 }
};
private static int GetNeighbourCount(bool[,] map,int x,int y) {
int res = 0;
for (int i = 0; i < offset.GetLength(0); i++) {
int nx = x + offset[i, 0];
int ny = y + offset[i, 1];
if (nx<=0 || ny <=0 || nx>=map.GetLength(0) || ny >= map.GetLength(1) ||map[nx,ny])
res++;
}
return res;
}
public void Iterate(bool[,] map) {
bool[,] copy = map.Clone() as bool[,];
for(int i = 0; i < copy.GetLength(0); i++) {
for(int j = 0; j < copy.GetLength(1); j++) {
map[i, j] = Rule(copy, i, j);
}
}
}
protected static bool Rule(bool[,] map, int x,int y) {
if (!map[x, y] && GetNeighbourCount(map, x, y) > 4)
return true;
else if (map[x, y] && GetNeighbourCount(map, x, y) < 4)
return false;
return map[x, y];
}
}
}
游戏中的过程生成——元胞自动机 Celluar Automata 生成洞穴地形的更多相关文章
- 简单二维元胞自动机 MATLAB实现
20世纪50年代,乌尔姆和冯·诺依曼(对此人真是崇拜的五体投地)为了研究机器人自我复制的可能性,提出了一种叫做元胞自动机(Cellular Automaton,CA)的算法.该算法采用局相互作用规则, ...
- 用C++实现的元胞自动机
我是一个C++初学者,控制台实现了一个元胞自动机. 代码如下: //"生命游戏"V1.0 //李国良于2017年1月1日编写完成 #include <iostream> ...
- 美国康奈尔大学BioNB441元胞自动机MATLAB应用
美国康奈尔大学BioNB441在Matlab中的元胞自动机 介绍 元胞自动机(CA)是用于计算计划利用当地的规则和本地通信.普遍CA定义一个网格,网格上的每个点代表一个有限数量的状态中的细胞.过渡规则 ...
- 基于元胞自动机NaSch模型的多车道手动-自动混合驾驶仿真模型的Matlab实现
模型的建立基本来自于:http://www.doc88.com/p-2078634086043.html 花了一天半的时间用新学会的matlab实现了一下. ───────────────────── ...
- 《 .NET并发编程实战》扩展阅读 - 元胞自动机 - 1 - 为什么要学元胞自动机
先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.
- matlab学习笔记12单元数组和元胞数组 cell,celldisp,iscell,isa,deal,cellfun,num2cell,size
一起来学matlab-matlab学习笔记12 12_1 单元数组和元胞数组 cell array --cell,celldisp,iscell,isa,deal,cellfun,num2cell,s ...
- MATLAB元胞数组
MATLAB元胞数组 元胞数组: 元胞数组是MATLAB的一种特殊数据类型,可以将元胞数组看做一种无所不包的通用矩阵,或者叫做广义矩阵.组成元胞数组的元素可以是任何一种数据类型的常数或者常量,每一个元 ...
- matlab中元胞数组(cell)转换为矩阵
matlab中元胞数组(cell)转换为矩阵. cell转换为矩阵函数为:cell2mat(c),其中c为待转换的元胞数组: 转化之后的矩阵可能不满足我们对矩阵维数的要求,那么也许还需要下面两个函数: ...
- MATLAB中TXT数据文件读取并写入元胞数组的方法与步骤
一. TXT数据文件读取 Data = load('train.txt'); %简单的文件读取,这时在工作区可以看到导入的大数据变量Data 二.大数据变量Data装入元胞数组中 D = cell ...
随机推荐
- 『AngularJS』创建 Service
创建服务 Angular提供了几种有用的服务,对于所有的应用来说,你将会发现这些服务对于创建你自己的服务是有用处的.为了创建自己的服务,你应该从通过一个模块(module)注册一个服务工厂方法开始(可 ...
- 时屏蔽ios和android下点击元素时出现的阴影
-webkit-tap-highlight-color -webkit-tap-highlight-color:rgba(255,255,255,0)
- 了解url
我对自己知道关于url的编码和解码的一些进行了一下整理. 我们的例子是百度翻译的地址: http://fanyi.baidu.com/translate#en/zh/The%20%22%3F%20ar ...
- python 正则表达式 (重点) re模块
京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示.假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误.这个功能是怎么实现的呢?假如现在你用python写一段 ...
- Visual Studio 2013安装包
点击下载
- Daily Scrum02 12.04
第二轮迭代已经进行到了白热化阶段,大家在被编译搞的水深火热的同时依然没有忘记我们的具有颠覆性的团队项目.虽然第一轮迭代我们的成绩不错,但是一定要克服时间不充裕,任务互相冲突的困难,克服不可避免的舆论压 ...
- winform自动最大化(在不同分辨率情况下)
load函数末尾加: System.Drawing.Rectangle rec = Screen.GetWorkingArea(this); int SH = rec.Height; int SW = ...
- hbase1.2.6完全分布式安装
环境,参考之前的两篇博文: jdk1.7 hadoop2.6.0 完全分布式 一个master,slave1,slave2,slave3 zookeeper3.4.6 完全分布式 安装与配置:(以下步 ...
- C - 最长公共子序列
C - 最长公共子序列 Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others) Problem De ...
- vue2.0中父子组件之间的通信总结
父组件: 子组件: 接受父组件的信息: 向父组件发送事件: (其中slot是插槽,可以将父组件中的<p>123</p>插入进来,如果父组件没有插入的内容,则显示slot内部的内 ...