背景:
这个年都没过,就开发了这一款游戏,大家都在吃吃喝喝的时候,我一个人在写代码。印证了一句话:孤独寂寞冷。
一边忍受着寂寞,一边强迫自己要坚持不能松懈,好在终于赶在上班之前弄完了。
实现思路:
首先要说一下曲线的路径,我这里所用的方法是通过一段段连接的贝塞尔曲线拼接而成,紧接着就要获取曲线上的点了,直接套用二阶贝塞尔曲线公式求得,这里贴一下曲线的原理和公式(具体细节请各位自行谷歌),如下:
二阶曲线由两个数据点(P0 和 P2),一个控制点(P1)来描述曲线状态,从而计算动点B:
这里为了实现匀速运动,需要一个求t的公式算法来达到匀速的目的,这里需要使用牛顿切线法求出近似解,同时通过牛顿切线法得到某一个点的导数,比如我的球在沿着曲线运动时,可以正常的旋转一定的角度。
关于t的推导公式,我这里借鉴了一位大神的帖子,迭代算法公式为:
L(t)函数的推导公式如下:
这样,当贝塞尔曲线的长度间距无限小时,得出的t值,也是相对于比较精确的。
来源链接:https://blog.csdn.net/linuxheik/article/details/79454663
(大神已经贴了完整的代码,可以直接参考)
有了这个,就好办了,拿到点以后,看似复杂的曲线,现在就可以看成是一条“直线”了,在直线上实现一个物体的加速度、减速度、匀速等运动,应该算很easy了。
注意:连接之后,每个连接点处,会重复一个额外的点,在代码上,需要考虑删去一个多余的重复点,简单点说,就是:去重。否则球运动到此时会多顿一下。
路径的生成,
我还特地做了一个贝塞尔曲线工具编辑器,如图:
请点击,传送门:
https://forum.cocos.com/t/topic/73416
球的运动,我这里的实现思路是将球通过一个球组对象来管理球,所有球的运动,比如加速度减速度和匀速运动都是通过球组对象来实现,然后每个球根据相互之间的“直线距离(就是一个球的直径距离)”计算依次的位置。
具体方式上,通过每帧的update方法,给球组始终保持一个不变的速度做匀速运动,也就是正常运动的速度,当需要做加速运动时,比如球刚开始冲出来时,给一个正的加速度,当需要做减速运动时,比如球收到撞击时,给一个负的加速度;如何让球慢慢回归匀速运动呢?这里我通过摩擦力系数,比如我这里使用0.9,加速度a*乘以这个系数0.9,慢慢最终使得加速度慢慢趋于0,然后回归到匀速运动状态。
发射球入轨的细节,我个人认为这里是整个游戏最复杂的地方。由于要实现球渐进式入轨,而不是瞬间“啪”的进入轨道,那么就必须要计算球的圆周路径,这样发射进来的球才能绕着接触的那个球的圆周,慢慢的绕进入轨道。
首先需要分阶段,我这里固定异步10次,也就是分10步让球慢慢的一步步进入轨道,到完成进入整个过程。每一步的逻辑是一致的。这里有大量的向量运算,我尽可能的说清楚。
a)从发射球接触到轨道球开始,计算第1步,标记为向量1:轨道球指向发射球,长度为1个球直径;
b)接着计算接触到的轨道球与下一个轨道球之间的向量,标记为向量2:从接触到的轨道球指向下一个轨道球,长度为1个球的直径;
c)向量1到向量2之间的向量,标记为向量3:从向量1指向向量2;
d)向量3长度除以10,标记为向量4,长度计算很简单,先将向量3单位化,再乘以数值1/10即可。
e)将发射球运动到向量4的位置,通过当前位置向量,做向量加向量4;
f) 依次类推,直到最终位置;
球组的合并与分拆,合并(2个球组连接之后需要合并)之后需要销毁前一个球组;分拆(1个球组在被打断了以后,需要将当前的球组1分为2)之后,产生一个新的球组插入到当前球组的前面。
以上就是整个游戏的完整思路,还有不明白的地方,请下方留言,我有时间一一为大家解答。