《交互媒体专题设计》之瘟疫模拟 相关技术介绍
作者:互联网
《交互媒体专题设计》之瘟疫模拟 相关技术介绍
一、生命游戏——细胞自动机
简述
细胞自动机(英语:Cellular automaton),又称格状自动机、元胞自动机,是一种离散模型,在可算性理论、数学及理论生物学都有相关研究。它是由无限个有规律、坚硬的方格组成,每格均处于一种有限状态。整个格网可以是任何有限维的。同时也是离散的。每格于t时的态由 t-1时的一集有限格的态决定。 每一格的“邻居”都是已被固定的。(每次演进时,每格均遵从同一规矩一齐演进。
三个特征
1)平行计算(parallel computation):每一个细胞个体都同时同步的改变
2)局部的(local):细胞的状态变化只受周遭细胞的影响。
3)一致性的(homogeneous):所有细胞均受同样的规则所支配
三种可变因素
1)计算规则
模拟生命数量稀少:当前细胞:存活状态,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态
模拟正常生存:当前细胞:存活状态,当周围有2个或3个存活细胞时, 该细胞保持原样。
模拟生命数量过多:当前细胞:存活状态,当周围有3个以上的存活细胞时,该细胞变成死亡状态。
模拟繁殖:当前细胞:死亡状态,当周围有3个存活细胞时,该细胞变成存活状态。
2)C的数值类型
每个细胞有两种状态-存活或死亡,每个细胞与以自身为中心的周围八格细胞产生互动。(如图,红色为存活,白色为死亡)
3)阵列的呈现形式
通过方块的形式来显示细胞,效果如下:
代码实现
(1)、细胞的两种状态Died,Living
public enum State
{
Died,
Living
};
(2)、定义细胞类
public class Cell
{
public State currentState;
}
(3)、定义变量
public int width; //定义宽度
public int height; //定义长度
public string seed;
public bool useRandomSeed;
public float updateInterval = 1.0f; //细胞进化的速度
float refreshTime = -1f;
int generation = 1; //细胞进化的代数
[Range(0, 100)]
public int randomFillPercent; //初始细胞存活率
Cell[,] map; //定义数组存放细胞
Cell[,] mapTmp; //细胞进化的中间变量
(4)、细胞数组初始化
void Start()
{
map = new Cell[width, height];
mapTmp = new Cell[width, height];
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
{
map[i, j] = new Cell();
map[i, j].currentState = State.Died;
mapTmp[i, j] = new Cell();
mapTmp[i, j].currentState = State.Died;
}
initEarth();
}
初始化的时候,边界处的细胞都处于活着的状态,内部的细胞通过随机数的设定随机选取部分细胞赋予“活”的状态。
void initEarth()
{
if (useRandomSeed)
{
seed = Time.time.ToString();
}
System.Random pseudoRandom = new System.Random(seed.GetHashCode());
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
{
map[x, y].currentState = State.Living;
}
else
{
map[x, y].currentState = (pseudoRandom.Next(0, 100) < randomFillPercent) ? State.Living : State.Died;
}
}
}
}
(5)、更新
void Update()
{
//更新频率
if (Time.time - refreshTime > updateInterval)
{
print("第" + generation + "代");
UpdateEarth();
generation += 1;
refreshTime = Time.time;
}
}
根据计算规则F进行细胞的更新
void UpdateEarth()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
mapTmp[x, y].currentState = map[x, y].currentState;
int neighbourLiveCells = GetSurroundingLiveCells(x, y);
if (map[x, y].currentState == State.Died && neighbourLiveCells == 3)
{
mapTmp[x, y].currentState = State.Living;
}
if (map[x, y].currentState == State.Living)
{
if (neighbourLiveCells < 2)
{
mapTmp[x, y].currentState = State.Died;
}
else if (neighbourLiveCells > 3)
{
mapTmp[x, y].currentState = State.Died;
}
else
{
mapTmp[x, y].currentState = State.Living;
}
}
}
}
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
map[x, y].currentState = mapTmp[x, y].currentState;
}
}
获取细胞周围的存活细胞数
int GetSurroundingLiveCells(int gridX, int gridY)
{
int count = 0;
for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX++)
{
for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY++)
{
if (neighbourX >= 0 && neighbourX < width && neighbourY >= 0 && neighbourY < height)
{
if (neighbourX != gridX || neighbourY != gridY)
{
count += map[neighbourX, neighbourY].currentState == State.Living ? 1 : 0;
}
}
}
}
return count;
}
(6)、显示
通过cube把细胞的进化进行可视化。
void OnDrawGizmos()
{
if (map != null)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (map[x, y] != null)
{
Gizmos.color = (map[x, y].currentState == State.Living) ? Color.red : Color.white;
Vector3 pos = new Vector3(-width / 2 + x + 0.5f, 0, -height / 2 + y + 0.5f);
Gizmos.DrawCube(pos, new Vector3(1.0f, 1.0f, 1.0f));
}
}
}
}
}
二、自动寻路
要实现瘟疫的模拟仿真,就要用到自动寻路技术。
下面有关群集动画的内容参考自博客UnityAI行为-----群组行为之群集动画,具体的细节请见该博文。
集群动画
群落运动是自然界中非常有趣的现象。在天空中,我们可以看见大群的候鸟南飞,在陆地上,我们可以看见羚羊群,牛群在飞快的奔跑,在海洋里,鱼群的运动更是壮观。群落和其他相关的群体,他们运动的时候都是非常的壮观,他们的气势常常让我们惊叹不已。在群落中,每一个个体都是非常的独立,然而整个群落又犹如一个整体。群体中的个体似乎是随机的,但确有一定的运动规律。最令我们感到震惊的是群落中似乎有一种中央控制,这种控制可以使每一个个体之间保持一定的距离,具有大致相同的运动方向,整个群落运动是建立在每一个个体的运动之上的,个体通过对环境的感知,来调整自己的运动方向以及各种状态。
群集动画的基本规则
在设计群集动画的时候,由一些基本原则是我们需要制定的。只有满足这些要求,我们才能基本建构出我们的动画系统。在群集动画的模拟过程中,系统会模拟群集中个体最基本的能力。群集动画中的每一个个体,都可以根据群落中其他个体的运动来决定自己的运动路径。建立一个群落动画并不是太难,但是我们必须遵循三条规则:
规则一:群落中每一个个体都必须有他自己的个人空间,如果其他的个体进入了这个安全空间,个体就要远离,从而保持个人空间不被侵占。
规则二:群落中的个体都尽量保持与群落中的其他个体运动方向保持一致。也就是说,每一个个体的运动方向是大致相同的。
规则三:每一个小的群落,如果有机会的话,假设附近没有障碍物,都会尝试与附近的群落融为一体。这在群落遇到障碍物分开,越过障碍物后又合在一起的情况时是非常重要。
unity的NavmentAgent组件
用unity的NavmentAgent组件可以实现物体的自动寻路,来实现瘟疫的模拟仿真。
NavmentAgent寻路教程
标签:map,专题,int,细胞,height,State,瘟疫,交互,currentState 来源: https://blog.csdn.net/YCSDNG/article/details/105778277