大家好,我是Lampard猿奋~~ “节奏大师”相信大家都不陌生,当初这款音游可是风靡全国,风头一时无二。今天要和大家分享如何实现一个节奏大师Like的音游玩法
我们可以简单的把需求拆成四个部分:1.播放背景音乐,2.在某一些时刻掉落音符,3.监听玩家的操作,4.结束时机的判定以及优化
前文已经和大家分析实现了背景音乐的播放以及音符的控制掉落,本文会着重分析后两点,不贴代码只讲思路,希望能帮助到大家~
前文中我们解决了音符操作序列的获取,并且在游戏开始的时候,启用了一个计时器,每帧去判定是否需要掉落音符,若需要,则在该音轨处生成一个音符控件并启用计时器控制下落
若玩家在控制区进行了操作,那么我们则根据玩家的实际操作结果来做出反馈,比如若成功,那么就给他算分并给出特效;若失败,则把控件置灰;若无操作,则待控件移出显示区之后清理掉
在操作区中有五个按钮控件,如果说只有单纯的单击控件,那么把监听交给按钮是可以的。但由于长按控件和滑动控件的存在,单靠按钮的监听已经无法满足需求了
因此我们需要在操作区加一个监听的层,用于监听玩家点单点点击,多点点击,滑动,长按等功能。不同的引擎都有相应的接口,这里就不展开说了
当我们监听到玩家的操作之后,就可以根据触摸点的位置判断是在哪一个音轨,然后进行下面的判定操作了
我们可以靠触摸层监听玩家的操作,根据触摸点判断现在点击的是哪一个音符。但如何判断是否击中该音轨的音符控件呢?
在我们生成控件的时候,会用一个队列根据音轨的编号存储生成的控件,队首是离操作区最近的音符,队尾是最新生成的音符,当音符被击中或者移出显示区时就会被回收并从队列中移除
local Widgets = {
[1] = {音符1,音符2,音符3...}, -- 音轨1的音符控件
[2] = 同上, -- 音轨2的音符控件
...
[5] = 同上, -- 音轨5的音符控件
}
因此判定的时候,就可以取队首的音符Y轴位置与操作区的位置进行判定,从而获知是否击中该音轨的音符控件
我们可以通过控件的Y轴位置和操作区的距离,获知是否击中该控件,你以为快要结束啦?
这只是刚刚开始......若判定击中了控件则需要分情况讨论接下来的操作:
若击中的是单击控件,则可以直接进入下一步的算分操作,并且把控件回收;
若击中的滑动控件,则需要继续监听玩家的下一步滑动操作,若滑动的方向不对(比如谱子设定从轨道3滑动至轨道4,往右滑,玩家却往左滑)或者滑动的位置并未到达谱子设定的位置(比如谱子是想从轨道1滑动至轨道3,玩家只从轨道1滑动至轨道2) ,则算miss需要把控件置灰,并且做好标记,让这个控件不能再被算分。若成功滑动则走算分回收逻辑;
若击中的是长按控件,则需要监听玩家松手的时间,当玩家松手的那一刻长按控件的尾部Y轴还未到达操作区域,则算miss需要把控件置灰,当然若长按的过程中作出滑动的操作(具体判定在于触摸的音轨发生了变化)也是一样要判定Miss。若成功则走算分回收逻辑;
当我们正确击中控件时,就可以根据策划设定的需求,换算出分数。比如我们这个玩法就会根据受击控件的不同,弹奏时选择佩戴的乐器不同,会有不一样的基础分以及buff,具体操作就用基础分 * buff叠加的分数就好了
然而有一点我们需要考虑,那就是如何与服务端同步该分数。为了防止外挂团队恶意刷分,我们不能直接直接上行分数,不然很容易就会被抓包。这边可以参考的一个做法是,客户端不去上传分数,而是上传玩家的操作信息,然后再用一些商定好的规则对信息进行加密,这样双重保障安全性就会大大提高
我们可以选择一定间隔时间上传一次数据,也可以等到所有的操作结束后再上传数据,这个就因人而异了~当商定好这一切之后,“监听玩家操作”这一模块就可以告一段落
上文我们能生成一个个不同的控件,并且能够成功地监听玩家的操作,剩下就交给计时器根据操作序列一个个生成控件即可
那游戏什么时候结束呢?这里需要满足两个条件:(Ⅰ)首先就是操作序列被制作完了,当最后一个音符被生成之后,我们就不需要再考虑生成新的音符了。但此时最后的一个控件还在生成区,还未落到操作区,(Ⅱ)因此第二个条件就是,所有的音符控件都已经被回收了(之前我们每一个音轨使用一个队列保存控件,判断所有的队列是否都空了就可以了),当满足两个条件的时候我们就可以弹出结算界面了
这个节奏大师like的音游玩法,会生成很多控件,使用很多特效,以及启用了很多计时器。玩家在玩音游期间也可能会出现强制退出,突然来电话,突然被拉进战斗等操作。为了避免内存泄露,在游戏时最好把它们都保存起来,然后在界面释放时进行手动回收
再者就是利用各个项目的内存泄露检测工具,做一下测试,然后记录对比游戏前和游戏后数据。规避内存泄露的风险,毕竟只是一个玩法,影响到整个游戏进程那就不好了
当把功能完成后,我哼哧哼哧地提测,结果被反馈太卡了体验不好。首先我排除了因为内存泄露而导致的卡顿;然后审视代码,把一些可以异步加载的资源进行了异步加载。然而卡顿问题并未得到很好的优化。最后发现问题是出现在克隆生成音符控件这一步,由于之前的做法是判定需要生成控件才克隆一个音符至生成区,这个过程就会比较耗
为了优化这个问题,我采取了使用控件缓冲池的操作,在游戏准备阶段先逐帧生成一些控件,然后当需要控件下落的时候,再从缓冲池中取该类型的音符控件并放置在生成区。当控件被回收时,我们也不直接release掉,而是清空其身上的状态,然后将之移除屏幕外,待再次需要时重复上述操作,卡顿问题大大得到缓解
那么,提前生成多少控件比较合适呢?如果提前生成的控件不足(比如我提前生成了10个单击控件,但在某一时刻,屏幕上就要同时出现15个单击控件)怎么办呢?
经过多次测试,我这边采取的做法是,由于单击音符出现的频率较多,因此提前准备更多的单击控件,长按控件和滑动控件可以更少的生成。再者,若真的出现控件不足的情况,从缓冲池取不出控件了,则再去进行克隆生成并保存至缓冲池中即可
经过一波性能优化之后,体验下来已经是非常丝滑了,那么下面看看效果吧~
至此音游玩法的分享到此结束~~
感谢阅读,点赞,关注!!!