nodejs游戏源码解析:《球球大作战》的移动算法

2017年6月4日 阅读:790

服务端处理了游戏的各种游戏逻辑,怎样让小球移动是重点之一。若想做服务端运算的游戏,这一部分代码是很值得参考的。

一、SetInterval

nodejs中的setInterval是定时器,如下的代码表示每隔1秒执行一次myfunc方法。

二、3个定时器

源码中设置了3个定时器,分别是moveloop、gameloop和sendUpdates。其中moveloop每秒执行60次,它主要处理小球的移动计算。

1、moveloop

Moveloop方法的代码如下,它对每个玩家执行tickPlayer,处理每个小球的移动。

2、moveMass

moveMass就是移动质量,小球可以喷射身体的一部分出去,喷出去的部分变成了食物。每个喷射出去的“质量”都会被保存在massFood列表里。moveMass会处理这些“质量”的运动轨迹,先是喷射出去、然后减速、停止。

moveMass的代码比较简单,先看看这一部分。Mass的运动分是个减速过程,喷射时Mass带有较高的初速度,然后每一帧减速0.5,直到停止。代码后半部分还对Mass撞上边缘的情况做处理。

3、tickPlayer

tickPlayer是处理玩家移动的核心部分,它处理了小球的移动、分身、吞食,代码也比较长,整体代码结构如下所示,首先做心跳判断,如果客户端太久没有发送心跳协议,那么向客户端发送kick协议,断开连接。其后调用movePlayer,处理玩家移动。

三、分身的过程

movePlayer计算了小球各个分身的移动过程,在游戏中,玩家可以让小球分身,具体过程如下。

1、玩家点击按钮后,大球分身,分出来的小球沿着移动方向弹射

2、弹射过后,分身们逐步靠近,最终连在一起

3、经过一段时间,分身合并,又成为一个大球

分身的过程分为弹射、靠近、紧靠、合并四个阶段。

四、怎样表示小球

既然小球有可能分身,那么它便不能单一的由x,y坐标和质量(半径)表示。该项目采用这样的表示方法(伪代码)。如果小球没有分身,那么cells数组长度为1,表示只有1个“细胞”,如果分裂成多个,则cells数组长度增加。player的x和y表示所有cell的中心坐标,由程序计算得出,target是目的地的坐标,即玩家鼠标指向的位置。每个cell都有质量,而cell的半径由质量换算而来,计算公式为radius = 4 + Math.sqrt(mass) * 6。

五、计算每个cell的目的地

由于每个cell都是独立运动的,每一个cell都有自己的移动目的地,计算每个cell目的地的代码如下。

具体来说,每个cell的目的地就是总目的地的坐标加上它自己相对中心点的偏移,如下图所示。

六、计算移动速度

分身过程中,每个阶段都有不同的速度,一开始弹射的时候速度很快,然后匀加速减少,减到一定程度后速度沿着对数函数曲线减小。

如果接近目的地,cell距离目的地只有50 + player.cells[i].radius的距离。那么调整速度,越接近移动速度越慢。

在计算完y方向的移动速度deltaY和x方向的移动速度deltaX后,给cell的位置赋值,完成移动操作。

七、合并处理

若分身经过一定时间(其实是以距离来判断),便需要合并,在下面的代码中,它会遍历其他所有的cell,这里分为两种情况。(1)if(distance < radiusTotal)(2)distance < radiusTotal / 1.75

如果distance < radiusTotal,也就是两个小球相互包含了,这里又分为两种情况(1)如果是还没到合并时间,那么让他们远离一点点。(2)如果到了合并时间,那就合并吧。

八、边界处理

moveplayer后面的代码便是做边界处理,保证cell在边界之内,代码如下所示。

九、重新计算中心点

player.x和player.y是所有cell的中心点,重新计算。

经过上述步骤,实现了moveplayer的功能。由于判断是否被其他cell包含的时候,采用了两次for,效率上是否还有优化的空间呢?下一节再看看吞食食物、玩家相互吞食的处理方式。

欢迎关注笔者出版的书籍《Unity3D网络游戏实战》,本书充分地讲解怎样开发一款网络游戏,特别对网络框架设计、网络协议、数据处理等方面都有详细的描述,相信会是一本好书的。

作者:碧俐千仞
转载请注明出处:http://weidublog.com/index.php/2017/06/04/876/

没有评论

评论已关闭。