45岁码农用不到2年时间撸出100款扑克游戏
前言
扑克的玩法非常多,常见的就有斗地主、跑得快、五十K、锄大地、梭哈、十点半、二十一点、打千分、升级、拖拉机、双扣、保皇、斗牛、挖坑等等。在国内的不同地方,同类游戏的玩法也有不同讲究。粗略估计,国内的扑克玩法,超过上百种。
要短期内开发出这么多款扑克游戏,需要先对大多数扑克游戏进行系统的分析,归纳总结,然后打造一条流水线,每一款游戏都使用相同的框架,使用通用的零组件,等等。
本文主要内容就是讲述这个设计过程。
1.算法库
扑克游戏的历史很悠久,能够广为流行的一个原因就是上手比较容易。就算在今天,如果说一个人没读过书就学不会打扑克,这没人会相信。所以我估计扑克游戏的算法,都是比较简单的。归纳一下,一般包括:
- 牌的大小(包括数字、花色等);牌的数目和分数;判断几张牌相同或连续;
- 还需要一些对一组牌进行操作的算法,比如取出、合并等等。
基于以上的分析,我们估计可以完成一套通用的扑克的算法库,能满足所有扑克游戏。最后实践证明,扑克算法库比预期稍微复杂一点,但仍在可接受范围内。
此外,我们很容易发现,很多流行的手游的玩法、功能层出不穷,开发团队频繁升级迭代。相反,扑克游戏的玩法相对固定,演化相对较慢。所以,在系统设计上,我们假定扑克游戏的数量有限,玩法有限,发展慢。这样的好处是流水线设计好之后,以后改动很小,维护工作量也比较小。
2交互UI库
扑克游戏可以归纳出3个核心要素:牌、规则、人(玩家)。对扑克游戏的一种高度抽象的描述是:按照一定的流程和规则,每个人通过选择选项、选择牌、选择数值,来争取获胜的一种游戏。
归纳了一下,玩家的行为包括以下3种:
- 对游戏流程中的选项,做出选择
- 按照游戏规则,对牌进行选择。
- 对数值(分数)进行选择。
比如斗地主中的叫地主、不抢,都是玩家自己要做的一种选择。出牌的时候选择不出,也是一种选择。后续会将“选项”称之为“命令”。
比如选择要出的牌,分组摆牌等。
比如下注。
以上三种玩家的行为,决定了游戏客户端需要提供哪些业务级UI库,对应下面几种:
- 一组按钮
- 选牌或牌分组的UI
- 选择数值的UI
由玩家选择其中一个按钮;在业务层,称为命令选择器。
允许玩家在一组牌中选出符合要求的牌。牌分组UI则允许玩家将牌放入不同分组或按不同顺序排布。这2种在业务层都称为牌选择器。
可以用滑动条,也有用按钮的。在业务层称为值选择器。
以上我们抽象出了扑克游戏的3个核心要素,以及玩家使用的3类UI。现在我们思考一下扑克游戏还需要哪些UI。
除了牌、规则、人,实际上我们还需要房间(桌子)、椅子(座位)。
一款扑克游戏有很多界面、子界面;我们大体将其分为:房间内,房间外。房间内就是一个桌面,UI都显示到桌面上。房间外包括一些扑克游戏的常用界面和功能:注册、登录、用户信息;房间列表;查询(分数记录、排名等);其他比如:公告、帮助、设置。这些都可以做成通用的几套,不同游戏选择其中的一套即可。房间内除了3类选择器,还需要下面一些界面UI:座位、牌(比如公共牌、出牌)、定时器、图片(比如筹码)、文本(用于显示数值或文字)。这里除了一些业务级别的UI对象,也包含一些基础的UI对象。
3管理员与通讯库
现实中,几个朋友坐一桌打扑克的时候,每个人都按照流程和规则来,大家共同监督。而对于线上的扑克游戏,其实有一个规则执行者,不妨称之为管理员(我们前面将选项称之为“命令”,可以理解为:管理员下达出牌的命令,由玩家选择出牌还是不出。所以,“选项”是站在玩家角度,“命令”是站在管理员角度)。那么前文的说法,可以进一步升级为:扑克游戏就是由管理员控制一套流程规则,特定的时候交由玩家来选择选项、选择牌、选择值,这样一种竞赛游戏。这里我们引入了管理员的概念。
下面说通讯库:
几个朋友坐一桌打扑克的时候,比如发牌,每个人收到的牌,其他人不能看到;再比如一个人出牌,是要给其他人看到。现实中打牌,我们是靠视觉来看,相当于靠光线传播数据(图像),而对于网络游戏,则需要的是一个通讯库通过网络传输数据。我们不能仅仅提供一个简单的基于socket、websocket、http封装(比如常见的封装接口有 read_cmd,read_version,read_int,read_string....),这太底层了,我们需要的是一个业务级别的通讯库。
比如你跟你老婆说:晚上加班要11点回去,你老婆说“好的”。通讯库应该是这样的:
创建一问一答的异步请求,发给老婆;
请求分类是告假(晚上晚回);参数是11点;
答复选项是3种:好的;不行;超时;(如果你老婆不是话痨的话)
再比如人事部给每个员工发短信,内容是本月工资明细。通讯库就是群发短信,格式相同,但内容不同。
通过分析一些扑克游戏,我们从这样几个层面进行设计抽象:通讯方向、是否应答、发送目标、单发还是群发。其中:不需要答复的,我们叫通知;需要答复的,我们叫“命令”或“请求”。从客户端发向管理员,称之为“客户端请求”;从管理员向客户端发送,称之为“服务端命令”;最终,我们把通讯归纳成5种模板:客户端请求;服务端命令;服务端广播;服务端私有通知;服务端公开通知;
有了通讯库,我们需要往里面塞数据,数据包括:通讯类型名称、命令选项、数值、牌。实际上数据内容也正是对应了选择选项、选择牌、选择数值。
举个例子:比如轮到一个玩家出牌了,我们使用服务端命令定义了一个出牌命令,这是一问一答的通讯,管理员发送时,不携带数据。客户端答复时,选项包括:出、不出;如果出牌,则需要携带出的牌。
再举一个例子:游戏结束时需要通知输赢,这时可以使用服务端公开通知,就是服务端给每一个玩家发送通知,通知内容是这一局输了还是赢了,赢了多少金币。那么,这个通讯中,携带的就是赢的金币(如果为负值,则表明是输)
总结一下:套用这5种模板,通过定义名称、携带的数据,来定义游戏中特定的通讯过程。比如拖拉机游戏中有以下几种通讯的定义:发牌公开通知、亮主请求、亮主结果广播、扣底牌命令、扣底牌通知、出牌命令、出牌结果广播、结算通知。此外所有游戏都会用到一些公共的通讯定义:坐下请求、站起请求、一局开始广播、一局结束广播、聊天等。
在通讯中,还涉及到数据对不同客户端的可见性的问题,这里就不再深入介绍了。
4流程
通过分析数十款不同特点的扑克游戏,整理了下面一种思路:
所有扑克游戏,在概念上,可以这样划分:
- 一局
- 阶段
- 一轮
比如斗地主,从发牌,到出牌,到结束,这是一局。一局结束后,开始下一局。
一局游戏可以划分成几个阶段,比如发牌阶段,出牌阶段,结算阶段;
大多数扑克游戏都是每个人轮着来的。还有一些游戏(或者游戏中的某个环节)是允许抢先的(比如拖拉机的亮主)。在技术上,一轮就是一个异步循环,提供很多参数和控制。
以上是为了方便而从概念上划分的,并不绝对,使用这样一种套路,开发不同扑克游戏时,可以更加统一了。
5组装
到目前为止,我们已经完成了下面的成品模块、框架、零组件。
- 一套扑克算法库
- 房间内的UI库
- 房间外的几套成品模块
- 5种通讯类模板
- 流程库
命令选择器;牌选择器;值选择器;头像、牌、图片、文本;
注册、登录、用户信息;房间列表;查询(分数记录、排名等);其他比如:公告、帮助、设置。
客户端请求;服务端命令;服务端广播;服务端私有通知;服务端公开通知;
提供一局、阶段、一轮等控制;
对于不同扑克游戏,我们首先要把游戏玩法弄清楚,然后用这些成品模块、框架、零组件,通过配置,通过编写一些代码来进行粘合,从而实现一个完整的游戏。
在实际的开发过程中我们验证了:对于简单的游戏,三五天就可以完成,对于极其复杂的游戏,一般在1~2周(比如拖拉机这类游戏)。这里说的是一个人,同时也包含自测时间。
为了提升粘合的效率,开发一个图形化编程工具,这里附上一些截图供参考:
- 主界面
- 函数库
- 牌型算法的例子
- 流程控制
- 调试
除了算法库、UI库以外,还包含了编程语言级别的函数、流程控制函数等。
有了这个工具,写牌型算法就快多了。
这个图中的例子,包括了对一副牌进行洗牌,每次取出17张牌,在一个循环中,给每一个玩家发牌。下面是用英文显示函数的样子:
实际使用过程中,还是习惯英文编程。切换到中文相当于看看文档。
调试的时候,可以随时看一组牌是什么牌,这样很方便,对开发效率的提升很明显。
以上介绍的图形化开发工具,已经具备的工程管理、图形化编程(编辑)、调试、发布、以及界面设置等辅助功能为一体的集成化开发环境。是图形化编程的一次有益的尝试。
6测试
技术人员自己可以搞定的测试是:单元测试;功能测试;性能测试(压力测试);
我们还请了专业的测试团队进行了游戏内测。
简单的公测:找老家亲戚朋友拉微信群,有些朋友人脉广,可以拉很多人。然后每天集中半小时搞一次测试,玩5局发10元红包,连续测试一周就差不多了。这种测试还挺有效,而且投入不大。
7进展
目前,项目已经基本达成了技术目标,所有扑克游戏使用了同一套算法库(C++代码使用emscripten 转为 javascript)、同一套UI库(html5/pixi.js)、两套标准的大厅,同一个服务器程序(C++),同一套通讯库(javascript)。另外还有:管理和监控后台;服务器更新;客户端更新;html5错误上报;C++错误上报等等。
除C++代码未开源,其他代码都开源了,文档齐全,放在 gitee上了,欢迎大家下载使用,欢迎提意见和交流。
(在html5浏览器兼容性方面有一些问题,比如UC浏览器、搜狗浏览器,特别需要熟悉这块的同学能给与一些支持!)
后记
作者是9年前误入游戏行业,也有幸在一家上市游戏公司担任技术副总监,并承担过游戏引擎主程的工作。其实我不是很喜欢棋牌游戏开发,如果有机会,我更想去加入古剑或河洛的团队中去学习。我大学出来后大部分时间里,从事的是GIS(地图编辑、空间分析、图形)开发,也有一部分跟AutoCAD有关,都是windows客户端。一个团队40多号人,开发企业用大型客户端,当时在国内也颇为壮观。现在看到米国禁止咱们大学用MATLAB,我也很想投入到这些领域中。
自己一直喜欢干技术,虽然早已是大龄,但也一直坚持干技术,是因为从大学时候起,就想在技术上干出一点名堂来。那时自己仰望一些技术大牛,就像小虾米仰望14本天书中的大侠一样,希望有一天像他们一样,成为技术界的侠之大者,成为对社会对行业有用的人。
风马 2020年7月