ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

《交互媒体专题设计》之瘟疫模拟 相关技术介绍

2020-04-27 10:39:07  阅读:279  来源: 互联网

标签:map 专题 int 细胞 height State 瘟疫 交互 currentState


《交互媒体专题设计》之瘟疫模拟 相关技术介绍

一、生命游戏——细胞自动机

简述

细胞自动机(英语: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有