首页 > 教程 > 第五期boss解析:沙粒溶解的秘密
2017
10-26

第五期boss解析:沙粒溶解的秘密

屏幕上出现任何你想要的文字或图像,在点击播放按钮之后,屏幕上的文字或图像开始变化,像是撒哈拉的山丘,随着一阵微风,沙粒慢慢飘落,这背后,到底隐藏着什么样的秘密呢?让我们一起来探讨,沙粒动画背后的故事。

在理解沙粒动画之前,需要提到一个元胞自动机(也称细胞自动机)的概念,简单描述一下,比如说目前有一条高速公路,很宽,路面上有很多车(是的,堵车了),我们随便选中一辆车(比如最中间的那辆车,它的四个方向都有车,我们也假设所有车停的很整齐,方向是东西南北,路的方向是东西走向),我们选中的这辆车称为A车,A车想要移动,我们的移动方向是自西向东(从左向右),那么A车需要判断正前方是否有车,或者两边是否有车(可以变道),我们可以说像A车这样能够根据周围其他车辆状态(有车或没车)来控制自身运动的个体为元胞(细胞)。是不是感觉说的很啰嗦,所以一句话总结:根据周围状态控制自身运动的个体称为元胞(细胞)。

元胞说完了,那什么是元胞自动机呢?哈哈,很简单,当很多个元胞在一个空间时,这个整体我们就可以称之为元胞自动机(这里只是按照个人理解通俗的说一下,毕竟元胞自动机理论不是三言两语能说清楚的)。

前置须知就是这些,那这和我们今天要探讨的沙粒动画有什么关系呢?在这里,沙粒==元胞。因此,我们看到的沙粒动画,每一个沙粒都会根据周围是否有沙粒来控制自身的下一步运动。其实说到这里,我们的秘密就已经公开了,窗口中的每一个字,都是由许许多多的沙粒组成的,这些沙粒受到一种向下的力(我才不会说是重力,实际上也不是重力,而是我们模拟的向下的力)的影响,然后开始下落,最后堆叠在一起。

看到这里,你是不是觉得沙粒动画已经毫无秘密可言?哈哈,如果这样想,那你可就错了。如果按照我们上面的说法,我们是不是需要写一个力的实现类,一个沙粒的实现类?可是,这些,在我们的代码里面都没有!(哼,写这篇文章的人肯定是个坏人!)

秘密嘛,自然是不能轻易就说出来的,那就让我们一起来探讨吧,解开这浓雾中的谜团!

打开processing IDE,你首先看到setup()之前的那一段代码:

boolean jump;
boolean p1, p2, p3, p4;
Block quadCube;
boolean[]status=new boolean[4];
PFont yahei;    //字体 == 雅黑

这一段代码,你会发现有四个布尔(boolean)变量,P1,P2,P3,P4,聪明的你可能已经猜到了他们代表什么,是的,他们代表当前我们探讨的沙粒以及沙粒周围的状态(是否有其他沙粒)。之后你又看到了一个布尔数组status,很巧,它也有四个布尔变量,它对应了P1,P2,P3,P4,那它是什么意思呢?它代表的是我们当前探讨的沙粒下一步该怎么运动。你可能会问了:你说了这么多,我怎么从这几句代码中看不出来这些?对呀,这几句代码当然看不出来这些(肯定是我偷偷看了后面的内容呀),所以我们接着往下看:

紧接着是setup()函数,简单的设置了一下窗口大小,背景颜色,帧率,字体,文本等信息;

再往下呢?

是谁,是draw()函数,你一看,哇,这段代码这么长,让人家怎么看嘛?(我刚开始看到也觉得头大,好多代码呀,嘻嘻,不过我有秘密武器——代码折叠)你看这段代码,全是if语句,而且也提到了P1,P2,P3,P4,是的,关于P1,P2,P3,P4,的结论是从这里得出来的,这里还藏着一个秘密哦,不知道细心的读者能不能发现?

get(i, j)==color(255)

 有很多语句里面有这段代码,那他是做什么的呢?我为什么把他单独拿出来说?这就和我们所说的小秘密有关了:

get(i,j)意思是获得(i,j)位置的像素颜色;

color(255)意思是白色。

上面这句话是在判断(i,j)位置的像素颜色是不是白色(哇,真相就要呼之欲出了,好期待!),再看一眼运行的动画,窗口里面是不是只有两种颜色,而且字体的颜色是不是白色的?

每一个白色的像素组成了文字,每一个沙粒组成了文字,沙粒 == 像素!

是的,这就是最大的秘密,屏幕里的每一个白色像素都被我们看做沙粒,

那它就是一个元胞,能够根据周围元胞的状态来控制自己运动;

那它就是一个像素,能够根据周围像素的状态来控制自己运动。

我们和开始所属的元胞自动机联系了起来,那我们就明白了,这个沙粒动画的本质是:

将每一个像素看作元胞,然后遍历整个屏幕空间(使用的是那两个for循环),当遍历到组成文字的白色像素时,我们将当前像素及其周围像素的状态传入判断类(不是白色的也会有这个过程,只是返回都是false,所以可以忽略),得到下一步的控制指示,之后按照这个指示来运动。

这就是沙粒动画的本质了,很巧妙的用像素作为单位个体来判断,根据周围状态控制像素的移动(其实是像素颜色的改变),模拟出了沙粒下落的动画效果。

其中,

 quadCube=new Block(p1, p2, p3, p4);  //保存该点及周围状态
 status=quadCube.output();      //根据该点及周围状态给出布尔状态

 这两句代码就是根据当前像素及其周围状态来判断下一步的运动指示。具体的判断过程在Block()的构造函数中。

那么到这里,我们的秘密就完全公开了,有兴趣的小伙伴们可以按照自己的想法来编写属于自己的沙粒动画哦。

 

PS:留在最后的补充才是真正的干货呢!

当你运行时,可能会发现,为什么文字上面的白色小点,下落速度和下面的小点下落速度不一致呢?秘密在这里:

for (int i=1; i<width-1; i+=2) 
      for (int j=1; j<height-1; j+=2) 

我们在遍历时使用的是i += 2,步长为2,也就是说有的像素点被调过去了,嘻嘻,所以就会出现上面那种现象了呢。

有的小伙伴们可能会觉得,这个看起来虽然不难但是好麻烦呐,你看源代码里有十个if判断了十种条件,我怎么能想得到嘛!所以呢,退而求其次,我们可以遍历每一个像素,每一次只判断它的下方有没有白色像素,如果没有的话,就可以向下移动一格咯(这个你可以自己设置啦,不过要记得不要超过下面的那个白色像素的位置哦,在元胞自动机理论中这个移动值是一格,即元胞大小),你也可以向其他方向运动啦,只需要判断那个地方有没有白色像素(什么颜色都好,只要你喜欢!)就好。

真正的PS:

元胞自动机理论并不像上面说的那么简单,用通俗的话讲出来也不是很准确,只想给各位读者一些参考,方便理解。

定有纰漏,还请谅解。



最后编辑:
作者:fishVD
知识就是金钱

第五期boss解析:沙粒溶解的秘密》有 2 条评论

  1. 卡萨布兰卡 说:

卡萨布兰卡的回复 取消回复

你的email不会被公开。