写在后面

这个月接手了两个较大的需要,其中一个是比赛类游戏,还有一个是抢红包的玩法。两种都波及人与人之间肯定的互动,游戏趣味性绝对较高,从数据上反馈用户也会绝对更加喜爱。

本文先介绍第一个需要的背景、设计与实现。对于抢红包的将放在下一篇文章进行探讨。

需要背景

之前有一阵子,有个很火的小游戏-阳光养猪场,那个养猪合成而后提现的,常常在短视频平台做广告。实质就是用户会每天来进行养猪,到肯定等级就能够提现。

产品感觉每个用户与猪场是独立互动的,用户与用户之间没有什么互动,想搞一场养猪大赛来进步用户与用户之间的互动,并通过PvP比赛机制刺激用户养猪,从而进步用户对产品的各项数据,比方UV、DAU啊等等……

最终成果大略是,用户进入猪场便开启一轮养猪大赛,随机匹配几名对手,在规定工夫内依照养猪次数进行排名,最终依照名次发放肯定的处分。

需要剖析

首先,一场养猪大赛的流程是用户上线,零碎主动为其随机匹配N名对手组成一队。比赛在无效工夫内,须要记录下每名玩家的养猪次数,便于用户实时统计查看对手的次数,确认本人的名次。所以,一场比赛次要包含比赛固有信息、队伍成员信息、选手养猪次数信息等外围信息。当然还会有一些其余辅助类信息,比方给用户展现所有对手的头像昵称、地区等级等信息给用户更真切的游戏体验。

那么进行一场这样的比赛,须要哪些数据呢?

比赛固有信息蕴含开始工夫和完结工夫,每个比赛都会有一只队伍,之间是一对一的关系,除非同一批人进行多轮比赛。每支队伍包含成员数量,每名成员的根本信息以及最外围的实时养猪次数信息。结算时还包含各个排名对应的处分信息。

可能以上都还好,读者应该和我刚拿到需要的时候一样,对如何匹配对手感到好奇。不禁想到咱们在玩LOL之类的游戏是如何匹配的,它会依照咱们本人的胜率、段位程度匹配旗鼓相当的对手,这样保障了游戏体验,维持均衡。所以养猪小游戏也是一样,用户的养猪能力也是分三六九等的,咱们须要依据用户以后的等级匹配对应等级的对手。至于如何确定用户以后的等级,这就须要你提前设置好一些规定对用户进行划分,在比赛上线之前,这个划分等级先先提前预埋。比方每天养猪100次的是A等,100~200次的是B等……这样划分好后,咱们还须要筹备一个反向索引,即A等有哪些用户(uid),B等有哪些,这样在匹配对手时,咱们就能够先判断本身是哪一等,再去按规定随机去其余等级的桶里捞uid,这样一队人就组成功了。

技术选型

晓得流程,定义好了数据结构,咱们就能够进行大抵的技术选型。

首先,思考到比赛自身是一个有时限的游戏,相当于有肯定的过期性,最适宜存储数据的首先想到用redis。而且这种实时PvP的比赛,查问与写入量都很大。

思考到当结算曾经到了结算工夫,用户能够支付了,然而redis过期了,数据岂不是没了?这一点倒不必放心,一是自身就能够设置处分支付时限,告知用户规定;二是咱们能够比赛结算时将后果进行落库等形式长久化。

对于上述讲的匹配对手局部,这次要波及的是一些离线数据,关乎到用户的历史行为,比方用户的养猪次数,他们的等级划分。目前业务遵循,用户的在游戏内的行为会进行记录,会落到MySQL、ES等存储上,甚至进一步异步抽数到大数据侧。BI同学能够通过大数据分析平台离线计算用户行为,依照业务的指标从新整合出一份数据。比方业务代码会将用户每次养猪行为记录到ES,之后同步到HIVE,BI便能够间接从HIVE表中对用户过来一整天的数据进行统计,最终依照规定划分出ABCD几个等级,也能建设反向索引。所以,这整个造成了一个闭环。(当然我对这个环认知肤浅,显著感觉到了大数据那块说的比拟抽象不业余)

具体实现

思考到实现老本,一期实现的成果是一个单向的比赛,即用户随机匹配n个对手,但本人并不是他们的对手。认真想想这样的差异?

如果是双向的,那么每场比赛是n个成员专用的信息,那么比赛和队伍、成员的关系是一对一和一对多的关系。而如果是单向的,齐全能够了解为比赛和成员也是一对一的关系,因为对手们不care是谁把“我”当成了对手,只有比赛的配角才care,只须要创立比赛的时候记录下匹配的对手名单即可。在技术实现上,单向的也更为简略,只须要将比赛信息、队伍中对手信息存在一个redis key中即可。如果是双向的,这须要比赛信息和队伍id保留在一个key,其实队伍id对应n的选手信息保留在一个key,所以成员都要保留一个本人以后对应的比赛信息key。

在对手匹配上,BI同学能够提前把每个等级用户们的uid进行存储到redis中,构造例如是:A-uidList,B-uidList……在匹配对手时,可能会所有人都拜访同一个redis key,所以也会造成热key问题。同时每个等级的uid汇合会十分宏大,而咱们每次匹配对手也仅仅随机取其中几个。这样势必须要咱们将uid汇合进行打散到多个桶中,既能解决热key也能解决大key问题。比方A等级10w个uid分到1000个桶中,每个桶仅寄存100个uid即可。

至于最外围的养猪次数怎么实时统计呢?既然是单向的比赛,我可能是周期是昨天明天的48h,对手的可能是明天今天的48h,所以必须将用户养猪次数按最小的工夫粒度存储。这里的最小指的是满足业务需要的最大粒度。比方每小时的用户养猪次数记录在同一个redis key下,key的构造能够为:prefix+uid+date+hour。这样在统计每个比赛的所有成员养猪次数信息时,能够依照比赛开始工夫截止以后工夫,批量查问所有合乎时间段的redis进行聚合。当然按小时粒度曾经足够小了,天级别的粒度也够咱们的需要了。

其余一些细枝末节的信息,比方处分,用户昵称头像等,这些存储到适合的中央都行,有现成接口调用不存储也可,怎么不便怎么来。

双向比赛

无妨想一想,如果要实现双向的怎么搞呢?

首先匹配对手的计划还是不变,次要变动的是比赛信息的存储,以及养猪次数的记录。

因为比赛和队伍、成员曾经不能看做是一对一的关系,那么就须要依照设计DB的那套办法对其关系进行梳理。每个比赛id关联一个队伍id,每个队伍id关联着n名uid,每个uid又关联一个比赛id,同一队伍的uid关联的当然也是同一比赛id。

从玩家角度讲,本人首先在redis存储本人以后的比赛id,而后redis对应会有一个以比赛id为key的值,外面寄存了所有成员uid(这里简化了队伍id)。

因为处于一队的成员们共享同一个比赛,所以每个人每次喂食都去批改本人的次数即可,齐全能够把养猪次数记在比赛id的key信息外面。链路即用户养猪后,先,查到以后本人的比赛id,而后再去查比赛信息,而后给本人的次数+1。别的成员会立即看到次数上涨了。

看似如同更简略了?

其实问题不在这里,而在于创立比赛时可能呈现并发行为,A选了B和C,B又选了D和E,这可能是同时的。所以这样游戏的整体交互流程须要进行变动,创立比赛不是由每个人本人创立,而应该由零碎对立进行创立调配,让零碎“串行”的去创立队伍,调配人员,解决并发。认真想想,咱们开始一局LOL较量时,匹配期待一段时间是为什么?

机器人

养猪比赛容许并列名次,如果大家都跟磋商好一样,都不养猪,都能拿第一,是不是很不错,一点也不卷。所以咱们要给它一个push,更好的调动用户们的养猪积极性。

产品说机器人可不能很呆,次数变化无穷,也得像真人一样,过一会儿养一次猪,23333。而且机器人也得有难度之分,就像LOL人机模式一般、个别、末日,其余网页游戏不同等级的BOSS一样。

怎么实现这种mock行为呢?

首先机器人这种模仿真人,齐全能够将“过来式”的真人行为表现在机器人身上,一样BI统计好养猪次数,依照小时划分好,业务代码计算机器人养猪次数时进行聚合即可。依照这种思路,置信难度之分齐全能够实现。