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