写在后面
这个月接手了两个较大的需要,其中一个是比赛类游戏,还有一个是抢红包的玩法。两种都波及人与人之间肯定的互动,游戏趣味性绝对较高,从数据上反馈用户也会绝对更加喜爱。
本文先介绍第一个需要的背景、设计与实现。对于抢红包的将放在下一篇文章进行探讨。
需要背景
之前有一阵子,有个很火的小游戏 - 阳光养猪场,那个养猪合成而后提现的,常常在短视频平台做广告。实质就是用户会每天来进行养猪,到肯定等级就能够提现。
产品感觉每个用户与猪场是独立互动的,用户与用户之间没有什么互动,想搞一场养猪大赛来进步用户与用户之间的互动,并通过 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 统计好养猪次数,依照小时划分好,业务代码计算机器人养猪次数时进行聚合即可。依照这种思路,置信难度之分齐全能够实现。