天天看点

《Android 应用案例开发大全(第3版)》——第2.7节线程相关类

本节书摘来自异步社区《android 应用案例开发大全(第3版)》一书中的第2章,第2.7节线程相关类,作者 吴亚峰 , 苏亚光 , 于复兴,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.7 线程相关类

上一节已为读者详细介绍了绘制相关类,在读者进一步了解本案例的基础上,在这一节将对线程相关类的开发进行详细的介绍。前面已经完成了对水族馆背景及水族馆中的鱼、鱼群、鱼食和气泡的绘制开发,只绘制出模型是不够的,还需要让它们动起来,从而产生更加真实的效果。

该壁纸开发中开启了多个线程,使得本案例中的场景更加活灵活现,更加逼真。线程相关类主要包括气泡移动线程类、群鱼游动线程类、鱼群游动线程类、鱼食移动线程类和吸引力线程类,下面将对线程相关类的开发进行详细的介绍。

2.7.1 气泡移动线程类——bubblethread

前面已经完成了对3d水族馆中气泡的开发,但只开发出一个模型是远远不够的,这就需要让气泡移动起来,并可以让多处位置连续不断地冒出气泡来,这样场景才会更加逼真。这就是本类的作用,本类开启了一个线程定时移动气泡,并在不同位置冒出。其具体代码如下。

第1~10行为声明相关成员变量,通过构造器,获取bubblecontrol的引用,为后面线程中调用bubblecontrol类中的bubblemove方法做准备。其中省略了部分类和包的引入代码,请读者自行查阅随书光盘中的源代码

第11~32行为该类中气泡移动线程方法,在该方法中遍历气泡列表bubblesingle。为了能够在场景中出现3处气泡,所以将气泡队列切分成3队,并根据每个队列中气泡的奇偶性来给出y的值,以作为气泡x、z轴移动的扰动变量,并调用气泡移动方法bubblemove,然后休眠10ms。

2.7.2 群鱼游动线程类——fishgothread

上小节介绍了气泡移动的线程bubblethread,本小节将为读者介绍群鱼游动的线程。在线程中有关于群鱼之间的受力算法,以防止两条鱼互穿;还有关于群鱼碰到鱼群的受力变化,以及群鱼和墙壁碰撞时群鱼的受力如何变化。其具体代码如下所示。

第3~24行首先遍历鱼群、群鱼列表,并计算单条鱼所受到的其他鱼的力和鱼群对该鱼的力。当鱼与其他单条鱼或群鱼之间的距离小于阙值后会产生力的作用,这样计算群鱼中的鱼一直游动,并不会与鱼群发生碰撞。

第25~47行是对碰壁检测处理的代码,这里计算了鱼与上、下、左、右、前、后墙壁的检测,然后判断鱼某个方向的位置是否超过了墙壁的范围,如果超过,则墙壁给一个相反方向的力,然后将鱼所受到的力与墙壁给鱼的力相加求出鱼所受到的合力。

第49~50行遍历所有鱼的速度与位移。遍历所有群鱼中的鱼,调用fishmove方法使之动态地修改鱼的速度与位移,并让线程睡眠后刷新群鱼,这样,群鱼在场景中就会一直的由来游去,非常酷炫。

2.7.3 鱼群游动线程类——fishschoolthread

上一小节为读者介绍了群鱼游动的线程类,本小节将着重介绍鱼群游动的线程类——fishschoolthread,其中计算了鱼群与群鱼之间的受力,使之不会碰撞,还计算了鱼群中鱼受到从该位置指向相对位置的力,以及鱼群与墙壁碰撞时的受力情况。

(1)首先给出了fishschoolthread类的整体框架。鱼群中单条鱼受到的向心力以及群鱼碰壁检测等其他算法代码过多,将在后面详细介绍。接下来详细介绍鱼群之间的受力算法,主要是群鱼对鱼群的作用力情况等。具体代码如下所示。

第4~9行是本类中一些变量的声明还有构造器的初始化。将线程是否开始的标志位设置为true,并获得鱼群控制类对象fishschoolcontrol,为下面的算法调用控制类对象中的方法,以及声明两条鱼之间的距离。

第14~35行当鱼群中的某条鱼与鱼群中的距离小于阙值后便对该鱼产生作用力。第一条鱼只受墙壁的力。鱼群中其他3条鱼互相没有力的作用,也没有第一条鱼的力。它们受到从该位置指向相对位置(以鱼群中第一条鱼的位置为中心,以定半径确定的球面上的一个点)的力,并受群鱼的力。

第36~45行为修改鱼群里面所有鱼的速度和位移。调用每条鱼的fishschoolmove方法定时修改鱼群里面鱼的速度和位移。进行异常处理,如果出现异常,则打印出异常。并让线程睡眠50ms后重新刷新鱼群。

(2)上面详细介绍了鱼群碰见群鱼之间的受力算法与鱼群中鱼的受力情况算法。下面将为读者详细介绍(1)中省略的鱼离开鱼群的受到恒力的算法,以及鱼群和墙壁碰撞时的鱼群受力变化的算法。这样鱼群一直是鱼群,不会被冲散。其具体代码如下所示。

第1~26行给离开鱼群的鱼赋予一个恒力。一旦这条鱼相对脱离了鱼群之后就会受到一个恒力使这条鱼游回鱼群,该条鱼游的距离鱼群越远这个恒力就会越大,从而使鱼群里面的鱼能够快速地回到鱼群,使鱼群一直是鱼群,不会被冲散。

第27~35行是鱼群里面第一条鱼与水族馆中的上墙壁、下墙壁、左墙壁、右墙壁、前墙壁及后墙壁的碰撞检测,碰撞时墙壁会对鱼群里面的第一条鱼产生力的作用,这样鱼群就会一直在鱼缸中游来游去。

2.7.4 鱼食移动线程类——foodthread

上一小节详细介绍了对鱼群的移动线程控制类,读者已经了解了鱼群的移动方法。本小节将为读者详细介绍鱼食的移动线程类foodthread,本小节中将着重为读者介绍鱼食的移动方法,以及对鱼食标志位的设置等,具体代码如下。

第4~11行是本类中一些标志位的初始化与本类中的构造。其中一些标志位的初始化有助于读者更加容易地理解本类中的逻辑关系,其构造器是拿到singlefood类的引用,为后面调用其中鱼食的坐标做准备。

第12~31行是本类中鱼食移动的线程方法,本案例中的鱼食从上到下匀速运动,并且每次计算失误y轴所在的位置之前,会通过增加或减少食物的x、z坐标来使食物产生轻微的晃动效果,从而增加食物的真实感,让线程休眠100ms后刷新鱼食。

2.7.5 吸引力线程类——attractthread

上一小节中介绍了食物的移动线程。本小节着重介绍鱼食对群鱼的吸引力线程类attractthread,本案例中群鱼是可以看到鱼食的,但是鱼群看不到鱼食,所以鱼群不会受到食物吸引力的影响。本节将详细介绍这是如何操作的。

(1)下面将为读者重点介绍本类中鱼食对群鱼的吸引力的算法,并定时对每条鱼的吸引力进行刷新。每当鱼食落下的时候,如果某条鱼看到了鱼食,这条鱼就会朝鱼食游去,将鱼食吃掉,这样使百纳水族馆壁纸更加地真实逼真。具体代码如下。

第4行为省略掉的部分变量与构造方法代码。此代码中部分变量主要是设置线程标志位、设置清空标志位(每次喂食之前会清空列表f1)、是否计算食物吸引力的标志位。并创建受到食物吸引力的鱼列表。

第5~24行首先判断是否需要喂食。开启喂食后寻找能看到鱼食的鱼,每喂食一次清空受到吸引力的鱼列表f1,然后在喂食的时候重新寻找满足条件的鱼,如果满足条件把该条鱼添加到受到吸引力的鱼列表f1中。

第25~45行是开始喂食后,计算f1里面鱼受到食物吸引力的算法。能看到鱼食的鱼受到一个由该条鱼当前位置指向食物的吸引力的作用。这样当开始喂食时,一条鱼看到鱼食会自动地向鱼食游去,并将鱼食吃掉。

(2)上面介绍了当开始喂食时,如何寻找能够看到鱼食的鱼的算法,并介绍了如何操作当鱼看到鱼食后的游动问题。下面将为读者介绍如果鱼食被吃掉或者鱼食位置超过地面后,如何对鱼食进行操作的方法stopallthread()。

第1~8行为stopallthread方法,若鱼食位置超过地面,或者鱼食被鱼吃掉后,就会调用此方法,把鱼食移动线程里面的计算标志位和计算群鱼是否受到的食物吸引力标志位变为false,同时点击喂食的标志位设置为true,从而能点击屏幕在此喂食。

继续阅读