疯狂吃豆人
下面是这篇博客的内容,其实挺简单的,有兴趣的继续看往下看吧。
预览什么鬼
最近没什么事干,想做点什么,又没有好的想法,其实是做不出来啦。在开始这个吃豆人之前,我想扯扯淡,来点前戏,这段 纯属吐槽 ,所以 想要直奔主题的同学可以跳过这一段 。
说来也是尴尬,学 iOS 整整一年了,基础知识学了不少,就是不知道怎么提高了。之前打算暑假出去找个实习,感受一下真实的开发流程。可是计划赶不上变化,我在学校的一个创业团队做iOS开发,我们在暑假要做一个项目,所以实习的事儿就泡汤了。可能有人会说在学校的创业团队也可以感受到真实的开发流程呀,可是坑爹的是学校搞 iOS 的我就没见过其他人,整个团队就我一个做 iOS 客户端的,Android 项目组七八个人。我之前在学校的贴吧发帖子问有没有学 iOS 的,大家一起学习。妈蛋,没一个回复的。
之前学校要做教务系统客户端,在大二大三当中招人,算是实习,还给报酬,但是都直接不要 iOS 的。我当时自己找过去跟他说我想来做 iOS 端的,不要报酬,他还一脸不愿意的答应了,说就算我做出来了,以后也不好找人维护。我算是加进去了,整个项目还不算很难,但是做了一半我才想起来我没有开发者帐号,没有信用卡注册不了,不用想学校也没有,然后跟他一说,他就开心地把我踢出群了,做了一半的项目也就不了了之了。
还有一次就比较近了,这个项目是我们接的一个外包项目。我们的头给他们谈的,当时双方都没有谈价钱,觉得我们是学生,先做个大概看看效果,我们的头也觉得没问题,把东西做好了,价钱自然好谈。然后就他妈坑爹了,他们要求在他们那里办公,这样好交流。我们只管做客户端,他们自己做后台。然后每天流转与他们办公室和教室之间,他们的产品经理一直给我们讲架构,虽然很烦,不过挺有收获的,呵呵。然后持续了半个月,这个时候我们的头觉得可以和他们谈价钱了。对方觉得我们是学生,便宜。我们的头觉得我们是商业团队,专业。于是,崩了。我当时的心情是逼了狗的!
现在我们要做自己的产品,希望这次不要再夭折了。我只想安静地敲几行代码而已。好吧,暑假太无聊,没人说话,我只能把它们写出来了。不过看到这里的也是够无聊的了。下面开始进入主题。
吃豆人
好吧,这个吃豆人确实太单一了,没啥值得说的,我都不好意思继续写了。大家就当我无聊随便写的,不要当真哦。代码在这里,大家顺便给点Star吧😭
分析
这个吃豆人就两个重点,一个是主体的张嘴闭嘴,一个是豆子的移动。
张嘴闭嘴部分
-
一看就会发现主体是一个扇形,这里可以用
UIBeizerPath
+CAShapeLayer
的方法。 -
因为这个扇形在变化,所以在
View
的drawRect
方法中设置 Path,并使用CADisplayLink
触发此方法。 -
UIBeizerPath
有一个画扇形的方法:func addArcWithCenter(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool)
这个方法传入4个参数:圆心、半径、开始角度、结束角度、是否顺时针。再看下面的分析图,吃豆人的主体是上下对称的扇形,嘴巴最大为 90° ,所以开始角度和结束角度都是介于 0° ~ 45° ,而且角度变化是 从 0° 到 45°, 然后再从 45° 到 0° 。所以重点是需要一个可以来回变化的参数!仔细想想!
angle.png-
想到了吗?这个参数可以用 三角函数 实现。我们需要一个全局变量作为自变量 x ,每次
drawRect
的时候累加。startAngle = abs(cos(x)) * M_PI_4 endAngle = -abs(cos(x)) * M_PI_4
-
为什么使用
绝对值abs()
?因为
cos
函数的值是介于 -1 到 1 的,我们需要的是 0 到 1,所以取绝对值就可以解决。 -
为什么使用
cos()
而不是sin()
?因为使用
sin
时,一开始当x = 0
的时候,sin(0) = 0
。这个扇形从 0° 到 0°,UIBeizerPath
的那个画扇形的函数就会什么都不做,所以得不到扇形。 -
经过实验,这个 x 每次累加 0.1 比较合适,大家可以自己试试。
-
豆子的移动部分
豆子的移动部分虽然很简单,但也有几点需要注意:
-
初始需要都多少个豆子?
最好的算法是,用
吃豆人主体右边缘
到父视图的右边缘
的距离 除以吃豆人主体的半径
。所以每个豆子的间距就是吃豆人的半径
。 -
豆子什么时候删除?豆子的移动速度是多少?
看下图,豆子在第二张图中被删除,这是吃豆人第一次闭嘴。当吃豆人嘴巴完全张开时,第二个豆子到达初始化的位置,完成了一次循环。
豆子移动过程再看下一张图,看一下解题思路:
-
因为:吃豆人在完成
张嘴 -> 闭嘴 -> 张嘴
一个循环时,需要x 从 0 到 π
。 -
所以:也就是说豆子移动一个间距时,x 从 0 到 π 。
-
因为:执行
drawRect
时,x 累加 0.1 。 -
所以:所以
x 从 0 到 π
需要执行drawRect
(π / 0.1)
次。 -
所以:豆子移动一个间距时,需要执行
drawRect
(π / 0.1)
次。 -
所以:每次执行
drawRect
,豆子需要移动的距离是(一个间距 / (π / 0.1))
-
-
什么时候添加新的豆子?
当最后一个豆子出现在父视图内时,需要添加一个新的豆子,位置是
最后一个豆子右边
一个间距。
总结
到此,这个吃豆人所有的重点都讲完了,代码很简单,主要是思路问题。思路有了,代码就是小事儿,所以讲解的时候没有贴代码。我感觉说的有点麻烦,可能还有病句,希望我没有让大家变得更糊涂。代码在这里,大家顺便给点Star吧😭